Merge branch 'master' into release
Conflicts: index.html
@@ -0,0 +1,203 @@
|
||||
## d3
|
||||
|
||||
[d3](http://d3js.org/) is the primary library used by iD. It is used for
|
||||
rendering the map data as well as many sorts of general DOM manipulation tasks
|
||||
for which jQuery would often be used.
|
||||
|
||||
Notable features of d3 that are used by iD include
|
||||
[d3.xhr](https://github.com/mbostock/d3/wiki/Requests#wiki-d3_xhr), which is
|
||||
used to make the API requests to download data from openstreetmap.org and save
|
||||
changes;
|
||||
[d3.dispatch](https://github.com/mbostock/d3/wiki/Internals#wiki-d3_dispatch),
|
||||
which provides a callback-based [Observer
|
||||
pattern](http://en.wikipedia.org/wiki/Observer_pattern) between different
|
||||
parts of iD;
|
||||
[d3.geo.path](https://github.com/mbostock/d3/wiki/Geo-Paths#wiki-path), which
|
||||
generates SVG paths for lines and areas; and
|
||||
[d3.behavior.zoom](https://github.com/mbostock/d3/wiki/Zoom-Behavior#wiki-zoom),
|
||||
which implements map panning and zooming.
|
||||
|
||||
## Core
|
||||
|
||||
The iD *core* implements the OSM data types, a graph of OSM object's
|
||||
relationships to each other, and an undo/redo history for changes made during
|
||||
editing. It aims to be generic enough to be used by other JavaScript-based
|
||||
tools for OpenStreetMap.
|
||||
|
||||
Briefly, the OSM data model includes three basic data types: nodes, ways, and
|
||||
relations. A _node_ is a point type, having a single geographic coordinate. A
|
||||
_way_ is an ordered list of nodes. And a _relation_ groups together nodes,
|
||||
ways, and other relations to provide free-form higher-level structures. Each
|
||||
of these three types has _tags_: an associative array of key-value pairs which
|
||||
describe the object.
|
||||
|
||||
In iD, these three types are implemented by `iD.Node`, `iD.Way` and
|
||||
`iD.Relation`. These three classes inherit from a common base, `iD.Entity`
|
||||
(the only use of classical inheritance in iD). Generically, we refer to a
|
||||
node, way or relation as an _entity_.
|
||||
|
||||
Every entity has an _ID_ either assigned by the OSM database, or, for an
|
||||
entity that is newly created, constructed as a proxy consisting of a negative
|
||||
numeral. IDs from the OSM database as treated as opaque strings; no
|
||||
[assumptions](http://lists.openstreetmap.org/pipermail/dev/2013-February/026495.html)
|
||||
are made of them other than that they can be compared for identity and do not
|
||||
begin with a minus sign (and thus will not conflict with proxy IDs). In fact,
|
||||
in the OSM database the three types of entities have separate ID spaces; a
|
||||
node can have the same ID as a way, for instance. Because it is useful to
|
||||
store heterogeneous entities in the same datastructure, iD ensures that every
|
||||
entity has a fully-unique ID by prefixing each OSM ID with the first letter of
|
||||
the entity type. For example, a way with OSM ID 123456 is represented as
|
||||
'w123456' within iD.
|
||||
|
||||
iD entities are *immutable*: once constructed, an `Entity` object cannot
|
||||
change. Tags cannot be updated; nodes cannot be added or removed from ways,
|
||||
and so on. Immutability makes it easier to reason about the behavior of an
|
||||
entity: if your code has a reference to one, it is safe to store it and use it
|
||||
later, knowing that it cannot have been changed outside of your control. It
|
||||
also makes it possible to implement the entity graph (described below) as an
|
||||
efficient [persistent data
|
||||
structure](http://en.wikipedia.org/wiki/Persistent_data_structure). But
|
||||
obviously, iD is an editor, and must allow entities to change somehow. The
|
||||
solution is that all edits produce new copies of anything that changes. At the
|
||||
entity level, this takes the form of methods such as `iD.Node#move`, which
|
||||
returns a new node object that has the same ID and tags as the original, but a
|
||||
different coordinate. More generically, `iD.Entity#update` returns a new
|
||||
entity of the same type and ID as the original but with specified properties
|
||||
such as `nodes`, `tags`, or `members` replaced.
|
||||
|
||||
Entities are related to one another: ways have many nodes and relations have
|
||||
many members. In order to render a map of a certain area, iD needs a
|
||||
datastructure to hold all the entities in that area and traverse these
|
||||
relationships. `iD.Graph` provides this functionality. The core of a graph is
|
||||
a map between IDs and the associated entities; given an ID, the graph can give
|
||||
you the entity. Like entities, a graph is immutable: adding, replacing, or
|
||||
removing an entity produces a new graph, and the original is unchanged.
|
||||
Because entities are immutable, the original and new graphs can share
|
||||
references to entities that have not changed, keeping memory use to a minimum.
|
||||
If you are familiar with how git works internally, this persistent data
|
||||
structure approach is very similar.
|
||||
|
||||
The final component of the core is comprised of `iD.History` and
|
||||
`iD.Difference`, which track the changes made in an editing session and
|
||||
provide undo/redo capabilities. Here, the immutable nature of the core types
|
||||
really pays off: the history is a simple stack of graphs, each representing
|
||||
the state of the data at a particular point in editing. The graph at the top
|
||||
of the stack is the current state, off which all rendering is based. To undo
|
||||
the last change, this graph is popped off the stack, and the map is
|
||||
re-rendered based on the new top of the stack. Contrast this to a mutable
|
||||
graph as used in JOSM and Potlatch: every command that changes the graph must
|
||||
implement an equal and opposite undo command that restores the graph to the
|
||||
previous state.
|
||||
|
||||
## Actions
|
||||
|
||||
In iD, an _action_ is a function that accepts a graph as input and returns a
|
||||
modified graph as output. Actions typically need other inputs as well; for
|
||||
example, `iD.actions.DeleteNode` also requires the ID of a node to delete. The
|
||||
additional input is passed to the action's constructor:
|
||||
|
||||
``` var action = iD.actions.DeleteNode('n123456'); // construct the action var
|
||||
newGraph = action(oldGraph); // apply the action ```
|
||||
|
||||
iD provides actions for all the typical things an editor needs to do: add a
|
||||
new entity, split a way in two, connect the vertices of two ways together, and
|
||||
so on. In addition to performing the basic work needed to accomplish these
|
||||
things, an action typically contains a significant amount of logic for keeping
|
||||
the relationships between entities logical and consistent. For example, an
|
||||
action as apparently simple as `DeleteNode`, in addition to removing the node
|
||||
from the graph, needs to do two other things: remove the node from any ways in
|
||||
which it is a member (which in turn requires deleting parent ways that are
|
||||
left with just a single node), and removing it from any relations of which it
|
||||
is a member.
|
||||
|
||||
As you can imagine, implementing all these details requires an expert
|
||||
knowledge of the OpenStreetMap data model. It is our hope that JavaScript
|
||||
based tools for OpenStreetMap can reuse the implementations provided by iD in
|
||||
other contexts, significantly reducing the work necessary to create a robust
|
||||
tool.
|
||||
|
||||
## Modes
|
||||
|
||||
With _modes_, we shift gears from abstract data types and algorithms to the
|
||||
parts of the architecture that implement the user interface for iD. Modes are
|
||||
manifested in the interface by the four buttons at the top left:
|
||||
|
||||

|
||||
|
||||
The modality of existing OSM editors runs the gamut from Potlatch 2, which is
|
||||
almost entirely modeless, to JOSM, which sports half a dozen modes out of the
|
||||
box and has many more provided by plugins. iD seeks a middle ground: too few
|
||||
modes can leave new users unsure where to start, while too many can be
|
||||
overwhelming.
|
||||
|
||||
iD's user-facing modes consist of a base "Browse" mode, in which you can move
|
||||
around the map and select and edit entities, and three geometrically-oriented
|
||||
drawing modes: Point, Line, and Area. In the code, these are broken down a
|
||||
little bit more. There are separate modes for when an entity is selected
|
||||
(`iD.modes.Select`) versus when nothing is selected (`iD.modes.Browse`), and
|
||||
each of the geometric modes is split into one mode for starting to draw an
|
||||
object and one mode for continuing an existing object (with the exception of
|
||||
`iD.modes.AddPoint`, which is a single-step operation for obvious reasons).
|
||||
|
||||
The code interface for each mode consists of a pair of methods: `enter` and
|
||||
`exit`. In the `enter` method, a mode sets up all the behavior that should be
|
||||
present when that mode is active. This typically means binding callbacks to
|
||||
DOM events that will be triggered on map elements, installing keybindings, and
|
||||
showing certain parts of the interface like the inspector in `Select` mode.
|
||||
The `exit` mode does the opposite, removing the behavior installed by the
|
||||
`enter` method. Together the two methods ensure that modes are self-contained
|
||||
and exclusive: each mode knows exactly the behavior that is specific to that
|
||||
mode, and exactly one mode's behavior is active at any time.
|
||||
|
||||
## Behavior
|
||||
|
||||
Certain behaviors are common to more than one mode. For example, iD indicates
|
||||
interactive map elements by drawing a halo around them when you hover over
|
||||
them, and this behavior is common to both the browse and draw modes. Instead
|
||||
of duplicating the code to implement this behavior in all these modes, we
|
||||
extract it to `iD.behavior.Hover`.
|
||||
|
||||
_Behaviors_ take their inspiration from [d3's
|
||||
behaviors](https://github.com/mbostock/d3/wiki/Behaviors). Like d3's `zoom`
|
||||
and `drag`, each iD behavior is a function that takes as input a d3 selection
|
||||
(assumed to consist of a single element) and installs the DOM event bindings
|
||||
necessary to implement the behavior. The `Hover` behavior, for example,
|
||||
installs bindings for the `mouseover` and `mouseout` events that add and
|
||||
remove a `hover` class from map elements.
|
||||
|
||||
Because certain behaviors are appropriate to some but not all modes, we need
|
||||
the ability to remove a behavior when entering a mode where it is not
|
||||
appropriate. (This is functionality [not yet
|
||||
provided](https://github.com/mbostock/d3/issues/894) by d3's own behaviors.)
|
||||
Each behavior implements an `off` function that "uninstalls" the behavior.
|
||||
This is very similar to the `exit` method of a mode, and in fact many modes do
|
||||
little else but uninstall behaviors in their `exit` methods.
|
||||
|
||||
## Operations
|
||||
|
||||
_Operations_ wrap actions, providing their user-interface: tooltips, key
|
||||
bindings, and the logic that determines whether an action can be validly
|
||||
performed given the current map state and selection. Each operation is
|
||||
constructed with the list of IDs which are currently selected and a `context`
|
||||
object which provides access to the history and other important parts of iD's
|
||||
internal state. After being constructed, an operation can be queried as to
|
||||
whether or not it should be made available (i.e., show up in the context menu)
|
||||
and if so, if it should be enabled.
|
||||
|
||||

|
||||
|
||||
We make a distinction between availability and enabled state for the sake of
|
||||
learnability: most operations are available so long as an entity of the
|
||||
appropriate type is selected. Even if it remains disabled for other reasons
|
||||
(e.g. because you can't split a way on its start or end vertex), a new user
|
||||
can still learn that "this is something I can do to this type of thing", and a
|
||||
tooltip can provide an explanation of what that operation does and the
|
||||
conditions under which it is enabled.
|
||||
|
||||
To execute an operation, call it as a function, with no arguments. The typical
|
||||
operation will perform the appropriate action, creating a new undo state in
|
||||
the history, and then enter the appropriate mode. For example,
|
||||
`iD.operations.Split` performs `iD.actions.Split`, then enters
|
||||
`iD.modes.Select` with the resulting ways selected.
|
||||
|
||||
## Rendering and other UI
|
||||
@@ -0,0 +1,101 @@
|
||||
# Contributing to iD
|
||||
|
||||
Thinking of contributing to iD? High five! Here are some basics for our habits
|
||||
so that you can write code that fits in perfectly.
|
||||
|
||||
## Reporting Issues
|
||||
|
||||
We'd love to hear what you think about iD, about any specific problems or
|
||||
concerns you have. Here's a quick list of things to consider:
|
||||
|
||||
Please [search for your issue before filing it: many bugs and improvements have already been reported](https://github.com/systemed/iD/issues/search?q=)
|
||||
|
||||
To report a bug:
|
||||
|
||||
* Write specifically what browser (type and version, like Firefox 22), OS, and browser extensions you have installed
|
||||
* Write steps to replicate the error: when did it happen? What did you expect to happen? What happened instead?
|
||||
* Please keep bug reports professional and straightforward: trust us, we share your dismay at software breaking.
|
||||
* If you can, [enable web developer extensions](http://macwright.org/enable-web-developer-extensions/) and report the
|
||||
Javascript error message.
|
||||
|
||||
When in doubt, be over-descriptive of the bug and how you discovered it.
|
||||
|
||||
To request a feature:
|
||||
|
||||
* If the feature is available in some other software (like Potlatch), link to that software and the implementation.
|
||||
We care about prior art.
|
||||
* Understand that iD is meant to be a simple editor and doesn't aim to be
|
||||
as complete or complicated as JOSM or similar.
|
||||
|
||||
## Javascript
|
||||
|
||||
We use the [Airbnb style for Javascript](https://github.com/airbnb/javascript) with
|
||||
only one difference:
|
||||
|
||||
**4 space soft tabs always for Javascript, not 2.**
|
||||
|
||||
No aligned `=`, no aligned arguments, spaces are either indents or the 1
|
||||
space between expressions. No hard tabs, ever.
|
||||
|
||||
Javascript code should pass through [JSHint](http://www.jshint.com/) with no
|
||||
warnings.
|
||||
|
||||
## HTML
|
||||
|
||||
There isn't much HTML in iD, but what there is is similar to JS: 4 spaces
|
||||
always, indented by the level of the tree:
|
||||
|
||||
```html
|
||||
<div>
|
||||
<div></div>
|
||||
</div>
|
||||
```
|
||||
|
||||
## CSS
|
||||
|
||||
Just like HTML and Javascript, 4 space soft tabs always.
|
||||
|
||||
```css
|
||||
.radial-menu-tooltip {
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
}
|
||||
```
|
||||
|
||||
We write vanilla CSS with no preprocessing step. Since iD targets modern browsers,
|
||||
feel free to use newer features wisely.
|
||||
|
||||
## Tests
|
||||
|
||||
Test your code and make sure it passes. Our testing harness requires [node.js](http://nodejs.org/)
|
||||
and a few modules:
|
||||
|
||||
1. [Install node.js](http://nodejs.org/) - 'Install' will download a package for your OS
|
||||
2. Go to the directory where you have checked out `iD`
|
||||
3. Run `npm install`
|
||||
4. Run `npm test` to see whether your tests pass or fail.
|
||||
|
||||
## Licensing
|
||||
|
||||
iD is under the [WTFPL](http://www.wtfpl.net/). Some of the libraries it uses
|
||||
are under different licenses. If you're contributing to iD, you're contributing
|
||||
WTFPL code.
|
||||
|
||||
## Submitting Changes
|
||||
|
||||
Let's say that you've thought of a great improvement to iD - a change that
|
||||
turns everything red (please do not do this, we like colors other than red).
|
||||
|
||||
In your local copy, make a branch for this change:
|
||||
|
||||
git checkout -b make-red
|
||||
|
||||
Make your changes to source files. By source files we mean the files in `js/`.
|
||||
the `iD.js` and `iD.min.js` files in this project are autogenerated - don't edit
|
||||
them.
|
||||
|
||||
So let's say you've changed `js/ui/confirm.js`.
|
||||
|
||||
1. Run `jshint js/id` to make sure your code is clean
|
||||
2. Run tests with `npm test`
|
||||
3. Commit your changes with an informative commit message
|
||||
4. [Submit a pull request](https://help.github.com/articles/using-pull-requests) to the `systemed/iD` project.
|
||||
@@ -23,12 +23,16 @@ all: \
|
||||
js/lib/jxon.js \
|
||||
js/lib/lodash.js \
|
||||
js/lib/ohauth.js \
|
||||
js/lib/rtree.js \
|
||||
js/lib/sha.js \
|
||||
js/id/start.js \
|
||||
js/id/id.js \
|
||||
js/id/connection.js \
|
||||
js/id/oauth.js \
|
||||
js/id/services/*.js \
|
||||
data/data.js \
|
||||
data/imagery.js \
|
||||
data/deprecated.js \
|
||||
js/id/util.js \
|
||||
js/id/geo.js \
|
||||
js/id/geo/*.js \
|
||||
@@ -40,14 +44,16 @@ all: \
|
||||
js/id/modes/*.js \
|
||||
js/id/operations.js \
|
||||
js/id/operations/*.js \
|
||||
js/id/controller/*.js \
|
||||
js/id/graph/*.js \
|
||||
js/id/core/*.js \
|
||||
js/id/renderer/*.js \
|
||||
js/id/svg.js \
|
||||
js/id/svg/*.js \
|
||||
js/id/ui.js \
|
||||
js/id/ui/*.js \
|
||||
js/id/end.js
|
||||
js/id/validate.js \
|
||||
js/id/end.js \
|
||||
js/lib/locale.js \
|
||||
locale/*.js
|
||||
|
||||
iD.js: Makefile
|
||||
@rm -f $@
|
||||
|
||||
@@ -2,31 +2,30 @@
|
||||
|
||||
[](https://travis-ci.org/systemed/iD)
|
||||
|
||||
[](http://geowiki.com/iD/)
|
||||
|
||||
[Try the online demo of the most recent code.](http://geowiki.com/iD/) and
|
||||
[open issues for bugs and ideas!](https://github.com/systemed/iD/issues)
|
||||
[](http://ideditor.com/)
|
||||
|
||||
## Basics
|
||||
|
||||
* iD is a JavaScript [OpenStreetMap](http://www.openstreetmap.org/) editor.
|
||||
* It's intentionally simple. It lets you do the most basic tasks while
|
||||
not breaking other people's data.
|
||||
* We support modern browsers. Data is rendered with [d3](http://d3js.org/).
|
||||
* It supports modern browsers. Data is rendered with [d3](http://d3js.org/).
|
||||
|
||||
## Participate!
|
||||
|
||||
* [Read NOTES.md, our ongoing dev journal](https://github.com/systemed/iD/blob/master/NOTES.md)
|
||||
* Fork this project. We eagerly accept pull requests.
|
||||
* See [open issues in the issue tracker if you're looking for something to do](https://github.com/systemed/iD/issues?state=open)
|
||||
* [Try out the latest stable release](http://geowiki.com/iD/)
|
||||
* [Read up on Contributing and the code style of iD](CONTRIBUTING.md)
|
||||
* See [open issues in the issue tracker](https://github.com/systemed/iD/issues?state=open) if you're looking for something to do
|
||||
|
||||
To run the code locally, just fork this project and run it from a local webserver.
|
||||
With a Mac, you can enable Web Sharing and drop this in your website directory.
|
||||
## Installation
|
||||
|
||||
If you have Python handy, just `cd` into `iD` and run
|
||||
To run the current development version, fork this project and serve it locally.
|
||||
If you have Python handy, just `cd` into the project root directory and run
|
||||
|
||||
python -m SimpleHTTPServer
|
||||
|
||||
Or, with a Mac, you can enable Web Sharing and clone iD into your website directory.
|
||||
|
||||
Come on in, the water's lovely. More help? Ping RichardF, tmcw, or jfire on IRC
|
||||
(`irc.oftc.net`, in `#osm-dev` or `#osm`), on the OSM mailing lists or at
|
||||
richard@systemeD.net.
|
||||
|
||||
@@ -0,0 +1,169 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset='utf-8'>
|
||||
<title>iD</title>
|
||||
<link rel='stylesheet' href='css/reset.css'>
|
||||
<link rel='stylesheet' href='css/map.css'>
|
||||
<link rel='stylesheet' href='css/app.css'>
|
||||
|
||||
<!-- mobile devices -->
|
||||
<meta name='viewport' content='initial-scale=1.0 maximum-scale=1.0'>
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
||||
|
||||
<script src='js/lib/lodash.js'></script>
|
||||
<script src='js/lib/d3.v3.js'></script>
|
||||
<script src='js/lib/sha.js'></script>
|
||||
<script src='js/lib/ohauth.js'></script>
|
||||
<script src='js/lib/jxon.js'></script>
|
||||
<script src='js/lib/d3.typeahead.js'></script>
|
||||
<script src='js/lib/d3.combobox.js'></script>
|
||||
<script src='js/lib/d3.geo.tile.js'></script>
|
||||
<script src='js/lib/d3.size.js'></script>
|
||||
<script src='js/lib/d3.trigger.js'></script>
|
||||
<script src='js/lib/d3.keybinding.js'></script>
|
||||
<script src='js/lib/d3.tail.js'></script>
|
||||
<script src='js/lib/d3-compat.js'></script>
|
||||
<script src='js/lib/bootstrap-tooltip.js'></script>
|
||||
<script src='js/lib/rtree.js'></script>
|
||||
|
||||
<script src='js/id/id.js'></script>
|
||||
<script src='js/id/util.js'></script>
|
||||
<script src='js/id/oauth.js'></script>
|
||||
<script src='js/id/services/taginfo.js'></script>
|
||||
|
||||
<script src="js/id/geo.js"></script>
|
||||
<script src="js/id/geo/extent.js"></script>
|
||||
|
||||
<script src='js/id/renderer/background.js'></script>
|
||||
<script src='js/id/renderer/background_source.js'></script>
|
||||
<script src='js/id/renderer/map.js'></script>
|
||||
<script src='js/id/renderer/hash.js'></script>
|
||||
|
||||
<script src="js/id/svg.js"></script>
|
||||
<script src="js/id/svg/areas.js"></script>
|
||||
<script src="js/id/svg/lines.js"></script>
|
||||
<script src="js/id/svg/member_classes.js"></script>
|
||||
<script src="js/id/svg/midpoints.js"></script>
|
||||
<script src="js/id/svg/multipolygons.js"></script>
|
||||
<script src="js/id/svg/points.js"></script>
|
||||
<script src="js/id/svg/surface.js"></script>
|
||||
<script src="js/id/svg/tag_classes.js"></script>
|
||||
<script src="js/id/svg/vertices.js"></script>
|
||||
<script src="js/id/svg/labels.js"></script>
|
||||
|
||||
<script src="js/id/ui.js"></script>
|
||||
<script src='js/id/ui/radial_menu.js'></script>
|
||||
<script src='js/id/ui/inspector.js'></script>
|
||||
<script src='js/id/ui/modal.js'></script>
|
||||
<script src='js/id/ui/confirm.js'></script>
|
||||
<script src='js/id/ui/commit.js'></script>
|
||||
<script src='js/id/ui/success.js'></script>
|
||||
<script src='js/id/ui/loading.js'></script>
|
||||
<script src='js/id/ui/account.js'></script>
|
||||
<script src='js/id/ui/layerswitcher.js'></script>
|
||||
<script src='js/id/ui/contributors.js'></script>
|
||||
<script src='js/id/ui/geocoder.js'></script>
|
||||
<script src='js/id/ui/geolocate.js'></script>
|
||||
<script src='js/id/ui/notice.js'></script>
|
||||
<script src='js/id/ui/flash.js'></script>
|
||||
<script src='js/id/ui/save.js'></script>
|
||||
<script src='js/id/ui/tag_reference.js'></script>
|
||||
<script src='js/id/ui/key_reference.js'></script>
|
||||
|
||||
<script src='js/id/actions.js'></script>
|
||||
<script src="js/id/actions/add_midpoint.js"></script>
|
||||
<script src='js/id/actions/add_entity.js'></script>
|
||||
<script src='js/id/actions/add_vertex.js'></script>
|
||||
<script src='js/id/actions/change_tags.js'></script>
|
||||
<script src='js/id/actions/delete_node.js'></script>
|
||||
<script src="js/id/actions/delete_way.js"></script>
|
||||
<script src='js/id/actions/disconnect.js'></script>
|
||||
<script src='js/id/actions/move_node.js'></script>
|
||||
<script src='js/id/actions/move_way.js'></script>
|
||||
<script src='js/id/actions/circularize.js'></script>
|
||||
<script src='js/id/actions/noop.js'></script>
|
||||
<script src='js/id/actions/reverse.js'></script>
|
||||
<script src='js/id/actions/split.js'></script>
|
||||
|
||||
<script src='js/id/behavior.js'></script>
|
||||
<script src='js/id/behavior/add_way.js'></script>
|
||||
<script src='js/id/behavior/drag.js'></script>
|
||||
<script src='js/id/behavior/drag_node.js'></script>
|
||||
<script src='js/id/behavior/draw.js'></script>
|
||||
<script src='js/id/behavior/draw_way.js'></script>
|
||||
<script src='js/id/behavior/hover.js'></script>
|
||||
<script src='js/id/behavior/select.js'></script>
|
||||
|
||||
<script src='js/id/modes.js'></script>
|
||||
<script src='js/id/modes/add_area.js'></script>
|
||||
<script src='js/id/modes/add_point.js'></script>
|
||||
<script src='js/id/modes/add_line.js'></script>
|
||||
<script src='js/id/modes/browse.js'></script>
|
||||
<script src='js/id/modes/draw_area.js'></script>
|
||||
<script src='js/id/modes/draw_line.js'></script>
|
||||
<script src='js/id/modes/move_way.js'></script>
|
||||
<script src='js/id/modes/select.js'></script>
|
||||
|
||||
<script src='js/id/operations.js'></script>
|
||||
<script src='js/id/operations/circularize.js'></script>
|
||||
<script src='js/id/operations/delete.js'></script>
|
||||
<script src='js/id/operations/move.js'></script>
|
||||
<script src='js/id/operations/reverse.js'></script>
|
||||
<script src='js/id/operations/split.js'></script>
|
||||
<script src='js/id/operations/unjoin.js'></script>
|
||||
|
||||
<script src='js/id/core/entity.js'></script>
|
||||
<script src='js/id/core/graph.js'></script>
|
||||
<script src='js/id/core/history.js'></script>
|
||||
<script src='js/id/core/node.js'></script>
|
||||
<script src='js/id/core/relation.js'></script>
|
||||
<script src='js/id/core/way.js'></script>
|
||||
|
||||
<script src='js/id/controller.js'></script>
|
||||
<script src='js/id/validate.js'></script>
|
||||
<script src='js/id/connection.js'></script>
|
||||
|
||||
<script src='locale/locale.js'></script>
|
||||
<script src='locale/en.js'></script>
|
||||
<style>
|
||||
body {
|
||||
margin:20px;
|
||||
}
|
||||
#foo, #bar {
|
||||
position:relative;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id='foo'><input /></div>
|
||||
<div id='bar'><input /></div>
|
||||
<div id="iD"></div><script>
|
||||
var options = d3.range(0, 50).map(function(i) {
|
||||
return {
|
||||
value: i * 10,
|
||||
title: i * 10
|
||||
};
|
||||
});
|
||||
d3.select('#foo').call(d3.combobox()
|
||||
.data(function(selection, cb) {
|
||||
cb(options);
|
||||
}));
|
||||
d3.select('#bar').call(d3.combobox()
|
||||
.data(function(selection, cb) {
|
||||
cb(options);
|
||||
}));
|
||||
</script></body>
|
||||
|
||||
<script type="text/javascript">
|
||||
var _gaq = _gaq || [];
|
||||
_gaq.push(['_setAccount', 'UA-38039653-2']);
|
||||
_gaq.push(['_trackPageview']);
|
||||
(function() {
|
||||
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
|
||||
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
|
||||
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
|
||||
})();
|
||||
</script>
|
||||
</html>
|
||||
@@ -19,10 +19,11 @@ body {
|
||||
}
|
||||
|
||||
.limiter {
|
||||
position: relative;
|
||||
max-width: 1200px;
|
||||
}
|
||||
|
||||
div, textarea, input, span, ul, li, ol, a, button {
|
||||
div, textarea, input, form, span, ul, li, ol, a, button {
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
@@ -33,6 +34,7 @@ div, textarea, input, span, ul, li, ol, a, button {
|
||||
a, button, input, textarea {
|
||||
-webkit-tap-highlight-color:rgba(0,0,0,0);
|
||||
-webkit-touch-callout:none;
|
||||
cursor:url(../img/cursor-pointer.png) 6 1, auto;
|
||||
}
|
||||
|
||||
h2 {
|
||||
@@ -92,7 +94,6 @@ a:hover {
|
||||
color:#597be7;
|
||||
}
|
||||
|
||||
|
||||
textarea,
|
||||
input[type=text] {
|
||||
background-color: white;
|
||||
@@ -120,7 +121,7 @@ input[type=text]:focus {
|
||||
}
|
||||
|
||||
input[type=text] {
|
||||
padding:4px 10px;
|
||||
padding:5px 10px;
|
||||
height:30px;
|
||||
resize: none;
|
||||
}
|
||||
@@ -181,11 +182,14 @@ ul li { list-style: none;}
|
||||
ul.toggle-list li a {
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
padding: 10px;
|
||||
border-top: 1px solid white;
|
||||
padding: 5px 10px;
|
||||
display:block;
|
||||
border-top: 1px solid rgba(0, 0, 0, .5);
|
||||
border-top: 1px solid #ccc;
|
||||
white-space:nowrap;
|
||||
text-overflow:ellipsis;
|
||||
overflow:hidden;
|
||||
}
|
||||
ul.toggle-list li a:hover { background-color: #ececec;}
|
||||
|
||||
ul.toggle-list .icon {
|
||||
float: left;
|
||||
@@ -220,7 +224,7 @@ ul.link-list li:last-child {
|
||||
|
||||
.fillD {
|
||||
background:rgba(0,0,0,.8);
|
||||
color: #a9a9a9;
|
||||
color: #6C6C6C;
|
||||
}
|
||||
|
||||
|
||||
@@ -246,7 +250,6 @@ form.hide {
|
||||
|
||||
button {
|
||||
line-height:20px;
|
||||
position: relative;
|
||||
border:0;
|
||||
color:#222;
|
||||
background: white;
|
||||
@@ -254,7 +257,6 @@ button {
|
||||
font-size:12px;
|
||||
display: inline-block;
|
||||
height:40px;
|
||||
cursor:url(../img/cursor-pointer.png) 6 1, auto;
|
||||
border-radius:4px;
|
||||
-webkit-transition: background 100ms;
|
||||
-moz-transition: background 100ms;
|
||||
@@ -265,16 +267,17 @@ button:hover {
|
||||
background-color: #ececec;
|
||||
}
|
||||
|
||||
button.col3:hover {
|
||||
background: #bde5aa;
|
||||
}
|
||||
|
||||
button.active {
|
||||
cursor:url(../img/cursor-pointing.png) 6 1, auto;
|
||||
}
|
||||
|
||||
button.active:not([disabled]) {
|
||||
background: #6bc641;
|
||||
button.disabled {
|
||||
background: #6c6c6c;
|
||||
cursor: auto;
|
||||
}
|
||||
|
||||
button.active:not([disabled]):not(.disabled) {
|
||||
background: #7092ff;
|
||||
}
|
||||
|
||||
button.minor {
|
||||
@@ -283,11 +286,11 @@ button.minor {
|
||||
width: 20px;
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
background-color: transparent;
|
||||
background: rgba(0,0,0,.5);
|
||||
}
|
||||
|
||||
button.minor:hover {
|
||||
background: white;
|
||||
background: #222;
|
||||
}
|
||||
|
||||
button.centered {
|
||||
@@ -319,6 +322,8 @@ button.centered {
|
||||
border-radius:0 4px 4px 0;
|
||||
}
|
||||
|
||||
button.browse .label { display: none;}
|
||||
|
||||
button.action {
|
||||
background: #7092ff;
|
||||
}
|
||||
@@ -344,16 +349,15 @@ button.save .count {
|
||||
button.save.has-count .count {
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: 115%;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
background: rgba(255,255,255,.5);
|
||||
top: 5px;
|
||||
background: rgba(255, 255, 255, .5);
|
||||
color: #333;
|
||||
padding: 10px;
|
||||
height: 30px;
|
||||
line-height: 12px;
|
||||
border-radius: 4px;
|
||||
margin: auto;
|
||||
margin-left: 8.3333%;
|
||||
}
|
||||
|
||||
button.save.has-count .count::before {
|
||||
@@ -416,12 +420,12 @@ button[disabled] .label {
|
||||
}
|
||||
|
||||
/* Definitions for every icon */
|
||||
.icon.browse { background-position: 0px -20px;}
|
||||
.icon.add-point { background-position: -20px -20px;}
|
||||
.icon.add-line { background-position: -40px -20px;}
|
||||
.icon.add-area { background-position: -60px -20px;}
|
||||
.icon.undo { background-position: -80px -20px;}
|
||||
.icon.redo { background-position: -100px -20px;}
|
||||
.icon.browse { background-position: 0px 0px;}
|
||||
.icon.add-point { background-position: -20px 0px;}
|
||||
.icon.add-line { background-position: -40px 0px;}
|
||||
.icon.add-area { background-position: -60px 0px;}
|
||||
.icon.undo { background-position: -80px 0px;}
|
||||
.icon.redo { background-position: -100px 0px;}
|
||||
|
||||
.icon.apply { background-position: -120px 0px;}
|
||||
.icon.save { background-position: -140px 0px;}
|
||||
@@ -431,6 +435,7 @@ button[disabled] .label {
|
||||
.icon.inspect { background-position: -220px 0px;}
|
||||
.icon.zoom-in { background-position: -240px 0px;}
|
||||
.icon.zoom-out { background-position: -260px 0px;}
|
||||
.icon.plus { background-position: -240px 0px;}
|
||||
.icon.geocode { background-position: -280px 0px;}
|
||||
.icon.layers { background-position: -300px 0px;}
|
||||
.icon.avatar { background-position: -320px 0px;}
|
||||
@@ -438,16 +443,7 @@ button[disabled] .label {
|
||||
.icon.geolocate { background-position: -360px 0px;}
|
||||
.icon.warning { background-position: -380px 0px;}
|
||||
|
||||
.icon.close-modal{ background-position: -200px -40px;}
|
||||
|
||||
.icon.invert.zoom-in { background-position: -240px -40px;}
|
||||
|
||||
.icon.browse { background-position: 0px 0px;}
|
||||
.icon.add-point { background-position: -20px 0px;}
|
||||
.icon.add-line { background-position: -40px 0px;}
|
||||
.icon.add-area { background-position: -60px 0px;}
|
||||
.icon.undo { background-position: -80px 0px;}
|
||||
.icon.redo { background-position: -100px 0px;}
|
||||
.icon.close-modal { background-position: -200px 0px;}
|
||||
|
||||
.fillD .icon.avatar { background-position: -320px -20px;}
|
||||
.fillD .icon.nearby { background-position: -340px -20px;}
|
||||
@@ -456,8 +452,8 @@ button[disabled] .icon.browse { background-position: 0px -40px;}
|
||||
button[disabled] .icon.add-point { background-position: -20px -40px;}
|
||||
button[disabled] .icon.add-line { background-position: -40px -40px;}
|
||||
button[disabled] .icon.add-area { background-position: -60px -40px;}
|
||||
button[disabled] .icon.undo { background-position: -80px -40px;}
|
||||
button[disabled] .icon.redo { background-position: -100px -40px;}
|
||||
button.disabled .icon.undo { background-position: -80px -40px;}
|
||||
button.disabled .icon.redo { background-position: -100px -40px;}
|
||||
button[disabled] .apply.icon { background-position: -120px -40px;}
|
||||
button[disabled] .save.icon { background-position: -140px -40px;}
|
||||
button[disabled] .close.icon { background-position: -160px -40px;}
|
||||
@@ -471,13 +467,24 @@ button[disabled] .icon.layers { background-position: -300px -40px;}
|
||||
button[disabled] .icon.avatar { background-position: -320px -40px;}
|
||||
button[disabled] .icon.nearby { background-position: -340px -40px;}
|
||||
|
||||
.icon.big-line { background-position: 0px -80px;}
|
||||
.icon.big-point { background-position: -40px -80px;}
|
||||
.icon.big-area { background-position: -80px -80px;}
|
||||
.icon.big-vertex { background-position: -120px -80px;}
|
||||
.icon.big-inspect { background-position: -160px -80px;}
|
||||
.icon.big-line { background-position: 0px -80px;}
|
||||
.icon.big-point { background-position: -40px -80px;}
|
||||
.icon.big-area { background-position: -80px -80px;}
|
||||
.icon.big-vertex { background-position: -120px -80px;}
|
||||
.icon.big-inspect { background-position: -160px -80px;}
|
||||
.icon.big-relation { background-position: -200px -80px;}
|
||||
|
||||
.icon-operation-delete { background-position: 0px -140px;}
|
||||
.icon-operation-circularize { background-position: -20px -140px;}
|
||||
.icon-operation-straighten { background-position: -40px -140px;}
|
||||
.icon-operation-split { background-position: -60px -140px;}
|
||||
.icon-operation-disconnect { background-position: -80px -140px;}
|
||||
.icon-operation-reverse { background-position: -100px -140px;}
|
||||
.icon-operation-move { background-position: -120px -140px;}
|
||||
.icon-operation-merge { background-position: -140px -140px;}
|
||||
.icon-operation-orthogonalize { background-position: -160px -140px;}
|
||||
|
||||
|
||||
/* Toggle icon is special */
|
||||
.toggle.icon { background-position: 0px -180px;}
|
||||
a:hover .toggle.icon { background-position: -20px -180px;}
|
||||
@@ -609,19 +616,20 @@ a.selected:hover .toggle.icon { background-position: -40px -180px;}
|
||||
width: 60%;
|
||||
}
|
||||
|
||||
.inspector-inner .add-tag-row {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.inspector-inner .add-tag-row button {
|
||||
.inspector-inner .add-tag {
|
||||
width: 20%;
|
||||
height: 30px;
|
||||
border-top: 0;
|
||||
background: rgba(0,0,0,.5);
|
||||
border-radius: 0 0 4px 4px;
|
||||
}
|
||||
|
||||
.inspector-inner .add-tag {
|
||||
width: 40%;
|
||||
height: 30px;
|
||||
border: 1px solid #ccc;
|
||||
border-top: 0;
|
||||
.inspector-inner .add-tag:hover {
|
||||
background: rgba(0,0,0,.8);
|
||||
}
|
||||
|
||||
.inspector-inner .add-tag .label {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Map Controls */
|
||||
@@ -631,25 +639,27 @@ a.selected:hover .toggle.icon { background-position: -40px -180px;}
|
||||
position:absolute;
|
||||
}
|
||||
|
||||
.map-control button {
|
||||
width: 40px;
|
||||
background: rgba(0,0,0,.8);
|
||||
border-radius: 0 4px 4px 0;
|
||||
.map-control > button {
|
||||
width: 30px;
|
||||
background: rgba(0,0,0,.5);
|
||||
border-radius: 0;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 1);
|
||||
}
|
||||
|
||||
.map-control button:hover {
|
||||
background: rgba(0, 0, 0, .9);
|
||||
.map-control > button:hover {
|
||||
background: rgba(0, 0, 0, .8);
|
||||
}
|
||||
|
||||
.map-control button.active:hover {
|
||||
background: #6bc641;
|
||||
.map-control > button.active:hover {
|
||||
background: #7092ff;
|
||||
}
|
||||
|
||||
.map-overlay {
|
||||
width: 150px;
|
||||
position:absolute;
|
||||
left:50px;
|
||||
top:0;
|
||||
right: 75%;
|
||||
max-width: 260px;
|
||||
min-width: 210px;
|
||||
position: fixed;
|
||||
left: 40px;
|
||||
display: block;
|
||||
border-radius: 4px;
|
||||
}
|
||||
@@ -658,43 +668,117 @@ a.selected:hover .toggle.icon { background-position: -40px -180px;}
|
||||
|
||||
.zoombuttons {
|
||||
top:70px;
|
||||
width: 40px;
|
||||
width: 30px;
|
||||
}
|
||||
|
||||
.zoombuttons button.zoom-in {
|
||||
border-radius:0 4px 0 0;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, .5);
|
||||
}
|
||||
|
||||
.zoombuttons button.zoom-out {
|
||||
border-top:0;
|
||||
border-radius:0 0 4px 0;
|
||||
}
|
||||
|
||||
/* Layer Switcher */
|
||||
|
||||
.layerswitcher-control {
|
||||
top:210px;
|
||||
top:190px;
|
||||
}
|
||||
|
||||
.nudge-container {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.layerswitcher-control .adjustments button {
|
||||
opacity:0.5;
|
||||
height:20px;
|
||||
height:30px;
|
||||
font-size:10px;
|
||||
font-weight:normal;
|
||||
padding:0 5px 3px 5px;
|
||||
background: white;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 0;
|
||||
text-transform: uppercase;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.layerswitcher-control .adjustments button:hover {
|
||||
opacity: 1;
|
||||
background:#ececec;
|
||||
}
|
||||
|
||||
.layerswitcher-control .alignment-toggle {
|
||||
display: block;
|
||||
padding-left: 12px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.layerswitcher-control .alignment-toggle:before {
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
height: 0;
|
||||
width: 0;
|
||||
left: 0;
|
||||
top: 4px;
|
||||
border-top: 4px solid transparent;
|
||||
border-bottom: 4px solid transparent;
|
||||
border-left: 8px solid #7092ff;
|
||||
}
|
||||
|
||||
.layerswitcher-control .alignment-toggle.expanded:before {
|
||||
border-top: 8px solid #7092ff;
|
||||
border-bottom: 0;
|
||||
border-right: 4px solid transparent;
|
||||
border-left: 4px solid transparent;
|
||||
|
||||
}
|
||||
|
||||
.layerswitcher-control .nudge {
|
||||
width:20px;
|
||||
margin-right:2px;
|
||||
text-indent: -9999px;
|
||||
overflow: hidden;
|
||||
width:16.6666%;
|
||||
border-radius: 0;
|
||||
border-right: 1px solid rgba(0, 0, 0, .5);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.layerswitcher-control .nudge::after {
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
margin: auto;
|
||||
left: 0; right: 0; top: 0; bottom: 0;
|
||||
height: 0;
|
||||
width: 0;
|
||||
}
|
||||
|
||||
.layerswitcher-control .nudge.left::after {
|
||||
border-top: 5px solid transparent;
|
||||
border-bottom: 5px solid transparent;
|
||||
border-left: 5px solid #222;
|
||||
}
|
||||
|
||||
.layerswitcher-control .nudge.right::after {
|
||||
border-top: 5px solid transparent;
|
||||
border-bottom: 5px solid transparent;
|
||||
border-right: 5px solid #222;
|
||||
}
|
||||
|
||||
.layerswitcher-control .nudge.top::after {
|
||||
border-right: 5px solid transparent;
|
||||
border-left: 5px solid transparent;
|
||||
border-bottom: 5px solid #222;
|
||||
}
|
||||
|
||||
.layerswitcher-control .nudge.bottom::after {
|
||||
border-right: 5px solid transparent;
|
||||
border-left: 5px solid transparent;
|
||||
border-top: 5px solid #222;
|
||||
}
|
||||
|
||||
.layerswitcher-control .nudge:first-child {
|
||||
border-radius: 4px 0 0 4px;
|
||||
}
|
||||
|
||||
.layerswitcher-control .reset {
|
||||
width: 33.3333%;
|
||||
border-radius: 0 4px 4px 0;
|
||||
}
|
||||
|
||||
.opacity-options-wrapper {
|
||||
@@ -708,6 +792,7 @@ a.selected:hover .toggle.icon { background-position: -40px -180px;}
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 10px;
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.opacity-options li {
|
||||
@@ -720,14 +805,14 @@ a.selected:hover .toggle.icon { background-position: -40px -180px;}
|
||||
.opacity-options li .select-box{
|
||||
position: absolute;
|
||||
width:20px;
|
||||
height:20px;
|
||||
height:18px;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
.layerswitcher-control li:hover .select-box,
|
||||
.layerswitcher-control li.selected .select-box {
|
||||
border: 2px solid #6bc641;
|
||||
background: rgba(107, 198, 65, .5);
|
||||
border: 2px solid #7092ff;
|
||||
background: rgba(89, 123, 231, .5);
|
||||
opacity: .5;
|
||||
}
|
||||
.layerswitcher-control li.selected:hover .select-box,
|
||||
@@ -739,23 +824,45 @@ a.selected:hover .toggle.icon { background-position: -40px -180px;}
|
||||
background:#222;
|
||||
display:inline-block;
|
||||
width:20px;
|
||||
height:20px;
|
||||
height:18px;
|
||||
}
|
||||
|
||||
/* Geocoder */
|
||||
|
||||
.geocode-control {
|
||||
top:160px;
|
||||
.geocode-control, .geocode-control form {
|
||||
top:150px;
|
||||
}
|
||||
|
||||
.geocode-control form {
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.geocode-control input {
|
||||
width: 140px;
|
||||
border: 1px solid #ccc;
|
||||
margin: 4px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.geocode-control div.content {
|
||||
z-index: 100;
|
||||
top: 190px;
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.geocode-control div.content span {
|
||||
display: inline-block;
|
||||
border-bottom: 1px solid #333;
|
||||
padding: 5px 10px;
|
||||
}
|
||||
|
||||
/* Geolocator */
|
||||
|
||||
.geolocate-control {
|
||||
top:260px;
|
||||
top:230px;
|
||||
}
|
||||
|
||||
.geolocate-control button {
|
||||
border-radius: 0 0 4px 0;
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
/* Map
|
||||
@@ -791,6 +898,10 @@ img.tile {
|
||||
-o-transform-origin:0 0;
|
||||
}
|
||||
|
||||
#surface {
|
||||
position: static;
|
||||
}
|
||||
|
||||
#tile-g {
|
||||
opacity: 0.5;
|
||||
}
|
||||
@@ -819,17 +930,17 @@ img.tile {
|
||||
color:#fff;
|
||||
}
|
||||
|
||||
#user-list a:not(:last-child):after {
|
||||
.user-list a:not(:last-child):after {
|
||||
content: ', ';
|
||||
}
|
||||
|
||||
/* Account Information */
|
||||
|
||||
.user-container {
|
||||
.account {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.user-container .logout {
|
||||
.account .logout {
|
||||
margin-left:10px;
|
||||
border-left: 1px solid white;
|
||||
padding-left: 10px;
|
||||
@@ -878,9 +989,11 @@ div.typeahead a:first-child {
|
||||
display: inline-block;
|
||||
position:absolute;
|
||||
width: 50%;
|
||||
left: 25%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: auto;
|
||||
max-width: 600px;
|
||||
top:80px;
|
||||
top: 80px;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
@@ -899,10 +1012,14 @@ div.typeahead a:first-child {
|
||||
position: absolute;
|
||||
right:5px;
|
||||
top:5px;
|
||||
border:0;
|
||||
opacity: .5;
|
||||
-webkit-transition: opacity 100ms;
|
||||
-moz-transition: opacity 100ms;
|
||||
transition: opacity 100ms;
|
||||
}
|
||||
.modal button.close-modal:hover {
|
||||
background-color: transparent;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.shaded {
|
||||
@@ -920,7 +1037,7 @@ div.typeahead a:first-child {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.modal-section.header {
|
||||
.modal-section:first-child {
|
||||
border-radius: 4px 4px 0 0;
|
||||
}
|
||||
|
||||
@@ -963,7 +1080,6 @@ div.typeahead a:first-child {
|
||||
|
||||
.modal-splash {
|
||||
width: 33.3333%;
|
||||
left: 33.3333%;
|
||||
}
|
||||
|
||||
.logo {
|
||||
@@ -976,7 +1092,7 @@ div.typeahead a:first-child {
|
||||
/* Commit Modal
|
||||
------------------------------------------------------- */
|
||||
|
||||
.commit-modal .user-info {
|
||||
.commit-modal a.user-info {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
@@ -1007,11 +1123,10 @@ div.typeahead a:first-child {
|
||||
border:1px solid #ccc;
|
||||
background:#fff;
|
||||
max-height: 160px;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.commit-modal .warning-section .changeset-list {
|
||||
margin-right: 20px;
|
||||
.commit-modal .warning-section .changeset-list button {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.commit-section.modal-section {
|
||||
@@ -1022,30 +1137,17 @@ div.typeahead a:first-child {
|
||||
|
||||
.commit-modal .changeset-list li {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.commit-modal .changeset-list li button {
|
||||
position: absolute;
|
||||
right: -30px;
|
||||
border-top:1px solid #ccc;
|
||||
padding:5px 10px;
|
||||
}
|
||||
|
||||
.modal-section {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.modal-section.header {
|
||||
border-radius: 4px 4px 0 0;
|
||||
}
|
||||
|
||||
.modal-section .buttons {
|
||||
padding-top: 10px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.modal-section img.wiki-image {
|
||||
max-width: 400px;
|
||||
max-width: 100%;
|
||||
max-height: 300px;
|
||||
padding: 10px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
@@ -1060,11 +1162,6 @@ div.typeahead a:first-child {
|
||||
display:none;
|
||||
}
|
||||
|
||||
.changeset-list li {
|
||||
border-top:1px solid #ccc;
|
||||
padding:5px 10px;
|
||||
}
|
||||
|
||||
.changeset-list li span.count {
|
||||
font-size:10px;
|
||||
color:#555;
|
||||
@@ -1082,10 +1179,6 @@ div.typeahead a:first-child {
|
||||
font:normal 12px/20px 'Helvetica Neue', Arial, sans-serif;
|
||||
}
|
||||
|
||||
.loading-modal {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Success
|
||||
------------------------------------------------------- */
|
||||
a.success-action {
|
||||
@@ -1104,7 +1197,8 @@ a.success-action {
|
||||
text-align:center;
|
||||
}
|
||||
|
||||
.notice .notice-inner {
|
||||
.notice .zoom-to {
|
||||
width:100%;
|
||||
height: 40px;
|
||||
border-radius: 5px;
|
||||
line-height: 40px;
|
||||
@@ -1113,22 +1207,27 @@ a.success-action {
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.notice .notice-inner .zoom-to {
|
||||
width:40px;
|
||||
height:40px;
|
||||
.notice .zoom-to:hover {
|
||||
background: #d8e1ff;
|
||||
}
|
||||
|
||||
.notice .zoom-to .icon {
|
||||
margin-top:10px;
|
||||
margin-right:10px;
|
||||
}
|
||||
|
||||
.icon.zoom-in-invert {
|
||||
background-position: -240px -40px;
|
||||
}
|
||||
|
||||
/* Tooltips
|
||||
------------------------------------------------------- */
|
||||
|
||||
.tooltip {
|
||||
white-space: normal;
|
||||
width: 200px;
|
||||
position: absolute;
|
||||
left: 0; right: 0; margin: auto;
|
||||
z-index: -1000;
|
||||
height: 0;
|
||||
padding: 5px;
|
||||
opacity: 0;
|
||||
display: block;
|
||||
}
|
||||
@@ -1140,106 +1239,140 @@ a.success-action {
|
||||
}
|
||||
|
||||
.tooltip.top {
|
||||
margin-top: -5px;
|
||||
margin-top: -10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tooltip.right {
|
||||
margin-left: 5px;
|
||||
margin-left: 10px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.tooltip.bottom {
|
||||
margin-top: 5px;
|
||||
margin-top: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tooltip.left {
|
||||
margin-left: -5px;
|
||||
margin-left: -10px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.tooltip-inner {
|
||||
text-align: left;
|
||||
width: 200px;
|
||||
font-size: 11px;
|
||||
font-weight: bold;
|
||||
line-height: 20px;
|
||||
padding: 5px 10px;
|
||||
color: #333;
|
||||
background-color: white;
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
color: #333;
|
||||
display: inline-block;
|
||||
padding: 5px 10px;
|
||||
font-size: 11px;
|
||||
font-weight: bold;
|
||||
line-height: 20px;
|
||||
background-color: white;
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
|
||||
}
|
||||
|
||||
.tooltip-arrow {
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-color: transparent;
|
||||
border-style: solid;
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-color: transparent;
|
||||
border-style: solid;
|
||||
}
|
||||
|
||||
.tooltip.top .tooltip-arrow {
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
margin-left: -5px;
|
||||
border-top-color: white;
|
||||
border-width: 5px 5px 0;
|
||||
bottom: -5px;
|
||||
left: 50%;
|
||||
margin-left: -5px;
|
||||
border-top-color: white;
|
||||
border-width: 5px 5px 0;
|
||||
}
|
||||
|
||||
.tooltip.right .tooltip-arrow {
|
||||
top: 50%;
|
||||
left: 0;
|
||||
margin-top: -5px;
|
||||
border-right-color: white;
|
||||
border-width: 5px 5px 5px 0;
|
||||
top: 50%;
|
||||
left: -5px;
|
||||
margin-top: -5px;
|
||||
border-right-color: white;
|
||||
border-width: 5px 5px 5px 0;
|
||||
}
|
||||
|
||||
.tooltip.left .tooltip-arrow {
|
||||
top: 50%;
|
||||
right: 0;
|
||||
margin-top: -5px;
|
||||
border-left-color: white;
|
||||
border-width: 5px 0 5px 5px;
|
||||
top: 50%;
|
||||
right: 5px;
|
||||
margin-top: -5px;
|
||||
border-left-color: white;
|
||||
border-width: 5px 0 5px 5px;
|
||||
}
|
||||
|
||||
.tooltip.bottom .tooltip-arrow {
|
||||
top: 0;
|
||||
left: 50%;
|
||||
margin-left: -5px;
|
||||
border-bottom-color: white;
|
||||
border-width: 0 5px 5px;
|
||||
top: -5px;
|
||||
left: 50%;
|
||||
margin-left: -5px;
|
||||
border-bottom-color: white;
|
||||
border-width: 0 5px 5px;
|
||||
}
|
||||
|
||||
.Browse .tooltip {
|
||||
left: -20px !important; }
|
||||
.Browse .tooltip .tooltip-arrow {
|
||||
left: 30px;
|
||||
left: 60px;
|
||||
}
|
||||
|
||||
.tooltip .keyhint-wrap {
|
||||
padding: 5px 0 5px 0;
|
||||
}
|
||||
|
||||
.tooltip .keyhint {
|
||||
float: right;
|
||||
background: #eee;
|
||||
display: block;
|
||||
color: #222;
|
||||
font-size: 10px;
|
||||
padding: 0 4px;
|
||||
background:#aaa;
|
||||
color:#fff;
|
||||
padding: 0px 7px;
|
||||
font-weight: bold;
|
||||
display: inline-block;
|
||||
border-radius: 2px;
|
||||
margin-left: 4px;
|
||||
border: 1px solid #CCC;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
text-align: left;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.tooltip .keyhint .keyhint-label{
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.tooltip .keyhint::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
border-radius: 2px;
|
||||
height: 10px;
|
||||
width: 100%;
|
||||
z-index: 0;
|
||||
bottom: -4px;
|
||||
left: -1px;
|
||||
border: 1px solid #CCC;
|
||||
border-top: 0;
|
||||
}
|
||||
|
||||
.tail {
|
||||
pointer-events:none;
|
||||
position: absolute;
|
||||
background: rgba(255, 255, 255, 0.7);
|
||||
max-width: 250px;
|
||||
margin-top: -15px;
|
||||
padding: 5px;
|
||||
-webkit-border-radius: 4px;
|
||||
pointer-events:none;
|
||||
position: absolute;
|
||||
background: rgba(255, 255, 255, 0.7);
|
||||
max-width: 250px;
|
||||
margin-top: -15px;
|
||||
padding: 5px;
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.radial-menu-background {
|
||||
stroke: #aaa;
|
||||
stroke-opacity: 0.4;
|
||||
}
|
||||
|
||||
.radial-menu-item {
|
||||
fill: white;
|
||||
stroke: black;
|
||||
stroke-width: 1;
|
||||
fill: black;
|
||||
cursor:url(../img/cursor-pointer.png) 6 1, auto;
|
||||
}
|
||||
|
||||
@@ -1257,6 +1390,24 @@ a.success-action {
|
||||
fill: rgba(255,255,255,.5);
|
||||
}
|
||||
|
||||
.radial-menu .icon {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.radial-menu-tooltip {
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
padding: 5px;
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.lasso-box {
|
||||
fill-opacity:0.2;
|
||||
fill: #bde5aa;
|
||||
stroke: #000;
|
||||
stroke-width: 1;
|
||||
}
|
||||
|
||||
/* Media Queries
|
||||
------------------------------------------------------- */
|
||||
@@ -1265,5 +1416,44 @@ a.success-action {
|
||||
span.label {display: none;}
|
||||
/* override hide for save button */
|
||||
.icon.icon-pre-text { margin-right: 0px;}
|
||||
.save .label { display: block;}
|
||||
.save .label, .apply .label, .cancel .label { display: block;}
|
||||
}
|
||||
|
||||
div.combobox {
|
||||
width:155px;
|
||||
z-index: 9999;
|
||||
display: none;
|
||||
box-shadow: 0 5px 10px 0 rgba(0,0,0,.2);
|
||||
margin-top: -1px;
|
||||
background: white;
|
||||
max-height: 180px;
|
||||
overflow: auto;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
|
||||
div.combobox a {
|
||||
height: 25px;
|
||||
line-height: 25px;
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
border-top:1px solid #ccc;
|
||||
background-color: #fff;
|
||||
padding:1px 4px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
div.combobox a:hover,
|
||||
div.combobox a.selected {
|
||||
background: #e1e8ff;
|
||||
color: #154dff;
|
||||
}
|
||||
|
||||
div.combobox a:first-child {
|
||||
border-top: 0;
|
||||
}
|
||||
|
||||
div.combobox-carat {
|
||||
cursor: pointer;
|
||||
padding:0 5px;
|
||||
vertical-align:middle;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,26 @@
|
||||
/* tiles */
|
||||
img.tile {
|
||||
position:absolute;
|
||||
transform-origin:0 0;
|
||||
-ms-transform-origin:0 0;
|
||||
-webkit-transform-origin:0 0;
|
||||
-moz-transform-origin:0 0;
|
||||
-o-transform-origin:0 0;
|
||||
-webkit-user-select: none;
|
||||
-webkit-user-drag: none;
|
||||
-moz-user-drag: none;
|
||||
|
||||
opacity: 0;
|
||||
|
||||
-webkit-transition: opacity 200ms linear;
|
||||
transition: opacity 200ms linear;
|
||||
-moz-transition: opacity 200ms linear;
|
||||
}
|
||||
|
||||
img.tile-loaded {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* base styles */
|
||||
path {
|
||||
fill: none;
|
||||
@@ -9,6 +32,10 @@ g.point circle {
|
||||
fill:#fff;
|
||||
}
|
||||
|
||||
g.point image {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
g.point .shadow {
|
||||
fill: none;
|
||||
pointer-events: all;
|
||||
@@ -16,22 +43,28 @@ g.point .shadow {
|
||||
transition: transform 100ms linear;
|
||||
-moz-transition: fill 100ms linear;
|
||||
}
|
||||
.behavior-hover g.point.hover .shadow {
|
||||
fill: #E96666;
|
||||
fill-opacity: 0.3;
|
||||
.behavior-hover g.point.hover:not(.selected) .shadow {
|
||||
fill: #f6634f;
|
||||
fill-opacity: 0.5;
|
||||
}
|
||||
g.point.selected .shadow {
|
||||
fill: #E96666;
|
||||
fill: #f6634f;
|
||||
fill-opacity: 0.7;
|
||||
}
|
||||
|
||||
g.point.active, g.point.active * {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* vertices */
|
||||
|
||||
g.vertex .fill {
|
||||
fill:white;
|
||||
}
|
||||
|
||||
g.vertex .stroke {
|
||||
stroke:#333;
|
||||
stroke:black;
|
||||
stroke-opacity: .5;
|
||||
stroke-width:2;
|
||||
fill:white;
|
||||
}
|
||||
@@ -101,28 +134,40 @@ g.vertex.shared .fill {
|
||||
g.vertex .shadow {
|
||||
fill: none;
|
||||
pointer-events: all;
|
||||
stroke-width: 10;
|
||||
stroke-width: 20;
|
||||
-webkit-transition: -webkit-transform 100ms linear;
|
||||
transition: transform 100ms linear;
|
||||
-moz-transition: fill 100ms linear;
|
||||
}
|
||||
.behavior-hover g.vertex.hover .shadow {
|
||||
fill: #E96666;
|
||||
.behavior-hover g.vertex.hover:not(.selected) .shadow {
|
||||
fill: #f6634f;
|
||||
fill-opacity: 0.3;
|
||||
}
|
||||
}
|
||||
g.vertex.selected .shadow {
|
||||
fill: #E96666;
|
||||
fill-opacity: 0.7;
|
||||
fill: #f6634f;
|
||||
fill-opacity: 0.5;
|
||||
}
|
||||
|
||||
/* midpoints */
|
||||
|
||||
g.midpoint .fill {
|
||||
fill:#aaa;
|
||||
.mode-draw-area g.midpoint,
|
||||
.mode-draw-line g.midpoint,
|
||||
.mode-add-area g.midpoint,
|
||||
.mode-add-line g.midpoint,
|
||||
.mode-add-point g.midpoint,
|
||||
.behavior-drag-node g.midpoint {
|
||||
display: none;
|
||||
}
|
||||
.behavior-hover g.midpoint .fill.hover {
|
||||
fill:#fff;
|
||||
stroke:#000;
|
||||
|
||||
g.midpoint .fill {
|
||||
fill:#ddd;
|
||||
stroke:black;
|
||||
stroke-opacity: .5;
|
||||
opacity: .5;
|
||||
}
|
||||
.behavior-hover g.midpoint .fill.hover:not(.selected) {
|
||||
fill:white;
|
||||
opacity: .75;
|
||||
}
|
||||
|
||||
g.midpoint .shadow {
|
||||
@@ -133,8 +178,8 @@ g.midpoint .shadow {
|
||||
transition: transform 100ms linear;
|
||||
-moz-transition: fill 100ms linear;
|
||||
}
|
||||
.behavior-hover g.midpoint .shadow.hover {
|
||||
fill:#E96666;
|
||||
.behavior-hover g.midpoint .shadow.hover:not(.selected) {
|
||||
fill:#f6634f;
|
||||
fill-opacity: 0.3;
|
||||
}
|
||||
|
||||
@@ -146,13 +191,8 @@ path.line {
|
||||
}
|
||||
|
||||
path.stroke {
|
||||
stroke: #222;
|
||||
stroke-width: 2;
|
||||
}
|
||||
|
||||
path.stroke,
|
||||
path.casing {
|
||||
shape-rendering: optimizeSpeed;
|
||||
stroke: black;
|
||||
stroke-width: 4;
|
||||
}
|
||||
|
||||
path.shadow {
|
||||
@@ -161,106 +201,83 @@ path.shadow {
|
||||
-webkit-transition: stroke 100ms linear;
|
||||
}
|
||||
|
||||
.behavior-hover path.shadow.hover {
|
||||
stroke: #E96666;
|
||||
.behavior-hover path.shadow.hover:not(.selected) {
|
||||
stroke: #f6634f;
|
||||
stroke-opacity: 0.3;
|
||||
}
|
||||
|
||||
path.shadow.selected {
|
||||
stroke: #E96666;
|
||||
stroke: #f6634f;
|
||||
stroke-opacity: 0.7;
|
||||
}
|
||||
|
||||
path.area.stroke,
|
||||
path.multipolygon {
|
||||
path.line.member-type-multipolygon.stroke {
|
||||
stroke-width:2;
|
||||
stroke:#fff;
|
||||
}
|
||||
path.area.fill,
|
||||
path.multipolygon {
|
||||
fill:#fff;
|
||||
fill-opacity:0.3;
|
||||
}
|
||||
|
||||
path.multipolygon {
|
||||
fill-rule: evenodd;
|
||||
}
|
||||
|
||||
path.area.fill.member-type-multipolygon {
|
||||
fill: none;
|
||||
}
|
||||
|
||||
path.area.stroke.selected {
|
||||
path.area.stroke.selected,
|
||||
path.line.member-type-multipolygon.stroke.selected {
|
||||
stroke-width:4 !important;
|
||||
}
|
||||
|
||||
path.area.stroke.tag-natural,
|
||||
path.multipolygon.tag-natural {
|
||||
stroke: #ADD6A5;
|
||||
path.area.stroke {
|
||||
stroke:#fff;
|
||||
}
|
||||
path.area.fill {
|
||||
fill:#fff;
|
||||
fill-opacity:0.3;
|
||||
fill-rule: evenodd;
|
||||
}
|
||||
|
||||
path.stroke.tag-natural {
|
||||
stroke: #b6e199;
|
||||
stroke-width:1;
|
||||
}
|
||||
path.area.fill.tag-natural,
|
||||
path.multipolygon.tag-natural {
|
||||
fill: #ADD6A5;
|
||||
path.fill.tag-natural {
|
||||
fill: #b6e199;
|
||||
}
|
||||
|
||||
path.area.stroke.tag-natural-water,
|
||||
path.multipolygon.tag-natural-water {
|
||||
stroke: #6382FF;
|
||||
path.stroke.tag-natural-water {
|
||||
stroke: #77d3de;
|
||||
}
|
||||
path.area.fill.tag-natural-water,
|
||||
path.multipolygon.tag-natural-water {
|
||||
fill: #ADBEFF;
|
||||
path.fill.tag-natural-water {
|
||||
fill: #77d3de;
|
||||
}
|
||||
|
||||
path.area.stroke.tag-building,
|
||||
path.multipolygon.tag-building {
|
||||
stroke: #9E176A;
|
||||
path.stroke.tag-building {
|
||||
stroke: #e06e5f;
|
||||
stroke-width: 1;
|
||||
}
|
||||
path.area.fill.tag-building,
|
||||
path.multipolygon.tag-building {
|
||||
fill: #ff6ec7;
|
||||
path.fill.tag-building {
|
||||
fill: #e06e5f;
|
||||
}
|
||||
|
||||
path.area.stroke.tag-landuse,
|
||||
path.area.stroke.tag-natural-wood,
|
||||
path.area.stroke.tag-natural-tree,
|
||||
path.area.stroke.tag-natural-grassland,
|
||||
path.area.stroke.tag-leisure-park,
|
||||
path.multipolygon.tag-landuse,
|
||||
path.multipolygon.tag-natural-wood,
|
||||
path.multipolygon.tag-natural-tree,
|
||||
path.multipolygon.tag-natural-grassland,
|
||||
path.multipolygon.tag-leisure-park {
|
||||
stroke: #006B34;
|
||||
path.stroke.tag-landuse,
|
||||
path.stroke.tag-natural-wood,
|
||||
path.stroke.tag-natural-tree,
|
||||
path.stroke.tag-natural-grassland,
|
||||
path.stroke.tag-leisure-park {
|
||||
stroke: #8cd05f;
|
||||
stroke-width: 1;
|
||||
}
|
||||
path.area.fill.tag-landuse,
|
||||
path.area.fill.tag-natural-wood,
|
||||
path.area.fill.tag-natural-tree,
|
||||
path.area.fill.tag-natural-grassland,
|
||||
path.area.fill.tag-leisure-park,
|
||||
path.multipolygon.tag-landuse,
|
||||
path.multipolygon.tag-natural-wood,
|
||||
path.multipolygon.tag-natural-tree,
|
||||
path.multipolygon.tag-natural-grassland,
|
||||
path.multipolygon.tag-leisure-park {
|
||||
fill: #189E59;
|
||||
path.fill.tag-landuse,
|
||||
path.fill.tag-natural-wood,
|
||||
path.fill.tag-natural-tree,
|
||||
path.fill.tag-natural-grassland,
|
||||
path.fill.tag-leisure-park {
|
||||
fill: #8cd05f;
|
||||
fill-opacity: 0.2;
|
||||
}
|
||||
|
||||
path.area.stroke.tag-amenity-parking,
|
||||
path.multipolygon.tag-amenity-parking {
|
||||
stroke: #beb267;
|
||||
path.stroke.tag-amenity-parking {
|
||||
stroke: #aaa;
|
||||
stroke-width: 1;
|
||||
}
|
||||
path.area.fill.tag-amenity-parking,
|
||||
path.multipolygon.tag-amenity-parking {
|
||||
fill: #edecc0;
|
||||
path.fill.tag-amenity-parking {
|
||||
fill: #aaa;
|
||||
}
|
||||
|
||||
path.multipolygon.tag-boundary {
|
||||
path.fill.tag-boundary {
|
||||
fill: none;
|
||||
}
|
||||
|
||||
@@ -291,56 +308,57 @@ svg[data-zoom="16"] path.stroke.tag-highway {
|
||||
path.stroke.tag-highway-motorway,
|
||||
path.stroke.tag-highway-motorway_link,
|
||||
path.stroke.tag-construction-motorway {
|
||||
stroke:#809bc0;
|
||||
stroke:#58a9ed;
|
||||
}
|
||||
|
||||
path.casing.tag-highway-motorway,
|
||||
path.casing.tag-highway-motorway_link,
|
||||
path.casing.tag-construction-motorway {
|
||||
stroke:#506077;
|
||||
stroke:#2c5476;
|
||||
}
|
||||
|
||||
path.stroke.tag-highway-trunk,
|
||||
path.stroke.tag-highway-trunk_link,
|
||||
path.stroke.tag-construction-trunk {
|
||||
stroke:#97d397;
|
||||
stroke:#8cd05f;
|
||||
}
|
||||
path.casing.tag-highway-trunk,
|
||||
path.casing.tag-highway-trunk_link,
|
||||
path.casing.tag-construction-trunk {
|
||||
stroke:#477147;
|
||||
stroke:#46682f;
|
||||
}
|
||||
|
||||
path.stroke.tag-highway-primary,
|
||||
path.stroke.tag-highway-primary_link,
|
||||
path.stroke.tag-construction-primary {
|
||||
stroke:#ec989a;
|
||||
stroke:#e06d5f;
|
||||
}
|
||||
path.casing.tag-highway-primary,
|
||||
path.casing.tag-highway-primary_link,
|
||||
path.casing.tag-construction-primary {
|
||||
stroke:#8d4346;
|
||||
stroke:#70372f;
|
||||
}
|
||||
|
||||
path.stroke.tag-highway-secondary,
|
||||
path.stroke.tag-highway-secondary_link,
|
||||
path.stroke.tag-construction-secondary {
|
||||
stroke:#fecc8b;
|
||||
stroke:#eab056;
|
||||
}
|
||||
path.casing.tag-highway-secondary,
|
||||
path.casing.tag-highway-secondary_link,
|
||||
path.casing.tag-construction-secondary {
|
||||
stroke:#a37b48;
|
||||
stroke:#75582b;
|
||||
}
|
||||
|
||||
path.stroke.tag-highway-tertiary,
|
||||
path.stroke.tag-highway-tertiary_link,
|
||||
path.stroke.tag-construction-tertiary {
|
||||
stroke:#ffffb3;
|
||||
stroke:#ffff7e;
|
||||
}
|
||||
path.casing.tag-highway-tertiary,
|
||||
path.casing.tag-highway-tertiary_link,
|
||||
path.casing.tag-construction-tertiary {
|
||||
stroke:#bbb;
|
||||
stroke:#7f7f3f;
|
||||
}
|
||||
|
||||
path.stroke.tag-highway-unclassified,
|
||||
@@ -377,7 +395,7 @@ path.stroke.tag-highway-pedestrian {
|
||||
shapeRendering: auto;
|
||||
}
|
||||
path.casing.tag-highway-pedestrian {
|
||||
stroke:#84C382;
|
||||
stroke:#8cd05f;
|
||||
stroke-width:6 !important;
|
||||
}
|
||||
|
||||
@@ -450,17 +468,17 @@ svg[data-zoom="16"] path.casing.tag-highway-bridleway {
|
||||
}
|
||||
|
||||
path.stroke.tag-highway-footway {
|
||||
stroke: #996600;
|
||||
stroke: #ae8681;
|
||||
}
|
||||
path.stroke.tag-highway-cycleway {
|
||||
stroke: #69f;
|
||||
stroke: #58a9ed;
|
||||
}
|
||||
path.stroke.tag-highway-bridleway {
|
||||
stroke: green;
|
||||
stroke: #e06d5f;
|
||||
}
|
||||
|
||||
path.stroke.tag-highway-steps {
|
||||
stroke: #ff6257;
|
||||
stroke: #81d25c;
|
||||
stroke-width: 4;
|
||||
stroke-linecap: butt;
|
||||
stroke-dasharray: 3, 3;
|
||||
@@ -472,7 +490,7 @@ path.casing.tag-highway-steps {
|
||||
|
||||
path.casing.tag-bridge-yes {
|
||||
stroke-width: 14;
|
||||
stroke: #000;
|
||||
stroke: #333;
|
||||
}
|
||||
|
||||
path.stroke.tag-highway-construction,
|
||||
@@ -516,12 +534,16 @@ path.casing.tag-railway-subway {
|
||||
|
||||
/* waterways */
|
||||
|
||||
path.fill.tag-waterway {
|
||||
fill: #77d3de;
|
||||
}
|
||||
|
||||
path.stroke.tag-waterway {
|
||||
stroke: #10539a;
|
||||
stroke: #77d3de;
|
||||
stroke-width: 2;
|
||||
}
|
||||
path.casing.tag-waterway {
|
||||
stroke: #6AA2FF;
|
||||
stroke: #77d3de;
|
||||
stroke-width: 4;
|
||||
}
|
||||
|
||||
@@ -540,11 +562,11 @@ svg[data-zoom="16"] path.casing.tag-waterway-river {
|
||||
}
|
||||
|
||||
path.stroke.tag-waterway-ditch {
|
||||
stroke: #10539a;
|
||||
stroke: #6591ff;
|
||||
stroke-width: 1;
|
||||
}
|
||||
path.casing.tag-waterway-ditch {
|
||||
stroke: #999692;
|
||||
stroke: #6591ff;
|
||||
stroke-width: 3;
|
||||
}
|
||||
|
||||
@@ -573,17 +595,22 @@ path.casing.tag-boundary {
|
||||
|
||||
path.casing.tag-boundary-protected_area,
|
||||
path.casing.tag-boundary-national_park {
|
||||
stroke: #4D9849;
|
||||
stroke: #b0e298;
|
||||
}
|
||||
|
||||
|
||||
text {
|
||||
font-size:10px;
|
||||
pointer-events: none;
|
||||
color: #222;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.oneway .textpath {
|
||||
pointer-events: none;
|
||||
font-size: 7px;
|
||||
baseline-shift: 2px;
|
||||
opacity: .7;
|
||||
}
|
||||
|
||||
text.tag-oneway {
|
||||
@@ -611,15 +638,29 @@ text.pathlabel,
|
||||
text.pointlabel {
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
fill: black;
|
||||
fill: #333;
|
||||
text-anchor: middle;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.layer-halo rect,
|
||||
.layer-halo path,
|
||||
.layer-label text {
|
||||
-webkit-transition: opacity 100ms linear;
|
||||
transition: opacity 100ms linear;
|
||||
-moz-transition: opacity 100ms linear;
|
||||
}
|
||||
|
||||
.pathlabel .textpath {
|
||||
dominant-baseline: middle;
|
||||
}
|
||||
|
||||
/* Opera doesn't support dominant-baseline. See #715 */
|
||||
.opera .pathlabel .textpath {
|
||||
baseline-shift: -33%;
|
||||
dominant-baseline: auto;
|
||||
}
|
||||
|
||||
.pointlabel-halo,
|
||||
.linelabel-halo,
|
||||
.arealabel-halo {
|
||||
@@ -628,13 +669,9 @@ text.pointlabel {
|
||||
}
|
||||
|
||||
|
||||
text.area.tag-leisure-park {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
text.point.tag-shop,
|
||||
text.point.tag-amenity {
|
||||
font-size: 9px;
|
||||
text.point {
|
||||
font-size: 10px;
|
||||
baseline-shift: 2px;
|
||||
}
|
||||
|
||||
/* Cursors */
|
||||
@@ -663,9 +700,7 @@ text.point.tag-amenity {
|
||||
}
|
||||
|
||||
.mode-select .area,
|
||||
.mode-browse .area,
|
||||
.mode-select .multipolygon,
|
||||
.mode-browse .multipolygon {
|
||||
.mode-browse .area {
|
||||
cursor: url(../img/cursor-select-area.png), pointer;
|
||||
}
|
||||
|
||||
@@ -678,7 +713,6 @@ text.point.tag-amenity {
|
||||
.vertex:active,
|
||||
.line:active,
|
||||
.area:active,
|
||||
.multipolygon:active,
|
||||
.midpoint:active,
|
||||
.mode-select .selected {
|
||||
cursor: url(../img/cursor-select-acting.png), pointer;
|
||||
@@ -694,14 +728,16 @@ text.point.tag-amenity {
|
||||
.mode-draw-line .behavior-hover .way,
|
||||
.mode-draw-area .behavior-hover .way,
|
||||
.mode-add-line .behavior-hover .way,
|
||||
.mode-add-area .behavior-hover .way {
|
||||
.mode-add-area .behavior-hover .way,
|
||||
.behavior-drag-node.behavior-hover .way {
|
||||
cursor:url(../img/cursor-draw-connect-line.png) 9 9, auto;
|
||||
}
|
||||
|
||||
.mode-draw-line .behavior-hover .vertex,
|
||||
.mode-draw-area .behavior-hover .vertex,
|
||||
.mode-add-line .behavior-hover .vertex,
|
||||
.mode-add-area .behavior-hover .vertex {
|
||||
.mode-add-area .behavior-hover .vertex,
|
||||
.behavior-drag-node.behavior-hover .vertex {
|
||||
cursor:url(../img/cursor-draw-connect-vertex.png) 9 9, auto;
|
||||
}
|
||||
|
||||
@@ -712,16 +748,19 @@ text.point.tag-amenity {
|
||||
/* Modes */
|
||||
|
||||
.mode-draw-line .vertex.active,
|
||||
.mode-draw-area .vertex.active {
|
||||
.mode-draw-area .vertex.active,
|
||||
.behavior-drag-node .vertex.active {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.mode-draw-line .way.active,
|
||||
.mode-draw-area .way.active {
|
||||
.mode-draw-area .way.active,
|
||||
.behavior-drag-node .active {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Ensure drawing doesn't interact with area fills. */
|
||||
.mode-add-point .area,
|
||||
.mode-draw-line .area,
|
||||
.mode-draw-area .area,
|
||||
.mode-add-line .area,
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
iD.data = {};
|
||||
@@ -0,0 +1,112 @@
|
||||
// from http://wiki.openstreetmap.org/wiki/Deprecated_features
|
||||
// TODO: deal with deprecated 'class' tag
|
||||
// does not deal with landuse=wood because of indecision
|
||||
// we will not care about http://taginfo.openstreetmap.org/tags/bicycle_parking=sheffield
|
||||
iD.data.deprecated = [
|
||||
{
|
||||
old: { barrier: 'wire_fence' },
|
||||
replace: {
|
||||
barrier: 'fence',
|
||||
fence_type: 'chain'
|
||||
}
|
||||
},
|
||||
{
|
||||
old: { barrier: 'wood_fence' },
|
||||
replace: {
|
||||
barrier: 'fence',
|
||||
fence_type: 'wood'
|
||||
}
|
||||
},
|
||||
{
|
||||
old: { highway: 'ford' },
|
||||
replace: {
|
||||
ford: 'yes'
|
||||
}
|
||||
},
|
||||
{
|
||||
old: { highway: 'ford' },
|
||||
replace: {
|
||||
ford: 'yes'
|
||||
}
|
||||
},
|
||||
{
|
||||
old: { highway: 'ford' },
|
||||
replace: {
|
||||
ford: 'yes'
|
||||
}
|
||||
},
|
||||
{
|
||||
old: { highway: 'stile' },
|
||||
replace: {
|
||||
barrier: 'stile'
|
||||
}
|
||||
},
|
||||
{
|
||||
old: { highway: 'incline' },
|
||||
replace: {
|
||||
highway: 'road',
|
||||
incline: 'up'
|
||||
}
|
||||
},
|
||||
{
|
||||
old: { highway: 'incline_steep' },
|
||||
replace: {
|
||||
highway: 'road',
|
||||
incline: 'up'
|
||||
}
|
||||
},
|
||||
{
|
||||
old: { highway: 'unsurfaced' },
|
||||
replace: {
|
||||
highway: 'road',
|
||||
incline: 'unpaved'
|
||||
}
|
||||
},
|
||||
{
|
||||
old: { highway: 'unsurfaced' },
|
||||
replace: {
|
||||
highway: 'road',
|
||||
incline: 'unpaved'
|
||||
}
|
||||
},
|
||||
{
|
||||
old: { landuse: 'wood' },
|
||||
replace: {
|
||||
highway: 'road',
|
||||
incline: 'unpaved'
|
||||
}
|
||||
},
|
||||
{
|
||||
old: { natural: 'marsh' },
|
||||
replace: {
|
||||
natural: 'wetland',
|
||||
wetland: 'marsh'
|
||||
}
|
||||
},
|
||||
{
|
||||
old: { shop: 'organic' },
|
||||
replace: {
|
||||
shop: 'supermarket',
|
||||
organic: 'only'
|
||||
}
|
||||
},
|
||||
{
|
||||
old: { power_source: '*' },
|
||||
replace: {
|
||||
'generator:source': '$1'
|
||||
}
|
||||
},
|
||||
{
|
||||
old: { power_rating: '*' },
|
||||
replace: {
|
||||
'generator:output': '$1'
|
||||
}
|
||||
},
|
||||
{
|
||||
old: { bicycle_parking: 'organic' },
|
||||
replace: {
|
||||
shop: 'supermarket',
|
||||
organic: 'only'
|
||||
}
|
||||
}
|
||||
];
|
||||
@@ -0,0 +1,10 @@
|
||||
// entirely discarded tags
|
||||
iD.data.discarded = [
|
||||
'tiger:upload_uuid',
|
||||
'tiger:tlid',
|
||||
'tiger:source',
|
||||
'tiger:separated',
|
||||
'geobase:datasetName',
|
||||
'geobase:uuid',
|
||||
'sub_sea:type'
|
||||
];
|
||||
@@ -0,0 +1,609 @@
|
||||
iD.data.imagery = [
|
||||
{
|
||||
"name": "Bing aerial imagery",
|
||||
"template": "http://ecn.t{t}.tiles.virtualearth.net/tiles/a{u}.jpeg?g=587&mkt=en-gb&n=z",
|
||||
"description": "Satellite imagery.",
|
||||
"scaleExtent": [
|
||||
0,
|
||||
20
|
||||
],
|
||||
"subdomains": [
|
||||
"0",
|
||||
"1",
|
||||
"2",
|
||||
"3"
|
||||
],
|
||||
"default": "yes",
|
||||
"sourcetag": "Bing",
|
||||
"logo": "bing_maps.png",
|
||||
"logo_url": "http://www.bing.com/maps",
|
||||
"terms_url": "http://opengeodata.org/microsoft-imagery-details"
|
||||
},
|
||||
{
|
||||
"name": "MapBox Satellite",
|
||||
"template": "http://{t}.tiles.mapbox.com/v3/openstreetmap.map-4wvf9l0l/{z}/{x}/{y}.png",
|
||||
"description": "Satellite and aerial imagery",
|
||||
"scaleExtent": [
|
||||
0,
|
||||
16
|
||||
],
|
||||
"subdomains": [
|
||||
"a",
|
||||
"b",
|
||||
"c"
|
||||
],
|
||||
"terms_url": "http://mapbox.com/tos/"
|
||||
},
|
||||
{
|
||||
"name": "OpenStreetMap",
|
||||
"template": "http://{t}.tile.openstreetmap.org/{z}/{x}/{y}.png",
|
||||
"description": "The default OpenStreetMap layer.",
|
||||
"scaleExtent": [
|
||||
0,
|
||||
18
|
||||
],
|
||||
"subdomains": [
|
||||
"a",
|
||||
"b",
|
||||
"c"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": " TIGER 2012 Roads Overlay",
|
||||
"template": "http://{t}.tile.openstreetmap.us/tiger2012_roads_expanded/{z}/{x}/{y}.png",
|
||||
"subdomains": [
|
||||
"a",
|
||||
"b",
|
||||
"c"
|
||||
],
|
||||
"extent": [
|
||||
[
|
||||
-124.81,
|
||||
24.055
|
||||
],
|
||||
[
|
||||
-66.865,
|
||||
49.386
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": " TIGER 2012 Roads Overlay",
|
||||
"template": "http://{t}.tile.openstreetmap.us/tiger2012_roads_expanded/{z}/{x}/{y}.png",
|
||||
"subdomains": [
|
||||
"a",
|
||||
"b",
|
||||
"c"
|
||||
],
|
||||
"extent": [
|
||||
[
|
||||
-179.754,
|
||||
50.858
|
||||
],
|
||||
[
|
||||
-129.899,
|
||||
71.463
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": " TIGER 2012 Roads Overlay",
|
||||
"template": "http://{t}.tile.openstreetmap.us/tiger2012_roads_expanded/{z}/{x}/{y}.png",
|
||||
"subdomains": [
|
||||
"a",
|
||||
"b",
|
||||
"c"
|
||||
],
|
||||
"extent": [
|
||||
[
|
||||
-174.46,
|
||||
18.702
|
||||
],
|
||||
[
|
||||
-154.516,
|
||||
26.501
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": " USGS Topographic Maps",
|
||||
"template": "http://{t}.tile.openstreetmap.us/usgs_scanned_topos/{z}/{x}/{y}.png",
|
||||
"subdomains": [
|
||||
"a",
|
||||
"b",
|
||||
"c"
|
||||
],
|
||||
"extent": [
|
||||
[
|
||||
-125.991,
|
||||
24.005
|
||||
],
|
||||
[
|
||||
-65.988,
|
||||
50.009
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": " USGS Topographic Maps",
|
||||
"template": "http://{t}.tile.openstreetmap.us/usgs_scanned_topos/{z}/{x}/{y}.png",
|
||||
"subdomains": [
|
||||
"a",
|
||||
"b",
|
||||
"c"
|
||||
],
|
||||
"extent": [
|
||||
[
|
||||
-160.579,
|
||||
18.902
|
||||
],
|
||||
[
|
||||
-154.793,
|
||||
22.508
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": " USGS Topographic Maps",
|
||||
"template": "http://{t}.tile.openstreetmap.us/usgs_scanned_topos/{z}/{x}/{y}.png",
|
||||
"subdomains": [
|
||||
"a",
|
||||
"b",
|
||||
"c"
|
||||
],
|
||||
"extent": [
|
||||
[
|
||||
-178.001,
|
||||
51.255
|
||||
],
|
||||
[
|
||||
-130.004,
|
||||
71.999
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": " USGS Large Scale Aerial Imagery",
|
||||
"template": "http://{t}.tile.openstreetmap.us/usgs_large_scale/{z}/{x}/{y}.jpg",
|
||||
"subdomains": [
|
||||
"a",
|
||||
"b",
|
||||
"c"
|
||||
],
|
||||
"extent": [
|
||||
[
|
||||
-124.819,
|
||||
24.496
|
||||
],
|
||||
[
|
||||
-66.931,
|
||||
49.443
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "British Columbia bc_mosaic",
|
||||
"template": "http://{t}.imagery.paulnorman.ca/tiles/bc_mosaic/{z}/{x}/{y}.png",
|
||||
"subdomains": [
|
||||
"a",
|
||||
"b",
|
||||
"c",
|
||||
"d"
|
||||
],
|
||||
"extent": [
|
||||
[
|
||||
-123.441,
|
||||
48.995
|
||||
],
|
||||
[
|
||||
-121.346,
|
||||
50.426
|
||||
]
|
||||
],
|
||||
"sourcetag": "bc_mosaic",
|
||||
"terms_url": "http://imagery.paulnorman.ca/tiles/about.html"
|
||||
},
|
||||
{
|
||||
"name": "OS OpenData Streetview",
|
||||
"template": "http://os.openstreetmap.org/sv/{z}/{x}/{y}.png",
|
||||
"extent": [
|
||||
[
|
||||
-8.72,
|
||||
49.86
|
||||
],
|
||||
[
|
||||
1.84,
|
||||
60.92
|
||||
]
|
||||
],
|
||||
"sourcetag": "OS_OpenData_StreetView"
|
||||
},
|
||||
{
|
||||
"name": "OS OpenData Locator",
|
||||
"template": "http://tiles.itoworld.com/os_locator/{z}/{x}/{y}.png",
|
||||
"extent": [
|
||||
[
|
||||
-9,
|
||||
49.8
|
||||
],
|
||||
[
|
||||
1.9,
|
||||
61.1
|
||||
]
|
||||
],
|
||||
"sourcetag": "OS_OpenData_Locator"
|
||||
},
|
||||
{
|
||||
"name": "OS 1:25k historic (OSM)",
|
||||
"template": "http://ooc.openstreetmap.org/os1/{z}/{x}/{y}.jpg",
|
||||
"extent": [
|
||||
[
|
||||
-9,
|
||||
49.8
|
||||
],
|
||||
[
|
||||
1.9,
|
||||
61.1
|
||||
]
|
||||
],
|
||||
"sourcetag": "OS 1:25k"
|
||||
},
|
||||
{
|
||||
"name": "OS 1:25k historic (NLS)",
|
||||
"template": "http://geo.nls.uk/mapdata2/os/25000/{z}/{x}/{y}.png",
|
||||
"extent": [
|
||||
[
|
||||
-9,
|
||||
49.8
|
||||
],
|
||||
[
|
||||
1.9,
|
||||
61.1
|
||||
]
|
||||
],
|
||||
"sourcetag": "OS 1:25k",
|
||||
"logo": "icons/logo_nls70-nq8.png",
|
||||
"logo_url": "http://geo.nls.uk/maps/"
|
||||
},
|
||||
{
|
||||
"name": "OS 7th Series historic (OSM)",
|
||||
"template": "http://ooc.openstreetmap.org/os7/{z}/{x}/{y}.jpg",
|
||||
"extent": [
|
||||
[
|
||||
-9,
|
||||
49.8
|
||||
],
|
||||
[
|
||||
1.9,
|
||||
61.1
|
||||
]
|
||||
],
|
||||
"sourcetag": "OS7"
|
||||
},
|
||||
{
|
||||
"name": "OS 7th Series historic (NLS)",
|
||||
"template": "http://geo.nls.uk/mapdata2/os/seventh/{z}/{x}/{y}.png",
|
||||
"extent": [
|
||||
[
|
||||
-9,
|
||||
49.8
|
||||
],
|
||||
[
|
||||
1.9,
|
||||
61.1
|
||||
]
|
||||
],
|
||||
"sourcetag": "OS7",
|
||||
"logo": "icons/logo_nls70-nq8.png",
|
||||
"logo_url": "http://geo.nls.uk/maps/"
|
||||
},
|
||||
{
|
||||
"name": "OS New Popular Edition historic",
|
||||
"template": "http://ooc.openstreetmap.org/npe/{z}/{x}/{y}.png",
|
||||
"extent": [
|
||||
[
|
||||
-5.8,
|
||||
49.8
|
||||
],
|
||||
[
|
||||
1.9,
|
||||
55.8
|
||||
]
|
||||
],
|
||||
"sourcetag": "NPE"
|
||||
},
|
||||
{
|
||||
"name": "OS Scottish Popular historic",
|
||||
"template": "http://ooc.openstreetmap.org/npescotland/tiles/{z}/{x}/{y}.jpg",
|
||||
"extent": [
|
||||
[
|
||||
-7.8,
|
||||
54.5
|
||||
],
|
||||
[
|
||||
-1.1,
|
||||
61.1
|
||||
]
|
||||
],
|
||||
"sourcetag": "NPE"
|
||||
},
|
||||
{
|
||||
"name": "Surrey aerial",
|
||||
"template": "http://gravitystorm.dev.openstreetmap.org/surrey/{z}/{x}/{y}.png",
|
||||
"extent": [
|
||||
[
|
||||
-0.856,
|
||||
51.071
|
||||
],
|
||||
[
|
||||
0.062,
|
||||
51.473
|
||||
]
|
||||
],
|
||||
"sourcetag": "Surrey aerial"
|
||||
},
|
||||
{
|
||||
"name": "Haiti - GeoEye Jan 13",
|
||||
"template": "http://gravitystorm.dev.openstreetmap.org/imagery/haiti/{z}/{x}/{y}.jpg",
|
||||
"extent": [
|
||||
[
|
||||
-74.5,
|
||||
17.95
|
||||
],
|
||||
[
|
||||
-71.58,
|
||||
20.12
|
||||
]
|
||||
],
|
||||
"sourcetag": "Haiti GeoEye"
|
||||
},
|
||||
{
|
||||
"name": "Haiti - GeoEye Jan 13+",
|
||||
"template": "http://maps.nypl.org/tilecache/1/geoeye/{z}/{x}/{y}.jpg",
|
||||
"extent": [
|
||||
[
|
||||
-74.5,
|
||||
17.95
|
||||
],
|
||||
[
|
||||
-71.58,
|
||||
20.12
|
||||
]
|
||||
],
|
||||
"sourcetag": "Haiti GeoEye"
|
||||
},
|
||||
{
|
||||
"name": "Haiti - DigitalGlobe",
|
||||
"template": "http://maps.nypl.org/tilecache/1/dg_crisis/{z}/{x}/{y}.jpg",
|
||||
"extent": [
|
||||
[
|
||||
-74.5,
|
||||
17.95
|
||||
],
|
||||
[
|
||||
-71.58,
|
||||
20.12
|
||||
]
|
||||
],
|
||||
"sourcetag": "Haiti DigitalGlobe"
|
||||
},
|
||||
{
|
||||
"name": "Haiti - Street names",
|
||||
"template": "http://hypercube.telascience.org/tiles/1.0.0/haiti-city/{z}/{x}/{y}.jpg",
|
||||
"extent": [
|
||||
[
|
||||
-74.5,
|
||||
17.95
|
||||
],
|
||||
[
|
||||
-71.58,
|
||||
20.12
|
||||
]
|
||||
],
|
||||
"sourcetag": "Haiti streetnames"
|
||||
},
|
||||
{
|
||||
"name": "NAIP",
|
||||
"template": "http://cube.telascience.org/tilecache/tilecache.py/NAIP_ALL/{z}/{x}/{y}.png",
|
||||
"description": "National Agriculture Imagery Program",
|
||||
"extent": [
|
||||
[
|
||||
-125.8,
|
||||
24.2
|
||||
],
|
||||
[
|
||||
-62.3,
|
||||
49.5
|
||||
]
|
||||
],
|
||||
"sourcetag": "NAIP"
|
||||
},
|
||||
{
|
||||
"name": "NAIP",
|
||||
"template": "http://cube.telascience.org/tilecache/tilecache.py/NAIP_ALL/{z}/{x}/{y}.png",
|
||||
"description": "National Agriculture Imagery Program",
|
||||
"extent": [
|
||||
[
|
||||
-168.5,
|
||||
55.3
|
||||
],
|
||||
[
|
||||
-140,
|
||||
71.5
|
||||
]
|
||||
],
|
||||
"sourcetag": "NAIP"
|
||||
},
|
||||
{
|
||||
"name": "Ireland - NLS Historic Maps",
|
||||
"template": "http://geo.nls.uk/maps/ireland/gsgs4136/{z}/{x}/{y}.png",
|
||||
"extent": [
|
||||
[
|
||||
-10.71,
|
||||
51.32
|
||||
],
|
||||
[
|
||||
-5.37,
|
||||
55.46
|
||||
]
|
||||
],
|
||||
"sourcetag": "NLS Historic Maps",
|
||||
"logo": "icons/logo_nls70-nq8.png",
|
||||
"logo_url": "http://geo.nls.uk/maps/"
|
||||
},
|
||||
{
|
||||
"name": "Denmark - Fugro Aerial Imagery",
|
||||
"template": "http://tile.openstreetmap.dk/fugro2005/{z}/{x}/{y}.jpg",
|
||||
"extent": [
|
||||
[
|
||||
7.81,
|
||||
54.44
|
||||
],
|
||||
[
|
||||
15.49,
|
||||
57.86
|
||||
]
|
||||
],
|
||||
"sourcetag": "Fugro (2005)"
|
||||
},
|
||||
{
|
||||
"name": "Denmark - Stevns Kommune",
|
||||
"template": "http://tile.openstreetmap.dk/stevns/2009/{z}/{x}/{y}.jpg",
|
||||
"extent": [
|
||||
[
|
||||
12.09144,
|
||||
55.23403
|
||||
],
|
||||
[
|
||||
12.47712,
|
||||
55.43647
|
||||
]
|
||||
],
|
||||
"sourcetag": "Stevns Kommune (2009)"
|
||||
},
|
||||
{
|
||||
"name": "Austria - geoimage.at",
|
||||
"template": "http://geoimage.openstreetmap.at/4d80de696cd562a63ce463a58a61488d/{z}/{x}/{y}.jpg",
|
||||
"extent": [
|
||||
[
|
||||
9.36,
|
||||
46.33
|
||||
],
|
||||
[
|
||||
17.28,
|
||||
49.09
|
||||
]
|
||||
],
|
||||
"sourcetag": "geoimage.at"
|
||||
},
|
||||
{
|
||||
"name": "Russia - Kosmosnimki.ru IRS Satellite",
|
||||
"template": "http://irs.gis-lab.info/?layers=irs&request=GetTile&z={z}&x={x}&y={y}",
|
||||
"extent": [
|
||||
[
|
||||
19.02,
|
||||
40.96
|
||||
],
|
||||
[
|
||||
77.34,
|
||||
70.48
|
||||
]
|
||||
],
|
||||
"sourcetag": "Kosmosnimki.ru IRS"
|
||||
},
|
||||
{
|
||||
"name": "Belarus - Kosmosnimki.ru SPOT4 Satellite",
|
||||
"template": "http://irs.gis-lab.info/?layers=spot&request=GetTile&z={z}&x={x}&y={y}",
|
||||
"extent": [
|
||||
[
|
||||
23.16,
|
||||
51.25
|
||||
],
|
||||
[
|
||||
32.83,
|
||||
56.19
|
||||
]
|
||||
],
|
||||
"sourcetag": "Kosmosnimki.ru SPOT4"
|
||||
},
|
||||
{
|
||||
"name": "Australia - Geographic Reference Image",
|
||||
"template": "http://agri.openstreetmap.org/{z}/{x}/{y}.png",
|
||||
"extent": [
|
||||
[
|
||||
96,
|
||||
-44
|
||||
],
|
||||
[
|
||||
168,
|
||||
-9
|
||||
]
|
||||
],
|
||||
"sourcetag": "AGRI"
|
||||
},
|
||||
{
|
||||
"name": "Switzerland - Canton Aargau - AGIS 25cm 2011",
|
||||
"template": "http://tiles.poole.ch/AGIS/OF2011/{z}/{x}/{y}.png",
|
||||
"extent": [
|
||||
[
|
||||
7.69,
|
||||
47.13
|
||||
],
|
||||
[
|
||||
8.48,
|
||||
47.63
|
||||
]
|
||||
],
|
||||
"sourcetag": "AGIS OF2011"
|
||||
},
|
||||
{
|
||||
"name": "Switzerland - Canton Solothurn - SOGIS 2007",
|
||||
"template": "http://mapproxy.sosm.ch:8080/tiles/sogis2007/EPSG900913/{z}/{x}/{y}.png?origin=nw",
|
||||
"extent": [
|
||||
[
|
||||
7.33,
|
||||
47.06
|
||||
],
|
||||
[
|
||||
8.04,
|
||||
47.5
|
||||
]
|
||||
],
|
||||
"sourcetag": "Orthofoto 2007 WMS Solothurn"
|
||||
},
|
||||
{
|
||||
"name": "Poland - Media-Lab fleet GPS masstracks",
|
||||
"template": "http://masstracks.media-lab.com.pl/{z}/{x}/{y}.png",
|
||||
"extent": [
|
||||
[
|
||||
14,
|
||||
48.9
|
||||
],
|
||||
[
|
||||
24.2,
|
||||
55
|
||||
]
|
||||
],
|
||||
"sourcetag": "masstracks"
|
||||
},
|
||||
{
|
||||
"name": "South Africa - CD:NGI Aerial",
|
||||
"template": "http://{t}.aerial.openstreetmap.org.za/ngi-aerial/{z}/{x}/{y}.jpg",
|
||||
"subdomains": [
|
||||
"a",
|
||||
"b",
|
||||
"c"
|
||||
],
|
||||
"extent": [
|
||||
[
|
||||
17.64,
|
||||
-34.95
|
||||
],
|
||||
[
|
||||
32.87,
|
||||
-22.05
|
||||
]
|
||||
],
|
||||
"sourcetag": "ngi-aerial"
|
||||
}
|
||||
];
|
||||
@@ -0,0 +1,609 @@
|
||||
[
|
||||
{
|
||||
"name": "Bing aerial imagery",
|
||||
"template": "http://ecn.t{t}.tiles.virtualearth.net/tiles/a{u}.jpeg?g=587&mkt=en-gb&n=z",
|
||||
"description": "Satellite imagery.",
|
||||
"scaleExtent": [
|
||||
0,
|
||||
20
|
||||
],
|
||||
"subdomains": [
|
||||
"0",
|
||||
"1",
|
||||
"2",
|
||||
"3"
|
||||
],
|
||||
"default": "yes",
|
||||
"sourcetag": "Bing",
|
||||
"logo": "bing_maps.png",
|
||||
"logo_url": "http://www.bing.com/maps",
|
||||
"terms_url": "http://opengeodata.org/microsoft-imagery-details"
|
||||
},
|
||||
{
|
||||
"name": "MapBox Satellite",
|
||||
"template": "http://{t}.tiles.mapbox.com/v3/openstreetmap.map-4wvf9l0l/{z}/{x}/{y}.png",
|
||||
"description": "Satellite and aerial imagery",
|
||||
"scaleExtent": [
|
||||
0,
|
||||
16
|
||||
],
|
||||
"subdomains": [
|
||||
"a",
|
||||
"b",
|
||||
"c"
|
||||
],
|
||||
"terms_url": "http://mapbox.com/tos/"
|
||||
},
|
||||
{
|
||||
"name": "OpenStreetMap",
|
||||
"template": "http://{t}.tile.openstreetmap.org/{z}/{x}/{y}.png",
|
||||
"description": "The default OpenStreetMap layer.",
|
||||
"scaleExtent": [
|
||||
0,
|
||||
18
|
||||
],
|
||||
"subdomains": [
|
||||
"a",
|
||||
"b",
|
||||
"c"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": " TIGER 2012 Roads Overlay",
|
||||
"template": "http://{t}.tile.openstreetmap.us/tiger2012_roads_expanded/{z}/{x}/{y}.png",
|
||||
"subdomains": [
|
||||
"a",
|
||||
"b",
|
||||
"c"
|
||||
],
|
||||
"extent": [
|
||||
[
|
||||
-124.81,
|
||||
24.055
|
||||
],
|
||||
[
|
||||
-66.865,
|
||||
49.386
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": " TIGER 2012 Roads Overlay",
|
||||
"template": "http://{t}.tile.openstreetmap.us/tiger2012_roads_expanded/{z}/{x}/{y}.png",
|
||||
"subdomains": [
|
||||
"a",
|
||||
"b",
|
||||
"c"
|
||||
],
|
||||
"extent": [
|
||||
[
|
||||
-179.754,
|
||||
50.858
|
||||
],
|
||||
[
|
||||
-129.899,
|
||||
71.463
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": " TIGER 2012 Roads Overlay",
|
||||
"template": "http://{t}.tile.openstreetmap.us/tiger2012_roads_expanded/{z}/{x}/{y}.png",
|
||||
"subdomains": [
|
||||
"a",
|
||||
"b",
|
||||
"c"
|
||||
],
|
||||
"extent": [
|
||||
[
|
||||
-174.46,
|
||||
18.702
|
||||
],
|
||||
[
|
||||
-154.516,
|
||||
26.501
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": " USGS Topographic Maps",
|
||||
"template": "http://{t}.tile.openstreetmap.us/usgs_scanned_topos/{z}/{x}/{y}.png",
|
||||
"subdomains": [
|
||||
"a",
|
||||
"b",
|
||||
"c"
|
||||
],
|
||||
"extent": [
|
||||
[
|
||||
-125.991,
|
||||
24.005
|
||||
],
|
||||
[
|
||||
-65.988,
|
||||
50.009
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": " USGS Topographic Maps",
|
||||
"template": "http://{t}.tile.openstreetmap.us/usgs_scanned_topos/{z}/{x}/{y}.png",
|
||||
"subdomains": [
|
||||
"a",
|
||||
"b",
|
||||
"c"
|
||||
],
|
||||
"extent": [
|
||||
[
|
||||
-160.579,
|
||||
18.902
|
||||
],
|
||||
[
|
||||
-154.793,
|
||||
22.508
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": " USGS Topographic Maps",
|
||||
"template": "http://{t}.tile.openstreetmap.us/usgs_scanned_topos/{z}/{x}/{y}.png",
|
||||
"subdomains": [
|
||||
"a",
|
||||
"b",
|
||||
"c"
|
||||
],
|
||||
"extent": [
|
||||
[
|
||||
-178.001,
|
||||
51.255
|
||||
],
|
||||
[
|
||||
-130.004,
|
||||
71.999
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": " USGS Large Scale Aerial Imagery",
|
||||
"template": "http://{t}.tile.openstreetmap.us/usgs_large_scale/{z}/{x}/{y}.jpg",
|
||||
"subdomains": [
|
||||
"a",
|
||||
"b",
|
||||
"c"
|
||||
],
|
||||
"extent": [
|
||||
[
|
||||
-124.819,
|
||||
24.496
|
||||
],
|
||||
[
|
||||
-66.931,
|
||||
49.443
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "British Columbia bc_mosaic",
|
||||
"template": "http://{t}.imagery.paulnorman.ca/tiles/bc_mosaic/{z}/{x}/{y}.png",
|
||||
"subdomains": [
|
||||
"a",
|
||||
"b",
|
||||
"c",
|
||||
"d"
|
||||
],
|
||||
"extent": [
|
||||
[
|
||||
-123.441,
|
||||
48.995
|
||||
],
|
||||
[
|
||||
-121.346,
|
||||
50.426
|
||||
]
|
||||
],
|
||||
"sourcetag": "bc_mosaic",
|
||||
"terms_url": "http://imagery.paulnorman.ca/tiles/about.html"
|
||||
},
|
||||
{
|
||||
"name": "OS OpenData Streetview",
|
||||
"template": "http://os.openstreetmap.org/sv/{z}/{x}/{y}.png",
|
||||
"extent": [
|
||||
[
|
||||
-8.72,
|
||||
49.86
|
||||
],
|
||||
[
|
||||
1.84,
|
||||
60.92
|
||||
]
|
||||
],
|
||||
"sourcetag": "OS_OpenData_StreetView"
|
||||
},
|
||||
{
|
||||
"name": "OS OpenData Locator",
|
||||
"template": "http://tiles.itoworld.com/os_locator/{z}/{x}/{y}.png",
|
||||
"extent": [
|
||||
[
|
||||
-9,
|
||||
49.8
|
||||
],
|
||||
[
|
||||
1.9,
|
||||
61.1
|
||||
]
|
||||
],
|
||||
"sourcetag": "OS_OpenData_Locator"
|
||||
},
|
||||
{
|
||||
"name": "OS 1:25k historic (OSM)",
|
||||
"template": "http://ooc.openstreetmap.org/os1/{z}/{x}/{y}.jpg",
|
||||
"extent": [
|
||||
[
|
||||
-9,
|
||||
49.8
|
||||
],
|
||||
[
|
||||
1.9,
|
||||
61.1
|
||||
]
|
||||
],
|
||||
"sourcetag": "OS 1:25k"
|
||||
},
|
||||
{
|
||||
"name": "OS 1:25k historic (NLS)",
|
||||
"template": "http://geo.nls.uk/mapdata2/os/25000/{z}/{x}/{y}.png",
|
||||
"extent": [
|
||||
[
|
||||
-9,
|
||||
49.8
|
||||
],
|
||||
[
|
||||
1.9,
|
||||
61.1
|
||||
]
|
||||
],
|
||||
"sourcetag": "OS 1:25k",
|
||||
"logo": "icons/logo_nls70-nq8.png",
|
||||
"logo_url": "http://geo.nls.uk/maps/"
|
||||
},
|
||||
{
|
||||
"name": "OS 7th Series historic (OSM)",
|
||||
"template": "http://ooc.openstreetmap.org/os7/{z}/{x}/{y}.jpg",
|
||||
"extent": [
|
||||
[
|
||||
-9,
|
||||
49.8
|
||||
],
|
||||
[
|
||||
1.9,
|
||||
61.1
|
||||
]
|
||||
],
|
||||
"sourcetag": "OS7"
|
||||
},
|
||||
{
|
||||
"name": "OS 7th Series historic (NLS)",
|
||||
"template": "http://geo.nls.uk/mapdata2/os/seventh/{z}/{x}/{y}.png",
|
||||
"extent": [
|
||||
[
|
||||
-9,
|
||||
49.8
|
||||
],
|
||||
[
|
||||
1.9,
|
||||
61.1
|
||||
]
|
||||
],
|
||||
"sourcetag": "OS7",
|
||||
"logo": "icons/logo_nls70-nq8.png",
|
||||
"logo_url": "http://geo.nls.uk/maps/"
|
||||
},
|
||||
{
|
||||
"name": "OS New Popular Edition historic",
|
||||
"template": "http://ooc.openstreetmap.org/npe/{z}/{x}/{y}.png",
|
||||
"extent": [
|
||||
[
|
||||
-5.8,
|
||||
49.8
|
||||
],
|
||||
[
|
||||
1.9,
|
||||
55.8
|
||||
]
|
||||
],
|
||||
"sourcetag": "NPE"
|
||||
},
|
||||
{
|
||||
"name": "OS Scottish Popular historic",
|
||||
"template": "http://ooc.openstreetmap.org/npescotland/tiles/{z}/{x}/{y}.jpg",
|
||||
"extent": [
|
||||
[
|
||||
-7.8,
|
||||
54.5
|
||||
],
|
||||
[
|
||||
-1.1,
|
||||
61.1
|
||||
]
|
||||
],
|
||||
"sourcetag": "NPE"
|
||||
},
|
||||
{
|
||||
"name": "Surrey aerial",
|
||||
"template": "http://gravitystorm.dev.openstreetmap.org/surrey/{z}/{x}/{y}.png",
|
||||
"extent": [
|
||||
[
|
||||
-0.856,
|
||||
51.071
|
||||
],
|
||||
[
|
||||
0.062,
|
||||
51.473
|
||||
]
|
||||
],
|
||||
"sourcetag": "Surrey aerial"
|
||||
},
|
||||
{
|
||||
"name": "Haiti - GeoEye Jan 13",
|
||||
"template": "http://gravitystorm.dev.openstreetmap.org/imagery/haiti/{z}/{x}/{y}.jpg",
|
||||
"extent": [
|
||||
[
|
||||
-74.5,
|
||||
17.95
|
||||
],
|
||||
[
|
||||
-71.58,
|
||||
20.12
|
||||
]
|
||||
],
|
||||
"sourcetag": "Haiti GeoEye"
|
||||
},
|
||||
{
|
||||
"name": "Haiti - GeoEye Jan 13+",
|
||||
"template": "http://maps.nypl.org/tilecache/1/geoeye/{z}/{x}/{y}.jpg",
|
||||
"extent": [
|
||||
[
|
||||
-74.5,
|
||||
17.95
|
||||
],
|
||||
[
|
||||
-71.58,
|
||||
20.12
|
||||
]
|
||||
],
|
||||
"sourcetag": "Haiti GeoEye"
|
||||
},
|
||||
{
|
||||
"name": "Haiti - DigitalGlobe",
|
||||
"template": "http://maps.nypl.org/tilecache/1/dg_crisis/{z}/{x}/{y}.jpg",
|
||||
"extent": [
|
||||
[
|
||||
-74.5,
|
||||
17.95
|
||||
],
|
||||
[
|
||||
-71.58,
|
||||
20.12
|
||||
]
|
||||
],
|
||||
"sourcetag": "Haiti DigitalGlobe"
|
||||
},
|
||||
{
|
||||
"name": "Haiti - Street names",
|
||||
"template": "http://hypercube.telascience.org/tiles/1.0.0/haiti-city/{z}/{x}/{y}.jpg",
|
||||
"extent": [
|
||||
[
|
||||
-74.5,
|
||||
17.95
|
||||
],
|
||||
[
|
||||
-71.58,
|
||||
20.12
|
||||
]
|
||||
],
|
||||
"sourcetag": "Haiti streetnames"
|
||||
},
|
||||
{
|
||||
"name": "NAIP",
|
||||
"template": "http://cube.telascience.org/tilecache/tilecache.py/NAIP_ALL/{z}/{x}/{y}.png",
|
||||
"description": "National Agriculture Imagery Program",
|
||||
"extent": [
|
||||
[
|
||||
-125.8,
|
||||
24.2
|
||||
],
|
||||
[
|
||||
-62.3,
|
||||
49.5
|
||||
]
|
||||
],
|
||||
"sourcetag": "NAIP"
|
||||
},
|
||||
{
|
||||
"name": "NAIP",
|
||||
"template": "http://cube.telascience.org/tilecache/tilecache.py/NAIP_ALL/{z}/{x}/{y}.png",
|
||||
"description": "National Agriculture Imagery Program",
|
||||
"extent": [
|
||||
[
|
||||
-168.5,
|
||||
55.3
|
||||
],
|
||||
[
|
||||
-140,
|
||||
71.5
|
||||
]
|
||||
],
|
||||
"sourcetag": "NAIP"
|
||||
},
|
||||
{
|
||||
"name": "Ireland - NLS Historic Maps",
|
||||
"template": "http://geo.nls.uk/maps/ireland/gsgs4136/{z}/{x}/{y}.png",
|
||||
"extent": [
|
||||
[
|
||||
-10.71,
|
||||
51.32
|
||||
],
|
||||
[
|
||||
-5.37,
|
||||
55.46
|
||||
]
|
||||
],
|
||||
"sourcetag": "NLS Historic Maps",
|
||||
"logo": "icons/logo_nls70-nq8.png",
|
||||
"logo_url": "http://geo.nls.uk/maps/"
|
||||
},
|
||||
{
|
||||
"name": "Denmark - Fugro Aerial Imagery",
|
||||
"template": "http://tile.openstreetmap.dk/fugro2005/{z}/{x}/{y}.jpg",
|
||||
"extent": [
|
||||
[
|
||||
7.81,
|
||||
54.44
|
||||
],
|
||||
[
|
||||
15.49,
|
||||
57.86
|
||||
]
|
||||
],
|
||||
"sourcetag": "Fugro (2005)"
|
||||
},
|
||||
{
|
||||
"name": "Denmark - Stevns Kommune",
|
||||
"template": "http://tile.openstreetmap.dk/stevns/2009/{z}/{x}/{y}.jpg",
|
||||
"extent": [
|
||||
[
|
||||
12.09144,
|
||||
55.23403
|
||||
],
|
||||
[
|
||||
12.47712,
|
||||
55.43647
|
||||
]
|
||||
],
|
||||
"sourcetag": "Stevns Kommune (2009)"
|
||||
},
|
||||
{
|
||||
"name": "Austria - geoimage.at",
|
||||
"template": "http://geoimage.openstreetmap.at/4d80de696cd562a63ce463a58a61488d/{z}/{x}/{y}.jpg",
|
||||
"extent": [
|
||||
[
|
||||
9.36,
|
||||
46.33
|
||||
],
|
||||
[
|
||||
17.28,
|
||||
49.09
|
||||
]
|
||||
],
|
||||
"sourcetag": "geoimage.at"
|
||||
},
|
||||
{
|
||||
"name": "Russia - Kosmosnimki.ru IRS Satellite",
|
||||
"template": "http://irs.gis-lab.info/?layers=irs&request=GetTile&z={z}&x={x}&y={y}",
|
||||
"extent": [
|
||||
[
|
||||
19.02,
|
||||
40.96
|
||||
],
|
||||
[
|
||||
77.34,
|
||||
70.48
|
||||
]
|
||||
],
|
||||
"sourcetag": "Kosmosnimki.ru IRS"
|
||||
},
|
||||
{
|
||||
"name": "Belarus - Kosmosnimki.ru SPOT4 Satellite",
|
||||
"template": "http://irs.gis-lab.info/?layers=spot&request=GetTile&z={z}&x={x}&y={y}",
|
||||
"extent": [
|
||||
[
|
||||
23.16,
|
||||
51.25
|
||||
],
|
||||
[
|
||||
32.83,
|
||||
56.19
|
||||
]
|
||||
],
|
||||
"sourcetag": "Kosmosnimki.ru SPOT4"
|
||||
},
|
||||
{
|
||||
"name": "Australia - Geographic Reference Image",
|
||||
"template": "http://agri.openstreetmap.org/{z}/{x}/{y}.png",
|
||||
"extent": [
|
||||
[
|
||||
96,
|
||||
-44
|
||||
],
|
||||
[
|
||||
168,
|
||||
-9
|
||||
]
|
||||
],
|
||||
"sourcetag": "AGRI"
|
||||
},
|
||||
{
|
||||
"name": "Switzerland - Canton Aargau - AGIS 25cm 2011",
|
||||
"template": "http://tiles.poole.ch/AGIS/OF2011/{z}/{x}/{y}.png",
|
||||
"extent": [
|
||||
[
|
||||
7.69,
|
||||
47.13
|
||||
],
|
||||
[
|
||||
8.48,
|
||||
47.63
|
||||
]
|
||||
],
|
||||
"sourcetag": "AGIS OF2011"
|
||||
},
|
||||
{
|
||||
"name": "Switzerland - Canton Solothurn - SOGIS 2007",
|
||||
"template": "http://mapproxy.sosm.ch:8080/tiles/sogis2007/EPSG900913/{z}/{x}/{y}.png?origin=nw",
|
||||
"extent": [
|
||||
[
|
||||
7.33,
|
||||
47.06
|
||||
],
|
||||
[
|
||||
8.04,
|
||||
47.5
|
||||
]
|
||||
],
|
||||
"sourcetag": "Orthofoto 2007 WMS Solothurn"
|
||||
},
|
||||
{
|
||||
"name": "Poland - Media-Lab fleet GPS masstracks",
|
||||
"template": "http://masstracks.media-lab.com.pl/{z}/{x}/{y}.png",
|
||||
"extent": [
|
||||
[
|
||||
14,
|
||||
48.9
|
||||
],
|
||||
[
|
||||
24.2,
|
||||
55
|
||||
]
|
||||
],
|
||||
"sourcetag": "masstracks"
|
||||
},
|
||||
{
|
||||
"name": "South Africa - CD:NGI Aerial",
|
||||
"template": "http://{t}.aerial.openstreetmap.org.za/ngi-aerial/{z}/{x}/{y}.jpg",
|
||||
"subdomains": [
|
||||
"a",
|
||||
"b",
|
||||
"c"
|
||||
],
|
||||
"extent": [
|
||||
[
|
||||
17.64,
|
||||
-34.95
|
||||
],
|
||||
[
|
||||
32.87,
|
||||
-22.05
|
||||
]
|
||||
],
|
||||
"sourcetag": "ngi-aerial"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,233 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<imagery>
|
||||
<set>
|
||||
<name>Bing aerial imagery</name>
|
||||
<url>http://ecn.t${0|1|2|3}.tiles.virtualearth.net/tiles/a$quadkey.jpeg?g=587&mkt=en-gb&n=z</url>
|
||||
<scheme>microsoft</scheme>
|
||||
<sourcetag>Bing</sourcetag>
|
||||
<attribution_url>http://dev.virtualearth.net/REST/v1/Imagery/Metadata/Aerial/0,0?zl=1&mapVersion=v1&key=Arzdiw4nlOJzRwOz__qailc8NiR31Tt51dN2D7cm57NrnceZnCpgOkmJhNpGoppU&include=ImageryProviders&output=xml</attribution_url>
|
||||
<logo>bing_maps.png</logo>
|
||||
<logo_url>http://www.bing.com/maps</logo_url>
|
||||
<terms_url>http://opengeodata.org/microsoft-imagery-details</terms_url>
|
||||
<default>yes</default>
|
||||
</set>
|
||||
<set>
|
||||
<name>MapBox Satellite</name>
|
||||
<url>http://${a|b|c}.tiles.mapbox.com/v3/openstreetmap.map-4wvf9l0l/$z/$x/$y.png</url>
|
||||
<terms_url>http://mapbox.com/tos/</terms_url>
|
||||
</set>
|
||||
<set>
|
||||
<name>MapQuest Open Aerial</name>
|
||||
<url>http://oatile1.mqcdn.com/tiles/1.0.0/sat/$z/$x/$y.jpg</url>
|
||||
<terms_url>http://developer.mapquest.com/web/products/open/map#terms</terms_url>
|
||||
</set>
|
||||
<set>
|
||||
<name>OSM - Mapnik</name>
|
||||
<url>http://${a|b|c}.tile.openstreetmap.org/$z/$x/$y.png</url>
|
||||
</set>
|
||||
<set>
|
||||
<name>OSM - OpenCycleMap</name>
|
||||
<url>http://tile.opencyclemap.org/cycle/$z/$x/$y.png</url>
|
||||
</set>
|
||||
<set>
|
||||
<name>OSM - MapQuest</name>
|
||||
<url>http://otile1.mqcdn.com/tiles/1.0.0/osm/$z/$x/$y.jpg</url>
|
||||
</set>
|
||||
<set minlat="24.055" minlon="-124.810" maxlat="49.386" maxlon="-66.865">
|
||||
<name>OSM - Tiger Edited Map</name>
|
||||
<type>900913</type>
|
||||
<url>http://tiger-osm.mapquest.com/tiles/1.0.0/tiger/$z/$x/$y.png</url>
|
||||
</set>
|
||||
<set minlat="50.858" minlon="-179.754" maxlat="71.463" maxlon="-129.899">
|
||||
<name>OSM - Tiger Edited Map</name>
|
||||
<type>900913</type>
|
||||
<url>http://tiger-osm.mapquest.com/tiles/1.0.0/tiger/$z/$x/$y.png</url>
|
||||
</set>
|
||||
<set minlat="18.702" minlon="-174.460" maxlat="26.501" maxlon="-154.516">
|
||||
<name>OSM - Tiger Edited Map</name>
|
||||
<type>900913</type>
|
||||
<url>http://tiger-osm.mapquest.com/tiles/1.0.0/tiger/$z/$x/$y.png</url>
|
||||
</set>
|
||||
<set minlat="24.055" minlon="-124.810" maxlat="49.386" maxlon="-66.865">
|
||||
<name>OSM US TIGER 2012 Roads Overlay</name>
|
||||
<type>900913</type>
|
||||
<url>http://${a|b|c}.tile.openstreetmap.us/tiger2012_roads_expanded/$z/$x/$y.png</url>
|
||||
</set>
|
||||
<set minlat="50.858" minlon="-179.754" maxlat="71.463" maxlon="-129.899">
|
||||
<name>OSM US TIGER 2012 Roads Overlay</name>
|
||||
<type>900913</type>
|
||||
<url>http://${a|b|c}.tile.openstreetmap.us/tiger2012_roads_expanded/$z/$x/$y.png</url>
|
||||
</set>
|
||||
<set minlat="18.702" minlon="-174.460" maxlat="26.501" maxlon="-154.516">
|
||||
<name>OSM US TIGER 2012 Roads Overlay</name>
|
||||
<type>900913</type>
|
||||
<url>http://${a|b|c}.tile.openstreetmap.us/tiger2012_roads_expanded/$z/$x/$y.png</url>
|
||||
</set>
|
||||
<set minlat="24.005" minlon="-125.991" maxlat="50.009" maxlon="-65.988">
|
||||
<name>OSM US USGS Topographic Maps</name>
|
||||
<type>900913</type>
|
||||
<url>http://${a|b|c}.tile.openstreetmap.us/usgs_scanned_topos/$z/$x/$y.png</url>
|
||||
</set>
|
||||
<set minlat="18.902" minlon="-160.579" maxlat="22.508" maxlon="-154.793">
|
||||
<name>OSM US USGS Topographic Maps</name>
|
||||
<type>900913</type>
|
||||
<url>http://${a|b|c}.tile.openstreetmap.us/usgs_scanned_topos/$z/$x/$y.png</url>
|
||||
</set>
|
||||
<set minlat="51.255" minlon="-178.001" maxlat="71.999" maxlon="-130.004">
|
||||
<name>OSM US USGS Topographic Maps</name>
|
||||
<type>900913</type>
|
||||
<url>http://${a|b|c}.tile.openstreetmap.us/usgs_scanned_topos/$z/$x/$y.png</url>
|
||||
</set>
|
||||
<set minlat="24.496" minlon="-124.819" maxlat="49.443" maxlon="-66.931">
|
||||
<name>OSM US USGS Large Scale Aerial Imagery</name>
|
||||
<type>900913</type>
|
||||
<url>http://${a|b|c}.tile.openstreetmap.us/usgs_large_scale/$z/$x/$y.jpg</url>
|
||||
</set>
|
||||
<set minlat="48.995" minlon="-123.441" maxlat="50.426" maxlon="-121.346">
|
||||
<name>British Columbia bc_mosaic</name>
|
||||
<type>900913</type>
|
||||
<url>http://${a|b|c|d}.imagery.paulnorman.ca/tiles/bc_mosaic/$z/$x/$y.png</url>
|
||||
<terms_url>http://imagery.paulnorman.ca/tiles/about.html</terms_url>
|
||||
<sourcetag>bc_mosaic</sourcetag>
|
||||
</set>
|
||||
<set minlat="49.86" minlon="-8.72" maxlat="60.92" maxlon="1.84">
|
||||
<name>OS OpenData Streetview</name>
|
||||
<url>http://os.openstreetmap.org/sv/$z/$x/$y.png</url>
|
||||
<sourcetag>OS_OpenData_StreetView</sourcetag>
|
||||
</set>
|
||||
<set minlat="49.8" minlon="-9" maxlat="61.1" maxlon="1.9">
|
||||
<name>OS OpenData Locator</name>
|
||||
<url>http://tiles.itoworld.com/os_locator/$z/$x/$y.png</url>
|
||||
<sourcetag>OS_OpenData_Locator</sourcetag>
|
||||
<sourcekey>source:name</sourcekey>
|
||||
</set>
|
||||
<set minlat="49.8" minlon="-9" maxlat="61.1" maxlon="1.9">
|
||||
<name>OS 1:25k historic (OSM)</name>
|
||||
<url>http://ooc.openstreetmap.org/os1/$z/$x/$y.jpg</url>
|
||||
<sourcetag>OS 1:25k</sourcetag>
|
||||
</set>
|
||||
<set minlat="49.8" minlon="-9" maxlat="61.1" maxlon="1.9">
|
||||
<name>OS 1:25k historic (NLS)</name>
|
||||
<scheme>tms</scheme>
|
||||
<url>http://geo.nls.uk/mapdata2/os/25000/$z/$x/$y.png</url>
|
||||
<logo>icons/logo_nls70-nq8.png</logo>
|
||||
<logo_url>http://geo.nls.uk/maps/</logo_url>
|
||||
<sourcetag>OS 1:25k</sourcetag>
|
||||
</set>
|
||||
<set minlat="49.8" minlon="-9" maxlat="61.1" maxlon="1.9">
|
||||
<name>OS 7th Series historic (OSM)</name>
|
||||
<url>http://ooc.openstreetmap.org/os7/$z/$x/$y.jpg</url>
|
||||
<sourcetag>OS7</sourcetag>
|
||||
</set>
|
||||
<set minlat="49.8" minlon="-9" maxlat="61.1" maxlon="1.9">
|
||||
<name>OS 7th Series historic (NLS)</name>
|
||||
<scheme>tms</scheme>
|
||||
<url>http://geo.nls.uk/mapdata2/os/seventh/$z/$x/$y.png</url>
|
||||
<logo>icons/logo_nls70-nq8.png</logo>
|
||||
<logo_url>http://geo.nls.uk/maps/</logo_url>
|
||||
<sourcetag>OS7</sourcetag>
|
||||
</set>
|
||||
<set minlat="49.8" minlon="-5.8" maxlat="55.8" maxlon="1.9">
|
||||
<name>OS New Popular Edition historic</name>
|
||||
<url>http://ooc.openstreetmap.org/npe/$z/$x/$y.png</url>
|
||||
<sourcetag>NPE</sourcetag>
|
||||
</set>
|
||||
<set minlat="54.5" minlon="-7.8" maxlat="61.1" maxlon="-1.1">
|
||||
<name>OS Scottish Popular historic</name>
|
||||
<url>http://ooc.openstreetmap.org/npescotland/tiles/$z/$x/$y.jpg</url>
|
||||
<sourcetag>NPE</sourcetag>
|
||||
</set>
|
||||
<set minlat="51.071" minlon="-0.856" maxlat="51.473" maxlon="0.062">
|
||||
<name>Surrey aerial</name>
|
||||
<url>http://gravitystorm.dev.openstreetmap.org/surrey/$z/$x/$y.png</url>
|
||||
<sourcetag>Surrey aerial</sourcetag>
|
||||
</set>
|
||||
<set minlat="17.95" minlon="-74.5" maxlat="20.12" maxlon="-71.58">
|
||||
<name>Haiti - GeoEye Jan 13</name>
|
||||
<url>http://gravitystorm.dev.openstreetmap.org/imagery/haiti/$z/$x/$y.jpg</url>
|
||||
<sourcetag>Haiti GeoEye</sourcetag>
|
||||
</set>
|
||||
<set minlat="17.95" minlon="-74.5" maxlat="20.12" maxlon="-71.58">
|
||||
<name>Haiti - GeoEye Jan 13+</name>
|
||||
<url>http://maps.nypl.org/tilecache/1/geoeye/$z/$x/$y.jpg</url>
|
||||
<sourcetag>Haiti GeoEye</sourcetag>
|
||||
</set>
|
||||
<set minlat="17.95" minlon="-74.5" maxlat="20.12" maxlon="-71.58">
|
||||
<name>Haiti - DigitalGlobe</name>
|
||||
<url>http://maps.nypl.org/tilecache/1/dg_crisis/$z/$x/$y.jpg</url>
|
||||
<sourcetag>Haiti DigitalGlobe</sourcetag>
|
||||
</set>
|
||||
<set minlat="17.95" minlon="-74.5" maxlat="20.12" maxlon="-71.58">
|
||||
<name>Haiti - Street names</name>
|
||||
<url>http://hypercube.telascience.org/tiles/1.0.0/haiti-city/$z/$x/$y.jpg</url>
|
||||
<sourcetag>Haiti streetnames</sourcetag>
|
||||
</set>
|
||||
<set minlat="24.2" minlon="-125.8" maxlat="49.5" maxlon="-62.3">
|
||||
<name>National Agriculture Imagery Program</name>
|
||||
<url>http://cube.telascience.org/tilecache/tilecache.py/NAIP_ALL/$z/$x/$y.png</url>
|
||||
<sourcetag>NAIP</sourcetag>
|
||||
</set>
|
||||
<set minlat="55.3" minlon="-168.5" maxlat="71.5" maxlon="-140">
|
||||
<name>National Agriculture Imagery Program</name>
|
||||
<url>http://cube.telascience.org/tilecache/tilecache.py/NAIP_ALL/$z/$x/$y.png</url>
|
||||
<sourcetag>NAIP</sourcetag>
|
||||
</set>
|
||||
<set minlat="51.32" minlon="-10.71" maxlat="55.46" maxlon="-5.37">
|
||||
<name>Ireland - NLS Historic Maps</name>
|
||||
<scheme>tms</scheme>
|
||||
<sourcetag>NLS Historic Maps</sourcetag>
|
||||
<url>http://geo.nls.uk/maps/ireland/gsgs4136/$z/$x/$y.png</url>
|
||||
<logo>icons/logo_nls70-nq8.png</logo>
|
||||
<logo_url>http://geo.nls.uk/maps/</logo_url>
|
||||
</set>
|
||||
<set minlat="54.44" minlon="7.81" maxlat="57.86" maxlon="15.49">
|
||||
<name>Denmark - Fugro Aerial Imagery</name>
|
||||
<url>http://tile.openstreetmap.dk/fugro2005/$z/$x/$y.jpg</url>
|
||||
<sourcetag>Fugro (2005)</sourcetag>
|
||||
</set>
|
||||
<set minlat="55.23403" minlon="12.09144" maxlat="55.43647" maxlon="12.47712">
|
||||
<name>Denmark - Stevns Kommune</name>
|
||||
<url>http://tile.openstreetmap.dk/stevns/2009/$z/$x/$y.jpg</url>
|
||||
<sourcetag>Stevns Kommune (2009)</sourcetag>
|
||||
</set>
|
||||
<set minlat="46.33" minlon="9.36" maxlat="49.09" maxlon="17.28">
|
||||
<name>Austria - geoimage.at</name>
|
||||
<url>http://geoimage.openstreetmap.at/4d80de696cd562a63ce463a58a61488d/$z/$x/$y.jpg</url>
|
||||
<sourcetag>geoimage.at</sourcetag>
|
||||
</set>
|
||||
<set minlon="19.02" minlat="40.96" maxlon="77.34" maxlat="70.48">
|
||||
<name>Russia - Kosmosnimki.ru IRS Satellite</name>
|
||||
<url>http://irs.gis-lab.info/?layers=irs&request=GetTile&z=$z&x=$x&y=$y</url>
|
||||
<sourcetag>Kosmosnimki.ru IRS</sourcetag>
|
||||
</set>
|
||||
<set minlon="23.16" minlat="51.25" maxlon="32.83" maxlat="56.19">
|
||||
<name>Belarus - Kosmosnimki.ru SPOT4 Satellite</name>
|
||||
<url>http://irs.gis-lab.info/?layers=spot&request=GetTile&z=$z&x=$x&y=$y</url>
|
||||
<sourcetag>Kosmosnimki.ru SPOT4</sourcetag>
|
||||
</set>
|
||||
<set minlon="96" minlat="-44" maxlon="168" maxlat="-9">
|
||||
<name>Australia - Geographic Reference Image</name>
|
||||
<url>http://agri.openstreetmap.org/$z/$x/$y.png</url>
|
||||
<sourcetag>AGRI</sourcetag>
|
||||
</set>
|
||||
<set minlat="47.13" minlon="7.69" maxlat="47.63" maxlon="8.48">
|
||||
<name>Switzerland - Canton Aargau - AGIS 25cm 2011</name>
|
||||
<url>http://tiles.poole.ch/AGIS/OF2011/$z/$x/$y.png</url>
|
||||
<sourcetag>AGIS OF2011</sourcetag>
|
||||
</set>
|
||||
<set minlat="47.06" minlon="7.33" maxlat="47.5" maxlon="8.04">
|
||||
<name>Switzerland - Canton Solothurn - SOGIS 2007</name>
|
||||
<url>http://mapproxy.sosm.ch:8080/tiles/sogis2007/EPSG900913/$z/$x/$y.png?origin=nw</url>
|
||||
<sourcetag>Orthofoto 2007 WMS Solothurn</sourcetag>
|
||||
</set>
|
||||
<set minlat="48.9" minlon="14" maxlat="55" maxlon="24.2">
|
||||
<name>Poland - Media-Lab fleet GPS masstracks</name>
|
||||
<url>http://masstracks.media-lab.com.pl/$z/$x/$y.png</url>
|
||||
<sourcetag>masstracks</sourcetag>
|
||||
</set>
|
||||
<set minlat="-34.95" minlon="17.64" maxlat="-22.05" maxlon="32.87">
|
||||
<name>South Africa - CD:NGI Aerial</name>
|
||||
<url>http://${a|b|c}.aerial.openstreetmap.org.za/ngi-aerial/$z/$x/$y.jpg</url>
|
||||
<sourcetag>ngi-aerial</sourcetag>
|
||||
</set>
|
||||
</imagery>
|
||||
@@ -0,0 +1,87 @@
|
||||
var fs = require('fs'),
|
||||
cheerio = require('cheerio');
|
||||
|
||||
$ = cheerio.load(fs.readFileSync('imagery.xml'));
|
||||
|
||||
var imagery = [];
|
||||
|
||||
// CENSORSHIP! No, these are just layers that essentially duplicate other layers
|
||||
// or which have no clear use case.
|
||||
var censor = {
|
||||
'MapQuest Open Aerial': true,
|
||||
'OSM - OpenCycleMap': true,
|
||||
'OSM - MapQuest': true
|
||||
};
|
||||
|
||||
var replace = {
|
||||
'OSM - Mapnik': 'OpenStreetMap',
|
||||
'National Agriculture Imagery Program': 'NAIP'
|
||||
};
|
||||
|
||||
var description = {
|
||||
'MapBox Satellite': 'Satellite and aerial imagery',
|
||||
'OpenStreetMap': 'The default OpenStreetMap layer.',
|
||||
'OSM US TIGER 2012 Roads Overlay': 'Public domain road data from the US Government.',
|
||||
'Bing aerial imagery': 'Satellite imagery.',
|
||||
'NAIP': 'National Agriculture Imagery Program'
|
||||
};
|
||||
|
||||
var scaleExtent = {
|
||||
'MapBox Satellite': [0, 16],
|
||||
'OpenStreetMap': [0, 18],
|
||||
'OSM US TIGER 2012 Roads Overlay': [0, 17],
|
||||
'Bing aerial imagery': [0, 20]
|
||||
};
|
||||
|
||||
$('set').each(function(i) {
|
||||
var elem = $(this);
|
||||
|
||||
var im = {
|
||||
name: $(this).find('name').first().text(),
|
||||
template: $(this).find('url').first().text()
|
||||
};
|
||||
|
||||
// no luck with mapquest servers currently...
|
||||
if (im.template.match(/mapquest/g)) return;
|
||||
if (censor[im.name]) return;
|
||||
|
||||
im.name = im.name.replace('OSM US', '');
|
||||
|
||||
if (replace[im.name]) im.name = replace[im.name];
|
||||
|
||||
if (description[im.name]) im.description = description[im.name];
|
||||
|
||||
if (scaleExtent[im.name]) im.scaleExtent = scaleExtent[im.name];
|
||||
|
||||
var subdomains = [];
|
||||
|
||||
im.template = im.template
|
||||
.replace('$quadkey', '{u}')
|
||||
.replace(/\$(\w)/g, function(m) {
|
||||
return '{' + m[1] + '}';
|
||||
})
|
||||
.replace(/\$\{([^}.]+)\}/g, function(m) {
|
||||
subdomains = m.slice(2, m.length - 1).split('|');
|
||||
return '{t}';
|
||||
});
|
||||
|
||||
if (subdomains.length) im.subdomains = subdomains;
|
||||
|
||||
if (elem.attr('minlat')) {
|
||||
im.extent = [
|
||||
[+elem.attr('minlon'),
|
||||
+elem.attr('minlat')],
|
||||
[+elem.attr('maxlon'),
|
||||
+elem.attr('maxlat')]];
|
||||
}
|
||||
|
||||
['default', 'sourcetag', 'logo', 'logo_url', 'terms_url'].forEach(function(a) {
|
||||
if (elem.find(a).length) {
|
||||
im[a] = elem.find(a).first().text();
|
||||
}
|
||||
});
|
||||
imagery.push(im);
|
||||
});
|
||||
|
||||
fs.writeFileSync('imagery.json', JSON.stringify(imagery, null, 4));
|
||||
fs.writeFileSync('imagery.js', 'iD.data.imagery = ' + JSON.stringify(imagery, null, 4) + ';');
|
||||
|
Before Width: | Height: | Size: 102 B After Width: | Height: | Size: 158 B |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 338 B |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 97 KiB |
|
Before Width: | Height: | Size: 1019 KiB After Width: | Height: | Size: 1021 KiB |
@@ -9,7 +9,7 @@
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="400"
|
||||
width="420"
|
||||
height="200"
|
||||
id="svg12393"
|
||||
version="1.1"
|
||||
@@ -39,14 +39,14 @@
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1"
|
||||
inkscape:cx="336.77382"
|
||||
inkscape:cy="126.79999"
|
||||
inkscape:cx="304.46947"
|
||||
inkscape:cy="116.03146"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer12"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1280"
|
||||
inkscape:window-height="756"
|
||||
inkscape:window-x="119"
|
||||
inkscape:window-height="700"
|
||||
inkscape:window-x="48"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="0"
|
||||
fit-margin-top="0"
|
||||
@@ -56,7 +56,7 @@
|
||||
showguides="false"
|
||||
inkscape:guide-bbox="true"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:snap-nodes="true">
|
||||
inkscape:snap-nodes="false">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid12420"
|
||||
@@ -172,6 +172,10 @@
|
||||
orientation="1,0"
|
||||
position="400,210"
|
||||
id="guide15997" />
|
||||
<sodipodi:guide
|
||||
orientation="1,0"
|
||||
position="420,191"
|
||||
id="guide10219" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata12398">
|
||||
@@ -181,7 +185,7 @@
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
@@ -190,11 +194,69 @@
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-25,-62.362183)"
|
||||
style="display:inline">
|
||||
style="display:none">
|
||||
<rect
|
||||
style="color:#000000;fill:#323232;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="rect4478"
|
||||
width="420"
|
||||
height="201"
|
||||
x="25"
|
||||
y="61.362183" />
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer12"
|
||||
inkscape:label="sprite"
|
||||
transform="translate(-25,3.0625001e-6)">
|
||||
<g
|
||||
transform="translate(105.03464,-25.104239)"
|
||||
id="g58869"
|
||||
style="fill:#ffffff;fill-opacity:1">
|
||||
<g
|
||||
id="g58871"
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter8013-4);enable-background:accumulate" />
|
||||
<g
|
||||
id="g58873"
|
||||
style="fill:#ffffff;fill-opacity:1" />
|
||||
</g>
|
||||
<g
|
||||
id="g5460"
|
||||
transform="translate(-321,-101.36218)"
|
||||
style="fill:#6bc641;fill-opacity:1;display:inline" />
|
||||
<g
|
||||
style="opacity:0.25;fill:#000000;fill-opacity:1;display:inline"
|
||||
transform="translate(-321,-62.36218)"
|
||||
id="g16215" />
|
||||
<g
|
||||
transform="matrix(-0.70710678,0.70710679,0.70710679,0.70710678,877.1436,-601.56033)"
|
||||
id="g16306-5"
|
||||
style="display:inline" />
|
||||
<g
|
||||
transform="translate(105.03464,-6.104239)"
|
||||
id="g58885">
|
||||
<g
|
||||
id="g58887"
|
||||
style="color:#000000;fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter8013-4);enable-background:accumulate" />
|
||||
<g
|
||||
id="g58889" />
|
||||
</g>
|
||||
<g
|
||||
id="g11035"
|
||||
style="fill:#ffffff;fill-opacity:1;display:inline"
|
||||
transform="translate(-354,-135)">
|
||||
<g
|
||||
style="fill:#ffffff;fill-opacity:1;display:inline"
|
||||
id="g11037"
|
||||
transform="matrix(0.70710678,0.70710679,-0.70710679,0.70710678,-113.14357,-447.56033)" />
|
||||
<g
|
||||
transform="matrix(-0.70710678,0.70710679,0.70710679,0.70710678,1293.1436,-447.56033)"
|
||||
id="g11041"
|
||||
style="fill:#ffffff;fill-opacity:1;display:inline" />
|
||||
</g>
|
||||
<g
|
||||
id="g9591"
|
||||
style="fill:#1a1a1a;fill-opacity:1;display:inline"
|
||||
transform="translate(505,-591)">
|
||||
style="display:inline;fill:#1a1a1a;fill-opacity:1"
|
||||
transform="translate(505,-653.36218)">
|
||||
<path
|
||||
style="color:#000000;fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="m -130.5,603 c -4.14213,0 -7.5,3.35787 -7.5,7.5 0,4.14214 3.35787,7.5 7.5,7.5 4.14213,0 7.5,-3.35786 7.5,-7.5 0,-4.14213 -3.35787,-7.5 -7.5,-7.5 z m 0,1 c 3.58393,0 6.5,2.91607 6.5,6.5 0,3.58393 -2.91607,6.5 -6.5,6.5 -3.58393,0 -6.5,-2.91607 -6.5,-6.5 0,-3.58393 2.91607,-6.5 6.5,-6.5 z"
|
||||
@@ -252,40 +314,31 @@
|
||||
</g>
|
||||
</g>
|
||||
<path
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
transform="translate(0,-62.362186)"
|
||||
style="display:inline;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;overflow:visible;enable-background:accumulate"
|
||||
d="m 388,72.362183 0,-2 10,-4 2,0 0,2 -4,10 -2,0 0,-6 z"
|
||||
id="path15565"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccccc" />
|
||||
<path
|
||||
transform="translate(0,-62.362186)"
|
||||
sodipodi:nodetypes="ccccccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3767"
|
||||
d="m 388,92.362183 0,-2 10,-4 2,0 0,2 -4,10 -2,0 0,-6 z"
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
style="display:inline;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;overflow:visible;enable-background:accumulate" />
|
||||
<path
|
||||
style="opacity:0.5;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
transform="translate(0,-62.362186)"
|
||||
style="display:inline;opacity:0.50000000000000000;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;overflow:visible;enable-background:accumulate"
|
||||
d="m 388,112.36218 0,-2 10,-4 2,0 0,2 -4,10 -2,0 0,-6 z"
|
||||
id="path3769"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccccc" />
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer12"
|
||||
inkscape:label="sprite"
|
||||
transform="translate(-25,3.0625e-6)">
|
||||
<g
|
||||
transform="translate(105.03464,-25.104239)"
|
||||
id="g58869"
|
||||
style="fill:#ffffff;fill-opacity:1">
|
||||
<g
|
||||
id="g58871"
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter8013-4);enable-background:accumulate" />
|
||||
<g
|
||||
id="g58873"
|
||||
style="fill:#ffffff;fill-opacity:1" />
|
||||
</g>
|
||||
<path
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="m 255,3.9999969 -1,1 0,1 1,1 1,0 1,-1 0,-1 -1,-1 -1,0 z m 0,4 -1,1 0,5.0000001 1,1 1,0 1,-1 0,-5.0000001 -1,-1 -1,0 z"
|
||||
id="path10936"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="color:#000000;fill:#222222;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter8013-4);enable-background:accumulate"
|
||||
@@ -298,13 +351,9 @@
|
||||
id="path5387" />
|
||||
<path
|
||||
style="color:#000000;fill:#222222;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter8013-4);enable-background:accumulate"
|
||||
d="m 55,3.9999981 c -2.76142,0 -5,2.23858 -5,5 0,2.7614299 5,6.9999999 5,6.9999999 0,0 5,-4.23857 5,-6.9999999 0,-2.76142 -2.23858,-5 -5,-5 z m 0.15625,3 c 1.10457,0 2,0.89543 2,2 0,1.1045699 -0.89543,1.9999999 -2,1.9999999 -1.104569,0 -2,-0.89543 -2,-1.9999999 0,-1.10457 0.895431,-2 2,-2 z"
|
||||
d="m 57,3.9999981 c -2.76142,0 -5,2.23858 -5,5 0,2.7614299 5,6.9999999 5,6.9999999 0,0 5,-4.23857 5,-6.9999999 0,-2.76142 -2.23858,-5 -5,-5 z m 0.15625,3 c 1.10457,0 2,0.89543 2,2 0,1.1045699 -0.89543,1.9999999 -2,1.9999999 -1.104569,0 -2,-0.89543 -2,-1.9999999 0,-1.10457 0.895431,-2 2,-2 z"
|
||||
id="path8139"
|
||||
inkscape:connector-curvature="0" />
|
||||
<g
|
||||
id="g5460"
|
||||
transform="translate(-321,-101.36218)"
|
||||
style="fill:#6bc641;fill-opacity:1;display:inline" />
|
||||
<path
|
||||
style="color:#000000;fill:#222222;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="m 113,2.01282 -5,4.5 5,4.5 0,-3 3,0 L 117,9 117,12.01282 116,13 l -5,0.0128 -1,1.00002 0,1 1,0.99998 5,0 2,-0.99998 1,-1 1,-2.00002 0,-3 -1,-1.99998 -1,-1 -2,-1.00002 -3,0 z"
|
||||
@@ -323,19 +372,11 @@
|
||||
id="path9203"
|
||||
d="m 136,2.01282 5,4.5 -5,4.5 0,-3 -3,0 L 132,9 l 0,3.01282 1,0.98718 5,0.0128 1,1.00002 0,1 -1,0.99998 -5,0 -2,-0.99998 -1,-1 -1,-2.00002 0,-3 1,-1.99998 1,-1 2,-1.00002 3,0 z"
|
||||
style="color:#000000;fill:#222222;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<g
|
||||
style="opacity:0.25;fill:#000000;fill-opacity:1;display:inline"
|
||||
transform="translate(-321,-62.36218)"
|
||||
id="g16215" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path9584-1-9"
|
||||
d="m 190,3.9999992 -1,1 0,1 4,4 -4,3.9999998 0,1 1,1 1,0 4,-4 4,4 1,0 1,-1 0,-1 -4,-3.9999998 4,-4 0,-1 -1,-1 -1,0 -4,4 -4,-4 -1,0 z"
|
||||
style="color:#000000;fill:#222222;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<g
|
||||
transform="matrix(-0.70710678,0.70710679,0.70710679,0.70710678,877.1436,-601.56033)"
|
||||
id="g16306-5"
|
||||
style="display:inline" />
|
||||
<path
|
||||
style="color:#000000;fill:#222222;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="m 169.00002,9.9999989 5.99998,-7 6.00002,7.0000201 -4,-10e-6 -1e-5,6 -1.00001,0.99999 -2,0 -1,-0.99998 1e-5,-6.0000201 z"
|
||||
@@ -346,7 +387,7 @@
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90" />
|
||||
<rect
|
||||
style="opacity:0.2;color:#000000;fill:#222222;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter8013-4);enable-background:accumulate"
|
||||
style="opacity:0.20000000000000001;color:#000000;fill:#222222;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter8013-4);enable-background:accumulate"
|
||||
id="rect5406"
|
||||
width="6"
|
||||
height="5.999999"
|
||||
@@ -357,12 +398,6 @@
|
||||
id="path22362"
|
||||
d="M 159.5,4 154.5625,12.5625 151,9 l -1,0 -1,1 0,1 5,5 1,0 1,0 6,-10 0,-1 -1,-1 -1.5,0 z"
|
||||
style="color:#000000;fill:#222222;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="color:#000000;fill:#222222;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="m 210,2.999999 -1,1 0,1 1,1 9,0 1,-1 0,-1 -1,-1 z m 0,4 0,9 1,1 7,0 1,-1 0,-9 z m 2,2 1,0 0,6 -1,0 0,-1 z m 2,0 1,0 0,5 0,1 -1,0 z m 2,0 1,0 0,5 0,1 -1,0 z"
|
||||
id="path22366"
|
||||
sodipodi:nodetypes="cccccccccccccccccccccccccccccccccc" />
|
||||
<g
|
||||
transform="translate(-55,-130)"
|
||||
style="display:inline"
|
||||
@@ -499,27 +534,7 @@
|
||||
inkscape:export-ydpi="90" />
|
||||
</g>
|
||||
<g
|
||||
transform="translate(-355,-155)"
|
||||
style="display:inline"
|
||||
id="g45432">
|
||||
<g
|
||||
transform="matrix(0.70710678,0.70710679,-0.70710679,0.70710678,-113.14357,-447.56033)"
|
||||
id="g9588-1-5"
|
||||
style="fill:#ff7070;fill-opacity:1;display:inline">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="color:#000000;fill:#ff7070;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="m 586,160 -1,1 0,1 3,3 -3,3 0,1 1,1 1,0 3,-3 3,3 1,0 1,-1 0,-1 -3,-3 3,-3 0,-1 -1,-1 -1,0 -3,3 -3,-3 -1,0 z"
|
||||
transform="matrix(0.70710677,-0.70710678,0.70710678,0.70710677,396.47753,236.46835)"
|
||||
id="path9584-1-7" />
|
||||
</g>
|
||||
<g
|
||||
style="fill:#ff7070;fill-opacity:1;display:inline"
|
||||
id="g16306-51"
|
||||
transform="matrix(-0.70710678,0.70710679,0.70710679,0.70710678,1293.1436,-447.56033)" />
|
||||
</g>
|
||||
<g
|
||||
style="opacity:0.5;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
style="opacity:0.50000000000000000;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
transform="translate(-511.00001,-44)"
|
||||
id="g44379">
|
||||
<g
|
||||
@@ -567,40 +582,12 @@
|
||||
d="m 313.5,3.00001 c -3.03757,0 -5.5,2.46243 -5.5,5.5 0,3.03757 2.46243,5.5 5.5,5.5 1.00612,0 1.93866,-0.27827 2.75,-0.75 l 3.75,3.75 1,0 1,-1 0,-1 -3.75,-3.75 c 0.47173,-0.81134 0.75,-1.74387 0.75,-2.75 0,-3.03757 -2.46243,-5.5 -5.5,-5.5 z m -0.5,2 1,0 2,1 1,2 0,1 -1,2 -2,1 -1,0 -2,-1 -1,-2 0,-1 1,-2 2,-1 z"
|
||||
id="path3048-0-7-5-6"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter8013-4);enable-background:accumulate"
|
||||
d="m 334.5,3 -6.5,3 0,1 6.5,3 1,0 6.5,-3 0,-1 -6.5,-3 -1,0 z M 329.09375,9 328,9.5 l 0,1 6.5,3 1,0 6.5,-3 0,-1 -1.09375,-0.5 -5.40625,2.5 -1,0 -5.40625,-2.5 z m 0,3.5 L 328,13 l 0,1 6.5,3 1,0 6.5,-3 0,-1 -1.09375,-0.5 -5.40625,2.5 -1,0 -5.40625,-2.5 z"
|
||||
id="path5530-2"
|
||||
inkscape:connector-curvature="0" />
|
||||
<g
|
||||
transform="translate(105.03464,-6.104239)"
|
||||
id="g58885">
|
||||
<g
|
||||
id="g58887"
|
||||
style="color:#000000;fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter8013-4);enable-background:accumulate" />
|
||||
<g
|
||||
id="g58889" />
|
||||
</g>
|
||||
<path
|
||||
sodipodi:nodetypes="scsssscccsssssssssssscscscccscs"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path55334"
|
||||
d="m 35,4 c 0,1 0,4 0,4 0,0 0,0.5 -0.5,0.5 C 34,8.5 34.070717,8.22484 34,8 33.695312,7.03125 33.132813,5.63541 33,5 32.795405,4.02115 32.333333,4 32,4 31,4 31,5 31,5 l 1,4 0,3 C 32,12 31.5,11.5 30.5,10.5 29.945312,9.94531 29.257659,9.7508 28.8125,10.00781 28.377049,10.25922 28.150942,10.89541 28.5,11.5 28.853553,12.11237 32,16 32,16 c 1,1 2,1 4,1 2.666667,0 1,0 3,0 2,0 2.288488,-2.86546 3,-5 C 43,9 43.5,7 43.5,7 43.613427,6.57668 43.45711,6.154 43,6 42.119539,5.70338 41.63994,6.35278 41.5,7 41.25,8.15625 41,9 41,9 40.90625,9.31383 41.0013,9.5 40.5,9.5 39.99086,9.5 40,9 40,9 40,9 40,6.33333 40,5 40,4 39,4 39,4 c 0,0 -1,0 -1,1 0,1 0,1.66667 0,3 0,0 0.01305,0.5 -0.5,0.5 C 36.998673,8.5 37,8 37,8 37,8 37,5 37,4 37,3 36,3 36,3 36,3 35,3 35,4 z"
|
||||
style="color:#000000;fill:#222222;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter8013-4);enable-background:accumulate" />
|
||||
<rect
|
||||
y="80"
|
||||
x="65"
|
||||
height="40"
|
||||
width="40"
|
||||
id="rect44456"
|
||||
style="color:#000000;fill:none;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<rect
|
||||
style="color:#000000;fill:none;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="rect44458"
|
||||
width="40"
|
||||
height="40"
|
||||
x="105"
|
||||
y="80" />
|
||||
<path
|
||||
style="color:#000000;fill:#c1c1c1;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="m 85,88 c -5.5228,0 -10,4.47716 -10,10 0,5.52286 10,14 10,14 0,0 10,-8.47714 10,-14 0,-5.52284 -4.4772,-10 -10,-10 z m 0.3124,6 c 2.2092,0 4,1.79086 4,4 0,2.20914 -1.7908,4 -4,4 -2.209,0 -4,-1.79086 -4,-4 0,-2.20914 1.791,-4 4,-4 z"
|
||||
@@ -610,13 +597,6 @@
|
||||
transform="translate(-1015,19.999998)"
|
||||
style="display:inline"
|
||||
id="g44643">
|
||||
<rect
|
||||
y="60"
|
||||
x="1040"
|
||||
height="40"
|
||||
width="40"
|
||||
id="rect43311-5"
|
||||
style="color:#000000;fill:none;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<g
|
||||
transform="matrix(2,0,0,2,529,-143.72437)"
|
||||
id="g5401-6"
|
||||
@@ -660,7 +640,7 @@
|
||||
sodipodi:nodetypes="ccsccssccssccsccc" />
|
||||
<g
|
||||
id="g9693"
|
||||
style="opacity:0.5;fill:#000000;fill-opacity:1;display:inline"
|
||||
style="opacity:0.50000000000000000;fill:#000000;fill-opacity:1;display:inline"
|
||||
transform="translate(505,-613.36218)">
|
||||
<path
|
||||
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
@@ -720,26 +700,26 @@
|
||||
</g>
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="opacity:0.5;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter8013-4);enable-background:accumulate"
|
||||
style="opacity:0.50000000000000000;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter8013-4);enable-background:accumulate"
|
||||
d="m 90,44 -1,1 0,2 1,1 0,4 -1,1 0,2 1,1 2,0 1,-1 4,0 1,1 2,0 1,-1 0,-2 -1,-1 0,-4 1,-1 0,-2 -1,-1 -2,0 -1,1 -4,0 -1,-1 -2,0 z m 1,1 c 0.55228,0 1,0.447715 1,1 0,0.552285 -0.44772,1 -1,1 -0.55228,0 -1,-0.447715 -1,-1 0,-0.552285 0.44772,-1 1,-1 z m 8,0 c 0.55228,0 1,0.447715 1,1 0,0.552285 -0.44772,1 -1,1 -0.55228,0 -1,-0.447715 -1,-1 0,-0.552285 0.44772,-1 1,-1 z m -6,2 4,0 1,1 0,4 -1,1 -4,0 -1,-1 0,-4 1,-1 z m -2,6 c 0.55228,0 1,0.447715 1,1 0,0.552285 -0.44772,1 -1,1 -0.55228,0 -1,-0.447715 -1,-1 0,-0.552285 0.44772,-1 1,-1 z m 8,0 c 0.55228,0 1,0.447715 1,1 0,0.552285 -0.44772,1 -1,1 -0.55228,0 -1,-0.447715 -1,-1 0,-0.552285 0.44772,-1 1,-1 z"
|
||||
id="path16225" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="opacity:0.5;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter8013-4);enable-background:accumulate"
|
||||
style="opacity:0.50000000000000000;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter8013-4);enable-background:accumulate"
|
||||
d="m 79,43.000003 -1,1 0,1.59375 -6.40625,6.40625 -1.59375,0 -1,1 0,2 1,1 2,0 1,-1 0,-1.59375 6.40625,-6.40625 1.59375,0 1,-1 0,-2 -1,-1 -2,0 z m 1,1 c 0.55228,0 1,0.44772 1,1 0,0.55229 -0.44772,1 -1,1 -0.25152,0 -0.48052,-0.0967 -0.65625,-0.25 -0.0344,-0.03002 -0.0637,-0.05934 -0.0937,-0.09375 C 79.0967,45.480522 79,45.251524 79,45.000003 c 0,-0.55228 0.44772,-1 1,-1 z m -9,9 c 0.25152,0 0.48052,0.0967 0.65625,0.25 l 0.0937,0.09375 C 71.9033,53.519484 72,53.748487 72,54.000003 c 0,0.55229 -0.44772,1 -1,1 -0.55228,0 -1,-0.44771 -1,-1 0,-0.55228 0.44772,-1 1,-1 z"
|
||||
id="path16227" />
|
||||
<path
|
||||
style="opacity:0.5;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter8013-4);enable-background:accumulate"
|
||||
d="m 55,43.999998 c -2.76142,0 -5,2.23858 -5,5 0,2.76143 5,7 5,7 0,0 5,-4.23857 5,-7 0,-2.76142 -2.23858,-5 -5,-5 z m 0.15625,3 c 1.10457,0 2,0.89543 2,2 0,1.10457 -0.89543,2 -2,2 -1.104569,0 -2,-0.89543 -2,-2 0,-1.10457 0.895431,-2 2,-2 z"
|
||||
style="opacity:0.50000000000000000;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter8013-4);enable-background:accumulate"
|
||||
d="m 57,43.999998 c -2.76142,0 -5,2.23858 -5,5 0,2.76143 5,7 5,7 0,0 5,-4.23857 5,-7 0,-2.76142 -2.23858,-5 -5,-5 z m 0.15625,3 c 1.10457,0 2,0.89543 2,2 0,1.10457 -0.89543,2 -2,2 -1.104569,0 -2,-0.89543 -2,-2 0,-1.10457 0.895431,-2 2,-2 z"
|
||||
id="path16231"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="opacity:0.5;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
style="opacity:0.50000000000000000;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="M 159.5,44 154.5625,52.5625 151,49 l -1,0 -1,1 0,1 5,5 1,0 1,0 6,-10 0,-1 -1,-1 -1.5,0 z"
|
||||
id="path16235"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="opacity:0.5;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
style="opacity:0.50000000000000000;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="m 113,42.01282 -5,4.5 5,4.5 0,-3 3,0 1,0.98718 0,3.01282 -1,0.98718 -5,0.0128 -1,1.00002 0,1 1,0.99998 5,0 2,-0.99998 1,-1 1,-2.00002 0,-3 -1,-1.99998 -1,-1 -2,-1.00002 -3,0 z"
|
||||
id="path16239"
|
||||
inkscape:connector-curvature="0"
|
||||
@@ -755,14 +735,14 @@
|
||||
inkscape:connector-curvature="0"
|
||||
id="path16241"
|
||||
d="m 136,42.01282 5,4.5 -5,4.5 0,-3 -3,0 -1,0.98718 0,3.01282 1,0.98718 5,0.0128 1,1.00002 0,1 -1,0.99998 -5,0 -2,-0.99998 -1,-1 -1,-2.00002 0,-3 1,-1.99998 1,-1 2,-1.00002 3,0 z"
|
||||
style="opacity:0.5;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
style="opacity:0.50000000000000000;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<path
|
||||
id="path16411"
|
||||
d="m 190.00001,44.000007 -1,1 -1e-5,0.999995 4.00001,4.000004 -4,4 -1e-5,0.999995 1,1.000005 1,-5e-6 4,-4 4,4.000004 1.00001,2e-6 1,-0.999999 -1e-5,-1.000003 -4,-4.000004 4,-4 0,-0.999995 -1,-1.000005 -0.99999,5e-6 -4,4 L 191,44.000002 l -0.99999,5e-6 z"
|
||||
style="opacity:0.5;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
style="opacity:0.50000000000000000;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="opacity:0.5;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
style="opacity:0.50000000000000000;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="m 169.00002,49.999999 5.99998,-7 6.00002,7.00002 -4,-1e-5 -1e-5,6 -1.00001,0.99999 -2,0 -1,-0.99998 1e-5,-6.00002 z"
|
||||
id="path16625"
|
||||
inkscape:connector-curvature="0"
|
||||
@@ -771,25 +751,14 @@
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="opacity:0.5;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="m 210,42.999999 -1,1 0,1 1,1 9,0 1,-1 0,-1 -1,-1 z m 0,4 0,9 1,1 7,0 1,-1 0,-9 z m 2,2 1,0 0,6 -1,0 0,-1 z m 2,0 1,0 0,5 0,1 -1,0 z m 2,0 1,0 0,5 0,1 -1,0 z"
|
||||
id="path16769"
|
||||
sodipodi:nodetypes="cccccccccccccccccccccccccccccccccc" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="opacity:0.5;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="m 231,45 -1,1 0,1 3,3 -3,3 0,1 1,1 1,0 3,-3 3,3 1,0 1,-1 0,-1 -3,-3 3,-3 0,-1 -1,-1 -1,0 -3,3 -3,-3 -1,0 z"
|
||||
id="path47520" />
|
||||
<path
|
||||
style="opacity:0.50000000000000000;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.79999375000000006;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
style="opacity:1;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.79999375000000006;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="m 416.5,3.9999947 c -2.48528,0 -4.5,2.0147207 -4.5,4.5 0,0.7234907 0.19662,1.3943635 0.50001,2.0000053 L 409,13.999995 l 0,1.999999 2.00001,0 3.49999,-3.499997 c 0.60565,0.303377 1.27651,0.499995 2,0.499995 2.48528,0 4.5,-2.014712 4.5,-4.4999973 0,-2.4852793 -2.01472,-4.5 -4.5,-4.5 z m 0,1.9999993 c 1.38071,0 2.5,1.1192914 2.5,2.5000007 0,1.3807157 -1.11929,2.5000003 -2.5,2.5000003 -1.38071,0 -2.5,-1.1192846 -2.5,-2.5000003 0,-1.3807093 1.11929,-2.5000007 2.5,-2.5000007 z"
|
||||
id="path47528"
|
||||
inkscape:connector-curvature="0" />
|
||||
<g
|
||||
transform="translate(-656,113.63782)"
|
||||
id="g47761"
|
||||
style="opacity:0.5;fill:#000000;fill-opacity:1;display:inline">
|
||||
style="opacity:0.50000000000000000;fill:#000000;fill-opacity:1;display:inline">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
@@ -800,7 +769,7 @@
|
||||
<g
|
||||
id="g47765"
|
||||
transform="translate(-635,113.63782)"
|
||||
style="opacity:0.5;fill:#000000;fill-opacity:1;display:inline">
|
||||
style="opacity:0.50000000000000000;fill:#000000;fill-opacity:1;display:inline">
|
||||
<path
|
||||
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="m 925,-65.637817 11,0 1,1.00002 0,1 -1,0.99998 -11,0 -1,-1 0,-1 z"
|
||||
@@ -812,12 +781,7 @@
|
||||
inkscape:export-ydpi="90" />
|
||||
</g>
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="opacity:0.5;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter8013-4);enable-background:accumulate"
|
||||
d="m 334.5,43 -6.5,3 0,1 6.5,3 1,0 6.5,-3 0,-1 -6.5,-3 -1,0 z m -5.40625,6 -1.09375,0.5 0,1 6.5,3 1,0 6.5,-3 0,-1 -1.09375,-0.5 -5.40625,2.5 -1,0 -5.40625,-2.5 z m 0,3.5 L 328,53 l 0,1 6.5,3 1,0 6.5,-3 0,-1 -1.09375,-0.5 -5.40625,2.5 -1,0 -5.40625,-2.5 z"
|
||||
id="path47795" />
|
||||
<path
|
||||
style="opacity:0.5;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
style="opacity:0.50000000000000000;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="m 313.5,43.00001 c -3.03757,0 -5.5,2.46243 -5.5,5.5 0,3.03757 2.46243,5.5 5.5,5.5 1.00612,0 1.93866,-0.27827 2.75,-0.75 l 3.75,3.75 1,0 1,-1 0,-1 -3.75,-3.75 c 0.47173,-0.81134 0.75,-1.74387 0.75,-2.75 0,-3.03757 -2.46243,-5.5 -5.5,-5.5 z m -0.5,2 1,0 2,1 1,2 0,1 -1,2 -2,1 -1,0 -2,-1 -1,-2 0,-1 1,-2 2,-1 z"
|
||||
id="path47777"
|
||||
inkscape:connector-curvature="0" />
|
||||
@@ -826,9 +790,9 @@
|
||||
inkscape:connector-curvature="0"
|
||||
id="path58971"
|
||||
d="m 35,44 c 0,1 0,4 0,4 0,0 0,0.5 -0.5,0.5 -0.5,0 -0.429283,-0.27516 -0.5,-0.5 -0.304688,-0.96875 -0.867187,-2.36459 -1,-3 -0.204595,-0.97885 -0.666667,-1 -1,-1 -1,0 -1,1 -1,1 l 1,4 0,3 C 32,52 31.5,51.5 30.5,50.5 29.945312,49.94531 29.257659,49.7508 28.8125,50.00781 28.377049,50.25922 28.150942,50.89541 28.5,51.5 28.853553,52.11237 32,56 32,56 c 1,1 2,1 4,1 2.666667,0 1,0 3,0 2,0 2.288488,-2.86546 3,-5 1,-3 1.5,-5 1.5,-5 0.113427,-0.42332 -0.04289,-0.846 -0.5,-1 -0.880461,-0.29662 -1.36006,0.35278 -1.5,1 -0.25,1.15625 -0.5,2 -0.5,2 -0.09375,0.31383 0.0013,0.5 -0.5,0.5 C 39.99086,49.5 40,49 40,49 c 0,0 0,-2.66667 0,-4 0,-1 -1,-1 -1,-1 0,0 -1,0 -1,1 0,1 0,1.66667 0,3 0,0 0.01305,0.5 -0.5,0.5 C 36.998673,48.5 37,48 37,48 c 0,0 0,-3 0,-4 0,-1 -1,-1 -1,-1 0,0 -1,0 -1,1 z"
|
||||
style="opacity:0.5;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter8013-4);enable-background:accumulate" />
|
||||
style="opacity:0.50000000000000000;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter8013-4);enable-background:accumulate" />
|
||||
<path
|
||||
style="opacity:0.5;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
style="opacity:0.50000000000000000;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="m 354.5,42.999997 c -1.5,0 -2.5,2 -2.5,3 0,0.666667 0,1.333333 0,2 0,1 1,2.153847 1,2.153847 l 0,0.846153 -1.69231,0.384617 c -1.45419,0.330499 -2.02608,1.236079 -2.15384,2.76923 L 349,55.999998 l 12,0 -0.15385,-1.846154 c -0.12776,-1.533151 -0.69965,-2.438731 -2.15384,-2.76923 L 357,50.999997 l 0,-0.846153 c 0,0 1,-1.153847 1,-2.153847 0,-0.666667 0,-1.333333 0,-2 0,-1 -1,-3 -2.5,-3 z"
|
||||
id="path14143"
|
||||
inkscape:connector-curvature="0"
|
||||
@@ -843,26 +807,12 @@
|
||||
transform="matrix(2,0,0,2,-1601,221.27564)"
|
||||
style="display:inline">
|
||||
<path
|
||||
sodipodi:nodetypes="cccccccccsssss"
|
||||
inkscape:connector-curvature="0"
|
||||
style="color:#000000;fill:#c1c1c1;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="m 136,92 -4,4 -7,0 0,8 7,0 4,4 8,0 4,-4 7,0 0,-8 -7,0 -4,-4 -8,0 z m 4,4 c 2.20912,0 4,1.79086 4,4 0,2.20914 -1.79088,4 -4,4 -2.20912,0 -4,-1.79086 -4,-4 0,-2.20914 1.79088,-4 4,-4 z"
|
||||
transform="matrix(0.5,0,0,0.5,813,-110.63782)"
|
||||
id="path4439"
|
||||
d="m 879,-58.63782 2,2 4,0 2,-2 0,-4 -2,-2 -4,-2e-6 -2,2 z m 4,-4 c 1.10456,0 2,0.89543 2,2 0,1.10457 -0.89544,2 -2,2 -1.10456,0 -2,-0.89543 -2,-2 0,-1.10457 0.89544,-2 2,-2 z"
|
||||
style="color:#000000;fill:#c1c1c1;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<rect
|
||||
style="color:#000000;fill:#c1c1c1;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="rect4444"
|
||||
width="9"
|
||||
height="8"
|
||||
x="150"
|
||||
y="96" />
|
||||
<rect
|
||||
y="96"
|
||||
x="171"
|
||||
height="8"
|
||||
width="9"
|
||||
id="rect4446"
|
||||
style="color:#000000;fill:#c1c1c1;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
@@ -872,7 +822,7 @@
|
||||
sodipodi:rx="4"
|
||||
sodipodi:ry="4"
|
||||
d="m 144,100 c 0,2.20914 -1.79086,4 -4,4 -2.20914,0 -4,-1.79086 -4,-4 0,-2.209139 1.79086,-4 4,-4 2.20914,0 4,1.790861 4,4 z"
|
||||
transform="translate(25,-2.6796875e-6)" />
|
||||
transform="translate(25,-3.0625001e-6)" />
|
||||
<g
|
||||
transform="translate(505,-633.36218)"
|
||||
style="fill:#ffffff;fill-opacity:1;display:inline"
|
||||
@@ -946,7 +896,7 @@
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path33321"
|
||||
d="m 55,23.999998 c -2.76142,0 -5,2.23858 -5,5 0,2.76143 5,7 5,7 0,0 5,-4.23857 5,-7 0,-2.76142 -2.23858,-5 -5,-5 z m 0.15625,3 c 1.10457,0 2,0.89543 2,2 0,1.10457 -0.89543,2 -2,2 -1.104569,0 -2,-0.89543 -2,-2 0,-1.10457 0.895431,-2 2,-2 z"
|
||||
d="m 57,23.999998 c -2.76142,0 -5,2.23858 -5,5 0,2.76143 5,7 5,7 0,0 5,-4.23857 5,-7 0,-2.76142 -2.23858,-5 -5,-5 z m 0.15625,3 c 1.10457,0 2,0.89543 2,2 0,1.10457 -0.89543,2 -2,2 -1.104569,0 -2,-0.89543 -2,-2 0,-1.10457 0.895431,-2 2,-2 z"
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter8013-4);enable-background:accumulate" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
@@ -985,17 +935,6 @@
|
||||
id="path33331"
|
||||
d="m 169.00002,29.999999 5.99998,-7 6.00002,7.00002 -4,-1e-5 -1e-5,6 -1.00001,0.99999 -2,0 -1,-0.99998 1e-5,-6.00002 z"
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<path
|
||||
sodipodi:nodetypes="cccccccccccccccccccccccccccccccccc"
|
||||
id="path33333"
|
||||
d="m 210,22.999999 -1,1 0,1 1,1 9,0 1,-1 0,-1 -1,-1 z m 0,4 0,9 1,1 7,0 1,-1 0,-9 z m 2,2 1,0 0,6 -1,0 0,-1 z m 2,0 1,0 0,5 0,1 -1,0 z m 2,0 1,0 0,5 0,1 -1,0 z"
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path33335"
|
||||
d="m 231,25 -1,1 0,1 3,3 -3,3 0,1 1,1 1,0 3,-3 3,3 1,0 1,-1 0,-1 -3,-3 3,-3 0,-1 -1,-1 -1,0 -3,3 -3,-3 -1,0 z"
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
inkscape:connector-curvature="0" />
|
||||
<g
|
||||
id="g33337"
|
||||
transform="translate(-511.00001,-14)"
|
||||
@@ -1040,11 +979,6 @@
|
||||
d="m 925,-65.637817 11,0 1,1.00002 0,1 -1,0.99998 -11,0 -1,-1 0,-1 z"
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
</g>
|
||||
<path
|
||||
id="path33353"
|
||||
d="m 334.5,23 -6.5,3 0,1 6.5,3 1,0 6.5,-3 0,-1 -6.5,-3 -1,0 z m -5.40625,6 -1.09375,0.5 0,1 6.5,3 1,0 6.5,-3 0,-1 -1.09375,-0.5 -5.40625,2.5 -1,0 -5.40625,-2.5 z m 0,3.5 L 328,33 l 0,1 6.5,3 1,0 6.5,-3 0,-1 -1.09375,-0.5 -5.40625,2.5 -1,0 -5.40625,-2.5 z"
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter8013-4);enable-background:accumulate"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path33355"
|
||||
@@ -1062,36 +996,6 @@
|
||||
id="path33359"
|
||||
d="m 354.5,22.999997 c -1.5,0 -2.5,2 -2.5,3 0,0.666667 0,1.333333 0,2 0,1 1,2.153847 1,2.153847 l 0,0.846153 -1.69231,0.384617 c -1.45419,0.330499 -2.02608,1.236079 -2.15384,2.76923 L 349,35.999998 l 12,0 -0.15385,-1.846154 c -0.12776,-1.533151 -0.69965,-2.438731 -2.15384,-2.76923 L 357,30.999997 l 0,-0.846153 c 0,0 1,-1.153847 1,-2.153847 0,-0.666667 0,-1.333333 0,-2 0,-1 -1,-3 -2.5,-3 z"
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<path
|
||||
style="color:#000000;fill:#7092ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="m 230,3 c -3.86599,0 -7,3.1340051 -7,7 0,3.865995 3.13401,7 7,7 3.86599,0 7,-3.134005 7,-7 0,-3.8659949 -3.13401,-7 -7,-7 z m -1,3 2,0 0,2 -1,1 1,1 0,4 -2,0 0,-4 1,-1 -1,-1 0,-2 z"
|
||||
transform="translate(25,-3.0625e-6)"
|
||||
id="path15945"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="m 230,23 c -3.86599,0 -7,3.134005 -7,7 0,3.865995 3.13401,7 7,7 3.86599,0 7,-3.134005 7,-7 0,-3.865995 -3.13401,-7 -7,-7 z m -1,3 2,0 0,2 -1,1 1,1 0,4 -2,0 0,-4 1,-1 -1,-1 0,-2 z"
|
||||
transform="translate(25,-3.0625e-6)"
|
||||
id="path15958"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path15966"
|
||||
d="m 255,42.999997 c -3.86599,0 -7,3.134005 -7,7 0,3.865995 3.13401,7 7,7 3.86599,0 7,-3.134005 7,-7 0,-3.865995 -3.13401,-7 -7,-7 z m -1,3 2,0 0,2 -1,1 1,1 0,4 -2,0 0,-4 1,-1 -1,-1 0,-2 z"
|
||||
style="color:#000000;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="color:#000000;fill:#ff7070;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="m 414,-47.000003 -8,13 1,1 16,0 1,-1 -8,-13 z m 0,4 2,0 0,4 -1,1 1,1 0,2 -2,0 0,-2 1,-1 -1,-1 z"
|
||||
id="path15971"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccccccccccccccc" />
|
||||
<rect
|
||||
y="80"
|
||||
x="225"
|
||||
height="40"
|
||||
width="40"
|
||||
id="rect16157"
|
||||
style="color:#000000;fill:none;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="color:#000000;fill:#c1c1c1;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
@@ -1104,23 +1008,23 @@
|
||||
id="path16191" />
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="color:#000000;fill:#c1c1c1;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.79999375;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
style="color:#000000;fill:#c1c1c1;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.79999375000000006;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="path16208"
|
||||
sodipodi:cx="215"
|
||||
sodipodi:cy="95"
|
||||
sodipodi:rx="1"
|
||||
sodipodi:ry="1"
|
||||
d="m 216,95 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"
|
||||
d="m 216,95 c 0,0.552285 -0.44772,1 -1,1 -0.55228,0 -1,-0.447715 -1,-1 0,-0.552285 0.44772,-1 1,-1 0.55228,0 1,0.447715 1,1 z"
|
||||
transform="translate(27,1.9999969)" />
|
||||
<path
|
||||
transform="translate(33,7.9999969)"
|
||||
d="m 216,95 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"
|
||||
d="m 216,95 c 0,0.552285 -0.44772,1 -1,1 -0.55228,0 -1,-0.447715 -1,-1 0,-0.552285 0.44772,-1 1,-1 0.55228,0 1,0.447715 1,1 z"
|
||||
sodipodi:ry="1"
|
||||
sodipodi:rx="1"
|
||||
sodipodi:cy="95"
|
||||
sodipodi:cx="215"
|
||||
id="path16210"
|
||||
style="color:#000000;fill:#c1c1c1;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.79999375;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
style="color:#000000;fill:#c1c1c1;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.79999375000000006;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
sodipodi:type="arc" />
|
||||
<path
|
||||
id="path16212"
|
||||
@@ -1134,33 +1038,333 @@
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
transform="matrix(-1,0,0,1,463,1.9999969)"
|
||||
d="m 216,95 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"
|
||||
d="m 216,95 c 0,0.552285 -0.44772,1 -1,1 -0.55228,0 -1,-0.447715 -1,-1 0,-0.552285 0.44772,-1 1,-1 0.55228,0 1,0.447715 1,1 z"
|
||||
sodipodi:ry="1"
|
||||
sodipodi:rx="1"
|
||||
sodipodi:cy="95"
|
||||
sodipodi:cx="215"
|
||||
id="path16216"
|
||||
style="color:#000000;fill:#c1c1c1;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.79999375;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
style="color:#000000;fill:#c1c1c1;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.79999375000000006;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
sodipodi:type="arc" />
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="color:#000000;fill:#c1c1c1;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.79999375;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
style="color:#000000;fill:#c1c1c1;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.79999375000000006;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="path16218"
|
||||
sodipodi:cx="215"
|
||||
sodipodi:cy="95"
|
||||
sodipodi:rx="1"
|
||||
sodipodi:ry="1"
|
||||
d="m 216,95 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"
|
||||
d="m 216,95 c 0,0.552285 -0.44772,1 -1,1 -0.55228,0 -1,-0.447715 -1,-1 0,-0.552285 0.44772,-1 1,-1 0.55228,0 1,0.447715 1,1 z"
|
||||
transform="matrix(-1,0,0,1,457,7.9999969)" />
|
||||
<path
|
||||
transform="matrix(-1,0,0,1,460,4.9999969)"
|
||||
d="m 216,95 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"
|
||||
d="m 216,95 c 0,0.552285 -0.44772,1 -1,1 -0.55228,0 -1,-0.447715 -1,-1 0,-0.552285 0.44772,-1 1,-1 0.55228,0 1,0.447715 1,1 z"
|
||||
sodipodi:ry="1"
|
||||
sodipodi:rx="1"
|
||||
sodipodi:cy="95"
|
||||
sodipodi:cx="215"
|
||||
id="path16220"
|
||||
style="color:#000000;fill:#c1c1c1;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.79999375;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
style="color:#000000;fill:#c1c1c1;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.79999375000000006;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
sodipodi:type="arc" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="m 31,144 -1,1 0,1 1,1 8,0 1,-1 0,-1 -1,-1 z m 0,4 0,7 1,1 6,0 1,-1 0,-7 z m 2,2 1,0 0,4 -1,0 0,-1 z m 3,0 1,0 0,3 0,1 -1,0 z"
|
||||
id="path9820"
|
||||
sodipodi:nodetypes="cccccccccccccccccccccccccccc" />
|
||||
<g
|
||||
transform="translate(-26,-582.36218)"
|
||||
id="g9824">
|
||||
<path
|
||||
sodipodi:nodetypes="sscccccsssscccccssccccsccccccccccsc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path9826"
|
||||
transform="translate(0.9999996,1.4591601e-6)"
|
||||
d="m 114,727.375 c -1,0 -2,1 -2,2 l 0,2 3,0 2,1 -2,1 -3,0 0,2 c 0,1 1,2 2,2 l 1,0 c 2,0 2.48722,-0.97443 3,-2 l 1,-2 9,-5 c 0,0 0,-1 -2,-1 l -7.03125,3.90625 L 118,729.375 c -0.49406,-0.98812 -1,-2 -3,-2 z m 0,1 2,0 1,2 -4,0 c 0,0 0,-0.66667 0,-1 0,-1.01282 1,-1 1,-1 z m 8.09375,4.71875 -2,1 L 126,737.375 c 2,0 2,-1 2,-1 z M 113,734.375 l 4,0 -1,2 -2,0 c 0,0 -1,0 -1,-1 z"
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.79999375;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
</g>
|
||||
<g
|
||||
transform="translate(-50,-762.36218)"
|
||||
id="g9961">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="rect9822"
|
||||
d="m 119.8125,911.375 c 0.11352,0.31647 0.1875,0.64447 0.1875,1 0,0.35553 -0.074,0.68353 -0.1875,1 l 2.375,0 c -0.11352,-0.31647 -0.1875,-0.64447 -0.1875,-1 0,-0.35553 0.074,-0.68353 0.1875,-1 l -2.375,0 z m 8,0 c 0.11352,0.31647 0.1875,0.64447 0.1875,1 0,0.35553 -0.074,0.68353 -0.1875,1 l 2.375,0 c -0.11352,-0.31647 -0.1875,-0.64447 -0.1875,-1 0,-0.35553 0.074,-0.68353 0.1875,-1 l -2.375,0 z"
|
||||
style="color:#000000;fill:#6bc641;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.79999375;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<path
|
||||
transform="translate(67,173)"
|
||||
sodipodi:type="arc"
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.79999375;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="path9830"
|
||||
sodipodi:cx="50"
|
||||
sodipodi:cy="739.36218"
|
||||
sodipodi:rx="2"
|
||||
sodipodi:ry="2"
|
||||
d="m 52,739.36218 c 0,1.10457 -0.895431,2 -2,2 -1.104569,0 -2,-0.89543 -2,-2 0,-1.10457 0.895431,-2 2,-2 1.104569,0 2,0.89543 2,2 z" />
|
||||
<path
|
||||
d="m 52,739.36218 c 0,1.10457 -0.895431,2 -2,2 -1.104569,0 -2,-0.89543 -2,-2 0,-1.10457 0.895431,-2 2,-2 1.104569,0 2,0.89543 2,2 z"
|
||||
sodipodi:ry="2"
|
||||
sodipodi:rx="2"
|
||||
sodipodi:cy="739.36218"
|
||||
sodipodi:cx="50"
|
||||
id="path9834"
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.79999375;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
sodipodi:type="arc"
|
||||
transform="translate(75,173)" />
|
||||
<path
|
||||
transform="translate(83,173)"
|
||||
sodipodi:type="arc"
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.79999375;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="path9838"
|
||||
sodipodi:cx="50"
|
||||
sodipodi:cy="739.36218"
|
||||
sodipodi:rx="2"
|
||||
sodipodi:ry="2"
|
||||
d="m 52,739.36218 c 0,1.10457 -0.895431,2 -2,2 -1.104569,0 -2,-0.89543 -2,-2 0,-1.10457 0.895431,-2 2,-2 1.104569,0 2,0.89543 2,2 z" />
|
||||
</g>
|
||||
<g
|
||||
transform="translate(-110,-762.36218)"
|
||||
id="g9967">
|
||||
<path
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter8013-4);enable-background:accumulate"
|
||||
d="m 268,906.36218 -3,-3 -3,3 1,1 4,0 z"
|
||||
id="path9844"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccc" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path9846"
|
||||
d="m 268,918.36218 -3,3 -3,-3 1,-1 4,0 z"
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter8013-4);enable-background:accumulate"
|
||||
sodipodi:nodetypes="cccccc" />
|
||||
<path
|
||||
sodipodi:nodetypes="cccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path9848"
|
||||
d="m 271,915.36219 3,-3.00001 -3,-2.99999 -1,0.99999 0,4 z"
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter8013-4);enable-background:accumulate" />
|
||||
<path
|
||||
sodipodi:nodetypes="cccccc"
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter8013-4);enable-background:accumulate"
|
||||
d="m 259,915.36217 -3,-2.99999 3,-3.00001 1,1.00001 0,4 z"
|
||||
id="path9850"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="path9852"
|
||||
sodipodi:cx="225"
|
||||
sodipodi:cy="732.36218"
|
||||
sodipodi:rx="1"
|
||||
sodipodi:ry="1"
|
||||
d="m 226,732.36218 c 0,0.55229 -0.44772,1 -1,1 -0.55228,0 -1,-0.44771 -1,-1 0,-0.55228 0.44772,-1 1,-1 0.55228,0 1,0.44772 1,1 z"
|
||||
transform="matrix(2,0,0,2,-185,-552.36218)" />
|
||||
</g>
|
||||
<g
|
||||
transform="translate(-35,-762.36218)"
|
||||
id="g9952">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path9840"
|
||||
d="m 87.03125,904.96875 c -1.32908,0.53118 -2.444369,1.41916 -3.3125,2.53125 0.07092,0.0184 0.149734,0.009 0.21875,0.0312 0.520689,0.16918 0.941853,0.48986 1.28125,0.875 0.583365,-0.69731 1.320919,-1.23792 2.15625,-1.625 C 87.146997,906.35926 87,905.88411 87,905.375 c 0,-0.14028 0.0122,-0.27085 0.03125,-0.40625 z m 5.9375,0 C 92.987796,905.10415 93,905.23472 93,905.375 c 0,0.50911 -0.146997,0.98426 -0.375,1.40625 0.835331,0.38708 1.572885,0.92769 2.15625,1.625 0.339397,-0.38514 0.760561,-0.70582 1.28125,-0.875 0.06748,-0.0219 0.146303,-0.0395 0.21875,-0.0625 -0.866395,-1.10291 -1.991152,-1.97191 -3.3125,-2.5 z m -10.9375,8.21875 c 0.132811,1.35398 0.618313,2.61506 1.34375,3.6875 0.05422,-0.0956 0.121594,-0.19054 0.1875,-0.28125 0.298579,-0.41096 0.689964,-0.72255 1.125,-0.9375 -0.439267,-0.72096 -0.728373,-1.5606 -0.84375,-2.4375 -0.563589,0.16464 -1.184566,0.16262 -1.78125,-0.0312 -0.009,-0.003 -0.02228,0.003 -0.03125,0 z m 15.90625,0 c -0.596684,0.19387 -1.217661,0.19589 -1.78125,0.0312 -0.115377,0.8769 -0.404483,1.71654 -0.84375,2.4375 0.438042,0.20421 0.821177,0.51932 1.125,0.9375 0.06591,0.0907 0.133279,0.18566 0.1875,0.28125 0.725438,-1.07244 1.210939,-2.33352 1.34375,-3.6875 -0.009,0.003 -0.02224,-0.003 -0.03125,0 z M 89,918.53125 c -0.03014,0.55835 -0.21394,1.114 -0.5625,1.59375 -0.027,0.0372 -0.06534,0.0582 -0.09375,0.0937 0.540476,0.11583 1.081942,0.1875 1.65625,0.1875 0.574308,0 1.115774,-0.0717 1.65625,-0.1875 -0.02841,-0.0355 -0.06675,-0.0566 -0.09375,-0.0937 -0.34856,-0.47975 -0.532362,-1.0354 -0.5625,-1.59375 -0.329444,0.0535 -0.654988,0.0937 -1,0.0937 -0.345012,0 -0.670556,-0.0403 -1,-0.0937 z"
|
||||
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#6bc641;fill-opacity:1;stroke:none;stroke-width:0.50000125;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans" />
|
||||
<g
|
||||
id="g9894"
|
||||
transform="translate(40,180)">
|
||||
<path
|
||||
d="m 52,725.36218 c 0,1.10457 -0.895431,2 -2,2 -1.104569,0 -2,-0.89543 -2,-2 0,-1.10457 0.895431,-2 2,-2 1.104569,0 2,0.89543 2,2 z"
|
||||
sodipodi:ry="2"
|
||||
sodipodi:rx="2"
|
||||
sodipodi:cy="725.36218"
|
||||
sodipodi:cx="50"
|
||||
id="path9896"
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
sodipodi:type="arc" />
|
||||
<path
|
||||
transform="matrix(0.30901699,-0.95105652,0.95105652,0.30901699,-662.31182,553.76523)"
|
||||
sodipodi:type="arc"
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="path9898"
|
||||
sodipodi:cx="50"
|
||||
sodipodi:cy="725.36218"
|
||||
sodipodi:rx="2"
|
||||
sodipodi:ry="2"
|
||||
d="m 52,725.36218 c 0,1.10457 -0.895431,2 -2,2 -1.104569,0 -2,-0.89543 -2,-2 0,-1.10457 0.895431,-2 2,-2 1.104569,0 2,0.89543 2,2 z" />
|
||||
<path
|
||||
d="m 52,725.36218 c 0,1.10457 -0.895431,2 -2,2 -1.104569,0 -2,-0.89543 -2,-2 0,-1.10457 0.895431,-2 2,-2 1.104569,0 2,0.89543 2,2 z"
|
||||
sodipodi:ry="2"
|
||||
sodipodi:rx="2"
|
||||
sodipodi:cy="725.36218"
|
||||
sodipodi:cx="50"
|
||||
id="path9900"
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
sodipodi:type="arc"
|
||||
transform="matrix(-0.809017,-0.58778525,0.58778525,-0.809017,-339.90648,1354.5819)" />
|
||||
<path
|
||||
transform="matrix(-0.80901699,0.58778526,-0.58778526,-0.80901699,520.80791,1295.8034)"
|
||||
sodipodi:type="arc"
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="path9902"
|
||||
sodipodi:cx="50"
|
||||
sodipodi:cy="725.36218"
|
||||
sodipodi:rx="2"
|
||||
sodipodi:ry="2"
|
||||
d="m 52,725.36218 c 0,1.10457 -0.895431,2 -2,2 -1.104569,0 -2,-0.89543 -2,-2 0,-1.10457 0.895431,-2 2,-2 1.104569,0 2,0.89543 2,2 z" />
|
||||
<path
|
||||
d="m 52,725.36218 c 0,1.10457 -0.895431,2 -2,2 -1.104569,0 -2,-0.89543 -2,-2 0,-1.10457 0.895431,-2 2,-2 1.104569,0 2,0.89543 2,2 z"
|
||||
sodipodi:ry="2"
|
||||
sodipodi:rx="2"
|
||||
sodipodi:cy="725.36218"
|
||||
sodipodi:cx="50"
|
||||
id="path9904"
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
sodipodi:type="arc"
|
||||
transform="matrix(0.309017,0.95105651,-0.95105651,0.309017,731.41012,458.66065)" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
transform="translate(-80,-762.36218)"
|
||||
id="g9978">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path9854"
|
||||
d="m 189,908.375 -4,4 4,4 1,-1 0,-2 2.1875,0 c -0.11352,-0.31647 -0.1875,-0.64447 -0.1875,-1 0,-0.34518 0.0802,-0.69136 0.1875,-1 l -2.1875,0 0,-2 -1,-1 z m 12,0 -1,1 0,2 -2.1875,0 c 0.10728,0.30864 0.1875,0.65482 0.1875,1 0,0.35553 -0.074,0.68353 -0.1875,1 l 2.1875,0 0,2 1,1 4,-4 -4,-4 z"
|
||||
style="color:#000000;fill:#6bc641;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<path
|
||||
transform="matrix(2.0000003,0,0,2.0000003,-255.00007,-552.36238)"
|
||||
d="m 226,732.36218 c 0,0.55229 -0.44772,1 -1,1 -0.55228,0 -1,-0.44771 -1,-1 0,-0.55228 0.44772,-1 1,-1 0.55228,0 1,0.44772 1,1 z"
|
||||
sodipodi:ry="1"
|
||||
sodipodi:rx="1"
|
||||
sodipodi:cy="732.36218"
|
||||
sodipodi:cx="225"
|
||||
id="path9908"
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
sodipodi:type="arc" />
|
||||
</g>
|
||||
<g
|
||||
transform="translate(-94,-762.36218)"
|
||||
id="g9974">
|
||||
<path
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="m 227,917.36218 -4,-5 4,-5 2,0 0,1 -3.5,4 3.5,4 0,1 z"
|
||||
id="path9842"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccccc" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccccccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path9910"
|
||||
d="m 233,917.36218 -4,-5 4,-5 2,0 0,1 -3.5,4 3.5,4 0,1 z"
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
</g>
|
||||
<g
|
||||
id="g9683"
|
||||
transform="translate(-109.40337,-628.51757)"
|
||||
style="fill:#6bc641;fill-opacity:1">
|
||||
<path
|
||||
style="color:#000000;fill:#6bc641;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="m 283.40337,771.51757 -1,1 0,4 -4,0 -1,1 0,2 1,1 4,0 0,4 1,1 2,0 1,-1 0,-4 4,0 1,-1 0,-2 -1,-1 -4,0 0,-4 -1,-1 z"
|
||||
id="path5624-8"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccccccccccccccccc" />
|
||||
</g>
|
||||
<g
|
||||
transform="translate(-100,-582.36218)"
|
||||
id="g9864-9">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="color:#000000;fill:#6bc641;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.79999375;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="m 331,910.1875 0,2.375 c 0.31647,-0.11352 0.64447,-0.1875 1,-0.1875 0.35553,0 0.68353,0.074 1,0.1875 l 0,-2.375 c -0.31647,0.11352 -0.64447,0.1875 -1,0.1875 -0.35553,0 -0.68353,-0.074 -1,-0.1875 z m 3.8125,4.1875 c 0.11352,0.31647 0.1875,0.64447 0.1875,1 0,0.35553 -0.074,0.68353 -0.1875,1 l 2.375,0 c -0.11352,-0.31647 -0.1875,-0.64447 -0.1875,-1 0,-0.35553 0.074,-0.68353 0.1875,-1 l -2.375,0 z"
|
||||
transform="translate(-41,-179.00001)"
|
||||
id="rect9866-2" />
|
||||
<path
|
||||
d="m 52,739.36218 c 0,1.10457 -0.895431,2 -2,2 -1.104569,0 -2,-0.89543 -2,-2 0,-1.10457 0.895431,-2 2,-2 1.104569,0 2,0.89543 2,2 z"
|
||||
sodipodi:ry="2"
|
||||
sodipodi:rx="2"
|
||||
sodipodi:cy="739.36218"
|
||||
sodipodi:cx="50"
|
||||
id="path9870-1"
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.79999375;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
sodipodi:type="arc"
|
||||
transform="translate(249,-3)" />
|
||||
<path
|
||||
transform="translate(241,-3)"
|
||||
sodipodi:type="arc"
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.79999375;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="path9878-4"
|
||||
sodipodi:cx="50"
|
||||
sodipodi:cy="739.36218"
|
||||
sodipodi:rx="2"
|
||||
sodipodi:ry="2"
|
||||
d="m 52,739.36218 c 0,1.10457 -0.895431,2 -2,2 -1.104569,0 -2,-0.89543 -2,-2 0,-1.10457 0.895431,-2 2,-2 1.104569,0 2,0.89543 2,2 z" />
|
||||
<path
|
||||
transform="translate(241,-11)"
|
||||
sodipodi:type="arc"
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.79999375;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="path9880-9"
|
||||
sodipodi:cx="50"
|
||||
sodipodi:cy="739.36218"
|
||||
sodipodi:rx="2"
|
||||
sodipodi:ry="2"
|
||||
d="m 52,739.36218 c 0,1.10457 -0.895431,2 -2,2 -1.104569,0 -2,-0.89543 -2,-2 0,-1.10457 0.895431,-2 2,-2 1.104569,0 2,0.89543 2,2 z" />
|
||||
</g>
|
||||
<rect
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="rect10175"
|
||||
width="40"
|
||||
height="140"
|
||||
x="-15"
|
||||
y="-3.0624999e-06" />
|
||||
<path
|
||||
id="path10245"
|
||||
d="m 436,22.999997 -1,1 0,4 -4,0 -1,1 0,1 1,1 4,0 0,4 1,1 1,0 1,-1 0,-4 4,0 1,-1 0,-1 -1,-1 -4,0 0,-4 -1,-1 -1,0 z"
|
||||
style="opacity:0.50000000000000000;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.79999375000000006;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="m 211,3.9999969 -1,1 0,1 1,1 8,0 1,-1 0,-1 -1,-1 z m 0,4 0,7.0000001 1,1 6,0 1,-1 0,-7.0000001 z m 2,2 1,0 0,4.0000001 -1,0 0,-1 z m 3,0 1,0 0,3.0000001 0,1 -1,0 z"
|
||||
id="path9820-4"
|
||||
sodipodi:nodetypes="cccccccccccccccccccccccccccc" />
|
||||
<path
|
||||
sodipodi:nodetypes="cccccccccccccccccccccccccccc"
|
||||
id="path10997"
|
||||
d="m 211,23.999997 -1,1 0,1 1,1 8,0 1,-1 0,-1 -1,-1 z m 0,4 0,7 1,1 6,0 1,-1 0,-7 z m 2,2 1,0 0,4 -1,0 0,-1 z m 3,0 1,0 0,3 0,1 -1,0 z"
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;opacity:0.50000000000000000"
|
||||
d="m 211,43.999997 -1,1 0,1 1,1 8,0 1,-1 0,-1 -1,-1 z m 0,4 0,7 1,1 6,0 1,-1 0,-7 z m 2,2 1,0 0,4 -1,0 0,-1 z m 3,0 1,0 0,3 0,1 -1,0 z"
|
||||
id="path11016"
|
||||
sodipodi:nodetypes="cccccccccccccccccccccccccccc" />
|
||||
<path
|
||||
style="color:#000000;fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="m 231,44.999999 -1,1 0,1 3,3 -3,3 0,1 1,1 1,0 3,-3 3,3 1,0 1,-1 0,-1 -3,-3 3,-3 0,-1 -1,-1 -1,0 -3,3 -3,-3 z"
|
||||
id="path11047"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccccccccccccccccc" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccccccccccccccccccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4246"
|
||||
d="m 231,4.999999 -1,1 0,1 3,3 -3,3 0,1 1,1 1,0 3,-3 3,3 1,0 1,-1 0,-1 -3,-3 3,-3 0,-1 -1,-1 -1,0 -3,3 -3,-3 z"
|
||||
style="color:#000000;fill:#222222;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<g
|
||||
id="g6389"
|
||||
transform="translate(5,-91)">
|
||||
<path
|
||||
id="path5530-2-0"
|
||||
transform="translate(25,-3.0625001e-6)"
|
||||
d="M 299.15625,101.84375 297,103 l 0,1 7.5,4 1,0 7.5,-4 0,-1 -1.03125,-0.5625 a 3.0003,3.0003 0 0 1 -4.28125,1.25 l -2.1875,-1.0625 -2.15625,1.0625 a 3.0047168,3.0047168 0 0 1 -4.1875,-1.84375 z"
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter8013-4);enable-background:accumulate"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path6316"
|
||||
transform="translate(25,-3.0625001e-6)"
|
||||
d="m 304.0625,94.9375 a 1.0030471,1.0030471 0 0 0 -0.25,0.0625 1.0001,1.0001 0 0 0 -0.25,0.09375 l -6,3 a 1.0063276,1.0063276 0 0 0 0.875,1.8125 l 3.03125,-1.5 A 1.0001,1.0001 0 0 0 301.75,98.5625 l 1.4375,0.71875 -1.625,0.8125 a 1.0063281,1.0063281 0 1 0 0.875,1.8125 l 3.03125,-1.53125 3.09375,1.53125 a 1.0063281,1.0063281 0 1 0 0.875,-1.8125 L 307.75,99.25 308.4375,98.90625 A 1.0030471,1.0030471 0 1 0 307.8125,97 a 1.0001,1.0001 0 0 0 -0.25,0.09375 l -2.09375,1.03125 -1.75,-0.84375 0.71875,-0.375 a 1.0030471,1.0030471 0 0 0 -0.375,-1.96875 z"
|
||||
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;opacity:0.75;color:#000000;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 73 KiB After Width: | Height: | Size: 88 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
@@ -9,8 +9,8 @@
|
||||
|
||||
<!-- mobile devices -->
|
||||
<meta name='viewport' content='initial-scale=1.0 maximum-scale=1.0'>
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
||||
<meta name='apple-mobile-web-app-capable' content='yes' />
|
||||
<meta name='apple-mobile-web-app-status-bar-style' content='black-translucent' />
|
||||
|
||||
<script src='js/lib/lodash.js'></script>
|
||||
<script src='js/lib/d3.v3.js'></script>
|
||||
@@ -24,7 +24,6 @@
|
||||
<script src='js/lib/d3.keybinding.js'></script>
|
||||
<script src='js/lib/d3.tail.js'></script>
|
||||
<script src='js/lib/d3-compat.js'></script>
|
||||
<script src='js/lib/queue.js'></script>
|
||||
<script src='js/lib/bootstrap-tooltip.js'></script>
|
||||
<script src='js/lib/rtree.js'></script>
|
||||
|
||||
@@ -33,20 +32,24 @@
|
||||
<script src='js/id/oauth.js'></script>
|
||||
<script src='js/id/services/taginfo.js'></script>
|
||||
|
||||
<script src='data/data.js'></script>
|
||||
<script src='data/deprecated.js'></script>
|
||||
<script src='data/imagery.js'></script>
|
||||
<script src='data/discarded.js'></script>
|
||||
|
||||
<script src="js/id/geo.js"></script>
|
||||
<script src="js/id/geo/extent.js"></script>
|
||||
|
||||
<script src='js/id/renderer/background.js'></script>
|
||||
<script src='js/id/renderer/background_source.js'></script>
|
||||
<script src='js/id/renderer/map.js'></script>
|
||||
<script src='js/id/renderer/hash.js'></script>
|
||||
<script src='js/id/renderer/layers.js'></script>
|
||||
|
||||
<script src="js/id/svg.js"></script>
|
||||
<script src="js/id/svg/areas.js"></script>
|
||||
<script src="js/id/svg/lines.js"></script>
|
||||
<script src="js/id/svg/member_classes.js"></script>
|
||||
<script src="js/id/svg/midpoints.js"></script>
|
||||
<script src="js/id/svg/multipolygons.js"></script>
|
||||
<script src="js/id/svg/points.js"></script>
|
||||
<script src="js/id/svg/surface.js"></script>
|
||||
<script src="js/id/svg/tag_classes.js"></script>
|
||||
@@ -54,15 +57,18 @@
|
||||
<script src="js/id/svg/labels.js"></script>
|
||||
|
||||
<script src="js/id/ui.js"></script>
|
||||
<script src='js/id/ui/attribution.js'></script>
|
||||
<script src='js/id/ui/radial_menu.js'></script>
|
||||
<script src='js/id/ui/inspector.js'></script>
|
||||
<script src='js/id/ui/modal.js'></script>
|
||||
<script src='js/id/ui/cmd.js'></script>
|
||||
<script src='js/id/ui/confirm.js'></script>
|
||||
<script src='js/id/ui/commit.js'></script>
|
||||
<script src='js/id/ui/success.js'></script>
|
||||
<script src='js/id/ui/loading.js'></script>
|
||||
<script src='js/id/ui/userpanel.js'></script>
|
||||
<script src='js/id/ui/account.js'></script>
|
||||
<script src='js/id/ui/layerswitcher.js'></script>
|
||||
<script src='js/id/ui/modes.js'></script>
|
||||
<script src='js/id/ui/contributors.js'></script>
|
||||
<script src='js/id/ui/geocoder.js'></script>
|
||||
<script src='js/id/ui/geolocate.js'></script>
|
||||
@@ -70,32 +76,46 @@
|
||||
<script src='js/id/ui/flash.js'></script>
|
||||
<script src='js/id/ui/save.js'></script>
|
||||
<script src='js/id/ui/splash.js'></script>
|
||||
<script src='js/id/ui/restore.js'></script>
|
||||
<script src='js/id/ui/tag_reference.js'></script>
|
||||
<script src='js/id/ui/key_reference.js'></script>
|
||||
<script src='js/id/ui/lasso.js'></script>
|
||||
<script src='js/id/ui/source_switch.js'></script>
|
||||
<script src='js/id/ui/toggle.js'></script>
|
||||
<script src='js/id/ui/undo_redo.js'></script>
|
||||
<script src='js/id/ui/zoom.js'></script>
|
||||
|
||||
<script src='js/id/actions.js'></script>
|
||||
<script src='js/id/actions/add_node.js'></script>
|
||||
<script src='js/id/actions/add_way.js'></script>
|
||||
<script src='js/id/actions/add_way_node.js'></script>
|
||||
<script src='js/id/actions/change_entity_tags.js'></script>
|
||||
<script src="js/id/actions/add_midpoint.js"></script>
|
||||
<script src='js/id/actions/add_entity.js'></script>
|
||||
<script src='js/id/actions/add_vertex.js'></script>
|
||||
<script src='js/id/actions/change_tags.js'></script>
|
||||
<script src='js/id/actions/connect.js'></script>
|
||||
<script src='js/id/actions/delete_multiple.js'></script>
|
||||
<script src='js/id/actions/delete_node.js'></script>
|
||||
<script src="js/id/actions/delete_relation.js"></script>
|
||||
<script src="js/id/actions/delete_way.js"></script>
|
||||
<script src='js/id/actions/disconnect.js'></script>
|
||||
<script src='js/id/actions/join.js'></script>
|
||||
<script src='js/id/actions/merge.js'></script>
|
||||
<script src='js/id/actions/move_node.js'></script>
|
||||
<script src='js/id/actions/move_way.js'></script>
|
||||
<script src='js/id/actions/circular.js'></script>
|
||||
<script src='js/id/actions/circularize.js'></script>
|
||||
<script src='js/id/actions/orthogonalize.js'></script>
|
||||
<script src='js/id/actions/noop.js'></script>
|
||||
<script src='js/id/actions/reverse_way.js'></script>
|
||||
<script src='js/id/actions/split_way.js'></script>
|
||||
<script src='js/id/actions/unjoin_node.js'></script>
|
||||
<script src='js/id/actions/reverse.js'></script>
|
||||
<script src='js/id/actions/split.js'></script>
|
||||
|
||||
<script src='js/id/behavior.js'></script>
|
||||
<script src='js/id/behavior/add_way.js'></script>
|
||||
<script src='js/id/behavior/drag.js'></script>
|
||||
<script src='js/id/behavior/drag_midpoint.js'></script>
|
||||
<script src='js/id/behavior/drag_node.js'></script>
|
||||
<script src='js/id/behavior/draw.js'></script>
|
||||
<script src='js/id/behavior/lasso.js'></script>
|
||||
<script src='js/id/behavior/draw_way.js'></script>
|
||||
<script src='js/id/behavior/hash.js'></script>
|
||||
<script src='js/id/behavior/hover.js'></script>
|
||||
<script src='js/id/behavior/select.js'></script>
|
||||
|
||||
<script src='js/id/modes.js'></script>
|
||||
<script src='js/id/modes/add_area.js'></script>
|
||||
@@ -108,35 +128,56 @@
|
||||
<script src='js/id/modes/select.js'></script>
|
||||
|
||||
<script src='js/id/operations.js'></script>
|
||||
<script src='js/id/operations/circular.js'></script>
|
||||
<script src='js/id/operations/circularize.js'></script>
|
||||
<script src='js/id/operations/orthogonalize.js'></script>
|
||||
<script src='js/id/operations/delete.js'></script>
|
||||
<script src='js/id/operations/disconnect.js'></script>
|
||||
<script src='js/id/operations/merge.js'></script>
|
||||
<script src='js/id/operations/move.js'></script>
|
||||
<script src='js/id/operations/reverse.js'></script>
|
||||
<script src='js/id/operations/split.js'></script>
|
||||
<script src='js/id/operations/unjoin.js'></script>
|
||||
|
||||
<script src='js/id/controller/controller.js'></script>
|
||||
|
||||
<script src='js/id/graph/entity.js'></script>
|
||||
<script src='js/id/graph/graph.js'></script>
|
||||
<script src='js/id/graph/history.js'></script>
|
||||
<script src='js/id/graph/node.js'></script>
|
||||
<script src='js/id/graph/relation.js'></script>
|
||||
<script src='js/id/graph/way.js'></script>
|
||||
<script src='js/id/graph/validate.js'></script>
|
||||
<script src='js/id/core/difference.js'></script>
|
||||
<script src='js/id/core/entity.js'></script>
|
||||
<script src='js/id/core/graph.js'></script>
|
||||
<script src='js/id/core/history.js'></script>
|
||||
<script src='js/id/core/node.js'></script>
|
||||
<script src='js/id/core/relation.js'></script>
|
||||
<script src='js/id/core/way.js'></script>
|
||||
|
||||
<script src='js/id/connection.js'></script>
|
||||
<script src='js/id/validate.js'></script>
|
||||
|
||||
<script src='js/lib/locale.js'></script>
|
||||
<script src='locale/da.js'></script>
|
||||
<script src='locale/de.js'></script>
|
||||
<script src='locale/en.js'></script>
|
||||
<script src='locale/es.js'></script>
|
||||
<script src='locale/fr.js'></script>
|
||||
<script src='locale/ja.js'></script>
|
||||
<script src='locale/lv.js'></script>
|
||||
<script src='locale/tr.js'></script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="iD"></div><script>
|
||||
<div id='iD'></div><script>
|
||||
locale
|
||||
.current('en')
|
||||
.current(iD.detect().locale);
|
||||
|
||||
var id = iD();
|
||||
|
||||
d3.json('keys.json', function(err, keys) {
|
||||
var id = iD();
|
||||
id.connection().keys(keys)
|
||||
.url('http://api06.dev.openstreetmap.org');
|
||||
d3.select("#iD").call(id);
|
||||
id.connection()
|
||||
.keys(keys);
|
||||
|
||||
d3.select("#iD")
|
||||
.call(id.ui())
|
||||
});
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
|
||||
<!-- google analytics -->
|
||||
<script type='text/javascript'>
|
||||
var _gaq = _gaq || [];
|
||||
_gaq.push(['_setAccount', 'UA-38039653-2']);
|
||||
_gaq.push(['_trackPageview']);
|
||||
@@ -144,7 +185,26 @@ _gaq.push(['_trackPageview']);
|
||||
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
|
||||
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
|
||||
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
|
||||
|
||||
// javascript errors
|
||||
var lastev = '';
|
||||
window.onerror = function(message, file, lineNumber) {
|
||||
var ev = ['_trackEvent', 'error', file + ':' + lineNumber, message + ''];
|
||||
if (ev.join(',') !== lastev) {
|
||||
_gaq.push(ev);
|
||||
lastev = ev.join(',');
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
</script>
|
||||
|
||||
<!-- crazyegg -->
|
||||
<script type="text/javascript">
|
||||
setTimeout(function(){var a=document.createElement("script");
|
||||
var b=document.getElementsByTagName("script")[0];
|
||||
a.src=document.location.protocol+"//dnn506yrbagrg.cloudfront.net/pages/scripts/0013/6714.js?"+Math.floor(new Date().getTime()/3600000);
|
||||
a.async=true;a.type="text/javascript";b.parentNode.insertBefore(a,b)}, 1);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -16,8 +16,17 @@
|
||||
</head>
|
||||
<body>
|
||||
<div id="iD"></div><script>
|
||||
locale.current = 'en';
|
||||
|
||||
var id = iD();
|
||||
id.connection().url('http://api06.dev.openstreetmap.org');
|
||||
d3.select("#iD").call(id);
|
||||
|
||||
d3.json('keys.json', function(err, keys) {
|
||||
id.connection()
|
||||
.keys(keys)
|
||||
.url('http://api06.dev.openstreetmap.org');
|
||||
|
||||
d3.select("#iD")
|
||||
.call(id.ui())
|
||||
});
|
||||
</script></body>
|
||||
</html>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
iD.actions.AddWay = function(way) {
|
||||
iD.actions.AddEntity = function(way) {
|
||||
return function(graph) {
|
||||
return graph.replace(way);
|
||||
};
|
||||
@@ -0,0 +1,11 @@
|
||||
iD.actions.AddMidpoint = function(midpoint, node) {
|
||||
return function(graph) {
|
||||
graph = graph.replace(node.move(midpoint.loc));
|
||||
|
||||
midpoint.ways.forEach(function(way) {
|
||||
graph = graph.replace(graph.entity(way.id).addNode(node.id, way.index));
|
||||
});
|
||||
|
||||
return graph;
|
||||
};
|
||||
};
|
||||
@@ -1,6 +0,0 @@
|
||||
// https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/command/AddCommand.java
|
||||
iD.actions.AddNode = function(node) {
|
||||
return function(graph) {
|
||||
return graph.replace(node);
|
||||
};
|
||||
};
|
||||
@@ -1,5 +1,5 @@
|
||||
// https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/AddNodeToWayAction.as
|
||||
iD.actions.AddWayNode = function(wayId, nodeId, index) {
|
||||
iD.actions.AddVertex = function(wayId, nodeId, index) {
|
||||
return function(graph) {
|
||||
return graph.replace(graph.entity(wayId).addNode(nodeId, index));
|
||||
};
|
||||
@@ -1,4 +1,4 @@
|
||||
iD.actions.ChangeEntityTags = function(entityId, tags) {
|
||||
iD.actions.ChangeTags = function(entityId, tags) {
|
||||
return function(graph) {
|
||||
var entity = graph.entity(entityId);
|
||||
return graph.replace(entity.update({tags: tags}));
|
||||
@@ -1,58 +0,0 @@
|
||||
iD.actions.Circular = function(wayId, map) {
|
||||
|
||||
var action = function(graph) {
|
||||
var way = graph.entity(wayId),
|
||||
nodes = graph.childNodes(way),
|
||||
tags = {}, key, role;
|
||||
|
||||
var points = nodes.map(function(n) {
|
||||
return map.projection(n.loc);
|
||||
}),
|
||||
centroid = d3.geom.polygon(points).centroid(),
|
||||
radius = d3.median(points, function(p) {
|
||||
return iD.geo.dist(centroid, p);
|
||||
}),
|
||||
circular_nodes = [];
|
||||
|
||||
for (var i = 0; i < 12; i++) {
|
||||
circular_nodes.push(iD.Node({ loc: map.projection.invert([
|
||||
centroid[0] + Math.cos((i / 12) * Math.PI * 2) * radius,
|
||||
centroid[1] + Math.sin((i / 12) * Math.PI * 2) * radius])
|
||||
}));
|
||||
}
|
||||
|
||||
circular_nodes.push(circular_nodes[0]);
|
||||
|
||||
for (i = 0; i < nodes.length; i++) {
|
||||
if (graph.parentWays(nodes[i]).length > 1) {
|
||||
var closest, closest_dist = Infinity, dist;
|
||||
for (var j = 0; j < circular_nodes.length; j++) {
|
||||
dist = iD.geo.dist(circular_nodes[j].loc, nodes[i].loc);
|
||||
if (dist < closest_dist) {
|
||||
closest_dist = dist;
|
||||
closest = j;
|
||||
}
|
||||
}
|
||||
circular_nodes.splice(closest, 1, nodes[i]);
|
||||
if (closest === 0) circular_nodes.splice(circular_nodes.length - 1, 1, nodes[i]);
|
||||
else if (closest === circular_nodes.length - 1) circular_nodes.splice(0, 1, nodes[i]);
|
||||
} else {
|
||||
graph = graph.remove(nodes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < circular_nodes.length; i++) {
|
||||
graph = graph.replace(circular_nodes[i]);
|
||||
}
|
||||
|
||||
return graph.replace(way.update({
|
||||
nodes: _.pluck(circular_nodes, 'id')
|
||||
}));
|
||||
};
|
||||
|
||||
action.enabled = function(graph) {
|
||||
return graph.entity(wayId).isClosed();
|
||||
};
|
||||
|
||||
return action;
|
||||
};
|
||||
@@ -0,0 +1,64 @@
|
||||
iD.actions.Circularize = function(wayId, projection, count) {
|
||||
count = count || 12;
|
||||
|
||||
function closestIndex(nodes, loc) {
|
||||
var idx, min = Infinity, dist;
|
||||
for (var i = 0; i < nodes.length; i++) {
|
||||
dist = iD.geo.dist(nodes[i].loc, loc);
|
||||
if (dist < min) {
|
||||
min = dist;
|
||||
idx = i;
|
||||
}
|
||||
}
|
||||
return idx;
|
||||
}
|
||||
|
||||
var action = function(graph) {
|
||||
var way = graph.entity(wayId),
|
||||
nodes = _.uniq(graph.childNodes(way)),
|
||||
points = nodes.map(function(n) { return projection(n.loc); }),
|
||||
centroid = d3.geom.polygon(points).centroid(),
|
||||
radius = d3.median(points, function(p) {
|
||||
return iD.geo.dist(centroid, p);
|
||||
}),
|
||||
ids = [];
|
||||
|
||||
for (var i = 0; i < count; i++) {
|
||||
var node,
|
||||
loc = projection.invert([
|
||||
centroid[0] + Math.cos((i / 12) * Math.PI * 2) * radius,
|
||||
centroid[1] + Math.sin((i / 12) * Math.PI * 2) * radius]);
|
||||
|
||||
if (nodes.length) {
|
||||
var idx = closestIndex(nodes, loc);
|
||||
node = nodes[idx];
|
||||
nodes.splice(idx, 1);
|
||||
} else {
|
||||
node = iD.Node();
|
||||
}
|
||||
|
||||
ids.push(node.id);
|
||||
graph = graph.replace(node.move(loc));
|
||||
}
|
||||
|
||||
ids.push(ids[0]);
|
||||
graph = graph.replace(way.update({nodes: ids}));
|
||||
|
||||
for (i = 0; i < nodes.length; i++) {
|
||||
graph.parentWays(nodes[i]).forEach(function(parent) {
|
||||
graph = graph.replace(parent.replaceNode(nodes[i].id,
|
||||
ids[closestIndex(graph.childNodes(way), nodes[i].loc)]));
|
||||
});
|
||||
|
||||
graph = iD.actions.DeleteNode(nodes[i].id)(graph);
|
||||
}
|
||||
|
||||
return graph;
|
||||
};
|
||||
|
||||
action.enabled = function(graph) {
|
||||
return graph.entity(wayId).isClosed();
|
||||
};
|
||||
|
||||
return action;
|
||||
};
|
||||
@@ -0,0 +1,44 @@
|
||||
// Connect the ways at the given nodes.
|
||||
//
|
||||
// The last node will survive. All other nodes will be replaced with
|
||||
// the surviving node in parent ways, and then removed.
|
||||
//
|
||||
// Tags and relation memberships of of non-surviving nodes are merged
|
||||
// to the survivor.
|
||||
//
|
||||
// This is the inverse of `iD.actions.Disconnect`.
|
||||
//
|
||||
// Reference:
|
||||
// https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MergeNodesAction.as
|
||||
// https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/MergeNodesAction.java
|
||||
//
|
||||
iD.actions.Connect = function(nodeIds) {
|
||||
var action = function(graph) {
|
||||
var survivor = graph.entity(_.last(nodeIds));
|
||||
|
||||
for (var i = 0; i < nodeIds.length - 1; i++) {
|
||||
var node = graph.entity(nodeIds[i]), index;
|
||||
|
||||
graph.parentWays(node).forEach(function(parent) {
|
||||
graph = graph.replace(parent.replaceNode(node.id, survivor.id));
|
||||
});
|
||||
|
||||
graph.parentRelations(node).forEach(function(parent) {
|
||||
graph = graph.replace(parent.replaceMember(node, survivor));
|
||||
});
|
||||
|
||||
survivor = survivor.mergeTags(node.tags);
|
||||
graph = iD.actions.DeleteNode(node.id)(graph);
|
||||
}
|
||||
|
||||
graph = graph.replace(survivor);
|
||||
|
||||
return graph;
|
||||
};
|
||||
|
||||
action.enabled = function(graph) {
|
||||
return nodeIds.length > 1;
|
||||
};
|
||||
|
||||
return action;
|
||||
};
|
||||
@@ -0,0 +1,18 @@
|
||||
iD.actions.DeleteMultiple = function(ids) {
|
||||
return function(graph) {
|
||||
var actions = {
|
||||
way: iD.actions.DeleteWay,
|
||||
node: iD.actions.DeleteNode,
|
||||
relation: iD.actions.DeleteRelation
|
||||
};
|
||||
|
||||
ids.forEach(function(id) {
|
||||
var entity = graph.entity(id);
|
||||
if (entity) { // It may have been deleted aready.
|
||||
graph = actions[entity.type](id)(graph);
|
||||
}
|
||||
});
|
||||
|
||||
return graph;
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,13 @@
|
||||
// https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/DeleteRelationAction.as
|
||||
iD.actions.DeleteRelation = function(relationId) {
|
||||
return function(graph) {
|
||||
var relation = graph.entity(relationId);
|
||||
|
||||
graph.parentRelations(relation)
|
||||
.forEach(function(parent) {
|
||||
graph = graph.replace(parent.removeMember(relationId));
|
||||
});
|
||||
|
||||
return graph.remove(relation);
|
||||
};
|
||||
};
|
||||
@@ -8,7 +8,7 @@ iD.actions.DeleteWay = function(wayId) {
|
||||
graph = graph.replace(parent.removeMember(wayId));
|
||||
});
|
||||
|
||||
way.nodes.forEach(function (nodeId) {
|
||||
way.nodes.forEach(function(nodeId) {
|
||||
var node = graph.entity(nodeId);
|
||||
|
||||
// Circular ways include nodes more than once, so they
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
iD.actions.DeprecateTags = function(entityId) {
|
||||
return function(graph) {
|
||||
var entity = graph.entity(entityId),
|
||||
newtags = _.clone(entity.tags),
|
||||
change = false,
|
||||
rule;
|
||||
|
||||
// This handles deprecated tags with a single condition
|
||||
for (var i = 0; i < iD.data.deprecated.length; i++) {
|
||||
|
||||
rule = iD.data.deprecated[i];
|
||||
var match = _.pairs(rule.old)[0],
|
||||
replacements = rule.replace ? _.pairs(rule.replace) : null;
|
||||
|
||||
if (entity.tags[match[0]] && match[1] === '*') {
|
||||
|
||||
var value = entity.tags[match[0]];
|
||||
if (replacements && !newtags[replacements[0][0]]) {
|
||||
newtags[replacements[0][0]] = value;
|
||||
}
|
||||
delete newtags[match[0]];
|
||||
change = true;
|
||||
|
||||
} else if (entity.tags[match[0]] === match[1]) {
|
||||
newtags = _.assign({}, rule.replace || {}, _.omit(newtags, match[0]));
|
||||
change = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (change) {
|
||||
return graph.replace(entity.update({tags: newtags}));
|
||||
} else {
|
||||
return graph;
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -1,14 +1,16 @@
|
||||
// Unjoin the ways at the given node.
|
||||
// Disconect the ways at the given node.
|
||||
//
|
||||
// For testing convenience, accepts an ID to assign to the (first) new node.
|
||||
// Normally, this will be undefined and the way will automatically
|
||||
// be assigned a new ID.
|
||||
//
|
||||
// This is the inverse of `iD.actions.Connect`.
|
||||
//
|
||||
// Reference:
|
||||
// https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/UnjoinNodeAction.as
|
||||
// https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/UnGlueAction.java
|
||||
//
|
||||
iD.actions.UnjoinNode = function(nodeId, newNodeId) {
|
||||
iD.actions.Disconnect = function(nodeId, newNodeId) {
|
||||
var action = function(graph) {
|
||||
if (!action.enabled(graph))
|
||||
return graph;
|
||||
@@ -0,0 +1,76 @@
|
||||
// Join ways at the end node they share.
|
||||
//
|
||||
// This is the inverse of `iD.actions.Split`.
|
||||
//
|
||||
// Reference:
|
||||
// https://github.com/systemed/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MergeWaysAction.as
|
||||
// https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/CombineWayAction.java
|
||||
//
|
||||
iD.actions.Join = function(ids) {
|
||||
var idA = ids[0],
|
||||
idB = ids[1];
|
||||
|
||||
function groupEntitiesByGeometry(graph) {
|
||||
var entities = ids.map(function(id) { return graph.entity(id); });
|
||||
return _.extend({line: []}, _.groupBy(entities, function(entity) { return entity.geometry(graph); }));
|
||||
}
|
||||
|
||||
var action = function(graph) {
|
||||
var a = graph.entity(idA),
|
||||
b = graph.entity(idB),
|
||||
nodes;
|
||||
|
||||
if (a.first() === b.first()) {
|
||||
// a <-- b ==> c
|
||||
// Expected result:
|
||||
// a <-- b <-- c
|
||||
b = iD.actions.Reverse(idB)(graph).entity(idB);
|
||||
nodes = b.nodes.slice().concat(a.nodes.slice(1));
|
||||
|
||||
} else if (a.first() === b.last()) {
|
||||
// a <-- b <== c
|
||||
// Expected result:
|
||||
// a <-- b <-- c
|
||||
nodes = b.nodes.concat(a.nodes.slice(1));
|
||||
|
||||
} else if (a.last() === b.first()) {
|
||||
// a --> b ==> c
|
||||
// Expected result:
|
||||
// a --> b --> c
|
||||
nodes = a.nodes.concat(b.nodes.slice(1));
|
||||
|
||||
} else if (a.last() === b.last()) {
|
||||
// a --> b <== c
|
||||
// Expected result:
|
||||
// a --> b --> c
|
||||
b = iD.actions.Reverse(idB)(graph).entity(idB);
|
||||
nodes = a.nodes.concat(b.nodes.slice().slice(1));
|
||||
}
|
||||
|
||||
graph.parentRelations(b).forEach(function(parent) {
|
||||
graph = graph.replace(parent.replaceMember(b, a));
|
||||
});
|
||||
|
||||
graph = graph.replace(a.mergeTags(b.tags).update({ nodes: nodes }));
|
||||
graph = iD.actions.DeleteWay(idB)(graph);
|
||||
|
||||
return graph;
|
||||
};
|
||||
|
||||
action.enabled = function(graph) {
|
||||
var geometries = groupEntitiesByGeometry(graph);
|
||||
|
||||
if (ids.length !== 2 || ids.length !== geometries.line.length)
|
||||
return false;
|
||||
|
||||
var a = graph.entity(idA),
|
||||
b = graph.entity(idB);
|
||||
|
||||
return a.first() === b.first() ||
|
||||
a.first() === b.last() ||
|
||||
a.last() === b.first() ||
|
||||
a.last() === b.last();
|
||||
};
|
||||
|
||||
return action;
|
||||
};
|
||||
@@ -0,0 +1,35 @@
|
||||
iD.actions.Merge = function(ids) {
|
||||
function groupEntitiesByGeometry(graph) {
|
||||
var entities = ids.map(function(id) { return graph.entity(id); });
|
||||
return _.extend({point: [], area: []}, _.groupBy(entities, function(entity) { return entity.geometry(graph); }));
|
||||
}
|
||||
|
||||
var action = function(graph) {
|
||||
var geometries = groupEntitiesByGeometry(graph),
|
||||
area = geometries.area[0],
|
||||
points = geometries.point;
|
||||
|
||||
points.forEach(function(point) {
|
||||
area = area.mergeTags(point.tags);
|
||||
|
||||
graph.parentRelations(point).forEach(function(parent) {
|
||||
graph = graph.replace(parent.replaceMember(point, area));
|
||||
});
|
||||
|
||||
graph = graph.remove(point);
|
||||
});
|
||||
|
||||
graph = graph.replace(area);
|
||||
|
||||
return graph;
|
||||
};
|
||||
|
||||
action.enabled = function(graph) {
|
||||
var geometries = groupEntitiesByGeometry(graph);
|
||||
return geometries.area.length === 1 &&
|
||||
geometries.point.length > 0 &&
|
||||
(geometries.area.length + geometries.point.length) === ids.length;
|
||||
};
|
||||
|
||||
return action;
|
||||
};
|
||||
@@ -1,9 +1,9 @@
|
||||
iD.actions.MoveWay = function(wayId, delta, projection) {
|
||||
return function(graph) {
|
||||
return graph.update(function (graph) {
|
||||
return graph.update(function(graph) {
|
||||
var way = graph.entity(wayId);
|
||||
|
||||
_.uniq(way.nodes).forEach(function (id) {
|
||||
_.uniq(way.nodes).forEach(function(id) {
|
||||
var node = graph.entity(id),
|
||||
start = projection(node.loc),
|
||||
end = projection.invert([start[0] + delta[0], start[1] + delta[1]]);
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Based on https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/potlatch2/tools/Quadrilateralise.as
|
||||
*/
|
||||
|
||||
iD.actions.Orthogonalize = function(wayId, projection) {
|
||||
var action = function(graph) {
|
||||
var way = graph.entity(wayId),
|
||||
nodes = graph.childNodes(way),
|
||||
points = nodes.map(function(n) { return projection(n.loc); }),
|
||||
quad_nodes = [],
|
||||
best, i, j;
|
||||
|
||||
var score = squareness();
|
||||
for (i = 0; i < 1000; i++) {
|
||||
var motions = points.map(stepMap);
|
||||
for (j = 0; j < motions.length; j++) {
|
||||
points[j] = addPoints(points[j],motions[j]);
|
||||
}
|
||||
var newScore = squareness();
|
||||
if (newScore < score) {
|
||||
best = _.clone(points);
|
||||
score = newScore;
|
||||
}
|
||||
if (score < 1.0e-8) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
points = best;
|
||||
|
||||
for (i = 0; i < points.length - 1; i++) {
|
||||
graph = graph.replace(graph.entity(nodes[i].id).move(projection.invert(points[i])));
|
||||
}
|
||||
|
||||
return graph;
|
||||
|
||||
function stepMap(b, i, array) {
|
||||
var a = array[(i - 1 + array.length) % array.length],
|
||||
c = array[(i + 1) % array.length],
|
||||
p = subtractPoints(a, b),
|
||||
q = subtractPoints(c, b);
|
||||
|
||||
var scale = iD.geo.dist(p, [0, 0]) + iD.geo.dist(q, [0, 0]);
|
||||
p = normalizePoint(p, 1.0);
|
||||
q = normalizePoint(q, 1.0);
|
||||
|
||||
var dotp = p[0] *q[0] + p[1] *q[1];
|
||||
// nasty hack to deal with almost-straight segments (angle is closer to 180 than to 90/270).
|
||||
if (dotp < -0.707106781186547) {
|
||||
dotp += 1.0;
|
||||
}
|
||||
|
||||
return normalizePoint(addPoints(p, q), 0.1 * dotp * scale);
|
||||
}
|
||||
|
||||
function squareness() {
|
||||
var g = 0.0;
|
||||
for (var i = 1; i < points.length - 1; i++) {
|
||||
var score = scoreOfPoints(points[i - 1], points[i], points[i + 1]);
|
||||
g += score;
|
||||
}
|
||||
var startScore = scoreOfPoints(points[points.length - 1], points[0], points[1]);
|
||||
var endScore = scoreOfPoints(points[points.length - 2], points[points.length - 1], points[0]);
|
||||
g += startScore;
|
||||
g += endScore;
|
||||
return g;
|
||||
}
|
||||
|
||||
function scoreOfPoints(a, b, c) {
|
||||
var p = subtractPoints(a, b),
|
||||
q = subtractPoints(c, b);
|
||||
|
||||
p = normalizePoint(p, 1.0);
|
||||
q = normalizePoint(q, 1.0);
|
||||
|
||||
var dotp = p[0] * q[0] + p[1] * q[1];
|
||||
// score is constructed so that +1, -1 and 0 are all scored 0, any other angle
|
||||
// is scored higher.
|
||||
return 2.0 * Math.min(Math.abs(dotp - 1.0), Math.min(Math.abs(dotp), Math.abs(dotp + 1)));
|
||||
}
|
||||
|
||||
function subtractPoints(a, b) {
|
||||
return [a[0] - b[0], a[1] - b[1]];
|
||||
}
|
||||
|
||||
function addPoints(a, b) {
|
||||
return [a[0] + b[0], a[1] + b[1]];
|
||||
}
|
||||
|
||||
function normalizePoint(point, thickness) {
|
||||
var vector = [0, 0];
|
||||
var length = Math.sqrt(point[0] * point[0] + point[1] * point[1]);
|
||||
if (length !== 0) {
|
||||
vector[0] = point[0] / length;
|
||||
vector[1] = point[1] / length;
|
||||
}
|
||||
|
||||
vector[0] *= thickness;
|
||||
vector[1] *= thickness;
|
||||
|
||||
return vector;
|
||||
}
|
||||
};
|
||||
|
||||
action.enabled = function(graph) {
|
||||
return graph.entity(wayId).isClosed();
|
||||
};
|
||||
|
||||
return action;
|
||||
};
|
||||
@@ -27,7 +27,7 @@
|
||||
http://wiki.openstreetmap.org/wiki/Route#Members
|
||||
http://josm.openstreetmap.de/browser/josm/trunk/src/org/openstreetmap/josm/corrector/ReverseWayTagCorrector.java
|
||||
*/
|
||||
iD.actions.ReverseWay = function(wayId) {
|
||||
iD.actions.Reverse = function(wayId) {
|
||||
var replacements = [
|
||||
[/:right$/, ':left'], [/:left$/, ':right'],
|
||||
[/:forward$/, ':backward'], [/:backward$/, ':forward']
|
||||
@@ -62,8 +62,8 @@ iD.actions.ReverseWay = function(wayId) {
|
||||
tags[reverseKey(key)] = reverseValue(key, way.tags[key]);
|
||||
}
|
||||
|
||||
graph.parentRelations(way).forEach(function (relation) {
|
||||
relation.members.forEach(function (member, index) {
|
||||
graph.parentRelations(way).forEach(function(relation) {
|
||||
relation.members.forEach(function(member, index) {
|
||||
if (member.id === way.id && (role = {forward: 'backward', backward: 'forward'}[member.role])) {
|
||||
relation = relation.updateMember({role: role}, index);
|
||||
graph = graph.replace(relation);
|
||||
@@ -0,0 +1,102 @@
|
||||
// Split a way at the given node.
|
||||
//
|
||||
// This is the inverse of `iD.actions.Join`.
|
||||
//
|
||||
// For testing convenience, accepts an ID to assign to the new way.
|
||||
// Normally, this will be undefined and the way will automatically
|
||||
// be assigned a new ID.
|
||||
//
|
||||
// Reference:
|
||||
// https://github.com/systemed/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/SplitWayAction.as
|
||||
//
|
||||
iD.actions.Split = function(nodeId, newWayId) {
|
||||
function candidateWays(graph) {
|
||||
var node = graph.entity(nodeId),
|
||||
parents = graph.parentWays(node);
|
||||
|
||||
return parents.filter(function(parent) {
|
||||
return parent.isClosed() ||
|
||||
(parent.first() !== nodeId &&
|
||||
parent.last() !== nodeId);
|
||||
});
|
||||
}
|
||||
|
||||
var action = function(graph) {
|
||||
var wayA = candidateWays(graph)[0],
|
||||
wayB = iD.Way({id: newWayId, tags: wayA.tags}),
|
||||
nodesA,
|
||||
nodesB,
|
||||
isArea = wayA.isArea();
|
||||
|
||||
if (wayA.isClosed()) {
|
||||
var nodes = wayA.nodes.slice(0, -1),
|
||||
idxA = _.indexOf(nodes, nodeId),
|
||||
idxB = idxA + Math.floor(nodes.length / 2);
|
||||
|
||||
if (idxB >= nodes.length) {
|
||||
idxB %= nodes.length;
|
||||
nodesA = nodes.slice(idxA).concat(nodes.slice(0, idxB + 1));
|
||||
nodesB = nodes.slice(idxB, idxA + 1);
|
||||
} else {
|
||||
nodesA = nodes.slice(idxA, idxB + 1);
|
||||
nodesB = nodes.slice(idxB).concat(nodes.slice(0, idxA + 1));
|
||||
}
|
||||
} else {
|
||||
var idx = _.indexOf(wayA.nodes, nodeId);
|
||||
nodesA = wayA.nodes.slice(0, idx + 1);
|
||||
nodesB = wayA.nodes.slice(idx);
|
||||
}
|
||||
|
||||
wayA = wayA.update({nodes: nodesA});
|
||||
wayB = wayB.update({nodes: nodesB});
|
||||
|
||||
graph = graph.replace(wayA);
|
||||
graph = graph.replace(wayB);
|
||||
|
||||
graph.parentRelations(wayA).forEach(function(relation) {
|
||||
if (relation.isRestriction()) {
|
||||
var via = relation.memberByRole('via');
|
||||
if (via && wayB.contains(via.id)) {
|
||||
relation = relation.updateMember({id: wayB.id}, relation.memberById(wayA.id).index);
|
||||
graph = graph.replace(relation);
|
||||
}
|
||||
} else {
|
||||
var role = relation.memberById(wayA.id).role,
|
||||
last = wayB.last(),
|
||||
i = relation.memberById(wayA.id).index,
|
||||
j;
|
||||
|
||||
for (j = 0; j < relation.members.length; j++) {
|
||||
var entity = graph.entity(relation.members[j].id);
|
||||
if (entity && entity.type === 'way' && entity.contains(last)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
relation = relation.addMember({id: wayB.id, type: 'way', role: role}, i <= j ? i + 1 : i);
|
||||
graph = graph.replace(relation);
|
||||
}
|
||||
});
|
||||
|
||||
if (isArea) {
|
||||
var multipolygon = iD.Relation({
|
||||
tags: _.extend({}, wayA.tags, {type: 'multipolygon'}),
|
||||
members: [
|
||||
{id: wayA.id, role: 'outer', type: 'way'},
|
||||
{id: wayB.id, role: 'outer', type: 'way'}
|
||||
]});
|
||||
|
||||
graph = graph.replace(multipolygon);
|
||||
graph = graph.replace(wayA.update({tags: {}}));
|
||||
graph = graph.replace(wayB.update({tags: {}}));
|
||||
}
|
||||
|
||||
return graph;
|
||||
};
|
||||
|
||||
action.enabled = function(graph) {
|
||||
return candidateWays(graph).length === 1;
|
||||
};
|
||||
|
||||
return action;
|
||||
};
|
||||
@@ -1,69 +0,0 @@
|
||||
// Split a way at the given node.
|
||||
//
|
||||
// For testing convenience, accepts an ID to assign to the new way.
|
||||
// Normally, this will be undefined and the way will automatically
|
||||
// be assigned a new ID.
|
||||
//
|
||||
// Reference:
|
||||
// https://github.com/systemed/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/SplitWayAction.as
|
||||
//
|
||||
iD.actions.SplitWay = function(nodeId, newWayId) {
|
||||
function candidateWays(graph) {
|
||||
var node = graph.entity(nodeId),
|
||||
parents = graph.parentWays(node);
|
||||
|
||||
return parents.filter(function (parent) {
|
||||
return parent.first() !== nodeId &&
|
||||
parent.last() !== nodeId;
|
||||
})
|
||||
}
|
||||
|
||||
var action = function(graph) {
|
||||
if (!action.enabled(graph))
|
||||
return graph;
|
||||
|
||||
var way = candidateWays(graph)[0],
|
||||
idx = _.indexOf(way.nodes, nodeId);
|
||||
|
||||
// Create a 'b' way that contains all of the tags in the second
|
||||
// half of this way
|
||||
var newWay = iD.Way({id: newWayId, tags: way.tags, nodes: way.nodes.slice(idx)});
|
||||
graph = graph.replace(newWay);
|
||||
|
||||
// Reduce the original way to only contain the first set of nodes
|
||||
graph = graph.replace(way.update({nodes: way.nodes.slice(0, idx + 1)}));
|
||||
|
||||
graph.parentRelations(way).forEach(function(relation) {
|
||||
if (relation.isRestriction()) {
|
||||
var via = relation.memberByRole('via');
|
||||
if (via && newWay.contains(via.id)) {
|
||||
relation = relation.updateMember({id: newWay.id}, relation.memberById(way.id).index);
|
||||
graph = graph.replace(relation);
|
||||
}
|
||||
} else {
|
||||
var role = relation.memberById(way.id).role,
|
||||
last = newWay.last(),
|
||||
i = relation.memberById(way.id).index,
|
||||
j;
|
||||
|
||||
for (j = 0; j < relation.members.length; j++) {
|
||||
var entity = graph.entity(relation.members[j].id);
|
||||
if (entity && entity.type === 'way' && entity.contains(last)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
relation = relation.addMember({id: newWay.id, type: 'way', role: role}, i <= j ? i + 1 : i);
|
||||
graph = graph.replace(relation);
|
||||
}
|
||||
});
|
||||
|
||||
return graph;
|
||||
};
|
||||
|
||||
action.enabled = function(graph) {
|
||||
return candidateWays(graph).length === 1;
|
||||
};
|
||||
|
||||
return action;
|
||||
};
|
||||
@@ -1,26 +1,16 @@
|
||||
iD.behavior.AddWay = function(mode) {
|
||||
var map = mode.map,
|
||||
history = mode.history,
|
||||
controller = mode.controller,
|
||||
event = d3.dispatch('startFromNode', 'startFromWay', 'start'),
|
||||
draw;
|
||||
|
||||
function add(datum) {
|
||||
if (datum.type === 'node') {
|
||||
event.startFromNode(datum);
|
||||
} else if (datum.type === 'way') {
|
||||
var choice = iD.geo.chooseIndex(datum, d3.mouse(map.surface.node()), map);
|
||||
event.startFromWay(datum, choice.loc, choice.index);
|
||||
} else if (datum.midpoint) {
|
||||
var way = history.graph().entity(datum.way);
|
||||
event.startFromWay(way, datum.loc, datum.index);
|
||||
} else {
|
||||
event.start(map.mouseCoordinates());
|
||||
}
|
||||
}
|
||||
iD.behavior.AddWay = function(context) {
|
||||
var event = d3.dispatch('start', 'startFromWay', 'startFromNode'),
|
||||
draw = iD.behavior.Draw(context);
|
||||
|
||||
var addWay = function(surface) {
|
||||
map.fastEnable(false)
|
||||
draw.on('click', event.start)
|
||||
.on('clickWay', event.startFromWay)
|
||||
.on('clickNode', event.startFromNode)
|
||||
.on('cancel', addWay.cancel)
|
||||
.on('finish', addWay.cancel);
|
||||
|
||||
context.map()
|
||||
.fastEnable(false)
|
||||
.minzoom(16)
|
||||
.dblclickEnable(false);
|
||||
|
||||
@@ -28,25 +18,21 @@ iD.behavior.AddWay = function(mode) {
|
||||
};
|
||||
|
||||
addWay.off = function(surface) {
|
||||
map.fastEnable(true)
|
||||
context.map()
|
||||
.fastEnable(true)
|
||||
.minzoom(0)
|
||||
.tail(false);
|
||||
|
||||
window.setTimeout(function() {
|
||||
map.dblclickEnable(true);
|
||||
context.map().dblclickEnable(true);
|
||||
}, 1000);
|
||||
|
||||
surface.call(draw.off);
|
||||
};
|
||||
|
||||
addWay.cancel = function() {
|
||||
controller.exit();
|
||||
context.enter(iD.modes.Browse(context));
|
||||
};
|
||||
|
||||
draw = iD.behavior.Draw()
|
||||
.on('add', add)
|
||||
.on('cancel', addWay.cancel)
|
||||
.on('finish', addWay.cancel);
|
||||
|
||||
return d3.rebind(addWay, event, 'on');
|
||||
};
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* Delegation is supported via the `delegate` function.
|
||||
|
||||
*/
|
||||
iD.behavior.drag = function () {
|
||||
iD.behavior.drag = function() {
|
||||
function d3_eventCancel() {
|
||||
d3.event.stopPropagation();
|
||||
d3.event.preventDefault();
|
||||
@@ -24,8 +24,7 @@ iD.behavior.drag = function () {
|
||||
origin = null,
|
||||
selector = '',
|
||||
filter = null,
|
||||
keybinding = d3.keybinding('drag'),
|
||||
event_, target;
|
||||
event_, target, surface;
|
||||
|
||||
event.of = function(thiz, argumentz) {
|
||||
return function(e1) {
|
||||
@@ -50,27 +49,26 @@ iD.behavior.drag = function () {
|
||||
moved = 0;
|
||||
|
||||
var w = d3.select(window)
|
||||
.on(touchId != null ? "touchmove.drag-" + touchId : "mousemove.drag", dragmove)
|
||||
.on(touchId != null ? "touchend.drag-" + touchId : "mouseup.drag", dragend, true);
|
||||
.on(touchId !== null ? "touchmove.drag-" + touchId : "mousemove.drag", dragmove)
|
||||
.on(touchId !== null ? "touchend.drag-" + touchId : "mouseup.drag", dragend, true);
|
||||
|
||||
if (origin) {
|
||||
offset = origin.apply(target, arguments);
|
||||
offset = [ offset[0] - origin_[0], offset[1] - origin_[1] ];
|
||||
offset = [offset[0] - origin_[0], offset[1] - origin_[1]];
|
||||
} else {
|
||||
offset = [ 0, 0 ];
|
||||
offset = [0, 0];
|
||||
}
|
||||
|
||||
if (touchId == null) d3_eventCancel();
|
||||
if (touchId === null) d3_eventCancel();
|
||||
|
||||
function point() {
|
||||
var p = target.parentNode;
|
||||
return touchId != null ? d3.touches(p).filter(function (p) {
|
||||
var p = target.parentNode || surface;
|
||||
return touchId !== null ? d3.touches(p).filter(function(p) {
|
||||
return p.identifier === touchId;
|
||||
})[0] : d3.mouse(p);
|
||||
}
|
||||
|
||||
function dragmove() {
|
||||
if (!target.parentNode) return dragend();
|
||||
|
||||
var p = point(),
|
||||
dx = p[0] - origin_[0],
|
||||
@@ -103,8 +101,8 @@ iD.behavior.drag = function () {
|
||||
if (d3.event.target === eventTarget) w.on("click.drag", click, true);
|
||||
}
|
||||
|
||||
w.on(touchId != null ? "touchmove.drag-" + touchId : "mousemove.drag", null)
|
||||
.on(touchId != null ? "touchend.drag-" + touchId : "mouseup.drag", null);
|
||||
w.on(touchId !== null ? "touchmove.drag-" + touchId : "mousemove.drag", null)
|
||||
.on(touchId !== null ? "touchend.drag-" + touchId : "mouseup.drag", null);
|
||||
}
|
||||
|
||||
function click() {
|
||||
@@ -137,9 +135,6 @@ iD.behavior.drag = function () {
|
||||
drag.off = function(selection) {
|
||||
selection.on("mousedown.drag" + selector, null)
|
||||
.on("touchstart.drag" + selector, null);
|
||||
keybinding
|
||||
.on('⌘+Z', null)
|
||||
.on('⌃+Z', null);
|
||||
};
|
||||
|
||||
drag.delegate = function(_) {
|
||||
@@ -174,11 +169,11 @@ iD.behavior.drag = function () {
|
||||
return drag;
|
||||
};
|
||||
|
||||
keybinding
|
||||
.on('⌘+Z', drag.cancel)
|
||||
.on('⌃+Z', drag.cancel);
|
||||
|
||||
d3.select(document).call(keybinding);
|
||||
drag.surface = function() {
|
||||
if (!arguments.length) return surface;
|
||||
surface = arguments[0];
|
||||
return drag;
|
||||
};
|
||||
|
||||
return d3.rebind(drag, event, "on");
|
||||
};
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
iD.behavior.DragMidpoint = function(mode) {
|
||||
var history = mode.history,
|
||||
projection = mode.map.projection,
|
||||
behavior = iD.behavior.drag()
|
||||
.delegate(".midpoint")
|
||||
.origin(function(d) {
|
||||
return projection(d.loc);
|
||||
})
|
||||
.on('start', function(d) {
|
||||
var w, nds;
|
||||
d.node = iD.Node({loc: d.loc});
|
||||
var args = [iD.actions.AddNode(d.node)];
|
||||
for (var i = 0; i < d.ways.length; i++) {
|
||||
w = d.ways[i], nds = w.nodes;
|
||||
for (var j = 0; j < nds.length; j++) {
|
||||
if ((nds[j] === d.nodes[0] && nds[j + 1] === d.nodes[1]) ||
|
||||
(nds[j] === d.nodes[1] && nds[j + 1] === d.nodes[0])) {
|
||||
args.push(iD.actions.AddWayNode(w.id, d.node.id, j + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
history.perform.apply(history, args);
|
||||
var node = d3.selectAll('.node.vertex')
|
||||
.filter(function(data) { return data.id === d.node.id; });
|
||||
behavior.target(node.node(), node.datum());
|
||||
|
||||
})
|
||||
.on('move', function(d) {
|
||||
d3.event.sourceEvent.stopPropagation();
|
||||
history.replace(
|
||||
iD.actions.MoveNode(d.id, projection.invert(d3.event.point)));
|
||||
})
|
||||
.on('end', function() {
|
||||
history.replace(
|
||||
iD.actions.Noop(),
|
||||
'added a node to a way');
|
||||
});
|
||||
return behavior;
|
||||
};
|
||||
@@ -1,25 +1,164 @@
|
||||
iD.behavior.DragNode = function(mode) {
|
||||
var history = mode.history,
|
||||
projection = mode.map.projection;
|
||||
iD.behavior.DragNode = function(context) {
|
||||
var nudgeInterval,
|
||||
wasMidpoint,
|
||||
cancelled;
|
||||
|
||||
return iD.behavior.drag()
|
||||
.delegate(".node")
|
||||
.origin(function(entity) {
|
||||
return projection(entity.loc);
|
||||
})
|
||||
.on('start', function() {
|
||||
history.perform(
|
||||
function edge(point, size) {
|
||||
var pad = [30, 100, 30, 100];
|
||||
if (point[0] > size[0] - pad[0]) return [-10, 0];
|
||||
else if (point[0] < pad[2]) return [10, 0];
|
||||
else if (point[1] > size[1] - pad[1]) return [0, -10];
|
||||
else if (point[1] < pad[3]) return [0, 10];
|
||||
return null;
|
||||
}
|
||||
|
||||
function startNudge(nudge) {
|
||||
if (nudgeInterval) window.clearInterval(nudgeInterval);
|
||||
nudgeInterval = window.setInterval(function() {
|
||||
context.pan(nudge);
|
||||
}, 50);
|
||||
}
|
||||
|
||||
function stopNudge() {
|
||||
if (nudgeInterval) window.clearInterval(nudgeInterval);
|
||||
nudgeInterval = null;
|
||||
}
|
||||
|
||||
function moveAnnotation(entity) {
|
||||
return t('operations.move.annotation.' + entity.geometry(context.graph()));
|
||||
}
|
||||
|
||||
function connectAnnotation(datum) {
|
||||
return t('operations.connect.annotation.' + datum.geometry(context.graph()));
|
||||
}
|
||||
|
||||
function origin(entity) {
|
||||
return context.projection(entity.loc);
|
||||
}
|
||||
|
||||
function start(entity) {
|
||||
cancelled = d3.event.sourceEvent.shiftKey;
|
||||
if (cancelled) return behavior.cancel();
|
||||
|
||||
context.history()
|
||||
.on('undone.drag-node', cancel);
|
||||
|
||||
wasMidpoint = entity.type === 'midpoint';
|
||||
if (wasMidpoint) {
|
||||
var midpoint = entity;
|
||||
entity = iD.Node();
|
||||
context.perform(iD.actions.AddMidpoint(midpoint, entity));
|
||||
|
||||
var vertex = context.surface()
|
||||
.selectAll('.vertex')
|
||||
.filter(function(d) { return d.id === entity.id; });
|
||||
behavior.target(vertex.node(), entity);
|
||||
|
||||
} else {
|
||||
context.perform(
|
||||
iD.actions.Noop());
|
||||
})
|
||||
.on('move', function(entity) {
|
||||
d3.event.sourceEvent.stopPropagation();
|
||||
history.replace(
|
||||
iD.actions.MoveNode(entity.id, projection.invert(d3.event.point)),
|
||||
'moved a node');
|
||||
})
|
||||
.on('end', function() {
|
||||
history.replace(
|
||||
}
|
||||
|
||||
var activeIDs = _.pluck(context.graph().parentWays(entity), 'id');
|
||||
activeIDs.push(entity.id);
|
||||
|
||||
context.surface()
|
||||
.classed('behavior-drag-node', true)
|
||||
.selectAll('.node, .way')
|
||||
.filter(function(d) { return activeIDs.indexOf(d.id) >= 0; })
|
||||
.classed('active', true);
|
||||
}
|
||||
|
||||
function datum() {
|
||||
if (d3.event.sourceEvent.altKey) {
|
||||
return {};
|
||||
} else {
|
||||
return d3.event.sourceEvent.target.__data__ || {};
|
||||
}
|
||||
}
|
||||
|
||||
function move(entity) {
|
||||
if (cancelled) return;
|
||||
d3.event.sourceEvent.stopPropagation();
|
||||
|
||||
var nudge = edge(d3.event.point, context.map().size());
|
||||
if (nudge) startNudge(nudge);
|
||||
else stopNudge();
|
||||
|
||||
var loc = context.map().mouseCoordinates();
|
||||
|
||||
var d = datum();
|
||||
if (d.type === 'node' && d.id !== entity.id) {
|
||||
loc = d.loc;
|
||||
} else if (d.type === 'way') {
|
||||
var point = d3.mouse(context.surface().node()),
|
||||
index = iD.geo.chooseIndex(d, point, context);
|
||||
if (iD.geo.dist(point, context.projection(index.loc)) < 10) {
|
||||
loc = index.loc;
|
||||
}
|
||||
}
|
||||
|
||||
context.replace(iD.actions.MoveNode(entity.id, loc));
|
||||
}
|
||||
|
||||
function end(entity) {
|
||||
if (cancelled) return;
|
||||
off();
|
||||
|
||||
var d = datum();
|
||||
if (d.type === 'way') {
|
||||
var point = d3.mouse(context.surface().node()),
|
||||
choice = iD.geo.chooseIndex(d, point, context);
|
||||
if (iD.geo.dist(point, context.projection(choice.loc)) < 10) {
|
||||
context.replace(
|
||||
iD.actions.MoveNode(entity.id, choice.loc),
|
||||
iD.actions.AddVertex(d.id, entity.id, choice.index),
|
||||
connectAnnotation(d));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (d.type === 'node' && d.id !== entity.id) {
|
||||
context.replace(
|
||||
iD.actions.Connect([entity.id, d.id]),
|
||||
connectAnnotation(d));
|
||||
|
||||
} else if (wasMidpoint) {
|
||||
context.replace(
|
||||
iD.actions.Noop(),
|
||||
'moved a node');
|
||||
});
|
||||
t('operations.add.annotation.vertex'));
|
||||
|
||||
} else {
|
||||
context.replace(
|
||||
iD.actions.Noop(),
|
||||
moveAnnotation(entity));
|
||||
}
|
||||
}
|
||||
|
||||
function off() {
|
||||
context.history()
|
||||
.on('undone.drag_node', null);
|
||||
|
||||
context.surface()
|
||||
.classed('behavior-drag-node', false)
|
||||
.selectAll('.active')
|
||||
.classed('active', false);
|
||||
|
||||
stopNudge();
|
||||
}
|
||||
|
||||
function cancel() {
|
||||
off();
|
||||
behavior.cancel();
|
||||
}
|
||||
|
||||
var behavior = iD.behavior.drag()
|
||||
.delegate("g.node, g.point, g.midpoint")
|
||||
.surface(context.surface().node())
|
||||
.origin(origin)
|
||||
.on('start', start)
|
||||
.on('move', move)
|
||||
.on('end', end);
|
||||
|
||||
return behavior;
|
||||
};
|
||||
|
||||
@@ -1,43 +1,75 @@
|
||||
iD.behavior.Draw = function () {
|
||||
var event = d3.dispatch('move', 'add', 'undo', 'cancel', 'finish'),
|
||||
iD.behavior.Draw = function(context) {
|
||||
var event = d3.dispatch('move', 'click', 'clickWay',
|
||||
'clickNode', 'undo', 'cancel', 'finish'),
|
||||
keybinding = d3.keybinding('draw'),
|
||||
down, surface, hover;
|
||||
hover = iD.behavior.Hover(),
|
||||
closeTolerance = 4,
|
||||
tolerance = 12;
|
||||
|
||||
function datum() {
|
||||
if (d3.event.altKey) {
|
||||
return {};
|
||||
} else {
|
||||
return d3.event.target.__data__ || {};
|
||||
}
|
||||
if (d3.event.altKey) return {};
|
||||
else return d3.event.target.__data__ || {};
|
||||
}
|
||||
|
||||
function mousedown() {
|
||||
down = true;
|
||||
}
|
||||
|
||||
function mouseup() {
|
||||
down = false;
|
||||
function point() {
|
||||
var p = target.node().parentNode;
|
||||
return touchId !== null ? d3.touches(p).filter(function(p) {
|
||||
return p.identifier === touchId;
|
||||
})[0] : d3.mouse(p);
|
||||
}
|
||||
|
||||
var target = d3.select(this),
|
||||
touchId = d3.event.touches ? d3.event.changedTouches[0].identifier : null,
|
||||
time = +new Date(),
|
||||
pos = point();
|
||||
|
||||
target.on('mousemove.draw', null);
|
||||
|
||||
d3.select(window).on('mouseup.draw', function() {
|
||||
target.on('mousemove.draw', mousemove);
|
||||
if (iD.geo.dist(pos, point()) < closeTolerance ||
|
||||
(iD.geo.dist(pos, point()) < tolerance &&
|
||||
(+new Date() - time) < 500)) {
|
||||
click();
|
||||
}
|
||||
if (target.node() === d3.event.target) {
|
||||
d3.select(window).on('click.draw', function() {
|
||||
d3.select(window).on('click.draw', null);
|
||||
d3.event.stopPropagation();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function mousemove() {
|
||||
if (!down) {
|
||||
event.move(datum());
|
||||
}
|
||||
event.move(datum());
|
||||
}
|
||||
|
||||
function click() {
|
||||
event.add(datum());
|
||||
var d = datum();
|
||||
if (d.type === 'way') {
|
||||
var choice = iD.geo.chooseIndex(d, d3.mouse(context.surface().node()), context);
|
||||
event.clickWay(d, choice.loc, choice.index);
|
||||
|
||||
} else if (d.type === 'node') {
|
||||
event.clickNode(d);
|
||||
|
||||
} else {
|
||||
event.click(context.map().mouseCoordinates());
|
||||
}
|
||||
}
|
||||
|
||||
function keydown() {
|
||||
if (d3.event.keyCode === d3.keybinding.modifierCodes.alt) {
|
||||
surface.call(hover.off);
|
||||
context.uninstall(hover);
|
||||
}
|
||||
}
|
||||
|
||||
function keyup() {
|
||||
if (d3.event.keyCode === d3.keybinding.modifierCodes.alt) {
|
||||
surface.call(hover);
|
||||
context.install(hover);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,8 +89,7 @@ iD.behavior.Draw = function () {
|
||||
}
|
||||
|
||||
function draw(selection) {
|
||||
surface = selection;
|
||||
hover = iD.behavior.Hover();
|
||||
context.install(hover);
|
||||
|
||||
keybinding
|
||||
.on('⌫', backspace)
|
||||
@@ -68,10 +99,7 @@ iD.behavior.Draw = function () {
|
||||
|
||||
selection
|
||||
.on('mousedown.draw', mousedown)
|
||||
.on('mouseup.draw', mouseup)
|
||||
.on('mousemove.draw', mousemove)
|
||||
.on('click.draw', click)
|
||||
.call(hover);
|
||||
.on('mousemove.draw', mousemove);
|
||||
|
||||
d3.select(document)
|
||||
.call(keybinding)
|
||||
@@ -82,12 +110,13 @@ iD.behavior.Draw = function () {
|
||||
}
|
||||
|
||||
draw.off = function(selection) {
|
||||
context.uninstall(hover);
|
||||
|
||||
selection
|
||||
.on('mousedown.draw', null)
|
||||
.on('mouseup.draw', null)
|
||||
.on('mousemove.draw', null)
|
||||
.on('click.draw', null)
|
||||
.call(hover.off);
|
||||
.on('mousemove.draw', null);
|
||||
|
||||
d3.select(window).on('mouseup.draw', null);
|
||||
|
||||
d3.select(document)
|
||||
.call(keybinding.off)
|
||||
|
||||
@@ -1,160 +1,181 @@
|
||||
iD.behavior.DrawWay = function(wayId, headId, tailId, index, mode, baseGraph) {
|
||||
var map = mode.map,
|
||||
history = mode.history,
|
||||
controller = mode.controller,
|
||||
event = d3.dispatch('add', 'addHead', 'addTail', 'addNode', 'addWay'),
|
||||
way = mode.history.graph().entity(wayId),
|
||||
iD.behavior.DrawWay = function(context, wayId, index, mode, baseGraph) {
|
||||
var way = context.entity(wayId),
|
||||
isArea = way.geometry() === 'area',
|
||||
finished = false,
|
||||
draw;
|
||||
annotation = t((way.isDegenerate() ?
|
||||
'operations.start.annotation.' :
|
||||
'operations.continue.annotation.') + context.geometry(wayId)),
|
||||
draw = iD.behavior.Draw(context);
|
||||
|
||||
var node = iD.Node({loc: map.mouseCoordinates()}),
|
||||
nodeId = node.id;
|
||||
var startIndex = typeof index === 'undefined' ? way.nodes.length - 1 : 0,
|
||||
start = iD.Node({loc: context.graph().entity(way.nodes[startIndex]).loc}),
|
||||
end = iD.Node({loc: context.map().mouseCoordinates()}),
|
||||
segment = iD.Way({
|
||||
nodes: [start.id, end.id],
|
||||
tags: _.clone(way.tags)
|
||||
});
|
||||
|
||||
history[way.isDegenerate() ? 'replace' : 'perform'](
|
||||
iD.actions.AddNode(node),
|
||||
iD.actions.AddWayNode(wayId, node.id, index));
|
||||
|
||||
function move(datum) {
|
||||
var loc = map.mouseCoordinates();
|
||||
|
||||
if (datum.type === 'node' || datum.midpoint) {
|
||||
loc = datum.loc;
|
||||
} else if (datum.type === 'way') {
|
||||
loc = iD.geo.chooseIndex(datum, d3.mouse(map.surface.node()), map).loc;
|
||||
}
|
||||
|
||||
history.replace(iD.actions.MoveNode(nodeId, loc));
|
||||
var f = context[way.isDegenerate() ? 'replace' : 'perform'];
|
||||
if (isArea) {
|
||||
f(iD.actions.AddEntity(end),
|
||||
iD.actions.AddVertex(wayId, end.id, index));
|
||||
} else {
|
||||
f(iD.actions.AddEntity(start),
|
||||
iD.actions.AddEntity(end),
|
||||
iD.actions.AddEntity(segment));
|
||||
}
|
||||
|
||||
function add(datum) {
|
||||
if (datum.id === headId) {
|
||||
event.addHead(datum);
|
||||
} else if (datum.id === tailId) {
|
||||
event.addTail(datum);
|
||||
} else if (datum.type === 'node' && datum.id !== nodeId) {
|
||||
event.addNode(datum);
|
||||
function move(datum) {
|
||||
var loc = context.map().mouseCoordinates();
|
||||
|
||||
if (datum.id === end.id || datum.id === segment.id) {
|
||||
context.surface().selectAll('.way, .node')
|
||||
.filter(function(d) {
|
||||
return d.id === end.id || d.id === segment.id;
|
||||
})
|
||||
.classed('active', true);
|
||||
} else if (datum.type === 'node') {
|
||||
loc = datum.loc;
|
||||
} else if (datum.type === 'way') {
|
||||
var choice = iD.geo.chooseIndex(datum, d3.mouse(map.surface.node()), map);
|
||||
event.addWay(datum, choice.loc, choice.index);
|
||||
} else if (datum.midpoint) {
|
||||
var way = history.graph().entity(datum.way);
|
||||
event.addWay(way, datum.loc, datum.index);
|
||||
} else {
|
||||
event.add(map.mouseCoordinates());
|
||||
loc = iD.geo.chooseIndex(datum, d3.mouse(context.surface().node()), context).loc;
|
||||
}
|
||||
|
||||
context.replace(iD.actions.MoveNode(end.id, loc));
|
||||
}
|
||||
|
||||
function undone() {
|
||||
controller.enter(iD.modes.Browse());
|
||||
context.enter(iD.modes.Browse(context));
|
||||
}
|
||||
|
||||
function lineActives(d) {
|
||||
return d.id === segment.id || d.id === start.id || d.id === end.id;
|
||||
}
|
||||
|
||||
function areaActives(d) {
|
||||
return d.id === wayId || d.id === end.id;
|
||||
}
|
||||
|
||||
var drawWay = function(surface) {
|
||||
map.fastEnable(false)
|
||||
draw.on('move', move)
|
||||
.on('click', drawWay.add)
|
||||
.on('clickWay', drawWay.addWay)
|
||||
.on('clickNode', drawWay.addNode)
|
||||
.on('undo', context.undo)
|
||||
.on('cancel', drawWay.cancel)
|
||||
.on('finish', drawWay.finish);
|
||||
|
||||
context.map()
|
||||
.fastEnable(false)
|
||||
.minzoom(16)
|
||||
.dblclickEnable(false);
|
||||
|
||||
surface.call(draw)
|
||||
.selectAll('.way, .node')
|
||||
.filter(function (d) { return d.id === wayId || d.id === nodeId; })
|
||||
.filter(isArea ? areaActives : lineActives)
|
||||
.classed('active', true);
|
||||
|
||||
history.on('undone.draw', undone);
|
||||
context.history()
|
||||
.on('undone.draw', undone);
|
||||
};
|
||||
|
||||
drawWay.off = function(surface) {
|
||||
if (!finished)
|
||||
history.pop();
|
||||
context.pop();
|
||||
|
||||
map.fastEnable(true)
|
||||
context.map()
|
||||
.fastEnable(true)
|
||||
.minzoom(0)
|
||||
.tail(false);
|
||||
|
||||
window.setTimeout(function() {
|
||||
map.dblclickEnable(true);
|
||||
context.map().dblclickEnable(true);
|
||||
}, 1000);
|
||||
|
||||
surface.call(draw.off)
|
||||
.selectAll('.way, .node')
|
||||
.classed('active', false);
|
||||
|
||||
history.on('undone.draw', null);
|
||||
context.history()
|
||||
.on('undone.draw', null);
|
||||
};
|
||||
|
||||
function ReplaceTemporaryNode(newNode) {
|
||||
return function(graph) {
|
||||
return graph
|
||||
.replace(way.removeNode(nodeId).addNode(newNode.id, index))
|
||||
.remove(node);
|
||||
}
|
||||
if (isArea) {
|
||||
return graph
|
||||
.replace(way.removeNode(end.id).addNode(newNode.id, index))
|
||||
.remove(end);
|
||||
|
||||
} else {
|
||||
return graph
|
||||
.replace(graph.entity(wayId).addNode(newNode.id, index))
|
||||
.remove(end)
|
||||
.remove(segment)
|
||||
.remove(start);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Accept the current position of the temporary node and continue drawing.
|
||||
drawWay.add = function(loc) {
|
||||
var newNode = iD.Node({loc: loc});
|
||||
|
||||
context.replace(
|
||||
iD.actions.AddEntity(newNode),
|
||||
ReplaceTemporaryNode(newNode),
|
||||
annotation);
|
||||
|
||||
finished = true;
|
||||
context.enter(mode);
|
||||
};
|
||||
|
||||
// Connect the way to an existing way.
|
||||
drawWay.addWay = function(way, loc, wayIndex) {
|
||||
var newNode = iD.Node({loc: loc});
|
||||
|
||||
context.perform(
|
||||
iD.actions.AddEntity(newNode),
|
||||
iD.actions.AddVertex(way.id, newNode.id, wayIndex),
|
||||
ReplaceTemporaryNode(newNode),
|
||||
annotation);
|
||||
|
||||
finished = true;
|
||||
context.enter(mode);
|
||||
};
|
||||
|
||||
// Connect the way to an existing node and continue drawing.
|
||||
drawWay.addNode = function(node, annotation) {
|
||||
history.perform(
|
||||
drawWay.addNode = function(node) {
|
||||
context.perform(
|
||||
ReplaceTemporaryNode(node),
|
||||
annotation);
|
||||
|
||||
finished = true;
|
||||
controller.enter(mode);
|
||||
};
|
||||
|
||||
// Connect the way to an existing way.
|
||||
drawWay.addWay = function(way, loc, wayIndex, annotation) {
|
||||
var newNode = iD.Node({loc: loc});
|
||||
|
||||
history.perform(
|
||||
iD.actions.AddNode(newNode),
|
||||
iD.actions.AddWayNode(way.id, newNode.id, wayIndex),
|
||||
ReplaceTemporaryNode(newNode),
|
||||
annotation);
|
||||
|
||||
finished = true;
|
||||
controller.enter(mode);
|
||||
};
|
||||
|
||||
// Accept the current position of the temporary node and continue drawing.
|
||||
drawWay.add = function(loc, annotation) {
|
||||
var newNode = iD.Node({loc: loc});
|
||||
|
||||
history.replace(
|
||||
iD.actions.AddNode(newNode),
|
||||
ReplaceTemporaryNode(newNode),
|
||||
annotation);
|
||||
|
||||
finished = true;
|
||||
controller.enter(mode);
|
||||
context.enter(mode);
|
||||
};
|
||||
|
||||
// Finish the draw operation, removing the temporary node. If the way has enough
|
||||
// nodes to be valid, it's selected. Otherwise, return to browse mode.
|
||||
drawWay.finish = function() {
|
||||
history.pop();
|
||||
context.pop();
|
||||
finished = true;
|
||||
|
||||
var way = history.graph().entity(wayId);
|
||||
var way = context.entity(wayId);
|
||||
if (way) {
|
||||
controller.enter(iD.modes.Select(way, true));
|
||||
context.enter(iD.modes.Select(context, [way.id], true));
|
||||
} else {
|
||||
controller.enter(iD.modes.Browse());
|
||||
context.enter(iD.modes.Browse(context));
|
||||
}
|
||||
};
|
||||
|
||||
// Cancel the draw operation and return to browse, deleting everything drawn.
|
||||
drawWay.cancel = function() {
|
||||
history.perform(
|
||||
context.perform(
|
||||
d3.functor(baseGraph),
|
||||
'cancelled drawing');
|
||||
t('operations.cancel_draw.annotation'));
|
||||
|
||||
finished = true;
|
||||
controller.enter(iD.modes.Browse());
|
||||
context.enter(iD.modes.Browse(context));
|
||||
};
|
||||
|
||||
draw = iD.behavior.Draw()
|
||||
.on('move', move)
|
||||
.on('add', add)
|
||||
.on('undo', history.undo)
|
||||
.on('cancel', drawWay.cancel)
|
||||
.on('finish', drawWay.finish);
|
||||
|
||||
return d3.rebind(drawWay, event, 'on');
|
||||
return drawWay;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
iD.behavior.Hash = function(context) {
|
||||
var s0 = null, // cached location.hash
|
||||
lat = 90 - 1e-8; // allowable latitude range
|
||||
|
||||
var parser = function(map, s) {
|
||||
var q = iD.util.stringQs(s);
|
||||
var args = (q.map || '').split("/").map(Number);
|
||||
if (args.length < 3 || args.some(isNaN)) {
|
||||
return true; // replace bogus hash
|
||||
} else if (s !== formatter(map).slice(1)) {
|
||||
map.centerZoom([args[2],
|
||||
Math.min(lat, Math.max(-lat, args[1]))],
|
||||
args[0]);
|
||||
}
|
||||
};
|
||||
|
||||
var formatter = function(map) {
|
||||
var center = map.center(),
|
||||
zoom = map.zoom(),
|
||||
precision = Math.max(0, Math.ceil(Math.log(zoom) / Math.LN2));
|
||||
var q = iD.util.stringQs(location.hash.substring(1));
|
||||
return '#' + iD.util.qsString(_.assign(q, {
|
||||
map: zoom.toFixed(2) +
|
||||
'/' + center[1].toFixed(precision) +
|
||||
'/' + center[0].toFixed(precision)
|
||||
}), true);
|
||||
};
|
||||
|
||||
var move = _.throttle(function() {
|
||||
var s1 = formatter(context.map());
|
||||
if (s0 !== s1) location.replace(s0 = s1); // don't recenter the map!
|
||||
}, 500);
|
||||
|
||||
function hashchange() {
|
||||
if (location.hash === s0) return; // ignore spurious hashchange events
|
||||
if (parser(context.map(), (s0 = location.hash).substring(1))) {
|
||||
move(); // replace bogus hash
|
||||
}
|
||||
}
|
||||
|
||||
// the hash can declare that the map should select a feature, but it can
|
||||
// do so before any features are loaded. thus wait for the feature to
|
||||
// be loaded and then select
|
||||
function willselect(id) {
|
||||
context.map().on('drawn.hash', function() {
|
||||
if (!context.entity(id)) return;
|
||||
selectoff();
|
||||
context.enter(iD.modes.Select(context, [id]));
|
||||
});
|
||||
|
||||
context.on('enter.hash', function() {
|
||||
if (context.mode().id !== 'browse') selectoff();
|
||||
});
|
||||
}
|
||||
|
||||
function selectoff() {
|
||||
context.map().on('drawn.hash', null);
|
||||
}
|
||||
|
||||
function hash() {
|
||||
context.map()
|
||||
.on('move.hash', move);
|
||||
|
||||
d3.select(window)
|
||||
.on('hashchange.hash', hashchange);
|
||||
|
||||
if (location.hash) {
|
||||
var q = iD.util.stringQs(location.hash.substring(1));
|
||||
if (q.id) willselect(q.id);
|
||||
hashchange();
|
||||
if (q.map) hash.hadHash = true;
|
||||
}
|
||||
}
|
||||
|
||||
hash.off = function() {
|
||||
context.map()
|
||||
.on('move.hash', null);
|
||||
|
||||
d3.select(window)
|
||||
.on('hashchange.hash', null);
|
||||
|
||||
location.hash = "";
|
||||
};
|
||||
|
||||
return hash;
|
||||
};
|
||||
@@ -7,20 +7,22 @@
|
||||
Only one of these elements can have the :hover pseudo-class, but all of them will
|
||||
have the .hover class.
|
||||
*/
|
||||
iD.behavior.Hover = function () {
|
||||
iD.behavior.Hover = function() {
|
||||
var hover = function(selection) {
|
||||
selection.classed('behavior-hover', true);
|
||||
|
||||
selection.on('mouseover.hover', function () {
|
||||
function mouseover() {
|
||||
var datum = d3.event.target.__data__;
|
||||
if (datum) {
|
||||
selection.selectAll('*')
|
||||
.filter(function (d) { return d === datum; })
|
||||
.filter(function(d) { return d === datum; })
|
||||
.classed('hover', true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
selection.on('mouseout.hover', function () {
|
||||
selection.on('mouseover.hover', mouseover);
|
||||
|
||||
selection.on('mouseout.hover', function() {
|
||||
selection.selectAll('.hover')
|
||||
.classed('hover', false);
|
||||
});
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
iD.behavior.Lasso = function(context) {
|
||||
|
||||
var behavior = function(selection) {
|
||||
|
||||
var timeout = null,
|
||||
// the position of the first mousedown
|
||||
pos = null,
|
||||
lasso;
|
||||
|
||||
function mousedown() {
|
||||
if (d3.event.shiftKey === true) {
|
||||
|
||||
pos = [d3.event.clientX, d3.event.clientY];
|
||||
|
||||
lasso = iD.ui.Lasso().a(d3.mouse(context.surface().node()));
|
||||
|
||||
context.surface().call(lasso);
|
||||
|
||||
selection
|
||||
.on('mousemove.lasso', mousemove)
|
||||
.on('mouseup.lasso', mouseup);
|
||||
|
||||
d3.event.stopPropagation();
|
||||
d3.event.preventDefault();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function mousemove() {
|
||||
lasso.b(d3.mouse(context.surface().node()));
|
||||
}
|
||||
|
||||
function normalize(a, b) {
|
||||
return [
|
||||
[Math.min(a[0], b[0]), Math.min(a[1], b[1])],
|
||||
[Math.max(a[0], b[0]), Math.max(a[1], b[1])]];
|
||||
}
|
||||
|
||||
function mouseup() {
|
||||
|
||||
var extent = iD.geo.Extent(
|
||||
normalize(context.projection.invert(lasso.a()),
|
||||
context.projection.invert(lasso.b())));
|
||||
|
||||
lasso.close();
|
||||
|
||||
selection
|
||||
.on('mousemove.lasso', null)
|
||||
.on('mouseup.lasso', null);
|
||||
|
||||
if (d3.event.clientX !== pos[0] || d3.event.clientY !== pos[1]) {
|
||||
var selected = context.graph().intersects(extent).filter(function (entity) {
|
||||
return entity.type === 'node';
|
||||
});
|
||||
|
||||
if (selected.length) {
|
||||
context.enter(iD.modes.Select(context, _.pluck(selected, 'id')));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
selection
|
||||
.on('mousedown.lasso', mousedown);
|
||||
};
|
||||
|
||||
behavior.off = function(selection) {
|
||||
selection.on('mousedown.lasso', null);
|
||||
};
|
||||
|
||||
return behavior;
|
||||
};
|
||||
@@ -0,0 +1,35 @@
|
||||
iD.behavior.Select = function(context) {
|
||||
var behavior = function(selection) {
|
||||
function click() {
|
||||
var datum = d3.event.target.__data__;
|
||||
if (!(datum instanceof iD.Entity)) {
|
||||
if (!d3.event.shiftKey)
|
||||
context.enter(iD.modes.Browse(context));
|
||||
|
||||
} else if (!d3.event.shiftKey) {
|
||||
// Avoid re-entering Select mode with same entity.
|
||||
if (context.selection().length !== 1 || context.selection()[0] !== datum.id) {
|
||||
context.enter(iD.modes.Select(context, [datum.id]));
|
||||
} else {
|
||||
context.mode().reselect();
|
||||
}
|
||||
} else if (context.selection().indexOf(datum.id) >= 0) {
|
||||
var selection = _.without(context.selection(), datum.id);
|
||||
context.enter(selection.length ?
|
||||
iD.modes.Select(context, selection) :
|
||||
iD.modes.Browse(context));
|
||||
|
||||
} else {
|
||||
context.enter(iD.modes.Select(context, context.selection().concat([datum.id])));
|
||||
}
|
||||
}
|
||||
|
||||
selection.on('click.select', click);
|
||||
};
|
||||
|
||||
behavior.off = function(selection) {
|
||||
selection.on('click.select', null);
|
||||
};
|
||||
|
||||
return behavior;
|
||||
};
|
||||
@@ -1,14 +1,19 @@
|
||||
iD.Connection = function() {
|
||||
iD.Connection = function(context) {
|
||||
|
||||
var event = d3.dispatch('auth', 'load'),
|
||||
url = 'http://www.openstreetmap.org',
|
||||
connection = {},
|
||||
user = {},
|
||||
version,
|
||||
keys,
|
||||
inflight = {},
|
||||
loadedTiles = {},
|
||||
oauth = iD.OAuth().url(url);
|
||||
oauth = iD.OAuth(context).url(url),
|
||||
ndStr = 'nd',
|
||||
tagStr = 'tag',
|
||||
memberStr = 'member',
|
||||
nodeStr = 'node',
|
||||
wayStr = 'way',
|
||||
relationStr = 'relation';
|
||||
|
||||
function changesetUrl(changesetId) {
|
||||
return url + '/browse/changeset/' + changesetId;
|
||||
@@ -35,96 +40,103 @@ iD.Connection = function() {
|
||||
}
|
||||
|
||||
function getNodes(obj) {
|
||||
var nelems = obj.getElementsByTagName('nd'), nodes = new Array(nelems.length);
|
||||
for (var i = 0, l = nelems.length; i < l; i++) {
|
||||
nodes[i] = 'n' + nelems[i].attributes.ref.nodeValue;
|
||||
var elems = obj.getElementsByTagName(ndStr),
|
||||
nodes = new Array(elems.length);
|
||||
for (var i = 0, l = elems.length; i < l; i++) {
|
||||
nodes[i] = 'n' + elems[i].attributes.ref.nodeValue;
|
||||
}
|
||||
return nodes;
|
||||
}
|
||||
|
||||
function getTags(obj) {
|
||||
var tags = {}, tagelems = obj.getElementsByTagName('tag');
|
||||
for (var i = 0, l = tagelems.length; i < l; i++) {
|
||||
var item = tagelems[i];
|
||||
tags[item.attributes.k.nodeValue] = item.attributes.v.nodeValue;
|
||||
var elems = obj.getElementsByTagName(tagStr),
|
||||
tags = {};
|
||||
for (var i = 0, l = elems.length; i < l; i++) {
|
||||
var attrs = elems[i].attributes;
|
||||
tags[attrs.k.nodeValue] = attrs.v.nodeValue;
|
||||
}
|
||||
return tags;
|
||||
}
|
||||
|
||||
function getMembers(obj) {
|
||||
var elems = obj.getElementsByTagName('member'),
|
||||
var elems = obj.getElementsByTagName(memberStr),
|
||||
members = new Array(elems.length);
|
||||
|
||||
for (var i = 0, l = elems.length; i < l; i++) {
|
||||
var attrs = elems[i].attributes;
|
||||
members[i] = {
|
||||
id: elems[i].attributes.type.nodeValue[0] + elems[i].attributes.ref.nodeValue,
|
||||
type: elems[i].attributes.type.nodeValue,
|
||||
role: elems[i].attributes.role.nodeValue
|
||||
id: attrs.type.nodeValue[0] + attrs.ref.nodeValue,
|
||||
type: attrs.type.nodeValue,
|
||||
role: attrs.role.nodeValue
|
||||
};
|
||||
}
|
||||
return members;
|
||||
}
|
||||
|
||||
function nodeData(obj) {
|
||||
var o = { type: 'node', tags: getTags(obj) };
|
||||
for (var i = 0, l = obj.attributes.length; i < l; i++) {
|
||||
o[obj.attributes[i].nodeName] = obj.attributes[i].nodeValue;
|
||||
}
|
||||
if (o.lon && o.lat) {
|
||||
o.loc = [parseFloat(o.lon), parseFloat(o.lat)];
|
||||
delete o.lon; delete o.lat;
|
||||
}
|
||||
o.id = iD.Entity.id.fromOSM('node', o.id);
|
||||
return new iD.Node(o);
|
||||
}
|
||||
var parsers = {
|
||||
node: function nodeData(obj) {
|
||||
var attrs = obj.attributes;
|
||||
return new iD.Node({
|
||||
id: iD.Entity.id.fromOSM(nodeStr, attrs.id.nodeValue),
|
||||
loc: [parseFloat(attrs.lon.nodeValue), parseFloat(attrs.lat.nodeValue)],
|
||||
version: attrs.version.nodeValue,
|
||||
changeset: attrs.changeset.nodeValue,
|
||||
user: attrs.user.nodeValue,
|
||||
uid: attrs.uid.nodeValue,
|
||||
visible: attrs.visible.nodeValue,
|
||||
timestamp: attrs.timestamp.nodeValue,
|
||||
tags: getTags(obj)
|
||||
});
|
||||
},
|
||||
|
||||
function wayData(obj) {
|
||||
var o = { type: 'way', nodes: getNodes(obj),
|
||||
tags: getTags(obj)
|
||||
};
|
||||
for (var i = 0, l = obj.attributes.length; i < l; i++) {
|
||||
o[obj.attributes[i].nodeName] = obj.attributes[i].nodeValue;
|
||||
}
|
||||
o.id = iD.Entity.id.fromOSM('way', o.id);
|
||||
return new iD.Way(o);
|
||||
}
|
||||
way: function wayData(obj) {
|
||||
var attrs = obj.attributes;
|
||||
return new iD.Way({
|
||||
id: iD.Entity.id.fromOSM(wayStr, attrs.id.nodeValue),
|
||||
version: attrs.version.nodeValue,
|
||||
changeset: attrs.changeset.nodeValue,
|
||||
user: attrs.user.nodeValue,
|
||||
uid: attrs.uid.nodeValue,
|
||||
visible: attrs.visible.nodeValue,
|
||||
timestamp: attrs.timestamp.nodeValue,
|
||||
tags: getTags(obj),
|
||||
nodes: getNodes(obj)
|
||||
});
|
||||
},
|
||||
|
||||
function relationData(obj) {
|
||||
var o = {
|
||||
type: 'relation', members: getMembers(obj),
|
||||
tags: getTags(obj)
|
||||
};
|
||||
for (var i = 0, l = obj.attributes.length; i < l; i++) {
|
||||
o[obj.attributes[i].nodeName] = obj.attributes[i].nodeValue;
|
||||
relation: function relationData(obj) {
|
||||
var attrs = obj.attributes;
|
||||
return new iD.Relation({
|
||||
id: iD.Entity.id.fromOSM(relationStr, attrs.id.nodeValue),
|
||||
version: attrs.version.nodeValue,
|
||||
changeset: attrs.changeset.nodeValue,
|
||||
user: attrs.user.nodeValue,
|
||||
uid: attrs.uid.nodeValue,
|
||||
visible: attrs.visible.nodeValue,
|
||||
timestamp: attrs.timestamp.nodeValue,
|
||||
tags: getTags(obj),
|
||||
members: getMembers(obj)
|
||||
});
|
||||
}
|
||||
o.id = iD.Entity.id.fromOSM('relation', o.id);
|
||||
return new iD.Relation(o);
|
||||
}
|
||||
};
|
||||
|
||||
function parse(dom) {
|
||||
if (!dom || !dom.childNodes) return new Error('Bad request');
|
||||
var root = dom.childNodes[0];
|
||||
var entities = {};
|
||||
|
||||
var root = dom.childNodes[0],
|
||||
children = root.childNodes,
|
||||
entities = {};
|
||||
|
||||
var i, o, l;
|
||||
for (i = 0, l = root.childNodes.length; i < l; i++) {
|
||||
switch(root.childNodes[i].nodeName) {
|
||||
case 'node':
|
||||
o = nodeData(root.childNodes[i]);
|
||||
entities[o.id] = o;
|
||||
break;
|
||||
case 'way':
|
||||
o = wayData(root.childNodes[i]);
|
||||
entities[o.id] = o;
|
||||
break;
|
||||
case 'relation':
|
||||
o = relationData(root.childNodes[i]);
|
||||
entities[o.id] = o;
|
||||
break;
|
||||
for (i = 0, l = children.length; i < l; i++) {
|
||||
var child = children[i],
|
||||
parser = parsers[child.nodeName];
|
||||
if (parser) {
|
||||
o = parser(child);
|
||||
entities[o.id] = o;
|
||||
}
|
||||
}
|
||||
|
||||
return iD.Graph(entities);
|
||||
return entities;
|
||||
}
|
||||
|
||||
function authenticated() {
|
||||
@@ -186,21 +198,21 @@ iD.Connection = function() {
|
||||
content: JXON.stringify(connection.changesetJXON({
|
||||
imagery_used: imagery_used.join(';'),
|
||||
comment: comment,
|
||||
created_by: 'iD ' + (version || '')
|
||||
created_by: 'iD ' + iD.version
|
||||
}))
|
||||
}, function (err, changeset_id) {
|
||||
}, function(err, changeset_id) {
|
||||
if (err) return callback(err);
|
||||
oauth.xhr({
|
||||
method: 'POST',
|
||||
path: '/api/0.6/changeset/' + changeset_id + '/upload',
|
||||
options: { header: { 'Content-Type': 'text/xml' } },
|
||||
content: JXON.stringify(connection.osmChangeJXON(user.id, changeset_id, changes))
|
||||
}, function (err) {
|
||||
}, function(err) {
|
||||
if (err) return callback(err);
|
||||
oauth.xhr({
|
||||
method: 'PUT',
|
||||
path: '/api/0.6/changeset/' + changeset_id + '/close'
|
||||
}, function (err) {
|
||||
}, function(err) {
|
||||
callback(err, changeset_id);
|
||||
});
|
||||
});
|
||||
@@ -209,13 +221,14 @@ iD.Connection = function() {
|
||||
|
||||
function userDetails(callback) {
|
||||
function done(err, user_details) {
|
||||
if (err) return callback(err);
|
||||
var u = user_details.getElementsByTagName('user')[0],
|
||||
img = u.getElementsByTagName('img'),
|
||||
image_url = '';
|
||||
if (img && img[0].getAttribute('href')) {
|
||||
image_url = img[0].getAttribute('href');
|
||||
}
|
||||
callback(connection.user({
|
||||
callback(undefined, connection.user({
|
||||
display_name: u.attributes.display_name.nodeValue,
|
||||
image_url: image_url,
|
||||
id: u.attributes.id.nodeValue
|
||||
@@ -322,12 +335,6 @@ iD.Connection = function() {
|
||||
return oauth.authenticate(done);
|
||||
};
|
||||
|
||||
connection.version = function(_) {
|
||||
if (!arguments.length) return version;
|
||||
version = _;
|
||||
return connection;
|
||||
};
|
||||
|
||||
connection.bboxFromAPI = bboxFromAPI;
|
||||
connection.changesetUrl = changesetUrl;
|
||||
connection.loadFromURL = loadFromURL;
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
// A controller holds a single action at a time and calls `.enter` and `.exit`
|
||||
// to bind and unbind actions.
|
||||
iD.Controller = function(map, history) {
|
||||
var event = d3.dispatch('enter', 'exit');
|
||||
var controller = { mode: null };
|
||||
|
||||
controller.enter = function(mode) {
|
||||
mode.controller = controller;
|
||||
mode.history = history;
|
||||
mode.map = map;
|
||||
|
||||
if (controller.mode) {
|
||||
controller.mode.exit();
|
||||
event.exit(controller.mode);
|
||||
}
|
||||
|
||||
mode.enter();
|
||||
controller.mode = mode;
|
||||
event.enter(mode);
|
||||
};
|
||||
|
||||
controller.exit = function() {
|
||||
controller.enter(iD.modes.Browse());
|
||||
};
|
||||
|
||||
return d3.rebind(controller, event, 'on');
|
||||
};
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
iD.Difference represents the difference between two graphs.
|
||||
It knows how to calculate the set of entities that were
|
||||
created, modified, or deleted, and also contains the logic
|
||||
for recursively extending a difference to the complete set
|
||||
of entities that will require a redraw, taking into account
|
||||
child and parent relationships.
|
||||
*/
|
||||
iD.Difference = function(base, head) {
|
||||
var changes = {}, length = 0;
|
||||
|
||||
_.each(head.entities, function(h, id) {
|
||||
var b = base.entities[id];
|
||||
if (h !== b) {
|
||||
changes[id] = {base: b, head: h};
|
||||
length++;
|
||||
}
|
||||
});
|
||||
|
||||
_.each(base.entities, function(b, id) {
|
||||
var h = head.entities[id];
|
||||
if (!changes[id] && h !== b) {
|
||||
changes[id] = {base: b, head: h};
|
||||
length++;
|
||||
}
|
||||
});
|
||||
|
||||
var difference = {};
|
||||
|
||||
difference.length = function() {
|
||||
return length;
|
||||
};
|
||||
|
||||
difference.changes = function() {
|
||||
return changes;
|
||||
};
|
||||
|
||||
difference.extantIDs = function() {
|
||||
var result = [];
|
||||
_.each(changes, function(change, id) {
|
||||
if (change.head) result.push(id);
|
||||
});
|
||||
return result;
|
||||
};
|
||||
|
||||
difference.modified = function() {
|
||||
var result = [];
|
||||
_.each(changes, function(change) {
|
||||
if (change.base && change.head) result.push(change.head);
|
||||
});
|
||||
return result;
|
||||
};
|
||||
|
||||
difference.created = function() {
|
||||
var result = [];
|
||||
_.each(changes, function(change) {
|
||||
if (!change.base && change.head) result.push(change.head);
|
||||
});
|
||||
return result;
|
||||
};
|
||||
|
||||
difference.deleted = function() {
|
||||
var result = [];
|
||||
_.each(changes, function(change) {
|
||||
if (change.base && !change.head) result.push(change.base);
|
||||
});
|
||||
return result;
|
||||
};
|
||||
|
||||
difference.complete = function(extent) {
|
||||
var result = {}, id, change;
|
||||
|
||||
function addParents(parents) {
|
||||
for (var i = 0; i < parents.length; i++) {
|
||||
var parent = parents[i];
|
||||
|
||||
if (parent.id in result)
|
||||
continue;
|
||||
|
||||
result[parent.id] = parent;
|
||||
addParents(head.parentRelations(parent));
|
||||
}
|
||||
}
|
||||
|
||||
for (id in changes) {
|
||||
change = changes[id];
|
||||
|
||||
var h = change.head,
|
||||
b = change.base,
|
||||
entity = h || b;
|
||||
|
||||
if (extent &&
|
||||
(!h || !h.intersects(extent, head)) &&
|
||||
(!b || !b.intersects(extent, base)))
|
||||
continue;
|
||||
|
||||
result[id] = h;
|
||||
|
||||
if (entity.type === 'way') {
|
||||
var nh = h ? h.nodes : [],
|
||||
nb = b ? b.nodes : [],
|
||||
diff;
|
||||
|
||||
diff = _.difference(nh, nb);
|
||||
for (var i = 0; i < diff.length; i++) {
|
||||
result[diff[i]] = head.entity(diff[i]);
|
||||
}
|
||||
|
||||
diff = _.difference(nb, nh);
|
||||
for (i = 0; i < diff.length; i++) {
|
||||
result[diff[i]] = head.entity(diff[i]);
|
||||
}
|
||||
}
|
||||
|
||||
addParents(head.parentWays(entity));
|
||||
addParents(head.parentRelations(entity));
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
return difference;
|
||||
};
|
||||
@@ -9,22 +9,22 @@ iD.Entity = function(attrs) {
|
||||
return (new iD.Entity()).initialize(arguments);
|
||||
};
|
||||
|
||||
iD.Entity.id = function (type) {
|
||||
iD.Entity.id = function(type) {
|
||||
return iD.Entity.id.fromOSM(type, iD.Entity.id.next[type]--);
|
||||
};
|
||||
|
||||
iD.Entity.id.next = {node: -1, way: -1, relation: -1};
|
||||
|
||||
iD.Entity.id.fromOSM = function (type, id) {
|
||||
iD.Entity.id.fromOSM = function(type, id) {
|
||||
return type[0] + id;
|
||||
};
|
||||
|
||||
iD.Entity.id.toOSM = function (id) {
|
||||
iD.Entity.id.toOSM = function(id) {
|
||||
return id.slice(1);
|
||||
};
|
||||
|
||||
// A function suitable for use as the second argument to d3.selection#data().
|
||||
iD.Entity.key = function (entity) {
|
||||
iD.Entity.key = function(entity) {
|
||||
return entity.id;
|
||||
};
|
||||
|
||||
@@ -43,7 +43,6 @@ iD.Entity.prototype = {
|
||||
|
||||
if (!this.id && this.type) {
|
||||
this.id = iD.Entity.id(this.type);
|
||||
this._updated = true;
|
||||
}
|
||||
|
||||
if (iD.debug) {
|
||||
@@ -63,15 +62,21 @@ iD.Entity.prototype = {
|
||||
},
|
||||
|
||||
update: function(attrs) {
|
||||
return iD.Entity(this, attrs, {_updated: true});
|
||||
return iD.Entity(this, attrs);
|
||||
},
|
||||
|
||||
created: function() {
|
||||
return this._updated && this.osmId().charAt(0) === '-';
|
||||
},
|
||||
|
||||
modified: function() {
|
||||
return this._updated && this.osmId().charAt(0) !== '-';
|
||||
mergeTags: function(tags) {
|
||||
var merged = _.clone(this.tags);
|
||||
for (var k in tags) {
|
||||
var t1 = merged[k],
|
||||
t2 = tags[k];
|
||||
if (t1 && t1 !== t2) {
|
||||
merged[k] = t1 + "; " + t2;
|
||||
} else {
|
||||
merged[k] = t2;
|
||||
}
|
||||
}
|
||||
return this.update({tags: merged});
|
||||
},
|
||||
|
||||
intersects: function(extent, resolver) {
|
||||
@@ -79,7 +84,7 @@ iD.Entity.prototype = {
|
||||
},
|
||||
|
||||
hasInterestingTags: function() {
|
||||
return _.keys(this.tags).some(function (key) {
|
||||
return _.keys(this.tags).some(function(key) {
|
||||
return key != "attribution" &&
|
||||
key != "created_by" &&
|
||||
key != "source" &&
|
||||
@@ -88,6 +93,23 @@ iD.Entity.prototype = {
|
||||
});
|
||||
},
|
||||
|
||||
deprecatedTags: function() {
|
||||
var tags = _.pairs(this.tags);
|
||||
var deprecated = {};
|
||||
|
||||
iD.data.deprecated.forEach(function(d) {
|
||||
var match = _.pairs(d.old)[0];
|
||||
tags.forEach(function(t) {
|
||||
if (t[0] == match[0] &&
|
||||
(t[1] == match[1] || match[1] == '*')) {
|
||||
deprecated[t[0]] = t[1];
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return deprecated;
|
||||
},
|
||||
|
||||
friendlyName: function() {
|
||||
// Generate a string such as 'river' or 'Fred's House' for an entity.
|
||||
if (!this.tags || !Object.keys(this.tags).length) { return ''; }
|
||||
@@ -0,0 +1,285 @@
|
||||
iD.Graph = function(other, mutable) {
|
||||
if (!(this instanceof iD.Graph)) return new iD.Graph(other, mutable);
|
||||
|
||||
if (other instanceof iD.Graph) {
|
||||
var base = other.base();
|
||||
this.entities = _.assign(Object.create(base.entities), other.entities);
|
||||
this._parentWays = _.assign(Object.create(base.parentWays), other._parentWays);
|
||||
this._parentRels = _.assign(Object.create(base.parentRels), other._parentRels);
|
||||
this.inherited = true;
|
||||
|
||||
} else {
|
||||
if (_.isArray(other)) {
|
||||
var entities = {};
|
||||
for (var i = 0; i < other.length; i++) {
|
||||
entities[other[i].id] = other[i];
|
||||
}
|
||||
other = entities;
|
||||
}
|
||||
this.entities = Object.create({});
|
||||
this._parentWays = Object.create({});
|
||||
this._parentRels = Object.create({});
|
||||
this.rebase(other || {});
|
||||
}
|
||||
|
||||
this.transients = {};
|
||||
this._childNodes = {};
|
||||
this.getEntity = _.bind(this.entity, this);
|
||||
|
||||
if (!mutable) {
|
||||
this.freeze();
|
||||
}
|
||||
};
|
||||
|
||||
iD.Graph.prototype = {
|
||||
entity: function(id) {
|
||||
return this.entities[id];
|
||||
},
|
||||
|
||||
transient: function(entity, key, fn) {
|
||||
var id = entity.id,
|
||||
transients = this.transients[id] ||
|
||||
(this.transients[id] = {});
|
||||
|
||||
if (transients[key] !== undefined) {
|
||||
return transients[key];
|
||||
}
|
||||
|
||||
return transients[key] = fn.call(entity);
|
||||
},
|
||||
|
||||
parentWays: function(entity) {
|
||||
return _.map(this._parentWays[entity.id], this.getEntity);
|
||||
},
|
||||
|
||||
isPoi: function(entity) {
|
||||
var parentWays = this._parentWays[entity.id];
|
||||
return !parentWays || parentWays.length === 0;
|
||||
},
|
||||
|
||||
isShared: function(entity) {
|
||||
var parentWays = this._parentWays[entity.id];
|
||||
return parentWays && parentWays.length > 1;
|
||||
},
|
||||
|
||||
parentRelations: function(entity) {
|
||||
return _.map(this._parentRels[entity.id], this.getEntity);
|
||||
},
|
||||
|
||||
childNodes: function(entity) {
|
||||
if (this._childNodes[entity.id])
|
||||
return this._childNodes[entity.id];
|
||||
|
||||
var nodes = [];
|
||||
for (var i = 0, l = entity.nodes.length; i < l; i++) {
|
||||
nodes[i] = this.entity(entity.nodes[i]);
|
||||
}
|
||||
|
||||
return (this._childNodes[entity.id] = nodes);
|
||||
},
|
||||
|
||||
base: function() {
|
||||
return {
|
||||
'entities': iD.util.getPrototypeOf(this.entities),
|
||||
'parentWays': iD.util.getPrototypeOf(this._parentWays),
|
||||
'parentRels': iD.util.getPrototypeOf(this._parentRels)
|
||||
};
|
||||
},
|
||||
|
||||
// Unlike other graph methods, rebase mutates in place. This is because it
|
||||
// is used only during the history operation that merges newly downloaded
|
||||
// data into each state. To external consumers, it should appear as if the
|
||||
// graph always contained the newly downloaded data.
|
||||
rebase: function(entities) {
|
||||
var base = this.base(),
|
||||
i, k, child, id, keys;
|
||||
|
||||
// Merging of data only needed if graph is the base graph
|
||||
if (!this.inherited) {
|
||||
for (i in entities) {
|
||||
if (!base.entities[i]) {
|
||||
base.entities[i] = entities[i];
|
||||
this._updateCalculated(undefined, entities[i],
|
||||
base.parentWays, base.parentRels);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
keys = Object.keys(this._parentWays);
|
||||
for (i = 0; i < keys.length; i++) {
|
||||
child = keys[i];
|
||||
if (base.parentWays[child]) {
|
||||
for (k = 0; k < base.parentWays[child].length; k++) {
|
||||
id = base.parentWays[child][k];
|
||||
if (!this.entities.hasOwnProperty(id) && !_.contains(this._parentWays[child], id)) {
|
||||
this._parentWays[child].push(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
keys = Object.keys(this._parentRels);
|
||||
for (i = 0; i < keys.length; i++) {
|
||||
child = keys[i];
|
||||
if (base.parentRels[child]) {
|
||||
for (k = 0; k < base.parentRels[child].length; k++) {
|
||||
id = base.parentRels[child][k];
|
||||
if (!this.entities.hasOwnProperty(id) && !_.contains(this._parentRels[child], id)) {
|
||||
this._parentRels[child].push(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Updates calculated properties (parentWays, parentRels) for the specified change
|
||||
_updateCalculated: function(oldentity, entity, parentWays, parentRels) {
|
||||
|
||||
parentWays = parentWays || this._parentWays;
|
||||
parentRels = parentRels || this._parentRels;
|
||||
|
||||
var type = entity && entity.type || oldentity && oldentity.type,
|
||||
removed, added, ways, rels, i;
|
||||
|
||||
|
||||
if (type === 'way') {
|
||||
|
||||
// Update parentWays
|
||||
if (oldentity && entity) {
|
||||
removed = _.difference(oldentity.nodes, entity.nodes);
|
||||
added = _.difference(entity.nodes, oldentity.nodes);
|
||||
} else if (oldentity) {
|
||||
removed = oldentity.nodes;
|
||||
added = [];
|
||||
} else if (entity) {
|
||||
removed = [];
|
||||
added = entity.nodes;
|
||||
}
|
||||
for (i = 0; i < removed.length; i++) {
|
||||
parentWays[removed[i]] = _.without(parentWays[removed[i]], oldentity.id);
|
||||
}
|
||||
for (i = 0; i < added.length; i++) {
|
||||
ways = _.without(parentWays[added[i]], entity.id);
|
||||
ways.push(entity.id);
|
||||
parentWays[added[i]] = ways;
|
||||
}
|
||||
} else if (type === 'node') {
|
||||
|
||||
} else if (type === 'relation') {
|
||||
|
||||
// Update parentRels
|
||||
if (oldentity && entity) {
|
||||
removed = _.difference(oldentity.members, entity.members);
|
||||
added = _.difference(entity.members, oldentity);
|
||||
} else if (oldentity) {
|
||||
removed = oldentity.members;
|
||||
added = [];
|
||||
} else if (entity) {
|
||||
removed = [];
|
||||
added = entity.members;
|
||||
}
|
||||
for (i = 0; i < removed.length; i++) {
|
||||
parentRels[removed[i].id] = _.without(parentRels[removed[i].id], oldentity.id);
|
||||
}
|
||||
for (i = 0; i < added.length; i++) {
|
||||
rels = _.without(parentRels[added[i].id], entity.id);
|
||||
rels.push(entity.id);
|
||||
parentRels[added[i].id] = rels;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
replace: function(entity) {
|
||||
if (this.entities[entity.id] === entity)
|
||||
return this;
|
||||
|
||||
return this.update(function() {
|
||||
this._updateCalculated(this.entities[entity.id], entity);
|
||||
this.entities[entity.id] = entity;
|
||||
});
|
||||
},
|
||||
|
||||
remove: function(entity) {
|
||||
return this.update(function() {
|
||||
this._updateCalculated(entity, undefined);
|
||||
this.entities[entity.id] = undefined;
|
||||
});
|
||||
},
|
||||
|
||||
update: function() {
|
||||
var graph = this.frozen ? iD.Graph(this, true) : this;
|
||||
|
||||
for (var i = 0; i < arguments.length; i++) {
|
||||
arguments[i].call(graph, graph);
|
||||
}
|
||||
|
||||
return this.frozen ? graph.freeze() : this;
|
||||
},
|
||||
|
||||
freeze: function() {
|
||||
this.frozen = true;
|
||||
|
||||
if (iD.debug) {
|
||||
Object.freeze(this.entities);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
// get all objects that intersect an extent.
|
||||
intersects: function(extent) {
|
||||
var items = [];
|
||||
for (var i in this.entities) {
|
||||
var entity = this.entities[i];
|
||||
if (entity && this.hasAllChildren(entity) && entity.intersects(extent, this)) {
|
||||
items.push(entity);
|
||||
}
|
||||
}
|
||||
return items;
|
||||
},
|
||||
|
||||
hasAllChildren: function(entity) {
|
||||
// we're only checking changed entities, since we assume fetched data
|
||||
// must have all children present
|
||||
if (this.entities.hasOwnProperty(entity.id)) {
|
||||
if (entity.type === 'way') {
|
||||
for (i = 0; i < entity.nodes.length; i++) {
|
||||
if (!this.entities[entity.nodes[i]]) return false;
|
||||
}
|
||||
} else if (entity.type === 'relation') {
|
||||
for (i = 0; i < entity.members.length; i++) {
|
||||
if (!this.entities[entity.members[i].id]) return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
// Obliterates any existing entities
|
||||
load: function(entities) {
|
||||
|
||||
var base = this.base(),
|
||||
i, entity, prefix;
|
||||
this.entities = Object.create(base.entities);
|
||||
|
||||
for (i in entities) {
|
||||
entity = entities[i];
|
||||
prefix = i[0];
|
||||
|
||||
if (entity === 'undefined') {
|
||||
this.entities[i] = undefined;
|
||||
} else if (prefix == 'n') {
|
||||
this.entities[i] = new iD.Node(entity);
|
||||
|
||||
} else if (prefix == 'w') {
|
||||
this.entities[i] = new iD.Way(entity);
|
||||
|
||||
} else if (prefix == 'r') {
|
||||
this.entities[i] = new iD.Relation(entity);
|
||||
}
|
||||
this._updateCalculated(base.entities[i], this.entities[i]);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
};
|
||||
@@ -0,0 +1,245 @@
|
||||
iD.History = function(context) {
|
||||
var stack, index,
|
||||
imagery_used = 'Bing',
|
||||
dispatch = d3.dispatch('change', 'undone', 'redone'),
|
||||
lock = false;
|
||||
|
||||
function perform(actions) {
|
||||
actions = Array.prototype.slice.call(actions);
|
||||
|
||||
var annotation;
|
||||
|
||||
if (!_.isFunction(_.last(actions))) {
|
||||
annotation = actions.pop();
|
||||
}
|
||||
|
||||
var graph = stack[index].graph;
|
||||
for (var i = 0; i < actions.length; i++) {
|
||||
graph = actions[i](graph);
|
||||
}
|
||||
|
||||
return {
|
||||
graph: graph,
|
||||
annotation: annotation,
|
||||
imagery_used: imagery_used
|
||||
};
|
||||
}
|
||||
|
||||
function change(previous) {
|
||||
var difference = iD.Difference(previous, history.graph());
|
||||
dispatch.change(difference);
|
||||
return difference;
|
||||
}
|
||||
|
||||
function getKey(n) {
|
||||
return 'iD_' + window.location.origin + '_' + n;
|
||||
}
|
||||
|
||||
var history = {
|
||||
graph: function() {
|
||||
return stack[index].graph;
|
||||
},
|
||||
|
||||
merge: function(entities) {
|
||||
for (var i = 0; i < stack.length; i++) {
|
||||
stack[i].graph.rebase(entities);
|
||||
}
|
||||
|
||||
dispatch.change();
|
||||
},
|
||||
|
||||
perform: function() {
|
||||
var previous = stack[index].graph;
|
||||
|
||||
stack = stack.slice(0, index + 1);
|
||||
stack.push(perform(arguments));
|
||||
index++;
|
||||
|
||||
return change(previous);
|
||||
},
|
||||
|
||||
replace: function() {
|
||||
var previous = stack[index].graph;
|
||||
|
||||
// assert(index == stack.length - 1)
|
||||
stack[index] = perform(arguments);
|
||||
|
||||
return change(previous);
|
||||
},
|
||||
|
||||
pop: function() {
|
||||
var previous = stack[index].graph;
|
||||
|
||||
if (index > 0) {
|
||||
index--;
|
||||
stack.pop();
|
||||
return change(previous);
|
||||
}
|
||||
},
|
||||
|
||||
undo: function() {
|
||||
var previous = stack[index].graph;
|
||||
|
||||
// Pop to the first annotated state.
|
||||
while (index > 0) {
|
||||
if (stack[index].annotation) break;
|
||||
index--;
|
||||
}
|
||||
|
||||
// Pop to the next annotated state.
|
||||
while (index > 0) {
|
||||
index--;
|
||||
if (stack[index].annotation) break;
|
||||
}
|
||||
|
||||
dispatch.undone();
|
||||
return change(previous);
|
||||
},
|
||||
|
||||
redo: function() {
|
||||
var previous = stack[index].graph;
|
||||
|
||||
while (index < stack.length - 1) {
|
||||
index++;
|
||||
if (stack[index].annotation) break;
|
||||
}
|
||||
|
||||
dispatch.redone();
|
||||
return change(previous);
|
||||
},
|
||||
|
||||
undoAnnotation: function() {
|
||||
var i = index;
|
||||
while (i >= 0) {
|
||||
if (stack[i].annotation) return stack[i].annotation;
|
||||
i--;
|
||||
}
|
||||
},
|
||||
|
||||
redoAnnotation: function() {
|
||||
var i = index + 1;
|
||||
while (i <= stack.length - 1) {
|
||||
if (stack[i].annotation) return stack[i].annotation;
|
||||
i++;
|
||||
}
|
||||
},
|
||||
|
||||
difference: function() {
|
||||
var base = stack[0].graph,
|
||||
head = stack[index].graph;
|
||||
return iD.Difference(base, head);
|
||||
},
|
||||
|
||||
changes: function() {
|
||||
var difference = history.difference();
|
||||
|
||||
function discardTags(entity) {
|
||||
if (_.isEmpty(entity.tags)) {
|
||||
return entity;
|
||||
} else {
|
||||
return entity.update({
|
||||
tags: _.omit(entity.tags, iD.data.discarded)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
modified: difference.modified().map(discardTags),
|
||||
created: difference.created().map(discardTags),
|
||||
deleted: difference.deleted()
|
||||
};
|
||||
},
|
||||
|
||||
hasChanges: function() {
|
||||
return this.difference().length() > 0;
|
||||
},
|
||||
|
||||
numChanges: function() {
|
||||
return this.difference().length();
|
||||
},
|
||||
|
||||
imagery_used: function(source) {
|
||||
if (source) imagery_used = source;
|
||||
else return _.without(
|
||||
_.unique(_.pluck(stack.slice(1, index + 1), 'imagery_used')),
|
||||
undefined, 'Custom');
|
||||
},
|
||||
|
||||
reset: function() {
|
||||
stack = [{graph: iD.Graph()}];
|
||||
index = 0;
|
||||
dispatch.change();
|
||||
},
|
||||
|
||||
save: function() {
|
||||
if (!lock) return;
|
||||
context.storage(getKey('lock'), null);
|
||||
|
||||
if (stack.length <= 1) return;
|
||||
|
||||
var json = JSON.stringify(stack.map(function(i) {
|
||||
return {
|
||||
annotation: i.annotation,
|
||||
imagery_used: i.imagery_used,
|
||||
entities: i.graph.entities
|
||||
};
|
||||
}), function includeUndefined(key, value) {
|
||||
if (typeof value === 'undefined') return 'undefined';
|
||||
return value;
|
||||
});
|
||||
|
||||
context.storage(getKey('history'), json);
|
||||
context.storage(getKey('nextIDs'), JSON.stringify(iD.Entity.id.next));
|
||||
context.storage(getKey('index'), index);
|
||||
},
|
||||
|
||||
clearSaved: function() {
|
||||
if (!lock) return;
|
||||
context.storage(getKey('history'), null);
|
||||
context.storage(getKey('nextIDs'), null);
|
||||
context.storage(getKey('index'), null);
|
||||
},
|
||||
|
||||
lock: function() {
|
||||
if (context.storage(getKey('lock'))) return false;
|
||||
context.storage(getKey('lock'), true);
|
||||
lock = true;
|
||||
return lock;
|
||||
},
|
||||
|
||||
restorableChanges: function() {
|
||||
return lock && !!context.storage(getKey('history'));
|
||||
},
|
||||
|
||||
load: function() {
|
||||
if (!lock) return;
|
||||
|
||||
var json = context.storage(getKey('history')),
|
||||
nextIDs = context.storage(getKey('nextIDs')),
|
||||
index_ = context.storage(getKey('index'));
|
||||
|
||||
if (!json) return;
|
||||
if (nextIDs) iD.Entity.id.next = JSON.parse(nextIDs);
|
||||
if (index_ !== null) index = parseInt(index_, 10);
|
||||
|
||||
context.storage(getKey('history', null));
|
||||
context.storage(getKey('nextIDs', null));
|
||||
context.storage(getKey('index', null));
|
||||
|
||||
stack = JSON.parse(json).map(function(d, i) {
|
||||
d.graph = iD.Graph(stack[0].graph).load(d.entities);
|
||||
return d;
|
||||
});
|
||||
stack[0].graph.inherited = false;
|
||||
dispatch.change();
|
||||
|
||||
},
|
||||
|
||||
_getKey: getKey
|
||||
|
||||
};
|
||||
|
||||
history.reset();
|
||||
|
||||
return d3.rebind(history, dispatch, 'on');
|
||||
};
|
||||
@@ -12,7 +12,7 @@ _.extend(iD.Node.prototype, {
|
||||
type: "node",
|
||||
|
||||
extent: function() {
|
||||
return iD.geo.Extent(this.loc);
|
||||
return new iD.geo.Extent(this.loc);
|
||||
},
|
||||
|
||||
geometry: function(graph) {
|
||||
@@ -47,6 +47,6 @@ _.extend(iD.Node.prototype, {
|
||||
type: 'Point',
|
||||
coordinates: this.loc
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
@@ -14,7 +14,7 @@ _.extend(iD.Relation.prototype, {
|
||||
|
||||
extent: function(resolver) {
|
||||
return resolver.transient(this, 'extent', function() {
|
||||
return this.members.reduce(function (extent, member) {
|
||||
return this.members.reduce(function(extent, member) {
|
||||
member = resolver.entity(member.id);
|
||||
if (member) {
|
||||
return extent.extend(member.extent(resolver));
|
||||
@@ -26,7 +26,7 @@ _.extend(iD.Relation.prototype, {
|
||||
},
|
||||
|
||||
geometry: function() {
|
||||
return 'relation';
|
||||
return this.isMultipolygon() ? 'area' : 'relation';
|
||||
},
|
||||
|
||||
// Return the first member with the given role. A copy of the member object
|
||||
@@ -49,6 +49,16 @@ _.extend(iD.Relation.prototype, {
|
||||
}
|
||||
},
|
||||
|
||||
// Return the first member with the given id and role. A copy of the member object
|
||||
// is returned, extended with an 'index' property whose value is the member index.
|
||||
memberByIdAndRole: function(id, role) {
|
||||
for (var i = 0; i < this.members.length; i++) {
|
||||
if (this.members[i].id === id && this.members[i].role === role) {
|
||||
return _.extend({}, this.members[i], {index: i});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
addMember: function(member, index) {
|
||||
var members = this.members.slice();
|
||||
members.splice(index === undefined ? members.length : index, 0, member);
|
||||
@@ -66,6 +76,28 @@ _.extend(iD.Relation.prototype, {
|
||||
return this.update({members: members});
|
||||
},
|
||||
|
||||
// Wherever a member appears with id `needle.id`, replace it with a member
|
||||
// with id `replacement.id`, type `replacement.type`, and the original role,
|
||||
// unless a member already exists with that id and role. Return an updated
|
||||
// relation.
|
||||
replaceMember: function(needle, replacement) {
|
||||
if (!this.memberById(needle.id))
|
||||
return this;
|
||||
|
||||
var members = [];
|
||||
|
||||
for (var i = 0; i < this.members.length; i++) {
|
||||
var member = this.members[i];
|
||||
if (member.id !== needle.id) {
|
||||
members.push(member);
|
||||
} else if (!this.memberByIdAndRole(replacement.id, member.role)) {
|
||||
members.push({id: replacement.id, type: replacement.type, role: member.role});
|
||||
}
|
||||
}
|
||||
|
||||
return this.update({members: members});
|
||||
},
|
||||
|
||||
asJXON: function(changeset_id) {
|
||||
var r = {
|
||||
relation: {
|
||||
@@ -83,6 +115,31 @@ _.extend(iD.Relation.prototype, {
|
||||
return r;
|
||||
},
|
||||
|
||||
asGeoJSON: function(resolver) {
|
||||
if (this.isMultipolygon()) {
|
||||
return {
|
||||
type: 'Feature',
|
||||
properties: this.tags,
|
||||
geometry: {
|
||||
type: 'MultiPolygon',
|
||||
coordinates: this.multipolygon(resolver)
|
||||
}
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
type: 'FeatureCollection',
|
||||
properties: this.tags,
|
||||
features: this.members.map(function(member) {
|
||||
return _.extend({role: member.role}, resolver.entity(member.id).asGeoJSON(resolver));
|
||||
})
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
isMultipolygon: function() {
|
||||
return this.tags.type === 'multipolygon';
|
||||
},
|
||||
|
||||
isRestriction: function() {
|
||||
return !!(this.tags.type && this.tags.type.match(/^restriction:?/));
|
||||
},
|
||||
@@ -99,8 +156,8 @@ _.extend(iD.Relation.prototype, {
|
||||
//
|
||||
multipolygon: function(resolver) {
|
||||
var members = this.members
|
||||
.filter(function (m) { return m.type === 'way' && resolver.entity(m.id); })
|
||||
.map(function (m) { return { role: m.role || 'outer', id: m.id, nodes: resolver.childNodes(resolver.entity(m.id)) }; });
|
||||
.filter(function(m) { return m.type === 'way' && resolver.entity(m.id); })
|
||||
.map(function(m) { return { role: m.role || 'outer', id: m.id, nodes: resolver.childNodes(resolver.entity(m.id)) }; });
|
||||
|
||||
function join(ways) {
|
||||
var joined = [], current, first, last, i, how, what;
|
||||
@@ -145,30 +202,28 @@ _.extend(iD.Relation.prototype, {
|
||||
}
|
||||
}
|
||||
|
||||
return joined;
|
||||
return joined.map(function(nodes) { return _.pluck(nodes, 'loc'); });
|
||||
}
|
||||
|
||||
function findOuter(inner) {
|
||||
var o, outer;
|
||||
|
||||
inner = _.pluck(inner, 'loc');
|
||||
|
||||
for (o = 0; o < outers.length; o++) {
|
||||
outer = _.pluck(outers[o], 'loc');
|
||||
outer = outers[o];
|
||||
if (iD.geo.polygonContainsPolygon(outer, inner))
|
||||
return o;
|
||||
}
|
||||
|
||||
for (o = 0; o < outers.length; o++) {
|
||||
outer = _.pluck(outers[o], 'loc');
|
||||
outer = outers[o];
|
||||
if (iD.geo.polygonIntersectsPolygon(outer, inner))
|
||||
return o;
|
||||
}
|
||||
}
|
||||
|
||||
var outers = join(members.filter(function (m) { return m.role === 'outer'; })),
|
||||
inners = join(members.filter(function (m) { return m.role === 'inner'; })),
|
||||
result = outers.map(function (o) { return [o]; });
|
||||
var outers = join(members.filter(function(m) { return m.role === 'outer'; })),
|
||||
inners = join(members.filter(function(m) { return m.role === 'inner'; })),
|
||||
result = outers.map(function(o) { return [o]; });
|
||||
|
||||
for (var i = 0; i < inners.length; i++) {
|
||||
var o = findOuter(inners[i]);
|
||||
@@ -14,7 +14,7 @@ _.extend(iD.Way.prototype, {
|
||||
|
||||
extent: function(resolver) {
|
||||
return resolver.transient(this, 'extent', function() {
|
||||
return this.nodes.reduce(function (extent, id) {
|
||||
return this.nodes.reduce(function(extent, id) {
|
||||
return extent.extend(resolver.entity(id).extent(resolver));
|
||||
}, iD.geo.Extent());
|
||||
});
|
||||
@@ -47,11 +47,14 @@ _.extend(iD.Way.prototype, {
|
||||
// - doesn't have area=no
|
||||
// - doesn't have highway tag
|
||||
isArea: function() {
|
||||
return this.tags.area === 'yes' ||
|
||||
(this.isClosed() &&
|
||||
this.tags.area !== 'no' &&
|
||||
!this.tags.highway &&
|
||||
!this.tags.barrier);
|
||||
if (this.tags.area === 'yes')
|
||||
return true;
|
||||
if (!this.isClosed() || this.tags.area === 'no')
|
||||
return false;
|
||||
for (var key in this.tags)
|
||||
if (key in iD.Way.areaKeys)
|
||||
return true;
|
||||
return false;
|
||||
},
|
||||
|
||||
isDegenerate: function() {
|
||||
@@ -74,6 +77,19 @@ _.extend(iD.Way.prototype, {
|
||||
return this.update({nodes: nodes});
|
||||
},
|
||||
|
||||
replaceNode: function(needle, replacement) {
|
||||
if (this.nodes.indexOf(needle) < 0)
|
||||
return this;
|
||||
|
||||
var nodes = this.nodes.slice();
|
||||
for (var i = 0; i < nodes.length; i++) {
|
||||
if (nodes[i] === needle) {
|
||||
nodes[i] = replacement;
|
||||
}
|
||||
}
|
||||
return this.update({nodes: nodes});
|
||||
},
|
||||
|
||||
removeNode: function(id) {
|
||||
var nodes = _.without(this.nodes, id);
|
||||
|
||||
@@ -103,13 +119,28 @@ _.extend(iD.Way.prototype, {
|
||||
},
|
||||
|
||||
asGeoJSON: function(resolver) {
|
||||
return {
|
||||
type: 'Feature',
|
||||
properties: this.tags,
|
||||
geometry: {
|
||||
type: 'LineString',
|
||||
coordinates: _.pluck(resolver.childNodes(this), 'loc')
|
||||
}
|
||||
};
|
||||
if (this.isArea()) {
|
||||
return {
|
||||
type: 'Feature',
|
||||
properties: this.tags,
|
||||
geometry: {
|
||||
type: 'Polygon',
|
||||
coordinates: [_.pluck(resolver.childNodes(this), 'loc')]
|
||||
}
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
type: 'Feature',
|
||||
properties: this.tags,
|
||||
geometry: {
|
||||
type: 'LineString',
|
||||
coordinates: _.pluck(resolver.childNodes(this), 'loc')
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
iD.Way.areaKeys = iD.util.trueObj(['area', 'building', 'leisure', 'tourism', 'ruins',
|
||||
'historic', 'landuse', 'military', 'natural', 'amenity', 'shop', 'man_made',
|
||||
'public_transport']);
|
||||
@@ -9,16 +9,17 @@ iD.geo.interp = function(p1, p2, t) {
|
||||
p1[1] + (p2[1] - p1[1]) * t];
|
||||
};
|
||||
|
||||
// http://jsperf.com/id-dist-optimization
|
||||
iD.geo.dist = function(a, b) {
|
||||
return Math.sqrt(Math.pow(a[0] - b[0], 2) +
|
||||
Math.pow(a[1] - b[1], 2));
|
||||
var x = a[0] - b[0], y = a[1] - b[1];
|
||||
return Math.sqrt((x * x) + (y * y));
|
||||
};
|
||||
|
||||
iD.geo.chooseIndex = function(way, point, map) {
|
||||
iD.geo.chooseIndex = function(way, point, context) {
|
||||
var dist = iD.geo.dist,
|
||||
graph = map.history().graph(),
|
||||
graph = context.graph(),
|
||||
nodes = graph.childNodes(way),
|
||||
projNodes = nodes.map(function(n) { return map.projection(n.loc); });
|
||||
projNodes = nodes.map(function(n) { return context.projection(n.loc); });
|
||||
|
||||
for (var i = 0, changes = []; i < projNodes.length - 1; i++) {
|
||||
changes[i] =
|
||||
@@ -63,13 +64,13 @@ iD.geo.pointInPolygon = function(point, polygon) {
|
||||
};
|
||||
|
||||
iD.geo.polygonContainsPolygon = function(outer, inner) {
|
||||
return _.every(inner, function (point) {
|
||||
return _.every(inner, function(point) {
|
||||
return iD.geo.pointInPolygon(point, outer);
|
||||
});
|
||||
};
|
||||
|
||||
iD.geo.polygonIntersectsPolygon = function(outer, inner) {
|
||||
return _.some(inner, function (point) {
|
||||
return _.some(inner, function(point) {
|
||||
return iD.geo.pointInPolygon(point, outer);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
iD.geo.Extent = function (min, max) {
|
||||
iD.geo.Extent = function geoExtent(min, max) {
|
||||
if (!(this instanceof iD.geo.Extent)) return new iD.geo.Extent(min, max);
|
||||
if (min instanceof iD.geo.Extent) {
|
||||
return min;
|
||||
@@ -14,21 +14,21 @@ iD.geo.Extent = function (min, max) {
|
||||
iD.geo.Extent.prototype = [[], []];
|
||||
|
||||
_.extend(iD.geo.Extent.prototype, {
|
||||
extend: function (obj) {
|
||||
obj = iD.geo.Extent(obj);
|
||||
extend: function(obj) {
|
||||
if (!(obj instanceof iD.geo.Extent)) obj = new iD.geo.Extent(obj);
|
||||
return iD.geo.Extent([Math.min(obj[0][0], this[0][0]),
|
||||
Math.min(obj[0][1], this[0][1])],
|
||||
[Math.max(obj[1][0], this[1][0]),
|
||||
Math.max(obj[1][1], this[1][1])]);
|
||||
},
|
||||
|
||||
center: function () {
|
||||
center: function() {
|
||||
return [(this[0][0] + this[1][0]) / 2,
|
||||
(this[0][1] + this[1][1]) / 2];
|
||||
},
|
||||
|
||||
intersects: function (obj) {
|
||||
obj = iD.geo.Extent(obj);
|
||||
intersects: function(obj) {
|
||||
if (!(obj instanceof iD.geo.Extent)) obj = new iD.geo.Extent(obj);
|
||||
return obj[0][0] <= this[1][0] &&
|
||||
obj[0][1] <= this[1][1] &&
|
||||
obj[1][0] >= this[0][0] &&
|
||||
|
||||
@@ -1,214 +0,0 @@
|
||||
iD.Graph = function(entities, mutable) {
|
||||
if (!(this instanceof iD.Graph)) return new iD.Graph(entities, mutable);
|
||||
|
||||
if (_.isArray(entities)) {
|
||||
this.entities = {};
|
||||
for (var i = 0; i < entities.length; i++) {
|
||||
this.entities[entities[i].id] = entities[i];
|
||||
}
|
||||
} else {
|
||||
this.entities = entities || {};
|
||||
}
|
||||
|
||||
this.transients = {};
|
||||
this._parentWays = {};
|
||||
this._parentRels = {};
|
||||
this._childNodes = {};
|
||||
|
||||
if (!mutable) {
|
||||
this.freeze();
|
||||
}
|
||||
};
|
||||
|
||||
iD.Graph.prototype = {
|
||||
entity: function(id) {
|
||||
return this.entities[id];
|
||||
},
|
||||
|
||||
transient: function(entity, key, fn) {
|
||||
var id = entity.id,
|
||||
transients = this.transients[id] ||
|
||||
(this.transients[id] = {});
|
||||
|
||||
if (transients[key] !== undefined) {
|
||||
return transients[key];
|
||||
}
|
||||
|
||||
return transients[key] = fn.call(entity);
|
||||
},
|
||||
|
||||
parentWays: function(entity) {
|
||||
var ent, id, parents;
|
||||
|
||||
if (!this._parentWays.calculated) {
|
||||
for (var i in this.entities) {
|
||||
ent = this.entities[i];
|
||||
if (ent && ent.type === 'way') {
|
||||
for (var j = 0; j < ent.nodes.length; j++) {
|
||||
id = ent.nodes[j];
|
||||
parents = this._parentWays[id] = this._parentWays[id] || [];
|
||||
if (parents.indexOf(ent) < 0) {
|
||||
parents.push(ent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this._parentWays.calculated = true;
|
||||
}
|
||||
|
||||
return this._parentWays[entity.id] || [];
|
||||
},
|
||||
|
||||
isPoi: function(entity) {
|
||||
return this.parentWays(entity).length === 0;
|
||||
},
|
||||
|
||||
parentRelations: function(entity) {
|
||||
var ent, id, parents;
|
||||
|
||||
if (!this._parentRels.calculated) {
|
||||
for (var i in this.entities) {
|
||||
ent = this.entities[i];
|
||||
if (ent && ent.type === 'relation') {
|
||||
for (var j = 0; j < ent.members.length; j++) {
|
||||
id = ent.members[j].id;
|
||||
parents = this._parentRels[id] = this._parentRels[id] || [];
|
||||
if (parents.indexOf(ent) < 0) {
|
||||
parents.push(ent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this._parentRels.calculated = true;
|
||||
}
|
||||
|
||||
return this._parentRels[entity.id] || [];
|
||||
},
|
||||
|
||||
childNodes: function(entity) {
|
||||
if (this._childNodes[entity.id])
|
||||
return this._childNodes[entity.id];
|
||||
|
||||
var nodes = [];
|
||||
for (var i = 0, l = entity.nodes.length; i < l; i++) {
|
||||
nodes[i] = this.entity(entity.nodes[i]);
|
||||
}
|
||||
|
||||
return (this._childNodes[entity.id] = nodes);
|
||||
},
|
||||
|
||||
merge: function(graph) {
|
||||
return this.update(function () {
|
||||
_.defaults(this.entities, graph.entities);
|
||||
});
|
||||
},
|
||||
|
||||
replace: function(entity) {
|
||||
return this.update(function () {
|
||||
this.entities[entity.id] = entity;
|
||||
});
|
||||
},
|
||||
|
||||
remove: function(entity) {
|
||||
return this.update(function () {
|
||||
if (entity.created()) {
|
||||
delete this.entities[entity.id];
|
||||
} else {
|
||||
this.entities[entity.id] = undefined;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
update: function() {
|
||||
var graph = this.frozen ? iD.Graph(_.clone(this.entities), true) : this;
|
||||
|
||||
for (var i = 0; i < arguments.length; i++) {
|
||||
arguments[i].call(graph, graph);
|
||||
}
|
||||
|
||||
return this.frozen ? graph.freeze() : this;
|
||||
},
|
||||
|
||||
freeze: function() {
|
||||
this.frozen = true;
|
||||
|
||||
if (iD.debug) {
|
||||
Object.freeze(this);
|
||||
Object.freeze(this.entities);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
// get all objects that intersect an extent.
|
||||
intersects: function(extent) {
|
||||
var items = [];
|
||||
for (var i in this.entities) {
|
||||
var entity = this.entities[i];
|
||||
if (entity && entity.intersects(extent, this)) {
|
||||
items.push(entity);
|
||||
}
|
||||
}
|
||||
return items;
|
||||
},
|
||||
|
||||
difference: function (graph) {
|
||||
var result = [], entity, oldentity, id;
|
||||
|
||||
for (id in this.entities) {
|
||||
entity = this.entities[id];
|
||||
oldentity = graph.entities[id];
|
||||
if (entity !== oldentity) {
|
||||
|
||||
if (entity && entity.type === 'way' &&
|
||||
oldentity && oldentity.type === 'way') {
|
||||
result = result
|
||||
.concat(_.difference(entity.nodes, oldentity.nodes))
|
||||
.concat(_.difference(oldentity.nodes, entity.nodes));
|
||||
|
||||
} else if (entity && entity.type === 'way') {
|
||||
result = result.concat(entity.nodes);
|
||||
|
||||
} else if (oldentity && oldentity.type === 'way') {
|
||||
result = result.concat(oldentity.nodes);
|
||||
}
|
||||
|
||||
result.push(id);
|
||||
}
|
||||
}
|
||||
|
||||
for (id in graph.entities) {
|
||||
entity = graph.entities[id];
|
||||
if (entity && !this.entities.hasOwnProperty(id)) {
|
||||
result.push(id);
|
||||
if (entity.type === 'way') result = result.concat(entity.nodes);
|
||||
}
|
||||
}
|
||||
|
||||
return result.sort();
|
||||
},
|
||||
|
||||
modified: function() {
|
||||
var result = [];
|
||||
_.each(this.entities, function(entity, id) {
|
||||
if (entity && entity.modified()) result.push(id);
|
||||
});
|
||||
return result;
|
||||
},
|
||||
|
||||
created: function() {
|
||||
var result = [];
|
||||
_.each(this.entities, function(entity, id) {
|
||||
if (entity && entity.created()) result.push(id);
|
||||
});
|
||||
return result;
|
||||
},
|
||||
|
||||
deleted: function() {
|
||||
var result = [];
|
||||
_.each(this.entities, function(entity, id) {
|
||||
if (!entity) result.push(id);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
};
|
||||
@@ -1,158 +0,0 @@
|
||||
iD.History = function() {
|
||||
var stack, index,
|
||||
imagery_used = 'Bing',
|
||||
dispatch = d3.dispatch('change', 'undone', 'redone');
|
||||
|
||||
function perform(actions) {
|
||||
actions = Array.prototype.slice.call(actions);
|
||||
|
||||
var annotation;
|
||||
|
||||
if (!_.isFunction(_.last(actions))) {
|
||||
annotation = actions.pop();
|
||||
}
|
||||
|
||||
var graph = stack[index].graph;
|
||||
for (var i = 0; i < actions.length; i++) {
|
||||
graph = actions[i](graph);
|
||||
}
|
||||
|
||||
return {graph: graph, annotation: annotation, imagery_used: imagery_used};
|
||||
}
|
||||
|
||||
function change(previous) {
|
||||
dispatch.change(history.graph().difference(previous));
|
||||
}
|
||||
|
||||
var history = {
|
||||
graph: function () {
|
||||
return stack[index].graph;
|
||||
},
|
||||
|
||||
merge: function (graph) {
|
||||
for (var i = 0; i < stack.length; i++) {
|
||||
stack[i].graph = stack[i].graph.merge(graph);
|
||||
}
|
||||
},
|
||||
|
||||
perform: function () {
|
||||
var previous = stack[index].graph;
|
||||
|
||||
stack = stack.slice(0, index + 1);
|
||||
stack.push(perform(arguments));
|
||||
index++;
|
||||
|
||||
change(previous);
|
||||
},
|
||||
|
||||
replace: function () {
|
||||
var previous = stack[index].graph;
|
||||
|
||||
// assert(index == stack.length - 1)
|
||||
stack[index] = perform(arguments);
|
||||
|
||||
change(previous);
|
||||
},
|
||||
|
||||
pop: function () {
|
||||
var previous = stack[index].graph;
|
||||
|
||||
if (index > 0) {
|
||||
index--;
|
||||
stack.pop();
|
||||
change(previous);
|
||||
}
|
||||
},
|
||||
|
||||
undo: function () {
|
||||
var previous = stack[index].graph;
|
||||
|
||||
// Pop to the first annotated state.
|
||||
while (index > 0) {
|
||||
if (stack[index].annotation) break;
|
||||
index--;
|
||||
}
|
||||
|
||||
// Pop to the next annotated state.
|
||||
while (index > 0) {
|
||||
index--;
|
||||
if (stack[index].annotation) break;
|
||||
}
|
||||
|
||||
dispatch.undone();
|
||||
change(previous);
|
||||
},
|
||||
|
||||
redo: function () {
|
||||
var previous = stack[index].graph;
|
||||
|
||||
while (index < stack.length - 1) {
|
||||
index++;
|
||||
if (stack[index].annotation) break;
|
||||
}
|
||||
|
||||
dispatch.redone();
|
||||
change(previous);
|
||||
},
|
||||
|
||||
undoAnnotation: function () {
|
||||
var i = index;
|
||||
while (i >= 0) {
|
||||
if (stack[i].annotation) return stack[i].annotation;
|
||||
i--;
|
||||
}
|
||||
},
|
||||
|
||||
redoAnnotation: function () {
|
||||
var i = index + 1;
|
||||
while (i <= stack.length - 1) {
|
||||
if (stack[i].annotation) return stack[i].annotation;
|
||||
i++;
|
||||
}
|
||||
},
|
||||
|
||||
changes: function () {
|
||||
var initial = stack[0].graph,
|
||||
current = stack[index].graph;
|
||||
|
||||
return {
|
||||
modified: current.modified().map(function (id) {
|
||||
return current.entity(id);
|
||||
}),
|
||||
created: current.created().map(function (id) {
|
||||
return current.entity(id);
|
||||
}),
|
||||
deleted: current.deleted().map(function (id) {
|
||||
return initial.entity(id);
|
||||
})
|
||||
};
|
||||
},
|
||||
|
||||
hasChanges: function() {
|
||||
return !!this.numChanges();
|
||||
},
|
||||
|
||||
numChanges: function() {
|
||||
return d3.sum(d3.values(this.changes()).map(function(c) {
|
||||
return c.length;
|
||||
}));
|
||||
},
|
||||
|
||||
imagery_used: function(source) {
|
||||
if (source) imagery_used = source;
|
||||
else return _.without(
|
||||
_.unique(_.pluck(stack.slice(1, index + 1), 'imagery_used')),
|
||||
undefined, 'Custom');
|
||||
},
|
||||
|
||||
reset: function () {
|
||||
stack = [{graph: iD.Graph()}];
|
||||
index = 0;
|
||||
dispatch.change();
|
||||
}
|
||||
};
|
||||
|
||||
history.reset();
|
||||
|
||||
return d3.rebind(history, dispatch, 'on');
|
||||
};
|
||||
@@ -1,47 +0,0 @@
|
||||
iD.validate = function(changes, graph) {
|
||||
var warnings = [], change;
|
||||
|
||||
// https://github.com/openstreetmap/josm/blob/mirror/src/org/
|
||||
// openstreetmap/josm/data/validation/tests/UnclosedWays.java#L80
|
||||
function tagSuggestsArea(change) {
|
||||
if (_.isEmpty(change.tags)) return false;
|
||||
var tags = change.tags;
|
||||
var presence = ['landuse', 'amenities', 'tourism', 'shop'];
|
||||
for (var i = 0; i < presence.length; i++) {
|
||||
if (tags[presence[i]] !== undefined) {
|
||||
return presence[i] + '=' + tags[presence[i]];
|
||||
}
|
||||
}
|
||||
if (tags.building && tags.building === 'yes') return 'building=yes';
|
||||
}
|
||||
|
||||
if (changes.created.length) {
|
||||
for (var i = 0; i < changes.created.length; i++) {
|
||||
change = changes.created[i];
|
||||
|
||||
if (change.geometry(graph) === 'point' && _.isEmpty(change.tags)) {
|
||||
warnings.push({
|
||||
message: 'Untagged point which is not part of a line or area',
|
||||
entity: change
|
||||
});
|
||||
}
|
||||
|
||||
if (change.geometry(graph) === 'line' && _.isEmpty(change.tags)) {
|
||||
warnings.push({ message: 'Untagged line', entity: change });
|
||||
}
|
||||
|
||||
if (change.geometry(graph) === 'area' && _.isEmpty(change.tags)) {
|
||||
warnings.push({ message: 'Untagged area', entity: change });
|
||||
}
|
||||
|
||||
if (change.geometry(graph) === 'line' && tagSuggestsArea(change)) {
|
||||
warnings.push({
|
||||
message: 'The tag ' + tagSuggestsArea(change) + ' suggests line should be area, but it is not and area',
|
||||
entity: change
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return warnings.length ? [warnings] : [];
|
||||
};
|
||||
@@ -1,288 +1,149 @@
|
||||
window.iD = function(container) {
|
||||
// the reported, displayed version of iD.
|
||||
var version = '0.0.0-alpha1';
|
||||
window.iD = function () {
|
||||
var context = {},
|
||||
storage = localStorage || {};
|
||||
|
||||
var connection = iD.Connection()
|
||||
.version(version),
|
||||
history = iD.History(),
|
||||
map = iD.Map()
|
||||
.connection(connection)
|
||||
.history(history),
|
||||
controller = iD.Controller(map, history);
|
||||
context.storage = function(k, v) {
|
||||
if (arguments.length === 1) return storage[k];
|
||||
else if (v === null) delete storage[k];
|
||||
else storage[k] = v;
|
||||
};
|
||||
|
||||
map.background.source(iD.BackgroundSource.Bing);
|
||||
var history = iD.History(context),
|
||||
dispatch = d3.dispatch('enter', 'exit'),
|
||||
mode,
|
||||
container,
|
||||
ui = iD.ui(context),
|
||||
map = iD.Map(context);
|
||||
|
||||
function editor(container) {
|
||||
if (!iD.supported()) {
|
||||
container.html('This editor is supported in Firefox, Chrome, Safari, Opera, ' +
|
||||
'and Internet Explorer 9 and above. Please upgrade your browser ' +
|
||||
'or use Potlatch 2 to edit the map.')
|
||||
.style('text-align:center;font-style:italic;');
|
||||
return;
|
||||
// the connection requires .storage() to be available on calling.
|
||||
var connection = iD.Connection(context);
|
||||
|
||||
connection.on('load.context', function loadContext(err, result) {
|
||||
history.merge(result);
|
||||
});
|
||||
|
||||
/* Straight accessors. Avoid using these if you can. */
|
||||
context.ui = function() { return ui; };
|
||||
context.connection = function() { return connection; };
|
||||
context.history = function() { return history; };
|
||||
context.map = function() { return map; };
|
||||
|
||||
/* History */
|
||||
context.graph = history.graph;
|
||||
context.perform = history.perform;
|
||||
context.replace = history.replace;
|
||||
context.pop = history.pop;
|
||||
context.undo = history.undo;
|
||||
context.redo = history.redo;
|
||||
context.changes = history.changes;
|
||||
|
||||
/* Graph */
|
||||
context.entity = function(id) {
|
||||
return history.graph().entity(id);
|
||||
};
|
||||
|
||||
context.geometry = function(id) {
|
||||
return context.entity(id).geometry(history.graph());
|
||||
};
|
||||
|
||||
/* Modes */
|
||||
context.enter = function(newMode) {
|
||||
if (mode) {
|
||||
mode.exit();
|
||||
dispatch.exit(mode);
|
||||
}
|
||||
|
||||
function hintprefix(x, y) {
|
||||
return '<span class="keyhint">' + x + '</span> ' + y;
|
||||
mode = newMode;
|
||||
mode.enter();
|
||||
dispatch.enter(mode);
|
||||
};
|
||||
|
||||
context.mode = function() {
|
||||
return mode;
|
||||
};
|
||||
|
||||
context.selection = function() {
|
||||
if (mode.id === 'select') {
|
||||
return mode.selection();
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
var m = container.append('div')
|
||||
.attr('id', 'map')
|
||||
.call(map);
|
||||
/* Behaviors */
|
||||
context.install = function(behavior) {
|
||||
context.surface().call(behavior);
|
||||
};
|
||||
|
||||
var bar = container.append('div')
|
||||
.attr('id', 'bar')
|
||||
.attr('class','pad1 fillD');
|
||||
context.uninstall = function(behavior) {
|
||||
context.surface().call(behavior.off);
|
||||
};
|
||||
|
||||
var limiter = bar.append('div')
|
||||
.attr('class', 'limiter');
|
||||
/* Map */
|
||||
context.background = function() { return map.background; };
|
||||
context.surface = function() { return map.surface; };
|
||||
context.projection = map.projection;
|
||||
context.tail = map.tail;
|
||||
context.redraw = map.redraw;
|
||||
context.pan = map.pan;
|
||||
context.zoomIn = map.zoomIn;
|
||||
context.zoomOut = map.zoomOut;
|
||||
|
||||
var buttons_joined = limiter.append('div')
|
||||
.attr('class', 'button-wrap joined col4');
|
||||
context.container = function(_) {
|
||||
if (!arguments.length) return container;
|
||||
container = _;
|
||||
return context;
|
||||
};
|
||||
|
||||
var buttons = buttons_joined.selectAll('button.add-button')
|
||||
.data([iD.modes.Browse(), iD.modes.AddPoint(), iD.modes.AddLine(), iD.modes.AddArea()])
|
||||
.enter().append('button')
|
||||
.attr('tabindex', -1)
|
||||
.attr('class', function (mode) { return mode.title + ' add-button col3'; })
|
||||
.attr('data-original-title', function (mode) {
|
||||
return hintprefix(mode.key, mode.description);
|
||||
})
|
||||
.call(bootstrap.tooltip().placement('bottom').html(true))
|
||||
.on('click.editor', function (mode) { controller.enter(mode); });
|
||||
|
||||
function disableTooHigh() {
|
||||
if (map.editable()) {
|
||||
notice.message(false);
|
||||
buttons.attr('disabled', null);
|
||||
} else {
|
||||
buttons.attr('disabled', 'disabled');
|
||||
notice.message(true);
|
||||
controller.enter(iD.modes.Browse());
|
||||
}
|
||||
}
|
||||
|
||||
var notice = iD.ui.notice(limiter)
|
||||
.message(false)
|
||||
.on('zoom', function() { map.zoom(16); });
|
||||
|
||||
map.on('move.editor', _.debounce(function() {
|
||||
disableTooHigh();
|
||||
contributors.call(iD.ui.contributors(map));
|
||||
}, 500));
|
||||
|
||||
buttons.append('span')
|
||||
.attr('class', function(d) {
|
||||
return d.id + ' icon icon-pre-text';
|
||||
});
|
||||
|
||||
buttons.append('span').attr('class', 'label').text(function (mode) { return mode.title; });
|
||||
|
||||
controller.on('enter.editor', function (entered) {
|
||||
buttons.classed('active', function (mode) { return entered.button === mode.button; });
|
||||
container.classed("mode-" + entered.id, true);
|
||||
});
|
||||
|
||||
controller.on('exit.editor', function (exited) {
|
||||
container.classed("mode-" + exited.id, false);
|
||||
});
|
||||
|
||||
var undo_buttons = limiter.append('div')
|
||||
.attr('class', 'button-wrap joined col1'),
|
||||
undo_tooltip = bootstrap.tooltip().placement('bottom').html(true);
|
||||
|
||||
undo_buttons.append('button')
|
||||
.attr({ id: 'undo', 'class': 'col6' })
|
||||
.property('disabled', true)
|
||||
.html("<span class='undo icon'></span><small></small>")
|
||||
.on('click.editor', history.undo)
|
||||
.call(undo_tooltip);
|
||||
|
||||
undo_buttons.append('button')
|
||||
.attr({ id: 'redo', 'class': 'col6' })
|
||||
.property('disabled', true)
|
||||
.html("<span class='redo icon'><small></small>")
|
||||
.on('click.editor', history.redo)
|
||||
.call(undo_tooltip);
|
||||
|
||||
var save_button = limiter.append('div').attr('class','button-wrap col1').append('button')
|
||||
.attr('class', 'save col12')
|
||||
.call(iD.ui.save().map(map).controller(controller));
|
||||
|
||||
var zoom = container.append('div')
|
||||
.attr('class', 'zoombuttons map-control')
|
||||
.selectAll('button')
|
||||
.data([['zoom-in', '+', map.zoomIn, 'Zoom In'], ['zoom-out', '-', map.zoomOut, 'Zoom Out']])
|
||||
.enter()
|
||||
.append('button')
|
||||
.attr('tabindex', -1)
|
||||
.attr('class', function(d) { return d[0]; })
|
||||
.attr('title', function(d) { return d[3]; })
|
||||
.on('click.editor', function(d) { return d[2](); })
|
||||
.append('span')
|
||||
.attr('class', function(d) {
|
||||
return d[0] + ' icon';
|
||||
});
|
||||
|
||||
if (navigator.geolocation) {
|
||||
container.append('div')
|
||||
.call(iD.ui.geolocate(map));
|
||||
}
|
||||
|
||||
var gc = container.append('div').attr('class', 'geocode-control map-control')
|
||||
.call(iD.ui.geocoder().map(map));
|
||||
|
||||
container.append('div').attr('class', 'map-control layerswitcher-control')
|
||||
.call(iD.ui.layerswitcher(map));
|
||||
|
||||
container.append('div')
|
||||
.style('display', 'none')
|
||||
.attr('class', 'inspector-wrap fr col5');
|
||||
|
||||
var about = container.append('div')
|
||||
.attr('class','col12 about-block fillD pad1');
|
||||
|
||||
about.append('div')
|
||||
.attr('class', 'user-container')
|
||||
.append('div')
|
||||
.attr('class', 'hello');
|
||||
|
||||
var aboutList = about.append('ul')
|
||||
.attr('id','about')
|
||||
.attr('class','link-list');
|
||||
|
||||
var linkList = aboutList.append('ul')
|
||||
.attr('id','about')
|
||||
.attr('class','pad1 fillD about-block link-list');
|
||||
linkList.append('li').append('a').attr('target', '_blank')
|
||||
.attr('href', 'http://github.com/systemed/iD').text(version);
|
||||
linkList.append('li').append('a').attr('target', '_blank')
|
||||
.attr('href', 'http://github.com/systemed/iD/issues').text('report a bug');
|
||||
|
||||
var imagery = linkList.append('li').attr('id', 'attribution');
|
||||
imagery.append('span').text('imagery');
|
||||
imagery.append('a').attr('target', '_blank')
|
||||
.attr('href', 'http://opengeodata.org/microsoft-imagery-details').text(' provided by bing');
|
||||
|
||||
linkList.append('li').attr('class', 'source-switch').append('a').attr('href', '#')
|
||||
.text('dev')
|
||||
.on('click.editor', function() {
|
||||
d3.event.preventDefault();
|
||||
if (d3.select(this).classed('live')) {
|
||||
map.flush().connection()
|
||||
.url('http://api06.dev.openstreetmap.org');
|
||||
d3.select(this).text('dev').classed('live', false);
|
||||
} else {
|
||||
map.flush().connection()
|
||||
.url('http://www.openstreetmap.org');
|
||||
d3.select(this).text('live').classed('live', true);
|
||||
}
|
||||
});
|
||||
|
||||
var contributors = linkList.append('li')
|
||||
.attr('id', 'user-list');
|
||||
contributors.append('span')
|
||||
.attr('class', 'icon nearby icon-pre-text');
|
||||
contributors.append('span')
|
||||
.text('Viewing contributions by ');
|
||||
contributors.append('span')
|
||||
.attr('class', 'contributor-list');
|
||||
contributors.append('span')
|
||||
.attr('class', 'contributor-count');
|
||||
|
||||
history.on('change.editor', function() {
|
||||
window.onbeforeunload = history.hasChanges() ? function() {
|
||||
return 'You have unsaved changes.';
|
||||
} : null;
|
||||
|
||||
var undo = history.undoAnnotation(),
|
||||
redo = history.redoAnnotation();
|
||||
|
||||
function refreshTooltip(selection) {
|
||||
if (selection.property('disabled')) {
|
||||
selection.call(undo_tooltip.hide);
|
||||
} else if (selection.property('tooltipVisible')) {
|
||||
selection.call(undo_tooltip.show);
|
||||
}
|
||||
}
|
||||
|
||||
limiter.select('#undo')
|
||||
.property('disabled', !undo)
|
||||
.attr('data-original-title', hintprefix('⌘Z', undo))
|
||||
.call(refreshTooltip);
|
||||
|
||||
limiter.select('#redo')
|
||||
.property('disabled', !redo)
|
||||
.attr('data-original-title', hintprefix('⌘⇧Z', redo))
|
||||
.call(refreshTooltip);
|
||||
});
|
||||
|
||||
d3.select(window).on('resize.editor', function() {
|
||||
map.size(m.size());
|
||||
});
|
||||
|
||||
var keybinding = d3.keybinding('main')
|
||||
.on('⌘+Z', function() { history.undo(); })
|
||||
.on('⌃+Z', function() { history.undo(); })
|
||||
.on('⌘+⇧+Z', function() { history.redo(); })
|
||||
.on('⌃+⇧+Z', function() { history.redo(); })
|
||||
.on('⌫', function() { d3.event.preventDefault(); });
|
||||
|
||||
[iD.modes.Browse(), iD.modes.AddPoint(), iD.modes.AddLine(), iD.modes.AddArea()].forEach(function(m) {
|
||||
keybinding.on(m.key, function() { if (map.editable()) controller.enter(m); });
|
||||
});
|
||||
|
||||
d3.select(document)
|
||||
.call(keybinding);
|
||||
|
||||
var hash = iD.Hash().controller(controller).map(map);
|
||||
|
||||
if (!hash.hadHash) {
|
||||
map.centerZoom([-77.02271, 38.90085], 20);
|
||||
}
|
||||
|
||||
d3.select('.user-container').call(iD.ui.userpanel(connection)
|
||||
.on('logout.editor', connection.logout)
|
||||
.on('login.editor', connection.authenticate));
|
||||
|
||||
controller.enter(iD.modes.Browse());
|
||||
|
||||
if (!localStorage.sawSplash) {
|
||||
iD.ui.splash();
|
||||
localStorage.sawSplash = true;
|
||||
}
|
||||
var q = iD.util.stringQs(location.hash.substring(1)), detected = false;
|
||||
if (q.layer) {
|
||||
context.background()
|
||||
.source(_.find(iD.layers, function(l) {
|
||||
if (l.data.sourcetag === q.layer) {
|
||||
return (detected = true);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
editor.connection = function(_) {
|
||||
if (!arguments.length) return connection;
|
||||
connection = _;
|
||||
return editor;
|
||||
};
|
||||
|
||||
editor.map = function() {
|
||||
return map;
|
||||
};
|
||||
|
||||
editor.controller = function() {
|
||||
return controller;
|
||||
};
|
||||
|
||||
if (arguments.length) {
|
||||
d3.select(container).call(editor);
|
||||
if (!detected) {
|
||||
context.background()
|
||||
.source(_.find(iD.layers, function(l) {
|
||||
return l.data.name === 'Bing aerial imagery';
|
||||
}));
|
||||
}
|
||||
|
||||
return editor;
|
||||
return d3.rebind(context, dispatch, 'on');
|
||||
};
|
||||
|
||||
iD.supported = function() {
|
||||
if (navigator.appName !== 'Microsoft Internet Explorer') {
|
||||
return true;
|
||||
iD.version = '0.0.0-alpha1';
|
||||
|
||||
iD.detect = function() {
|
||||
var browser = {};
|
||||
|
||||
var ua = navigator.userAgent,
|
||||
msie = new RegExp("MSIE ([0-9]{1,}[\\.0-9]{0,})");
|
||||
|
||||
if (msie.exec(ua) !== null) {
|
||||
var rv = parseFloat(RegExp.$1);
|
||||
browser.support = !(rv && rv < 9);
|
||||
} else {
|
||||
var ua = navigator.userAgent;
|
||||
var re = new RegExp("MSIE ([0-9]{1,}[\\.0-9]{0,})");
|
||||
if (re.exec(ua) !== null) {
|
||||
rv = parseFloat( RegExp.$1 );
|
||||
}
|
||||
if (rv && rv < 9) return false;
|
||||
else return true;
|
||||
browser.support = true;
|
||||
}
|
||||
|
||||
// Added due to incomplete svg style support. See #715
|
||||
browser.opera = ua.indexOf('Opera') >= 0;
|
||||
|
||||
browser.locale = navigator.language;
|
||||
|
||||
function nav(x) {
|
||||
return navigator.userAgent.indexOf(x) !== -1;
|
||||
}
|
||||
|
||||
if (nav('Win')) browser.os = 'win';
|
||||
else if (nav('Mac')) browser.os = 'mac';
|
||||
else if (nav('X11')) browser.os = 'linux';
|
||||
else if (nav('Linux')) browser.os = 'linux';
|
||||
else browser.os = 'win';
|
||||
|
||||
return browser;
|
||||
};
|
||||
|
||||
@@ -1,72 +1,66 @@
|
||||
iD.modes.AddArea = function() {
|
||||
iD.modes.AddArea = function(context) {
|
||||
var mode = {
|
||||
id: 'add-area',
|
||||
button: 'area',
|
||||
title: 'Area',
|
||||
description: 'Add parks, buildings, lakes, or other areas to the map.',
|
||||
key: 'a'
|
||||
title: t('modes.add_area.title'),
|
||||
description: t('modes.add_area.description'),
|
||||
key: '4'
|
||||
};
|
||||
|
||||
var behavior,
|
||||
var behavior = iD.behavior.AddWay(context)
|
||||
.on('start', start)
|
||||
.on('startFromWay', startFromWay)
|
||||
.on('startFromNode', startFromNode),
|
||||
defaultTags = {area: 'yes'};
|
||||
|
||||
function start(loc) {
|
||||
var graph = context.graph(),
|
||||
node = iD.Node({loc: loc}),
|
||||
way = iD.Way({tags: defaultTags});
|
||||
|
||||
context.perform(
|
||||
iD.actions.AddEntity(node),
|
||||
iD.actions.AddEntity(way),
|
||||
iD.actions.AddVertex(way.id, node.id),
|
||||
iD.actions.AddVertex(way.id, node.id));
|
||||
|
||||
context.enter(iD.modes.DrawArea(context, way.id, graph));
|
||||
}
|
||||
|
||||
function startFromWay(other, loc, index) {
|
||||
var graph = context.graph(),
|
||||
node = iD.Node({loc: loc}),
|
||||
way = iD.Way({tags: defaultTags});
|
||||
|
||||
context.perform(
|
||||
iD.actions.AddEntity(node),
|
||||
iD.actions.AddEntity(way),
|
||||
iD.actions.AddVertex(way.id, node.id),
|
||||
iD.actions.AddVertex(way.id, node.id),
|
||||
iD.actions.AddVertex(other.id, node.id, index));
|
||||
|
||||
context.enter(iD.modes.DrawArea(context, way.id, graph));
|
||||
}
|
||||
|
||||
function startFromNode(node) {
|
||||
var graph = context.graph(),
|
||||
way = iD.Way({tags: defaultTags});
|
||||
|
||||
context.perform(
|
||||
iD.actions.AddEntity(way),
|
||||
iD.actions.AddVertex(way.id, node.id),
|
||||
iD.actions.AddVertex(way.id, node.id));
|
||||
|
||||
context.enter(iD.modes.DrawArea(context, way.id, graph));
|
||||
}
|
||||
|
||||
mode.enter = function() {
|
||||
var map = mode.map,
|
||||
history = mode.history,
|
||||
controller = mode.controller;
|
||||
|
||||
function startFromNode(node) {
|
||||
var graph = history.graph(),
|
||||
way = iD.Way({tags: defaultTags});
|
||||
|
||||
history.perform(
|
||||
iD.actions.AddWay(way),
|
||||
iD.actions.AddWayNode(way.id, node.id),
|
||||
iD.actions.AddWayNode(way.id, node.id));
|
||||
|
||||
controller.enter(iD.modes.DrawArea(way.id, graph));
|
||||
}
|
||||
|
||||
function startFromWay(other, loc, index) {
|
||||
var graph = history.graph(),
|
||||
node = iD.Node({loc: loc}),
|
||||
way = iD.Way({tags: defaultTags});
|
||||
|
||||
history.perform(
|
||||
iD.actions.AddNode(node),
|
||||
iD.actions.AddWay(way),
|
||||
iD.actions.AddWayNode(way.id, node.id),
|
||||
iD.actions.AddWayNode(way.id, node.id),
|
||||
iD.actions.AddWayNode(other.id, node.id, index));
|
||||
|
||||
controller.enter(iD.modes.DrawArea(way.id, graph));
|
||||
}
|
||||
|
||||
function start(loc) {
|
||||
var graph = history.graph(),
|
||||
node = iD.Node({loc: loc}),
|
||||
way = iD.Way({tags: defaultTags});
|
||||
|
||||
history.perform(
|
||||
iD.actions.AddNode(node),
|
||||
iD.actions.AddWay(way),
|
||||
iD.actions.AddWayNode(way.id, node.id),
|
||||
iD.actions.AddWayNode(way.id, node.id));
|
||||
|
||||
controller.enter(iD.modes.DrawArea(way.id, graph));
|
||||
}
|
||||
|
||||
behavior = iD.behavior.AddWay(mode)
|
||||
.on('startFromNode', startFromNode)
|
||||
.on('startFromWay', startFromWay)
|
||||
.on('start', start);
|
||||
|
||||
mode.map.surface.call(behavior);
|
||||
mode.map.tail('Click on the map to start drawing an area, like a park, lake, or building.', true);
|
||||
context.install(behavior);
|
||||
context.tail(t('modes.add_area.tail'));
|
||||
};
|
||||
|
||||
mode.exit = function() {
|
||||
mode.map.surface.call(behavior.off);
|
||||
context.uninstall(behavior);
|
||||
};
|
||||
|
||||
return mode;
|
||||
|
||||
@@ -1,80 +1,74 @@
|
||||
iD.modes.AddLine = function() {
|
||||
iD.modes.AddLine = function(context) {
|
||||
var mode = {
|
||||
id: 'add-line',
|
||||
button: 'line',
|
||||
title: 'Line',
|
||||
description: 'Lines can be highways, streets, pedestrian paths, or even canals.',
|
||||
key: 'l'
|
||||
title: t('modes.add_line.title'),
|
||||
description: t('modes.add_line.description'),
|
||||
key: '3'
|
||||
};
|
||||
|
||||
var behavior,
|
||||
var behavior = iD.behavior.AddWay(context)
|
||||
.on('start', start)
|
||||
.on('startFromWay', startFromWay)
|
||||
.on('startFromNode', startFromNode),
|
||||
defaultTags = {highway: 'residential'};
|
||||
|
||||
function start(loc) {
|
||||
var graph = context.graph(),
|
||||
node = iD.Node({loc: loc}),
|
||||
way = iD.Way({tags: defaultTags});
|
||||
|
||||
context.perform(
|
||||
iD.actions.AddEntity(node),
|
||||
iD.actions.AddEntity(way),
|
||||
iD.actions.AddVertex(way.id, node.id));
|
||||
|
||||
context.enter(iD.modes.DrawLine(context, way.id, 'forward', graph));
|
||||
}
|
||||
|
||||
function startFromWay(other, loc, index) {
|
||||
var graph = context.graph(),
|
||||
node = iD.Node({loc: loc}),
|
||||
way = iD.Way({tags: defaultTags});
|
||||
|
||||
context.perform(
|
||||
iD.actions.AddEntity(node),
|
||||
iD.actions.AddEntity(way),
|
||||
iD.actions.AddVertex(way.id, node.id),
|
||||
iD.actions.AddVertex(other.id, node.id, index));
|
||||
|
||||
context.enter(iD.modes.DrawLine(context, way.id, 'forward', graph));
|
||||
}
|
||||
|
||||
function startFromNode(node) {
|
||||
var graph = context.graph(),
|
||||
parent = graph.parentWays(node)[0],
|
||||
isLine = parent && parent.geometry(graph) === 'line';
|
||||
|
||||
if (isLine && parent.first() === node.id) {
|
||||
context.enter(iD.modes.DrawLine(context, parent.id, 'backward', graph));
|
||||
|
||||
} else if (isLine && parent.last() === node.id) {
|
||||
context.enter(iD.modes.DrawLine(context, parent.id, 'forward', graph));
|
||||
|
||||
} else {
|
||||
var way = iD.Way({tags: defaultTags});
|
||||
|
||||
context.perform(
|
||||
iD.actions.AddEntity(way),
|
||||
iD.actions.AddVertex(way.id, node.id));
|
||||
|
||||
context.enter(iD.modes.DrawLine(context, way.id, 'forward', graph));
|
||||
}
|
||||
}
|
||||
|
||||
mode.enter = function() {
|
||||
var map = mode.map,
|
||||
history = mode.history,
|
||||
controller = mode.controller;
|
||||
|
||||
function startFromNode(node) {
|
||||
var graph = history.graph(),
|
||||
parent = graph.parentWays(node)[0],
|
||||
isLine = parent && parent.geometry(graph) === 'line';
|
||||
|
||||
if (isLine && parent.first() === node.id) {
|
||||
controller.enter(iD.modes.DrawLine(parent.id, 'backward', graph));
|
||||
|
||||
} else if (isLine && parent.last() === node.id) {
|
||||
controller.enter(iD.modes.DrawLine(parent.id, 'forward', graph));
|
||||
|
||||
} else {
|
||||
var way = iD.Way({tags: defaultTags});
|
||||
|
||||
history.perform(
|
||||
iD.actions.AddWay(way),
|
||||
iD.actions.AddWayNode(way.id, node.id));
|
||||
|
||||
controller.enter(iD.modes.DrawLine(way.id, 'forward', graph));
|
||||
}
|
||||
}
|
||||
|
||||
function startFromWay(other, loc, index) {
|
||||
var graph = history.graph(),
|
||||
node = iD.Node({loc: loc}),
|
||||
way = iD.Way({tags: defaultTags});
|
||||
|
||||
history.perform(
|
||||
iD.actions.AddNode(node),
|
||||
iD.actions.AddWay(way),
|
||||
iD.actions.AddWayNode(way.id, node.id),
|
||||
iD.actions.AddWayNode(other.id, node.id, index));
|
||||
|
||||
controller.enter(iD.modes.DrawLine(way.id, 'forward', graph));
|
||||
}
|
||||
|
||||
function start(loc) {
|
||||
var graph = history.graph(),
|
||||
node = iD.Node({loc: loc}),
|
||||
way = iD.Way({tags: defaultTags});
|
||||
|
||||
history.perform(
|
||||
iD.actions.AddNode(node),
|
||||
iD.actions.AddWay(way),
|
||||
iD.actions.AddWayNode(way.id, node.id));
|
||||
|
||||
controller.enter(iD.modes.DrawLine(way.id, 'forward', graph));
|
||||
}
|
||||
|
||||
behavior = iD.behavior.AddWay(mode)
|
||||
.on('startFromNode', startFromNode)
|
||||
.on('startFromWay', startFromWay)
|
||||
.on('start', start);
|
||||
|
||||
mode.map.surface.call(behavior);
|
||||
mode.map.tail('Click on the map to start drawing an road, path, or route.', true);
|
||||
context.install(behavior);
|
||||
context.tail(t('modes.add_line.tail'));
|
||||
};
|
||||
|
||||
mode.exit = function() {
|
||||
mode.map.surface.call(behavior.off);
|
||||
context.uninstall(behavior);
|
||||
};
|
||||
|
||||
return mode;
|
||||
|
||||
@@ -1,48 +1,48 @@
|
||||
iD.modes.AddPoint = function() {
|
||||
iD.modes.AddPoint = function(context) {
|
||||
var mode = {
|
||||
id: 'add-point',
|
||||
title: 'Point',
|
||||
description: 'Restaurants, monuments, and postal boxes are points.',
|
||||
key: 'p'
|
||||
title: t('modes.add_point.title'),
|
||||
description: t('modes.add_point.description'),
|
||||
key: '2'
|
||||
};
|
||||
|
||||
var behavior;
|
||||
var behavior = iD.behavior.Draw(context)
|
||||
.on('click', add)
|
||||
.on('clickWay', addWay)
|
||||
.on('clickNode', addNode)
|
||||
.on('cancel', cancel)
|
||||
.on('finish', cancel);
|
||||
|
||||
function add(loc) {
|
||||
var node = iD.Node({loc: loc});
|
||||
|
||||
context.perform(
|
||||
iD.actions.AddEntity(node),
|
||||
t('operations.add.annotation.point'));
|
||||
|
||||
context.enter(iD.modes.Select(context, [node.id], true));
|
||||
}
|
||||
|
||||
function addWay(way, loc, index) {
|
||||
add(loc);
|
||||
}
|
||||
|
||||
function addNode(node) {
|
||||
add(node.loc);
|
||||
}
|
||||
|
||||
function cancel() {
|
||||
context.enter(iD.modes.Browse(context));
|
||||
}
|
||||
|
||||
mode.enter = function() {
|
||||
var map = mode.map,
|
||||
surface = map.surface,
|
||||
history = mode.history,
|
||||
controller = mode.controller;
|
||||
|
||||
map.tail('Click on the map to add a point.', true);
|
||||
|
||||
function add() {
|
||||
var node = iD.Node({loc: map.mouseCoordinates()});
|
||||
|
||||
history.perform(
|
||||
iD.actions.AddNode(node),
|
||||
'added a point');
|
||||
|
||||
controller.enter(iD.modes.Select(node, true));
|
||||
}
|
||||
|
||||
function cancel() {
|
||||
controller.exit();
|
||||
}
|
||||
|
||||
behavior = iD.behavior.Draw()
|
||||
.on('add', add)
|
||||
.on('cancel', cancel)
|
||||
.on('finish', cancel)
|
||||
(surface);
|
||||
context.install(behavior);
|
||||
context.tail(t('modes.add_point.tail'));
|
||||
};
|
||||
|
||||
mode.exit = function() {
|
||||
var map = mode.map,
|
||||
surface = map.surface;
|
||||
|
||||
map.tail(false);
|
||||
behavior.off(surface);
|
||||
context.uninstall(behavior);
|
||||
context.tail(false);
|
||||
};
|
||||
|
||||
return mode;
|
||||
|
||||
@@ -1,42 +1,28 @@
|
||||
iD.modes.Browse = function() {
|
||||
iD.modes.Browse = function(context) {
|
||||
var mode = {
|
||||
button: 'browse',
|
||||
id: 'browse',
|
||||
title: 'Browse',
|
||||
description: 'Pan and zoom the map',
|
||||
key: 'b'
|
||||
title: t('modes.browse.title'),
|
||||
description: t('modes.browse.description'),
|
||||
key: '1'
|
||||
};
|
||||
|
||||
var behaviors;
|
||||
var behaviors = [
|
||||
iD.behavior.Hover(),
|
||||
iD.behavior.Select(context),
|
||||
iD.behavior.Lasso(context),
|
||||
iD.behavior.DragNode(context)];
|
||||
|
||||
mode.enter = function() {
|
||||
var surface = mode.map.surface;
|
||||
|
||||
behaviors = [
|
||||
iD.behavior.Hover(),
|
||||
iD.behavior.DragNode(mode),
|
||||
iD.behavior.DragMidpoint(mode)];
|
||||
|
||||
behaviors.forEach(function(behavior) {
|
||||
behavior(surface);
|
||||
});
|
||||
|
||||
surface.on('click.browse', function () {
|
||||
var datum = d3.select(d3.event.target).datum();
|
||||
if (datum instanceof iD.Entity) {
|
||||
mode.controller.enter(iD.modes.Select(datum));
|
||||
}
|
||||
context.install(behavior);
|
||||
});
|
||||
};
|
||||
|
||||
mode.exit = function() {
|
||||
var surface = mode.map.surface;
|
||||
|
||||
behaviors.forEach(function(behavior) {
|
||||
behavior.off(surface);
|
||||
context.uninstall(behavior);
|
||||
});
|
||||
|
||||
surface.on('click.browse', null);
|
||||
};
|
||||
|
||||
return mode;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
iD.modes.DrawArea = function(wayId, baseGraph) {
|
||||
iD.modes.DrawArea = function(context, wayId, baseGraph) {
|
||||
var mode = {
|
||||
button: 'area',
|
||||
id: 'draw-area'
|
||||
@@ -7,41 +7,28 @@ iD.modes.DrawArea = function(wayId, baseGraph) {
|
||||
var behavior;
|
||||
|
||||
mode.enter = function() {
|
||||
var way = mode.history.graph().entity(wayId),
|
||||
index = -1,
|
||||
var way = context.entity(wayId),
|
||||
headId = way.nodes[way.nodes.length - 2],
|
||||
tailId = way.first(),
|
||||
annotation = way.isDegenerate() ? 'started an area' : 'continued an area';
|
||||
tailId = way.first();
|
||||
|
||||
function addHeadTail() {
|
||||
behavior.finish();
|
||||
}
|
||||
behavior = iD.behavior.DrawWay(context, wayId, -1, mode, baseGraph);
|
||||
|
||||
function addNode(node) {
|
||||
behavior.addNode(node, annotation);
|
||||
}
|
||||
var addNode = behavior.addNode;
|
||||
|
||||
function addWay(way, loc, index) {
|
||||
behavior.addWay(way, loc, index, annotation);
|
||||
}
|
||||
behavior.addNode = function(node) {
|
||||
if (node.id === headId || node.id === tailId) {
|
||||
behavior.finish();
|
||||
} else {
|
||||
addNode(node);
|
||||
}
|
||||
};
|
||||
|
||||
function add(loc) {
|
||||
behavior.add(loc, annotation);
|
||||
}
|
||||
|
||||
behavior = iD.behavior.DrawWay(wayId, headId, tailId, index, mode, baseGraph)
|
||||
.on('addHead', addHeadTail)
|
||||
.on('addTail', addHeadTail)
|
||||
.on('addNode', addNode)
|
||||
.on('addWay', addWay)
|
||||
.on('add', add);
|
||||
|
||||
mode.map.surface.call(behavior);
|
||||
mode.map.tail('Click to add points to your area. Click the first point to finish the area.', true);
|
||||
context.install(behavior);
|
||||
context.tail(t('modes.draw_area.tail'));
|
||||
};
|
||||
|
||||
mode.exit = function() {
|
||||
mode.map.surface.call(behavior.off);
|
||||
context.uninstall(behavior);
|
||||
};
|
||||
|
||||
return mode;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
iD.modes.DrawLine = function(wayId, direction, baseGraph) {
|
||||
iD.modes.DrawLine = function(context, wayId, direction, baseGraph) {
|
||||
var mode = {
|
||||
button: 'line',
|
||||
id: 'draw-line'
|
||||
@@ -7,52 +7,28 @@ iD.modes.DrawLine = function(wayId, direction, baseGraph) {
|
||||
var behavior;
|
||||
|
||||
mode.enter = function() {
|
||||
var way = mode.history.graph().entity(wayId),
|
||||
var way = context.entity(wayId),
|
||||
index = (direction === 'forward') ? undefined : 0,
|
||||
headId = (direction === 'forward') ? way.last() : way.first(),
|
||||
tailId = (direction === 'forward') ? way.first() : way.last(),
|
||||
annotation = way.isDegenerate() ? 'started a line' : 'continued a line';
|
||||
headId = (direction === 'forward') ? way.last() : way.first();
|
||||
|
||||
function addHead() {
|
||||
behavior.finish();
|
||||
}
|
||||
behavior = iD.behavior.DrawWay(context, wayId, index, mode, baseGraph);
|
||||
|
||||
function addTail(node) {
|
||||
// connect the way in a loop
|
||||
if (way.nodes.length > 2) {
|
||||
behavior.addNode(node, annotation);
|
||||
var addNode = behavior.addNode;
|
||||
|
||||
behavior.addNode = function(node) {
|
||||
if (node.id === headId) {
|
||||
behavior.finish();
|
||||
} else {
|
||||
behavior.cancel();
|
||||
addNode(node);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function addNode(node) {
|
||||
behavior.addNode(node, annotation);
|
||||
}
|
||||
|
||||
function addWay(way, loc, index) {
|
||||
behavior.addWay(way, loc, index, annotation);
|
||||
}
|
||||
|
||||
function add(loc) {
|
||||
behavior.add(loc, annotation);
|
||||
}
|
||||
|
||||
behavior = iD.behavior.DrawWay(wayId, headId, tailId, index, mode, baseGraph)
|
||||
.on('addHead', addHead)
|
||||
.on('addTail', addTail)
|
||||
.on('addNode', addNode)
|
||||
.on('addWay', addWay)
|
||||
.on('add', add);
|
||||
|
||||
mode.map.surface.call(behavior);
|
||||
mode.map.tail('Click to add more points to the line. ' +
|
||||
'Click on other lines to connect to them, and double-click to ' +
|
||||
'end the line.', true);
|
||||
context.install(behavior);
|
||||
context.tail(t('modes.draw_line.tail'));
|
||||
};
|
||||
|
||||
mode.exit = function() {
|
||||
mode.map.surface.call(behavior.off);
|
||||
context.uninstall(behavior);
|
||||
};
|
||||
|
||||
return mode;
|
||||
|
||||
@@ -1,51 +1,88 @@
|
||||
iD.modes.MoveWay = function(wayId) {
|
||||
iD.modes.MoveWay = function(context, wayId) {
|
||||
var mode = {
|
||||
id: 'move-way'
|
||||
id: 'move-way',
|
||||
button: 'browse'
|
||||
};
|
||||
|
||||
var keybinding = d3.keybinding('move-way');
|
||||
|
||||
mode.enter = function() {
|
||||
var map = mode.map,
|
||||
history = mode.history,
|
||||
graph = history.graph(),
|
||||
selection = map.surface,
|
||||
controller = mode.controller,
|
||||
projection = map.projection;
|
||||
var origin = context.map().mouseCoordinates(),
|
||||
nudgeInterval,
|
||||
annotation = t('operations.move.annotation.' + context.geometry(wayId));
|
||||
|
||||
var way = graph.entity(wayId),
|
||||
origin = d3.mouse(selection.node());
|
||||
// If intiated via keyboard
|
||||
if (!origin[0] && !origin[1]) origin = null;
|
||||
|
||||
history.perform(
|
||||
context.perform(
|
||||
iD.actions.Noop(),
|
||||
'moved a way');
|
||||
annotation);
|
||||
|
||||
function edge(point, size) {
|
||||
var pad = [30, 100, 30, 100];
|
||||
if (point[0] > size[0] - pad[0]) return [-10, 0];
|
||||
else if (point[0] < pad[2]) return [10, 0];
|
||||
else if (point[1] > size[1] - pad[1]) return [0, -10];
|
||||
else if (point[1] < pad[3]) return [0, 10];
|
||||
return null;
|
||||
}
|
||||
|
||||
function startNudge(nudge) {
|
||||
if (nudgeInterval) window.clearInterval(nudgeInterval);
|
||||
nudgeInterval = window.setInterval(function() {
|
||||
context.pan(nudge);
|
||||
}, 50);
|
||||
}
|
||||
|
||||
function stopNudge() {
|
||||
if (nudgeInterval) window.clearInterval(nudgeInterval);
|
||||
nudgeInterval = null;
|
||||
}
|
||||
|
||||
function point() {
|
||||
return d3.mouse(context.map().surface.node());
|
||||
}
|
||||
|
||||
function move() {
|
||||
var p = d3.mouse(selection.node()),
|
||||
delta = [p[0] - origin[0],
|
||||
p[1] - origin[1]];
|
||||
var p = point();
|
||||
|
||||
origin = p;
|
||||
var delta = origin ?
|
||||
[p[0] - context.projection(origin)[0],
|
||||
p[1] - context.projection(origin)[1]] :
|
||||
[0, 0];
|
||||
|
||||
history.replace(
|
||||
iD.actions.MoveWay(wayId, delta, projection),
|
||||
'moved a way');
|
||||
var nudge = edge(p, context.map().size());
|
||||
if (nudge) startNudge(nudge);
|
||||
else stopNudge();
|
||||
|
||||
origin = context.map().mouseCoordinates();
|
||||
|
||||
context.replace(
|
||||
iD.actions.MoveWay(wayId, delta, context.projection),
|
||||
annotation);
|
||||
}
|
||||
|
||||
function finish() {
|
||||
d3.event.stopPropagation();
|
||||
controller.enter(iD.modes.Select(way, true));
|
||||
context.enter(iD.modes.Select(context, [wayId], true));
|
||||
}
|
||||
|
||||
function cancel() {
|
||||
history.pop();
|
||||
controller.enter(iD.modes.Select(way, true));
|
||||
context.pop();
|
||||
context.enter(iD.modes.Select(context, [wayId], true));
|
||||
}
|
||||
|
||||
selection
|
||||
function undone() {
|
||||
context.enter(iD.modes.Browse(context));
|
||||
}
|
||||
|
||||
context.surface()
|
||||
.on('mousemove.move-way', move)
|
||||
.on('click.move-way', finish);
|
||||
|
||||
context.history()
|
||||
.on('undone.move-way', undone);
|
||||
|
||||
keybinding
|
||||
.on('⎋', cancel)
|
||||
.on('↩', finish);
|
||||
@@ -55,13 +92,13 @@ iD.modes.MoveWay = function(wayId) {
|
||||
};
|
||||
|
||||
mode.exit = function() {
|
||||
var map = mode.map,
|
||||
selection = map.surface;
|
||||
|
||||
selection
|
||||
context.surface()
|
||||
.on('mousemove.move-way', null)
|
||||
.on('click.move-way', null);
|
||||
|
||||
context.history()
|
||||
.on('undone.move-way', null);
|
||||
|
||||
keybinding.off();
|
||||
};
|
||||
|
||||
|
||||
@@ -1,164 +1,217 @@
|
||||
iD.modes.Select = function(entity, initial) {
|
||||
iD.modes.Select = function(context, selection, initial) {
|
||||
var mode = {
|
||||
id: 'select',
|
||||
button: 'browse',
|
||||
entity: entity
|
||||
button: 'browse'
|
||||
};
|
||||
|
||||
var inspector = iD.ui.inspector().initial(!!initial),
|
||||
var inspector = iD.ui.Inspector().initial(!!initial),
|
||||
keybinding = d3.keybinding('select'),
|
||||
behaviors,
|
||||
radialMenu;
|
||||
|
||||
function remove() {
|
||||
if (entity.type === 'way') {
|
||||
mode.history.perform(
|
||||
iD.actions.DeleteWay(entity.id),
|
||||
'deleted a way');
|
||||
} else if (entity.type === 'node') {
|
||||
mode.history.perform(
|
||||
iD.actions.DeleteNode(entity.id),
|
||||
'deleted a node');
|
||||
}
|
||||
|
||||
mode.controller.exit();
|
||||
}
|
||||
|
||||
function changeTags(d, tags) {
|
||||
if (!_.isEqual(entity.tags, tags)) {
|
||||
mode.history.perform(
|
||||
iD.actions.ChangeEntityTags(d.id, tags),
|
||||
'changed tags');
|
||||
}
|
||||
}
|
||||
|
||||
mode.enter = function() {
|
||||
var map = mode.map,
|
||||
graph = map.history().graph(),
|
||||
history = map.history(),
|
||||
surface = mode.map.surface;
|
||||
|
||||
inspector.graph(graph);
|
||||
|
||||
timeout = null,
|
||||
behaviors = [
|
||||
iD.behavior.Hover(),
|
||||
iD.behavior.DragNode(mode),
|
||||
iD.behavior.DragMidpoint(mode)];
|
||||
iD.behavior.Select(context),
|
||||
iD.behavior.Lasso(context),
|
||||
iD.behavior.DragNode(context)],
|
||||
radialMenu;
|
||||
|
||||
function changeTags(d, tags) {
|
||||
if (!_.isEqual(singular().tags, tags)) {
|
||||
context.perform(
|
||||
iD.actions.ChangeTags(d.id, tags),
|
||||
t('operations.change_tags.annotation'));
|
||||
}
|
||||
}
|
||||
|
||||
function singular() {
|
||||
if (selection.length === 1) {
|
||||
return context.entity(selection[0]);
|
||||
}
|
||||
}
|
||||
|
||||
function positionMenu() {
|
||||
var entity = singular();
|
||||
|
||||
if (entity && entity.type === 'node') {
|
||||
radialMenu.center(context.projection(entity.loc));
|
||||
} else {
|
||||
radialMenu.center(d3.mouse(context.surface().node()));
|
||||
}
|
||||
}
|
||||
|
||||
function showMenu() {
|
||||
context.surface()
|
||||
.call(radialMenu.close)
|
||||
.call(radialMenu);
|
||||
}
|
||||
|
||||
mode.selection = function() {
|
||||
return selection;
|
||||
};
|
||||
|
||||
mode.reselect = function() {
|
||||
positionMenu();
|
||||
showMenu();
|
||||
};
|
||||
|
||||
mode.enter = function() {
|
||||
var entity = singular();
|
||||
|
||||
behaviors.forEach(function(behavior) {
|
||||
behavior(surface);
|
||||
context.install(behavior);
|
||||
});
|
||||
|
||||
var operations = _.without(d3.values(iD.operations), iD.operations.Delete)
|
||||
.map(function(o) { return o(selection, context); })
|
||||
.filter(function(o) { return o.available(); });
|
||||
operations.unshift(iD.operations.Delete(selection, context));
|
||||
|
||||
keybinding.on('⎋', function() {
|
||||
context.enter(iD.modes.Browse(context));
|
||||
});
|
||||
|
||||
operations.forEach(function(operation) {
|
||||
keybinding.on(operation.key, function() {
|
||||
if (operation.enabled()) {
|
||||
operation();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
var q = iD.util.stringQs(location.hash.substring(1));
|
||||
location.replace('#' + iD.util.qsString(_.assign(q, {
|
||||
id: entity.id
|
||||
id: selection.join(',')
|
||||
}), true));
|
||||
|
||||
d3.select('.inspector-wrap')
|
||||
.style('display', 'block')
|
||||
.style('opacity', 1)
|
||||
.datum(entity)
|
||||
.call(inspector);
|
||||
if (entity) {
|
||||
inspector.context(context);
|
||||
|
||||
if (d3.event) {
|
||||
// Pan the map if the clicked feature intersects with the position
|
||||
// of the inspector
|
||||
var inspector_size = d3.select('.inspector-wrap').size(),
|
||||
map_size = mode.map.size(),
|
||||
offset = 50,
|
||||
shift_left = d3.event.x - map_size[0] + inspector_size[0] + offset,
|
||||
center = (map_size[0] / 2) + shift_left + offset;
|
||||
context.container()
|
||||
.select('.inspector-wrap')
|
||||
.style('display', 'block')
|
||||
.style('opacity', 1)
|
||||
.datum(entity)
|
||||
.call(inspector);
|
||||
|
||||
if (shift_left > 0 && inspector_size[1] > d3.event.y) {
|
||||
mode.map.centerEase(mode.map.projection.invert([center, map_size[1]/2]));
|
||||
if (d3.event) {
|
||||
// Pan the map if the clicked feature intersects with the position
|
||||
// of the inspector
|
||||
var inspector_size = context.container().select('.inspector-wrap').size(),
|
||||
map_size = context.map().size(),
|
||||
offset = 50,
|
||||
shift_left = d3.event.clientX - map_size[0] + inspector_size[0] + offset,
|
||||
center = (map_size[0] / 2) + shift_left + offset;
|
||||
|
||||
if (shift_left > 0 && inspector_size[1] > d3.event.clientY) {
|
||||
context.map().centerEase(context.projection.invert([center, map_size[1]/2]));
|
||||
}
|
||||
}
|
||||
|
||||
inspector
|
||||
.on('changeTags', changeTags)
|
||||
.on('close', function() { context.enter(iD.modes.Browse(context)); });
|
||||
}
|
||||
|
||||
inspector
|
||||
.on('changeTags', changeTags)
|
||||
.on('close', function() { mode.controller.exit(); });
|
||||
context.history().on('change.select', function() {
|
||||
context.surface().call(radialMenu.close);
|
||||
|
||||
history.on('change.select', function() {
|
||||
// Exit mode if selected entity gets undone
|
||||
var old = entity;
|
||||
entity = history.graph().entity(entity.id);
|
||||
if (!entity) {
|
||||
mode.controller.enter(iD.modes.Browse());
|
||||
} else if(!_.isEqual(entity.tags, old.tags)) {
|
||||
inspector.tags(entity.tags);
|
||||
if (_.any(selection, function(id) { return !context.entity(id); })) {
|
||||
// Exit mode if selected entity gets undone
|
||||
context.enter(iD.modes.Browse(context));
|
||||
|
||||
} else if (entity) {
|
||||
var newEntity = context.entity(selection[0]);
|
||||
if (!_.isEqual(entity.tags, newEntity.tags)) {
|
||||
inspector.tags(newEntity.tags);
|
||||
}
|
||||
}
|
||||
|
||||
surface.call(radialMenu.close);
|
||||
});
|
||||
|
||||
map.on('move.select', function() {
|
||||
surface.call(radialMenu.close);
|
||||
context.map().on('move.select', function() {
|
||||
context.surface().call(radialMenu.close);
|
||||
});
|
||||
|
||||
function click() {
|
||||
var datum = d3.select(d3.event.target).datum();
|
||||
if (datum instanceof iD.Entity) {
|
||||
mode.controller.enter(iD.modes.Select(datum));
|
||||
} else {
|
||||
mode.controller.enter(iD.modes.Browse());
|
||||
}
|
||||
}
|
||||
|
||||
function dblclick() {
|
||||
var selection = d3.select(d3.event.target),
|
||||
datum = selection.datum();
|
||||
var target = d3.select(d3.event.target),
|
||||
datum = target.datum();
|
||||
|
||||
if (datum instanceof iD.Way && !selection.classed('fill')) {
|
||||
if (datum instanceof iD.Way && !target.classed('fill')) {
|
||||
var choice = iD.geo.chooseIndex(datum,
|
||||
d3.mouse(mode.map.surface.node()), mode.map),
|
||||
d3.mouse(context.surface().node()), context),
|
||||
node = iD.Node({ loc: choice.loc });
|
||||
|
||||
history.perform(
|
||||
iD.actions.AddNode(node),
|
||||
iD.actions.AddWayNode(datum.id, node.id, choice.index),
|
||||
'added a point to a road');
|
||||
var prev = datum.nodes[choice.index - 1],
|
||||
next = datum.nodes[choice.index],
|
||||
prevParents = context.graph().parentWays({ id: prev }),
|
||||
ways = [];
|
||||
|
||||
|
||||
for (var i = 0; i < prevParents.length; i++) {
|
||||
var p = prevParents[i];
|
||||
for (var k = 0; k < p.nodes.length; k++) {
|
||||
if (p.nodes[k] === prev) {
|
||||
if (p.nodes[k-1] === next) {
|
||||
ways.push({ id: p.id, index: k});
|
||||
break;
|
||||
} else if (p.nodes[k+1] === next) {
|
||||
ways.push({ id: p.id, index: k+1});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
context.perform(iD.actions.AddEntity(node),
|
||||
iD.actions.AddMidpoint({ ways: ways, loc: node.loc }, node),
|
||||
t('operations.add.annotation.vertex'));
|
||||
|
||||
d3.event.preventDefault();
|
||||
d3.event.stopPropagation();
|
||||
}
|
||||
}
|
||||
|
||||
surface.on('click.select', click)
|
||||
.on('dblclick.select', dblclick);
|
||||
|
||||
keybinding.on('⌫', remove);
|
||||
function selected(entity) {
|
||||
if (!entity) return false;
|
||||
if (selection.indexOf(entity.id) >= 0) return true;
|
||||
return d3.select(this).classed('stroke') &&
|
||||
_.any(context.graph().parentRelations(entity), function(parent) {
|
||||
return selection.indexOf(parent.id) >= 0;
|
||||
});
|
||||
}
|
||||
|
||||
d3.select(document)
|
||||
.call(keybinding);
|
||||
|
||||
surface.selectAll("*")
|
||||
.filter(function (d) {
|
||||
return d && entity && d.id === entity.id;
|
||||
})
|
||||
context.surface()
|
||||
.selectAll("*")
|
||||
.filter(selected)
|
||||
.classed('selected', true);
|
||||
|
||||
radialMenu = iD.ui.RadialMenu(entity, mode);
|
||||
radialMenu = iD.ui.RadialMenu(operations);
|
||||
var show = d3.event && !initial;
|
||||
|
||||
if (d3.event && !initial) {
|
||||
var loc = map.mouseCoordinates();
|
||||
if (show) {
|
||||
positionMenu();
|
||||
}
|
||||
|
||||
if (entity.type === 'node') {
|
||||
loc = entity.loc;
|
||||
timeout = window.setTimeout(function() {
|
||||
if (show) {
|
||||
showMenu();
|
||||
}
|
||||
|
||||
surface.call(radialMenu, map.projection(loc));
|
||||
}
|
||||
context.surface()
|
||||
.on('dblclick.select', dblclick);
|
||||
}, 200);
|
||||
};
|
||||
|
||||
mode.exit = function () {
|
||||
var surface = mode.map.surface,
|
||||
history = mode.history;
|
||||
|
||||
if (entity) {
|
||||
changeTags(entity, inspector.tags());
|
||||
mode.exit = function() {
|
||||
if (singular()) {
|
||||
changeTags(singular(), inspector.tags());
|
||||
}
|
||||
|
||||
d3.select('.inspector-wrap')
|
||||
if (timeout) window.clearTimeout(timeout);
|
||||
|
||||
context.container()
|
||||
.select('.inspector-wrap')
|
||||
.style('display', 'none')
|
||||
.html('');
|
||||
|
||||
@@ -167,7 +220,7 @@ iD.modes.Select = function(entity, initial) {
|
||||
d3.selectAll('div.typeahead').remove();
|
||||
|
||||
behaviors.forEach(function(behavior) {
|
||||
behavior.off(surface);
|
||||
context.uninstall(behavior);
|
||||
});
|
||||
|
||||
var q = iD.util.stringQs(location.hash.substring(1));
|
||||
@@ -175,15 +228,14 @@ iD.modes.Select = function(entity, initial) {
|
||||
|
||||
keybinding.off();
|
||||
|
||||
surface.on('click.select', null)
|
||||
.on('dblclick.select', null);
|
||||
context.history()
|
||||
.on('change.select', null);
|
||||
|
||||
history.on('change.select', null);
|
||||
|
||||
surface.selectAll(".selected")
|
||||
context.surface()
|
||||
.call(radialMenu.close)
|
||||
.on('dblclick.select', null)
|
||||
.selectAll(".selected")
|
||||
.classed('selected', false);
|
||||
|
||||
surface.call(radialMenu.close);
|
||||
};
|
||||
|
||||
return mode;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
iD.OAuth = function() {
|
||||
iD.OAuth = function(context) {
|
||||
var baseurl = 'http://www.openstreetmap.org',
|
||||
o = {},
|
||||
keys,
|
||||
@@ -6,10 +6,6 @@ iD.OAuth = function() {
|
||||
|
||||
function keyclean(x) { return x.replace(/\W/g, ''); }
|
||||
|
||||
if (token('oauth_token')) {
|
||||
o.oauth_token = token('oauth_token');
|
||||
}
|
||||
|
||||
function timenonce(o) {
|
||||
o.oauth_timestamp = ohauth.timestamp();
|
||||
o.oauth_nonce = ohauth.nonce();
|
||||
@@ -17,11 +13,12 @@ iD.OAuth = function() {
|
||||
}
|
||||
|
||||
// token getter/setter, namespaced to the current `apibase` value.
|
||||
function token(k, x) {
|
||||
if (arguments.length == 2) {
|
||||
localStorage[keyclean(baseurl) + k] = x;
|
||||
}
|
||||
return localStorage[keyclean(baseurl) + k];
|
||||
function token() {
|
||||
return context.storage.apply(context, arguments);
|
||||
}
|
||||
|
||||
if (token('oauth_token')) {
|
||||
o.oauth_token = token('oauth_token');
|
||||
}
|
||||
|
||||
oauth.authenticated = function() {
|
||||
@@ -63,7 +60,7 @@ iD.OAuth = function() {
|
||||
o.oauth_signature = ohauth.signature(oauth_secret, '',
|
||||
ohauth.baseString('POST', url, o));
|
||||
|
||||
var l = iD.ui.loading('contacting openstreetmap...');
|
||||
var l = iD.ui.loading(context.container(), 'contacting openstreetmap...');
|
||||
|
||||
// it would make more sense to have this code within the callback
|
||||
// to oauth.xhr below. however, it needs to be directly within a
|
||||
@@ -112,7 +109,7 @@ iD.OAuth = function() {
|
||||
var request_token_secret = token('oauth_request_token_secret');
|
||||
o.oauth_signature = ohauth.signature(oauth_secret, request_token_secret,
|
||||
ohauth.baseString('POST', url, o));
|
||||
var l = iD.ui.loading('contacting openstreetmap...');
|
||||
var l = iD.ui.loading(context.container(), 'contacting openstreetmap...');
|
||||
|
||||
function accessTokenDone(err, xhr) {
|
||||
if (err) callback(err);
|
||||
|
||||
@@ -1 +1 @@
|
||||
iD.operations = {}
|
||||
iD.operations = {};
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
iD.operations.Circular = function(entityId, mode) {
|
||||
var action = iD.actions.Circular(entityId, mode.map);
|
||||
|
||||
var operation = function(history) {
|
||||
var graph = history.graph(),
|
||||
entity = graph.entity(entityId),
|
||||
geometry = entity.geometry(graph);
|
||||
|
||||
if (geometry === 'line') {
|
||||
history.perform(
|
||||
action,
|
||||
'made a line circular');
|
||||
|
||||
} else if (geometry === 'area') {
|
||||
history.perform(
|
||||
action,
|
||||
'made an area circular');
|
||||
}
|
||||
};
|
||||
|
||||
operation.available = function(graph) {
|
||||
var entity = graph.entity(entityId);
|
||||
return entity.geometry(graph) === 'area' || entity.geometry(graph) === 'line';
|
||||
};
|
||||
|
||||
operation.enabled = function(graph) {
|
||||
return action.enabled(graph);
|
||||
};
|
||||
|
||||
operation.id = "circular";
|
||||
operation.title = "Circular";
|
||||
|
||||
return operation;
|
||||
};
|
||||
@@ -0,0 +1,25 @@
|
||||
iD.operations.Circularize = function(selection, context) {
|
||||
var entityId = selection[0],
|
||||
action = iD.actions.Circularize(entityId, context.projection);
|
||||
|
||||
var operation = function() {
|
||||
var annotation = t('operations.circularize.annotation.' + context.geometry(entityId));
|
||||
context.perform(action, annotation);
|
||||
};
|
||||
|
||||
operation.available = function() {
|
||||
return selection.length === 1 &&
|
||||
context.entity(entityId).type === 'way';
|
||||
};
|
||||
|
||||
operation.enabled = function() {
|
||||
return action.enabled(context.graph());
|
||||
};
|
||||
|
||||
operation.id = "circularize";
|
||||
operation.key = t('operations.circularize.key');
|
||||
operation.title = t('operations.circularize.title');
|
||||
operation.description = t('operations.circularize.description');
|
||||
|
||||
return operation;
|
||||
};
|
||||
@@ -1,34 +1,20 @@
|
||||
iD.operations.Delete = function(entityId) {
|
||||
var operation = function(history) {
|
||||
var graph = history.graph(),
|
||||
entity = graph.entity(entityId),
|
||||
geometry = entity.geometry(graph);
|
||||
iD.operations.Delete = function(selection, context) {
|
||||
var operation = function() {
|
||||
var annotation;
|
||||
|
||||
if (geometry === 'vertex') {
|
||||
history.perform(
|
||||
iD.actions.DeleteNode(entityId),
|
||||
'deleted a vertex');
|
||||
|
||||
} else if (geometry === 'point') {
|
||||
history.perform(
|
||||
iD.actions.DeleteNode(entityId),
|
||||
'deleted a point');
|
||||
|
||||
} else if (geometry === 'line') {
|
||||
history.perform(
|
||||
iD.actions.DeleteWay(entityId),
|
||||
'deleted a line');
|
||||
|
||||
} else if (geometry === 'area') {
|
||||
history.perform(
|
||||
iD.actions.DeleteWay(entityId),
|
||||
'deleted an area');
|
||||
if (selection.length === 1) {
|
||||
annotation = t('operations.delete.annotation.' + context.geometry(selection[0]));
|
||||
} else {
|
||||
annotation = t('operations.delete.annotation.multiple', {n: selection.length});
|
||||
}
|
||||
|
||||
context.perform(
|
||||
iD.actions.DeleteMultiple(selection),
|
||||
annotation);
|
||||
};
|
||||
|
||||
operation.available = function(graph) {
|
||||
var entity = graph.entity(entityId);
|
||||
return _.contains(['vertex', 'point', 'line', 'area'], entity.geometry(graph));
|
||||
operation.available = function() {
|
||||
return true;
|
||||
};
|
||||
|
||||
operation.enabled = function() {
|
||||
@@ -36,7 +22,9 @@ iD.operations.Delete = function(entityId) {
|
||||
};
|
||||
|
||||
operation.id = "delete";
|
||||
operation.title = "Delete";
|
||||
operation.key = t('operations.delete.key');
|
||||
operation.title = t('operations.delete.title');
|
||||
operation.description = t('operations.delete.description');
|
||||
|
||||
return operation;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
iD.operations.Disconnect = function(selection, context) {
|
||||
var entityId = selection[0],
|
||||
action = iD.actions.Disconnect(entityId);
|
||||
|
||||
var operation = function() {
|
||||
context.perform(action, t('operations.disconnect.annotation'));
|
||||
};
|
||||
|
||||
operation.available = function() {
|
||||
return selection.length === 1 &&
|
||||
context.geometry(entityId) === 'vertex';
|
||||
};
|
||||
|
||||
operation.enabled = function() {
|
||||
return action.enabled(context.graph());
|
||||
};
|
||||
|
||||
operation.id = "disconnect";
|
||||
operation.key = t('operations.disconnect.key');
|
||||
operation.title = t('operations.disconnect.title');
|
||||
operation.description = t('operations.disconnect.description');
|
||||
|
||||
return operation;
|
||||
};
|
||||
@@ -0,0 +1,34 @@
|
||||
iD.operations.Merge = function(selection, context) {
|
||||
var join = iD.actions.Join(selection),
|
||||
merge = iD.actions.Merge(selection);
|
||||
|
||||
var operation = function() {
|
||||
var annotation = t('operations.merge.annotation', {n: selection.length}),
|
||||
action;
|
||||
|
||||
if (join.enabled(context.graph())) {
|
||||
action = join;
|
||||
} else {
|
||||
action = merge;
|
||||
}
|
||||
|
||||
var difference = context.perform(action, annotation);
|
||||
context.enter(iD.modes.Select(context, difference.extantIDs()));
|
||||
};
|
||||
|
||||
operation.available = function() {
|
||||
return selection.length >= 2;
|
||||
};
|
||||
|
||||
operation.enabled = function() {
|
||||
return join.enabled(context.graph()) ||
|
||||
merge.enabled(context.graph());
|
||||
};
|
||||
|
||||
operation.id = "merge";
|
||||
operation.key = t('operations.merge.key');
|
||||
operation.title = t('operations.merge.title');
|
||||
operation.description = t('operations.merge.description');
|
||||
|
||||
return operation;
|
||||
};
|
||||
@@ -1,10 +1,13 @@
|
||||
iD.operations.Move = function(entityId, mode) {
|
||||
iD.operations.Move = function(selection, context) {
|
||||
var entityId = selection[0];
|
||||
|
||||
var operation = function() {
|
||||
mode.controller.enter(iD.modes.MoveWay(entityId));
|
||||
context.enter(iD.modes.MoveWay(context, entityId));
|
||||
};
|
||||
|
||||
operation.available = function(graph) {
|
||||
return graph.entity(entityId).type === 'way';
|
||||
operation.available = function() {
|
||||
return selection.length === 1 &&
|
||||
context.entity(entityId).type === 'way';
|
||||
};
|
||||
|
||||
operation.enabled = function() {
|
||||
@@ -12,7 +15,9 @@ iD.operations.Move = function(entityId, mode) {
|
||||
};
|
||||
|
||||
operation.id = "move";
|
||||
operation.title = "Move";
|
||||
operation.key = t('operations.move.key');
|
||||
operation.title = t('operations.move.title');
|
||||
operation.description = t('operations.move.description');
|
||||
|
||||
return operation;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
iD.operations.Orthogonalize = function(selection, context) {
|
||||
var entityId = selection[0],
|
||||
action = iD.actions.Orthogonalize(entityId, context.projection);
|
||||
|
||||
var operation = function() {
|
||||
var annotation = t('operations.orthogonalize.annotation.' + context.geometry(entityId));
|
||||
context.perform(action, annotation);
|
||||
};
|
||||
|
||||
operation.available = function() {
|
||||
return selection.length === 1 &&
|
||||
context.entity(entityId).type === 'way';
|
||||
};
|
||||
|
||||
operation.enabled = function() {
|
||||
return action.enabled(context.graph());
|
||||
};
|
||||
|
||||
operation.id = "orthogonalize";
|
||||
operation.key = t('operations.orthogonalize.key');
|
||||
operation.title = t('operations.orthogonalize.title');
|
||||
operation.description = t('operations.orthogonalize.description');
|
||||
|
||||
return operation;
|
||||
};
|
||||
@@ -1,13 +1,15 @@
|
||||
iD.operations.Reverse = function(entityId) {
|
||||
var operation = function(history) {
|
||||
history.perform(
|
||||
iD.actions.ReverseWay(entityId),
|
||||
'reversed a line');
|
||||
iD.operations.Reverse = function(selection, context) {
|
||||
var entityId = selection[0];
|
||||
|
||||
var operation = function() {
|
||||
context.perform(
|
||||
iD.actions.Reverse(entityId),
|
||||
t('operations.reverse.annotation'));
|
||||
};
|
||||
|
||||
operation.available = function(graph) {
|
||||
var entity = graph.entity(entityId);
|
||||
return entity.geometry(graph) === 'line';
|
||||
operation.available = function() {
|
||||
return selection.length === 1 &&
|
||||
context.geometry(entityId) === 'line';
|
||||
};
|
||||
|
||||
operation.enabled = function() {
|
||||
@@ -15,7 +17,9 @@ iD.operations.Reverse = function(entityId) {
|
||||
};
|
||||
|
||||
operation.id = "reverse";
|
||||
operation.title = "Reverse";
|
||||
operation.key = t('operations.reverse.key');
|
||||
operation.title = t('operations.reverse.title');
|
||||
operation.description = t('operations.reverse.description');
|
||||
|
||||
return operation;
|
||||
};
|
||||
|
||||
@@ -1,21 +1,26 @@
|
||||
iD.operations.Split = function(entityId) {
|
||||
var action = iD.actions.SplitWay(entityId);
|
||||
iD.operations.Split = function(selection, context) {
|
||||
var entityId = selection[0],
|
||||
action = iD.actions.Split(entityId);
|
||||
|
||||
var operation = function(history) {
|
||||
history.perform(action, 'split a way');
|
||||
var operation = function() {
|
||||
var annotation = t('operations.split.annotation'),
|
||||
difference = context.perform(action, annotation);
|
||||
context.enter(iD.modes.Select(context, difference.extantIDs()));
|
||||
};
|
||||
|
||||
operation.available = function(graph) {
|
||||
var entity = graph.entity(entityId);
|
||||
return entity.geometry(graph) === 'vertex';
|
||||
operation.available = function() {
|
||||
return selection.length === 1 &&
|
||||
context.geometry(entityId) === 'vertex';
|
||||
};
|
||||
|
||||
operation.enabled = function(graph) {
|
||||
return action.enabled(graph);
|
||||
operation.enabled = function() {
|
||||
return action.enabled(context.graph());
|
||||
};
|
||||
|
||||
operation.id = "split";
|
||||
operation.title = "Split";
|
||||
operation.key = t('operations.split.key');
|
||||
operation.title = t('operations.split.title');
|
||||
operation.description = t('operations.split.description');
|
||||
|
||||
return operation;
|
||||
};
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
iD.operations.Unjoin = function(entityId) {
|
||||
var action = iD.actions.UnjoinNode(entityId);
|
||||
|
||||
var operation = function(history) {
|
||||
history.perform(action, 'unjoined lines');
|
||||
};
|
||||
|
||||
operation.available = function(graph) {
|
||||
var entity = graph.entity(entityId);
|
||||
return entity.geometry(graph) === 'vertex';
|
||||
};
|
||||
|
||||
operation.enabled = function(graph) {
|
||||
return action.enabled(graph);
|
||||
};
|
||||
|
||||
operation.id = "unjoin";
|
||||
operation.title = "Unjoin";
|
||||
|
||||
return operation;
|
||||
};
|
||||
@@ -1,4 +1,10 @@
|
||||
iD.Background = function() {
|
||||
|
||||
var deviceRatio = (window.devicePixelRatio &&
|
||||
window.devicePixelRatio === 2) ? 0.5 : 1;
|
||||
// tileSize = (deviceRatio === 0.5) ? [128,128] : [256,256];
|
||||
var tileSize = [256, 256];
|
||||
|
||||
var tile = d3.geo.tile(),
|
||||
projection,
|
||||
cache = {},
|
||||
@@ -6,14 +12,9 @@ iD.Background = function() {
|
||||
transformProp = iD.util.prefixCSSProperty('Transform'),
|
||||
source = d3.functor('');
|
||||
|
||||
var imgstyle = 'position:absolute;transform-origin:0 0;' +
|
||||
'-ms-transform-origin:0 0;' +
|
||||
'-webkit-transform-origin:0 0;' +
|
||||
'-moz-transform-origin:0 0;' +
|
||||
'-o-transform-origin:0 0;' +
|
||||
'-webkit-user-select: none;' +
|
||||
'-webkit-user-drag: none;' +
|
||||
'-moz-user-drag: none;';
|
||||
function tileSizeAtZoom(d, z) {
|
||||
return Math.ceil(tileSize[0] * Math.pow(2, z - d[2])) / tileSize[0];
|
||||
}
|
||||
|
||||
function atZoom(t, distance) {
|
||||
var power = Math.pow(2, distance);
|
||||
@@ -21,110 +22,110 @@ iD.Background = function() {
|
||||
Math.floor(t[0] * power),
|
||||
Math.floor(t[1] * power),
|
||||
t[2] + distance];
|
||||
az.push(source(az));
|
||||
return az;
|
||||
}
|
||||
|
||||
function upZoom(t, distance) {
|
||||
var az = atZoom(t, distance), tiles = [];
|
||||
for (var x = 0; x < 2; x++) {
|
||||
for (var y = 0; y < 2; y++) {
|
||||
var up = [az[0] + x, az[1] + y, az[2]];
|
||||
up.push(source(up));
|
||||
tiles.push(up);
|
||||
}
|
||||
}
|
||||
return tiles;
|
||||
}
|
||||
|
||||
function tileSize(d, z) {
|
||||
return Math.ceil(256 * Math.pow(2, z - d[2])) / 256;
|
||||
}
|
||||
|
||||
function lookUp(d) {
|
||||
for (var up = -1; up > -d[2]; up--) {
|
||||
if (cache[atZoom(d, up)] !== false) return atZoom(d, up);
|
||||
}
|
||||
}
|
||||
|
||||
function uniqueBy(a, n) {
|
||||
var o = [], seen = {};
|
||||
for (var i = 0; i < a.length; i++) {
|
||||
if (seen[a[i][n]] === undefined) {
|
||||
o.push(a[i]);
|
||||
seen[a[i][n]] = true;
|
||||
}
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
function addSource(d) {
|
||||
d.push(source(d));
|
||||
return d;
|
||||
}
|
||||
|
||||
// derive the tiles onscreen, remove those offscreen and position tiles
|
||||
// correctly for the currentstate of `projection`
|
||||
function background() {
|
||||
var tiles = tile
|
||||
var sel = this,
|
||||
tiles = tile
|
||||
.scale(projection.scale())
|
||||
.scaleExtent(source.scaleExtent || [1, 17])
|
||||
.scaleExtent((source.data && source.data.scaleExtent) || [1, 17])
|
||||
.translate(projection.translate())(),
|
||||
requests = [],
|
||||
scaleExtent = tile.scaleExtent(),
|
||||
z = Math.max(Math.log(projection.scale()) / Math.log(2) - 8, 0),
|
||||
rz = Math.max(scaleExtent[0], Math.min(scaleExtent[1], Math.floor(z))),
|
||||
ts = 256 * Math.pow(2, z - rz),
|
||||
rz = Math.max(scaleExtent[0],
|
||||
Math.min(scaleExtent[1], Math.floor(z))),
|
||||
ts = tileSize[0] * Math.pow(2, z - rz),
|
||||
tile_origin = [
|
||||
projection.scale() / 2 - projection.translate()[0],
|
||||
projection.scale() / 2 - projection.translate()[1]],
|
||||
ups = {};
|
||||
projection.scale() / 2 - projection.translate()[1]];
|
||||
|
||||
tiles.forEach(function(d) {
|
||||
|
||||
if (cache[d] === true) {
|
||||
d.push(source(d));
|
||||
} else if (cache[d] === false &&
|
||||
cache[atZoom(d, -1)] !== false &&
|
||||
!ups[atZoom(d, -1)]) {
|
||||
|
||||
ups[atZoom(d, -1)] = true;
|
||||
tiles.push(atZoom(d, -1));
|
||||
|
||||
} else if (cache[d] === undefined &&
|
||||
lookUp(d)) {
|
||||
|
||||
var upTile = lookUp(d);
|
||||
if (!ups[upTile]) {
|
||||
ups[upTile] = true;
|
||||
tiles.push(upTile);
|
||||
}
|
||||
|
||||
} else if (cache[d] === undefined ||
|
||||
cache[d] === false) {
|
||||
upZoom(d, 1).forEach(function(u) {
|
||||
if (cache[u] && !ups[u]) {
|
||||
ups[u] = true;
|
||||
tiles.push(u);
|
||||
}
|
||||
});
|
||||
addSource(d);
|
||||
requests.push(d);
|
||||
if (!cache[d[3]] && lookUp(d)) {
|
||||
requests.push(addSource(lookUp(d)));
|
||||
}
|
||||
});
|
||||
|
||||
var image = this
|
||||
.selectAll('img')
|
||||
.data(tiles, function(d) { return d; });
|
||||
requests = uniqueBy(requests, 3).filter(function(r) {
|
||||
// don't re-request tiles which have failed in the past
|
||||
return cache[r[3]] !== false;
|
||||
});
|
||||
|
||||
function load(d) {
|
||||
cache[d.slice(0, 3)] = true;
|
||||
d3.select(this).on('load', null);
|
||||
cache[d[3]] = true;
|
||||
d3.select(this)
|
||||
.on('load', null)
|
||||
.classed('tile-loaded', true);
|
||||
background.apply(sel);
|
||||
}
|
||||
|
||||
function error(d) {
|
||||
cache[d.slice(0, 3)] = false;
|
||||
cache[d[3]] = false;
|
||||
d3.select(this).on('load', null);
|
||||
d3.select(this).remove();
|
||||
background.apply(sel);
|
||||
}
|
||||
|
||||
function imageTransform(d) {
|
||||
var _ts = tileSize[0] * Math.pow(2, z - d[2]);
|
||||
var scale = tileSizeAtZoom(d, z);
|
||||
return 'translate(' +
|
||||
(Math.round((d[0] * _ts) - tile_origin[0]) + offset[0]) + 'px,' +
|
||||
(Math.round((d[1] * _ts) - tile_origin[1]) + offset[1]) + 'px)' +
|
||||
'scale(' + scale + ',' + scale + ')';
|
||||
}
|
||||
|
||||
var image = this
|
||||
.selectAll('img')
|
||||
.data(requests, function(d) { return d[3]; });
|
||||
|
||||
image.exit()
|
||||
.style(transformProp, imageTransform)
|
||||
.classed('tile-loaded', false)
|
||||
.each(function() {
|
||||
var tile = this;
|
||||
window.setTimeout(function() {
|
||||
// this tile may already be removed
|
||||
if (tile.parentNode) {
|
||||
tile.parentNode.removeChild(tile);
|
||||
}
|
||||
}, 300);
|
||||
});
|
||||
|
||||
image.enter().append('img')
|
||||
.attr('style', imgstyle)
|
||||
.attr('class', 'tile')
|
||||
.attr('src', function(d) { return d[3]; })
|
||||
.on('error', error)
|
||||
.on('load', load);
|
||||
|
||||
image.exit().remove();
|
||||
|
||||
image.style(transformProp, function(d) {
|
||||
var _ts = 256 * Math.pow(2, z - d[2]);
|
||||
var scale = tileSize(d, z);
|
||||
return 'translate(' +
|
||||
(Math.round((d[0] * _ts) - tile_origin[0]) + offset[0]) + 'px,' +
|
||||
(Math.round((d[1] * _ts) - tile_origin[1]) + offset[1]) + 'px) scale(' + scale + ',' + scale + ')';
|
||||
});
|
||||
|
||||
if (Object.keys(cache).length > 100) cache = {};
|
||||
image.style(transformProp, imageTransform);
|
||||
}
|
||||
|
||||
background.offset = function(_) {
|
||||
@@ -151,9 +152,22 @@ iD.Background = function() {
|
||||
return background;
|
||||
};
|
||||
|
||||
function setPermalink(source) {
|
||||
var tag = source.data.sourcetag;
|
||||
var q = iD.util.stringQs(location.hash.substring(1));
|
||||
if (tag) {
|
||||
location.replace('#' + iD.util.qsString(_.assign(q, {
|
||||
layer: tag
|
||||
}), true));
|
||||
} else {
|
||||
location.replace('#' + iD.util.qsString(_.omit(q, 'layer'), true));
|
||||
}
|
||||
}
|
||||
|
||||
background.source = function(_) {
|
||||
if (!arguments.length) return source;
|
||||
source = _;
|
||||
setPermalink(source);
|
||||
return background;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
iD.BackgroundSource = {};
|
||||
|
||||
// derive the url of a 'quadkey' style tile from a coordinate object
|
||||
iD.BackgroundSource.template = function(template, subdomains, scaleExtent) {
|
||||
scaleExtent = scaleExtent || [0, 18];
|
||||
iD.BackgroundSource.template = function(data) {
|
||||
var generator = function(coord) {
|
||||
var u = '';
|
||||
for (var zoom = coord[2]; zoom > 0; zoom--) {
|
||||
@@ -12,18 +11,17 @@ iD.BackgroundSource.template = function(template, subdomains, scaleExtent) {
|
||||
if ((coord[1] & mask) !== 0) byte += 2;
|
||||
u += byte.toString();
|
||||
}
|
||||
// distribute requests against multiple domains
|
||||
var t = subdomains ?
|
||||
subdomains[coord[2] % subdomains.length] : '';
|
||||
return template
|
||||
.replace('{t}', t)
|
||||
|
||||
return data.template
|
||||
.replace('{t}', data.subdomains ?
|
||||
data.subdomains[coord[2] % data.subdomains.length] : '')
|
||||
.replace('{u}', u)
|
||||
.replace('{x}', coord[0])
|
||||
.replace('{y}', coord[1])
|
||||
.replace('{z}', coord[2]);
|
||||
};
|
||||
|
||||
generator.scaleExtent = scaleExtent;
|
||||
generator.data = data;
|
||||
|
||||
return generator;
|
||||
};
|
||||
@@ -31,21 +29,9 @@ iD.BackgroundSource.template = function(template, subdomains, scaleExtent) {
|
||||
iD.BackgroundSource.Custom = function() {
|
||||
var template = window.prompt('Enter a tile template. Valid tokens are {z}, {x}, {y} for Z/X/Y scheme and {u} for quadtile scheme.');
|
||||
if (!template) return null;
|
||||
return iD.BackgroundSource.template(template, null, [0, 20]);
|
||||
return iD.BackgroundSource.template({
|
||||
template: template,
|
||||
name: 'Custom (customized)'
|
||||
});
|
||||
};
|
||||
|
||||
iD.BackgroundSource.Bing = iD.BackgroundSource.template(
|
||||
'http://ecn.t{t}.tiles.virtualearth.net/tiles/a{u}.jpeg?g=587&mkt=en-gb&n=z',
|
||||
[0, 1, 2, 3], [0, 20]);
|
||||
|
||||
iD.BackgroundSource.Tiger2012 = iD.BackgroundSource.template(
|
||||
'http://{t}.tile.openstreetmap.us/tiger2012_roads_expanded/{z}/{x}/{y}.png',
|
||||
['a', 'b', 'c'], [0, 17]);
|
||||
|
||||
iD.BackgroundSource.OSM = iD.BackgroundSource.template(
|
||||
'http://{t}.tile.openstreetmap.org/{z}/{x}/{y}.png',
|
||||
['a', 'b', 'c'], [0, 18]);
|
||||
|
||||
iD.BackgroundSource.MapBox = iD.BackgroundSource.template(
|
||||
'http://{t}.tiles.mapbox.com/v3/openstreetmap.map-4wvf9l0l/{z}/{x}/{y}.jpg70',
|
||||
['a', 'b', 'c'], [0, 16]);
|
||||
iD.BackgroundSource.Custom.data = { 'name': 'Custom' };
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
iD.Hash = function() {
|
||||
var hash = { hadHash: false },
|
||||
s0 = null, // cached location.hash
|
||||
lat = 90 - 1e-8, // allowable latitude range
|
||||
controller,
|
||||
map;
|
||||
|
||||
var parser = function(map, s) {
|
||||
var q = iD.util.stringQs(s);
|
||||
var args = (q.map || '').split("/").map(Number);
|
||||
if (args.length < 3 || args.some(isNaN)) {
|
||||
return true; // replace bogus hash
|
||||
} else if (s !== formatter(map).slice(1)) {
|
||||
map.centerZoom([args[2],
|
||||
Math.min(lat, Math.max(-lat, args[1]))],
|
||||
args[0]);
|
||||
}
|
||||
};
|
||||
|
||||
var formatter = function(map) {
|
||||
var center = map.center(),
|
||||
zoom = map.zoom(),
|
||||
precision = Math.max(0, Math.ceil(Math.log(zoom) / Math.LN2));
|
||||
var q = iD.util.stringQs(location.hash.substring(1));
|
||||
return '#' + iD.util.qsString(_.assign(q, {
|
||||
map: zoom.toFixed(2) +
|
||||
'/' + center[1].toFixed(precision) +
|
||||
'/' + center[0].toFixed(precision)
|
||||
}), true);
|
||||
};
|
||||
|
||||
var move = _.throttle(function() {
|
||||
var s1 = formatter(map);
|
||||
if (s0 !== s1) location.replace(s0 = s1); // don't recenter the map!
|
||||
}, 100);
|
||||
|
||||
function hashchange() {
|
||||
if (location.hash === s0) return; // ignore spurious hashchange events
|
||||
if (parser(map, (s0 = location.hash).substring(1))) {
|
||||
move(); // replace bogus hash
|
||||
}
|
||||
}
|
||||
|
||||
// the hash can declare that the map should select a feature, but it can
|
||||
// do so before any features are loaded. thus wait for the feature to
|
||||
// be loaded and then select
|
||||
function willselect(id) {
|
||||
map.on('drawn.hash', function() {
|
||||
var entity = map.history().graph().entity(id);
|
||||
if (entity === undefined) return;
|
||||
else selectoff();
|
||||
controller.enter(iD.modes.Select(entity));
|
||||
map.on('drawn.hash', null);
|
||||
});
|
||||
controller.on('enter.hash', function() {
|
||||
if (controller.mode.id !== 'browse') selectoff();
|
||||
});
|
||||
}
|
||||
|
||||
function selectoff() {
|
||||
map.on('drawn.hash', null);
|
||||
}
|
||||
|
||||
hash.controller = function(_) {
|
||||
if (!arguments.length) return controller;
|
||||
controller = _;
|
||||
return hash;
|
||||
};
|
||||
|
||||
hash.map = function(x) {
|
||||
if (!arguments.length) return map;
|
||||
if (map) {
|
||||
map.on("move.hash", null);
|
||||
window.removeEventListener("hashchange", hashchange, false);
|
||||
}
|
||||
map = x;
|
||||
if (x) {
|
||||
map.on("move.hash", move);
|
||||
window.addEventListener("hashchange", hashchange, false);
|
||||
if (location.hash) {
|
||||
var q = iD.util.stringQs(location.hash.substring(1));
|
||||
if (q.id) {
|
||||
willselect(q.id);
|
||||
}
|
||||
hashchange();
|
||||
hash.hadHash = true;
|
||||
}
|
||||
}
|
||||
return hash;
|
||||
};
|
||||
|
||||
return hash;
|
||||
};
|
||||
@@ -0,0 +1,15 @@
|
||||
iD.layers = iD.data.imagery.map(iD.BackgroundSource.template);
|
||||
|
||||
iD.layers.push((function() {
|
||||
function custom() {
|
||||
var template = window.prompt('Enter a tile template. Valid tokens are {z}, {x}, {y} for Z/X/Y scheme and {u} for quadtile scheme.');
|
||||
if (!template) return null;
|
||||
if (template.match(/google/g)) return null;
|
||||
return iD.BackgroundSource.template({
|
||||
template: template,
|
||||
name: 'Custom (customized)'
|
||||
});
|
||||
}
|
||||
custom.data = { name: 'Custom' };
|
||||
return custom;
|
||||
})());
|
||||
@@ -1,6 +1,5 @@
|
||||
iD.Map = function() {
|
||||
var connection, history,
|
||||
dimensions = [],
|
||||
iD.Map = function(context) {
|
||||
var dimensions = [],
|
||||
dispatch = d3.dispatch('move', 'drawn'),
|
||||
projection = d3.geo.mercator().scale(1024),
|
||||
roundedProjection = iD.svg.RoundProjection(projection),
|
||||
@@ -20,13 +19,15 @@ iD.Map = function() {
|
||||
vertices = iD.svg.Vertices(roundedProjection),
|
||||
lines = iD.svg.Lines(roundedProjection),
|
||||
areas = iD.svg.Areas(roundedProjection),
|
||||
multipolygons = iD.svg.Multipolygons(roundedProjection),
|
||||
midpoints = iD.svg.Midpoints(roundedProjection),
|
||||
labels = iD.svg.Labels(roundedProjection),
|
||||
tail = d3.tail(),
|
||||
surface, tilegroup;
|
||||
|
||||
function map(selection) {
|
||||
context.history()
|
||||
.on('change.map', redraw);
|
||||
|
||||
selection.call(zoom);
|
||||
|
||||
tilegroup = selection.append('div')
|
||||
@@ -41,12 +42,16 @@ iD.Map = function() {
|
||||
d3.event.stopPropagation();
|
||||
}
|
||||
}, true)
|
||||
.on('mouseup.zoom', function() {
|
||||
if (resetTransform()) redraw();
|
||||
})
|
||||
.attr('id', 'surface')
|
||||
.call(iD.svg.Surface());
|
||||
|
||||
|
||||
map.size(selection.size());
|
||||
map.surface = surface;
|
||||
map.tilesurface = tilegroup;
|
||||
|
||||
supersurface
|
||||
.call(tail);
|
||||
@@ -55,49 +60,23 @@ iD.Map = function() {
|
||||
function pxCenter() { return [dimensions[0] / 2, dimensions[1] / 2]; }
|
||||
|
||||
function drawVector(difference) {
|
||||
if (surface.style(transformProp) != 'none') return;
|
||||
var filter, all,
|
||||
extent = map.extent(),
|
||||
graph = history.graph();
|
||||
|
||||
function addParents(parents) {
|
||||
for (var i = 0; i < parents.length; i++) {
|
||||
var parent = parents[i];
|
||||
if (only[parent.id] === undefined) {
|
||||
only[parent.id] = graph.entity(parent.id);
|
||||
addParents(graph.parentRelations(parent));
|
||||
}
|
||||
}
|
||||
}
|
||||
graph = context.graph();
|
||||
|
||||
if (!difference) {
|
||||
all = graph.intersects(extent);
|
||||
filter = d3.functor(true);
|
||||
} else {
|
||||
var only = {};
|
||||
|
||||
for (var j = 0; j < difference.length; j++) {
|
||||
var id = difference[j],
|
||||
entity = graph.entity(id);
|
||||
|
||||
// Even if the entity is false (deleted), it needs to be
|
||||
// removed from the surface
|
||||
only[id] = entity;
|
||||
|
||||
if (entity && entity.intersects(extent, graph)) {
|
||||
addParents(graph.parentWays(only[id]));
|
||||
addParents(graph.parentRelations(only[id]));
|
||||
}
|
||||
}
|
||||
|
||||
all = _.compact(_.values(only));
|
||||
var complete = difference.complete(extent);
|
||||
all = _.compact(_.values(complete));
|
||||
filter = function(d) {
|
||||
if (d.midpoint) {
|
||||
if (d.type === 'midpoint') {
|
||||
for (var i = 0; i < d.ways.length; i++) {
|
||||
if (d.ways[i].id in only) return true;
|
||||
if (d.ways[i].id in complete) return true;
|
||||
}
|
||||
} else {
|
||||
return d.id in only;
|
||||
return d.id in complete;
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -110,9 +89,8 @@ iD.Map = function() {
|
||||
.call(vertices, graph, all, filter)
|
||||
.call(lines, graph, all, filter)
|
||||
.call(areas, graph, all, filter)
|
||||
.call(multipolygons, graph, all, filter)
|
||||
.call(midpoints, graph, all, filter)
|
||||
.call(labels, graph, all, filter, dimensions);
|
||||
.call(labels, graph, all, filter, dimensions, !difference);
|
||||
}
|
||||
dispatch.drawn(map);
|
||||
}
|
||||
@@ -121,11 +99,6 @@ iD.Map = function() {
|
||||
surface.selectAll('.layer *').remove();
|
||||
}
|
||||
|
||||
function connectionLoad(err, result) {
|
||||
history.merge(result);
|
||||
redraw(Object.keys(result.entities));
|
||||
}
|
||||
|
||||
function zoomPan() {
|
||||
if (d3.event && d3.event.sourceEvent.type === 'dblclick') {
|
||||
if (!dblclickEnabled) {
|
||||
@@ -136,10 +109,10 @@ iD.Map = function() {
|
||||
}
|
||||
|
||||
if (Math.log(d3.event.scale / Math.LN2 - 8) < minzoom + 1) {
|
||||
iD.flash()
|
||||
iD.ui.flash(context.container())
|
||||
.select('.content')
|
||||
.text('Cannot zoom out further in current mode.');
|
||||
return map.zoom(16);
|
||||
return setZoom(16, true);
|
||||
}
|
||||
|
||||
projection
|
||||
@@ -165,24 +138,34 @@ iD.Map = function() {
|
||||
}
|
||||
|
||||
function resetTransform() {
|
||||
if (!surface.style(transformProp)) return false;
|
||||
var prop = surface.style(transformProp);
|
||||
if (!prop || prop === 'none') return false;
|
||||
surface.style(transformProp, '');
|
||||
tilegroup.style(transformProp, '');
|
||||
return true;
|
||||
}
|
||||
|
||||
function redraw(difference) {
|
||||
clearTimeout(timeoutId);
|
||||
|
||||
// If we are in the middle of a zoom/pan, we can't do differenced redraws.
|
||||
// It would result in artifacts where differenced entities are redrawn with
|
||||
// one transform and unchanged entities with another.
|
||||
if (resetTransform())
|
||||
if (resetTransform()) {
|
||||
difference = undefined;
|
||||
}
|
||||
|
||||
surface.attr('data-zoom', ~~map.zoom());
|
||||
tilegroup.call(background);
|
||||
var zoom = String(~~map.zoom());
|
||||
if (surface.attr('data-zoom') !== zoom) {
|
||||
surface.attr('data-zoom', zoom);
|
||||
}
|
||||
|
||||
if (!difference) {
|
||||
tilegroup.call(background);
|
||||
}
|
||||
|
||||
if (map.editable()) {
|
||||
connection.loadTiles(projection, dimensions);
|
||||
context.connection().loadTiles(projection, dimensions);
|
||||
drawVector(difference);
|
||||
} else {
|
||||
editOff();
|
||||
@@ -195,7 +178,11 @@ iD.Map = function() {
|
||||
return map;
|
||||
}
|
||||
|
||||
var queueRedraw = _.debounce(redraw, 200);
|
||||
var timeoutId;
|
||||
function queueRedraw() {
|
||||
clearTimeout(timeoutId);
|
||||
timeoutId = setTimeout(function() { redraw(); }, 300);
|
||||
}
|
||||
|
||||
function pointLocation(p) {
|
||||
var translate = projection.translate(),
|
||||
@@ -230,8 +217,8 @@ iD.Map = function() {
|
||||
return map;
|
||||
};
|
||||
|
||||
function setZoom(z) {
|
||||
if (z === map.zoom())
|
||||
function setZoom(z, force) {
|
||||
if (z === map.zoom() && !force)
|
||||
return false;
|
||||
var scale = 256 * Math.pow(2, z),
|
||||
center = pxCenter(),
|
||||
@@ -261,6 +248,15 @@ iD.Map = function() {
|
||||
return true;
|
||||
}
|
||||
|
||||
map.pan = function(d) {
|
||||
var t = projection.translate();
|
||||
t[0] += d[0];
|
||||
t[1] += d[1];
|
||||
projection.translate(t);
|
||||
zoom.translate(projection.translate());
|
||||
return redraw();
|
||||
};
|
||||
|
||||
map.size = function(_) {
|
||||
if (!arguments.length) return dimensions;
|
||||
dimensions = _;
|
||||
@@ -318,39 +314,37 @@ iD.Map = function() {
|
||||
|
||||
map.extent = function(_) {
|
||||
if (!arguments.length) {
|
||||
return iD.geo.Extent(projection.invert([0, dimensions[1]]),
|
||||
return new iD.geo.Extent(projection.invert([0, dimensions[1]]),
|
||||
projection.invert([dimensions[0], 0]));
|
||||
} else {
|
||||
var extent = iD.geo.Extent(_),
|
||||
tl = projection([extent[0][0], extent[1][1]]),
|
||||
br = projection([extent[1][0], extent[0][1]]);
|
||||
|
||||
// Calculate maximum zoom that fits extent
|
||||
var hFactor = (br[0] - tl[0]) / dimensions[0],
|
||||
vFactor = (br[1] - tl[1]) / dimensions[1],
|
||||
hZoomDiff = Math.log(Math.abs(hFactor)) / Math.LN2,
|
||||
vZoomDiff = Math.log(Math.abs(vFactor)) / Math.LN2,
|
||||
newZoom = map.zoom() - Math.max(hZoomDiff, vZoomDiff);
|
||||
|
||||
map.centerZoom(extent.center(), newZoom);
|
||||
var extent = iD.geo.Extent(_);
|
||||
map.centerZoom(extent.center(), map.extentZoom(extent));
|
||||
}
|
||||
};
|
||||
|
||||
map.flush = function () {
|
||||
connection.flush();
|
||||
history.reset();
|
||||
return map;
|
||||
map.extentZoom = function(_) {
|
||||
var extent = iD.geo.Extent(_),
|
||||
tl = projection([extent[0][0], extent[1][1]]),
|
||||
br = projection([extent[1][0], extent[0][1]]);
|
||||
|
||||
// Calculate maximum zoom that fits extent
|
||||
var hFactor = (br[0] - tl[0]) / dimensions[0],
|
||||
vFactor = (br[1] - tl[1]) / dimensions[1],
|
||||
hZoomDiff = Math.log(Math.abs(hFactor)) / Math.LN2,
|
||||
vZoomDiff = Math.log(Math.abs(vFactor)) / Math.LN2,
|
||||
newZoom = map.zoom() - Math.max(hZoomDiff, vZoomDiff);
|
||||
|
||||
return newZoom;
|
||||
};
|
||||
|
||||
map.connection = function(_) {
|
||||
if (!arguments.length) return connection;
|
||||
connection = _;
|
||||
connection.on('load.tile', connectionLoad);
|
||||
map.flush = function() {
|
||||
context.connection().flush();
|
||||
context.history().reset();
|
||||
return map;
|
||||
};
|
||||
|
||||
var usedTails = {};
|
||||
map.tail = function (_, once) {
|
||||
map.tail = function(_) {
|
||||
if (!_ || usedTails[_] === undefined) {
|
||||
tail.text(_);
|
||||
usedTails[_] = true;
|
||||
@@ -358,24 +352,6 @@ iD.Map = function() {
|
||||
return map;
|
||||
};
|
||||
|
||||
map.hint = function (_) {
|
||||
if (_ === false) {
|
||||
d3.select('div.inspector-wrap')
|
||||
.style('opacity', 0)
|
||||
.style('display', 'none');
|
||||
} else {
|
||||
d3.select('div.inspector-wrap')
|
||||
.html('')
|
||||
.style('display', 'block')
|
||||
.transition()
|
||||
.style('opacity', 1);
|
||||
d3.select('div.inspector-wrap')
|
||||
.append('div')
|
||||
.attr('class','inspector-inner')
|
||||
.text(_);
|
||||
}
|
||||
};
|
||||
|
||||
map.editable = function() {
|
||||
return map.zoom() >= 16;
|
||||
};
|
||||
@@ -386,13 +362,6 @@ iD.Map = function() {
|
||||
return map;
|
||||
};
|
||||
|
||||
map.history = function (_) {
|
||||
if (!arguments.length) return history;
|
||||
history = _;
|
||||
history.on('change.map', redraw);
|
||||
return map;
|
||||
};
|
||||
|
||||
map.background = background;
|
||||
map.projection = projection;
|
||||
map.redraw = redraw;
|
||||
|
||||
@@ -40,7 +40,7 @@ iD.taginfo = function() {
|
||||
}
|
||||
|
||||
function popularValues(parameters) {
|
||||
return function(d) { return parseFloat(d['fraction']) > 0.01; };
|
||||
return function(d) { return parseFloat(d.fraction) > 0.01; };
|
||||
}
|
||||
|
||||
function valKey(d) { return { value: d.key }; }
|
||||
@@ -76,7 +76,7 @@ iD.taginfo = function() {
|
||||
page: 1
|
||||
}, parameters)), function(err, d) {
|
||||
if (err) return callback(err);
|
||||
callback(null, d.data.filter(popularValues()).map(valKeyDescription));
|
||||
callback(null, d.data.filter(popularValues()).map(valKeyDescription), parameters);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
iD.svg = {
|
||||
RoundProjection: function (projection) {
|
||||
return function (d) {
|
||||
RoundProjection: function(projection) {
|
||||
return function(d) {
|
||||
return iD.geo.roundCoords(projection(d));
|
||||
};
|
||||
},
|
||||
|
||||
PointTransform: function (projection) {
|
||||
return function (entity) {
|
||||
return 'translate(' + projection(entity.loc) + ')';
|
||||
PointTransform: function(projection) {
|
||||
return function(entity) {
|
||||
// http://jsperf.com/short-array-join
|
||||
var pt = projection(entity.loc);
|
||||
return 'translate(' + pt[0] + ',' + pt[1] + ')';
|
||||
};
|
||||
},
|
||||
|
||||
LineString: function (projection, graph) {
|
||||
LineString: function(projection, graph) {
|
||||
var cache = {};
|
||||
return function (entity) {
|
||||
return function(entity) {
|
||||
if (cache[entity.id] !== undefined) {
|
||||
return cache[entity.id];
|
||||
}
|
||||
@@ -23,7 +25,22 @@ iD.svg = {
|
||||
}
|
||||
|
||||
return (cache[entity.id] =
|
||||
'M' + graph.childNodes(entity).map(function (n) { return projection(n.loc); }).join('L'));
|
||||
}
|
||||
'M' + graph.childNodes(entity).map(function(n) {
|
||||
var pt = projection(n.loc);
|
||||
return pt[0] + ',' + pt[1];
|
||||
}).join('L'));
|
||||
};
|
||||
},
|
||||
|
||||
MultipolygonMemberTags: function(graph) {
|
||||
return function(entity) {
|
||||
var tags = entity.tags;
|
||||
graph.parentRelations(entity).forEach(function(relation) {
|
||||
if (relation.isMultipolygon()) {
|
||||
tags = _.extend({}, relation.tags, tags);
|
||||
}
|
||||
});
|
||||
return tags;
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,38 +1,39 @@
|
||||
iD.svg.Areas = function(projection) {
|
||||
return function drawAreas(surface, graph, entities, filter) {
|
||||
var areas = [];
|
||||
var path = d3.geo.path().projection(projection),
|
||||
areas = [];
|
||||
|
||||
for (var i = 0; i < entities.length; i++) {
|
||||
var entity = entities[i];
|
||||
if (entity.geometry(graph) === 'area') {
|
||||
var points = graph.childNodes(entity).map(function(n) {
|
||||
return projection(n.loc);
|
||||
});
|
||||
|
||||
areas.push({
|
||||
entity: entity,
|
||||
area: entity.isDegenerate() ? 0 : Math.abs(d3.geom.polygon(points).area())
|
||||
area: Math.abs(path.area(entity.asGeoJSON(graph)))
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
areas.sort(function(a, b) { return b.area - a.area; });
|
||||
|
||||
var lineString = iD.svg.LineString(projection, graph);
|
||||
function drawPaths(group, areas, filter, klass) {
|
||||
var tagClasses = iD.svg.TagClasses();
|
||||
|
||||
if (klass === 'stroke') {
|
||||
tagClasses.tags(iD.svg.MultipolygonMemberTags(graph));
|
||||
}
|
||||
|
||||
function drawPaths(group, areas, filter, classes) {
|
||||
var paths = group.selectAll('path.area')
|
||||
.filter(filter)
|
||||
.data(areas, iD.Entity.key);
|
||||
|
||||
paths.enter()
|
||||
.append('path')
|
||||
.attr('class', classes);
|
||||
.attr('class', function(d) { return d.type + ' area ' + klass; });
|
||||
|
||||
paths
|
||||
.order()
|
||||
.attr('d', lineString)
|
||||
.call(iD.svg.TagClasses())
|
||||
.attr('d', function(entity) { return path(entity.asGeoJSON(graph)); })
|
||||
.call(tagClasses)
|
||||
.call(iD.svg.MemberClasses(graph));
|
||||
|
||||
paths.exit()
|
||||
@@ -43,9 +44,14 @@ iD.svg.Areas = function(projection) {
|
||||
|
||||
areas = _.pluck(areas, 'entity');
|
||||
|
||||
var strokes = areas.filter(function(area) {
|
||||
return area.type === 'way';
|
||||
});
|
||||
|
||||
var fill = surface.select('.layer-fill'),
|
||||
stroke = surface.select('.layer-stroke'),
|
||||
fills = drawPaths(fill, areas, filter, 'way area fill'),
|
||||
strokes = drawPaths(stroke, areas, filter, 'way area stroke');
|
||||
stroke = surface.select('.layer-stroke');
|
||||
|
||||
drawPaths(fill, areas, filter, 'fill');
|
||||
drawPaths(stroke, strokes, filter, 'stroke');
|
||||
};
|
||||
};
|
||||
|
||||
@@ -2,21 +2,42 @@ iD.svg.Labels = function(projection) {
|
||||
|
||||
// Replace with dict and iterate over entities tags instead?
|
||||
var label_stack = [
|
||||
['line', 'aeroway'],
|
||||
['line', 'highway'],
|
||||
['area', 'building', 'yes'],
|
||||
['area', 'leisure', 'park'],
|
||||
['line', 'railway'],
|
||||
['line', 'waterway'],
|
||||
['area', 'aeroway'],
|
||||
['area', 'amenity'],
|
||||
['area', 'building'],
|
||||
['area', 'historic'],
|
||||
['area', 'leisure'],
|
||||
['area', 'man_made'],
|
||||
['area', 'natural'],
|
||||
['area', 'shop'],
|
||||
['area', 'tourism'],
|
||||
['point', 'aeroway'],
|
||||
['point', 'amenity'],
|
||||
['point', 'shop']
|
||||
['point', 'building'],
|
||||
['point', 'historic'],
|
||||
['point', 'leisure'],
|
||||
['point', 'man_made'],
|
||||
['point', 'natural'],
|
||||
['point', 'shop'],
|
||||
['point', 'tourism'],
|
||||
['line', 'name'],
|
||||
['area', 'name'],
|
||||
['point', 'name']
|
||||
];
|
||||
|
||||
var default_size = 12;
|
||||
var font_sizes = label_stack.map(function(d) {
|
||||
var style = iD.util.getStyle(
|
||||
'text.' + d[0] + '.tag-' + d.slice(1).join('-'));
|
||||
var style = iD.util.getStyle('text.' + d[0] + '.tag-' + d[1]);
|
||||
var m = style && style.cssText.match("font-size: ([0-9]{1,2})px;");
|
||||
if (!m) return default_size;
|
||||
return parseInt(m[1], 10);
|
||||
if (m) return parseInt(m[1], 10);
|
||||
style = iD.util.getStyle('text.' + d[0]);
|
||||
m = style && style.cssText.match("font-size: ([0-9]{1,2})px;");
|
||||
if (m) return parseInt(m[1], 10);
|
||||
return default_size;
|
||||
});
|
||||
|
||||
var pointOffsets = [
|
||||
@@ -61,7 +82,7 @@ iD.svg.Labels = function(projection) {
|
||||
'startOffset': '50%',
|
||||
'xlink:href': function(d, i) { return '#halo-' + d.id; }
|
||||
})
|
||||
.text(function(d, i) { return d.tags.name; });
|
||||
.text(function(d, i) { return name(d); });
|
||||
|
||||
texts.exit().remove();
|
||||
|
||||
@@ -98,14 +119,14 @@ iD.svg.Labels = function(projection) {
|
||||
'x': function(d, i) {
|
||||
var x = labels[i].x - 2;
|
||||
if (labels[i].textAnchor === 'middle') {
|
||||
x -= textWidth(d.tags.name, labels[i].height) / 2;
|
||||
x -= textWidth(name(d), labels[i].height) / 2;
|
||||
}
|
||||
return x;
|
||||
},
|
||||
'y': function(d, i) { return labels[i].y - labels[i].height + 1 - 2; },
|
||||
'rx': 3,
|
||||
'ry': 3,
|
||||
'width': function(d, i) { return textWidth(d.tags.name, labels[i].height) + 4; },
|
||||
'width': function(d, i) { return textWidth(name(d), labels[i].height) + 4; },
|
||||
'height': function(d, i) { return labels[i].height + 4; },
|
||||
'fill': 'white'
|
||||
});
|
||||
@@ -128,8 +149,8 @@ iD.svg.Labels = function(projection) {
|
||||
.attr('y', get(labels, 'y'))
|
||||
.attr('transform', get(labels, 'transform'))
|
||||
.style('text-anchor', get(labels, 'textAnchor'))
|
||||
.text(function(d) { return d.tags.name; })
|
||||
.each(function(d, i) { textWidth(d.tags.name, labels[i].height, this); });
|
||||
.text(function(d) { return name(d); })
|
||||
.each(function(d, i) { textWidth(name(d), labels[i].height, this); });
|
||||
|
||||
texts.exit().remove();
|
||||
return texts;
|
||||
@@ -156,7 +177,7 @@ iD.svg.Labels = function(projection) {
|
||||
for (var i = 0; i < nodes.length - 1; i++) {
|
||||
var current = segmentLength(i);
|
||||
var portion;
|
||||
if (!start && sofar + current > from) {
|
||||
if (!start && sofar + current >= from) {
|
||||
portion = (from - sofar) / current;
|
||||
start = [
|
||||
nodes[i][0] + portion * (nodes[i + 1][0] - nodes[i][0]),
|
||||
@@ -164,7 +185,7 @@ iD.svg.Labels = function(projection) {
|
||||
];
|
||||
i0 = i + 1;
|
||||
}
|
||||
if (!end && sofar + current > to) {
|
||||
if (!end && sofar + current >= to) {
|
||||
portion = (to - sofar) / current;
|
||||
end = [
|
||||
nodes[i][0] + portion * (nodes[i + 1][0] - nodes[i][0]),
|
||||
@@ -183,29 +204,82 @@ iD.svg.Labels = function(projection) {
|
||||
}
|
||||
|
||||
|
||||
return function drawLabels(surface, graph, entities, filter, dimensions) {
|
||||
function hideOnMouseover() {
|
||||
var mouse = mousePosition(d3.event),
|
||||
pad = 50,
|
||||
rect = new RTree.Rectangle(mouse[0] - pad, mouse[1] - pad, 2*pad, 2*pad),
|
||||
labels = _.pluck(rtree.search(rect, this), 'leaf'),
|
||||
containsLabel = iD.util.trueObj(labels),
|
||||
selection = d3.select(this);
|
||||
|
||||
var rtree = new RTree();
|
||||
var hidePoints = !d3.select('.node.point').node();
|
||||
// ensures that simply resetting opacity
|
||||
// does not force style recalculation
|
||||
function resetOpacity() {
|
||||
if (this._opacity !== '') {
|
||||
this.style.opacity = '';
|
||||
this._opacity = '';
|
||||
}
|
||||
}
|
||||
|
||||
selection.selectAll('.layer-label text, .layer-halo path, .layer-halo rect')
|
||||
.each(resetOpacity);
|
||||
|
||||
if (!labels.length) return;
|
||||
selection.selectAll('.layer-label text, .layer-halo path, .layer-halo rect')
|
||||
.filter(function(d) {
|
||||
return containsLabel[d.id];
|
||||
})
|
||||
.style('opacity', 0)
|
||||
.property('_opacity', 0);
|
||||
}
|
||||
|
||||
function name(d) {
|
||||
return d.tags[lang] || d.tags.name;
|
||||
}
|
||||
|
||||
var rtree = new RTree(),
|
||||
rectangles = {},
|
||||
lang = 'name:' + iD.detect().locale.toLowerCase().split('-')[0],
|
||||
mousePosition, cacheDimensions;
|
||||
|
||||
return function drawLabels(surface, graph, entities, filter, dimensions, fullRedraw) {
|
||||
|
||||
if (!mousePosition || dimensions.join(',') !== cacheDimensions) {
|
||||
mousePosition = iD.util.fastMouse(surface.node().parentNode);
|
||||
cacheDimensions = dimensions.join(',');
|
||||
}
|
||||
|
||||
d3.select(surface.node().parentNode)
|
||||
.on('mousemove.hidelabels', hideOnMouseover);
|
||||
|
||||
var hidePoints = !surface.select('.node.point').node();
|
||||
|
||||
var labelable = [], i, k, entity;
|
||||
for (i = 0; i < label_stack.length; i++) labelable.push([]);
|
||||
|
||||
if (fullRedraw) {
|
||||
rtree = new RTree();
|
||||
rectangles = {};
|
||||
} else {
|
||||
for (i = 0; i < entities.length; i++) {
|
||||
rtree.remove(rectangles[entities[i].id], entities[i].id);
|
||||
}
|
||||
}
|
||||
|
||||
// Split entities into groups specified by label_stack
|
||||
for (i = 0; i < entities.length; i++) {
|
||||
entity = entities[i];
|
||||
if (!entity.tags.name) continue;
|
||||
if (!name(entity)) continue;
|
||||
if (hidePoints && entity.geometry(graph) === 'point') continue;
|
||||
for (k = 0; k < label_stack.length; k ++) {
|
||||
if (entity.geometry(graph) === label_stack[k][0] &&
|
||||
entity.tags[label_stack[k][1]] && !entity.tags[label_stack[k][2]]) {
|
||||
entity.tags[label_stack[k][1]]) {
|
||||
labelable[k].push(entity);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var positions = {
|
||||
point: [],
|
||||
line: [],
|
||||
@@ -223,7 +297,7 @@ iD.svg.Labels = function(projection) {
|
||||
var font_size = font_sizes[k];
|
||||
for (i = 0; i < labelable[k].length; i ++) {
|
||||
entity = labelable[k][i];
|
||||
var width = textWidth(entity.tags.name, font_size),
|
||||
var width = textWidth(name(entity), font_size),
|
||||
p;
|
||||
if (entity.geometry(graph) === 'point') {
|
||||
p = getPointLabel(entity, width, font_size);
|
||||
@@ -233,7 +307,7 @@ iD.svg.Labels = function(projection) {
|
||||
p = getAreaLabel(entity, width, font_size);
|
||||
}
|
||||
if (p) {
|
||||
p.classes = entity.geometry(graph) + ' tag-' + label_stack[k].slice(1).join('-');
|
||||
p.classes = entity.geometry(graph) + ' tag-' + label_stack[k][1];
|
||||
positions[entity.geometry(graph)].push(p);
|
||||
labelled[entity.geometry(graph)].push(entity);
|
||||
}
|
||||
@@ -252,7 +326,7 @@ iD.svg.Labels = function(projection) {
|
||||
textAnchor: offset[2]
|
||||
};
|
||||
var rect = new RTree.Rectangle(p.x - m, p.y - m, width + 2*m, height + 2*m);
|
||||
if (tryInsert(rect)) return p;
|
||||
if (tryInsert(rect, entity.id)) return p;
|
||||
}
|
||||
|
||||
|
||||
@@ -275,7 +349,7 @@ iD.svg.Labels = function(projection) {
|
||||
Math.abs(sub[0][1] - sub[sub.length - 1][1]) + 30
|
||||
);
|
||||
if (rev) sub = sub.reverse();
|
||||
if (tryInsert(rect)) return {
|
||||
if (tryInsert(rect, entity.id)) return {
|
||||
'font-size': height + 2,
|
||||
lineString: lineString(sub),
|
||||
startOffset: offset + '%'
|
||||
@@ -284,9 +358,8 @@ iD.svg.Labels = function(projection) {
|
||||
}
|
||||
|
||||
function getAreaLabel(entity, width, height) {
|
||||
var nodes = _.pluck(graph.childNodes(entity), 'loc')
|
||||
.map(iD.svg.RoundProjection(projection)),
|
||||
centroid = d3.geom.polygon(nodes).centroid(),
|
||||
var path = d3.geo.path().projection(projection),
|
||||
centroid = path.centroid(entity.asGeoJSON(graph)),
|
||||
extent = entity.extent(graph),
|
||||
entitywidth = projection(extent[1])[0] - projection(extent[0])[0];
|
||||
|
||||
@@ -298,16 +371,19 @@ iD.svg.Labels = function(projection) {
|
||||
height: height
|
||||
};
|
||||
var rect = new RTree.Rectangle(p.x - width/2, p.y, width, height);
|
||||
if (tryInsert(rect)) return p;
|
||||
if (tryInsert(rect, entity.id)) return p;
|
||||
|
||||
}
|
||||
|
||||
function tryInsert(rect) {
|
||||
function tryInsert(rect, id) {
|
||||
// Check that label is visible
|
||||
if (rect.x1 < 0 || rect.y1 < 0 || rect.x2 > dimensions[0] ||
|
||||
rect.y2 > dimensions[1]) return false;
|
||||
var v = rtree.search(rect, true).length === 0;
|
||||
if (v) rtree.insert(rect);
|
||||
if (v) {
|
||||
rtree.insert(rect, id);
|
||||
rectangles[id] = rect;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
iD.svg.Lines = function(projection) {
|
||||
|
||||
var arrowtext = '►\u3000\u3000',
|
||||
var arrowtext = '►\u3000\u3000\u3000',
|
||||
alength;
|
||||
|
||||
var highway_stack = {
|
||||
@@ -34,19 +34,25 @@ iD.svg.Lines = function(projection) {
|
||||
}
|
||||
|
||||
return function drawLines(surface, graph, entities, filter) {
|
||||
function drawPaths(group, lines, filter, classes, lineString) {
|
||||
var paths = group.selectAll('path')
|
||||
function drawPaths(group, lines, filter, klass, lineString) {
|
||||
var tagClasses = iD.svg.TagClasses();
|
||||
|
||||
if (klass === 'stroke') {
|
||||
tagClasses.tags(iD.svg.MultipolygonMemberTags(graph));
|
||||
}
|
||||
|
||||
var paths = group.selectAll('path.line')
|
||||
.filter(filter)
|
||||
.data(lines, iD.Entity.key);
|
||||
|
||||
paths.enter()
|
||||
.append('path')
|
||||
.attr('class', classes);
|
||||
.attr('class', 'way line ' + klass);
|
||||
|
||||
paths
|
||||
.order()
|
||||
.attr('d', lineString)
|
||||
.call(iD.svg.TagClasses())
|
||||
.call(tagClasses)
|
||||
.call(iD.svg.MemberClasses(graph));
|
||||
|
||||
paths.exit()
|
||||
@@ -56,13 +62,16 @@ iD.svg.Lines = function(projection) {
|
||||
}
|
||||
|
||||
if (!alength) {
|
||||
var arrow = surface.append('text').text(arrowtext);
|
||||
var container = surface.append('g')
|
||||
.attr('class', 'oneway'),
|
||||
arrow = container.append('text')
|
||||
.attr('class', 'textpath')
|
||||
.text(arrowtext);
|
||||
alength = arrow.node().getComputedTextLength();
|
||||
arrow.remove();
|
||||
container.remove();
|
||||
}
|
||||
|
||||
var lines = [],
|
||||
lineStrings = {};
|
||||
var lines = [];
|
||||
|
||||
for (var i = 0; i < entities.length; i++) {
|
||||
var entity = entities[i];
|
||||
@@ -80,13 +89,13 @@ iD.svg.Lines = function(projection) {
|
||||
stroke = surface.select('.layer-stroke'),
|
||||
defs = surface.select('defs'),
|
||||
text = surface.select('.layer-text'),
|
||||
shadows = drawPaths(shadow, lines, filter, 'way line shadow', lineString),
|
||||
casings = drawPaths(casing, lines, filter, 'way line casing', lineString),
|
||||
strokes = drawPaths(stroke, lines, filter, 'way line stroke', lineString);
|
||||
shadows = drawPaths(shadow, lines, filter, 'shadow', lineString),
|
||||
casings = drawPaths(casing, lines, filter, 'casing', lineString),
|
||||
strokes = drawPaths(stroke, lines, filter, 'stroke', lineString);
|
||||
|
||||
// Determine the lengths of oneway paths
|
||||
var lengths = {},
|
||||
oneways = strokes.filter(function (d) { return d.isOneWay(); }).each(function(d) {
|
||||
oneways = strokes.filter(function(d) { return d.isOneWay(); }).each(function(d) {
|
||||
lengths[d.id] = Math.floor(this.getTotalLength() / alength);
|
||||
}).data();
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ iD.svg.MemberClasses = function(graph) {
|
||||
classes += ' member';
|
||||
}
|
||||
|
||||
relations.forEach(function (relation) {
|
||||
relations.forEach(function(relation) {
|
||||
classes += ' member-type-' + relation.tags.type;
|
||||
classes += ' member-role-' + relation.memberById(d.id).role;
|
||||
});
|
||||
|
||||
@@ -2,6 +2,10 @@ iD.svg.Midpoints = function(projection) {
|
||||
return function drawMidpoints(surface, graph, entities, filter) {
|
||||
var midpoints = {};
|
||||
|
||||
if (!surface.select('.layer-hit g.vertex').node()) {
|
||||
return surface.selectAll('.layer-hit g.midpoint').remove();
|
||||
}
|
||||
|
||||
for (var i = 0; i < entities.length; i++) {
|
||||
if (entities[i].type !== 'way') continue;
|
||||
|
||||
@@ -15,19 +19,15 @@ iD.svg.Midpoints = function(projection) {
|
||||
b = nodes[j + 1],
|
||||
id = [a.id, b.id].sort().join('-');
|
||||
|
||||
if (!midpoints[id] &&
|
||||
iD.geo.dist(projection(a.loc), projection(b.loc)) > 40) {
|
||||
|
||||
var midpoint_loc = iD.geo.interp(a.loc, b.loc, 0.5),
|
||||
parents = _.intersection(graph.parentWays(a),
|
||||
graph.parentWays(b));
|
||||
if (midpoints[id]) {
|
||||
midpoints[id].ways.push({id: entity.id, index: j + 1});
|
||||
|
||||
} else if (iD.geo.dist(projection(a.loc), projection(b.loc)) > 40) {
|
||||
midpoints[id] = {
|
||||
loc: midpoint_loc,
|
||||
ways: parents,
|
||||
nodes: [a.id, b.id],
|
||||
type: 'midpoint',
|
||||
id: id,
|
||||
midpoint: true
|
||||
loc: iD.geo.interp(a.loc, b.loc, 0.5),
|
||||
ways: [{id: entity.id, index: j + 1}]
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -35,14 +35,14 @@ iD.svg.Midpoints = function(projection) {
|
||||
|
||||
var groups = surface.select('.layer-hit').selectAll('g.midpoint')
|
||||
.filter(filter)
|
||||
.data(_.values(midpoints), function (d) { return [d.parents, d.id].join(","); });
|
||||
.data(_.values(midpoints), function(d) { return d.id; });
|
||||
|
||||
var group = groups.enter()
|
||||
.insert('g', ':first-child')
|
||||
.attr('class', 'midpoint');
|
||||
|
||||
group.append('circle')
|
||||
.attr('r', 7)
|
||||
.attr('r', 8)
|
||||
.attr('class', 'shadow');
|
||||
|
||||
group.append('circle')
|
||||
@@ -51,6 +51,10 @@ iD.svg.Midpoints = function(projection) {
|
||||
|
||||
groups.attr('transform', iD.svg.PointTransform(projection));
|
||||
|
||||
// Propagate data bindings.
|
||||
groups.select('circle.shadow');
|
||||
groups.select('circle.fill');
|
||||
|
||||
groups.exit()
|
||||
.remove();
|
||||
};
|
||||
|
||||