Compare commits

..

138 Commits

Author SHA1 Message Date
Bart van den Eijnden
f468239e71 Merge pull request #2394 from tonio/style_order
Give precedence to feature styles
2014-07-25 11:34:24 +02:00
Antoine Abt
4b8ceca8eb Move defaults style into style.js 2014-07-25 09:50:53 +02:00
Tim Schaub
10ffc8953b Merge pull request #2436 from tschaub/doc-link
Correct link to API docs.
2014-07-24 14:58:24 -06:00
Tim Schaub
d846fbc0b4 Correct link to API docs 2014-07-24 14:32:34 -06:00
Marc Jansen
f5bb790509 Merge pull request #2167 from elemoine/graticule
Add a Graticule component
2014-07-24 19:13:26 +02:00
Tim Schaub
9fd5c1370e Merge pull request #2316 from tschaub/layer-extent
Support for layers with limited extent.
2014-07-24 10:41:01 -06:00
Tim Schaub
caa0b568ad Remove extent option for sources
Most of our uses of source extent were cargo cult programming.  The source extent was seldom and inconsistently used.  Instead, layers can now be configured with an extent, and layer renderers limit rendering (and data requests) to the layer extent.

For vector sources, the `getExtent` method returns the extent of currently loaded features (this was the case before and after this change).  For tile based sources, we will likely want to allow easy construction of tile grids based on an extent (this is not possible before or after this change, but could be added later).
2014-07-24 10:30:06 -06:00
Tim Schaub
7bbd27e68e ol.tilegrid.TileGrid doesn't accept an extent option
Tile grids cannot currently be constructed with an extent (though we should perhaps provide a function that allows this - see 68815dca10 for an example).
2014-07-24 10:26:07 -06:00
Tim Schaub
2b0284a342 Only request tiles within the layer extent
Layer renderers are now responsible for requesting data within a limited extent.
2014-07-24 10:26:07 -06:00
Tim Schaub
234cff4de5 Limit image layer requests to layer extent
This has two nice consequences that can be seen in the wms-image.js and mapbuide-untiled.js examples:
 * no images are requested when you browse outside of the layer extent
 * when the layer extent is within the viewport extent, cached images are used since the intersecting extent is the same for multiple viewport extents
2014-07-24 10:26:07 -06:00
Tim Schaub
1daf36956c Layer extent option
If provided, the layer extent will be used to limit data requests and rendering.  If undefined, to limit will be imposed.
2014-07-24 10:26:07 -06:00
Tim Schaub
42f953d08d Function for getting extent intersection 2014-07-24 10:26:07 -06:00
Éric Lemoine
e5a0e736ca Add a sphere mollweide example 2014-07-24 17:59:56 +02:00
Éric Lemoine
2365e73bef Add a graticule example 2014-07-24 17:59:56 +02:00
Éric Lemoine
9bd1ab78fc Add Graticule component 2014-07-24 17:59:56 +02:00
Éric Lemoine
9c70a49fb0 Add ol.geom.flat.geodesic
Inspired by #1884 by @twpayne.
2014-07-24 17:59:56 +02:00
Éric Lemoine
9f19569144 Add a worldExtent to ol.proj.Projection 2014-07-24 17:59:56 +02:00
Antoine Abt
9de010c791 Merge pull request #2413 from tonio/logos
Revisit Logos
2014-07-24 17:25:07 +02:00
Frédéric Junod
c25b1e939e Merge pull request #2431 from probins/intro
Update introduction tutorial
2014-07-24 16:54:46 +02:00
Antoine Abt
d50f40dcce Type check with olx.LogoOptions 2014-07-24 16:40:34 +02:00
Antoine Abt
280a7c520f More complete doc for logo option 2014-07-24 15:22:20 +02:00
Antoine Abt
31c9f5806e Wording in docs 2014-07-24 15:22:19 +02:00
Antoine Abt
ba8077010a Add link support for source logos 2014-07-24 15:22:19 +02:00
Antoine Abt
c1f7db9611 Set type=button to avoid forms submit 2014-07-24 15:22:19 +02:00
Antoine Abt
a314203e12 Fixes wording in comments 2014-07-24 15:22:19 +02:00
Antoine Abt
a43c546667 Uncollapse when there’s only logos 2014-07-24 15:22:19 +02:00
Antoine Abt
a71714e8b6 Allow string & object to be passed as map logo 2014-07-24 15:22:18 +02:00
Andreas Hocevar
16cdd35f6d Test to make sure that feature styles take prececence 2014-07-24 14:37:45 +02:00
Andreas Hocevar
c1d49a8cef Update to use the correct default style function namespace 2014-07-24 14:31:12 +02:00
Peter Robins
b945147950 Update introduction tutorial 2014-07-24 11:08:20 +00:00
Frédéric Junod
b29195639f Merge pull request #2429 from fredj/reuse-pixel-for-coord
Reuse event pixel to compute the coordinate
2014-07-24 07:54:39 +02:00
Frederic Junod
b2e345c407 Reuse event pixel to compute the coordinate 2014-07-23 16:53:56 +02:00
Antoine Abt
7fbc4e3bff Rename ol3Logo to logo in map options 2014-07-23 16:27:01 +02:00
Frédéric Junod
d3e575339b Merge pull request #2427 from fredj/misc
Revert "Add FIXME"
2014-07-23 13:55:11 +02:00
Frederic Junod
9bcafc0fab Revert "Add FIXME"
This reverts commit a4afcd533f.

Code removed in 7fabff5ffa
2014-07-23 13:18:23 +02:00
Marc Jansen
8b7f80c64e Merge pull request #2425 from marcjansen/examples
Add examples to ol.coordinate functions
2014-07-23 09:26:47 +02:00
Marc Jansen
64c03d0f9c Add examples to ol.coordinate functions. 2014-07-23 09:15:50 +02:00
Tim Schaub
e81e030dcd Merge pull request #2424 from tschaub/build-css
Build css if source is newer.
2014-07-22 20:56:47 -06:00
Tim Schaub
288c997322 Build css if source is newer
Previously, build/ol.css wasn't getting rebuilt on updates to css/ol.css.
2014-07-22 14:04:52 -06:00
Frédéric Junod
1d22113420 Merge pull request #2421 from fredj/misc
miscellaneous documentation and coding style fixes
2014-07-22 15:37:06 +02:00
Frédéric Junod
962b94444c Merge pull request #2417 from probins/patch-1
Update buildcfg/readme
2014-07-22 15:30:53 +02:00
Frederic Junod
a8961877e8 Add link to the OSM XML documentation 2014-07-22 15:21:27 +02:00
Frederic Junod
8cf48eac4f Document options default value 2014-07-22 15:11:40 +02:00
Frederic Junod
7b7788973b Remove unnecessary newlines 2014-07-22 15:00:23 +02:00
Peter Robins
ddfe11042b Update buildcfg/readme 2014-07-22 10:00:56 +01:00
Bart van den Eijnden
8e106a2c98 Merge pull request #2403 from bartvde/gpx-write
ol.format.GPX writeFeatures is not working
2014-07-22 10:51:05 +02:00
Andreas Hocevar
8d805c6403 Merge pull request #2415 from probins/debugtile
Document debugtilesource
2014-07-22 10:25:17 +02:00
Peter Robins
3f1f450d5c Document debugtilesource 2014-07-22 08:14:33 +00:00
Tobias Sauerwein
a9d68a1899 Merge pull request #2405 from tsauerwein/kinetic-fast
Improve kinetic effect when panning fast
2014-07-22 08:37:57 +02:00
Tim Schaub
e593e5fb60 Merge pull request #2412 from tschaub/unused-proj
Removing unused ol.proj.CH.
2014-07-21 14:33:02 -06:00
Tim Schaub
74dbd2b3e5 Merge pull request #2404 from tschaub/builds
Two ways to use the library: advanced compilation (prod) or raw/concatenated (dev).
2014-07-21 09:39:32 -06:00
Tim Schaub
aa4ee80033 Removing unused ol.proj.CH 2014-07-21 09:28:48 -06:00
Andreas Hocevar
fa7ff506fc Merge pull request #2406 from ahocevar/scaleline-infinite
Infinite loop in ol.control.ScaleLine
2014-07-21 14:08:36 +02:00
Andreas Hocevar
eb71e8e92d Handle cases where the x-axis distance cannot be calculated 2014-07-21 12:20:51 +02:00
Frédéric Junod
82b921ff06 Merge pull request #2411 from fredj/createMouseEvent
Remove ol.pointer.PointerEvent.createMouseEvent
2014-07-21 11:07:42 +02:00
Frederic Junod
fee4c79757 Remove ol.pointer.PointerEvent.createMouseEvent
The externs declarations for MouseEvent are now fixed upstream
2014-07-21 09:51:26 +02:00
tsauerwein
73951394f9 Ensure that the first point for kinetic is valid 2014-07-21 09:05:32 +02:00
Marc Jansen
434bf0bf42 Merge pull request #2409 from vicb/patch-1
fix: typos in map.js
2014-07-20 17:37:16 +02:00
Victor Berchet
9838687d88 fix: typos in map.js 2014-07-20 17:24:09 +02:00
Tim Schaub
cee5b81ec2 Merge pull request #2408 from gingerik/wkt-apidoc
Fix apidoc for WKT format.
2014-07-19 13:28:46 -06:00
Erik Timmers
71b2bf73de Fix apidoc for WKT format 2014-07-18 22:01:17 +02:00
tsauerwein
02a2c5aceb Start earlier to log points for kinetic 2014-07-18 15:54:38 +02:00
Bart van den Eijnden
dbb72f5080 Conflate ol.format.GPX.V1_1 and ol.format.GXP into ol.format.GXP 2014-07-18 15:11:45 +02:00
Andreas Hocevar
b4f6baa613 Merge pull request #2401 from probins/layerbase
Fix issue with layergroup event docs
2014-07-18 14:19:35 +02:00
Tim Schaub
e9c6e58663 Removing the build-all target
The ol-all.json and ol.json build configurations differ only in their use of the manage_closure_dependencies Compiler option.  I don't think there is value in running both (there are plenty of other compiler options that we don't exercise in this same way).
2014-07-17 21:48:53 -06:00
Tim Schaub
737e063937 Two ways to run the hosted examples: compiled and raw
When viewing the hosted examples, people can load the compiled version of the library or load each script individually.
2014-07-17 21:42:55 -06:00
Tim Schaub
4dc601f30d Generate a ol-debug.js script useful for debugging
Instead of running everything through the Compiler just to remove whitespace, we provide a build that is a simple concatenation of all scripts in dependency order.  This build (ol-debug.js) should never be used in production (the same applies to the old ol-whitespace.js build).  Instead, the intention is that it be used to aid in debugging during development.
2014-07-17 21:33:02 -06:00
Tim Schaub
28a23a11b5 Remove ol-simple.js build
We've proven that we can, but that doesn't mean we should be building with `SIMPLE_OPTIMIZATIONS`.
2014-07-17 21:31:58 -06:00
Andreas Hocevar
3ac7cb58af Merge pull request #2402 from probins/plugins
Fix jshint issues in apidoc/plugins
2014-07-17 13:35:38 +02:00
Peter Robins
346ff9c186 Fix jshint issues in apidoc/plugins 2014-07-17 09:50:31 +00:00
Peter Robins
4dccb32545 Fix issue with layergroup event docs 2014-07-17 09:24:39 +00:00
Tim Schaub
ad272a1b3a Merge pull request #2399 from tschaub/functions
Annotate functions that are aliases for goog functions.
2014-07-17 01:11:50 -06:00
Tim Schaub
b0c0d077c9 Annotate always and never conditions as functions 2014-07-16 23:16:51 -06:00
Tim Schaub
12d94e1405 Document ol.inherits and annotate as a function 2014-07-16 23:16:30 -06:00
Paul Spencer
10aa2019e7 Merge pull request #2398 from probins/color
Add color to api docs
2014-07-16 19:35:45 -04:00
Peter Robins
2b1c96a7ea Add color to api docs 2014-07-16 19:50:06 +00:00
Andreas Hocevar
c9d44fe842 Merge pull request #2397 from probins/nav
Docs sidebar in alphanumeric sequence
2014-07-16 18:55:48 +02:00
Andreas Hocevar
e56f759574 Merge pull request #2395 from probins/defaults
Remove classdesc tag from control/interaction defaults
2014-07-16 18:52:23 +02:00
Peter Robins
6a0d08eafd Docs sidebar in alphanumeric sequence 2014-07-16 15:37:03 +00:00
Peter Robins
b77af6d416 Remove classdesc tag from control/interaction defaults 2014-07-16 12:54:18 +00:00
Antoine Abt
b7b5de659b Distinct style function types 2014-07-16 11:25:16 +02:00
Antoine Abt
60f1874766 Give precedence to feature style 2014-07-16 11:25:16 +02:00
Tim Schaub
0b9936107d Merge pull request #2377 from tschaub/portable-config
Make our build configs more portable by using the default src config.
2014-07-15 20:56:25 -06:00
Paul Spencer
7ca069de39 Merge pull request #2311 from probins/tilegrid
Improve docs for tilegrid
2014-07-15 21:12:27 -04:00
Paul Spencer
8383f60fcf Merge pull request #2349 from probins/projdocs
Improve docs for projection
2014-07-15 21:10:33 -04:00
Paul Spencer
aa9dab092a Merge pull request #2387 from bnare/patch-1
Update mapguidesource.js
2014-07-15 21:05:11 -04:00
Paul Spencer
38b36a09bd Merge pull request #2378 from pagameba/doc-feature
Improve documentation for ol.Feature
2014-07-15 20:36:06 -04:00
Tim Schaub
b96fb6ad3a Merge pull request #2345 from tschaub/no-static
Remove static and other attributes from the docs.
2014-07-15 16:54:27 -06:00
Tim Schaub
1cbedadf48 Merge pull request #2390 from tschaub/unit-conversion
Make ol.proj.METERS_PER_UNIT exportable.
2014-07-15 16:26:53 -06:00
Tim Schaub
1657ed2d23 Make ol.proj.METERS_PER_UNIT exportable
We need to apply the `@api` annotation to the object itself in order for it to be exportable.
2014-07-15 15:49:48 -06:00
Tim Schaub
7a26966c8d Merge pull request #2360 from gingerik/wkt-lexer
WKT lexer.
2014-07-15 15:39:31 -06:00
Paul Spencer
685265e1db Improve documentation for ol.Feature 2014-07-15 13:09:43 -04:00
bnare
9e3b46762b Update mapguidesource.js
Add a method updateParams to ol.source.MapGuide.
2014-07-15 17:04:19 +02:00
Erik Timmers
1e7dc5cd32 Add tests for empty & invalid WKT strings 2014-07-15 14:28:05 +02:00
Erik Timmers
4abc887f5d Encode empty geometries as WKT strings 2014-07-15 13:20:58 +02:00
Erik Timmers
fe8a72dce5 Allow for empty Point & GeometryCollection 2014-07-15 13:20:58 +02:00
Tim Schaub
0bd9be547d Merge pull request #2376 from tschaub/transitive
Add packages required by the build task to dependencies.
2014-07-14 17:59:02 -06:00
Tim Schaub
aecaa52cb1 Make our build configs more portable by using the default src config
If a `src` config is not provided, by default, all of the library sources are included.  There is some special handling in the build task to make sure all library sources are included regardless of the path to the build config.  When someone includes a `src` config, path patterns are assumed to be relative to the current working directory (unless overriden with the `cwd` config).  So, when you use the `src` config, your config is no longer portable.
2014-07-14 17:52:10 -06:00
Tim Schaub
4f7073d7aa For jsdoc to find plugins, we need to set the cwd
This allows the `build.js` (and the exports from `generate-info.js`) to be run with a different working directory.
2014-07-14 14:42:42 -06:00
Tim Schaub
4de2520109 Add packages required to build the library to dependencies
This allows other packages to depend on the ol3 package and get the build tools (devDependencies are not installed when they are transitive dependencies).  The justification here is that the ol3 package becomes useful to other packages when you are able to run the build.js task.  For this task to run all of its dependencies must be available.
2014-07-14 14:19:24 -06:00
Andreas Hocevar
4aa76977d2 Merge pull request #2374 from probins/patch-1
Remove duplication from contributing.md
2014-07-14 19:01:50 +02:00
Peter Robins
fe1131b850 Remove duplication from contributing.md 2014-07-14 17:00:28 +01:00
Tim Schaub
a2e7432e42 Merge pull request #2356 from tschaub/regenerate-info
Always regenerate info using all sources if any have changed.
2014-07-14 09:17:36 -06:00
Tim Schaub
d7f4a06f61 Merge pull request #2369 from probins/contribute
Move developer guide from wiki to CONTRIBUTING.md.
2014-07-14 08:59:17 -06:00
Antoine Abt
f57a364534 Merge pull request #2370 from gingerik/classlist
Use goog.dom.classlist functions (2)
2014-07-14 16:09:32 +02:00
Erik Timmers
bd08bfe6c8 Use goog.dom.classlist functions
The goog.dom.classes functions have now been deprecated.
See google/closure-library@97e8a0c
2014-07-14 15:15:16 +02:00
Peter Robins
313e313f7a Move developer guide from wiki to CONTRIBUTING.md 2014-07-14 11:26:49 +00:00
Andreas Hocevar
9131512598 Merge pull request #2367 from probins/collection
Improve Collection docs
2014-07-14 13:18:10 +02:00
Peter Robins
307ee09988 Improve Collection docs 2014-07-14 09:20:25 +00:00
Andreas Hocevar
3e2350b2a0 Merge pull request #2364 from probins/observable
Tag always exported methods as api/observable
2014-07-14 10:53:37 +02:00
Andreas Hocevar
29d581bbee Merge pull request #2365 from probins/patch-1
Fix missing backtick in ol.Object docs
2014-07-14 10:49:36 +02:00
Peter Robins
aa85318d78 Fix missing backtick in ol.Object docs 2014-07-14 09:47:50 +01:00
Peter Robins
97f9527f41 Tag always exported methods as api/observable 2014-07-14 08:23:17 +00:00
Erik Timmers
4c03b3b35c Parse WKT strings using a lexer/parser 2014-07-13 23:09:38 +02:00
Erik Timmers
621aafbdde Encode WKT strings statically 2014-07-13 22:36:12 +02:00
Andreas Hocevar
cc9acef01f Merge pull request #2358 from probins/patch-1
Change docs landing page to link to transformExtent
2014-07-13 17:19:35 +02:00
Marc Jansen
5cd202d50b Merge pull request #2355 from probins/mapelements
Document map DOM elements
2014-07-13 11:05:05 +02:00
Peter Robins
be09368359 Document map DOM elements 2014-07-13 07:47:47 +00:00
Peter Robins
3259b1078c Change docs landing page to link to transformExtent 2014-07-13 08:34:12 +01:00
Tim Schaub
7286c29fbc Merge pull request #2343 from tschaub/build-cleanups
Build cleanups.
2014-07-13 01:18:01 -06:00
Tim Schaub
847440f30a Merge pull request #2342 from tschaub/private-proj
Make internal proj constructors private.
2014-07-13 01:11:57 -06:00
Tim Schaub
f5830cc8e5 Unused JAVA executable 2014-07-12 14:46:05 -06:00
Tim Schaub
5010596ec0 Unused JAR executable 2014-07-12 14:45:20 -06:00
Tim Schaub
db431ebdc6 No reason for build.py to run generate-exports.js
The doc task does not use the generated exports.js file.
2014-07-12 14:43:50 -06:00
Tim Schaub
df2c14b7af Remove unnecessary linting of generated exports file 2014-07-12 14:43:50 -06:00
Tim Schaub
c93e80a14a Always regenerate info using all sources if any have changed
Because we don't know if a new or modified file includes changes to the class hierarchy, we regenerate info for all sources any time any one has changed.  An alternative would be to generate info first for the new or modified file and then (potentially) regenerate info for more source files in the class hierarchy, but this makes the generate-info.js task far more complicated.
2014-07-12 14:39:18 -06:00
Tim Schaub
543250c88a Merge pull request #2346 from tschaub/clean-css
Minify CSS.
2014-07-12 11:48:12 -06:00
Marc Jansen
59fe635b46 Merge pull request #2350 from probins/obj
Expand on docs for observable properties
2014-07-12 17:51:47 +02:00
Peter Robins
753727c15f Expand on docs for observable properties 2014-07-12 15:28:46 +00:00
Peter Robins
96ec96c4d5 Improve docs for projection 2014-07-12 11:31:38 +00:00
Tim Schaub
046ae42b38 Merge pull request #2347 from tschaub/render-sync
Fix the export map example.
2014-07-11 23:48:16 -06:00
Tim Schaub
a6f921d443 To force a download by setting the href, we need synchronous rendering 2014-07-11 21:49:57 -06:00
Tim Schaub
3e23da7c83 Minify CSS 2014-07-11 21:25:21 -06:00
Tim Schaub
aa4dbde841 Remove static and other attributes from the docs 2014-07-11 19:47:49 -06:00
Éric Lemoine
8c1ad54bd8 Merge pull request #2340 from tsauerwein/view-fitGeometry-maxZoom
Add maxZoom to ol.View.fitGeometry() options
2014-07-11 17:02:18 +02:00
tsauerwein
3b8e182856 Add maxZoom to ol.View.fitGeometry() options 2014-07-11 16:31:01 +02:00
Tim Schaub
521cbfb1b0 Make internal proj constructors private 2014-07-10 16:37:07 -06:00
Peter Robins
b396773183 Improve docs for tilegrid 2014-07-09 06:54:24 -04:00
127 changed files with 3276 additions and 2008 deletions

View File

@@ -4,18 +4,301 @@ Thanks for your interest in contributing to OpenLayers 3.
## Contributing Code ## Contributing Code
Our preferred means of receiving contributions is through [pull Our preferred means of receiving contributions is through [pull requests](https://help.github.com/articles/using-pull-requests). Make sure
requests](https://help.github.com/articles/using-pull-requests). that your pull request follows our pull request guidelines below before submitting it.
See the [Developer This page describes what you need to know to contribute code to ol3 as a developer.
Guide](https://github.com/openlayers/ol3/wiki/Developer-Guide) to get started
with OpenLayers 3 development. This guide provides information you should know
before creating pull requests.
Note that, before accepting a contribution, we ask that you provide us ## Contributor License Agreement
a Contributor License Agreement. If you are making your contribution as part of
work for your employer, please follow the guidelines on submitting a [Corporate Before accepting a contribution, we ask that you provide us a Contributor
Contributor License Agreement](http://www.openlayers.org/ccla.txt). If you are License Agreement. If you are making your contribution as part of work for
your employer, please follow the guidelines on submitting a [Corporate
Contributor License Agreement](https://raw.github.com/openlayers/cla/master/ccla.txt). If you are
making your contribution as an individual, you can submit a digital [Individual making your contribution as an individual, you can submit a digital [Individual
Contributor License Contributor License Agreement](https://docs.google.com/spreadsheet/viewform?formkey=dGNNVUJEMXF2dERTU0FXM3JjNVBQblE6MQ).
Agreement](https://docs.google.com/spreadsheet/viewform?formkey=dGNNVUJEMXF2dERTU0FXM3JjNVBQblE6MQ).
## Setting up development environment
You will obviously start by
[forking](https://github.com/openlayers/ol3/fork_select) the ol3 repository.
### Travis CI
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.
Although not mandatory, it is also recommended to set up Travis CI for your ol3 fork.
For that go to your ol3 fork's Service Hooks page and set up the Travis hook.
Then every time you push to your fork, the test suite will be run. This means
errors can be caught before creating a pull request. For those making
small or occasional contributions, this may be enough to check that your contributions
are ok; in this case, you do not need to install the build tools on your local environment
as described below.
### Development dependencies
The minimum requirements are:
* Git
* [Node.js](http://nodejs.org/)
* Python 2.6 or 2.7 with a couple of extra modules (see below)
* Java 7 (JRE and JDK)
The executables `git`, `java`, `jar`, and `python` should be in your `PATH`.
You can check your configuration by running:
$ ./build.py checkdeps
To install the Node.js dependencies run
$ npm install
To install the extra Python modules, run:
$ sudo pip install -r requirements.txt
or
$ cat requirements.txt | sudo xargs easy_install
depending on your OS and Python installation.
## Working with the build tool
As an ol3 developer you will need to use the `build.py` Python script. This is
the script to use to run the linter, the compiler, the tests, etc. Windows users
can use `build.cmd` which is a thin wrapper around `build.py`.
The `build.py` script is equivalent to a Makefile. It is actually based on
[pake](https://github.com/twpayne/pake/), which is a simple implementation of
`make` in Python.
The usage of the script is:
$ ./build.py <target>
where `<target>` is the name of the build target you want to execute. For
example:
$ ./build.py test
The main build targets are `serve`, `lint`, `build`, `test`, and `check`. The
latter is a meta-target that basically runs `lint`, `build`, and `test`.
The `serve` target starts a node-based web server, which we will refer to as the *dev server*. You'll need to start that server for running the examples and the tests in a browser. More information on that further down.
Other targets include `apidoc` and `ci`. The latter is the target used on Travis CI. See ol3's [Travis configuration file](https://github.com/openlayers/ol3/blob/master/.travis.yml).
## Running the `check` target
The `check` target is to be run before pushing code to GitHub and opening pull
requests. Branches that don't pass `check` won't pass the integration tests,
and have therefore no chance of being merged into `master`.
To run the `check` target:
$ ./build.py check
If you want to run the full suite of integration tests, see "Running the integration
tests" below.
## Running examples
To run the examples you first need to start the dev server:
$ ./build.py serve
Then, just point your browser <http://localhost:3000/examples> in your browser. For example <http://localhost:3000/examples/side-by-side.html>.
Run examples against the `ol.js` standalone build:
The examples can also be run against the `ol.js` standalone lib, just like the examples
[hosted](http://openlayers.github.com/ol3/master/examples/) on GitHub. Start by
executing the `host-examples` build target:
$ ./build.py host-examples
After running `host-examples` you can now open the examples index page in the browser, for example: <http://localhost/~elemoine/ol3/build/hosted/master/examples/>. (This assumes that the `hosted` directory is a web directory, served by Apache for example.)
Append `?mode=raw` to make the example work in full debug mode. In raw mode the OpenLayers and Closure Library scripts are loaded individually by the Closure Library's `base.js` script (which the example page loads and executes before any other script).
## Running tests
To run the tests in a browser start the dev server (`./build.py serve`) and open <http://localhost:3000/test/index.html> in the browser.
To run the tests on the console (headless testing with PhantomJS) use the `test` target:
$ ./build.py test
See also the test-specific [README](../blob/master/test/README.md).
## Running the integration tests
When you submit a pull request the [Travis continuous integration
server](https://travis-ci.org/) will run a full suite of tests, including
building all versions of the library and checking that all of the examples
work. You will receive an email with the results, and the status will be
displayed in the pull request.
To run the full suite of integration tests use the `ci` target:
$ ./build.py ci
Running the full suite of integration tests currently takes 5-10 minutes.
This makes sure that your commit won't break the build. It also runs JSDoc3 to
make sure that there are no invalid API doc directives.
## Adding examples
Adding functionality often implies adding one or several examples. This
section provides explanations related to adding examples.
The examples are located in the `examples` directory. Adding a new example
implies creating two files in this directory, an `.html` file and a `.js` file.
See `examples/simple.html` and `examples/simple.js` for instance.
The `.html` file needs to include a script tag with
`loader.js?id=<example_name>` as its `src`. For example, if the two files for
the example are `myexample.js` and `myexample.html` then the script tag's `src`
should be set to `myexample`.
You can use `simple.js` and `simple.html` as templates for new examples.
### Use of the `goog` namespace in examples
Short story: the ol3 examples should not use the `goog` namespace, except
for `goog.require`.
Longer story: we want that the ol3 examples work in multiple modes, with the
standalone lib (which has implications of the symbols and properties we
export), and compiled together with the ol3 library.
Compiling the examples together with the library makes it mandatory to declare dependencies with `goog.require` statements.
## Pull request guidelines
Your pull request must:
* Follow OpenLayers 3's coding style.
* Pass the integration tests run automatically by the Travis Continuous
Integration system.
* Address a single issue or add a single item of functionality.
* Contain a clean history of small, incremental, logically separate commits,
with no merge commits.
* Use clear commit messages.
* Be possible to merge automatically.
### The `check` build target
It is strongly recommended that you run
$ ./build.py check
before every commit. This will catch many problems quickly, and it is much
faster than waiting for the Travis CI integration tests to run.
The `check` build target runs a number of quick tests on your code. These
include:
* Lint
* Compile
* Tests
### Follow OpenLayers 3's coding style
OpenLayers 3 follows [Google's JavaScript Style
Guide](http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml).
This is checked using the [Closure
Linter](https://developers.google.com/closure/utilities/) in strict mode. You
can run the linter locally on your machine before committing using the `lint`
target to `build.py`:
$ ./build.py lint
In addition to fixing problems identified by the linter, please also follow the
style of the existing OpenLayers 3 code, which includes:
* Always wrap the body of `for`, `if`, and `while` statements in braces.
* Class methods should be in alphabetical order.
* `var` declarations should not span multiple lines. If you cannot fit all
the declarations in a single line, then start a new `var` declaration on a
new line. Within a single line, variables should be declared in
alphabetical order.
* Do not use assignments inside expressions.
### Pass the integration tests run automatically by the Travis CI system
The integration tests contain a number of automated checks to ensure that the
code follows the OpenLayers 3 style and does not break tests or examples. You
can run the integration tests locally using the `ci` target:
$ ./build.py ci
### Address a single issue or add a single item of functionality
Please submit separate pull requests for separate issues. This allows each to
be reviewed on its own merits.
### Contain a clean history of small, incremental, logically separate commits, with no merge commits
The commit history explains to the reviewer the series of modifications to the
code that you have made and breaks the overall contribution into a series of
easily-understandable chunks. Any individual commit should not add more than
one new class or one new function. Do not submit commits that change thousands
of lines or that contain more than one distinct logical change. Trivial
commits, e.g. to fix lint errors, should be merged into the commit that
introduced the error. See the [Atomic Commit Convention on Wikipedia](http://en.wikipedia.org/wiki/Atomic_commit#Atomic_Commit_Convention) for more detail.
`git apply --patch` and `git rebase` can help you create a clean commit
history.
[Reviewboard.org](http://www.reviewboard.org/docs/codebase/dev/git/clean-commits/)
and [Pro GIT](http://git-scm.com/book/en/Git-Tools-Rewriting-History) have
explain how to use them.
### Use clear commit messages
Commit messages should be short, begin with a verb in the imperative, and
contain no trailing punctuation. We follow
http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
for the formatting of commit messages.
Git commit message should look like:
Header line: explaining the commit in one line
Body of commit message is a few lines of text, explaining things
in more detail, possibly giving some background about the issue
being fixed, etc etc.
The body of the commit message can be several paragraphs, and
please do proper word-wrap and keep columns shorter than about
74 characters or so. That way "git log" will show things
nicely even when it's indented.
Further paragraphs come after blank lines.
Please keep the header line short, no more than 50 characters.
### Be possible to merge automatically
Occasionally other changes to `master` might mean that your pull request cannot
be merged automatically. In this case you may need to rebase your branch on a
more recent `master`, resolve any conflicts, and `git push --force` to update
your branch so that it can be merged automatically.

View File

@@ -30,7 +30,7 @@ Interactions for [vector features](ol.Feature.html)
<br>[Formats](ol.format.Feature.html) for reading/writing vector data <br>[Formats](ol.format.Feature.html) for reading/writing vector data
<br>[ol.format.WMSCapabilities](ol.format.WMSCapabilities.html)</td></tr> <br>[ol.format.WMSCapabilities](ol.format.WMSCapabilities.html)</td></tr>
<tr><th>Projections</th><th>2-way bindings</th><th>Other components</th></tr> <tr><th>Projections</th><th>2-way bindings</th><th>Other components</th></tr>
<tr><td><p>All coordinates and extents need to be provided in view projection (default: [EPSG:3857](ol.proj.EPSG3857.html)). To transform, use [ol.proj.transform()](ol.proj.html#transform) and [ol.extent.applyTransform()](ol.extent.html#applyTransform).</p> <tr><td><p>All coordinates and extents need to be provided in view projection (default: EPSG:3857). To transform, use [ol.proj.transform()](ol.proj.html#transform) and [ol.proj.transformExtent()](ol.proj.html#transformExtent).</p>
[ol.proj](ol.proj.html)</td> [ol.proj](ol.proj.html)</td>
<td><p>[Objects](ol.Object.html) can be kept in sync using the [bindTo()](ol.Object.html#bindTo) method.</p> <td><p>[Objects](ol.Object.html) can be kept in sync using the [bindTo()](ol.Object.html#bindTo) method.</p>
<p>A [DOM Input](ol.dom.Input.html) class is available to bind Object properties to HTML Input elements.</p></td> <p>A [DOM Input](ol.dom.Input.html) class is available to bind Object properties to HTML Input elements.</p></td>

View File

@@ -72,7 +72,6 @@ function includeAugments(doclet) {
} }
var api = []; var api = [];
var augments = {};
var classes = {}; var classes = {};
exports.handlers = { exports.handlers = {

View File

@@ -19,7 +19,7 @@ exports.handlers = {
parseComplete: function(e) { parseComplete: function(e) {
var doclets = e.doclets; var doclets = e.doclets;
var eventClass, doclet, i, ii, j, jj, event, fires; var doclet, i, ii, j, jj, event, fires;
for (i = 0, ii = doclets.length - 1; i < ii; ++i) { for (i = 0, ii = doclets.length - 1; i < ii; ++i) {
doclet = doclets[i]; doclet = doclets[i];
if (doclet.fires) { if (doclet.fires) {

View File

@@ -87,7 +87,7 @@ exports.handlers = {
for (l = candidates.length - 1; l >= 0; --l) { for (l = candidates.length - 1; l >= 0; --l) {
candidate = candidates[l]; candidate = candidates[l];
if (candidate && !candidate.inheritdoc) { if (candidate && !candidate.inheritdoc) {
stability = candidate.stability || incompleteDoclet.stability stability = candidate.stability || incompleteDoclet.stability;
if (stability) { if (stability) {
incompleteDoclet.stability = stability; incompleteDoclet.stability = stability;
for (key in candidate) { for (key in candidate) {

View File

@@ -1,4 +1,3 @@
var util = require('util');
exports.defineTags = function(dictionary) { exports.defineTags = function(dictionary) {
var classTag = dictionary.lookUp('class'); var classTag = dictionary.lookUp('class');

View File

@@ -44,7 +44,7 @@ exports.handlers = {
if (!cls.fires) { if (!cls.fires) {
cls.fires = []; cls.fires = [];
} }
var event = 'ol.ObjectEvent#event:change:' + name.toLowerCase(); event = 'ol.ObjectEvent#event:change:' + name.toLowerCase();
if (cls.fires.indexOf(event) == -1) { if (cls.fires.indexOf(event) == -1) {
cls.fires.push(event); cls.fires.push(event);
} }

View File

@@ -79,14 +79,6 @@ function addSignatureTypes(f) {
f.signature = (f.signature || '') + '<span class="type-signature">'+(types.length? ' :'+types.join('|') : '')+' </span>'; f.signature = (f.signature || '') + '<span class="type-signature">'+(types.length? ' :'+types.join('|') : '')+' </span>';
} }
function addAttribs(f) {
var attribs = helper.getAttribs(f);
if (attribs.length) {
f.attribs = '<span class="type-signature ' + (attribs[0] === 'static' ? 'static' : '') + '">' + htmlsafe(attribs.length ? attribs.join(',') : '') + ' </span>';
}
}
function shortenPaths(files, commonPrefix) { function shortenPaths(files, commonPrefix) {
// always use forward slashes // always use forward slashes
var regexp = new RegExp('\\\\', 'g'); var regexp = new RegExp('\\\\', 'g');
@@ -198,11 +190,19 @@ function attachModuleSymbols(doclets, modules) {
*/ */
function buildNav(members) { function buildNav(members) {
var nav = []; var nav = [];
// merge namespaces and classes, then sort
if (members.namespaces.length) { var merged = members.namespaces.concat(members.classes);
_.each(members.namespaces, function (v) { merged.sort(function (a, b) {
// exclude 'olx' from sidebar if (a.longname > b.longname)
if (v.longname.indexOf('olx') !== 0) { return 1;
if (a.longname < b.longname)
return -1;
return 0;
});
_.each(merged, function (v) {
// exclude 'olx' and interfaces from sidebar
if (v.longname.indexOf('olx') !== 0 && v.interface !== true) {
if (v.kind == 'namespace') {
nav.push({ nav.push({
type: 'namespace', type: 'namespace',
longname: v.longname, longname: v.longname,
@@ -225,13 +225,7 @@ function buildNav(members) {
}) })
}); });
} }
}); if (v.kind == 'class') {
}
if (members.classes.length) {
_.each(members.classes, function (v) {
// ignore interfaces
if (v.interface !== true) {
nav.push({ nav.push({
type: 'class', type: 'class',
longname: v.longname, longname: v.longname,
@@ -255,9 +249,8 @@ function buildNav(members) {
}) })
}); });
} }
}); }
} });
return nav; return nav;
} }
@@ -404,7 +397,6 @@ exports.publish = function(taffyData, opts, tutorials) {
if ( needsSignature(doclet) ) { if ( needsSignature(doclet) ) {
addSignatureParams(doclet); addSignatureParams(doclet);
addSignatureReturns(doclet); addSignatureReturns(doclet);
addAttribs(doclet);
} }
}); });
@@ -414,12 +406,10 @@ exports.publish = function(taffyData, opts, tutorials) {
if (doclet.kind === 'member') { if (doclet.kind === 'member') {
addSignatureTypes(doclet); addSignatureTypes(doclet);
addAttribs(doclet);
} }
if (doclet.kind === 'constant') { if (doclet.kind === 'constant') {
addSignatureTypes(doclet); addSignatureTypes(doclet);
addAttribs(doclet);
doclet.kind = 'member'; doclet.kind = 'member';
} }
}); });

View File

@@ -15,7 +15,6 @@ var self = this;
<?js if (item.type === 'namespace' && <?js if (item.type === 'namespace' &&
(item.members.length + item.typedefs.length + item.methods.length + (item.members.length + item.typedefs.length + item.methods.length +
item.events.length > 0)) { ?> item.events.length > 0)) { ?>
<span class="static">static</span>
<?js } ?> <?js } ?>
</span> </span>
<ul class="members itemMembers"> <ul class="members itemMembers">

View File

@@ -5,9 +5,9 @@
* This loader is used for the hosted examples. It is used in place of the * This loader is used for the hosted examples. It is used in place of the
* development loader (examples/loader.js). * development loader (examples/loader.js).
* *
* ol.js, ol-simple.js, ol-whitespace.js, and ol-deps.js are built * The ol.js, ol-debug.js, and ol-deps.js scripts are built by OL3's
* by OL3's build.py script. They are located in the ../build/ directory, * build.py script. They are located in the ../build/ directory, relative to
* relatively to this script. * this script.
* *
* The script must be named loader.js. * The script must be named loader.js.
* *
@@ -54,20 +54,11 @@
} }
} }
var oljs = 'ol.js', mode; var raw = pageParams.mode && pageParams.mode.toLowerCase() === 'raw';
if ('mode' in pageParams) {
mode = pageParams.mode.toLowerCase();
if (mode == 'debug') {
mode = 'raw';
}
if (mode != 'advanced' && mode != 'raw') {
oljs = 'ol-' + mode + '.js';
}
}
var scriptId = encodeURIComponent(scriptParams.id); var scriptId = encodeURIComponent(scriptParams.id);
if (mode != 'raw') { if (!raw) {
document.write('<scr' + 'ipt type="text/javascript" src="../build/' + oljs + '"></scr' + 'ipt>'); document.write('<scr' + 'ipt type="text/javascript" src="../build/ol.js"></scr' + 'ipt>');
} else { } else {
window.CLOSURE_NO_DEPS = true; // we've got our own deps file window.CLOSURE_NO_DEPS = true; // we've got our own deps file
document.write('<scr' + 'ipt type="text/javascript" src="../closure-library/closure/goog/base.js"></scr' + 'ipt>'); document.write('<scr' + 'ipt type="text/javascript" src="../closure-library/closure/goog/base.js"></scr' + 'ipt>');

View File

@@ -16,10 +16,9 @@ from pake import ifind, main, output, rule, target, variables, virtual, which
if sys.platform == 'win32': if sys.platform == 'win32':
win = { win = {
'CLEANCSS': './node_modules/.bin/cleancss',
'GIT': 'git.exe', 'GIT': 'git.exe',
'GJSLINT': 'gjslint.exe', 'GJSLINT': 'gjslint.exe',
'JAVA': 'java.exe',
'JAR': 'jar.exe',
'JSDOC': './node_modules/.bin/jsdoc', 'JSDOC': './node_modules/.bin/jsdoc',
'JSHINT': './node_modules/.bin/jshint', 'JSHINT': './node_modules/.bin/jshint',
'PYTHON': 'python.exe', 'PYTHON': 'python.exe',
@@ -28,24 +27,6 @@ if sys.platform == 'win32':
sys_dir = os.environ.get('SYSTEMDRIVE') sys_dir = os.environ.get('SYSTEMDRIVE')
program_files = os.environ.get('PROGRAMFILES') program_files = os.environ.get('PROGRAMFILES')
java_home = os.environ.get('JAVA_HOME')
if not java_home:
# Following lines choose sensible defaults to guess JAVA_HOME in
# 32/64bit Program Files folder opting for the most current version.
search_term = os.path.join(sys_dir, os.sep, 'Program Files*', 'Java', 'jdk*')
found_jdks = sorted(glob.glob(search_term), key=lambda x: x[-8:])
if found_jdks:
java_home = found_jdks[-1]
if java_home:
if not which(win['JAVA']):
win['JAVA'] = os.path.join(java_home, 'bin', 'java.exe')
if not which(win['JAR']):
win['JAR'] = os.path.join(java_home, 'bin', 'jar.exe')
elif not which(win['JAVA']):
win['JAVA'] = os.path.join(program_files,
'Java', 'jre7', 'bin', 'java.exe')
if not which(win['GIT']): if not which(win['GIT']):
win['GIT'] = os.path.join(program_files, 'Git', 'cmd', 'git.exe') win['GIT'] = os.path.join(program_files, 'Git', 'cmd', 'git.exe')
@@ -70,11 +51,10 @@ if sys.platform == 'win32':
setattr(variables, program, path) setattr(variables, program, path)
else: else:
variables.CLEANCSS = './node_modules/.bin/cleancss'
variables.GIT = 'git' variables.GIT = 'git'
variables.GJSLINT = 'gjslint' variables.GJSLINT = 'gjslint'
variables.JSHINT = './node_modules/.bin/jshint' variables.JSHINT = './node_modules/.bin/jshint'
variables.JAVA = 'java'
variables.JAR = 'jar'
variables.JSDOC = './node_modules/.bin/jsdoc' variables.JSDOC = './node_modules/.bin/jsdoc'
variables.PYTHON = 'python' variables.PYTHON = 'python'
variables.PHANTOMJS = './node_modules/.bin/phantomjs' variables.PHANTOMJS = './node_modules/.bin/phantomjs'
@@ -82,12 +62,10 @@ else:
variables.BRANCH = output( variables.BRANCH = output(
'%(GIT)s', 'rev-parse', '--abbrev-ref', 'HEAD').strip() '%(GIT)s', 'rev-parse', '--abbrev-ref', 'HEAD').strip()
EXECUTABLES = [variables.GIT, variables.GJSLINT, variables.JAVA, variables.JAR, EXECUTABLES = [variables.CLEANCSS, variables.GIT, variables.GJSLINT,
variables.JSDOC, variables.JSHINT, variables.PYTHON, variables.JSDOC, variables.JSHINT, variables.PYTHON,
variables.PHANTOMJS] variables.PHANTOMJS]
EXPORTS = 'build/exports.js'
EXAMPLES = [path EXAMPLES = [path
for path in ifind('examples') for path in ifind('examples')
if path.endswith('.html') if path.endswith('.html')
@@ -145,23 +123,22 @@ def report_sizes(t):
virtual('default', 'build') virtual('default', 'build')
virtual('ci', 'lint', 'jshint', 'build', 'build-all', virtual('ci', 'lint', 'jshint', 'build', 'test',
'test', 'build/examples/all.combined.js', 'check-examples', 'apidoc') 'build/examples/all.combined.js', 'check-examples', 'apidoc')
virtual('build', 'build/ol.css', 'build/ol.js', virtual('build', 'build/ol.css', 'build/ol.js', 'build/ol-debug.js')
'build/ol-simple.js', 'build/ol-whitespace.js')
virtual('check', 'lint', 'jshint', 'build/ol-all.js', 'test') virtual('check', 'lint', 'jshint', 'test')
virtual('todo', 'fixme') virtual('todo', 'fixme')
@target('build/ol.css', 'build/ol.js') @target('build/ol.css', 'css/ol.css')
def build_ol_css(t): def build_ol_css(t):
t.touch() t.output('%(CLEANCSS)s', 'css/ol.css')
@target('build/ol.js', SRC, SHADER_SRC, 'buildcfg/ol.json') @target('build/ol.js', SRC, SHADER_SRC, 'buildcfg/ol.json')
@@ -170,31 +147,12 @@ def build_ol_new_js(t):
report_sizes(t) report_sizes(t)
@target('build/ol-simple.js', SRC, SHADER_SRC, 'buildcfg/ol-simple.json') @target('build/ol-debug.js', SRC, SHADER_SRC, 'buildcfg/ol-debug.json')
def build_ol_simple_js(t): def build_ol_debug_js(t):
t.run('node', 'tasks/build.js', 'buildcfg/ol-simple.json', 'build/ol-simple.js') t.run('node', 'tasks/build.js', 'buildcfg/ol-debug.json', 'build/ol-debug.js')
report_sizes(t) report_sizes(t)
@target('build/ol-whitespace.js', SRC, SHADER_SRC, 'buildcfg/ol-whitespace.json')
def build_ol_whitespace_js(t):
t.run('node', 'tasks/build.js', 'buildcfg/ol-whitespace.json', 'build/ol-whitespace.js')
report_sizes(t)
virtual('build-all', 'build/ol-all.js')
@target('build/ol-all.js', SRC, SHADER_SRC, 'buildcfg/ol-all.json')
def build_ol_all_js(t):
t.run('node', 'tasks/build.js', 'buildcfg/ol-all.json', 'build/ol-all.js')
@target(EXPORTS, SRC)
def build_exports_js(t):
t.run('node', 'tasks/generate-exports.js', EXPORTS)
for glsl_src in GLSL_SRC: for glsl_src in GLSL_SRC:
def shader_src_helper(glsl_src): def shader_src_helper(glsl_src):
@target(glsl_src.replace('.glsl', 'shader.js'), glsl_src, @target(glsl_src.replace('.glsl', 'shader.js'), glsl_src,
@@ -353,7 +311,7 @@ virtual('lint', 'build/lint-timestamp', 'build/check-requires-timestamp',
'build/check-whitespace-timestamp') 'build/check-whitespace-timestamp')
@target('build/lint-timestamp', SRC, EXPORTS, EXAMPLES_SRC, SPEC, precious=True) @target('build/lint-timestamp', SRC, EXAMPLES_SRC, SPEC, precious=True)
def build_lint_src_timestamp(t): def build_lint_src_timestamp(t):
t.run('%(GJSLINT)s', t.run('%(GJSLINT)s',
'--jslint_error=all', '--jslint_error=all',
@@ -365,7 +323,7 @@ def build_lint_src_timestamp(t):
virtual('jshint', 'build/jshint-timestamp') virtual('jshint', 'build/jshint-timestamp')
@target('build/jshint-timestamp', SRC, EXPORTS, EXAMPLES_SRC, SPEC, @target('build/jshint-timestamp', SRC, EXAMPLES_SRC, SPEC,
precious=True) precious=True)
def build_jshint_timestamp(t): def build_jshint_timestamp(t):
t.run(variables.JSHINT, '--verbose', t.newer(t.dependencies)) t.run(variables.JSHINT, '--verbose', t.newer(t.dependencies))
@@ -535,7 +493,7 @@ def build_check_requires_timestamp(t):
t.touch() t.touch()
@target('build/check-whitespace-timestamp', SRC, EXPORTS, EXAMPLES_SRC, @target('build/check-whitespace-timestamp', SRC, EXAMPLES_SRC,
SPEC, JSDOC_SRC, precious=True) SPEC, JSDOC_SRC, precious=True)
def build_check_whitespace_timestamp(t): def build_check_whitespace_timestamp(t):
CR_RE = re.compile(r'\r') CR_RE = re.compile(r'\r')
@@ -572,8 +530,7 @@ virtual('apidoc', 'build/jsdoc-%(BRANCH)s-timestamp' % vars(variables))
@target('build/jsdoc-%(BRANCH)s-timestamp' % vars(variables), 'host-resources', @target('build/jsdoc-%(BRANCH)s-timestamp' % vars(variables), 'host-resources',
EXPORTS, SRC, SHADER_SRC, SRC, SHADER_SRC, ifind('apidoc/template'))
ifind('apidoc/template'))
def jsdoc_BRANCH_timestamp(t): def jsdoc_BRANCH_timestamp(t):
t.run('%(JSDOC)s', 'apidoc/index.md', '-c', 'apidoc/conf.json', t.run('%(JSDOC)s', 'apidoc/index.md', '-c', 'apidoc/conf.json',
'-d', 'build/hosted/%(BRANCH)s/apidoc') '-d', 'build/hosted/%(BRANCH)s/apidoc')
@@ -637,8 +594,7 @@ def host_examples(t):
split_example_file(example, examples_dir % vars(variables)) split_example_file(example, examples_dir % vars(variables))
t.cp_r('examples/data', examples_dir + '/data') t.cp_r('examples/data', examples_dir + '/data')
t.cp('bin/loader_hosted_examples.js', examples_dir + '/loader.js') t.cp('bin/loader_hosted_examples.js', examples_dir + '/loader.js')
t.cp('build/ol.js', 'build/ol-simple.js', 'build/ol-whitespace.js', t.cp('build/ol.js', 'build/ol-debug.js', build_dir)
build_dir)
t.cp('build/ol.css', css_dir) t.cp('build/ol.css', css_dir)
t.cp('examples/index.html', 'examples/example-list.js', t.cp('examples/index.html', 'examples/example-list.js',
'examples/example-list.xml', 'examples/Jugl.js', 'examples/example-list.xml', 'examples/Jugl.js',

View File

@@ -48,7 +48,6 @@ exports.publish = function(data, opts) {
name: doc.longname, name: doc.longname,
kind: doc.kind, kind: doc.kind,
description: doc.classdesc || doc.description, description: doc.classdesc || doc.description,
extends: doc.augments,
path: path.join(doc.meta.path, doc.meta.filename) path: path.join(doc.meta.path, doc.meta.filename)
}); });
} }

View File

@@ -1,65 +0,0 @@
{
"exports": ["*"],
"src": ["src/**/*.js"],
"compile": {
"externs": [
"externs/bingmaps.js",
"externs/closure-compiler.js",
"externs/geojson.js",
"externs/oli.js",
"externs/olx.js",
"externs/proj4js.js",
"externs/tilejson.js",
"externs/topojson.js",
"externs/vbarray.js"
],
"define": [
"goog.dom.ASSUME_STANDARDS_MODE=true",
"goog.DEBUG=false"
],
"jscomp_error": [
"accessControls",
"ambiguousFunctionDecl",
"checkEventfulObjectDisposal",
"checkRegExp",
"checkStructDictInheritance",
"checkTypes",
"checkVars",
"const",
"constantProperty",
"deprecated",
"duplicateMessage",
"es3",
"externsValidation",
"fileoverviewTags",
"globalThis",
"internetExplorerChecks",
"invalidCasts",
"misplacedTypeAnnotation",
"missingGetCssName",
"missingProperties",
"missingProvide",
"missingRequire",
"missingReturn",
"newCheckTypes",
"nonStandardJsDocs",
"suspiciousCode",
"strictModuleDepCheck",
"typeInvalidation",
"undefinedNames",
"undefinedVars",
"unknownDefines",
"uselessCode",
"visibility"
],
"extra_annotation_name": [
"api", "observable"
],
"jscomp_off": [
"es5Strict"
],
"compilation_level": "ADVANCED",
"output_wrapper": "// OpenLayers 3. See http://ol3.js.org/\n(function(){%output%})();",
"use_types_for_optimization": true
}
}

3
buildcfg/ol-debug.json Normal file
View File

@@ -0,0 +1,3 @@
{
"exports": ["*"]
}

View File

@@ -1,66 +0,0 @@
{
"exports": ["*"],
"src": ["src/**/*.js"],
"compile": {
"externs": [
"externs/bingmaps.js",
"externs/closure-compiler.js",
"externs/geojson.js",
"externs/oli.js",
"externs/olx.js",
"externs/proj4js.js",
"externs/tilejson.js",
"externs/topojson.js",
"externs/vbarray.js"
],
"define": [
"goog.dom.ASSUME_STANDARDS_MODE=true",
"goog.DEBUG=false"
],
"jscomp_error": [
"accessControls",
"ambiguousFunctionDecl",
"checkEventfulObjectDisposal",
"checkRegExp",
"checkStructDictInheritance",
"checkTypes",
"checkVars",
"const",
"constantProperty",
"deprecated",
"duplicateMessage",
"es3",
"externsValidation",
"fileoverviewTags",
"globalThis",
"internetExplorerChecks",
"invalidCasts",
"misplacedTypeAnnotation",
"missingGetCssName",
"missingProperties",
"missingProvide",
"missingRequire",
"missingReturn",
"newCheckTypes",
"nonStandardJsDocs",
"suspiciousCode",
"strictModuleDepCheck",
"typeInvalidation",
"undefinedNames",
"undefinedVars",
"unknownDefines",
"uselessCode",
"visibility"
],
"extra_annotation_name": [
"api", "observable"
],
"jscomp_off": [
"es5Strict"
],
"compilation_level": "SIMPLE",
"output_wrapper": "%output%",
"use_types_for_optimization": false,
"manage_closure_dependencies": true
}
}

View File

@@ -1,66 +0,0 @@
{
"exports": ["*"],
"src": ["src/**/*.js"],
"compile": {
"externs": [
"externs/bingmaps.js",
"externs/closure-compiler.js",
"externs/geojson.js",
"externs/oli.js",
"externs/olx.js",
"externs/proj4js.js",
"externs/tilejson.js",
"externs/topojson.js",
"externs/vbarray.js"
],
"define": [
"goog.dom.ASSUME_STANDARDS_MODE=true",
"goog.DEBUG=false"
],
"jscomp_error": [
"accessControls",
"ambiguousFunctionDecl",
"checkEventfulObjectDisposal",
"checkRegExp",
"checkStructDictInheritance",
"checkTypes",
"checkVars",
"const",
"constantProperty",
"deprecated",
"duplicateMessage",
"es3",
"externsValidation",
"fileoverviewTags",
"globalThis",
"internetExplorerChecks",
"invalidCasts",
"misplacedTypeAnnotation",
"missingGetCssName",
"missingProperties",
"missingProvide",
"missingRequire",
"missingReturn",
"newCheckTypes",
"nonStandardJsDocs",
"suspiciousCode",
"strictModuleDepCheck",
"typeInvalidation",
"undefinedNames",
"undefinedVars",
"unknownDefines",
"uselessCode",
"visibility"
],
"extra_annotation_name": [
"api", "observable"
],
"jscomp_off": [
"es5Strict"
],
"compilation_level": "WHITESPACE_ONLY",
"output_wrapper": "var CLOSURE_DEPS = false;\n%output%",
"use_types_for_optimization": false,
"manage_closure_dependencies": true
}
}

View File

@@ -1,6 +1,5 @@
{ {
"exports": ["*"], "exports": ["*"],
"src": ["src/**/*.js"],
"compile": { "compile": {
"externs": [ "externs": [
"externs/bingmaps.js", "externs/bingmaps.js",

View File

@@ -1,12 +1,3 @@
# Build configs # Build configs
This directory includes configuration files (json) for the tasks/build.js This directory includes configuration files (json) for the build scripts in tasks/.
build script.
Notes:
`use_types_for_optimization` is set to `false` for the SIMPLE and WHITESPACE
builds. If it was set to `true` we would get function names like
`ol_control_Control_prototype$setMap` in the compiled code when using the
SIMPLE compilation. `use_types_for_optimization` is only appropriate for
ADVANCED compilation. To be sure we also don't set it for WHITESPACE.

View File

@@ -219,6 +219,9 @@ button.ol-full-screen-true:after {
.ol-attribution.ol-collapsed ul { .ol-attribution.ol-collapsed ul {
display: none; display: none;
} }
.ol-attribution.ol-logo-only ul {
display: block;
}
.ol-attribution:not(.ol-collapsed) { .ol-attribution:not(.ol-collapsed) {
background: rgba(255,255,255,0.8); background: rgba(255,255,255,0.8);
} }
@@ -229,10 +232,17 @@ button.ol-full-screen-true:after {
height: 1.1em; height: 1.1em;
line-height: 1em; line-height: 1em;
} }
.ol-attribution.ol-logo-only {
background: transparent;
bottom: .4em;
height: 1.1em;
line-height: 1em;
}
.ol-attribution.ol-uncollapsible img { .ol-attribution.ol-uncollapsible img {
margin-top: -.2em; margin-top: -.2em;
max-height: 1.6em; max-height: 1.6em;
} }
.ol-attribution.ol-logo-only button,
.ol-attribution.ol-uncollapsible button { .ol-attribution.ol-uncollapsible button {
display: none; display: none;
} }

View File

@@ -16,7 +16,7 @@ It is also designed such that major new features, such as displaying 3D maps, or
OL3 is based on Google's Closure Tools. It makes heavy use of parts of the [__Closure Library__](https://developers.google.com/closure/library/). Using this to handle basics like DOM or event handling means the developers can concentrate on mapping functionality, and be sure that the underlying software is well-tested and cross-browser. Closure Library is specially designed to be optimized by the [__Closure Compiler__](https://developers.google.com/closure/compiler/). The 'advanced' optimizations that this provides offers a level of compression that far exceeds anything else available. OL3 has been designed to make full use of this. OL3 is based on Google's Closure Tools. It makes heavy use of parts of the [__Closure Library__](https://developers.google.com/closure/library/). Using this to handle basics like DOM or event handling means the developers can concentrate on mapping functionality, and be sure that the underlying software is well-tested and cross-browser. Closure Library is specially designed to be optimized by the [__Closure Compiler__](https://developers.google.com/closure/compiler/). The 'advanced' optimizations that this provides offers a level of compression that far exceeds anything else available. OL3 has been designed to make full use of this.
## Public API ## Public API
Using the advanced optimizations of the Closure Compiler means that properties and methods are renamed &ndash; `longMeaningfulName` might become `xB` &ndash; and so are effectively unusable in applications using the library. To be usable, they have to be explicitly `exported`. This means the exported names, those not renamed, effectively become the public API of the library. These __exportable__ properties and methods are marked in the source, and documented in the [API docs](../apidoc). This is the officially supported API of the library. A build containing all these exportable names is known as a __full build__. A hosted version of this is available, which can be used by any application. Using the advanced optimizations of the Closure Compiler means that properties and methods are renamed &ndash; `longMeaningfulName` might become `xB` &ndash; and so are effectively unusable in applications using the library. To be usable, they have to be explicitly `exported`. This means the exported names, those not renamed, effectively become the public API of the library. These __exportable__ properties and methods are marked in the source, and documented in the [API docs](../../apidoc). This is the officially supported API of the library. A build containing all these exportable names is known as a __full build__. A hosted version of this is available, which can be used by any application.
Although Closure library functions are widely used within OL3, none of them are exported. You will see references to them (they are all in the `goog` namespace) in the API docs, but these are for information only. You can use the Closure library in your own applications if you like, but this is not required. Although Closure library functions are widely used within OL3, none of them are exported. You will see references to them (they are all in the `goog` namespace) in the API docs, but these are for information only. You can use the Closure library in your own applications if you like, but this is not required.
@@ -35,10 +35,10 @@ OL3 uses a similar object hierarchy to the Closure library. There is a top-level
* simple objects containing static properties and methods, such as `ol.animation`; these also have a lower-case initial * simple objects containing static properties and methods, such as `ol.animation`; these also have a lower-case initial
* types, which have an upper-case initial. These are mainly 'classes', which here means a constructor function with prototypal inheritance, such as `ol.Map` or `ol.layer.Vector` (the Vector class within the layer namespace). There are however other, simpler, types, such as `ol.Extent`, which is an array. * types, which have an upper-case initial. These are mainly 'classes', which here means a constructor function with prototypal inheritance, such as `ol.Map` or `ol.layer.Vector` (the Vector class within the layer namespace). There are however other, simpler, types, such as `ol.Extent`, which is an array.
In the API docs, the index on the left lists the namespaces and simple objects first, followed by the classes.
Class namespaces, such as `ol.layer` have a base class type with the same name, such as `ol.layer.Layer`. These are mainly abstract classes, from which the other subclasses inherit. Class namespaces, such as `ol.layer` have a base class type with the same name, such as `ol.layer.Layer`. These are mainly abstract classes, from which the other subclasses inherit.
Source files are similarly organised, with a directory for each class namespace. Names are however all lower-case, and the subclasses repeat the superclass type in their name, for example, `ol/layer/vectorlayer.js`. Source files are similarly organised, with a directory for each class namespace. Names are however all lower-case, and the subclasses repeat the superclass type in their name, for example, `ol/layer/vectorlayer.js`.
The naming structure means that there are sometimes 2 objects with the same name but different initial, such as `ol.feature`, a simple object with static functions to be used with features, and `ol.Feature`, a class used to instantiate new features. These two objects are however stored in the same file, in this case, `ol/feature.js` The naming structure means that there are sometimes 2 objects with the same name but different initial, such as `ol.feature`, a simple object with static functions to be used with features, and `ol.Feature`, a class used to instantiate new features. These two objects are however stored in the same file, in this case, `ol/feature.js`
OL3 follows the convention that the names of private properties and methods, that is, those that are not part of the API, end in an underscore. In general, instance properties are private and accessed using accessors.

File diff suppressed because one or more lines are too long

View File

@@ -31,7 +31,7 @@ if ('download' in exportPNGElement) {
var canvas = event.context.canvas; var canvas = event.context.canvas;
exportPNGElement.href = canvas.toDataURL('image/png'); exportPNGElement.href = canvas.toDataURL('image/png');
}); });
map.render(); map.renderSync();
}, false); }, false);
} else { } else {
var info = document.getElementById('no-download'); var info = document.getElementById('no-download');

View File

@@ -25,6 +25,12 @@
<div class="row-fluid"> <div class="row-fluid">
<div class="span12"> <div class="span12">
<div id="map" class="map"></div> <div id="map" class="map"></div>
<div id="no-download" class="alert alert-error" style="display: none">
The "Export GPX" functionality requires a browser that supports the
<a href="http://caniuse.com/#feat=download">link download</a> attribute.
</div>
<a id="export-gpx" class="btn" download="map.gpx"><i class="icon-download"></i>Export GPX</a>
</div>
</div> </div>
</div> </div>

View File

@@ -1,7 +1,9 @@
goog.require('ol.Map'); goog.require('ol.Map');
goog.require('ol.View'); goog.require('ol.View');
goog.require('ol.format.GPX');
goog.require('ol.layer.Tile'); goog.require('ol.layer.Tile');
goog.require('ol.layer.Vector'); goog.require('ol.layer.Vector');
goog.require('ol.proj');
goog.require('ol.source.BingMaps'); goog.require('ol.source.BingMaps');
goog.require('ol.source.GPX'); goog.require('ol.source.GPX');
goog.require('ol.style.Circle'); goog.require('ol.style.Circle');
@@ -9,6 +11,8 @@ goog.require('ol.style.Fill');
goog.require('ol.style.Stroke'); goog.require('ol.style.Stroke');
goog.require('ol.style.Style'); goog.require('ol.style.Style');
var projection = ol.proj.get('EPSG:3857');
var raster = new ol.layer.Tile({ var raster = new ol.layer.Tile({
source: new ol.source.BingMaps({ source: new ol.source.BingMaps({
imagerySet: 'Aerial', imagerySet: 'Aerial',
@@ -45,7 +49,7 @@ var style = {
var vector = new ol.layer.Vector({ var vector = new ol.layer.Vector({
source: new ol.source.GPX({ source: new ol.source.GPX({
projection: 'EPSG:3857', projection: projection,
url: 'data/gpx/fells_loop.gpx' url: 'data/gpx/fells_loop.gpx'
}), }),
style: function(feature, resolution) { style: function(feature, resolution) {
@@ -89,3 +93,30 @@ $(map.getViewport()).on('mousemove', function(evt) {
map.on('click', function(evt) { map.on('click', function(evt) {
displayFeatureInfo(evt.pixel); displayFeatureInfo(evt.pixel);
}); });
var exportGPXElement = document.getElementById('export-gpx');
if ('download' in exportGPXElement) {
var vectorSource = /** @type {ol.source.Vector} */ (vector.getSource());
exportGPXElement.addEventListener('click', function(e) {
if (!exportGPXElement.href) {
var features = [];
vectorSource.forEachFeature(function(feature) {
var clone = feature.clone();
clone.getGeometry().transform(projection, 'EPSG:4326');
features.push(clone);
});
var node = new ol.format.GPX().writeFeatures(features);
var string = new XMLSerializer().serializeToString(
/** @type {Node} */ (node));
var base64 = exampleNS.strToBase64(string);
exportGPXElement.href =
'data:gpx+xml;base64,' + base64;
}
}, false);
} else {
var info = document.getElementById('no-download');
/**
* display error message
*/
info.style.display = '';
}

51
examples/graticule.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>Graticule 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">Graticule example</h4>
<p id="shortdesc">This example shows how to add a graticule overlay to a map.</p>
<div id="docs">
<p>See the <a href="graticule.js" target="_blank">graticule.js source</a> to see how this is done.</p>
</div>
<div id="tags">graticule</div>
</div>
</div>
</div>
<script src="jquery.min.js" type="text/javascript"></script>
<script src="../resources/example-behaviour.js" type="text/javascript"></script>
<script src="loader.js?id=graticule" type="text/javascript"></script>
</body>
</html>

25
examples/graticule.js Normal file
View File

@@ -0,0 +1,25 @@
goog.require('ol.Graticule');
goog.require('ol.Map');
goog.require('ol.View');
goog.require('ol.layer.Tile');
goog.require('ol.proj');
goog.require('ol.source.OSM');
var map = new ol.Map({
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
renderer: 'canvas',
target: 'map',
view: new ol.View({
center: ol.proj.transform([4.8, 47.75], 'EPSG:4326', 'EPSG:3857'),
zoom: 5
})
});
// Create the graticule component
var graticule = new ol.Graticule();
graticule.setMap(map);

View File

@@ -15,6 +15,7 @@ var bounds = [
var map = new ol.Map({ var map = new ol.Map({
layers: [ layers: [
new ol.layer.Image({ new ol.layer.Image({
extent: bounds,
source: new ol.source.MapGuide({ source: new ol.source.MapGuide({
projection: 'EPSG:4326', projection: 'EPSG:4326',
url: agentUrl, url: agentUrl,
@@ -24,8 +25,7 @@ var map = new ol.Map({
MAPDEFINITION: mdf, MAPDEFINITION: mdf,
FORMAT: 'PNG' FORMAT: 'PNG'
}, },
ratio: 2, ratio: 2
extent: bounds
}) })
}) })
], ],

View File

@@ -0,0 +1,52 @@
<!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>Sphere Mollweide 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">Sphere Mollweide example</h4>
<p id="shortdesc">Example of a Sphere Mollweide map with a Graticule component.</p>
<div id="docs">
<p>See the <a href="sphere-mollweide.js" target="_blank">sphere-mollweide.js source</a> to see how this is done.</p>
</div>
<div id="tags">graticule, Mollweide, projection, proj4js</div>
</div>
</div>
</div>
<script src="jquery.min.js" type="text/javascript"></script>
<script src="../resources/example-behaviour.js" type="text/javascript"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/proj4js/2.2.1/proj4.js" type="text/javascript"></script>
<script src="loader.js?id=sphere-mollweide" type="text/javascript"></script>
</body>
</html>

View File

@@ -0,0 +1,42 @@
goog.require('ol.Graticule');
goog.require('ol.Map');
goog.require('ol.View');
goog.require('ol.layer.Vector');
goog.require('ol.proj');
goog.require('ol.source.GeoJSON');
proj4.defs('ESRI:53009', '+proj=moll +lon_0=0 +x_0=0 +y_0=0 +a=6371000 ' +
'+b=6371000 +units=m +no_defs');
// 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 map = new ol.Map({
keyboardEventTarget: document,
layers: [
new ol.layer.Vector({
source: new ol.source.GeoJSON({
projection: sphereMollweideProjection,
url: 'data/geojson/countries-110m.geojson'
})
})
],
renderer: 'canvas',
target: 'map',
view: new ol.View({
center: [0, 0],
projection: sphereMollweideProjection,
resolutions: [65536, 32768, 16384, 8192, 4096, 2048],
zoom: 0
})
});
var graticule = new ol.Graticule({
map: map
});

View File

@@ -44,6 +44,7 @@ ol.proj.addCoordinateTransforms('EPSG:4326', projection,
var extent = [420000, 30000, 900000, 350000]; var extent = [420000, 30000, 900000, 350000];
var layers = [ var layers = [
new ol.layer.Tile({ new ol.layer.Tile({
extent: extent,
source: new ol.source.TileWMS({ source: new ol.source.TileWMS({
url: 'http://wms.geo.admin.ch/', url: 'http://wms.geo.admin.ch/',
crossOrigin: 'anonymous', crossOrigin: 'anonymous',
@@ -57,11 +58,11 @@ var layers = [
'LAYERS': 'ch.swisstopo.pixelkarte-farbe-pk1000.noscale', 'LAYERS': 'ch.swisstopo.pixelkarte-farbe-pk1000.noscale',
'FORMAT': 'image/jpeg' 'FORMAT': 'image/jpeg'
}, },
extent: extent,
serverType: 'mapserver' serverType: 'mapserver'
}) })
}), }),
new ol.layer.Tile({ new ol.layer.Tile({
extent: extent,
source: new ol.source.TileWMS({ source: new ol.source.TileWMS({
url: 'http://wms.geo.admin.ch/', url: 'http://wms.geo.admin.ch/',
crossOrigin: 'anonymous', crossOrigin: 'anonymous',
@@ -72,7 +73,6 @@ var layers = [
'National parks / geo.admin.ch</a>' 'National parks / geo.admin.ch</a>'
})], })],
params: {'LAYERS': 'ch.bafu.schutzgebiete-paerke_nationaler_bedeutung'}, params: {'LAYERS': 'ch.bafu.schutzgebiete-paerke_nationaler_bedeutung'},
extent: extent,
serverType: 'mapserver' serverType: 'mapserver'
}) })
}) })

View File

@@ -12,6 +12,10 @@ goog.require('ol.source.ImageWMS');
// known to Proj4js if it is unknown to OpenLayers, and registers functions to // known to Proj4js if it is unknown to OpenLayers, and registers functions to
// transform between all registered projections. // transform between all registered projections.
// EPSG:21781 is known to Proj4js because its definition was loaded in the html. // 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'); var projection = ol.proj.get('EPSG:21781');
// The extent is used to determine zoom level 0. Recommended values for a // The extent is used to determine zoom level 0. Recommended values for a
// projection's validity extent can be found at http://epsg.io/. // projection's validity extent can be found at http://epsg.io/.
@@ -20,6 +24,7 @@ projection.setExtent([485869.5728, 76443.1884, 837076.5648, 299941.7864]);
var extent = [420000, 30000, 900000, 350000]; var extent = [420000, 30000, 900000, 350000];
var layers = [ var layers = [
new ol.layer.Image({ new ol.layer.Image({
extent: extent,
source: new ol.source.ImageWMS({ source: new ol.source.ImageWMS({
url: 'http://wms.geo.admin.ch/', url: 'http://wms.geo.admin.ch/',
crossOrigin: 'anonymous', crossOrigin: 'anonymous',
@@ -33,11 +38,11 @@ var layers = [
'LAYERS': 'ch.swisstopo.pixelkarte-farbe-pk1000.noscale', 'LAYERS': 'ch.swisstopo.pixelkarte-farbe-pk1000.noscale',
'FORMAT': 'image/jpeg' 'FORMAT': 'image/jpeg'
}, },
serverType: /** @type {ol.source.wms.ServerType} */ ('mapserver'), serverType: /** @type {ol.source.wms.ServerType} */ ('mapserver')
extent: extent
}) })
}), }),
new ol.layer.Image({ new ol.layer.Image({
extent: extent,
source: new ol.source.ImageWMS({ source: new ol.source.ImageWMS({
url: 'http://wms.geo.admin.ch/', url: 'http://wms.geo.admin.ch/',
crossOrigin: 'anonymous', crossOrigin: 'anonymous',
@@ -48,8 +53,7 @@ var layers = [
'National parks / geo.admin.ch</a>' 'National parks / geo.admin.ch</a>'
})], })],
params: {'LAYERS': 'ch.bafu.schutzgebiete-paerke_nationaler_bedeutung'}, params: {'LAYERS': 'ch.bafu.schutzgebiete-paerke_nationaler_bedeutung'},
serverType: /** @type {ol.source.wms.ServerType} */ ('mapserver'), serverType: /** @type {ol.source.wms.ServerType} */ ('mapserver')
extent: extent
}) })
}) })
]; ];

View File

@@ -11,11 +11,11 @@ var layers = [
source: new ol.source.MapQuest({layer: 'sat'}) source: new ol.source.MapQuest({layer: 'sat'})
}), }),
new ol.layer.Image({ new ol.layer.Image({
extent: [-13884991, 2870341, -7455066, 6338219],
source: new ol.source.ImageWMS({ source: new ol.source.ImageWMS({
url: 'http://demo.opengeo.org/geoserver/wms', url: 'http://demo.opengeo.org/geoserver/wms',
params: {'LAYERS': 'topp:states'}, params: {'LAYERS': 'topp:states'},
serverType: 'geoserver', serverType: 'geoserver'
extent: [-13884991, 2870341, -7455066, 6338219]
}) })
}) })
]; ];

View File

@@ -42,8 +42,10 @@ var layers = [
]; ];
// A minimal projection object is configured with only the SRS code and the map // A minimal projection object is configured with only the SRS code and the map
// units. No client side coordinate transforms are possible with such a // units. No client-side coordinate transforms are possible with such a
// projection object. // projection object. Requesting tiles only needs the code together with a
// tile grid of Cartesian coordinates; it does not matter how those
// coordinates relate to latitude or longitude.
var projection = new ol.proj.Projection({ var projection = new ol.proj.Projection({
code: 'EPSG:21781', code: 'EPSG:21781',
units: 'm' units: 'm'

View File

@@ -10,10 +10,10 @@ var layers = [
source: new ol.source.MapQuest({layer: 'sat'}) source: new ol.source.MapQuest({layer: 'sat'})
}), }),
new ol.layer.Tile({ new ol.layer.Tile({
extent: [-13884991, 2870341, -7455066, 6338219],
source: new ol.source.TileWMS(/** @type {olx.source.TileWMSOptions} */ ({ source: new ol.source.TileWMS(/** @type {olx.source.TileWMSOptions} */ ({
url: 'http://demo.opengeo.org/geoserver/wms', url: 'http://demo.opengeo.org/geoserver/wms',
params: {'LAYERS': 'topp:states', 'TILED': true}, params: {'LAYERS': 'topp:states', 'TILED': true},
extent: [-13884991, 2870341, -7455066, 6338219],
serverType: 'geoserver' serverType: 'geoserver'
})) }))
}) })

View File

@@ -9,6 +9,11 @@
<link rel="stylesheet" href="../resources/layout.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"> <link rel="stylesheet" href="../resources/bootstrap/css/bootstrap-responsive.min.css" type="text/css">
<title>WMTS HiDPI example</title> <title>WMTS HiDPI example</title>
<style>
.map {
background: white;
}
</style>
</head> </head>
<body> <body>

View File

@@ -23,7 +23,6 @@ var urls = [
var hiDPI = ol.BrowserFeature.DEVICE_PIXEL_RATIO > 1; var hiDPI = ol.BrowserFeature.DEVICE_PIXEL_RATIO > 1;
var source = new ol.source.WMTS({ var source = new ol.source.WMTS({
extent: [977844.377599999, 5837774.6617, 1915609.8654, 6295560.8122],
projection: 'EPSG:3857', projection: 'EPSG:3857',
layer: hiDPI ? 'bmaphidpi' : 'geolandbasemap', layer: hiDPI ? 'bmaphidpi' : 'geolandbasemap',
tilePixelRatio: hiDPI ? 2 : 1, tilePixelRatio: hiDPI ? 2 : 1,
@@ -64,6 +63,7 @@ var source = new ol.source.WMTS({
var map = new ol.Map({ var map = new ol.Map({
layers: [ layers: [
new ol.layer.Tile({ new ol.layer.Tile({
extent: [977844.377599999, 5837774.6617, 1915609.8654, 6295560.8122],
source: source source: source
}) })
], ],

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -17,23 +17,24 @@
}, },
"dependencies": { "dependencies": {
"async": "~0.2.10", "async": "~0.2.10",
"htmlparser2": "~3.7.1"
},
"devDependencies": {
"closure-util": "0.19.0", "closure-util": "0.19.0",
"expect.js": "~0.3.1",
"fs-extra": "~0.8.1", "fs-extra": "~0.8.1",
"graceful-fs": "~3.0.2", "graceful-fs": "~3.0.2",
"jquery": "~2.1.1", "htmlparser2": "~3.7.1",
"jsdoc": "~3.3.0-alpha9", "jsdoc": "~3.3.0-alpha9",
"nomnom": "~1.6.2",
"temp": "~0.7.0",
"walk": "~2.3.3"
},
"devDependencies": {
"clean-css": "^2.2.7",
"expect.js": "~0.3.1",
"jquery": "~2.1.1",
"jshint": "~2.5.1", "jshint": "~2.5.1",
"mocha": "~1.20.1", "mocha": "~1.20.1",
"mocha-phantomjs": "~3.5.0", "mocha-phantomjs": "~3.5.0",
"nomnom": "~1.6.2",
"phantomjs": "~1.9.7-5", "phantomjs": "~1.9.7-5",
"proj4": "~2.2.1", "proj4": "~2.2.1",
"sinon": "~1.10.2", "sinon": "~1.10.2"
"temp": "~0.7.0",
"walk": "~2.3.3"
} }
} }

View File

@@ -66,10 +66,15 @@ ol.CollectionProperty = {
/** /**
* @classdesc * @classdesc
* Adds methods to standard Array; changes (add/remove) to the Collection * An expanded version of standard JS Array, adding convenience methods for
* trigger events. Because a Collection is itself an {@link ol.Object}, it * manipulation. Add and remove changes to the Collection trigger a Collection
* can be bound to any other Object or Collection such that a change in one * event. Note that this does not cover changes to the objects _within_ the
* will automatically be reflected in the other. * Collection; they trigger events on the appropriate object, not on the
* Collection as a whole.
*
* Because a Collection is itself an {@link ol.Object}, it can be bound to any
* other Object or Collection such that a change in one will automatically be
* reflected in the other.
* *
* @constructor * @constructor
* @extends {ol.Object} * @extends {ol.Object}

View File

@@ -18,6 +18,7 @@ goog.require('ol');
* red, green, and blue should be integers in the range 0..255 inclusive. * red, green, and blue should be integers in the range 0..255 inclusive.
* alpha should be a float in the range 0..1 inclusive. * alpha should be a float in the range 0..1 inclusive.
* @typedef {Array.<number>} * @typedef {Array.<number>}
* @api
*/ */
ol.Color; ol.Color;

3
src/ol/color/color.jsdoc Normal file
View File

@@ -0,0 +1,3 @@
/**
* @namespace ol.color
*/

View File

@@ -4,7 +4,7 @@ goog.provide('ol.control.Attribution');
goog.require('goog.dom'); goog.require('goog.dom');
goog.require('goog.dom.TagName'); goog.require('goog.dom.TagName');
goog.require('goog.dom.classes'); goog.require('goog.dom.classlist');
goog.require('goog.events'); goog.require('goog.events');
goog.require('goog.events.EventType'); goog.require('goog.events.EventType');
goog.require('goog.object'); goog.require('goog.object');
@@ -96,7 +96,8 @@ ol.control.Attribution = function(opt_options) {
*/ */
this.labelSpan_ = label; this.labelSpan_ = label;
var button = goog.dom.createDom(goog.dom.TagName.BUTTON, { var button = goog.dom.createDom(goog.dom.TagName.BUTTON, {
'class': 'ol-has-tooltip' 'class': 'ol-has-tooltip',
'type': 'button'
}, this.labelSpan_); }, this.labelSpan_);
goog.dom.appendChild(button, tip); goog.dom.appendChild(button, tip);
@@ -158,8 +159,7 @@ goog.inherits(ol.control.Attribution, ol.control.Control);
* @param {?olx.FrameState} frameState Frame state. * @param {?olx.FrameState} frameState Frame state.
* @return {Array.<Object.<string, ol.Attribution>>} Attributions. * @return {Array.<Object.<string, ol.Attribution>>} Attributions.
*/ */
ol.control.Attribution.prototype.getSourceAttributions = ol.control.Attribution.prototype.getSourceAttributions = function(frameState) {
function(frameState) {
var i, ii, j, jj, tileRanges, source, sourceAttribution, var i, ii, j, jj, tileRanges, source, sourceAttribution,
sourceAttributionKey, sourceAttributions, sourceKey; sourceAttributionKey, sourceAttributions, sourceKey;
var layerStatesArray = frameState.layerStatesArray; var layerStatesArray = frameState.layerStatesArray;
@@ -273,6 +273,12 @@ ol.control.Attribution.prototype.updateElement_ = function(frameState) {
goog.style.setElementShown(this.element, renderVisible); goog.style.setElementShown(this.element, renderVisible);
this.renderedVisible_ = renderVisible; this.renderedVisible_ = renderVisible;
} }
if (renderVisible &&
goog.object.isEmpty(this.attributionElementRenderedVisible_)) {
goog.dom.classlist.add(this.element, 'ol-logo-only');
} else {
goog.dom.classlist.remove(this.element, 'ol-logo-only');
}
this.insertLogos_(frameState); this.insertLogos_(frameState);
@@ -347,7 +353,7 @@ ol.control.Attribution.prototype.handlePointerUp_ = function(pointerEvent) {
* @private * @private
*/ */
ol.control.Attribution.prototype.handleToggle_ = function() { ol.control.Attribution.prototype.handleToggle_ = function() {
goog.dom.classes.toggle(this.element, 'ol-collapsed'); goog.dom.classlist.toggle(this.element, 'ol-collapsed');
goog.dom.setTextContent(this.labelSpan_, goog.dom.setTextContent(this.labelSpan_,
(this.collapsed_) ? this.collapseLabel_ : this.label_); (this.collapsed_) ? this.collapseLabel_ : this.label_);
this.collapsed_ = !this.collapsed_; this.collapsed_ = !this.collapsed_;
@@ -355,7 +361,7 @@ ol.control.Attribution.prototype.handleToggle_ = function() {
/** /**
* @return {boolean} True is the widget is collapsible. * @return {boolean} True if the widget is collapsible.
* @api * @api
*/ */
ol.control.Attribution.prototype.getCollapsible = function() { ol.control.Attribution.prototype.getCollapsible = function() {
@@ -364,7 +370,7 @@ ol.control.Attribution.prototype.getCollapsible = function() {
/** /**
* @param {boolean} collapsible True is the widget is collapsible. * @param {boolean} collapsible True if the widget is collapsible.
* @api * @api
*/ */
ol.control.Attribution.prototype.setCollapsible = function(collapsible) { ol.control.Attribution.prototype.setCollapsible = function(collapsible) {
@@ -372,7 +378,7 @@ ol.control.Attribution.prototype.setCollapsible = function(collapsible) {
return; return;
} }
this.collapsible_ = collapsible; this.collapsible_ = collapsible;
goog.dom.classes.toggle(this.element, 'ol-uncollapsible'); goog.dom.classlist.toggle(this.element, 'ol-uncollapsible');
if (!collapsible && this.collapsed_) { if (!collapsible && this.collapsed_) {
this.handleToggle_(); this.handleToggle_();
} }
@@ -380,7 +386,7 @@ ol.control.Attribution.prototype.setCollapsible = function(collapsible) {
/** /**
* @param {boolean} collapsed True is the widget is collapsed. * @param {boolean} collapsed True if the widget is collapsed.
* @api * @api
*/ */
ol.control.Attribution.prototype.setCollapsed = function(collapsed) { ol.control.Attribution.prototype.setCollapsed = function(collapsed) {
@@ -392,7 +398,7 @@ ol.control.Attribution.prototype.setCollapsed = function(collapsed) {
/** /**
* @return {boolean} True is the widget is collapsed. * @return {boolean} True if the widget is collapsed.
* @api * @api
*/ */
ol.control.Attribution.prototype.getCollapsed = function() { ol.control.Attribution.prototype.getCollapsed = function() {

View File

@@ -12,8 +12,9 @@ goog.require('ol.Object');
* @classdesc * @classdesc
* A control is a visible widget with a DOM element in a fixed position on the * A control is a visible widget with a DOM element in a fixed position on the
* screen. They can involve user input (buttons), or be informational only; * screen. They can involve user input (buttons), or be informational only;
* the position is determined using CSS. By default these are part of the map * the position is determined using CSS. By default these are placed in the
* container, but can use any outside DOM element. * container with CSS class name `ol-overlaycontainer-stopevent`, but can use
* any outside DOM element.
* *
* This is the base class for controls. You can use it for simple custom * This is the base class for controls. You can use it for simple custom
* controls by creating the element with listeners, creating an instance: * controls by creating the element with listeners, creating an instance:

View File

@@ -7,7 +7,6 @@ goog.require('ol.control.Zoom');
/** /**
* @classdesc
* Set of controls included in maps by default. Unless configured otherwise, * Set of controls included in maps by default. Unless configured otherwise,
* this returns a collection containing an instance of each of the following * this returns a collection containing an instance of each of the following
* controls: * controls:

View File

@@ -43,9 +43,12 @@ ol.control.ScaleLineUnits = {
/** /**
* @classdesc * @classdesc
* A control displaying rough x-axis distances. * A control displaying rough x-axis distances, calculated for the center of the
* By default it will show in the bottom left portion of the map, but this can * viewport.
* be changed by using the css selector `.ol-scale-line`. * No scale line will be shown when the x-axis distance cannot be calculated in
* the view projection (e.g. at or beyond the poles in EPSG:4326).
* By default the scale line will show in the bottom left portion of the map,
* but this can be changed by using the css selector `.ol-scale-line`.
* *
* @constructor * @constructor
* @extends {ol.control.Control} * @extends {ol.control.Control}
@@ -304,7 +307,11 @@ ol.control.ScaleLine.prototype.updateElement_ = function() {
count = ol.control.ScaleLine.LEADING_DIGITS[i % 3] * count = ol.control.ScaleLine.LEADING_DIGITS[i % 3] *
Math.pow(10, Math.floor(i / 3)); Math.pow(10, Math.floor(i / 3));
width = Math.round(count / pointResolution); width = Math.round(count / pointResolution);
if (width >= this.minWidth_) { if (isNaN(width)) {
goog.style.setElementShown(this.element_, false);
this.renderedVisible_ = false;
return;
} else if (width >= this.minWidth_) {
break; break;
} }
++i; ++i;

View File

@@ -36,9 +36,15 @@ ol.CoordinateArray;
* Add `delta` to `coordinate`. `coordinate` is modified in place and returned * Add `delta` to `coordinate`. `coordinate` is modified in place and returned
* by the function. * by the function.
* *
* Example:
*
* var coord = [7.85, 47.983333];
* ol.coordinate.add(coord, [-2, 4]);
* // coord is now [5.85, 51.983333]
*
* @param {ol.Coordinate} coordinate Coordinate. * @param {ol.Coordinate} coordinate Coordinate.
* @param {ol.Coordinate} delta Delta. * @param {ol.Coordinate} delta Delta.
* @return {ol.Coordinate} Coordinate. * @return {ol.Coordinate} The input coordinate adjusted by the given delta.
* @api * @api
*/ */
ol.coordinate.add = function(coordinate, delta) { ol.coordinate.add = function(coordinate, delta) {
@@ -88,6 +94,23 @@ ol.coordinate.closestOnSegment = function(coordinate, segment) {
/** /**
* Returns a {@link ol.CoordinateFormatType} function that can be used to format
* a {ol.Coordinate} to a string.
*
* Example without specifying the fractional digits:
*
* var coord = [7.85, 47.983333];
* var stringifyFunc = ol.coordinate.createStringXY();
* var out = stringifyFunc(coord);
* // out is now '8, 48'
*
* Example with explicitly specifying 2 fractional digits:
*
* var coord = [7.85, 47.983333];
* var stringifyFunc = ol.coordinate.createStringXY(2);
* var out = stringifyFunc(coord);
* // out is now '7.85, 47.98'
*
* @param {number=} opt_fractionDigits The number of digits to include * @param {number=} opt_fractionDigits The number of digits to include
* after the decimal point. Default is `0`. * after the decimal point. Default is `0`.
* @return {ol.CoordinateFormatType} Coordinate format. * @return {ol.CoordinateFormatType} Coordinate format.
@@ -122,6 +145,24 @@ ol.coordinate.degreesToStringHDMS_ = function(degrees, hemispheres) {
/** /**
* Transforms the given {@link ol.Coordinate} to a string using the given string
* template. The strings `{x}` and `{y}` in the template will be replaced with
* the first and second coordinate values respectively.
*
* Example without specifying the fractional digits:
*
* var coord = [7.85, 47.983333];
* var template = 'Coordinate is ({x}|{y}).';
* var out = ol.coordinate.format(coord, template);
* // out is now 'Coordinate is (8|48).'
*
* Example explicitly specifying the fractional digits:
*
* var coord = [7.85, 47.983333];
* var template = 'Coordinate is ({x}|{y}).';
* var out = ol.coordinate.format(coord, template, 2);
* // out is now 'Coordinate is (7.85|47.98).'
*
* @param {ol.Coordinate|undefined} coordinate Coordinate. * @param {ol.Coordinate|undefined} coordinate Coordinate.
* @param {string} template A template string with `{x}` and `{y}` placeholders * @param {string} template A template string with `{x}` and `{y}` placeholders
* that will be replaced by first and second coordinate values. * that will be replaced by first and second coordinate values.
@@ -162,6 +203,13 @@ ol.coordinate.equals = function(coordinate1, coordinate2) {
* Rotate `coordinate` by `angle`. `coordinate` is modified in place and * Rotate `coordinate` by `angle`. `coordinate` is modified in place and
* returned by the function. * returned by the function.
* *
* Example:
*
* var coord = [7.85, 47.983333];
* var rotateRadians = Math.PI / 2; // 90 degrees
* ol.coordinate.rotate(coord, rotateRadians);
* // coord is now [-47.983333, 7.85]
*
* @param {ol.Coordinate} coordinate Coordinate. * @param {ol.Coordinate} coordinate Coordinate.
* @param {number} angle Angle in radian. * @param {number} angle Angle in radian.
* @return {ol.Coordinate} Coordinate. * @return {ol.Coordinate} Coordinate.
@@ -182,6 +230,13 @@ ol.coordinate.rotate = function(coordinate, angle) {
* Scale `coordinate` by `scale`. `coordinate` is modified in place and returned * Scale `coordinate` by `scale`. `coordinate` is modified in place and returned
* by the function. * by the function.
* *
* Example:
*
* var coord = [7.85, 47.983333];
* var scale = 1.2;
* ol.coordinate.scale(coord, scale);
* // coord is now [9.42, 57.5799996]
*
* @param {ol.Coordinate} coordinate Coordinate. * @param {ol.Coordinate} coordinate Coordinate.
* @param {number} scale Scale factor. * @param {number} scale Scale factor.
* @return {ol.Coordinate} Coordinate. * @return {ol.Coordinate} Coordinate.
@@ -234,6 +289,12 @@ ol.coordinate.squaredDistanceToSegment = function(coordinate, segment) {
/** /**
* Example:
*
* var coord = [7.85, 47.983333];
* var out = ol.coordinate.toStringHDMS(coord);
* // out is now '47° 59 0″ N 7° 51 0″ E'
*
* @param {ol.Coordinate|undefined} coordinate Coordinate. * @param {ol.Coordinate|undefined} coordinate Coordinate.
* @return {string} Hemisphere, degrees, minutes and seconds. * @return {string} Hemisphere, degrees, minutes and seconds.
* @api * @api
@@ -249,6 +310,18 @@ ol.coordinate.toStringHDMS = function(coordinate) {
/** /**
* Example without specifying fractional digits:
*
* var coord = [7.85, 47.983333];
* var out = ol.coordinate.toStringXY(coord);
* // out is now '8, 48'
*
* Example explicitly specifying 1 fractional digit:
*
* var coord = [7.85, 47.983333];
* var out = ol.coordinate.toStringXY(coord, 1);
* // out is now '7.8, 48.0'
*
* @param {ol.Coordinate|undefined} coordinate Coordinate. * @param {ol.Coordinate|undefined} coordinate Coordinate.
* @param {number=} opt_fractionDigits The number of digits to include * @param {number=} opt_fractionDigits The number of digits to include
* after the decimal point. Default is `0`. * after the decimal point. Default is `0`.
@@ -262,6 +335,15 @@ ol.coordinate.toStringXY = function(coordinate, opt_fractionDigits) {
/** /**
* Create an ol.Coordinate from an Array and take into account axis order. * Create an ol.Coordinate from an Array and take into account axis order.
*
* Examples:
*
* var northCoord = ol.coordinate.fromProjectedArray([1, 2], 'n');
* // northCoord is now [2, 1]
*
* var eastCoord = ol.coordinate.fromProjectedArray([1, 2], 'e');
* // eastCoord is now [1, 2]
*
* @param {Array} array The array with coordinates. * @param {Array} array The array with coordinates.
* @param {string} axis the axis info. * @param {string} axis the axis info.
* @return {ol.Coordinate} The coordinate created. * @return {ol.Coordinate} The coordinate created.

View File

@@ -1,10 +0,0 @@
goog.provide('ol.ellipsoid.BESSEL1841');
goog.require('ol.Ellipsoid');
/**
* @const
* @type {ol.Ellipsoid}
*/
ol.ellipsoid.BESSEL1841 = new ol.Ellipsoid(6377397.155, 1 / 299.15281285);

View File

@@ -50,6 +50,7 @@ ol.events.condition.altShiftKeysOnly = function(mapBrowserEvent) {
* Always true. * Always true.
* @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event. * @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event.
* @return {boolean} True. * @return {boolean} True.
* @function
* @api * @api
*/ */
ol.events.condition.always = goog.functions.TRUE; ol.events.condition.always = goog.functions.TRUE;
@@ -79,6 +80,7 @@ ol.events.condition.mouseMove = function(mapBrowserEvent) {
* Always false. * Always false.
* @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event. * @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event.
* @return {boolean} False. * @return {boolean} False.
* @function
* @api * @api
*/ */
ol.events.condition.never = goog.functions.FALSE; ol.events.condition.never = goog.functions.FALSE;

View File

@@ -418,7 +418,11 @@ ol.extent.extendXY = function(extent, x, y) {
* @return {number} Area. * @return {number} Area.
*/ */
ol.extent.getArea = function(extent) { ol.extent.getArea = function(extent) {
return ol.extent.getWidth(extent) * ol.extent.getHeight(extent); var area = 0;
if (!ol.extent.isEmpty(extent)) {
area = ol.extent.getWidth(extent) * ol.extent.getHeight(extent);
}
return area;
}; };
@@ -511,11 +515,44 @@ ol.extent.getHeight = function(extent) {
* @return {number} Intersection area. * @return {number} Intersection area.
*/ */
ol.extent.getIntersectionArea = function(extent1, extent2) { ol.extent.getIntersectionArea = function(extent1, extent2) {
var minX = Math.max(extent1[0], extent2[0]); var intersection = ol.extent.getIntersection(extent1, extent2);
var minY = Math.max(extent1[1], extent2[1]); return ol.extent.getArea(intersection);
var maxX = Math.min(extent1[2], extent2[2]); };
var maxY = Math.min(extent1[3], extent2[3]);
return Math.max(0, maxX - minX) * Math.max(0, maxY - minY);
/**
* Get the intersection of two extents.
* @param {ol.Extent} extent1 Extent 1.
* @param {ol.Extent} extent2 Extent 2.
* @param {ol.Extent=} opt_extent Optional extent to populate with intersection.
* @return {ol.Extent} Intersecting extent.
*/
ol.extent.getIntersection = function(extent1, extent2, opt_extent) {
var intersection = goog.isDef(opt_extent) ?
opt_extent : ol.extent.createEmpty();
if (ol.extent.intersects(extent1, extent2)) {
if (extent1[0] > extent2[0]) {
intersection[0] = extent1[0];
} else {
intersection[0] = extent2[0];
}
if (extent1[1] > extent2[1]) {
intersection[1] = extent1[1];
} else {
intersection[1] = extent2[1];
}
if (extent1[2] < extent2[2]) {
intersection[2] = extent1[2];
} else {
intersection[2] = extent2[2];
}
if (extent1[3] < extent2[3]) {
intersection[3] = extent1[3];
} else {
intersection[3] = extent2[3];
}
}
return intersection;
}; };

View File

@@ -17,18 +17,46 @@ goog.require('ol.style.Style');
/** /**
* @classdesc * @classdesc
* A vector object for geographical features with a geometry and other * A vector object for geographic features with a geometry and other
* attribute properties, similar to the features in vector file formats like * attribute properties, similar to the features in vector file formats like
* GeoJSON. * GeoJSON.
*
* Features can be styled individually or use the style of their vector layer. * Features can be styled individually or use the style of their vector layer.
* Note that attribute properties are set as {@link ol.Object} properties on the * Note that attribute properties are set as {@link ol.Object} properties on
* feature object, so they are observable, and have get/set accessors. * the feature object, so they are observable, and have get/set accessors.
*
* Typically, a feature has a single geometry property. You can set the
* geometry using the `setGeometry` method and get it with `getGeometry`.
* It is possible to store more than one geometry on a feature using attribute
* properties. By default, the geometry used for rendering is identified by
* the property name `geometry`. If you want to use another geometry property
* for rendering, use the `setGeometryName` method to change the attribute
* property associated with the geometry for the feature. For example:
*
* ```js
* var feature = new ol.Feature({
* geometry: new ol.geom.Polygon(polyCoords),
* labelPoint: new ol.geom.Point(labelCoords),
* name: 'My Polygon'
* });
*
* // get the polygon geometry
* var poly = feature.getGeometry();
*
* // Render the feature as a point using the coordinates from labelPoint
* feature.setGeometryName('labelPoint');
*
* // get the point geometry
* var point = feature.getGeometry();
* ```
* *
* @constructor * @constructor
* @extends {ol.Object} * @extends {ol.Object}
* @fires change Triggered when the geometry or style of the feature changes. * @fires change Triggered when the geometry or style of the feature changes.
* @param {ol.geom.Geometry|Object.<string, *>=} opt_geometryOrProperties * @param {ol.geom.Geometry|Object.<string, *>=} opt_geometryOrProperties
* Geometry or properties. * You may pass a Geometry object directly, or an object literal
* containing properties. If you pass an object literal, you may
* include a Geometry associated with a `geometry` key.
* @api * @api
*/ */
ol.Feature = function(opt_geometryOrProperties) { ol.Feature = function(opt_geometryOrProperties) {
@@ -109,8 +137,12 @@ ol.Feature.prototype.clone = function() {
/** /**
* @return {ol.geom.Geometry|undefined} Geometry. * @return {ol.geom.Geometry|undefined} Returns the Geometry associated
* with this feature using the current geometry name property. By
* default, this is `geometry` but it may be changed by calling
* `setGeometryName`.
* @api * @api
* @observable
*/ */
ol.Feature.prototype.getGeometry = function() { ol.Feature.prototype.getGeometry = function() {
return /** @type {ol.geom.Geometry|undefined} */ ( return /** @type {ol.geom.Geometry|undefined} */ (
@@ -132,7 +164,9 @@ ol.Feature.prototype.getId = function() {
/** /**
* @return {string} Geometry property name. * @return {string} Get the property name associated with the geometry for
* this feature. By default, this is `geometry` but it may be changed by
* calling `setGeometryName`.
* @api * @api
*/ */
ol.Feature.prototype.getGeometryName = function() { ol.Feature.prototype.getGeometryName = function() {
@@ -142,7 +176,9 @@ ol.Feature.prototype.getGeometryName = function() {
/** /**
* @return {ol.style.Style|Array.<ol.style.Style>| * @return {ol.style.Style|Array.<ol.style.Style>|
* ol.feature.FeatureStyleFunction} User provided style. * ol.feature.FeatureStyleFunction} Return the style provided in the
* constructor options or the last call to setStyle in the same format
* that it was provided in.
* @api * @api
*/ */
ol.Feature.prototype.getStyle = function() { ol.Feature.prototype.getStyle = function() {
@@ -151,7 +187,8 @@ ol.Feature.prototype.getStyle = function() {
/** /**
* @return {ol.feature.FeatureStyleFunction|undefined} Style function. * @return {ol.feature.FeatureStyleFunction|undefined} Return a function
* representing the current style of this feature.
* @api * @api
*/ */
ol.Feature.prototype.getStyleFunction = function() { ol.Feature.prototype.getStyleFunction = function() {
@@ -185,8 +222,12 @@ ol.Feature.prototype.handleGeometryChanged_ = function() {
/** /**
* @param {ol.geom.Geometry|undefined} geometry Geometry. * @param {ol.geom.Geometry|undefined} geometry Set the geometry for this
* feature. This will update the property associated with the current
* geometry property name. By default, this is `geometry` but it can be
* changed by calling `setGeometryName`.
* @api * @api
* @observable
*/ */
ol.Feature.prototype.setGeometry = function(geometry) { ol.Feature.prototype.setGeometry = function(geometry) {
this.set(this.geometryName_, geometry); this.set(this.geometryName_, geometry);
@@ -199,7 +240,7 @@ goog.exportProperty(
/** /**
* @param {ol.style.Style|Array.<ol.style.Style>| * @param {ol.style.Style|Array.<ol.style.Style>|
* ol.feature.FeatureStyleFunction} style Feature style. * ol.feature.FeatureStyleFunction} style Set the style for this feature.
* @api * @api
*/ */
ol.Feature.prototype.setStyle = function(style) { ol.Feature.prototype.setStyle = function(style) {
@@ -210,7 +251,9 @@ ol.Feature.prototype.setStyle = function(style) {
/** /**
* @param {number|string|undefined} id Id. * @param {number|string|undefined} id Set a unique id for this feature.
* The id may be used to retrieve a feature from a vector source with the
* {@link ol.source.Vector#getFeatureById} method.
* @api * @api
*/ */
ol.Feature.prototype.setId = function(id) { ol.Feature.prototype.setId = function(id) {
@@ -220,7 +263,8 @@ ol.Feature.prototype.setId = function(id) {
/** /**
* @param {string} name Geometry property name. * @param {string} name Set the property name from which this feature's
* geometry will be fetched when calling `getGeometry`.
* @api * @api
*/ */
ol.Feature.prototype.setGeometryName = function(name) { ol.Feature.prototype.setGeometryName = function(name) {
@@ -247,69 +291,6 @@ ol.Feature.prototype.setGeometryName = function(name) {
ol.feature.FeatureStyleFunction; ol.feature.FeatureStyleFunction;
/**
* Default style function for features.
* @param {number} resolution Resolution.
* @return {Array.<ol.style.Style>} Style.
* @this {ol.Feature}
*/
ol.feature.defaultFeatureStyleFunction = function(resolution) {
var fill = new ol.style.Fill({
color: 'rgba(255,255,255,0.4)'
});
var stroke = new ol.style.Stroke({
color: '#3399CC',
width: 1.25
});
var styles = [
new ol.style.Style({
image: new ol.style.Circle({
fill: fill,
stroke: stroke,
radius: 5
}),
fill: fill,
stroke: stroke
})
];
// now that we've run it the first time,
// replace the function with a constant version
ol.feature.defaultFeatureStyleFunction =
/** @type {function(this:ol.Feature):Array.<ol.style.Style>} */(
function(resolution) {
return styles;
});
return styles;
};
/**
* A function that takes an {@link ol.Feature} and a `{number}` representing
* the view's resolution. The function should return an array of
* {@link ol.style.Style}. This way e.g. a vector layer can be styled.
*
* @typedef {function(ol.Feature, number): Array.<ol.style.Style>}
* @api
*/
ol.feature.StyleFunction;
/**
* @param {ol.Feature} feature Feature.
* @param {number} resolution Resolution.
* @return {Array.<ol.style.Style>} Style.
*/
ol.feature.defaultStyleFunction = function(feature, resolution) {
var featureStyleFunction = feature.getStyleFunction();
if (!goog.isDef(featureStyleFunction)) {
featureStyleFunction = ol.feature.defaultFeatureStyleFunction;
}
return featureStyleFunction.call(feature, resolution);
};
/** /**
* Convert the provided object into a feature style function. Functions passed * Convert the provided object into a feature style function. Functions passed
* through unchanged. Arrays of ol.style.Style or single style objects wrapped * through unchanged. Arrays of ol.style.Style or single style objects wrapped
@@ -344,39 +325,6 @@ ol.feature.createFeatureStyleFunction = function(obj) {
}; };
/**
* Convert the provided object into a style function. Functions passed through
* unchanged. Arrays of ol.style.Style or single style objects wrapped in a
* new style function.
* @param {ol.feature.StyleFunction|Array.<ol.style.Style>|ol.style.Style} obj
* A style function, a single style, or an array of styles.
* @return {ol.feature.StyleFunction} A style function.
*/
ol.feature.createStyleFunction = function(obj) {
/**
* @type {ol.feature.StyleFunction}
*/
var styleFunction;
if (goog.isFunction(obj)) {
styleFunction = /** @type {ol.feature.StyleFunction} */ (obj);
} else {
/**
* @type {Array.<ol.style.Style>}
*/
var styles;
if (goog.isArray(obj)) {
styles = obj;
} else {
goog.asserts.assertInstanceof(obj, ol.style.Style);
styles = [obj];
}
styleFunction = goog.functions.constant(styles);
}
return styleFunction;
};
/** /**
* Default styles for editing features. * Default styles for editing features.
* @return {Object.<ol.geom.GeometryType, Array.<ol.style.Style>>} Styles * @return {Object.<ol.geom.GeometryType, Array.<ol.style.Style>>} Styles

View File

@@ -8,9 +8,9 @@ goog.require('goog.object');
goog.require('ol.Collection'); goog.require('ol.Collection');
goog.require('ol.CollectionEventType'); goog.require('ol.CollectionEventType');
goog.require('ol.Feature'); goog.require('ol.Feature');
goog.require('ol.feature');
goog.require('ol.render.EventType'); goog.require('ol.render.EventType');
goog.require('ol.renderer.vector'); goog.require('ol.renderer.vector');
goog.require('ol.style.Style');
@@ -63,19 +63,18 @@ ol.FeatureOverlay = function(opt_options) {
/** /**
* @private * @private
* @type {ol.style.Style|Array.<ol.style.Style>|ol.feature.StyleFunction} * @type {ol.style.Style|Array.<ol.style.Style>|ol.style.StyleFunction}
*/ */
this.style_ = null; this.style_ = null;
/** /**
* @private * @private
* @type {ol.feature.StyleFunction|undefined} * @type {ol.style.StyleFunction|undefined}
*/ */
this.styleFunction_ = undefined; this.styleFunction_ = undefined;
if (goog.isDef(options.style)) { this.setStyle(goog.isDef(options.style) ?
this.setStyle(options.style); options.style : ol.style.defaultStyleFunction);
}
if (goog.isDef(options.features)) { if (goog.isDef(options.features)) {
if (goog.isArray(options.features)) { if (goog.isArray(options.features)) {
@@ -169,7 +168,7 @@ ol.FeatureOverlay.prototype.handleMapPostCompose_ = function(event) {
} }
var styleFunction = this.styleFunction_; var styleFunction = this.styleFunction_;
if (!goog.isDef(styleFunction)) { if (!goog.isDef(styleFunction)) {
styleFunction = ol.feature.defaultStyleFunction; styleFunction = ol.style.defaultStyleFunction;
} }
var replayGroup = /** @type {ol.render.IReplayGroup} */ var replayGroup = /** @type {ol.render.IReplayGroup} */
(event.replayGroup); (event.replayGroup);
@@ -270,13 +269,13 @@ ol.FeatureOverlay.prototype.setMap = function(map) {
* Set the style for features. This can be a single style object, an array * Set the style for features. This can be a single style object, an array
* of styles, or a function that takes a feature and resolution and returns * of styles, or a function that takes a feature and resolution and returns
* an array of styles. * an array of styles.
* @param {ol.style.Style|Array.<ol.style.Style>|ol.feature.StyleFunction} style * @param {ol.style.Style|Array.<ol.style.Style>|ol.style.StyleFunction} style
* Overlay style. * Overlay style.
* @api * @api
*/ */
ol.FeatureOverlay.prototype.setStyle = function(style) { ol.FeatureOverlay.prototype.setStyle = function(style) {
this.style_ = style; this.style_ = style;
this.styleFunction_ = ol.feature.createStyleFunction(style); this.styleFunction_ = ol.style.createStyleFunction(style);
this.render_(); this.render_();
}; };
@@ -284,7 +283,7 @@ ol.FeatureOverlay.prototype.setStyle = function(style) {
/** /**
* Get the style for features. This returns whatever was passed to the `style` * Get the style for features. This returns whatever was passed to the `style`
* option at construction or to the `setStyle` method. * option at construction or to the `setStyle` method.
* @return {ol.style.Style|Array.<ol.style.Style>|ol.feature.StyleFunction} * @return {ol.style.Style|Array.<ol.style.Style>|ol.style.StyleFunction}
* Overlay style. * Overlay style.
* @api * @api
*/ */
@@ -295,7 +294,7 @@ ol.FeatureOverlay.prototype.getStyle = function() {
/** /**
* Get the style function. * Get the style function.
* @return {ol.feature.StyleFunction|undefined} Style function. * @return {ol.style.StyleFunction|undefined} Style function.
* @api * @api
*/ */
ol.FeatureOverlay.prototype.getStyleFunction = function() { ol.FeatureOverlay.prototype.getStyleFunction = function() {

View File

@@ -1,5 +1,4 @@
goog.provide('ol.format.GPX'); goog.provide('ol.format.GPX');
goog.provide('ol.format.GPX.V1_1');
goog.require('goog.array'); goog.require('goog.array');
goog.require('goog.asserts'); goog.require('goog.asserts');
@@ -794,17 +793,6 @@ ol.format.GPX.GPX_SERIALIZERS_ = ol.xml.makeStructureNS(
}); });
/**
* @constructor
* @extends {ol.format.GPX}
*/
ol.format.GPX.V1_1 = function() {
goog.base(this);
};
goog.inherits(ol.format.GPX.V1_1, ol.format.GPX);
/** /**
* Encode an array of features in the GPX format. * Encode an array of features in the GPX format.
* *
@@ -819,7 +807,7 @@ ol.format.GPX.prototype.writeFeatures;
/** /**
* @inheritDoc * @inheritDoc
*/ */
ol.format.GPX.V1_1.prototype.writeFeaturesNode = function(features) { ol.format.GPX.prototype.writeFeaturesNode = function(features) {
//FIXME Serialize metadata //FIXME Serialize metadata
var gpx = ol.xml.createElementNS('http://www.topografix.com/GPX/1/1', 'gpx'); var gpx = ol.xml.createElementNS('http://www.topografix.com/GPX/1/1', 'gpx');
ol.xml.pushSerializeAndPop(/** @type {ol.xml.NodeStackItem} */ ol.xml.pushSerializeAndPop(/** @type {ol.xml.NodeStackItem} */

View File

@@ -17,7 +17,8 @@ goog.require('ol.xml');
/** /**
* @classdesc * @classdesc
* Feature format for reading and writing data in the OSMXML format. * Feature format for reading data in the
* [OSMXML format](http://wiki.openstreetmap.org/wiki/OSM_XML).
* *
* @constructor * @constructor
* @extends {ol.format.XMLFeature} * @extends {ol.format.XMLFeature}

View File

@@ -1,7 +1,7 @@
goog.provide('ol.format.WKT'); goog.provide('ol.format.WKT');
goog.require('goog.array'); goog.require('goog.array');
goog.require('goog.string'); goog.require('goog.asserts');
goog.require('ol.Feature'); goog.require('ol.Feature');
goog.require('ol.format.TextFeature'); goog.require('ol.format.TextFeature');
goog.require('ol.geom.Geometry'); goog.require('ol.geom.Geometry');
@@ -29,7 +29,7 @@ ol.format.WKT = function(opt_options) {
goog.base(this); goog.base(this);
/** /**
* Split GEOMETRYCOLLECTION into multiple features. * Split GeometryCollection into multiple features.
* @type {boolean} * @type {boolean}
* @private * @private
*/ */
@@ -41,132 +41,10 @@ goog.inherits(ol.format.WKT, ol.format.TextFeature);
/** /**
* Constants for regExes. * @const
* @enum {RegExp} * @type {string}
*/ */
ol.format.WKT.regExes = { ol.format.WKT.EMPTY = 'EMPTY';
typeStr: /^\s*(\w+)\s*\(\s*(.*)\s*\)\s*$/,
spaces: /\s+/,
parenComma: /\)\s*,\s*\(/,
doubleParenComma: /\)\s*\)\s*,\s*\(\s*\(/,
trimParens: /^\s*\(?(.*?)\)?\s*$/,
geomCollection: /,\s*([A-Za-z])/g,
removeNewLine: /[\n\r]/g
};
/**
* @param {string} str WKT point.
* @return {ol.geom.Point} Parsed point.
* @private
*/
ol.format.WKT.prototype.parsePoint_ = function(str) {
var coords = goog.string.trim(str).split(ol.format.WKT.regExes.spaces);
return new ol.geom.Point(goog.array.map(coords, parseFloat));
};
/**
* @param {string} str WKT linestring.
* @return {ol.geom.LineString} Parsed linestring.
* @private
*/
ol.format.WKT.prototype.parseLineString_ = function(str) {
var points = goog.string.trim(str).split(',');
var coordinates = [];
for (var i = 0, ii = points.length; i < ii; ++i) {
coordinates.push(this.parsePoint_.apply(this,
[points[i]]).getCoordinates());
}
return new ol.geom.LineString(coordinates);
};
/**
* @param {string} str WKT multipoint.
* @return {ol.geom.MultiPoint} Parsed multipoint.
* @private
*/
ol.format.WKT.prototype.parseMultiPoint_ = function(str) {
var point;
var points = goog.string.trim(str).split(',');
var geom = new ol.geom.MultiPoint(null);
for (var i = 0, ii = points.length; i < ii; ++i) {
point = points[i].replace(ol.format.WKT.regExes.trimParens, '$1');
geom.appendPoint(this.parsePoint_.apply(this, [point]));
}
return geom;
};
/**
* @param {string} str WKT multilinestring.
* @return {ol.geom.MultiLineString} Parsed multilinestring.
* @private
*/
ol.format.WKT.prototype.parseMultiLineString_ = function(str) {
var line;
var lines = goog.string.trim(str).split(ol.format.WKT.regExes.parenComma);
var geom = new ol.geom.MultiLineString(null);
for (var i = 0, ii = lines.length; i < ii; ++i) {
line = lines[i].replace(ol.format.WKT.regExes.trimParens, '$1');
geom.appendLineString(this.parseLineString_.apply(this, [line]));
}
return geom;
};
/**
* @param {string} str WKT polygon.
* @return {ol.geom.Polygon} Parsed polygon.
* @private
*/
ol.format.WKT.prototype.parsePolygon_ = function(str) {
var ring, linestring, linearring;
var rings = goog.string.trim(str).split(ol.format.WKT.regExes.parenComma);
var coordinates = [];
for (var i = 0, ii = rings.length; i < ii; ++i) {
ring = rings[i].replace(ol.format.WKT.regExes.trimParens, '$1');
linestring = this.parseLineString_.apply(this, [ring]).getCoordinates();
coordinates.push(linestring);
}
return new ol.geom.Polygon(coordinates);
};
/**
* @param {string} str WKT multipolygon.
* @return {ol.geom.MultiPolygon} Parsed multipolygon.
* @private
*/
ol.format.WKT.prototype.parseMultiPolygon_ = function(str) {
var polygon;
var polygons = goog.string.trim(str).split(
ol.format.WKT.regExes.doubleParenComma);
var geom = new ol.geom.MultiPolygon(null);
for (var i = 0, ii = polygons.length; i < ii; ++i) {
polygon = polygons[i].replace(ol.format.WKT.regExes.trimParens, '$1');
geom.appendPolygon(this.parsePolygon_.apply(this, [polygon]));
}
return geom;
};
/**
* @param {string} str WKT geometrycollection.
* @return {ol.geom.GeometryCollection} Parsed geometrycollection.
* @private
*/
ol.format.WKT.prototype.parseGeometryCollection_ = function(str) {
// separate components of the collection with |
str = str.replace(ol.format.WKT.regExes.geomCollection, '|$1');
var wktArray = goog.string.trim(str).split('|');
var geoms = [];
for (var i = 0, ii = wktArray.length; i < ii; ++i) {
geoms.push(this.parse_.apply(this, [wktArray[i]]));
}
return new ol.geom.GeometryCollection(geoms);
};
/** /**
@@ -174,8 +52,11 @@ ol.format.WKT.prototype.parseGeometryCollection_ = function(str) {
* @return {string} Coordinates part of Point as WKT. * @return {string} Coordinates part of Point as WKT.
* @private * @private
*/ */
ol.format.WKT.prototype.encodePoint_ = function(geom) { ol.format.WKT.encodePointGeometry_ = function(geom) {
var coordinates = geom.getCoordinates(); var coordinates = geom.getCoordinates();
if (goog.array.isEmpty(coordinates)) {
return '';
}
return coordinates[0] + ' ' + coordinates[1]; return coordinates[0] + ' ' + coordinates[1];
}; };
@@ -185,11 +66,11 @@ ol.format.WKT.prototype.encodePoint_ = function(geom) {
* @return {string} Coordinates part of MultiPoint as WKT. * @return {string} Coordinates part of MultiPoint as WKT.
* @private * @private
*/ */
ol.format.WKT.prototype.encodeMultiPoint_ = function(geom) { ol.format.WKT.encodeMultiPointGeometry_ = function(geom) {
var array = []; var array = [];
var components = geom.getPoints(); var components = geom.getPoints();
for (var i = 0, ii = components.length; i < ii; ++i) { for (var i = 0, ii = components.length; i < ii; ++i) {
array.push('(' + this.encodePoint_.apply(this, [components[i]]) + ')'); array.push('(' + ol.format.WKT.encodePointGeometry_(components[i]) + ')');
} }
return array.join(','); return array.join(',');
}; };
@@ -200,22 +81,22 @@ ol.format.WKT.prototype.encodeMultiPoint_ = function(geom) {
* @return {string} Coordinates part of GeometryCollection as WKT. * @return {string} Coordinates part of GeometryCollection as WKT.
* @private * @private
*/ */
ol.format.WKT.prototype.encodeGeometryCollection_ = function(geom) { ol.format.WKT.encodeGeometryCollectionGeometry_ = function(geom) {
var array = []; var array = [];
var geoms = geom.getGeometries(); var geoms = geom.getGeometries();
for (var i = 0, ii = geoms.length; i < ii; ++i) { for (var i = 0, ii = geoms.length; i < ii; ++i) {
array.push(this.encode_.apply(this, [geoms[i]])); array.push(ol.format.WKT.encode_(geoms[i]));
} }
return array.join(','); return array.join(',');
}; };
/** /**
* @param {ol.geom.LineString} geom LineString geometry. * @param {ol.geom.LineString|ol.geom.LinearRing} geom LineString geometry.
* @return {string} Coordinates part of LineString as WKT. * @return {string} Coordinates part of LineString as WKT.
* @private * @private
*/ */
ol.format.WKT.prototype.encodeLineString_ = function(geom) { ol.format.WKT.encodeLineStringGeometry_ = function(geom) {
var coordinates = geom.getCoordinates(); var coordinates = geom.getCoordinates();
var array = []; var array = [];
for (var i = 0, ii = coordinates.length; i < ii; ++i) { for (var i = 0, ii = coordinates.length; i < ii; ++i) {
@@ -230,12 +111,12 @@ ol.format.WKT.prototype.encodeLineString_ = function(geom) {
* @return {string} Coordinates part of MultiLineString as WKT. * @return {string} Coordinates part of MultiLineString as WKT.
* @private * @private
*/ */
ol.format.WKT.prototype.encodeMultiLineString_ = function(geom) { ol.format.WKT.encodeMultiLineStringGeometry_ = function(geom) {
var array = []; var array = [];
var components = geom.getLineStrings(); var components = geom.getLineStrings();
for (var i = 0, ii = components.length; i < ii; ++i) { for (var i = 0, ii = components.length; i < ii; ++i) {
array.push('(' + this.encodeLineString_.apply(this, array.push('(' + ol.format.WKT.encodeLineStringGeometry_(
[components[i]]) + ')'); components[i]) + ')');
} }
return array.join(','); return array.join(',');
}; };
@@ -246,12 +127,12 @@ ol.format.WKT.prototype.encodeMultiLineString_ = function(geom) {
* @return {string} Coordinates part of Polygon as WKT. * @return {string} Coordinates part of Polygon as WKT.
* @private * @private
*/ */
ol.format.WKT.prototype.encodePolygon_ = function(geom) { ol.format.WKT.encodePolygonGeometry_ = function(geom) {
var array = []; var array = [];
var rings = geom.getLinearRings(); var rings = geom.getLinearRings();
for (var i = 0, ii = rings.length; i < ii; ++i) { for (var i = 0, ii = rings.length; i < ii; ++i) {
array.push('(' + this.encodeLineString_.apply(this, array.push('(' + ol.format.WKT.encodeLineStringGeometry_(
[rings[i]]) + ')'); rings[i]) + ')');
} }
return array.join(','); return array.join(',');
}; };
@@ -262,16 +143,52 @@ ol.format.WKT.prototype.encodePolygon_ = function(geom) {
* @return {string} Coordinates part of MultiPolygon as WKT. * @return {string} Coordinates part of MultiPolygon as WKT.
* @private * @private
*/ */
ol.format.WKT.prototype.encodeMultiPolygon_ = function(geom) { ol.format.WKT.encodeMultiPolygonGeometry_ = function(geom) {
var array = []; var array = [];
var components = geom.getPolygons(); var components = geom.getPolygons();
for (var i = 0, ii = components.length; i < ii; ++i) { for (var i = 0, ii = components.length; i < ii; ++i) {
array.push('(' + this.encodePolygon_.apply(this, [components[i]]) + ')'); array.push('(' + ol.format.WKT.encodePolygonGeometry_(
components[i]) + ')');
} }
return array.join(','); return array.join(',');
}; };
/**
* Encode a geometry as WKT.
* @param {ol.geom.Geometry} geom The geometry to encode.
* @return {string} WKT string for the geometry.
* @private
*/
ol.format.WKT.encode_ = function(geom) {
var type = geom.getType();
var geometryEncoder = ol.format.WKT.GeometryEncoder_[type];
goog.asserts.assert(goog.isDef(geometryEncoder));
var enc = geometryEncoder(geom);
type = type.toUpperCase();
if (enc.length === 0) {
return type + ' ' + ol.format.WKT.EMPTY;
}
return type + '(' + enc + ')';
};
/**
* @const
* @type {Object.<string, function(ol.geom.Geometry): string>}
* @private
*/
ol.format.WKT.GeometryEncoder_ = {
'Point': ol.format.WKT.encodePointGeometry_,
'LineString': ol.format.WKT.encodeLineStringGeometry_,
'Polygon': ol.format.WKT.encodePolygonGeometry_,
'MultiPoint': ol.format.WKT.encodeMultiPointGeometry_,
'MultiLineString': ol.format.WKT.encodeMultiLineStringGeometry_,
'MultiPolygon': ol.format.WKT.encodeMultiPolygonGeometry_,
'GeometryCollection': ol.format.WKT.encodeGeometryCollectionGeometry_
};
/** /**
* Parse a WKT string. * Parse a WKT string.
* @param {string} wkt WKT string. * @param {string} wkt WKT string.
@@ -280,75 +197,16 @@ ol.format.WKT.prototype.encodeMultiPolygon_ = function(geom) {
* @private * @private
*/ */
ol.format.WKT.prototype.parse_ = function(wkt) { ol.format.WKT.prototype.parse_ = function(wkt) {
wkt = wkt.replace(ol.format.WKT.regExes.removeNewLine, ' '); var lexer = new ol.format.WKT.Lexer(wkt);
var matches = ol.format.WKT.regExes.typeStr.exec(wkt); var parser = new ol.format.WKT.Parser(lexer);
var geometry; return parser.parse();
if (matches) {
var type = matches[1].toLowerCase();
var str = matches[2];
switch (type) {
case 'point':
geometry = this.parsePoint_(str);
break;
case 'multipoint':
geometry = this.parseMultiPoint_(str);
break;
case 'linestring':
geometry = this.parseLineString_(str);
break;
case 'multilinestring':
geometry = this.parseMultiLineString_(str);
break;
case 'polygon':
geometry = this.parsePolygon_(str);
break;
case 'multipolygon':
geometry = this.parseMultiPolygon_(str);
break;
case 'geometrycollection':
geometry = this.parseGeometryCollection_(str);
break;
default:
throw new Error('Bad geometry type: ' + type);
}
}
return geometry;
};
/**
* Encode a geometry as WKT.
* @param {ol.geom.Geometry} geom The geometry to encode.
* @return {string} WKT string for the geometry.
* @private
*/
ol.format.WKT.prototype.encode_ = function(geom) {
var type = geom.getType();
var result = type.toUpperCase() + '(';
if (geom instanceof ol.geom.Point) {
result += this.encodePoint_(geom);
} else if (geom instanceof ol.geom.MultiPoint) {
result += this.encodeMultiPoint_(geom);
} else if (geom instanceof ol.geom.LineString) {
result += this.encodeLineString_(geom);
} else if (geom instanceof ol.geom.MultiLineString) {
result += this.encodeMultiLineString_(geom);
} else if (geom instanceof ol.geom.Polygon) {
result += this.encodePolygon_(geom);
} else if (geom instanceof ol.geom.MultiPolygon) {
result += this.encodeMultiPolygon_(geom);
} else if (geom instanceof ol.geom.GeometryCollection) {
result += this.encodeGeometryCollection_(geom);
} else {
throw new Error('Bad geometry type: ' + type);
}
return result + ')';
}; };
/** /**
* Read a feature from a WKT source. * Read a feature from a WKT source.
* *
* @function
* @param {ArrayBuffer|Document|Node|Object|string} source Source. * @param {ArrayBuffer|Document|Node|Object|string} source Source.
* @return {ol.Feature} Feature. * @return {ol.Feature} Feature.
* @api * @api
@@ -373,6 +231,7 @@ ol.format.WKT.prototype.readFeatureFromText = function(text) {
/** /**
* Read all features from a WKT source. * Read all features from a WKT source.
* *
* @function
* @param {ArrayBuffer|Document|Node|Object|string} source Source. * @param {ArrayBuffer|Document|Node|Object|string} source Source.
* @return {Array.<ol.Feature>} Features. * @return {Array.<ol.Feature>} Features.
* @api * @api
@@ -406,6 +265,7 @@ ol.format.WKT.prototype.readFeaturesFromText = function(text) {
/** /**
* Read a single geometry from a WKT source. * Read a single geometry from a WKT source.
* *
* @function
* @param {ArrayBuffer|Document|Node|Object|string} source Source. * @param {ArrayBuffer|Document|Node|Object|string} source Source.
* @return {ol.geom.Geometry} Geometry. * @return {ol.geom.Geometry} Geometry.
* @api * @api
@@ -432,6 +292,7 @@ ol.format.WKT.prototype.readProjectionFromText = function(text) {
/** /**
* Encode a feature as a WKT string. * Encode a feature as a WKT string.
* *
* @function
* @param {ol.Feature} feature Feature. * @param {ol.Feature} feature Feature.
* @return {ArrayBuffer|Node|Object|string} Result. * @return {ArrayBuffer|Node|Object|string} Result.
* @api * @api
@@ -454,6 +315,7 @@ ol.format.WKT.prototype.writeFeatureText = function(feature) {
/** /**
* Encode an array of features as a WKT string. * Encode an array of features as a WKT string.
* *
* @function
* @param {Array.<ol.Feature>} features Features. * @param {Array.<ol.Feature>} features Features.
* @return {ArrayBuffer|Node|Object|string} Result. * @return {ArrayBuffer|Node|Object|string} Result.
* @api * @api
@@ -480,6 +342,7 @@ ol.format.WKT.prototype.writeFeaturesText = function(features) {
/** /**
* Write a single geometry as a WKT string. * Write a single geometry as a WKT string.
* *
* @function
* @param {ol.geom.Geometry} geometry Geometry. * @param {ol.geom.Geometry} geometry Geometry.
* @return {ArrayBuffer|Node|Object|string} Node. * @return {ArrayBuffer|Node|Object|string} Node.
* @api * @api
@@ -491,5 +354,493 @@ ol.format.WKT.prototype.writeGeometry;
* @inheritDoc * @inheritDoc
*/ */
ol.format.WKT.prototype.writeGeometryText = function(geometry) { ol.format.WKT.prototype.writeGeometryText = function(geometry) {
return this.encode_(geometry); return ol.format.WKT.encode_(geometry);
};
/**
* @typedef {{type: number, value: (number|string|undefined), position: number}}
*/
ol.format.WKT.Token;
/**
* @const
* @enum {number}
*/
ol.format.WKT.TokenType = {
TEXT: 1,
LEFT_PAREN: 2,
RIGHT_PAREN: 3,
NUMBER: 4,
COMMA: 5,
EOF: 6
};
/**
* Class to tokenize a WKT string.
* @param {string} wkt WKT string.
* @constructor
* @protected
*/
ol.format.WKT.Lexer = function(wkt) {
/**
* @type {string}
*/
this.wkt = wkt;
/**
* @type {number}
* @private
*/
this.index_ = -1;
};
/**
* @param {string} c Character.
* @return {boolean} Whether the character is alphabetic.
* @private
*/
ol.format.WKT.Lexer.prototype.isAlpha_ = function(c) {
return c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z';
};
/**
* @param {string} c Character.
* @param {boolean=} opt_decimal Whether the string number
* contains a dot, i.e. is a decimal number.
* @return {boolean} Whether the character is numeric.
* @private
*/
ol.format.WKT.Lexer.prototype.isNumeric_ = function(c, opt_decimal) {
var decimal = goog.isDef(opt_decimal) ? opt_decimal : false;
return c >= '0' && c <= '9' || c == '.' && !decimal;
};
/**
* @param {string} c Character.
* @return {boolean} Whether the character is whitespace.
* @private
*/
ol.format.WKT.Lexer.prototype.isWhiteSpace_ = function(c) {
return c == ' ' || c == '\t' || c == '\r' || c == '\n';
};
/**
* @return {string} Next string character.
* @private
*/
ol.format.WKT.Lexer.prototype.nextChar_ = function() {
return this.wkt.charAt(++this.index_);
};
/**
* Fetch and return the next token.
* @return {!ol.format.WKT.Token} Next string token.
*/
ol.format.WKT.Lexer.prototype.nextToken = function() {
var c = this.nextChar_();
var token = {position: this.index_, value: c};
if (c == '(') {
token.type = ol.format.WKT.TokenType.LEFT_PAREN;
} else if (c == ',') {
token.type = ol.format.WKT.TokenType.COMMA;
} else if (c == ')') {
token.type = ol.format.WKT.TokenType.RIGHT_PAREN;
} else if (this.isNumeric_(c) || c == '-') {
token.type = ol.format.WKT.TokenType.NUMBER;
token.value = this.readNumber_();
} else if (this.isAlpha_(c)) {
token.type = ol.format.WKT.TokenType.TEXT;
token.value = this.readText_();
} else if (this.isWhiteSpace_(c)) {
return this.nextToken();
} else if (c === '') {
token.type = ol.format.WKT.TokenType.EOF;
} else {
throw new Error('Unexpected character: ' + c);
}
return token;
};
/**
* @return {number} Numeric token value.
* @private
*/
ol.format.WKT.Lexer.prototype.readNumber_ = function() {
var c, index = this.index_;
var decimal = false;
do {
if (c == '.') {
decimal = true;
}
c = this.nextChar_();
} while (this.isNumeric_(c, decimal));
return parseFloat(this.wkt.substring(index, this.index_--));
};
/**
* @return {string} String token value.
* @private
*/
ol.format.WKT.Lexer.prototype.readText_ = function() {
var c, index = this.index_;
do {
c = this.nextChar_();
} while (this.isAlpha_(c));
return this.wkt.substring(index, this.index_--).toUpperCase();
};
/**
* Class to parse the tokens from the WKT string.
* @param {ol.format.WKT.Lexer} lexer
* @constructor
* @protected
*/
ol.format.WKT.Parser = function(lexer) {
/**
* @type {ol.format.WKT.Lexer}
* @private
*/
this.lexer_ = lexer;
/**
* @type {ol.format.WKT.Token}
* @private
*/
this.token_;
/**
* @type {number}
* @private
*/
this.dimension_ = 2;
};
/**
* Fetch the next token form the lexer and replace the active token.
* @private
*/
ol.format.WKT.Parser.prototype.consume_ = function() {
this.token_ = this.lexer_.nextToken();
};
/**
* If the given type matches the current token, consume it.
* @param {ol.format.WKT.TokenType.<number>} type Token type.
* @return {boolean} Whether the token matches the given type.
*/
ol.format.WKT.Parser.prototype.match = function(type) {
var isMatch = this.token_.type == type;
if (isMatch) {
this.consume_();
}
return isMatch;
};
/**
* Try to parse the tokens provided by the lexer.
* @return {ol.geom.Geometry|ol.geom.GeometryCollection} The geometry.
*/
ol.format.WKT.Parser.prototype.parse = function() {
this.consume_();
var geometry = this.parseGeometry_();
goog.asserts.assert(this.token_.type == ol.format.WKT.TokenType.EOF);
return geometry;
};
/**
* @return {!ol.geom.Geometry|!ol.geom.GeometryCollection} The geometry.
* @private
*/
ol.format.WKT.Parser.prototype.parseGeometry_ = function() {
var token = this.token_;
if (this.match(ol.format.WKT.TokenType.TEXT)) {
var geomType = token.value;
if (geomType == ol.geom.GeometryType.GEOMETRY_COLLECTION.toUpperCase()) {
var geometries = this.parseGeometryCollectionText_();
return new ol.geom.GeometryCollection(geometries);
} else {
var parser = ol.format.WKT.Parser.GeometryParser_[geomType];
var ctor = ol.format.WKT.Parser.GeometryConstructor_[geomType];
if (!goog.isDef(parser) || !goog.isDef(ctor)) {
throw new Error('Invalid geometry type: ' + geomType);
}
var coordinates = parser.call(this);
return new ctor(coordinates);
}
}
this.raiseError_();
};
/**
* @return {!Array.<ol.geom.Geometry>} A collection of geometries.
* @private
*/
ol.format.WKT.Parser.prototype.parseGeometryCollectionText_ = function() {
if (this.match(ol.format.WKT.TokenType.LEFT_PAREN)) {
var geometries = [];
do {
geometries.push(this.parseGeometry_());
} while (this.match(ol.format.WKT.TokenType.COMMA));
if (this.match(ol.format.WKT.TokenType.RIGHT_PAREN)) {
return geometries;
}
} else if (this.isEmptyGeometry_()) {
return [];
}
this.raiseError_();
};
/**
* @return {Array.<number>} All values in a point.
* @private
*/
ol.format.WKT.Parser.prototype.parsePointText_ = function() {
if (this.match(ol.format.WKT.TokenType.LEFT_PAREN)) {
var coordinates = this.parsePoint_();
if (this.match(ol.format.WKT.TokenType.RIGHT_PAREN)) {
return coordinates;
}
} else if (this.isEmptyGeometry_()) {
return null;
}
this.raiseError_();
};
/**
* @return {!Array.<!Array.<number>>} All points in a linestring.
* @private
*/
ol.format.WKT.Parser.prototype.parseLineStringText_ = function() {
if (this.match(ol.format.WKT.TokenType.LEFT_PAREN)) {
var coordinates = this.parsePointList_();
if (this.match(ol.format.WKT.TokenType.RIGHT_PAREN)) {
return coordinates;
}
} else if (this.isEmptyGeometry_()) {
return [];
}
this.raiseError_();
};
/**
* @return {!Array.<!Array.<number>>} All points in a polygon.
* @private
*/
ol.format.WKT.Parser.prototype.parsePolygonText_ = function() {
if (this.match(ol.format.WKT.TokenType.LEFT_PAREN)) {
var coordinates = this.parseLineStringTextList_();
if (this.match(ol.format.WKT.TokenType.RIGHT_PAREN)) {
return coordinates;
}
} else if (this.isEmptyGeometry_()) {
return [];
}
this.raiseError_();
};
/**
* @return {!Array.<!Array.<number>>} All points in a multipoint.
* @private
*/
ol.format.WKT.Parser.prototype.parseMultiPointText_ = function() {
if (this.match(ol.format.WKT.TokenType.LEFT_PAREN)) {
var coordinates;
if (this.token_.type == ol.format.WKT.TokenType.LEFT_PAREN) {
coordinates = this.parsePointTextList_();
} else {
coordinates = this.parsePointList_();
}
if (this.match(ol.format.WKT.TokenType.RIGHT_PAREN)) {
return coordinates;
}
} else if (this.isEmptyGeometry_()) {
return [];
}
this.raiseError_();
};
/**
* @return {!Array.<!Array.<number>>} All linestring points
* in a multilinestring.
* @private
*/
ol.format.WKT.Parser.prototype.parseMultiLineStringText_ = function() {
if (this.match(ol.format.WKT.TokenType.LEFT_PAREN)) {
var coordinates = this.parseLineStringTextList_();
if (this.match(ol.format.WKT.TokenType.RIGHT_PAREN)) {
return coordinates;
}
} else if (this.isEmptyGeometry_()) {
return [];
}
this.raiseError_();
};
/**
* @return {!Array.<!Array.<number>>} All polygon points in a multipolygon.
* @private
*/
ol.format.WKT.Parser.prototype.parseMultiPolygonText_ = function() {
if (this.match(ol.format.WKT.TokenType.LEFT_PAREN)) {
var coordinates = this.parsePolygonTextList_();
if (this.match(ol.format.WKT.TokenType.RIGHT_PAREN)) {
return coordinates;
}
} else if (this.isEmptyGeometry_()) {
return [];
}
this.raiseError_();
};
/**
* @return {!Array.<number>} A point.
* @private
*/
ol.format.WKT.Parser.prototype.parsePoint_ = function() {
var coordinates = [];
for (var i = 0; i < this.dimension_; ++i) {
var token = this.token_;
if (this.match(ol.format.WKT.TokenType.NUMBER)) {
coordinates.push(token.value);
} else {
break;
}
}
if (coordinates.length == this.dimension_) {
return coordinates;
}
this.raiseError_();
};
/**
* @return {!Array.<!Array.<number>>} An array of points.
* @private
*/
ol.format.WKT.Parser.prototype.parsePointList_ = function() {
var coordinates = [this.parsePoint_()];
if (this.match(ol.format.WKT.TokenType.COMMA)) {
goog.array.extend(coordinates, this.parsePointList_());
}
return coordinates;
};
/**
* @return {!Array.<!Array.<number>>} An array of points.
* @private
*/
ol.format.WKT.Parser.prototype.parsePointTextList_ = function() {
var coordinates = [this.parsePointText_()];
if (this.match(ol.format.WKT.TokenType.COMMA)) {
goog.array.extend(coordinates, this.parsePointTextList_());
}
return coordinates;
};
/**
* @return {!Array.<!Array.<number>>} An array of points.
* @private
*/
ol.format.WKT.Parser.prototype.parseLineStringTextList_ = function() {
var coordinates = [this.parseLineStringText_()];
if (this.match(ol.format.WKT.TokenType.COMMA)) {
goog.array.extend(coordinates, this.parseLineStringTextList_());
}
return coordinates;
};
/**
* @return {!Array.<!Array.<number>>} An array of points.
* @private
*/
ol.format.WKT.Parser.prototype.parsePolygonTextList_ = function() {
var coordinates = [this.parsePolygonText_()];
if (this.match(ol.format.WKT.TokenType.COMMA)) {
goog.array.extend(coordinates, this.parsePolygonTextList_());
}
return coordinates;
};
/**
* @return {boolean} Whether the token implies an empty geometry.
* @private
*/
ol.format.WKT.Parser.prototype.isEmptyGeometry_ = function() {
var isEmpty = this.token_.type == ol.format.WKT.TokenType.TEXT &&
this.token_.value == ol.format.WKT.EMPTY;
if (isEmpty) {
this.consume_();
}
return isEmpty;
};
/**
* @private
*/
ol.format.WKT.Parser.prototype.raiseError_ = function() {
throw new Error('Unexpected `' + this.token_.value +
'` at position ' + this.token_.position +
' in `' + this.lexer_.wkt + '`');
};
/**
* @enum {function (new:ol.geom.Geometry, Array, ol.geom.GeometryLayout.<string>=)}
* @private
*/
ol.format.WKT.Parser.GeometryConstructor_ = {
'POINT': ol.geom.Point,
'LINESTRING': ol.geom.LineString,
'POLYGON': ol.geom.Polygon,
'MULTIPOINT': ol.geom.MultiPoint,
'MULTILINESTRING': ol.geom.MultiLineString,
'MULTIPOLYGON': ol.geom.MultiPolygon
};
/**
* @enum {(function(): Array)}
* @private
*/
ol.format.WKT.Parser.GeometryParser_ = {
'POINT': ol.format.WKT.Parser.prototype.parsePointText_,
'LINESTRING': ol.format.WKT.Parser.prototype.parseLineStringText_,
'POLYGON': ol.format.WKT.Parser.prototype.parsePolygonText_,
'MULTIPOINT': ol.format.WKT.Parser.prototype.parseMultiPointText_,
'MULTILINESTRING': ol.format.WKT.Parser.prototype.parseMultiLineStringText_,
'MULTIPOLYGON': ol.format.WKT.Parser.prototype.parseMultiPolygonText_
}; };

View File

@@ -0,0 +1,180 @@
goog.provide('ol.geom.flat.geodesic');
goog.require('goog.asserts');
goog.require('goog.math');
goog.require('goog.object');
goog.require('ol.TransformFunction');
goog.require('ol.math');
goog.require('ol.proj');
/**
* @private
* @param {function(number): ol.Coordinate} interpolate Interpolate function.
* @param {ol.TransformFunction} transform Transform from longitude/latitude to
* projected coordinates.
* @param {number} squaredTolerance Squared tolerance.
* @return {Array.<number>} Flat coordinates.
*/
ol.geom.flat.geodesic.line_ =
function(interpolate, transform, squaredTolerance) {
// FIXME reduce garbage generation
// FIXME optimize stack operations
/** @type {Array.<number>} */
var flatCoordinates = [];
var geoA = interpolate(0);
var geoB = interpolate(1);
var a = transform(geoA);
var b = transform(geoB);
/** @type {Array.<ol.Coordinate>} */
var geoStack = [geoB, geoA];
/** @type {Array.<ol.Coordinate>} */
var stack = [b, a];
/** @type {Array.<number>} */
var fractionStack = [1, 0];
/** @type {Object.<number, boolean>} */
var fractions = {};
var maxIterations = 1e5;
var geoM, m, fracA, fracB, fracM, key;
while (--maxIterations > 0 && fractionStack.length > 0) {
// Pop the a coordinate off the stack
fracA = fractionStack.pop();
geoA = geoStack.pop();
a = stack.pop();
// Add the a coordinate if it has not been added yet
key = fracA.toString();
if (!goog.object.containsKey(fractions, key)) {
flatCoordinates.push(a[0], a[1]);
goog.object.set(fractions, key, true);
}
// Pop the b coordinate off the stack
fracB = fractionStack.pop();
geoB = geoStack.pop();
b = stack.pop();
// Find the m point between the a and b coordinates
fracM = (fracA + fracB) / 2;
geoM = interpolate(fracM);
m = transform(geoM);
if (ol.math.squaredSegmentDistance(m[0], m[1], a[0], a[1],
b[0], b[1]) < squaredTolerance) {
// If the m point is sufficiently close to the straight line, then we
// discard it. Just use the b coordinate and move on to the next line
// segment.
flatCoordinates.push(b[0], b[1]);
key = fracB.toString();
goog.asserts.assert(!goog.object.containsKey(fractions, key));
goog.object.set(fractions, key, true);
} else {
// Otherwise, we need to subdivide the current line segment. Split it
// into two and push the two line segments onto the stack.
fractionStack.push(fracB, fracM, fracM, fracA);
stack.push(b, m, m, a);
geoStack.push(geoB, geoM, geoM, geoA);
}
}
goog.asserts.assert(maxIterations > 0);
return flatCoordinates;
};
/**
* Generate a great-circle arcs between two lat/lon points.
* @param {number} lon1 Longitude 1 in degrees.
* @param {number} lat1 Latitude 1 in degrees.
* @param {number} lon2 Longitude 2 in degrees.
* @param {number} lat2 Latitude 2 in degrees.
* @param {ol.proj.Projection} projection Projection.
* @param {number} squaredTolerance Squared tolerance.
* @return {Array.<number>} Flat coordinates.
*/
ol.geom.flat.geodesic.greatCircleArc = function(
lon1, lat1, lon2, lat2, projection, squaredTolerance) {
var geoProjection = ol.proj.get('EPSG:4326');
var cosLat1 = Math.cos(goog.math.toRadians(lat1));
var sinLat1 = Math.sin(goog.math.toRadians(lat1));
var cosLat2 = Math.cos(goog.math.toRadians(lat2));
var sinLat2 = Math.sin(goog.math.toRadians(lat2));
var cosDeltaLon = Math.cos(goog.math.toRadians(lon2 - lon1));
var sinDeltaLon = Math.sin(goog.math.toRadians(lon2 - lon1));
var d = sinLat1 * sinLat2 + cosLat1 * cosLat2 * cosDeltaLon;
return ol.geom.flat.geodesic.line_(
/**
* @param {number} frac Fraction.
* @return {ol.Coordinate} Coordinate.
*/
function(frac) {
if (1 <= d) {
return [lon2, lat2];
}
var D = frac * Math.acos(d);
var cosD = Math.cos(D);
var sinD = Math.sin(D);
var y = sinDeltaLon * cosLat2;
var x = cosLat1 * sinLat2 - sinLat1 * cosLat2 * cosDeltaLon;
var theta = Math.atan2(y, x);
var lat = Math.asin(sinLat1 * cosD + cosLat1 * sinD * Math.cos(theta));
var lon = goog.math.toRadians(lon1) +
Math.atan2(Math.sin(theta) * sinD * cosLat1,
cosD - sinLat1 * Math.sin(lat));
return [goog.math.toDegrees(lon), goog.math.toDegrees(lat)];
}, ol.proj.getTransform(geoProjection, projection), squaredTolerance);
};
/**
* Generate a meridian (line at constant longitude).
* @param {number} lon Longitude.
* @param {number} lat1 Latitude 1.
* @param {number} lat2 Latitude 2.
* @param {ol.proj.Projection} projection Projection.
* @param {number} squaredTolerance Squared tolerance.
* @return {Array.<number>} Flat coordinates.
*/
ol.geom.flat.geodesic.meridian =
function(lon, lat1, lat2, projection, squaredTolerance) {
var epsg4326Projection = ol.proj.get('EPSG:4326');
return ol.geom.flat.geodesic.line_(
/**
* @param {number} frac Fraction.
* @return {ol.Coordinate} Coordinate.
*/
function(frac) {
return [lon, lat1 + ((lat2 - lat1) * frac)];
},
ol.proj.getTransform(epsg4326Projection, projection), squaredTolerance);
};
/**
* Generate a parallel (line at constant latitude).
* @param {number} lat Latitude.
* @param {number} lon1 Longitude 1.
* @param {number} lon2 Longitude 2.
* @param {ol.proj.Projection} projection Projection.
* @param {number} squaredTolerance Squared tolerance.
* @return {Array.<number>} Flat coordinates.
*/
ol.geom.flat.geodesic.parallel =
function(lat, lon1, lon2, projection, squaredTolerance) {
var epsg4326Projection = ol.proj.get('EPSG:4326');
return ol.geom.flat.geodesic.line_(
/**
* @param {number} frac Fraction.
* @return {ol.Coordinate} Coordinate.
*/
function(frac) {
return [lon1 + ((lon2 - lon1) * frac), lat];
},
ol.proj.getTransform(epsg4326Projection, projection), squaredTolerance);
};

View File

@@ -65,7 +65,7 @@ ol.geom.Point.prototype.closestPointXY =
* @api * @api
*/ */
ol.geom.Point.prototype.getCoordinates = function() { ol.geom.Point.prototype.getCoordinates = function() {
return this.flatCoordinates.slice(); return goog.isNull(this.flatCoordinates) ? [] : this.flatCoordinates.slice();
}; };

427
src/ol/graticule.js Normal file
View File

@@ -0,0 +1,427 @@
goog.provide('ol.Graticule');
goog.require('goog.asserts');
goog.require('goog.math');
goog.require('ol.extent');
goog.require('ol.geom.LineString');
goog.require('ol.geom.flat.geodesic');
goog.require('ol.proj');
goog.require('ol.render.EventType');
goog.require('ol.style.Stroke');
/**
* @constructor
* @param {olx.GraticuleOptions=} opt_options Options.
* @api
*/
ol.Graticule = function(opt_options) {
var options = goog.isDef(opt_options) ? opt_options : {};
/**
* @type {ol.Map}
* @private
*/
this.map_ = null;
/**
* @type {ol.proj.Projection}
* @private
*/
this.projection_ = null;
/**
* @type {number}
* @private
*/
this.maxLat_ = Infinity;
/**
* @type {number}
* @private
*/
this.maxLon_ = Infinity;
/**
* @type {number}
* @private
*/
this.minLat_ = -Infinity;
/**
* @type {number}
* @private
*/
this.minLon_ = -Infinity;
/**
* @type {number}
* @private
*/
this.targetSize_ = goog.isDef(options.targetSize) ?
options.targetSize : 100;
/**
* @type {number}
* @private
*/
this.maxLines_ = goog.isDef(options.maxLines) ? options.maxLines : 100;
goog.asserts.assert(this.maxLines_ > 0);
/**
* @type {Array.<ol.geom.LineString>}
* @private
*/
this.meridians_ = [];
/**
* @type {Array.<ol.geom.LineString>}
* @private
*/
this.parallels_ = [];
/**
* TODO can be configurable
* @type {ol.style.Stroke}
* @private
*/
this.strokeStyle_ = new ol.style.Stroke({
color: 'rgba(0,0,0,0.2)'
});
/**
* @type {ol.TransformFunction|undefined}
* @private
*/
this.fromLonLatTransform_ = undefined;
/**
* @type {ol.TransformFunction|undefined}
* @private
*/
this.toLonLatTransform_ = undefined;
/**
* @type {ol.Coordinate}
* @private
*/
this.projectionCenterLonLat_ = null;
this.setMap(goog.isDef(options.map) ? options.map : null);
};
/**
* TODO can be configurable
* @type {Array.<number>}
* @private
*/
ol.Graticule.intervals_ = [90, 45, 30, 20, 10, 5, 2, 1, 0.5, 0.2, 0.1, 0.05,
0.01, 0.005, 0.002, 0.001];
/**
* @param {number} lon Longitude.
* @param {number} squaredTolerance Squared tolerance.
* @param {ol.Extent} extent Extent.
* @param {number} index Index.
* @return {number} Index.
* @private
*/
ol.Graticule.prototype.addMeridian_ =
function(lon, squaredTolerance, extent, index) {
var lineString = this.getMeridian_(lon, squaredTolerance, index);
if (ol.extent.intersects(lineString.getExtent(), extent)) {
this.meridians_[index++] = lineString;
}
return index;
};
/**
* @param {number} lat Latitude.
* @param {number} squaredTolerance Squared tolerance.
* @param {ol.Extent} extent Extent.
* @param {number} index Index.
* @return {number} Index.
* @private
*/
ol.Graticule.prototype.addParallel_ =
function(lat, squaredTolerance, extent, index) {
var lineString = this.getParallel_(lat, squaredTolerance, index);
if (ol.extent.intersects(lineString.getExtent(), extent)) {
this.parallels_[index++] = lineString;
}
return index;
};
/**
* @param {ol.Extent} extent Extent.
* @param {ol.Coordinate} center Center.
* @param {number} resolution Resolution.
* @param {number} squaredTolerance Squared tolerance.
* @private
*/
ol.Graticule.prototype.createGraticule_ =
function(extent, center, resolution, squaredTolerance) {
var interval = this.getInterval_(resolution);
if (interval == -1) {
this.meridians_.length = this.parallels_.length = 0;
return;
}
var centerLonLat = this.toLonLatTransform_(center);
var centerLon = centerLonLat[0];
var centerLat = centerLonLat[1];
var maxLines = this.maxLines_;
var cnt, idx, lat, lon;
// Create meridians
centerLon = Math.floor(centerLon / interval) * interval;
lon = goog.math.clamp(centerLon, this.minLon_, this.maxLon_);
idx = this.addMeridian_(lon, squaredTolerance, extent, 0);
cnt = 0;
while (lon != this.minLon_ && cnt++ < maxLines) {
lon = Math.max(lon - interval, this.minLon_);
idx = this.addMeridian_(lon, squaredTolerance, extent, idx);
}
lon = goog.math.clamp(centerLon, this.minLon_, this.maxLon_);
cnt = 0;
while (lon != this.maxLon_ && cnt++ < maxLines) {
lon = Math.min(lon + interval, this.maxLon_);
idx = this.addMeridian_(lon, squaredTolerance, extent, idx);
}
this.meridians_.length = idx;
// Create parallels
centerLat = Math.floor(centerLat / interval) * interval;
lat = goog.math.clamp(centerLat, this.minLat_, this.maxLat_);
idx = this.addParallel_(lat, squaredTolerance, extent, 0);
cnt = 0;
while (lat != this.minLat_ && cnt++ < maxLines) {
lat = Math.max(lat - interval, this.minLat_);
idx = this.addParallel_(lat, squaredTolerance, extent, idx);
}
lat = goog.math.clamp(centerLat, this.minLat_, this.maxLat_);
cnt = 0;
while (lat != this.maxLat_ && cnt++ < maxLines) {
lat = Math.min(lat + interval, this.maxLat_);
idx = this.addParallel_(lat, squaredTolerance, extent, idx);
}
this.parallels_.length = idx;
};
/**
* @param {number} resolution Resolution.
* @return {number} The interval in degrees.
* @private
*/
ol.Graticule.prototype.getInterval_ = function(resolution) {
var centerLon = this.projectionCenterLonLat_[0];
var centerLat = this.projectionCenterLonLat_[1];
var interval = -1;
var i, ii, delta, dist;
var target = Math.pow(this.targetSize_ * resolution, 2);
/** @type {Array.<number>} **/
var p1 = [];
/** @type {Array.<number>} **/
var p2 = [];
for (i = 0, ii = ol.Graticule.intervals_.length; i < ii; ++i) {
delta = ol.Graticule.intervals_[i] / 2;
p1[0] = centerLon - delta;
p1[1] = centerLat - delta;
p2[0] = centerLon + delta;
p2[1] = centerLat + delta;
this.fromLonLatTransform_(p1, p1);
this.fromLonLatTransform_(p2, p2);
dist = Math.pow(p2[0] - p1[0], 2) + Math.pow(p2[1] - p1[1], 2);
if (dist <= target) {
break;
}
interval = ol.Graticule.intervals_[i];
}
return interval;
};
/**
* @return {ol.Map} The map.
* @api
*/
ol.Graticule.prototype.getMap = function() {
return this.map_;
};
/**
* @param {number} lon Longitude.
* @param {number} squaredTolerance Squared tolerance.
* @return {ol.geom.LineString} The meridian line string.
* @param {number} index Index.
* @private
*/
ol.Graticule.prototype.getMeridian_ = function(lon, squaredTolerance, index) {
goog.asserts.assert(lon >= this.minLon_);
goog.asserts.assert(lon <= this.maxLon_);
var flatCoordinates = ol.geom.flat.geodesic.meridian(lon,
this.minLat_, this.maxLat_, this.projection_, squaredTolerance);
goog.asserts.assert(flatCoordinates.length > 0);
var lineString = goog.isDef(this.meridians_[index]) ?
this.meridians_[index] : new ol.geom.LineString(null);
lineString.setFlatCoordinates(ol.geom.GeometryLayout.XY, flatCoordinates);
return lineString;
};
/**
* @return {Array.<ol.geom.LineString>} The meridians.
* @api
*/
ol.Graticule.prototype.getMeridians = function() {
return this.meridians_;
};
/**
* @param {number} lat Latitude.
* @param {number} squaredTolerance Squared tolerance.
* @return {ol.geom.LineString} The parallel line string.
* @param {number} index Index.
* @private
*/
ol.Graticule.prototype.getParallel_ = function(lat, squaredTolerance, index) {
goog.asserts.assert(lat >= this.minLat_);
goog.asserts.assert(lat <= this.maxLat_);
var flatCoordinates = ol.geom.flat.geodesic.parallel(lat,
this.minLon_, this.maxLon_, this.projection_, squaredTolerance);
goog.asserts.assert(flatCoordinates.length > 0);
var lineString = goog.isDef(this.parallels_[index]) ?
this.parallels_[index] : new ol.geom.LineString(null);
lineString.setFlatCoordinates(ol.geom.GeometryLayout.XY, flatCoordinates);
return lineString;
};
/**
* @return {Array.<ol.geom.LineString>} The parallels.
* @api
*/
ol.Graticule.prototype.getParallels = function() {
return this.parallels_;
};
/**
* @param {ol.render.Event} e Event.
* @private
*/
ol.Graticule.prototype.handlePostCompose_ = function(e) {
var vectorContext = e.vectorContext;
var frameState = e.frameState;
var extent = frameState.extent;
var viewState = frameState.viewState;
var center = viewState.center;
var projection = viewState.projection;
var resolution = viewState.resolution;
var pixelRatio = frameState.pixelRatio;
var squaredTolerance =
resolution * resolution / (4 * pixelRatio * pixelRatio);
var updateProjectionInfo = goog.isNull(this.projection_) ||
!ol.proj.equivalent(this.projection_, projection);
if (updateProjectionInfo) {
this.updateProjectionInfo_(projection);
}
this.createGraticule_(extent, center, resolution, squaredTolerance);
// Draw the lines
vectorContext.setFillStrokeStyle(null, this.strokeStyle_);
var i, l, line;
for (i = 0, l = this.meridians_.length; i < l; ++i) {
line = this.meridians_[i];
vectorContext.drawLineStringGeometry(line, null);
}
for (i = 0, l = this.parallels_.length; i < l; ++i) {
line = this.parallels_[i];
vectorContext.drawLineStringGeometry(line, null);
}
};
/**
* @param {ol.proj.Projection} projection Projection.
* @private
*/
ol.Graticule.prototype.updateProjectionInfo_ = function(projection) {
goog.asserts.assert(!goog.isNull(projection));
var extent = projection.getExtent();
var worldExtent = projection.getWorldExtent();
var maxLat = worldExtent[3];
var maxLon = worldExtent[2];
var minLat = worldExtent[1];
var minLon = worldExtent[0];
goog.asserts.assert(!goog.isNull(extent));
goog.asserts.assert(goog.isDef(maxLat));
goog.asserts.assert(goog.isDef(maxLon));
goog.asserts.assert(goog.isDef(minLat));
goog.asserts.assert(goog.isDef(minLon));
this.maxLat_ = maxLat;
this.maxLon_ = maxLon;
this.minLat_ = minLat;
this.minLon_ = minLon;
var epsg4326Projection = ol.proj.get('EPSG:4326');
this.fromLonLatTransform_ = ol.proj.getTransform(
epsg4326Projection, projection);
this.toLonLatTransform_ = ol.proj.getTransform(
projection, epsg4326Projection);
this.projectionCenterLonLat_ = this.toLonLatTransform_(
ol.extent.getCenter(extent));
this.projection_ = projection;
};
/**
* @param {ol.Map} map Map.
* @api
*/
ol.Graticule.prototype.setMap = function(map) {
if (!goog.isNull(this.map_)) {
this.map_.un(ol.render.EventType.POSTCOMPOSE,
this.handlePostCompose_, this);
this.map_.render();
}
if (!goog.isNull(map)) {
map.on(ol.render.EventType.POSTCOMPOSE,
this.handlePostCompose_, this);
map.render();
}
this.map_ = map;
};

View File

@@ -152,8 +152,7 @@ ol.interaction.DragBox.prototype.onBoxEnd = goog.nullFunction;
/** /**
* @inheritDoc * @inheritDoc
*/ */
ol.interaction.DragBox.prototype.handlePointerUp = ol.interaction.DragBox.prototype.handlePointerUp = function(mapBrowserEvent) {
function(mapBrowserEvent) {
if (!ol.events.condition.mouseOnly(mapBrowserEvent)) { if (!ol.events.condition.mouseOnly(mapBrowserEvent)) {
return true; return true;
} }
@@ -176,8 +175,7 @@ ol.interaction.DragBox.prototype.handlePointerUp =
/** /**
* @inheritDoc * @inheritDoc
*/ */
ol.interaction.DragBox.prototype.handlePointerDown = ol.interaction.DragBox.prototype.handlePointerDown = function(mapBrowserEvent) {
function(mapBrowserEvent) {
if (!ol.events.condition.mouseOnly(mapBrowserEvent)) { if (!ol.events.condition.mouseOnly(mapBrowserEvent)) {
return false; return false;
} }

View File

@@ -67,10 +67,10 @@ ol.interaction.DragPan.prototype.handlePointerDrag = function(mapBrowserEvent) {
goog.asserts.assert(this.targetPointers.length >= 1); goog.asserts.assert(this.targetPointers.length >= 1);
var centroid = var centroid =
ol.interaction.Pointer.centroid(this.targetPointers); ol.interaction.Pointer.centroid(this.targetPointers);
if (this.kinetic_) {
this.kinetic_.update(centroid[0], centroid[1]);
}
if (!goog.isNull(this.lastCentroid)) { if (!goog.isNull(this.lastCentroid)) {
if (this.kinetic_) {
this.kinetic_.update(centroid[0], centroid[1]);
}
var deltaX = this.lastCentroid[0] - centroid[0]; var deltaX = this.lastCentroid[0] - centroid[0];
var deltaY = centroid[1] - this.lastCentroid[1]; var deltaY = centroid[1] - this.lastCentroid[1];
var map = mapBrowserEvent.map; var map = mapBrowserEvent.map;
@@ -91,8 +91,7 @@ ol.interaction.DragPan.prototype.handlePointerDrag = function(mapBrowserEvent) {
/** /**
* @inheritDoc * @inheritDoc
*/ */
ol.interaction.DragPan.prototype.handlePointerUp = ol.interaction.DragPan.prototype.handlePointerUp = function(mapBrowserEvent) {
function(mapBrowserEvent) {
var map = mapBrowserEvent.map; var map = mapBrowserEvent.map;
var view = map.getView(); var view = map.getView();
if (this.targetPointers.length === 0) { if (this.targetPointers.length === 0) {
@@ -124,8 +123,7 @@ ol.interaction.DragPan.prototype.handlePointerUp =
/** /**
* @inheritDoc * @inheritDoc
*/ */
ol.interaction.DragPan.prototype.handlePointerDown = ol.interaction.DragPan.prototype.handlePointerDown = function(mapBrowserEvent) {
function(mapBrowserEvent) {
if (this.targetPointers.length > 0 && this.condition_(mapBrowserEvent)) { if (this.targetPointers.length > 0 && this.condition_(mapBrowserEvent)) {
var map = mapBrowserEvent.map; var map = mapBrowserEvent.map;
var view = map.getView(); var view = map.getView();

View File

@@ -205,7 +205,7 @@ goog.inherits(ol.interaction.Draw, ol.interaction.Pointer);
/** /**
* @return {ol.feature.StyleFunction} Styles. * @return {ol.style.StyleFunction} Styles.
*/ */
ol.interaction.Draw.getDefaultStyleFunction = function() { ol.interaction.Draw.getDefaultStyleFunction = function() {
var styles = ol.feature.createDefaultEditingStyles(); var styles = ol.feature.createDefaultEditingStyles();

View File

@@ -74,8 +74,7 @@ ol.interaction.Interaction.prototype.setMap = function(map) {
* @param {ol.Coordinate} delta Delta. * @param {ol.Coordinate} delta Delta.
* @param {number=} opt_duration Duration. * @param {number=} opt_duration Duration.
*/ */
ol.interaction.Interaction.pan = function( ol.interaction.Interaction.pan = function(map, view, delta, opt_duration) {
map, view, delta, opt_duration) {
var currentCenter = view.getCenter(); var currentCenter = view.getCenter();
if (goog.isDef(currentCenter)) { if (goog.isDef(currentCenter)) {
if (goog.isDef(opt_duration) && opt_duration > 0) { if (goog.isDef(opt_duration) && opt_duration > 0) {

View File

@@ -14,7 +14,6 @@ goog.require('ol.interaction.PinchZoom');
/** /**
* @classdesc
* Set of interactions included in maps by default. Specific interactions can be * Set of interactions included in maps by default. Specific interactions can be
* excluded by setting the appropriate option to false in the constructor * excluded by setting the appropriate option to false in the constructor
* options, but the order of the interactions is fixed. If you want to specify * options, but the order of the interactions is fixed. If you want to specify

View File

@@ -769,7 +769,7 @@ ol.interaction.Modify.prototype.updateSegmentIndices_ = function(
/** /**
* @return {ol.feature.StyleFunction} Styles. * @return {ol.style.StyleFunction} Styles.
*/ */
ol.interaction.Modify.getDefaultStyleFunction = function() { ol.interaction.Modify.getDefaultStyleFunction = function() {
var style = ol.feature.createDefaultEditingStyles(); var style = ol.feature.createDefaultEditingStyles();

View File

@@ -204,7 +204,7 @@ ol.interaction.Select.prototype.setMap = function(map) {
/** /**
* @return {ol.feature.StyleFunction} Styles. * @return {ol.style.StyleFunction} Styles.
*/ */
ol.interaction.Select.getDefaultStyleFunction = function() { ol.interaction.Select.getDefaultStyleFunction = function() {
var styles = ol.feature.createDefaultEditingStyles(); var styles = ol.feature.createDefaultEditingStyles();

View File

@@ -81,25 +81,30 @@ ol.Kinetic.prototype.update = function(x, y) {
* @return {boolean} Whether we should do kinetic animation. * @return {boolean} Whether we should do kinetic animation.
*/ */
ol.Kinetic.prototype.end = function() { ol.Kinetic.prototype.end = function() {
if (this.points_.length < 6) {
// at least 2 points are required (i.e. there must be at least 6 elements
// in the array)
return false;
}
var delay = goog.now() - this.delay_; var delay = goog.now() - this.delay_;
var lastIndex = this.points_.length - 3; var lastIndex = this.points_.length - 3;
if (this.points_[lastIndex + 2] < delay) { if (this.points_[lastIndex + 2] < delay) {
// the user stopped panning before releasing the map // the last tracked point is too old, which means that the user stopped
// panning before releasing the map
return false; return false;
} }
// get the first point which still falls into the delay time
var firstIndex = lastIndex - 3; var firstIndex = lastIndex - 3;
while (firstIndex >= 0 && this.points_[firstIndex + 2] > delay) { while (firstIndex > 0 && this.points_[firstIndex + 2] > delay) {
firstIndex -= 3; firstIndex -= 3;
} }
if (firstIndex >= 0) { var duration = this.points_[lastIndex + 2] - this.points_[firstIndex + 2];
var duration = this.points_[lastIndex + 2] - this.points_[firstIndex + 2]; var dx = this.points_[lastIndex] - this.points_[firstIndex];
var dx = this.points_[lastIndex] - this.points_[firstIndex]; var dy = this.points_[lastIndex + 1] - this.points_[firstIndex + 1];
var dy = this.points_[lastIndex + 1] - this.points_[firstIndex + 1]; this.angle_ = Math.atan2(dy, dx);
this.angle_ = Math.atan2(dy, dx); this.initialVelocity_ = Math.sqrt(dx * dx + dy * dy) / duration;
this.initialVelocity_ = Math.sqrt(dx * dx + dy * dy) / duration; return this.initialVelocity_ > this.minVelocity_;
return this.initialVelocity_ > this.minVelocity_;
}
return false;
}; };

View File

@@ -157,6 +157,8 @@ ol.layer.Heatmap.createCircle_ = function(radius, blur, shadow) {
/** /**
* @return {Array.<string>} Colors. * @return {Array.<string>} Colors.
* @api
* @observable
*/ */
ol.layer.Heatmap.prototype.getGradient = function() { ol.layer.Heatmap.prototype.getGradient = function() {
return /** @type {Array.<string>} */ ( return /** @type {Array.<string>} */ (
@@ -201,6 +203,8 @@ ol.layer.Heatmap.prototype.handleRender_ = function(event) {
/** /**
* @param {Array.<string>} colors Gradient. * @param {Array.<string>} colors Gradient.
* @api
* @observable
*/ */
ol.layer.Heatmap.prototype.setGradient = function(colors) { ol.layer.Heatmap.prototype.setGradient = function(colors) {
this.set(ol.layer.HeatmapLayerProperty.GRADIENT, colors); this.set(ol.layer.HeatmapLayerProperty.GRADIENT, colors);

View File

@@ -19,6 +19,7 @@ ol.layer.LayerProperty = {
OPACITY: 'opacity', OPACITY: 'opacity',
SATURATION: 'saturation', SATURATION: 'saturation',
VISIBLE: 'visible', VISIBLE: 'visible',
EXTENT: 'extent',
MAX_RESOLUTION: 'maxResolution', MAX_RESOLUTION: 'maxResolution',
MIN_RESOLUTION: 'minResolution' MIN_RESOLUTION: 'minResolution'
}; };
@@ -33,6 +34,7 @@ ol.layer.LayerProperty = {
* saturation: number, * saturation: number,
* sourceState: ol.source.State, * sourceState: ol.source.State,
* visible: boolean, * visible: boolean,
* extent: (ol.Extent|undefined),
* maxResolution: number, * maxResolution: number,
* minResolution: number}} * minResolution: number}}
*/ */
@@ -141,6 +143,7 @@ ol.layer.Base.prototype.getLayerState = function() {
var saturation = this.getSaturation(); var saturation = this.getSaturation();
var sourceState = this.getSourceState(); var sourceState = this.getSourceState();
var visible = this.getVisible(); var visible = this.getVisible();
var extent = this.getExtent();
var maxResolution = this.getMaxResolution(); var maxResolution = this.getMaxResolution();
var minResolution = this.getMinResolution(); var minResolution = this.getMinResolution();
return { return {
@@ -152,6 +155,7 @@ ol.layer.Base.prototype.getLayerState = function() {
saturation: goog.isDef(saturation) ? Math.max(saturation, 0) : 1, saturation: goog.isDef(saturation) ? Math.max(saturation, 0) : 1,
sourceState: sourceState, sourceState: sourceState,
visible: goog.isDef(visible) ? !!visible : true, visible: goog.isDef(visible) ? !!visible : true,
extent: extent,
maxResolution: goog.isDef(maxResolution) ? maxResolution : Infinity, maxResolution: goog.isDef(maxResolution) ? maxResolution : Infinity,
minResolution: goog.isDef(minResolution) ? Math.max(minResolution, 0) : 0 minResolution: goog.isDef(minResolution) ? Math.max(minResolution, 0) : 0
}; };
@@ -174,6 +178,21 @@ ol.layer.Base.prototype.getLayersArray = goog.abstractMethod;
ol.layer.Base.prototype.getLayerStatesArray = goog.abstractMethod; ol.layer.Base.prototype.getLayerStatesArray = goog.abstractMethod;
/**
* @return {ol.Extent|undefined} The layer extent.
* @observable
* @api
*/
ol.layer.Base.prototype.getExtent = function() {
return /** @type {ol.Extent|undefined} */ (
this.get(ol.layer.LayerProperty.EXTENT));
};
goog.exportProperty(
ol.layer.Base.prototype,
'getExtent',
ol.layer.Base.prototype.getExtent);
/** /**
* @return {number|undefined} The maximum resolution of the layer. * @return {number|undefined} The maximum resolution of the layer.
* @observable * @observable
@@ -320,6 +339,22 @@ goog.exportProperty(
ol.layer.Base.prototype.setHue); ol.layer.Base.prototype.setHue);
/**
* Set the extent at which the layer is visible. If `undefined`, the layer
* will be visible at all extents.
* @param {ol.Extent|undefined} extent The extent of the layer.
* @observable
* @api
*/
ol.layer.Base.prototype.setExtent = function(extent) {
this.set(ol.layer.LayerProperty.EXTENT, extent);
};
goog.exportProperty(
ol.layer.Base.prototype,
'setExtent',
ol.layer.Base.prototype.setExtent);
/** /**
* @param {number|undefined} maxResolution The maximum resolution of the layer. * @param {number|undefined} maxResolution The maximum resolution of the layer.
* @observable * @observable

View File

@@ -11,6 +11,7 @@ goog.require('ol.CollectionEvent');
goog.require('ol.CollectionEventType'); goog.require('ol.CollectionEventType');
goog.require('ol.Object'); goog.require('ol.Object');
goog.require('ol.ObjectEventType'); goog.require('ol.ObjectEventType');
goog.require('ol.extent');
goog.require('ol.layer.Base'); goog.require('ol.layer.Base');
goog.require('ol.source.State'); goog.require('ol.source.State');
@@ -30,8 +31,7 @@ ol.layer.GroupProperty = {
* *
* @constructor * @constructor
* @extends {ol.layer.Base} * @extends {ol.layer.Base}
* @fires change Triggered when the state of the source of any of the layers of * @fires change Triggered when the group/Collection changes.
* this group changes
* @param {olx.layer.GroupOptions=} opt_options Layer options. * @param {olx.layer.GroupOptions=} opt_options Layer options.
* @api * @api
*/ */
@@ -212,6 +212,10 @@ ol.layer.Group.prototype.getLayerStatesArray = function(opt_states) {
layerState.maxResolution, ownLayerState.maxResolution); layerState.maxResolution, ownLayerState.maxResolution);
layerState.minResolution = Math.max( layerState.minResolution = Math.max(
layerState.minResolution, ownLayerState.minResolution); layerState.minResolution, ownLayerState.minResolution);
if (goog.isDef(ownLayerState.extent) && goog.isDef(layerState.extent)) {
layerState.extent = ol.extent.getIntersection(
layerState.extent, ownLayerState.extent);
}
} }
return states; return states;

View File

@@ -1,8 +1,8 @@
goog.provide('ol.layer.Vector'); goog.provide('ol.layer.Vector');
goog.require('goog.object'); goog.require('goog.object');
goog.require('ol.feature');
goog.require('ol.layer.Layer'); goog.require('ol.layer.Layer');
goog.require('ol.style.Style');
/** /**
@@ -39,21 +39,20 @@ ol.layer.Vector = function(opt_options) {
/** /**
* User provided style. * User provided style.
* @type {ol.style.Style|Array.<ol.style.Style>|ol.feature.StyleFunction} * @type {ol.style.Style|Array.<ol.style.Style>|ol.style.StyleFunction}
* @private * @private
*/ */
this.style_ = null; this.style_ = null;
/** /**
* Style function for use within the library. * Style function for use within the library.
* @type {ol.feature.StyleFunction|undefined} * @type {ol.style.StyleFunction|undefined}
* @private * @private
*/ */
this.styleFunction_ = undefined; this.styleFunction_ = undefined;
if (goog.isDef(options.style)) { this.setStyle(goog.isDefAndNotNull(options.style) ?
this.setStyle(options.style); options.style : ol.style.defaultStyleFunction);
}
}; };
goog.inherits(ol.layer.Vector, ol.layer.Layer); goog.inherits(ol.layer.Vector, ol.layer.Layer);
@@ -72,7 +71,7 @@ ol.layer.Vector.prototype.getRenderOrder = function() {
/** /**
* Get the style for features. This returns whatever was passed to the `style` * Get the style for features. This returns whatever was passed to the `style`
* option at construction or to the `setStyle` method. * option at construction or to the `setStyle` method.
* @return {ol.style.Style|Array.<ol.style.Style>|ol.feature.StyleFunction} * @return {ol.style.Style|Array.<ol.style.Style>|ol.style.StyleFunction}
* Layer style. * Layer style.
* @api * @api
*/ */
@@ -83,7 +82,7 @@ ol.layer.Vector.prototype.getStyle = function() {
/** /**
* Get the style function. * Get the style function.
* @return {ol.feature.StyleFunction|undefined} Layer style function. * @return {ol.style.StyleFunction|undefined} Layer style function.
* @api * @api
*/ */
ol.layer.Vector.prototype.getStyleFunction = function() { ol.layer.Vector.prototype.getStyleFunction = function() {
@@ -104,12 +103,12 @@ ol.layer.Vector.prototype.setRenderOrder = function(renderOrder) {
* Set the style for features. This can be a single style object, an array * Set the style for features. This can be a single style object, an array
* of styles, or a function that takes a feature and resolution and returns * of styles, or a function that takes a feature and resolution and returns
* an array of styles. * an array of styles.
* @param {ol.style.Style|Array.<ol.style.Style>|ol.feature.StyleFunction} style * @param {ol.style.Style|Array.<ol.style.Style>|ol.style.StyleFunction} style
* Layer style. * Layer style.
* @api * @api
*/ */
ol.layer.Vector.prototype.setStyle = function(style) { ol.layer.Vector.prototype.setStyle = function(style) {
this.style_ = style; this.style_ = style;
this.styleFunction_ = ol.feature.createStyleFunction(style); this.styleFunction_ = ol.style.createStyleFunction(style);
this.dispatchChangeEvent(); this.dispatchChangeEvent();
}; };

View File

@@ -139,6 +139,15 @@ ol.MapProperty = {
* The above snippet creates a map with a MapQuest OSM layer on a 2D view and * The above snippet creates a map with a MapQuest OSM layer on a 2D view and
* renders it to a DOM element with the id `map`. * renders it to a DOM element with the id `map`.
* *
* The constructor places a viewport container (with CSS class name
* `ol-viewport`) in the target element (see `getViewport()`), and then two
* further elements within the viewport: one with CSS class name
* `ol-overlaycontainer-stopevent` for controls and some overlays, and one with
* CSS class name `ol-overlaycontainer` for other overlays (see the `stopEvent`
* option of {@link ol.Overlay} for the difference). The map itself is placed in
* a further element within the viewport, either DOM or Canvas, depending on the
* renderer.
*
* @constructor * @constructor
* @extends {ol.Object} * @extends {ol.Object}
* @param {olx.MapOptions} options Map options. * @param {olx.MapOptions} options Map options.
@@ -163,9 +172,9 @@ ol.Map = function(options) {
/** /**
* @private * @private
* @type {boolean} * @type {Object}
*/ */
this.ol3Logo_ = optionsInternal.ol3Logo; this.logos_ = optionsInternal.logos;
/** /**
* @private * @private
@@ -680,8 +689,7 @@ ol.Map.prototype.getInteractions = function() {
* @api stable * @api stable
*/ */
ol.Map.prototype.getLayerGroup = function() { ol.Map.prototype.getLayerGroup = function() {
return /** @type {ol.layer.Group} */ ( return /** @type {ol.layer.Group} */ (this.get(ol.MapProperty.LAYERGROUP));
this.get(ol.MapProperty.LAYERGROUP));
}; };
goog.exportProperty( goog.exportProperty(
ol.Map.prototype, ol.Map.prototype,
@@ -1094,8 +1102,8 @@ ol.Map.prototype.render = function() {
/** /**
* Remove the given control from the map. * Remove the given control from the map.
* @param {ol.control.Control} control Control. * @param {ol.control.Control} control Control.
* @return {ol.control.Control|undefined} The removed control of undefined * @return {ol.control.Control|undefined} The removed control (or undefined
* if the control was not found. * if the control was not found).
* @api stable * @api stable
*/ */
ol.Map.prototype.removeControl = function(control) { ol.Map.prototype.removeControl = function(control) {
@@ -1129,8 +1137,8 @@ ol.Map.prototype.removeInteraction = function(interaction) {
/** /**
* Removes the given layer from the map. * Removes the given layer from the map.
* @param {ol.layer.Base} layer Layer. * @param {ol.layer.Base} layer Layer.
* @return {ol.layer.Base|undefined} The removed layer or undefined if the * @return {ol.layer.Base|undefined} The removed layer (or undefined if the
* layer was not found. * layer was not found).
* @api stable * @api stable
*/ */
ol.Map.prototype.removeLayer = function(layer) { ol.Map.prototype.removeLayer = function(layer) {
@@ -1143,8 +1151,8 @@ ol.Map.prototype.removeLayer = function(layer) {
/** /**
* Remove the given overlay from the map. * Remove the given overlay from the map.
* @param {ol.Overlay} overlay Overlay. * @param {ol.Overlay} overlay Overlay.
* @return {ol.Overlay|undefined} The removed overlay of undefined * @return {ol.Overlay|undefined} The removed overlay (or undefined
* if the overlay was not found. * if the overlay was not found).
* @api stable * @api stable
*/ */
ol.Map.prototype.removeOverlay = function(overlay) { ol.Map.prototype.removeOverlay = function(overlay) {
@@ -1201,7 +1209,7 @@ ol.Map.prototype.renderFrame_ = function(time) {
index: this.frameIndex_++, index: this.frameIndex_++,
layerStates: layerStates, layerStates: layerStates,
layerStatesArray: layerStatesArray, layerStatesArray: layerStatesArray,
logos: {}, logos: this.logos_,
pixelRatio: this.pixelRatio_, pixelRatio: this.pixelRatio_,
pixelToCoordinateMatrix: this.pixelToCoordinateMatrix_, pixelToCoordinateMatrix: this.pixelToCoordinateMatrix_,
postRenderFunctions: [], postRenderFunctions: [],
@@ -1214,9 +1222,6 @@ ol.Map.prototype.renderFrame_ = function(time) {
viewHints: viewHints, viewHints: viewHints,
wantedTiles: {} wantedTiles: {}
}); });
if (this.ol3Logo_) {
frameState.logos[ol.OL3_LOGO_URL] = ol.OL3_URL;
}
} }
var preRenderFunctions = this.preRenderFunctions_; var preRenderFunctions = this.preRenderFunctions_;
@@ -1348,8 +1353,7 @@ ol.Map.prototype.updateSize = function() {
/** /**
* @type {Element} * @type {Element}
*/ */
var targetElement = goog.isDef(target) ? var targetElement = goog.isDef(target) ? goog.dom.getElement(target) : null;
goog.dom.getElement(target) : null;
if (goog.isNull(targetElement)) { if (goog.isNull(targetElement)) {
this.setSize(undefined); this.setSize(undefined);
@@ -1375,7 +1379,7 @@ ol.Map.prototype.unskipFeature = function(feature) {
* deviceOptions: olx.DeviceOptions, * deviceOptions: olx.DeviceOptions,
* interactions: ol.Collection, * interactions: ol.Collection,
* keyboardEventTarget: (Element|Document), * keyboardEventTarget: (Element|Document),
* ol3Logo: boolean, * logos: Object,
* overlays: ol.Collection, * overlays: ol.Collection,
* rendererConstructor: * rendererConstructor:
* function(new: ol.renderer.Map, Element, ol.Map), * function(new: ol.renderer.Map, Element, ol.Map),
@@ -1407,7 +1411,20 @@ ol.Map.createOptionsInternal = function(options) {
*/ */
var values = {}; var values = {};
var ol3Logo = goog.isDef(options.ol3Logo) ? options.ol3Logo : true; var logos = {};
if (!goog.isDef(options.logo) ||
(goog.isBoolean(options.logo) && options.logo)) {
logos[ol.OL3_LOGO_URL] = ol.OL3_URL;
} else {
var logo = options.logo;
if (goog.isString(logo)) {
logos[logo] = '';
} else if (goog.isObject(logo)) {
goog.asserts.assertString(logo.href);
goog.asserts.assertString(logo.src);
logos[logo.src] = logo.href;
}
}
var layerGroup = (options.layers instanceof ol.layer.Group) ? var layerGroup = (options.layers instanceof ol.layer.Group) ?
options.layers : new ol.layer.Group({layers: options.layers}); options.layers : new ol.layer.Group({layers: options.layers});
@@ -1505,7 +1522,7 @@ ol.Map.createOptionsInternal = function(options) {
deviceOptions: deviceOptions, deviceOptions: deviceOptions,
interactions: interactions, interactions: interactions,
keyboardEventTarget: keyboardEventTarget, keyboardEventTarget: keyboardEventTarget,
ol3Logo: ol3Logo, logos: logos,
overlays: overlays, overlays: overlays,
rendererConstructor: rendererConstructor, rendererConstructor: rendererConstructor,
values: values values: values

View File

@@ -45,18 +45,18 @@ ol.MapBrowserEvent = function(type, map, browserEvent, opt_frameState) {
*/ */
this.originalEvent = browserEvent.getBrowserEvent(); this.originalEvent = browserEvent.getBrowserEvent();
/**
* @type {ol.Coordinate}
* @api
*/
this.coordinate = map.getEventCoordinate(this.originalEvent);
/** /**
* @type {ol.Pixel} * @type {ol.Pixel}
* @api * @api
*/ */
this.pixel = map.getEventPixel(this.originalEvent); this.pixel = map.getEventPixel(this.originalEvent);
/**
* @type {ol.Coordinate}
* @api
*/
this.coordinate = map.getCoordinateFromPixel(this.pixel);
}; };
goog.inherits(ol.MapBrowserEvent, ol.MapEvent); goog.inherits(ol.MapBrowserEvent, ol.MapEvent);

View File

@@ -119,19 +119,47 @@ ol.ObjectAccessor.prototype.transform = function(from, to) {
* @classdesc * @classdesc
* Abstract base class; normally only used for creating subclasses and not * Abstract base class; normally only used for creating subclasses and not
* instantiated in apps. * instantiated in apps.
* All non-trivial classes inherit from this. * Most non-trivial classes inherit from this.
* *
* It provides standardised get/set methods, and implements a form of * This extends {@link ol.Observable} with observable properties, where each
* Key Value Observing. Setting a value triggers a change event, and 2 objects * property is observable as well as the object as a whole.
* can be bound together such that a change in one will automatically be
* reflected in the other.
* *
* See {@link ol.dom.Input} for specific case of binding an object with an * Classes that inherit from this have pre-defined properties, to which you can
* HTML element. * add your own. The pre-defined properties are listed in this documentation as
* 'Observable Properties', and have their own accessors; for example,
* {@link ol.Map} has a `target` property, accessed with `getTarget()` and
* changed with `setTarget()`. Not all properties are however settable. There
* are also general-purpose accessors `get()` and `set()`. For example,
* `get('target')` is equivalent to `getTarget()`.
*
* The `set` accessors trigger a change event, and you can monitor this by
* registering a listener. For example, {@link ol.View} has a `center`
* property, so `view.on('change:center', function(evt) {...});` would call the
* function whenever the value of the center property changes. Within the
* function, `evt.target` would be the view, so `evt.target.getCenter()` would
* return the new center.
*
* You can add your own observable properties with `set('myProp', 'new value')`,
* and retrieve that with `get('myProp')`. A change listener can then be
* registered with `on('change:myProp', ...)`. And a change can be triggered
* with `dispatchEvent('change:myProp')`. You can get a list of all properties
* with `getProperties()`.
*
* Note that the observable properties are separate from standard JS properties.
* You can, for example, give your map object a title with
* `map.title='New title'` and with `map.set('title', 'Another title')`. The
* first will be a `hasOwnProperty`; the second will appear in
* `getProperties()`. Only the second is observable.
*
* The observable properties also implement a form of Key Value Observing.
* Two objects can be bound together such that a change in one will
* automatically be reflected in the other. See `bindTo` method for more
* details, and see {@link ol.dom.Input} for the specific case of binding an
* object with an HTML element.
* *
* @constructor * @constructor
* @extends {ol.Observable} * @extends {ol.Observable}
* @param {Object.<string, *>=} opt_values Values. * @param {Object.<string, *>=} opt_values An object with key-value pairs.
* @fires ol.ObjectEvent * @fires ol.ObjectEvent
* @api * @api
*/ */

View File

@@ -208,14 +208,34 @@ ol.ZOOMSLIDER_ANIMATION_DURATION = 200;
/** /**
* ol.inherits is an alias to the goog.inherits function. It is exported * Inherit the prototype methods from one constructor into another.
* for use in non-compiled application code.
* *
* FIXME: We use a new line to fake the linter. Without the new line the * Usage:
* linter complains with:
* *
* "Missing newline between constructor and goog.inherits" * function ParentClass(a, b) { }
* ParentClass.prototype.foo = function(a) { }
*
* function ChildClass(a, b, c) {
* goog.base(this, a, b);
* }
* ol.inherits(ChildClass, ParentClass);
*
* var child = new ChildClass('a', 'b', 'see');
* child.foo(); // This works.
*
* In addition, a superclass' implementation of a method can be invoked as
* follows:
*
* ChildClass.prototype.foo = function(a) {
* ChildClass.superClass_.foo.call(this, a);
* // Other code here.
* };
*
* @param {Function} childCtor Child constructor.
* @param {Function} parentCtor Parent constructor.
* @function
* @api * @api
*/ */
ol.inherits = ol.inherits =
goog.inherits; goog.inherits;
// note that the newline above is necessary to satisfy the linter

View File

@@ -257,19 +257,6 @@ ol.pointer.PointerEvent.prototype.getPressure_ = function(eventDict, buttons) {
}; };
/**
* Warning is suppressed because Closure thinks the MouseEvent
* constructor takes no arguments.
* @param {string} inType The type of the event to create.
* @param {Object} inDict An dictionary of initial event properties.
* @return {MouseEvent}
* @suppress {checkTypes}
*/
ol.pointer.PointerEvent.createMouseEvent = function(inType, inDict) {
return new MouseEvent(inType, inDict);
};
/** /**
* Is the `buttons` property supported? * Is the `buttons` property supported?
* @type {boolean} * @type {boolean}
@@ -282,7 +269,7 @@ ol.pointer.PointerEvent.HAS_BUTTONS = false;
*/ */
(function() { (function() {
try { try {
var ev = ol.pointer.PointerEvent.createMouseEvent('click', {buttons: 1}); var ev = new MouseEvent('click', {buttons: 1});
ol.pointer.PointerEvent.HAS_BUTTONS = ev.buttons === 1; ol.pointer.PointerEvent.HAS_BUTTONS = ev.buttons === 1;
} catch (e) { } catch (e) {
} }

View File

@@ -1,471 +0,0 @@
goog.provide('ol.proj.CH');
goog.provide('ol.proj.EPSG2056');
goog.provide('ol.proj.EPSG21781');
goog.require('goog.asserts');
goog.require('goog.math');
goog.require('ol.ellipsoid.BESSEL1841');
goog.require('ol.proj');
goog.require('ol.proj.EPSG4326');
goog.require('ol.proj.Projection');
goog.require('ol.proj.Units');
/**
* Internal base class for Swiss grid projections.
* @constructor
* @extends {ol.proj.Projection}
* @param {{code: string, extent: ol.Extent}} options Options.
* @api
*/
ol.proj.CH = function(options) {
goog.base(this, {
code: options.code,
extent: options.extent,
global: false,
units: ol.proj.Units.METERS
});
};
goog.inherits(ol.proj.CH, ol.proj.Projection);
/**
* @const
* @type {number}
*/
ol.proj.CH.PHI0 = goog.math.toRadians((3600 * 46 + 60 * 57 + 8.66) / 3600);
/**
* @const
* @type {number}
*/
ol.proj.CH.LAMBDA0 = goog.math.toRadians((3600 * 7 + 60 * 26 + 22.5) / 3600);
/**
* @const
* @type {ol.Ellipsoid}
*/
ol.proj.CH.ELLIPSOID = ol.ellipsoid.BESSEL1841;
/**
* @const
* @type {number}
*/
ol.proj.CH.COS_PHI0 = Math.cos(ol.proj.CH.PHI0);
/**
* @const
* @type {number}
*/
ol.proj.CH.SIN_PHI0 = Math.sin(ol.proj.CH.PHI0);
/**
* @const
* @type {number}
*/
ol.proj.CH.R = ol.proj.CH.ELLIPSOID.a * Math.sqrt(1 -
ol.proj.CH.ELLIPSOID.eSquared) / (1 - ol.proj.CH.ELLIPSOID.eSquared *
ol.proj.CH.SIN_PHI0 * ol.proj.CH.SIN_PHI0);
/**
* @const
* @type {number}
*/
ol.proj.CH.ALPHA = Math.sqrt(1 +
ol.proj.CH.ELLIPSOID.eSquared * Math.pow(ol.proj.CH.COS_PHI0, 4) /
(1 - ol.proj.CH.ELLIPSOID.eSquared));
/**
* @const
* @type {number}
*/
ol.proj.CH.SIN_B0 = ol.proj.CH.SIN_PHI0 / ol.proj.CH.ALPHA;
/**
* @const
* @type {number}
*/
ol.proj.CH.B0 = Math.asin(ol.proj.CH.SIN_B0);
/**
* @const
* @type {number}
*/
ol.proj.CH.COS_B0 = Math.cos(ol.proj.CH.B0);
// FIXME should we use Math.sqrt(1 - ol.proj.CH.SIN_B0 * ol.proj.CH.SIN_B0) ?
/**
* @const
* @type {number}
*/
ol.proj.CH.K = Math.log(Math.tan(Math.PI / 4 + ol.proj.CH.B0 / 2)) -
ol.proj.CH.ALPHA * Math.log(Math.tan(Math.PI / 4 + ol.proj.CH.PHI0 / 2)) +
ol.proj.CH.ALPHA * ol.proj.CH.ELLIPSOID.e * Math.log(
(1 + ol.proj.CH.ELLIPSOID.e * ol.proj.CH.SIN_PHI0) /
(1 - ol.proj.CH.ELLIPSOID.e * ol.proj.CH.SIN_PHI0)) / 2;
/**
* Add EPSG:2056 and EPSG:21781 projections, and transformations between them.
*/
ol.proj.CH.add = function() {
ol.proj.EPSG2056.add();
ol.proj.EPSG21781.add();
var epsg2056 = ol.proj.get('EPSG:2056');
var epsg21781 = ol.proj.get('EPSG:21781');
ol.proj.addTransform(epsg2056, epsg21781,
goog.partial(ol.proj.CH.translate_, -2000000, -1000000));
ol.proj.addTransform(epsg21781, epsg2056,
goog.partial(ol.proj.CH.translate_, 2000000, 1000000));
};
/**
* Transformation from EPSG:4326 to EPSG:2056/EPSG:21781.
*
* This uses an approximation that is accurate to about 1m.
*
* @see http://www.swisstopo.admin.ch/internet/swisstopo/en/home/products/software/products/skripts.html
*
* @param {number} offsetY Y offset.
* @param {number} offsetX X offset.
* @param {Array.<number>} input Input array of coordinate values.
* @param {Array.<number>=} opt_output Output array of coordinate values.
* @param {number=} opt_dimension Dimension (default is `2`).
* @private
* @return {Array.<number>} Output array of coordinate values.
*/
ol.proj.CH.fromEPSG4326Approximate_ =
function(offsetY, offsetX, input, opt_output, opt_dimension) {
var n = input.length;
var dimension = goog.isDef(opt_dimension) ? opt_dimension : 2;
var output;
if (goog.isDef(opt_output)) {
output = opt_output;
} else {
if (dimension > 2) {
output = input.slice();
} else {
output = new Array(n);
}
}
goog.asserts.assert(dimension >= 2);
goog.asserts.assert(output.length % dimension === 0);
var auxLat, auxLon, i;
for (i = 0; i < n; i += dimension) {
auxLat = 36 * input[i + 1] / 100 - 16.902866;
auxLon = 36 * input[i] / 100 - 2.67825;
output[i] = offsetY + 72.37 +
211455.93 * auxLon -
10938.51 * auxLon * auxLat -
0.36 * auxLon * auxLat * auxLat -
44.54 * auxLon * auxLon * auxLon;
output[i + 1] = offsetX + 147.07 +
308807.95 * auxLat +
3745.25 * auxLon * auxLon +
76.63 * auxLat * auxLat -
194.56 * auxLon * auxLon * auxLat +
119.79 * auxLat * auxLat * auxLat;
}
return output;
};
/**
* Transformation from EPSG:4326 to EPSG:2056/EPSG:21781.
*
* @see http://www.swisstopo.admin.ch/internet/swisstopo/en/home/topics/survey/sys/refsys/projections.html
*
* @param {number} offsetY Y offset.
* @param {number} offsetX X offset.
* @param {Array.<number>} input Input array of coordinate values.
* @param {Array.<number>=} opt_output Output array of coordinate values.
* @param {number=} opt_dimension Dimension (default is `2`).
* @private
* @return {Array.<number>} Output array of coordinate values.
*/
ol.proj.CH.fromEPSG4326Rigorous_ =
function(offsetY, offsetX, input, opt_output, opt_dimension) {
var n = input.length;
var dimension = goog.isDef(opt_dimension) ? opt_dimension : 2;
var output;
if (goog.isDef(opt_output)) {
output = opt_output;
} else {
if (dimension > 2) {
output = input.slice();
} else {
output = new Array(n);
}
}
goog.asserts.assert(dimension >= 2);
goog.asserts.assert(output.length % dimension === 0);
var b, bBar, eSinPhi, i, l, lambda, lBar, phi, s;
for (i = 0; i < n; i += dimension) {
lambda = goog.math.toRadians(input[i]);
phi = goog.math.toRadians(input[i + 1]);
eSinPhi = ol.proj.CH.ELLIPSOID.e * Math.sin(phi);
s = ol.proj.CH.ALPHA * Math.log(Math.tan(Math.PI / 4 + phi / 2)) -
ol.proj.CH.ALPHA * ol.proj.CH.ELLIPSOID.e * Math.log(
(1 + eSinPhi) / (1 - eSinPhi)) / 2 + ol.proj.CH.K;
b = 2 * (Math.atan(Math.exp(s)) - Math.PI / 4);
l = ol.proj.CH.ALPHA * (lambda - ol.proj.CH.LAMBDA0);
lBar = Math.atan2(Math.sin(l),
ol.proj.CH.SIN_B0 * Math.tan(b) + ol.proj.CH.COS_B0 * Math.cos(l));
bBar = Math.asin(ol.proj.CH.COS_B0 * Math.sin(b) -
ol.proj.CH.SIN_B0 * Math.cos(b) * Math.cos(l));
output[i] = offsetY + ol.proj.CH.R * lBar;
output[i + 1] = offsetX + ol.proj.CH.R *
Math.log((1 + Math.sin(bBar)) / (1 - Math.sin(bBar))) / 2;
}
return output;
};
/**
* Transformation from EPSG:2056/EPSG:21781 to EPSG:4326.
*
* This uses an approximation that is accurate to about 1m.
*
* @see http://www.swisstopo.admin.ch/internet/swisstopo/en/home/products/software/products/skripts.html
*
* @param {number} offsetY Y offset.
* @param {number} offsetX X offset.
* @param {Array.<number>} input Input array of coordinate values.
* @param {Array.<number>=} opt_output Output array of coordinate values.
* @param {number=} opt_dimension Dimension (default is `2`).
* @private
* @return {Array.<number>} Output array of coordinate values.
*/
ol.proj.CH.toEPSG4326Approximate_ =
function(offsetY, offsetX, input, opt_output, opt_dimension) {
var n = input.length;
var dimension = goog.isDef(opt_dimension) ? opt_dimension : 2;
var output;
if (goog.isDef(opt_output)) {
output = opt_output;
} else {
if (dimension > 2) {
output = input.slice();
} else {
output = new Array(n);
}
}
goog.asserts.assert(dimension >= 2);
goog.asserts.assert(output.length % dimension === 0);
var auxX, auxY, i;
for (i = 0; i < n; i += dimension) {
auxY = (input[i] - offsetY) / 1000000;
auxX = (input[i + 1] - offsetX) / 1000000;
output[i] = 100 * (2.6779094 +
4.728982 * auxY +
0.791484 * auxY * auxX +
0.1306 * auxY * auxX * auxX -
0.0436 * auxY * auxY * auxY) / 36;
output[i + 1] = 100 * (16.9023892 +
3.238272 * auxX -
0.270978 * auxY * auxY -
0.002528 * auxX * auxX -
0.0447 * auxY * auxY * auxX -
0.014 * auxX * auxX * auxX) / 36;
}
return output;
};
/**
* Transformation from EPSG:2056/EPSG:21781 to EPSG:4326.
*
* @see http://www.swisstopo.admin.ch/internet/swisstopo/en/home/topics/survey/sys/refsys/projections.html
*
* @param {number} offsetY Y offset.
* @param {number} offsetX X offset.
* @param {Array.<number>} input Input array of coordinate values.
* @param {Array.<number>=} opt_output Output array of coordinate values.
* @param {number=} opt_dimension Dimension (default is `2`).
* @private
* @return {Array.<number>} Output array of coordinate values.
*/
ol.proj.CH.toEPSG4326Rigorous_ =
function(offsetY, offsetX, input, opt_output, opt_dimension) {
var n = input.length;
var dimension = goog.isDef(opt_dimension) ? opt_dimension : 2;
var output;
if (goog.isDef(opt_output)) {
output = opt_output;
} else {
if (dimension > 2) {
output = input.slice();
} else {
output = new Array(n);
}
}
goog.asserts.assert(dimension >= 2);
goog.asserts.assert(output.length % dimension === 0);
var b, bBar, eSinPhi, i, iterations, l, lambda, lastPhi, lBar, phi, s, x, y;
for (i = 0; i < n; i += dimension) {
y = input[i] - offsetY;
x = input[i + 1] - offsetX;
lBar = y / ol.proj.CH.R;
bBar = 2 * (Math.atan(Math.exp(x / ol.proj.CH.R)) - Math.PI / 4);
b = Math.asin(ol.proj.CH.COS_B0 * Math.sin(bBar) +
ol.proj.CH.SIN_B0 * Math.cos(bBar) * Math.cos(lBar));
l = Math.atan2(Math.sin(lBar), ol.proj.CH.COS_B0 * Math.cos(lBar) -
ol.proj.CH.SIN_B0 * Math.tan(bBar));
lambda = ol.proj.CH.LAMBDA0 + l / ol.proj.CH.ALPHA;
lastPhi = phi = b;
// Empirically, about 18 iterations are required for 1e-7 radian accuracy
for (iterations = 20; iterations > 0; --iterations) {
s = (Math.log(Math.tan(Math.PI / 4 + b / 2)) -
ol.proj.CH.K) / ol.proj.CH.ALPHA +
ol.proj.CH.ELLIPSOID.e * Math.log(Math.tan(Math.PI / 4 +
Math.asin(ol.proj.CH.ELLIPSOID.e * Math.sin(phi)) / 2));
phi = 2 * Math.atan(Math.exp(s)) - Math.PI / 2;
if (Math.abs(phi - lastPhi) < 1e-7) {
break;
}
lastPhi = phi;
}
goog.asserts.assert(iterations !== 0);
output[i] = goog.math.toDegrees(lambda);
output[i + 1] = goog.math.toDegrees(phi);
}
return output;
};
/**
* Transformation between EPSG:2056 and EPSG:21781.
*
* Currently a simple offset is used. This is accurate to within 3m.
*
* @param {number} offsetY Y offset.
* @param {number} offsetX X offset.
* @param {Array.<number>} input Input array of coordinate values.
* @param {Array.<number>=} opt_output Output array of coordinate values.
* @param {number=} opt_dimension Dimension (default is `2`).
* @private
* @return {Array.<number>} Output array of coordinate values.
*/
ol.proj.CH.translate_ =
function(offsetY, offsetX, input, opt_output, opt_dimension) {
var n = input.length;
var dimension = goog.isDef(opt_dimension) ? opt_dimension : 2;
var output;
if (goog.isDef(opt_output)) {
output = opt_output;
} else {
if (dimension > 2) {
output = input.slice();
} else {
output = new Array(n);
}
}
goog.asserts.assert(dimension >= 2);
goog.asserts.assert(output.length % dimension === 0);
var i;
for (i = 0; i < n; i += dimension) {
output[i] = input[i] + offsetY;
output[i + 1] = input[i + 1] + offsetX;
}
return output;
};
/**
* @inheritDoc
*/
ol.proj.CH.prototype.getPointResolution = function(resolution, point) {
return resolution;
};
/**
* The EPSG:2056 projection, also known as LV95 (CH1903+).
* @constructor
* @extends {ol.proj.CH}
* @api
*/
ol.proj.EPSG2056 = function() {
goog.base(this, {
code: 'EPSG:2056',
extent: ol.proj.EPSG2056.EXTENT
});
};
goog.inherits(ol.proj.EPSG2056, ol.proj.CH);
/**
* @const
* @type {ol.Extent}
*/
ol.proj.EPSG2056.EXTENT =
[2485869.5728, 1076443.1884, 2837076.5648, 1299941.7864];
/**
* Add the EPSG:2056 projection and transformations to and from EPSG:4326.
*/
ol.proj.EPSG2056.add = function() {
ol.proj.addEquivalentProjections(ol.proj.EPSG4326.PROJECTIONS);
var epsg2056 = new ol.proj.EPSG2056();
ol.proj.addProjection(epsg2056);
ol.proj.addEquivalentTransforms(
ol.proj.EPSG4326.PROJECTIONS,
[epsg2056],
goog.partial(ol.proj.CH.fromEPSG4326Rigorous_, 2600000, 1200000),
goog.partial(ol.proj.CH.toEPSG4326Rigorous_, 2600000, 1200000));
};
/**
* The EPSG:21781 projection, also known as LV03 (CH1903).
* @constructor
* @extends {ol.proj.CH}
* @api
*/
ol.proj.EPSG21781 = function() {
goog.base(this, {
code: 'EPSG:21781',
extent: ol.proj.EPSG21781.EXTENT
});
};
goog.inherits(ol.proj.EPSG21781, ol.proj.CH);
/**
* @const
* @type {ol.Extent}
*/
ol.proj.EPSG21781.EXTENT = [
485869.5728, 76443.1884,
837076.5648, 299941.7864
];
/**
* Add the EPSG:21781 projection and transformations to and from EPSG:4326.
*/
ol.proj.EPSG21781.add = function() {
ol.proj.addEquivalentProjections(ol.proj.EPSG4326.PROJECTIONS);
var epsg21781 = new ol.proj.EPSG21781();
ol.proj.addProjection(epsg21781);
ol.proj.addEquivalentTransforms(
ol.proj.EPSG4326.PROJECTIONS,
[epsg21781],
goog.partial(ol.proj.CH.fromEPSG4326Rigorous_, 600000, 200000),
goog.partial(ol.proj.CH.toEPSG4326Rigorous_, 600000, 200000));
};

View File

@@ -16,17 +16,26 @@ goog.require('ol.proj.Units');
* @constructor * @constructor
* @extends {ol.proj.Projection} * @extends {ol.proj.Projection}
* @param {string} code Code. * @param {string} code Code.
* @api * @private
*/ */
ol.proj.EPSG3857 = function(code) { ol.proj.EPSG3857_ = function(code) {
goog.base(this, { goog.base(this, {
code: code, code: code,
units: ol.proj.Units.METERS, units: ol.proj.Units.METERS,
extent: ol.proj.EPSG3857.EXTENT, extent: ol.proj.EPSG3857.EXTENT,
global: true global: true,
worldExtent: ol.proj.EPSG3857.WORLD_EXTENT
}); });
}; };
goog.inherits(ol.proj.EPSG3857, ol.proj.Projection); goog.inherits(ol.proj.EPSG3857_, ol.proj.Projection);
/**
* @inheritDoc
*/
ol.proj.EPSG3857_.prototype.getPointResolution = function(resolution, point) {
return resolution / ol.math.cosh(point[1] / ol.proj.EPSG3857.RADIUS);
};
/** /**
@@ -53,6 +62,13 @@ ol.proj.EPSG3857.EXTENT = [
]; ];
/**
* @const
* @type {ol.Extent}
*/
ol.proj.EPSG3857.WORLD_EXTENT = [-180, -85, 180, 85];
/** /**
* Lists several projection codes with the same meaning as EPSG:3857. * Lists several projection codes with the same meaning as EPSG:3857.
* *
@@ -77,7 +93,7 @@ ol.proj.EPSG3857.CODES = [
ol.proj.EPSG3857.PROJECTIONS = goog.array.map( ol.proj.EPSG3857.PROJECTIONS = goog.array.map(
ol.proj.EPSG3857.CODES, ol.proj.EPSG3857.CODES,
function(code) { function(code) {
return new ol.proj.EPSG3857(code); return new ol.proj.EPSG3857_(code);
}); });
@@ -139,11 +155,3 @@ ol.proj.EPSG3857.toEPSG4326 = function(input, opt_output, opt_dimension) {
} }
return output; return output;
}; };
/**
* @inheritDoc
*/
ol.proj.EPSG3857.prototype.getPointResolution = function(resolution, point) {
return resolution / ol.math.cosh(point[1] / ol.proj.EPSG3857.RADIUS);
};

View File

@@ -18,18 +18,27 @@ goog.require('ol.proj.Units');
* @extends {ol.proj.Projection} * @extends {ol.proj.Projection}
* @param {string} code Code. * @param {string} code Code.
* @param {string=} opt_axisOrientation Axis orientation. * @param {string=} opt_axisOrientation Axis orientation.
* @api * @private
*/ */
ol.proj.EPSG4326 = function(code, opt_axisOrientation) { ol.proj.EPSG4326_ = function(code, opt_axisOrientation) {
goog.base(this, { goog.base(this, {
code: code, code: code,
units: ol.proj.Units.DEGREES, units: ol.proj.Units.DEGREES,
extent: ol.proj.EPSG4326.EXTENT, extent: ol.proj.EPSG4326.EXTENT,
axisOrientation: opt_axisOrientation, axisOrientation: opt_axisOrientation,
global: true global: true,
worldExtent: ol.proj.EPSG4326.EXTENT
}); });
}; };
goog.inherits(ol.proj.EPSG4326, ol.proj.Projection); goog.inherits(ol.proj.EPSG4326_, ol.proj.Projection);
/**
* @inheritDoc
*/
ol.proj.EPSG4326_.prototype.getPointResolution = function(resolution, point) {
return resolution;
};
/** /**
@@ -48,19 +57,11 @@ ol.proj.EPSG4326.EXTENT = [-180, -90, 180, 90];
* @type {Array.<ol.proj.Projection>} * @type {Array.<ol.proj.Projection>}
*/ */
ol.proj.EPSG4326.PROJECTIONS = [ ol.proj.EPSG4326.PROJECTIONS = [
new ol.proj.EPSG4326('CRS:84'), new ol.proj.EPSG4326_('CRS:84'),
new ol.proj.EPSG4326('EPSG:4326', 'neu'), new ol.proj.EPSG4326_('EPSG:4326', 'neu'),
new ol.proj.EPSG4326('urn:ogc:def:crs:EPSG:6.6:4326', 'neu'), new ol.proj.EPSG4326_('urn:ogc:def:crs:EPSG:6.6:4326', 'neu'),
new ol.proj.EPSG4326('urn:ogc:def:crs:OGC:1.3:CRS84'), new ol.proj.EPSG4326_('urn:ogc:def:crs:OGC:1.3:CRS84'),
new ol.proj.EPSG4326('urn:ogc:def:crs:OGC:2:84'), new ol.proj.EPSG4326_('urn:ogc:def:crs:OGC:2:84'),
new ol.proj.EPSG4326('http://www.opengis.net/gml/srs/epsg.xml#4326', 'neu'), new ol.proj.EPSG4326_('http://www.opengis.net/gml/srs/epsg.xml#4326', 'neu'),
new ol.proj.EPSG4326('urn:x-ogc:def:crs:EPSG:4326', 'neu') new ol.proj.EPSG4326_('urn:x-ogc:def:crs:EPSG:4326', 'neu')
]; ];
/**
* @inheritDoc
*/
ol.proj.EPSG4326.prototype.getPointResolution = function(resolution, point) {
return resolution;
};

View File

@@ -42,6 +42,7 @@ ol.proj.Units = {
* @type {Object.<ol.proj.Units, number>} * @type {Object.<ol.proj.Units, number>}
* @api * @api
*/ */
ol.proj.METERS_PER_UNIT = {};
ol.proj.METERS_PER_UNIT[ol.proj.Units.DEGREES] = ol.proj.METERS_PER_UNIT[ol.proj.Units.DEGREES] =
2 * Math.PI * ol.sphere.NORMAL.radius / 360; 2 * Math.PI * ol.sphere.NORMAL.radius / 360;
ol.proj.METERS_PER_UNIT[ol.proj.Units.FEET] = 0.3048; ol.proj.METERS_PER_UNIT[ol.proj.Units.FEET] = 0.3048;
@@ -51,16 +52,14 @@ ol.proj.METERS_PER_UNIT[ol.proj.Units.METERS] = 1;
/** /**
* @classdesc * @classdesc
* Class for coordinate transforms between coordinate systems. By default, * Projection definition class. One of these is created for each projection
* OpenLayers ships with the ability to transform coordinates between * supported in the application and stored in the {@link ol.proj} namespace.
* geographic (EPSG:4326) and web or spherical mercator (EPSG:3857) * You can use these in applications, but this is not required, as API params
* coordinate reference systems. Any transform functions can be added with * and options use {@link ol.proj.ProjectionLike} which means the simple string
* {@link ol.proj.addCoordinateTransforms}. * code will suffice.
* *
* Additional transforms may be added by using the {@link http://proj4js.org/} * You can use {@link ol.proj.get} to retrieve the object for a particular
* library. If the proj4js library is loaded, transforms will work between any * projection.
* coordinate reference systems with proj4js definitions. These definitions can
* be obtained from {@link http://epsg.io/}.
* *
* @constructor * @constructor
* @param {olx.ProjectionOptions} options Projection options. * @param {olx.ProjectionOptions} options Projection options.
@@ -87,6 +86,13 @@ ol.proj.Projection = function(options) {
*/ */
this.extent_ = goog.isDef(options.extent) ? options.extent : null; this.extent_ = goog.isDef(options.extent) ? options.extent : null;
/**
* @private
* @type {ol.Extent}
*/
this.worldExtent_ = goog.isDef(options.worldExtent) ?
options.worldExtent : null;
/** /**
* @private * @private
* @type {string} * @type {string}
@@ -149,6 +155,16 @@ ol.proj.Projection.prototype.getMetersPerUnit = function() {
}; };
/**
* Get the world extent for this projection.
* @return {ol.Extent} Extent.
* @api
*/
ol.proj.Projection.prototype.getWorldExtent = function() {
return this.worldExtent_;
};
/** /**
* Get the axis orientation of this projection. * Get the axis orientation of this projection.
* Example values are: * Example values are:
@@ -199,6 +215,17 @@ ol.proj.Projection.prototype.setExtent = function(extent) {
}; };
/**
* Set the world extent for this projection.
* @param {ol.Extent} worldExtent World extent
* [minlon, minlat, maxlon, maxlat].
* @api
*/
ol.proj.Projection.prototype.setWorldExtent = function(worldExtent) {
this.worldExtent_ = worldExtent;
};
/** /**
* Get the resolution of the point in degrees. For projections with degrees as * Get the resolution of the point in degrees. For projections with degrees as
* the unit this will simply return the provided resolution. For other * the unit this will simply return the provided resolution. For other
@@ -368,6 +395,9 @@ ol.proj.addTransform = function(source, destination, transformFn) {
/** /**
* Registers coordinate transform functions to convert coordinates between the * Registers coordinate transform functions to convert coordinates between the
* source projection and the destination projection. * source projection and the destination projection.
* The forward and inverse functions convert coordinate pairs; this function
* converts these into the functions used internally which also handle
* extents and coordinate arrays.
* *
* @param {ol.proj.ProjectionLike} source Source projection. * @param {ol.proj.ProjectionLike} source Source projection.
* @param {ol.proj.ProjectionLike} destination Destination projection. * @param {ol.proj.ProjectionLike} destination Destination projection.

View File

@@ -14,5 +14,41 @@
* for example by Bing Maps or OpenStreetMap), together with the relevant * for example by Bing Maps or OpenStreetMap), together with the relevant
* transform functions. * transform functions.
* *
* Additional transforms may be added by using the {@link http://proj4js.org/}
* library (version 2.2 or later). You can use the full build supplied by
* Proj4js, or create a custom build to support those projections you need; see
* the Proj4js website for how to do this. You also need the Proj4js definitions
* for the required projections. These definitions can be obtained from
* {@link http://epsg.io/}, and are a JS function, so can be loaded in a script
* tag (as in the examples) or pasted into your application.
* The first time there is a request for a projection, either with a
* {@link ol.proj.projectionLike} or directly with {@link ol.proj.get}, the
* code will check if the Proj4js library and the necessary definition are
* loaded; if so, it will register the appropriate {@link ol.proj.Projection}
* object and add transform functions between the new projection and all the
* existing ones. See examples/wms-image-custom-proj for an example of this.
* Because the check for presence of the Proj4js library and the definition only
* takes place on the first request for them, this means they can be loaded
* dynamically as needed; for example, with user-supplied data where you don't
* know in advance what projections are needed, you can initially load minimal
* support and then load whichever are requested.
*
* Note that Proj4js does not support projection extents. If you want to add
* one for creating default tile grids, you can add it after the Projection
* object has been created with `setExtent`, for example,
* `ol.proj.get('EPSG:1234').setExtent(extent)`.
*
* In addition to Proj4js support, any transform functions can be added with
* {@link ol.proj.addCoordinateTransforms}. To use this, you must first create
* a {@link ol.proj.Projection} object for the new projection and add it with
* {@link ol.proj.addProjection}. You can then add the forward and inverse
* functions with {@link ol.proj.addCoordinateTransforms}. See
* examples/wms-custom-proj for an example of this.
*
* Note that if no transforms are needed and you only need to define the
* projection, just add a {@link ol.proj.Projection} with
* {@link ol.proj.addProjection}. See examples/wms-no-proj for an example of
* this.
*
* @namespace ol.proj * @namespace ol.proj
*/ */

View File

@@ -7,6 +7,7 @@ goog.require('goog.vec.Mat4');
goog.require('ol.ImageBase'); goog.require('ol.ImageBase');
goog.require('ol.ImageState'); goog.require('ol.ImageState');
goog.require('ol.ViewHint'); goog.require('ol.ViewHint');
goog.require('ol.extent');
goog.require('ol.layer.Image'); goog.require('ol.layer.Image');
goog.require('ol.renderer.Map'); goog.require('ol.renderer.Map');
goog.require('ol.renderer.canvas.Layer'); goog.require('ol.renderer.canvas.Layer');
@@ -102,9 +103,16 @@ ol.renderer.canvas.ImageLayer.prototype.prepareFrame =
var hints = frameState.viewHints; var hints = frameState.viewHints;
if (!hints[ol.ViewHint.ANIMATING] && !hints[ol.ViewHint.INTERACTING]) { var renderedExtent = frameState.extent;
if (goog.isDef(layerState.extent)) {
renderedExtent = ol.extent.getIntersection(
renderedExtent, layerState.extent);
}
if (!hints[ol.ViewHint.ANIMATING] && !hints[ol.ViewHint.INTERACTING] &&
!ol.extent.isEmpty(renderedExtent)) {
image = imageSource.getImage( image = imageSource.getImage(
frameState.extent, viewResolution, pixelRatio, viewState.projection); renderedExtent, viewResolution, pixelRatio, viewState.projection);
if (!goog.isNull(image)) { if (!goog.isNull(image)) {
var imageState = image.getState(); var imageState = image.getState();
if (imageState == ol.ImageState.IDLE) { if (imageState == ol.ImageState.IDLE) {

View File

@@ -193,6 +193,11 @@ ol.renderer.canvas.TileLayer.prototype.prepareFrame =
} else { } else {
extent = frameState.extent; extent = frameState.extent;
} }
if (goog.isDef(layerState.extent)) {
extent = ol.extent.getIntersection(extent, layerState.extent);
}
var tileRange = tileGrid.getTileRangeForExtentAndResolution( var tileRange = tileGrid.getTileRangeForExtentAndResolution(
extent, tileResolution); extent, tileResolution);
@@ -233,6 +238,11 @@ ol.renderer.canvas.TileLayer.prototype.prepareFrame =
if (z != this.renderedCanvasZ_ || if (z != this.renderedCanvasZ_ ||
!this.renderedCanvasTileRange_.containsTileRange(tileRange)) { !this.renderedCanvasTileRange_.containsTileRange(tileRange)) {
this.renderedCanvasTileRange_ = null; this.renderedCanvasTileRange_ = null;
// Due to limited layer extent, we may be rendering tiles on a small
// portion of the canvas.
if (z < this.renderedCanvasZ_) {
this.context_.clearRect(0, 0, canvasWidth, canvasHeight);
}
} }
} }
} }

View File

@@ -6,7 +6,6 @@ goog.require('goog.events');
goog.require('ol.ViewHint'); goog.require('ol.ViewHint');
goog.require('ol.dom'); goog.require('ol.dom');
goog.require('ol.extent'); goog.require('ol.extent');
goog.require('ol.feature');
goog.require('ol.layer.Vector'); goog.require('ol.layer.Vector');
goog.require('ol.render.EventType'); goog.require('ol.render.EventType');
goog.require('ol.render.canvas.ReplayGroup'); goog.require('ol.render.canvas.ReplayGroup');
@@ -155,7 +154,7 @@ ol.renderer.canvas.VectorLayer.prototype.handleImageChange_ =
ol.renderer.canvas.VectorLayer.prototype.prepareFrame = ol.renderer.canvas.VectorLayer.prototype.prepareFrame =
function(frameState, layerState) { function(frameState, layerState) {
var vectorLayer = this.getLayer(); var vectorLayer = /** @type {ol.layer.Vector} */ (this.getLayer());
goog.asserts.assertInstanceof(vectorLayer, ol.layer.Vector); goog.asserts.assertInstanceof(vectorLayer, ol.layer.Vector);
var vectorSource = vectorLayer.getSource(); var vectorSource = vectorLayer.getSource();
goog.asserts.assertInstanceof(vectorSource, ol.source.Vector); goog.asserts.assertInstanceof(vectorSource, ol.source.Vector);
@@ -202,10 +201,6 @@ ol.renderer.canvas.VectorLayer.prototype.prepareFrame =
this.dirty_ = false; this.dirty_ = false;
var styleFunction = vectorLayer.getStyleFunction();
if (!goog.isDef(styleFunction)) {
styleFunction = ol.feature.defaultStyleFunction;
}
var replayGroup = var replayGroup =
new ol.render.canvas.ReplayGroup( new ol.render.canvas.ReplayGroup(
ol.renderer.vector.getTolerance(resolution, pixelRatio), extent, ol.renderer.vector.getTolerance(resolution, pixelRatio), extent,
@@ -217,10 +212,17 @@ ol.renderer.canvas.VectorLayer.prototype.prepareFrame =
* @this {ol.renderer.canvas.VectorLayer} * @this {ol.renderer.canvas.VectorLayer}
*/ */
function(feature) { function(feature) {
goog.asserts.assert(goog.isDef(styleFunction)); var styles;
var dirty = this.renderFeature( if (goog.isDef(feature.getStyleFunction())) {
feature, resolution, pixelRatio, styleFunction, replayGroup); styles = feature.getStyleFunction().call(feature, resolution);
this.dirty_ = this.dirty_ || dirty; } else if (goog.isDef(vectorLayer.getStyleFunction())) {
styles = vectorLayer.getStyleFunction()(feature, resolution);
}
if (goog.isDefAndNotNull(styles)) {
var dirty = this.renderFeature(
feature, resolution, pixelRatio, styles, replayGroup);
this.dirty_ = this.dirty_ || dirty;
}
}; };
if (!goog.isNull(vectorLayerRenderOrder)) { if (!goog.isNull(vectorLayerRenderOrder)) {
/** @type {Array.<ol.Feature>} */ /** @type {Array.<ol.Feature>} */
@@ -252,13 +254,12 @@ ol.renderer.canvas.VectorLayer.prototype.prepareFrame =
* @param {ol.Feature} feature Feature. * @param {ol.Feature} feature Feature.
* @param {number} resolution Resolution. * @param {number} resolution Resolution.
* @param {number} pixelRatio Pixel ratio. * @param {number} pixelRatio Pixel ratio.
* @param {ol.feature.StyleFunction} styleFunction Style function. * @param {Array.<ol.style.Style>} styles Array of styles
* @param {ol.render.canvas.ReplayGroup} replayGroup Replay group. * @param {ol.render.canvas.ReplayGroup} replayGroup Replay group.
* @return {boolean} `true` if an image is loading. * @return {boolean} `true` if an image is loading.
*/ */
ol.renderer.canvas.VectorLayer.prototype.renderFeature = ol.renderer.canvas.VectorLayer.prototype.renderFeature =
function(feature, resolution, pixelRatio, styleFunction, replayGroup) { function(feature, resolution, pixelRatio, styles, replayGroup) {
var styles = styleFunction(feature, resolution);
if (!goog.isDefAndNotNull(styles)) { if (!goog.isDefAndNotNull(styles)) {
return false; return false;
} }

View File

@@ -10,6 +10,7 @@ goog.require('ol.ImageBase');
goog.require('ol.ImageState'); goog.require('ol.ImageState');
goog.require('ol.ViewHint'); goog.require('ol.ViewHint');
goog.require('ol.dom'); goog.require('ol.dom');
goog.require('ol.extent');
goog.require('ol.layer.Image'); goog.require('ol.layer.Image');
goog.require('ol.renderer.dom.Layer'); goog.require('ol.renderer.dom.Layer');
goog.require('ol.source.Image'); goog.require('ol.source.Image');
@@ -89,8 +90,15 @@ ol.renderer.dom.ImageLayer.prototype.prepareFrame =
var hints = frameState.viewHints; var hints = frameState.viewHints;
if (!hints[ol.ViewHint.ANIMATING] && !hints[ol.ViewHint.INTERACTING]) { var renderedExtent = frameState.extent;
var image_ = imageSource.getImage(frameState.extent, viewResolution, if (goog.isDef(layerState.extent)) {
renderedExtent = ol.extent.getIntersection(
renderedExtent, layerState.extent);
}
if (!hints[ol.ViewHint.ANIMATING] && !hints[ol.ViewHint.INTERACTING] &&
!ol.extent.isEmpty(renderedExtent)) {
var image_ = imageSource.getImage(renderedExtent, viewResolution,
frameState.pixelRatio, viewState.projection); frameState.pixelRatio, viewState.projection);
if (!goog.isNull(image_)) { if (!goog.isNull(image_)) {
var imageState = image_.getState(); var imageState = image_.getState();

View File

@@ -109,6 +109,11 @@ ol.renderer.dom.TileLayer.prototype.prepareFrame =
} else { } else {
extent = frameState.extent; extent = frameState.extent;
} }
if (goog.isDef(layerState.extent)) {
extent = ol.extent.getIntersection(extent, layerState.extent);
}
var tileRange = tileGrid.getTileRangeForExtentAndResolution( var tileRange = tileGrid.getTileRangeForExtentAndResolution(
extent, tileResolution); extent, tileResolution);

View File

@@ -1,6 +1,7 @@
goog.provide('ol.renderer.Layer'); goog.provide('ol.renderer.Layer');
goog.require('goog.Disposable'); goog.require('goog.Disposable');
goog.require('goog.asserts');
goog.require('ol.ImageState'); goog.require('ol.ImageState');
goog.require('ol.TileRange'); goog.require('ol.TileRange');
goog.require('ol.TileState'); goog.require('ol.TileState');
@@ -160,7 +161,13 @@ ol.renderer.Layer.prototype.updateAttributions =
ol.renderer.Layer.prototype.updateLogos = function(frameState, source) { ol.renderer.Layer.prototype.updateLogos = function(frameState, source) {
var logo = source.getLogo(); var logo = source.getLogo();
if (goog.isDef(logo)) { if (goog.isDef(logo)) {
frameState.logos[logo] = ''; if (goog.isString(logo)) {
frameState.logos[logo] = '';
} else if (goog.isObject(logo)) {
goog.asserts.assertString(logo.href);
goog.asserts.assertString(logo.src);
frameState.logos[logo.src] = logo.href;
}
} }
}; };

View File

@@ -10,6 +10,7 @@ goog.require('ol.Extent');
goog.require('ol.ImageBase'); goog.require('ol.ImageBase');
goog.require('ol.ImageState'); goog.require('ol.ImageState');
goog.require('ol.ViewHint'); goog.require('ol.ViewHint');
goog.require('ol.extent');
goog.require('ol.layer.Image'); goog.require('ol.layer.Image');
goog.require('ol.renderer.webgl.Layer'); goog.require('ol.renderer.webgl.Layer');
goog.require('ol.source.Image'); goog.require('ol.source.Image');
@@ -119,8 +120,14 @@ ol.renderer.webgl.ImageLayer.prototype.prepareFrame =
var hints = frameState.viewHints; var hints = frameState.viewHints;
if (!hints[ol.ViewHint.ANIMATING] && !hints[ol.ViewHint.INTERACTING]) { var renderedExtent = frameState.extent;
var image_ = imageSource.getImage(frameState.extent, viewResolution, if (goog.isDef(layerState.extent)) {
renderedExtent = ol.extent.getIntersection(
renderedExtent, layerState.extent);
}
if (!hints[ol.ViewHint.ANIMATING] && !hints[ol.ViewHint.INTERACTING] &&
!ol.extent.isEmpty(renderedExtent)) {
var image_ = imageSource.getImage(renderedExtent, viewResolution,
frameState.pixelRatio, viewState.projection); frameState.pixelRatio, viewState.projection);
if (!goog.isNull(image_)) { if (!goog.isNull(image_)) {
var imageState = image_.getState(); var imageState = image_.getState();

View File

@@ -207,11 +207,18 @@ ol.renderer.webgl.TileLayer.prototype.prepareFrame =
var allTilesLoaded = true; var allTilesLoaded = true;
var tmpExtent = ol.extent.createEmpty(); var tmpExtent = ol.extent.createEmpty();
var tmpTileRange = new ol.TileRange(0, 0, 0, 0); var tmpTileRange = new ol.TileRange(0, 0, 0, 0);
var childTileRange, fullyLoaded, tile, tileState, x, y; var childTileRange, fullyLoaded, tile, tileState, x, y, tileExtent;
for (x = tileRange.minX; x <= tileRange.maxX; ++x) { for (x = tileRange.minX; x <= tileRange.maxX; ++x) {
for (y = tileRange.minY; y <= tileRange.maxY; ++y) { for (y = tileRange.minY; y <= tileRange.maxY; ++y) {
tile = tileSource.getTile(z, x, y, pixelRatio, projection); tile = tileSource.getTile(z, x, y, pixelRatio, projection);
if (goog.isDef(layerState.extent)) {
// ignore tiles outside layer extent
tileExtent = tileGrid.getTileCoordExtent(tile.tileCoord, tmpExtent);
if (!ol.extent.intersects(tileExtent, layerState.extent)) {
continue;
}
}
tileState = tile.getState(); tileState = tile.getState();
if (tileState == ol.TileState.LOADED) { if (tileState == ol.TileState.LOADED) {
if (mapRenderer.isTileTextureLoaded(tile)) { if (mapRenderer.isTileTextureLoaded(tile)) {
@@ -243,7 +250,7 @@ ol.renderer.webgl.TileLayer.prototype.prepareFrame =
var zs = goog.array.map(goog.object.getKeys(tilesToDrawByZ), Number); var zs = goog.array.map(goog.object.getKeys(tilesToDrawByZ), Number);
goog.array.sort(zs); goog.array.sort(zs);
var u_tileOffset = goog.vec.Vec4.createFloat32(); var u_tileOffset = goog.vec.Vec4.createFloat32();
var i, ii, sx, sy, tileExtent, tileKey, tilesToDraw, tx, ty; var i, ii, sx, sy, tileKey, tilesToDraw, tx, ty;
for (i = 0, ii = zs.length; i < ii; ++i) { for (i = 0, ii = zs.length; i < ii; ++i) {
tilesToDraw = tilesToDrawByZ[zs[i]]; tilesToDraw = tilesToDrawByZ[zs[i]];
for (tileKey in tilesToDraw) { for (tileKey in tilesToDraw) {

View File

@@ -74,6 +74,13 @@ ol.DebugTile_.prototype.getImage = function(opt_context) {
/** /**
* @classdesc
* A pseudo tile source, which does not fetch tiles from a server, but renders
* a grid outline for the tile grid/projection along with the coordinates for
* each tile. See examples/canvas-tiles for an example.
*
* Uses Canvas context2d, so requires Canvas support.
*
* @constructor * @constructor
* @extends {ol.source.Tile} * @extends {ol.source.Tile}
* @param {olx.source.TileDebugOptions} options Debug tile options. * @param {olx.source.TileDebugOptions} options Debug tile options.
@@ -82,7 +89,6 @@ ol.DebugTile_.prototype.getImage = function(opt_context) {
ol.source.TileDebug = function(options) { ol.source.TileDebug = function(options) {
goog.base(this, { goog.base(this, {
extent: options.extent,
opaque: false, opaque: false,
projection: options.projection, projection: options.projection,
tileGrid: options.tileGrid tileGrid: options.tileGrid

View File

@@ -33,7 +33,6 @@ ol.source.FormatVector = function(options) {
goog.base(this, { goog.base(this, {
attributions: options.attributions, attributions: options.attributions,
extent: options.extent,
logo: options.logo, logo: options.logo,
projection: options.projection projection: options.projection
}); });

View File

@@ -20,7 +20,6 @@ ol.source.ImageCanvas = function(options) {
goog.base(this, { goog.base(this, {
attributions: options.attributions, attributions: options.attributions,
extent: options.extent,
logo: options.logo, logo: options.logo,
projection: options.projection, projection: options.projection,
resolutions: options.resolutions, resolutions: options.resolutions,

View File

@@ -11,7 +11,7 @@ goog.require('ol.source.Source');
/** /**
* @typedef {{attributions: (Array.<ol.Attribution>|undefined), * @typedef {{attributions: (Array.<ol.Attribution>|undefined),
* extent: (null|ol.Extent|undefined), * extent: (null|ol.Extent|undefined),
* logo: (string|undefined), * logo: (string|olx.LogoOptions|undefined),
* projection: ol.proj.ProjectionLike, * projection: ol.proj.ProjectionLike,
* resolutions: (Array.<number>|undefined), * resolutions: (Array.<number>|undefined),
* state: (ol.source.State|string|undefined)}} * state: (ol.source.State|string|undefined)}}

View File

@@ -31,7 +31,6 @@ ol.source.ImageStatic = function(options) {
goog.base(this, { goog.base(this, {
attributions: attributions, attributions: attributions,
extent: options.extent,
logo: options.logo, logo: options.logo,
projection: projection, projection: projection,
resolutions: [imageResolution] resolutions: [imageResolution]

View File

@@ -6,11 +6,11 @@ goog.require('goog.events.EventType');
goog.require('goog.vec.Mat4'); goog.require('goog.vec.Mat4');
goog.require('ol.dom'); goog.require('ol.dom');
goog.require('ol.extent'); goog.require('ol.extent');
goog.require('ol.feature');
goog.require('ol.render.canvas.ReplayGroup'); goog.require('ol.render.canvas.ReplayGroup');
goog.require('ol.renderer.vector'); goog.require('ol.renderer.vector');
goog.require('ol.source.ImageCanvas'); goog.require('ol.source.ImageCanvas');
goog.require('ol.source.Vector'); goog.require('ol.source.Vector');
goog.require('ol.style.Style');
goog.require('ol.vec.Mat4'); goog.require('ol.vec.Mat4');
@@ -42,11 +42,11 @@ ol.source.ImageVector = function(options) {
/** /**
* @private * @private
* @type {!ol.feature.StyleFunction} * @type {!ol.style.StyleFunction}
*/ */
this.styleFunction_ = goog.isDef(options.style) ? this.styleFunction_ = goog.isDefAndNotNull(options.style) ?
ol.feature.createStyleFunction(options.style) : ol.style.createStyleFunction(options.style) :
ol.feature.defaultStyleFunction; ol.style.defaultStyleFunction;
/** /**
* @private * @private
@@ -75,7 +75,6 @@ ol.source.ImageVector = function(options) {
goog.base(this, { goog.base(this, {
attributions: options.attributions, attributions: options.attributions,
canvasFunction: goog.bind(this.canvasFunctionInternal_, this), canvasFunction: goog.bind(this.canvasFunctionInternal_, this),
extent: options.extent,
logo: options.logo, logo: options.logo,
projection: options.projection, projection: options.projection,
ratio: options.ratio, ratio: options.ratio,

View File

@@ -31,7 +31,6 @@ ol.source.ImageWMS = function(opt_options) {
goog.base(this, { goog.base(this, {
attributions: options.attributions, attributions: options.attributions,
extent: options.extent,
logo: options.logo, logo: options.logo,
projection: options.projection, projection: options.projection,
resolutions: options.resolutions resolutions: options.resolutions

View File

@@ -22,7 +22,6 @@ ol.source.KML = function(opt_options) {
goog.base(this, { goog.base(this, {
attributions: options.attributions, attributions: options.attributions,
doc: options.doc, doc: options.doc,
extent: options.extent,
format: new ol.format.KML({ format: new ol.format.KML({
defaultStyle: options.defaultStyle defaultStyle: options.defaultStyle
}), }),

View File

@@ -21,7 +21,6 @@ goog.require('ol.source.Image');
ol.source.MapGuide = function(options) { ol.source.MapGuide = function(options) {
goog.base(this, { goog.base(this, {
extent: options.extent,
projection: options.projection, projection: options.projection,
resolutions: options.resolutions resolutions: options.resolutions
}); });
@@ -55,6 +54,12 @@ ol.source.MapGuide = function(options) {
*/ */
this.imageUrlFunction_ = imageUrlFunction; this.imageUrlFunction_ = imageUrlFunction;
/**
* @private
* @type {Object}
*/
this.params_ = null;
/** /**
* @private * @private
* @type {boolean} * @type {boolean}
@@ -87,10 +92,27 @@ ol.source.MapGuide = function(options) {
*/ */
this.image_ = null; this.image_ = null;
/**
* @private
* @type {number}
*/
this.renderedRevision_ = 0;
}; };
goog.inherits(ol.source.MapGuide, ol.source.Image); goog.inherits(ol.source.MapGuide, ol.source.Image);
/**
* Get the user-provided params, i.e. those passed to the constructor through
* the "params" option, and possibly updated using the updateParams method.
* @return {Object} Params.
* @api
*/
ol.source.MapGuide.prototype.getParams = function() {
return this.params_;
};
/** /**
* @inheritDoc * @inheritDoc
*/ */
@@ -101,6 +123,7 @@ ol.source.MapGuide.prototype.getImage =
var image = this.image_; var image = this.image_;
if (!goog.isNull(image) && if (!goog.isNull(image) &&
this.renderedRevision_ == this.getRevision() &&
image.getResolution() == resolution && image.getResolution() == resolution &&
image.getPixelRatio() == pixelRatio && image.getPixelRatio() == pixelRatio &&
ol.extent.containsExtent(image.getExtent(), extent)) { ol.extent.containsExtent(image.getExtent(), extent)) {
@@ -123,6 +146,7 @@ ol.source.MapGuide.prototype.getImage =
image = null; image = null;
} }
this.image_ = image; this.image_ = image;
this.renderedRevision_ = this.getRevision();
return image; return image;
}; };
@@ -149,6 +173,17 @@ ol.source.MapGuide.getScale = function(extent, size, metersPerUnit, dpi) {
}; };
/**
* Update the user-provided params.
* @param {Object} params Params.
* @api
*/
ol.source.MapGuide.prototype.updateParams = function(params) {
goog.object.extend(this.params_, params);
this.dispatchChangeEvent();
};
/** /**
* @param {string} baseUrl The mapagent url. * @param {string} baseUrl The mapagent url.
* @param {Object.<string, string|number>} params Request parameters. * @param {Object.<string, string|number>} params Request parameters.

View File

@@ -22,7 +22,6 @@ ol.source.OSMXML = function(opt_options) {
goog.base(this, { goog.base(this, {
attributions: options.attributions, attributions: options.attributions,
doc: options.doc, doc: options.doc,
extent: options.extent,
format: new ol.format.OSMXML(), format: new ol.format.OSMXML(),
logo: options.logo, logo: options.logo,
node: options.node, node: options.node,

View File

@@ -23,7 +23,6 @@ ol.source.ServerVector = function(options) {
goog.base(this, { goog.base(this, {
attributions: options.attributions, attributions: options.attributions,
extent: options.extent,
format: options.format, format: options.format,
logo: options.logo, logo: options.logo,
projection: options.projection projection: options.projection

View File

@@ -22,8 +22,7 @@ ol.source.State = {
/** /**
* @typedef {{attributions: (Array.<ol.Attribution>|undefined), * @typedef {{attributions: (Array.<ol.Attribution>|undefined),
* extent: (ol.Extent|undefined), * logo: (string|olx.LogoOptions|undefined),
* logo: (string|undefined),
* projection: ol.proj.ProjectionLike, * projection: ol.proj.ProjectionLike,
* state: (ol.source.State|string|undefined)}} * state: (ol.source.State|string|undefined)}}
*/ */
@@ -52,14 +51,6 @@ ol.source.Source = function(options) {
*/ */
this.projection_ = ol.proj.get(options.projection); this.projection_ = ol.proj.get(options.projection);
/**
* @private
* @type {ol.Extent}
*/
this.extent_ = goog.isDef(options.extent) ?
options.extent : goog.isDef(options.projection) ?
this.projection_.getExtent() : null;
/** /**
* @private * @private
* @type {Array.<ol.Attribution>} * @type {Array.<ol.Attribution>}
@@ -69,7 +60,7 @@ ol.source.Source = function(options) {
/** /**
* @private * @private
* @type {string|undefined} * @type {string|olx.LogoOptions|undefined}
*/ */
this.logo_ = options.logo; this.logo_ = options.logo;
@@ -107,15 +98,7 @@ ol.source.Source.prototype.getAttributions = function() {
/** /**
* @return {ol.Extent} Extent. * @return {string|olx.LogoOptions|undefined} Logo.
*/
ol.source.Source.prototype.getExtent = function() {
return this.extent_;
};
/**
* @return {string|undefined} Logo.
*/ */
ol.source.Source.prototype.getLogo = function() { ol.source.Source.prototype.getLogo = function() {
return this.logo_; return this.logo_;
@@ -154,15 +137,7 @@ ol.source.Source.prototype.setAttributions = function(attributions) {
/** /**
* @param {ol.Extent} extent Extent. * @param {string|olx.LogoOptions|undefined} logo Logo.
*/
ol.source.Source.prototype.setExtent = function(extent) {
this.extent_ = extent;
};
/**
* @param {string|undefined} logo Logo.
*/ */
ol.source.Source.prototype.setLogo = function(logo) { ol.source.Source.prototype.setLogo = function(logo) {
this.logo_ = logo; this.logo_ = logo;

Some files were not shown because too many files have changed in this diff Show More