├── .eslintrc.js
├── .gitignore
├── .jsbeautifyrc
├── LICENSE
├── README.md
├── docs
├── class-breaks-symbology
│ └── index.html
├── comparison
│ ├── css
│ │ ├── normalize.css
│ │ └── skeleton.css
│ └── index.html
├── csv-data
│ ├── Flowmap_Cities.csv
│ ├── Flowmap_Cities_many_to_one.csv
│ ├── Flowmap_Cities_one_to_many.csv
│ └── Flowmap_Cities_one_to_one.csv
└── main
│ └── index.html
├── img
└── img_01.png
└── src
└── CanvasFlowmapLayer.js
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | "env": {
3 | "browser": true
4 | },
5 | "globals": {
6 | "define": false,
7 | "require": false,
8 | "module": false,
9 | "L": false,
10 | "TWEEN": false,
11 | "Papa": false
12 | },
13 | "rules": {
14 | "no-debugger": "error",
15 | "no-bitwise": "error",
16 | "curly": "error",
17 | "eqeqeq": "error",
18 | "guard-for-in": "error",
19 | "block-scoped-var": "off",
20 | "no-use-before-define": "warn",
21 | "max-params": "off",
22 | "no-caller": "error",
23 | "no-new": "error",
24 | "no-shadow": "error",
25 | "strict": "off",
26 | "no-undef": "error",
27 | "no-unused-vars": "error",
28 | "no-eval": "off",
29 | "indent": ["error", 2, {
30 | "SwitchCase": 1
31 | }],
32 | "quotes": ["error", "single"]
33 | }
34 | };
35 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jwasilgeo/Leaflet.Canvas-Flowmap-Layer/7ae3238d3bbe11512eeda5ce47b5593c172b23e6/.gitignore
--------------------------------------------------------------------------------
/.jsbeautifyrc:
--------------------------------------------------------------------------------
1 | {
2 | "indent_size": 2,
3 | "indent_char": " ",
4 | "other": "",
5 | "indent_level": 0,
6 | "indent_with_tabs": false,
7 | "preserve_newlines": true,
8 | "max_preserve_newlines": 2,
9 | "indent_handlebars": true
10 | }
11 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Jacob Wasilkowski
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Leaflet.Canvas-Flowmap-Layer
2 |
3 | The `Leaflet.Canvas-Flowmap-Layer` is a custom layer plugin for [LeafletJS](http://leafletjs.com/) to map the flow of objects from an origin point to a destination point by using a Bezier curve. GeoJSON point feature coordinates are translated to pixel space so that rendering for the points and curves are mapped to an [HTMLCanvasElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement).
4 |
5 | **Demos:**
6 |
7 | - [Simple](https://jwasilgeo.github.io/Leaflet.Canvas-Flowmap-Layer/docs/main)
8 | - [Feature comparison](https://jwasilgeo.github.io/Leaflet.Canvas-Flowmap-Layer/docs/comparison) (aka: kitchen sink, sandbox)
9 | - [Advanced symbology: class breaks of flowlines](https://jwasilgeo.github.io/Leaflet.Canvas-Flowmap-Layer/docs/class-breaks-symbology)
10 |
11 | **Important!**
12 |
13 | This is a LeafletJS port of [sarahbellum/Canvas-Flowmap-Layer](https://www.github.com/sarahbellum/Canvas-Flowmap-Layer), which was originally written for the ArcGIS API for JavaScript. Go there to learn more!
14 |
15 | View our [**presentation at NACIS 2017**](https://www.youtube.com/watch?v=cRPx-BfBtv0).
16 |
17 | **Table of Contents:**
18 |
19 | - [Purpose and Background](#purpose-and-background)
20 | - [Options and More Information for Developers](#options-and-more-information-for-developers)
21 | - [Data Relationships](#data-relationships)
22 | - [Animation](#animation)
23 | - [Interaction](#interaction)
24 | - [Symbology](#symbology)
25 | - [API](#api)
26 | - [Constructor Summary](#constructor-summary)
27 | - [Options and Property Summary](#options-and-property-summary)
28 | - [Method Summary](#method-summary)
29 | - [Event Summary](#event-summary)
30 | - [Licensing](#licensing)
31 |
32 | [](https://jwasilgeo.github.io/Leaflet.Canvas-Flowmap-Layer/docs/main)
33 |
34 | ## Purpose and Background
35 |
36 | Please see [sarahbellum/Canvas-Flowmap-Layer#purpose](https://github.com/sarahbellum/Canvas-Flowmap-Layer#purpose) for more detailed information.
37 |
38 | ## Options and More Information for Developers
39 |
40 | ### Data Relationships
41 |
42 | "One-to-many", "many-to-one" and "one-to-one" origin-to-destination relationships are supported by this custom layer.
43 |
44 | **Important:** The developer must format and provide a GeoJSON point feature collection in a specific format. This layer expects that _both_ origin and destination attributes and spatial coordinates are available in each GeoJSON point feature's properties.
45 |
46 | Example of a single GeoJSON point feature within a feature collection that includes _both_ origin and destination info:
47 |
48 | ```json
49 | {
50 | "type": "Feature",
51 | "geometry": {
52 | "type": "Point",
53 | "coordinates":[109.6091129, 23.09653465]
54 | },
55 | "properties": {
56 | "origin_id": 238,
57 | "origin_city": "Hechi",
58 | "origin_country": "China",
59 | "origin_lon": 109.6091129,
60 | "origin_lat": 23.09653465,
61 | "destination_id": 1,
62 | "destination_city": "Sarh",
63 | "destination_country": "Chad",
64 | "destination_lon": 18.39002966,
65 | "destination_lat": 9.149969909
66 | }
67 | }
68 | ```
69 |
70 | Please see [sarahbellum/Canvas-Flowmap-Layer#data-relationships](https://github.com/sarahbellum/Canvas-Flowmap-Layer#data-relationships) for more details.
71 |
72 | ### Animation
73 |
74 | The animations rely on the [tween.js library](https://github.com/tweenjs/tween.js) to assist with changing the underlying line property values as well as providing many different easing functions and durations. See the `setAnimationDuration()` and `setAnimationEasing()` method descriptions below for more information.
75 |
76 | **Important:** If animations are going to be used, then the developer must first load the tween.js library.
77 |
78 | ```html
79 |
80 |
81 |
82 |
83 |
84 | ```
85 |
86 | ### Interaction
87 |
88 | You can change how users interact with the `Leaflet.CanvasFlowmapLayer` by controlling which Bezier curves appear and disappear at any time. The demos we provide show how to do this in several ways with LeafletJS `click` and `mouseover` events, coupled with using this layer's `selectFeaturesForPathDisplay()` method.
89 |
90 | For example, you could listen for a `click` event on an origin point feature—which is displayed on the map as an `L.CircleMarker`—and then choose to either **add** to your selection of displayed Bezier curves, **subtract** from your selection, or establish a brand **new** selection.
91 |
92 | Alternatively, you could set the `pathDisplayMode` option to `'all'` when constructing the layer to display every Bezier curve at once.
93 |
94 | ### Symbology
95 |
96 | The `Leaflet.Canvas-Flowmap-Layer` has default symbol styles established for origin and destination point `L.CircleMarker`s, canvas Bezier curves, and animated canvas Bezier curves.
97 |
98 | The default symbol styles for **origin and destination point** `L.CircleMarker`s can be changed by using the layer constructor option `style()` method, since this layer extends from `L.GeoJSON`.
99 |
100 | The default symbol styles for **canvas Bezier paths and animations** can be changed by overriding the layer constructor options for `canvasBezierStyle` and `animatedCanvasBezierStyle`, specifically using HTMLCanvasElement stroke and line style property names (instead of LeafletJS marker style properties).
101 |
102 | The caveat here is that this Leaflet version of the Canvas-Flowmap-Layer **and** the [Esri-compatible Canvas-Flowmap-Layer](https://github.com/sarahbellum/Canvas-Flowmap-Layer) both rely on symbol configurations that are defined using property objects inspired by the ArcGIS REST API renderer objects specification. Simple, unique value, and class breaks are all supported but instead use canvas stroke and line style property names. Specifically for this, read about the [ArcGIS REST API renderer objects specification](http://resources.arcgis.com/en/help/arcgis-rest-api/#/Renderer_objects/02r30000019t000000/).
103 |
104 | See the developer API section below and also [sarahbellum/Canvas-Flowmap-Layer#symbology](https://github.com/sarahbellum/Canvas-Flowmap-Layer#symbology) for more details. We have provided a demo page of how to set class breaks symbology for Bezier curves.
105 |
106 | ## API
107 |
108 | This extends the LeafletJS v1 [`L.GeoJSON` layer](http://leafletjs.com/reference-1.3.0.html#geojson). All properties, methods, and events provided by the `L.GeoJSON` layer are available in the `Leaflet.CanvasFlowmapLayer`, with additional custom features described below.
109 |
110 | ### Constructor Summary
111 |
112 | ```javascript
113 | var geoJsonFeatureCollection = {
114 | // collection of GeoJSON point features
115 | // with origin and destination attribute properties
116 |
117 | // see discussion above, demos, and CSV example data sources
118 | };
119 |
120 | var exampleFlowmapLayer = L.canvasFlowmapLayer(geoJsonFeatureCollection, {
121 | // required property for this custom layer,
122 | // which relies on the property names of your own data
123 | originAndDestinationFieldIds: {
124 | // all kinds of important stuff here...see docs below
125 |
126 | // however, this isn't required if your own data
127 | // is in the same format as the layer source code
128 | },
129 |
130 | // some custom options
131 | pathDisplayMode: 'selection',
132 | animationStarted: true,
133 | animationEasingFamily: 'Cubic',
134 | animationEasingType: 'In',
135 | animationDuration: 2000
136 | }).addTo(map);
137 | ```
138 |
139 | ### Options and Property Summary
140 |
141 | | Property | Description |
142 | | --- | --- |
143 | | `originAndDestinationFieldIds` | **Required if your data does not have the same property field names as the layer source code.** `Object`. This object informs the layer of your unique origin and destination attributes (fields). Both origins and destinations need to have their own unique ID attribute and geometry definition. [See example below](#originanddestinationfieldids-example) which includes minimum required object properties. |
144 | | `style` | _Optional_. `Function`. This function defines the symbol style properties of the origin and destination `L.CircleMarker`. [See example below](#style-example). |
145 | | `canvasBezierStyle` | _Optional_. `Object`. This object defines the symbol properties of the non-animated Bezier curve that is drawn on the canvas connecting an origin point to a destination point. [See Symbology discussion above](#symbology). |
146 | | `animatedCanvasBezierStyle` | _Optional_. `Object`. This defines the symbol properties of the animated Bezier curve that is drawn on the canvas directly on top of the non-animated Bezier curve. [See Symbology discussion above](#symbology). |
147 | | `pathDisplayMode` | _Optional_. `String`. Valid values: `'selection'` or `'all'`. Defaults to `'all'`. |
148 | | `wrapAroundCanvas` | _Optional_. `Boolean`. Defaults to `true`. Ensures that canvas features will be drawn beyond +/-180 longitude. |
149 | | `animationStarted` | _Optional_. `Boolean`. Defaults to `false`. This can be set during construction, but you should use the `playAnimation()` and `stopAnimation()` methods to control animations after layer construction. |
150 | | `animationDuration` | See `setAnimationDuration()` method description below. |
151 | | `animationEasingFamily` | See `setAnimationEasing()` method description below. |
152 | | `animationEasingType` | See `setAnimationEasing()` method description below. |
153 |
154 | **`originAndDestinationFieldIds` example:**
155 |
156 | (This is also the default in the layer source code.)
157 |
158 | ```javascript
159 | // this is only a default option example,
160 | // developers will most likely need to provide this
161 | // options object with values unique to their data
162 | originAndDestinationFieldIds: {
163 | originUniqueIdField: 'origin_id',
164 | originGeometry: {
165 | x: 'origin_lon',
166 | y: 'origin_lat'
167 | },
168 | destinationUniqueIdField: 'destination_id',
169 | destinationGeometry: {
170 | x: 'destination_lon',
171 | y: 'destination_lat'
172 | }
173 | }
174 | ```
175 |
176 | **`style` example:**
177 |
178 | (This is also the default in the layer source code.)
179 |
180 | ```javascript
181 | style: function(geoJsonFeature) {
182 | // use leaflet's path styling options
183 |
184 | // since the GeoJSON feature properties are modified by the layer,
185 | // developers can rely on the "isOrigin" property to set different
186 | // symbols for origin vs destination CircleMarker stylings
187 |
188 | if (geoJsonFeature.properties.isOrigin) {
189 | return {
190 | renderer: canvasRenderer, // recommended to use your own L.canvas()
191 | radius: 5,
192 | weight: 1,
193 | color: 'rgb(195, 255, 62)',
194 | fillColor: 'rgba(195, 255, 62, 0.6)',
195 | fillOpacity: 0.6
196 | };
197 | } else {
198 | return {
199 | renderer: canvasRenderer,
200 | radius: 2.5,
201 | weight: 0.25,
202 | color: 'rgb(17, 142, 170)',
203 | fillColor: 'rgb(17, 142, 170)',
204 | fillOpacity: 0.7
205 | };
206 | }
207 | }
208 | ```
209 |
210 | ### Method Summary
211 |
212 | | Method | Arguments | Description |
213 | | --- | --- | --- |
214 | | `selectFeaturesForPathDisplay( selectionFeatures, selectionMode )` | `selectionFeatures`: `Array` of origin or destination features already managed and displayed by the layer. `selectionMode`: `String`. Valid values: `'SELECTION_NEW'`, `'SELECTION_ADD'`, or `'SELECTION_SUBTRACT'`. | This informs the layer which Bezier curves should be drawn on the map. For example, you can most easily use this in conjunction with a `click` or `mouseover` event listener. |
215 | | `selectFeaturesForPathDisplayById( uniqueOriginOrDestinationIdField, idValue, originBoolean, selectionMode )` | | This is a convenience method if the unique origin or destination ID value is already known and you do not wish to rely on a `click` or `mouseover` event listener. |
216 | | `selectAllFeaturesForPathDisplay()` | | This informs the layer to select (and thus show) all Bezier curves. |
217 | | `clearAllPathSelections()` | | This informs the layer to unselect (and thus hide) all Bezier curves. |
218 | | `playAnimation()` | | This starts and shows Bezier curve animations. |
219 | | `stopAnimation()` | | This stops and hides any Bezier curve animations. |
220 | | `setAnimationDuration( duration )` | `duration`: _Optional_. `Number` in milliseconds. | This changes the animation duration. |
221 | | `setAnimationEasing( easingFamily, easingType )` | `easingFamily`: `String`. `easingType`: `String`. See `getAnimationEasingOptions()` method for info on valid values. | This changes the animation easing function with the help of the [tween.js library](https://github.com/tweenjs/tween.js). |
222 | | `getAnimationEasingOptions()` | | Returns information on valid `easingFamily` and `easingType` values based on the [tween.js library](https://github.com/tweenjs/tween.js). |
223 |
224 | ### Event Summary
225 |
226 | | Event | Description |
227 | | --- | --- |
228 | | `click` | Extends [layer `click`](http://leafletjs.com/reference-1.3.0.html#interactive-layer-click) and adds the following properties to the event object: `isOriginFeature`: `true` if an origin point has been clicked, but `false` if a destination point has been clicked. `sharedOriginFeatures`: `Array` of features that share the same origin. `sharedDestinationFeatures`: `Array` of features that share the same destination. |
229 | | `mouseover` | Extends [layer `mouseover`](http://leafletjs.com/reference-1.3.0.html#interactive-layer-mouseover) and adds the following properties to the event object: `isOriginFeature`: `true` when the mouse first entered an origin point, but `false` when the mouse first entered a destination point. `sharedOriginFeatures`: `Array` of features that share the same origin. `sharedDestinationFeatures`: `Array` of features that share the same destination. |
230 |
231 | ## Licensing
232 |
233 | A copy of the license is available in the repository's [LICENSE](./LICENSE) file.
234 |
--------------------------------------------------------------------------------
/docs/class-breaks-symbology/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Canvas Flowmap Layer with LeafletJS
10 |
11 |
12 |
13 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
163 |
164 |
165 |
166 |
167 |
--------------------------------------------------------------------------------
/docs/comparison/css/normalize.css:
--------------------------------------------------------------------------------
1 | /*! normalize.css v3.0.2 | MIT License | git.io/normalize */
2 |
3 | /**
4 | * 1. Set default font family to sans-serif.
5 | * 2. Prevent iOS text size adjust after orientation change, without disabling
6 | * user zoom.
7 | */
8 |
9 | html {
10 | font-family: sans-serif; /* 1 */
11 | -ms-text-size-adjust: 100%; /* 2 */
12 | -webkit-text-size-adjust: 100%; /* 2 */
13 | }
14 |
15 | /**
16 | * Remove default margin.
17 | */
18 |
19 | body {
20 | margin: 0;
21 | }
22 |
23 | /* HTML5 display definitions
24 | ========================================================================== */
25 |
26 | /**
27 | * Correct `block` display not defined for any HTML5 element in IE 8/9.
28 | * Correct `block` display not defined for `details` or `summary` in IE 10/11
29 | * and Firefox.
30 | * Correct `block` display not defined for `main` in IE 11.
31 | */
32 |
33 | article,
34 | aside,
35 | details,
36 | figcaption,
37 | figure,
38 | footer,
39 | header,
40 | hgroup,
41 | main,
42 | menu,
43 | nav,
44 | section,
45 | summary {
46 | display: block;
47 | }
48 |
49 | /**
50 | * 1. Correct `inline-block` display not defined in IE 8/9.
51 | * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.
52 | */
53 |
54 | audio,
55 | canvas,
56 | progress,
57 | video {
58 | display: inline-block; /* 1 */
59 | vertical-align: baseline; /* 2 */
60 | }
61 |
62 | /**
63 | * Prevent modern browsers from displaying `audio` without controls.
64 | * Remove excess height in iOS 5 devices.
65 | */
66 |
67 | audio:not([controls]) {
68 | display: none;
69 | height: 0;
70 | }
71 |
72 | /**
73 | * Address `[hidden]` styling not present in IE 8/9/10.
74 | * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22.
75 | */
76 |
77 | [hidden],
78 | template {
79 | display: none;
80 | }
81 |
82 | /* Links
83 | ========================================================================== */
84 |
85 | /**
86 | * Remove the gray background color from active links in IE 10.
87 | */
88 |
89 | a {
90 | background-color: transparent;
91 | }
92 |
93 | /**
94 | * Improve readability when focused and also mouse hovered in all browsers.
95 | */
96 |
97 | a:active,
98 | a:hover {
99 | outline: 0;
100 | }
101 |
102 | /* Text-level semantics
103 | ========================================================================== */
104 |
105 | /**
106 | * Address styling not present in IE 8/9/10/11, Safari, and Chrome.
107 | */
108 |
109 | abbr[title] {
110 | border-bottom: 1px dotted;
111 | }
112 |
113 | /**
114 | * Address style set to `bolder` in Firefox 4+, Safari, and Chrome.
115 | */
116 |
117 | b,
118 | strong {
119 | font-weight: bold;
120 | }
121 |
122 | /**
123 | * Address styling not present in Safari and Chrome.
124 | */
125 |
126 | dfn {
127 | font-style: italic;
128 | }
129 |
130 | /**
131 | * Address variable `h1` font-size and margin within `section` and `article`
132 | * contexts in Firefox 4+, Safari, and Chrome.
133 | */
134 |
135 | h1 {
136 | font-size: 2em;
137 | margin: 0.67em 0;
138 | }
139 |
140 | /**
141 | * Address styling not present in IE 8/9.
142 | */
143 |
144 | mark {
145 | background: #ff0;
146 | color: #000;
147 | }
148 |
149 | /**
150 | * Address inconsistent and variable font size in all browsers.
151 | */
152 |
153 | small {
154 | font-size: 80%;
155 | }
156 |
157 | /**
158 | * Prevent `sub` and `sup` affecting `line-height` in all browsers.
159 | */
160 |
161 | sub,
162 | sup {
163 | font-size: 75%;
164 | line-height: 0;
165 | position: relative;
166 | vertical-align: baseline;
167 | }
168 |
169 | sup {
170 | top: -0.5em;
171 | }
172 |
173 | sub {
174 | bottom: -0.25em;
175 | }
176 |
177 | /* Embedded content
178 | ========================================================================== */
179 |
180 | /**
181 | * Remove border when inside `a` element in IE 8/9/10.
182 | */
183 |
184 | img {
185 | border: 0;
186 | }
187 |
188 | /**
189 | * Correct overflow not hidden in IE 9/10/11.
190 | */
191 |
192 | svg:not(:root) {
193 | overflow: hidden;
194 | }
195 |
196 | /* Grouping content
197 | ========================================================================== */
198 |
199 | /**
200 | * Address margin not present in IE 8/9 and Safari.
201 | */
202 |
203 | figure {
204 | margin: 1em 40px;
205 | }
206 |
207 | /**
208 | * Address differences between Firefox and other browsers.
209 | */
210 |
211 | hr {
212 | -moz-box-sizing: content-box;
213 | box-sizing: content-box;
214 | height: 0;
215 | }
216 |
217 | /**
218 | * Contain overflow in all browsers.
219 | */
220 |
221 | pre {
222 | overflow: auto;
223 | }
224 |
225 | /**
226 | * Address odd `em`-unit font size rendering in all browsers.
227 | */
228 |
229 | code,
230 | kbd,
231 | pre,
232 | samp {
233 | font-family: monospace, monospace;
234 | font-size: 1em;
235 | }
236 |
237 | /* Forms
238 | ========================================================================== */
239 |
240 | /**
241 | * Known limitation: by default, Chrome and Safari on OS X allow very limited
242 | * styling of `select`, unless a `border` property is set.
243 | */
244 |
245 | /**
246 | * 1. Correct color not being inherited.
247 | * Known issue: affects color of disabled elements.
248 | * 2. Correct font properties not being inherited.
249 | * 3. Address margins set differently in Firefox 4+, Safari, and Chrome.
250 | */
251 |
252 | button,
253 | input,
254 | optgroup,
255 | select,
256 | textarea {
257 | color: inherit; /* 1 */
258 | font: inherit; /* 2 */
259 | margin: 0; /* 3 */
260 | }
261 |
262 | /**
263 | * Address `overflow` set to `hidden` in IE 8/9/10/11.
264 | */
265 |
266 | button {
267 | overflow: visible;
268 | }
269 |
270 | /**
271 | * Address inconsistent `text-transform` inheritance for `button` and `select`.
272 | * All other form control elements do not inherit `text-transform` values.
273 | * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.
274 | * Correct `select` style inheritance in Firefox.
275 | */
276 |
277 | button,
278 | select {
279 | text-transform: none;
280 | }
281 |
282 | /**
283 | * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
284 | * and `video` controls.
285 | * 2. Correct inability to style clickable `input` types in iOS.
286 | * 3. Improve usability and consistency of cursor style between image-type
287 | * `input` and others.
288 | */
289 |
290 | button,
291 | html input[type="button"], /* 1 */
292 | input[type="reset"],
293 | input[type="submit"] {
294 | -webkit-appearance: button; /* 2 */
295 | cursor: pointer; /* 3 */
296 | }
297 |
298 | /**
299 | * Re-set default cursor for disabled elements.
300 | */
301 |
302 | button[disabled],
303 | html input[disabled] {
304 | cursor: default;
305 | }
306 |
307 | /**
308 | * Remove inner padding and border in Firefox 4+.
309 | */
310 |
311 | button::-moz-focus-inner,
312 | input::-moz-focus-inner {
313 | border: 0;
314 | padding: 0;
315 | }
316 |
317 | /**
318 | * Address Firefox 4+ setting `line-height` on `input` using `!important` in
319 | * the UA stylesheet.
320 | */
321 |
322 | input {
323 | line-height: normal;
324 | }
325 |
326 | /**
327 | * It's recommended that you don't attempt to style these elements.
328 | * Firefox's implementation doesn't respect box-sizing, padding, or width.
329 | *
330 | * 1. Address box sizing set to `content-box` in IE 8/9/10.
331 | * 2. Remove excess padding in IE 8/9/10.
332 | */
333 |
334 | input[type="checkbox"],
335 | input[type="radio"] {
336 | box-sizing: border-box; /* 1 */
337 | padding: 0; /* 2 */
338 | }
339 |
340 | /**
341 | * Fix the cursor style for Chrome's increment/decrement buttons. For certain
342 | * `font-size` values of the `input`, it causes the cursor style of the
343 | * decrement button to change from `default` to `text`.
344 | */
345 |
346 | input[type="number"]::-webkit-inner-spin-button,
347 | input[type="number"]::-webkit-outer-spin-button {
348 | height: auto;
349 | }
350 |
351 | /**
352 | * 1. Address `appearance` set to `searchfield` in Safari and Chrome.
353 | * 2. Address `box-sizing` set to `border-box` in Safari and Chrome
354 | * (include `-moz` to future-proof).
355 | */
356 |
357 | input[type="search"] {
358 | -webkit-appearance: textfield; /* 1 */
359 | -moz-box-sizing: content-box;
360 | -webkit-box-sizing: content-box; /* 2 */
361 | box-sizing: content-box;
362 | }
363 |
364 | /**
365 | * Remove inner padding and search cancel button in Safari and Chrome on OS X.
366 | * Safari (but not Chrome) clips the cancel button when the search input has
367 | * padding (and `textfield` appearance).
368 | */
369 |
370 | input[type="search"]::-webkit-search-cancel-button,
371 | input[type="search"]::-webkit-search-decoration {
372 | -webkit-appearance: none;
373 | }
374 |
375 | /**
376 | * Define consistent border, margin, and padding.
377 | */
378 |
379 | fieldset {
380 | border: 1px solid #c0c0c0;
381 | margin: 0 2px;
382 | padding: 0.35em 0.625em 0.75em;
383 | }
384 |
385 | /**
386 | * 1. Correct `color` not being inherited in IE 8/9/10/11.
387 | * 2. Remove padding so people aren't caught out if they zero out fieldsets.
388 | */
389 |
390 | legend {
391 | border: 0; /* 1 */
392 | padding: 0; /* 2 */
393 | }
394 |
395 | /**
396 | * Remove default vertical scrollbar in IE 8/9/10/11.
397 | */
398 |
399 | textarea {
400 | overflow: auto;
401 | }
402 |
403 | /**
404 | * Don't inherit the `font-weight` (applied by a rule above).
405 | * NOTE: the default cannot safely be changed in Chrome and Safari on OS X.
406 | */
407 |
408 | optgroup {
409 | font-weight: bold;
410 | }
411 |
412 | /* Tables
413 | ========================================================================== */
414 |
415 | /**
416 | * Remove most spacing between table cells.
417 | */
418 |
419 | table {
420 | border-collapse: collapse;
421 | border-spacing: 0;
422 | }
423 |
424 | td,
425 | th {
426 | padding: 0;
427 | }
--------------------------------------------------------------------------------
/docs/comparison/css/skeleton.css:
--------------------------------------------------------------------------------
1 | /*
2 | * Skeleton V2.0.4
3 | * Copyright 2014, Dave Gamache
4 | * www.getskeleton.com
5 | * Free to use under the MIT license.
6 | * http://www.opensource.org/licenses/mit-license.php
7 | * 12/29/2014
8 | */
9 |
10 |
11 | /* Table of contents
12 | ––––––––––––––––––––––––––––––––––––––––––––––––––
13 | - Grid
14 | - Base Styles
15 | - Typography
16 | - Links
17 | - Buttons
18 | - Forms
19 | - Lists
20 | - Code
21 | - Tables
22 | - Spacing
23 | - Utilities
24 | - Clearing
25 | - Media Queries
26 | */
27 |
28 |
29 | /* Grid
30 | –––––––––––––––––––––––––––––––––––––––––––––––––– */
31 | .container {
32 | position: relative;
33 | width: 100%;
34 | max-width: 960px;
35 | margin: 0 auto;
36 | padding: 0 20px;
37 | box-sizing: border-box; }
38 | .column,
39 | .columns {
40 | width: 100%;
41 | float: left;
42 | box-sizing: border-box; }
43 |
44 | /* For devices larger than 400px */
45 | @media (min-width: 400px) {
46 | .container {
47 | width: 85%;
48 | padding: 0; }
49 | }
50 |
51 | /* For devices larger than 550px */
52 | @media (min-width: 550px) {
53 | .container {
54 | width: 80%; }
55 | .column,
56 | .columns {
57 | margin-left: 4%; }
58 | .column:first-child,
59 | .columns:first-child {
60 | margin-left: 0; }
61 |
62 | .one.column,
63 | .one.columns { width: 4.66666666667%; }
64 | .two.columns { width: 13.3333333333%; }
65 | .three.columns { width: 22%; }
66 | .four.columns { width: 30.6666666667%; }
67 | .five.columns { width: 39.3333333333%; }
68 | .six.columns { width: 48%; }
69 | .seven.columns { width: 56.6666666667%; }
70 | .eight.columns { width: 65.3333333333%; }
71 | .nine.columns { width: 74.0%; }
72 | .ten.columns { width: 82.6666666667%; }
73 | .eleven.columns { width: 91.3333333333%; }
74 | .twelve.columns { width: 100%; margin-left: 0; }
75 |
76 | .one-third.column { width: 30.6666666667%; }
77 | .two-thirds.column { width: 65.3333333333%; }
78 |
79 | .one-half.column { width: 48%; }
80 |
81 | /* Offsets */
82 | .offset-by-one.column,
83 | .offset-by-one.columns { margin-left: 8.66666666667%; }
84 | .offset-by-two.column,
85 | .offset-by-two.columns { margin-left: 17.3333333333%; }
86 | .offset-by-three.column,
87 | .offset-by-three.columns { margin-left: 26%; }
88 | .offset-by-four.column,
89 | .offset-by-four.columns { margin-left: 34.6666666667%; }
90 | .offset-by-five.column,
91 | .offset-by-five.columns { margin-left: 43.3333333333%; }
92 | .offset-by-six.column,
93 | .offset-by-six.columns { margin-left: 52%; }
94 | .offset-by-seven.column,
95 | .offset-by-seven.columns { margin-left: 60.6666666667%; }
96 | .offset-by-eight.column,
97 | .offset-by-eight.columns { margin-left: 69.3333333333%; }
98 | .offset-by-nine.column,
99 | .offset-by-nine.columns { margin-left: 78.0%; }
100 | .offset-by-ten.column,
101 | .offset-by-ten.columns { margin-left: 86.6666666667%; }
102 | .offset-by-eleven.column,
103 | .offset-by-eleven.columns { margin-left: 95.3333333333%; }
104 |
105 | .offset-by-one-third.column,
106 | .offset-by-one-third.columns { margin-left: 34.6666666667%; }
107 | .offset-by-two-thirds.column,
108 | .offset-by-two-thirds.columns { margin-left: 69.3333333333%; }
109 |
110 | .offset-by-one-half.column,
111 | .offset-by-one-half.columns { margin-left: 52%; }
112 |
113 | }
114 |
115 |
116 | /* Base Styles
117 | –––––––––––––––––––––––––––––––––––––––––––––––––– */
118 | /* NOTE
119 | html is set to 62.5% so that all the REM measurements throughout Skeleton
120 | are based on 10px sizing. So basically 1.5rem = 15px :) */
121 | html {
122 | font-size: 62.5%; }
123 | body {
124 | font-size: 1.5em; /* currently ems cause chrome bug misinterpreting rems on body element */
125 | line-height: 1.6;
126 | font-weight: 400;
127 | font-family: "Raleway", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif;
128 | color: #222; }
129 |
130 |
131 | /* Typography
132 | –––––––––––––––––––––––––––––––––––––––––––––––––– */
133 | h1, h2, h3, h4, h5, h6 {
134 | margin-top: 0;
135 | margin-bottom: 2rem;
136 | font-weight: 300; }
137 | h1 { font-size: 4.0rem; line-height: 1.2; letter-spacing: -.1rem;}
138 | h2 { font-size: 3.6rem; line-height: 1.25; letter-spacing: -.1rem; }
139 | h3 { font-size: 3.0rem; line-height: 1.3; letter-spacing: -.1rem; }
140 | h4 { font-size: 2.4rem; line-height: 1.35; letter-spacing: -.08rem; }
141 | h5 { font-size: 1.8rem; line-height: 1.5; letter-spacing: -.05rem; }
142 | h6 { font-size: 1.5rem; line-height: 1.6; letter-spacing: 0; }
143 |
144 | /* Larger than phablet */
145 | @media (min-width: 550px) {
146 | h1 { font-size: 5.0rem; }
147 | h2 { font-size: 4.2rem; }
148 | h3 { font-size: 3.6rem; }
149 | h4 { font-size: 3.0rem; }
150 | h5 { font-size: 2.4rem; }
151 | h6 { font-size: 1.5rem; }
152 | }
153 |
154 | p {
155 | margin-top: 0; }
156 |
157 |
158 | /* Links
159 | –––––––––––––––––––––––––––––––––––––––––––––––––– */
160 | a {
161 | color: #1EAEDB; }
162 | a:hover {
163 | color: #0FA0CE; }
164 |
165 |
166 | /* Buttons
167 | –––––––––––––––––––––––––––––––––––––––––––––––––– */
168 | .button,
169 | button,
170 | input[type="submit"],
171 | input[type="reset"],
172 | input[type="button"] {
173 | display: inline-block;
174 | height: 38px;
175 | padding: 0 30px;
176 | color: #555;
177 | text-align: center;
178 | font-size: 11px;
179 | font-weight: 600;
180 | line-height: 38px;
181 | letter-spacing: .1rem;
182 | text-transform: uppercase;
183 | text-decoration: none;
184 | white-space: nowrap;
185 | background-color: transparent;
186 | border-radius: 4px;
187 | border: 1px solid #bbb;
188 | cursor: pointer;
189 | box-sizing: border-box; }
190 | .button:hover,
191 | button:hover,
192 | input[type="submit"]:hover,
193 | input[type="reset"]:hover,
194 | input[type="button"]:hover,
195 | .button:focus,
196 | button:focus,
197 | input[type="submit"]:focus,
198 | input[type="reset"]:focus,
199 | input[type="button"]:focus {
200 | color: #333;
201 | border-color: #888;
202 | outline: 0; }
203 | .button.button-primary,
204 | button.button-primary,
205 | input[type="submit"].button-primary,
206 | input[type="reset"].button-primary,
207 | input[type="button"].button-primary {
208 | color: #FFF;
209 | background-color: #33C3F0;
210 | border-color: #33C3F0; }
211 | .button.button-primary:hover,
212 | button.button-primary:hover,
213 | input[type="submit"].button-primary:hover,
214 | input[type="reset"].button-primary:hover,
215 | input[type="button"].button-primary:hover,
216 | .button.button-primary:focus,
217 | button.button-primary:focus,
218 | input[type="submit"].button-primary:focus,
219 | input[type="reset"].button-primary:focus,
220 | input[type="button"].button-primary:focus {
221 | color: #FFF;
222 | background-color: #1EAEDB;
223 | border-color: #1EAEDB; }
224 |
225 |
226 | /* Forms
227 | –––––––––––––––––––––––––––––––––––––––––––––––––– */
228 | input[type="email"],
229 | input[type="number"],
230 | input[type="search"],
231 | input[type="text"],
232 | input[type="tel"],
233 | input[type="url"],
234 | input[type="password"],
235 | textarea,
236 | select {
237 | height: 38px;
238 | padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */
239 | background-color: #fff;
240 | border: 1px solid #D1D1D1;
241 | border-radius: 4px;
242 | box-shadow: none;
243 | box-sizing: border-box; }
244 | /* Removes awkward default styles on some inputs for iOS */
245 | input[type="email"],
246 | input[type="number"],
247 | input[type="search"],
248 | input[type="text"],
249 | input[type="tel"],
250 | input[type="url"],
251 | input[type="password"],
252 | textarea {
253 | -webkit-appearance: none;
254 | -moz-appearance: none;
255 | appearance: none; }
256 | textarea {
257 | min-height: 65px;
258 | padding-top: 6px;
259 | padding-bottom: 6px; }
260 | input[type="email"]:focus,
261 | input[type="number"]:focus,
262 | input[type="search"]:focus,
263 | input[type="text"]:focus,
264 | input[type="tel"]:focus,
265 | input[type="url"]:focus,
266 | input[type="password"]:focus,
267 | textarea:focus,
268 | select:focus {
269 | border: 1px solid #33C3F0;
270 | outline: 0; }
271 | label,
272 | legend {
273 | display: block;
274 | margin-bottom: .5rem;
275 | font-weight: 600; }
276 | fieldset {
277 | padding: 0;
278 | border-width: 0; }
279 | input[type="checkbox"],
280 | input[type="radio"] {
281 | display: inline; }
282 | label > .label-body {
283 | display: inline-block;
284 | margin-left: .5rem;
285 | font-weight: normal; }
286 |
287 |
288 | /* Lists
289 | –––––––––––––––––––––––––––––––––––––––––––––––––– */
290 | ul {
291 | list-style: circle inside; }
292 | ol {
293 | list-style: decimal inside; }
294 | ol, ul {
295 | padding-left: 0;
296 | margin-top: 0; }
297 | ul ul,
298 | ul ol,
299 | ol ol,
300 | ol ul {
301 | margin: 1.5rem 0 1.5rem 3rem;
302 | font-size: 90%; }
303 | li {
304 | margin-bottom: 1rem; }
305 |
306 |
307 | /* Code
308 | –––––––––––––––––––––––––––––––––––––––––––––––––– */
309 | code {
310 | padding: .2rem .5rem;
311 | margin: 0 .2rem;
312 | font-size: 90%;
313 | white-space: nowrap;
314 | background: #F1F1F1;
315 | border: 1px solid #E1E1E1;
316 | border-radius: 4px; }
317 | pre > code {
318 | display: block;
319 | padding: 1rem 1.5rem;
320 | white-space: pre; }
321 |
322 |
323 | /* Tables
324 | –––––––––––––––––––––––––––––––––––––––––––––––––– */
325 | th,
326 | td {
327 | padding: 12px 15px;
328 | text-align: left;
329 | border-bottom: 1px solid #E1E1E1; }
330 | th:first-child,
331 | td:first-child {
332 | padding-left: 0; }
333 | th:last-child,
334 | td:last-child {
335 | padding-right: 0; }
336 |
337 |
338 | /* Spacing
339 | –––––––––––––––––––––––––––––––––––––––––––––––––– */
340 | button,
341 | .button {
342 | margin-bottom: 1rem; }
343 | input,
344 | textarea,
345 | select,
346 | fieldset {
347 | margin-bottom: 1.5rem; }
348 | pre,
349 | blockquote,
350 | dl,
351 | figure,
352 | table,
353 | p,
354 | ul,
355 | ol,
356 | form {
357 | margin-bottom: 2.5rem; }
358 |
359 |
360 | /* Utilities
361 | –––––––––––––––––––––––––––––––––––––––––––––––––– */
362 | .u-full-width {
363 | width: 100%;
364 | box-sizing: border-box; }
365 | .u-max-full-width {
366 | max-width: 100%;
367 | box-sizing: border-box; }
368 | .u-pull-right {
369 | float: right; }
370 | .u-pull-left {
371 | float: left; }
372 |
373 |
374 | /* Misc
375 | –––––––––––––––––––––––––––––––––––––––––––––––––– */
376 | hr {
377 | margin-top: 3rem;
378 | margin-bottom: 3.5rem;
379 | border-width: 0;
380 | border-top: 1px solid #E1E1E1; }
381 |
382 |
383 | /* Clearing
384 | –––––––––––––––––––––––––––––––––––––––––––––––––– */
385 |
386 | /* Self Clearing Goodness */
387 | .container:after,
388 | .row:after,
389 | .u-cf {
390 | content: "";
391 | display: table;
392 | clear: both; }
393 |
394 |
395 | /* Media Queries
396 | –––––––––––––––––––––––––––––––––––––––––––––––––– */
397 | /*
398 | Note: The best way to structure the use of media queries is to create the queries
399 | near the relevant code. For example, if you wanted to change the styles for buttons
400 | on small devices, paste the mobile query code up in the buttons section and style it
401 | there.
402 | */
403 |
404 |
405 | /* Larger than mobile */
406 | @media (min-width: 400px) {}
407 |
408 | /* Larger than phablet (also point when grid becomes active) */
409 | @media (min-width: 550px) {}
410 |
411 | /* Larger than tablet */
412 | @media (min-width: 750px) {}
413 |
414 | /* Larger than desktop */
415 | @media (min-width: 1000px) {}
416 |
417 | /* Larger than Desktop HD */
418 | @media (min-width: 1200px) {}
419 |
--------------------------------------------------------------------------------
/docs/comparison/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Canvas Flowmap Layer with LeafletJS
10 |
11 |
12 |
13 |
14 |
15 |
16 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
Canvas Flowmap Layer
99 |
100 |
101 | Explore origin-to-destination layers with different relationships:
102 |
103 |
One-to-Many
104 |
Many-to-One
105 |
One-to-One
106 |
107 |
108 | Change animation properties:
109 |
110 |
111 |
112 | Pause
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 | duration (ms)
122 |
123 |
124 |
125 | Change user interaction and path selection properties:
126 |
127 |
128 |
129 |
130 | Click
131 | Mouseover
132 |
133 |
134 |
135 |
136 | New
137 | Add
138 | Subtract
139 |
140 |
141 |
142 |
143 |
144 |
145 | Show All
146 |
147 |
148 | Clear All
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
372 |
373 |
374 |
375 |
--------------------------------------------------------------------------------
/docs/csv-data/Flowmap_Cities_one_to_many.csv:
--------------------------------------------------------------------------------
1 | s_city_id,s_city,s_lat,s_lon,s_pop,s_country,s_Volume,e_city_id,e_City,e_lat,e_lon,e_pop,e_country,e_vol
2 | 238,Hechi,23.09653465,109.6091129,3275189.5,China,291099,1,Sarh,9.149969909,18.39002966,135862,Chad,1
3 | 238,Hechi,23.09653465,109.6091129,3275189.5,China,291099,2,Tandil,-37.32001015,-59.15004358,84799.5,Argentina,1
4 | 238,Hechi,23.09653465,109.6091129,3275189.5,China,291099,3,Victorville,34.5365082,-117.2903191,83496,United States of America,1
5 | 238,Hechi,23.09653465,109.6091129,3275189.5,China,291099,4,Cranbourne,-38.09960081,145.2833695,249955,Australia,1
6 | 238,Hechi,23.09653465,109.6091129,3275189.5,China,291099,5,Curico,-34.97999795,-71.24002914,108074.5,Chile,1
7 | 238,Hechi,23.09653465,109.6091129,3275189.5,China,291099,6,Dahuk,36.86670013,43.00000263,620500,Iraq,1
8 | 238,Hechi,23.09653465,109.6091129,3275189.5,China,291099,7,Olympia,47.03804486,-122.899434,100950,United States of America,1
9 | 238,Hechi,23.09653465,109.6091129,3275189.5,China,291099,8,Oostanay,53.22089744,63.62830196,223450.5,Kazakhstan,1
10 | 238,Hechi,23.09653465,109.6091129,3275189.5,China,291099,9,Oran,35.71000246,-0.61997278,721992,Algeria,1
11 | 623,San Jose,9.93501243,-84.08405135,642862,Costa Rica,302064,10,Asheville,35.60119773,-82.55414474,105775,United States of America,1
12 | 623,San Jose,9.93501243,-84.08405135,642862,Costa Rica,302064,11,Asti,44.92998232,8.209979206,63410.5,Italy,1
13 | 623,San Jose,9.93501243,-84.08405135,642862,Costa Rica,302064,12,Athens,33.96129783,-83.3780221,78017.5,United States of America,1
14 | 623,San Jose,9.93501243,-84.08405135,642862,Costa Rica,302064,13,Atlanta,33.83001385,-84.39994938,2464454,United States of America,1
15 | 623,San Jose,9.93501243,-84.08405135,642862,Costa Rica,302064,14,Atyrau,47.11269147,51.92002437,170583,Kazakhstan,1
16 | 623,San Jose,9.93501243,-84.08405135,642862,Costa Rica,302064,15,Aurora,41.76539512,-88.29999557,273949.5,United States of America,1
17 | 623,San Jose,9.93501243,-84.08405135,642862,Costa Rica,302064,16,Babruysk,53.12656211,29.19278113,212821.5,Belarus,1
18 | 222,Haifa,32.8204114,34.98002478,639150,Israel,400017,17,Ballarat,-37.55958209,143.8400468,73404,Australia,1
19 | 222,Haifa,32.8204114,34.98002478,639150,Israel,400017,18,Barnaul,53.35499778,83.74500688,569711,Russia,1
20 | 222,Haifa,32.8204114,34.98002478,639150,Israel,400017,19,Lanzhou,36.05602785,103.7920003,2282609,China,1
21 | 222,Haifa,32.8204114,34.98002478,639150,Israel,400017,20,L'Aquila,42.35039817,13.39002478,62201.5,Italy,1
22 | 222,Haifa,32.8204114,34.98002478,639150,Israel,400017,21,Larache,35.20042116,-6.160022218,114688,Morocco,1
23 | 222,Haifa,32.8204114,34.98002478,639150,Israel,400017,22,Le Mans,48.00041506,0.099983275,143392.5,France,1
24 | 657,Ulaanbaatar,47.9166734,106.9166158,827306,Mongolia,645321,23,Elkhart,41.68294537,-85.96879419,100295,United States of America,1
25 | 657,Ulaanbaatar,47.9166734,106.9166158,827306,Mongolia,645321,24,Encarnacion,-27.34718482,-55.87391878,251813.5,Paraguay,1
26 | 657,Ulaanbaatar,47.9166734,106.9166158,827306,Mongolia,645321,25,Erechim,-27.63000731,-52.26999841,85365.5,Brazil,1
27 | 657,Ulaanbaatar,47.9166734,106.9166158,827306,Mongolia,645321,26,Everett,47.9604175,-122.1999677,291948,United States of America,1
28 | 657,Ulaanbaatar,47.9166734,106.9166158,827306,Mongolia,645321,27,Exeter,50.70040529,-3.529950197,108242,United Kingdom,1
29 | 657,Ulaanbaatar,47.9166734,106.9166158,827306,Mongolia,645321,28,Faisalabad,31.40998069,73.10999711,2561797.5,Pakistan,1
30 | 657,Ulaanbaatar,47.9166734,106.9166158,827306,Mongolia,645321,29,Fargo,46.8772278,-96.7894257,127472.5,United States of America,1
31 | 657,Ulaanbaatar,47.9166734,106.9166158,827306,Mongolia,645321,30,Fayetteville,36.06297833,-94.15720911,108267.5,United States of America,1
32 | 657,Ulaanbaatar,47.9166734,106.9166158,827306,Mongolia,645321,31,Florianopolis,-27.57998452,-48.52002059,568783,Brazil,1
33 | 657,Ulaanbaatar,47.9166734,106.9166158,827306,Mongolia,645321,32,Fort Pierce,27.44678591,-80.3258053,132984,United States of America,1
34 | 657,Ulaanbaatar,47.9166734,106.9166158,827306,Mongolia,645321,33,Fort Wayne,41.08039817,-85.12998234,264793,United States of America,1
35 | 657,Ulaanbaatar,47.9166734,106.9166158,827306,Mongolia,645321,34,Fresno,36.7477169,-119.7729841,540768,United States of America,1
36 | 657,Ulaanbaatar,47.9166734,106.9166158,827306,Mongolia,645321,35,Ft. Myers,26.64029767,-81.86049199,120810.5,United States of America,1
37 | 657,Ulaanbaatar,47.9166734,106.9166158,827306,Mongolia,645321,36,Fukui,36.07041974,136.2200468,241288.5,Japan,1
38 | 657,Ulaanbaatar,47.9166734,106.9166158,827306,Mongolia,645321,37,Furth,49.47001528,10.99998979,174934.5,Germany,1
39 | 657,Ulaanbaatar,47.9166734,106.9166158,827306,Mongolia,645321,38,Gävle,60.66698041,17.1666418,68235.5,Sweden,1
40 | 657,Ulaanbaatar,47.9166734,106.9166158,827306,Mongolia,645321,39,Galway,53.272393,-9.048812298,73140,Ireland,1
41 | 657,Ulaanbaatar,47.9166734,106.9166158,827306,Mongolia,645321,40,Ganca,40.68499595,46.35002844,301699.5,Azerbaijan,1
42 | 657,Ulaanbaatar,47.9166734,106.9166158,827306,Mongolia,645321,41,Ganzhou,25.91997988,114.9500272,1216134.5,China,1
43 | 657,Ulaanbaatar,47.9166734,106.9166158,827306,Mongolia,645321,42,Garissa,-0.439625632,39.67002274,65948,Kenya,1
44 | 262,Johannesburg,-26.17004474,28.03000972,2730734.5,South Africa,666365,43,Chengdu,30.67000002,104.0700195,4036718.5,China,1
45 | 262,Johannesburg,-26.17004474,28.03000972,2730734.5,South Africa,666365,44,Chester,53.20002016,-2.919987428,83285.5,United Kingdom,1
46 | 262,Johannesburg,-26.17004474,28.03000972,2730734.5,South Africa,666365,45,Chihuahua,28.64498151,-106.0849823,750633.5,Mexico,1
47 | 262,Johannesburg,-26.17004474,28.03000972,2730734.5,South Africa,666365,46,Chita,52.05502545,113.4650016,293153.5,Russia,1
48 | 262,Johannesburg,-26.17004474,28.03000972,2730734.5,South Africa,666365,47,Chlef,36.17041363,1.319960489,449167,Algeria,1
49 | 262,Johannesburg,-26.17004474,28.03000972,2730734.5,South Africa,666365,48,Daytona Beach,29.21055422,-81.0230754,140775.5,United States of America,1
50 | 262,Johannesburg,-26.17004474,28.03000972,2730734.5,South Africa,666365,49,Denton,33.21576194,-97.12883651,138952.5,United States of America,1
51 | 262,Johannesburg,-26.17004474,28.03000972,2730734.5,South Africa,666365,50,Detroit,42.32996014,-83.08005579,2526135,United States of America,1
52 | 262,Johannesburg,-26.17004474,28.03000972,2730734.5,South Africa,666365,51,Divinopolis,-20.14953367,-44.89998316,181457,Brazil,1
53 | 262,Johannesburg,-26.17004474,28.03000972,2730734.5,South Africa,666365,52,Dondo,-19.61959186,34.7300142,75217.5,Mozambique,1
54 | 262,Johannesburg,-26.17004474,28.03000972,2730734.5,South Africa,666365,53,Dongguan,23.0488889,113.7447222,4528000,China,1
55 | 262,Johannesburg,-26.17004474,28.03000972,2730734.5,South Africa,666365,54,Dresden,51.04997052,13.75000281,552184.5,Germany,1
56 | 262,Johannesburg,-26.17004474,28.03000972,2730734.5,South Africa,666365,55,Drohobych,49.34436403,23.49938188,101837.5,Ukraine,1
57 | 262,Johannesburg,-26.17004474,28.03000972,2730734.5,South Africa,666365,56,Dublin,53.33306114,-6.248905682,1013988,Ireland,1
58 | 183,Dakar,14.71583173,-17.47313013,2540200,Senegal,765122,57,Beirut,33.87197512,35.50970821,1779062.5,Lebanon,1
59 | 183,Dakar,14.71583173,-17.47313013,2540200,Senegal,765122,58,Linhares,-19.38999347,-40.05002079,86413,Brazil,1
60 | 183,Dakar,14.71583173,-17.47313013,2540200,Senegal,765122,59,Linköping,58.41001223,15.62993974,94111.5,Sweden,1
61 | 183,Dakar,14.71583173,-17.47313013,2540200,Senegal,765122,60,Linyi,35.07998924,118.329976,1176334.5,China,1
62 | 183,Dakar,14.71583173,-17.47313013,2540200,Senegal,765122,61,Liverpool,53.41600181,-2.917997886,639972.5,United Kingdom,1
63 | 183,Dakar,14.71583173,-17.47313013,2540200,Senegal,765122,62,Lobito,-12.37000853,13.54123002,170733,Angola,1
64 | 183,Dakar,14.71583173,-17.47313013,2540200,Senegal,765122,63,Logrono,42.47036501,-2.429991497,123918.5,Spain,1
65 | 183,Dakar,14.71583173,-17.47313013,2540200,Senegal,765122,64,Londonderry,55.00037539,-7.333283937,82635,United Kingdom,1
66 | 183,Dakar,14.71583173,-17.47313013,2540200,Senegal,765122,65,Lorient,47.75040448,-3.366575156,71532,France,1
67 | 183,Dakar,14.71583173,-17.47313013,2540200,Senegal,765122,66,Los Angeles,-37.46000161,-72.35998661,135334.5,Chile,1
68 | 183,Dakar,14.71583173,-17.47313013,2540200,Senegal,765122,67,Louangphrabang,19.88453432,102.1416101,77260,Laos,1
69 | 183,Dakar,14.71583173,-17.47313013,2540200,Senegal,765122,68,Lujan,-34.57960895,-59.10999435,69744.5,Argentina,1
70 | 183,Dakar,14.71583173,-17.47313013,2540200,Senegal,765122,69,Santiago del Estero,-27.78333128,-64.26665633,317549.5,Argentina,1
71 | 183,Dakar,14.71583173,-17.47313013,2540200,Senegal,765122,70,Junin,-34.58456989,-60.95887374,66141.5,Argentina,1
72 | 183,Dakar,14.71583173,-17.47313013,2540200,Senegal,765122,71,Kagoshima,31.58596478,130.561064,536092.5,Japan,1
73 | 183,Dakar,14.71583173,-17.47313013,2540200,Senegal,765122,72,Kakamega,0.290407327,34.7300142,63426,Kenya,1
74 | 183,Dakar,14.71583173,-17.47313013,2540200,Senegal,765122,73,Kalamata,37.03891359,22.11419511,61465.5,Greece,1
75 | 183,Dakar,14.71583173,-17.47313013,2540200,Senegal,765122,74,Kalamazoo,42.29215883,-85.58718958,128759.5,United States of America,1
76 | 183,Dakar,14.71583173,-17.47313013,2540200,Senegal,765122,75,Kamensk Uralskiy,56.42046958,61.9350203,176598.5,Russia,1
77 | 183,Dakar,14.71583173,-17.47313013,2540200,Senegal,765122,76,Kampong Cham,12.00044191,105.4500386,72491.5,Cambodia,1
78 | 183,Dakar,14.71583173,-17.47313013,2540200,Senegal,765122,77,Kamyanets-Podilskyy,48.68430096,26.58089921,107329,Ukraine,1
79 | 183,Dakar,14.71583173,-17.47313013,2540200,Senegal,765122,78,Kamyshin,50.08039146,45.40000891,82613,Russia,1
80 | 183,Dakar,14.71583173,-17.47313013,2540200,Senegal,765122,79,Kanazawa,36.56000226,136.6400211,505093,Japan,1
81 | 183,Dakar,14.71583173,-17.47313013,2540200,Senegal,765122,80,Kanoya,31.38331565,130.8500386,68513.5,Japan,1
82 | 183,Dakar,14.71583173,-17.47313013,2540200,Senegal,765122,81,Rostock,54.07038047,12.14999711,200686.5,Germany,1
83 | 183,Dakar,14.71583173,-17.47313013,2540200,Senegal,765122,82,Skopje,42.00000612,21.43346147,484488,Macedonia,1
84 | 183,Dakar,14.71583173,-17.47313013,2540200,Senegal,765122,83,Townsville,-19.24995034,146.7699971,129212,Australia,1
85 | 183,Dakar,14.71583173,-17.47313013,2540200,Senegal,765122,84,Szekesfehervar,47.19467613,18.40806474,122959.5,Hungary,1
86 | 183,Dakar,14.71583173,-17.47313013,2540200,Senegal,765122,85,Van,38.49543968,43.39997595,326262,Turkey,1
87 | 183,Dakar,14.71583173,-17.47313013,2540200,Senegal,765122,86,Mainz,49.98247246,8.273219156,184997,Germany,1
88 | 183,Dakar,14.71583173,-17.47313013,2540200,Senegal,765122,87,Maizuru,35.4504059,135.3333309,62531.5,Japan,1
89 | 183,Dakar,14.71583173,-17.47313013,2540200,Senegal,765122,88,Makkah,21.43002138,39.82003943,1354312,Saudi Arabia,1
90 | 183,Dakar,14.71583173,-17.47313013,2540200,Senegal,765122,89,Malacca,2.206414407,102.2464615,645916.5,Malaysia,1
91 | 183,Dakar,14.71583173,-17.47313013,2540200,Senegal,765122,90,Maladzyechna,54.31878908,26.86532629,96055,Belarus,1
92 | 183,Dakar,14.71583173,-17.47313013,2540200,Senegal,765122,91,Malanje,-9.540000388,16.34002559,106451,Angola,1
93 | 183,Dakar,14.71583173,-17.47313013,2540200,Senegal,765122,92,Male,4.16670819,73.49994747,108310,Maldives,1
94 | 183,Dakar,14.71583173,-17.47313013,2540200,Senegal,765122,93,Santo Domingo,18.47007285,-69.90008508,1078436.5,Dominican Republic,1
95 | 183,Dakar,14.71583173,-17.47313013,2540200,Senegal,765122,94,Takamatsu,34.34473696,134.044779,329861.5,Japan,1
96 | 183,Dakar,14.71583173,-17.47313013,2540200,Senegal,765122,95,Velikiy Novgorod,58.4999809,31.33001501,218717,Russia,1
97 | 579,Rome,41.89595563,12.48325842,1687226,Italy,800446,96,Mar del Plata,-38.00002033,-57.57998438,554916,Argentina,1
98 | 579,Rome,41.89595563,12.48325842,1687226,Italy,800446,97,Marbella,36.51661989,-4.88333012,153069.5,Spain,1
99 | 579,Rome,41.89595563,12.48325842,1687226,Italy,800446,98,Marietta,33.95561342,-84.54324813,61360,United States of America,1
100 | 579,Rome,41.89595563,12.48325842,1687226,Italy,800446,99,Maseru,-29.31667438,27.48327307,239839.5,Lesotho,1
101 | 579,Rome,41.89595563,12.48325842,1687226,Italy,800446,100,Masvingo,-20.05961668,30.8200203,76300.5,Zimbabwe,1
102 | 579,Rome,41.89595563,12.48325842,1687226,Italy,800446,101,Mataro,41.53995668,2.45002071,149826,Spain,1
103 | 579,Rome,41.89595563,12.48325842,1687226,Italy,800446,102,Matsue,35.46699404,133.0666475,150527,Japan,1
104 | 579,Rome,41.89595563,12.48325842,1687226,Italy,800446,103,Matsumoto,36.2404352,137.9700175,217796.5,Japan,1
105 | 579,Rome,41.89595563,12.48325842,1687226,Italy,800446,104,Matsuyama,33.84554262,132.765839,525089,Japan,1
106 | 579,Rome,41.89595563,12.48325842,1687226,Italy,800446,105,Medenine,33.399999,10.41669956,61705,Tunisia,1
107 | 579,Rome,41.89595563,12.48325842,1687226,Italy,800446,106,Medina,24.49998903,39.5800024,1010000,Saudi Arabia,1
108 | 579,Rome,41.89595563,12.48325842,1687226,Italy,800446,107,Melbourne,28.08331036,-80.60832035,170870,United States of America,1
109 | 579,Rome,41.89595563,12.48325842,1687226,Italy,800446,108,Melbourne,-37.82003131,144.9750162,2131812.5,Australia,1
110 | 579,Rome,41.89595563,12.48325842,1687226,Italy,800446,109,Metairie,29.98386619,-90.15277653,270171,United States of America,1
111 | 103,Berlin,52.52181866,13.40154862,3250007,Germany,904561,110,Tacoma,47.21131594,-122.5150131,460273,United States of America,1
112 | 103,Berlin,52.52181866,13.40154862,3250007,Germany,904561,111,Vancouver,49.27341658,-123.1216442,1458415,Canada,1
113 | 103,Berlin,52.52181866,13.40154862,3250007,Germany,904561,112,Columbia,38.95207847,-92.33390955,244754,United States of America,1
114 | 103,Berlin,52.52181866,13.40154862,3250007,Germany,904561,113,Adapazari,40.79997601,30.4150321,260109,Turkey,1
115 | 103,Berlin,52.52181866,13.40154862,3250007,Germany,904561,114,Adelaide,-34.93498777,138.6000048,990677,Australia,1
116 | 103,Berlin,52.52181866,13.40154862,3250007,Germany,904561,115,Aguascalientes,21.87945992,-102.2904135,763589.5,Mexico,1
117 | 103,Berlin,52.52181866,13.40154862,3250007,Germany,904561,116,Akron,41.07039878,-81.51999597,451155,United States of America,1
118 | 103,Berlin,52.52181866,13.40154862,3250007,Germany,904561,117,Al Ahmadi,29.0769448,48.08377274,68763,Kuwait,1
119 | 103,Berlin,52.52181866,13.40154862,3250007,Germany,904561,118,Al Jahra,29.33747154,47.6580623,194193,Kuwait,1
120 | 103,Berlin,52.52181866,13.40154862,3250007,Germany,904561,119,Albacete,39.00034426,-1.869999839,127597,Spain,1
121 | 103,Berlin,52.52181866,13.40154862,3250007,Germany,904561,120,Albany,42.67001691,-73.81994918,484286,United States of America,1
122 | 103,Berlin,52.52181866,13.40154862,3250007,Germany,904561,1,Alexandria,38.82043276,-77.09998153,127273,United States of America,1
123 | 103,Berlin,52.52181866,13.40154862,3250007,Germany,904561,122,Algeciras,36.12671215,-5.466530363,106687.5,Spain,1
124 | 103,Berlin,52.52181866,13.40154862,3250007,Germany,904561,123,Algiers,36.7630648,3.05055253,2665831.5,Algeria,1
125 | 103,Berlin,52.52181866,13.40154862,3250007,Germany,904561,124,Allentown,40.59998822,-75.50002751,300980.5,United States of America,1
126 | 103,Berlin,52.52181866,13.40154862,3250007,Germany,904561,125,Gisenyi,-1.684665915,29.26290605,83623,Rwanda,1
127 | 103,Berlin,52.52181866,13.40154862,3250007,Germany,904561,126,Gitarama,-2.069603659,29.75998165,87613,Rwanda,1
128 | 103,Berlin,52.52181866,13.40154862,3250007,Germany,904561,127,Gliwice,50.3303762,18.67001257,353252.5,Poland,1
129 | 103,Berlin,52.52181866,13.40154862,3250007,Germany,904561,128,Gold Coast,-28.08150429,153.4482458,429954.5,Australia,1
130 | 103,Berlin,52.52181866,13.40154862,3250007,Germany,904561,129,Goya,-29.13999266,-59.26998458,71274.5,Argentina,1
131 | 103,Berlin,52.52181866,13.40154862,3250007,Germany,904561,130,Graz,47.0777582,15.41000484,242780,Austria,1
132 | 103,Berlin,52.52181866,13.40154862,3250007,Germany,904561,131,Great Falls,47.50029055,-111.299987,61316.5,United States of America,1
133 | 103,Berlin,52.52181866,13.40154862,3250007,Germany,904561,132,Greeley,40.41919822,-104.739974,106142.5,United States of America,1
134 | 103,Berlin,52.52181866,13.40154862,3250007,Germany,904561,133,Greensboro,36.07000633,-79.80002344,310328,United States of America,1
135 | 103,Berlin,52.52181866,13.40154862,3250007,Germany,904561,134,Greenville,35.61287661,-77.3666836,81661,United States of America,1
136 | 373,Mendoza,-32.88333006,-68.81661117,827815,Argentina,987654,135,San Pedro de Macoris,18.4503583,-69.29996668,211019.5,Dominican Republic,1
137 | 373,Mendoza,-32.88333006,-68.81661117,827815,Argentina,987654,136,Stockton,37.95813397,-121.289739,488506.5,United States of America,1
138 | 373,Mendoza,-32.88333006,-68.81661117,827815,Argentina,987654,137,Usti Nad Labem,50.66299816,14.08100455,94105,Czech Republic,1
139 | 373,Mendoza,-32.88333006,-68.81661117,827815,Argentina,987654,138,Mexicali,32.64998252,-115.4800161,736138.5,Mexico,1
140 | 373,Mendoza,-32.88333006,-68.81661117,827815,Argentina,987654,139,Middlesbrough,54.58037518,-1.230013063,279374.5,United Kingdom,1
141 | 373,Mendoza,-32.88333006,-68.81661117,827815,Argentina,987654,140,Midland,32.030718,-102.0974996,98141.5,United States of America,1
142 | 373,Mendoza,-32.88333006,-68.81661117,827815,Argentina,987654,141,Mito,36.37042727,140.4800451,300215,Japan,1
143 | 373,Mendoza,-32.88333006,-68.81661117,827815,Argentina,987654,142,Moca,19.39699814,-70.52300059,61834,Dominican Republic,1
144 | 373,Mendoza,-32.88333006,-68.81661117,827815,Argentina,987654,143,Modesto,37.65541343,-120.9899899,269697,United States of America,1
145 | 373,Mendoza,-32.88333006,-68.81661117,827815,Argentina,987654,144,Mombasa,-4.040026022,39.68991817,840834,Kenya,1
146 | 373,Mendoza,-32.88333006,-68.81661117,827815,Argentina,987654,145,Rio Largo,-9.48000405,-35.83996769,110966,Brazil,1
147 | 373,Mendoza,-32.88333006,-68.81661117,827815,Argentina,987654,146,Shenzhen,22.55237051,114.1221231,4291796,China,1
148 | 373,Mendoza,-32.88333006,-68.81661117,827815,Argentina,987654,147,Toowoomba,-27.56453327,151.9555204,86711,Australia,1
149 | 373,Mendoza,-32.88333006,-68.81661117,827815,Argentina,987654,148,Santa Fe,35.68692893,-105.9372394,80943,United States of America,1
150 | 373,Mendoza,-32.88333006,-68.81661117,827815,Argentina,987654,149,Svobodnyy,51.40617617,128.1311865,62318.5,Russia,1
151 | 373,Mendoza,-32.88333006,-68.81661117,827815,Argentina,987654,150,Utsunomiya,36.54997703,139.8700048,558808.5,Japan,1
152 | 237,Ipoh,4.599989236,101.0649833,656227,Malaysia,1148668,151,Salerno,40.68039675,14.76994055,546922,Italy,1
153 | 237,Ipoh,4.599989236,101.0649833,656227,Malaysia,1148668,152,St. Cloud,45.56120994,-94.16222172,85974,United States of America,1
154 | 237,Ipoh,4.599989236,101.0649833,656227,Malaysia,1148668,153,Tuzla,44.5504706,18.6800378,143410,Bosnia and Herzegovina,1
155 | 237,Ipoh,4.599989236,101.0649833,656227,Malaysia,1148668,154,Kitami,43.8503583,143.8999914,103971.5,Japan,1
156 | 237,Ipoh,4.599989236,101.0649833,656227,Malaysia,1148668,155,Kitchener,43.44999514,-80.50000655,413056.5,Canada,1
157 | 237,Ipoh,4.599989236,101.0649833,656227,Malaysia,1148668,156,Klagenfurt,46.62034426,14.3100203,88588,Austria,1
158 | 237,Ipoh,4.599989236,101.0649833,656227,Malaysia,1148668,157,Klerksdorp,-26.88002724,26.62001827,163362.5,South Africa,1
159 | 237,Ipoh,4.599989236,101.0649833,656227,Malaysia,1148668,158,Koblenz,50.35047833,7.599990599,209976,Germany,1
160 | 237,Ipoh,4.599989236,101.0649833,656227,Malaysia,1148668,159,Kofu,35.6503937,138.5833134,193770,Japan,1
161 | 237,Ipoh,4.599989236,101.0649833,656227,Malaysia,1148668,160,Kokshetau,53.29998822,69.41998979,126658.5,Kazakhstan,1
162 | 237,Ipoh,4.599989236,101.0649833,656227,Malaysia,1148668,161,Kolpino,59.73000917,30.65000484,180938.5,Russia,1
163 | 237,Ipoh,4.599989236,101.0649833,656227,Malaysia,1148668,162,Kolwezi,-10.71672443,25.47243974,418000,Congo (Kinshasa),1
164 | 237,Ipoh,4.599989236,101.0649833,656227,Malaysia,1148668,163,Kompong Chhnang,12.25047833,104.6666239,65817,Cambodia,1
165 | 237,Ipoh,4.599989236,101.0649833,656227,Malaysia,1148668,164,Konotop,51.24238771,33.20902177,97672.5,Ukraine,1
166 | 237,Ipoh,4.599989236,101.0649833,656227,Malaysia,1148668,165,Koriyama,37.40997622,140.3799996,302581,Japan,1
167 | 237,Ipoh,4.599989236,101.0649833,656227,Malaysia,1148668,166,Koudougou,12.25047833,-2.369995159,85339,Burkina Faso,1
168 | 237,Ipoh,4.599989236,101.0649833,656227,Malaysia,1148668,167,Kraków,50.05997927,19.96001135,755525,Poland,1
169 | 237,Ipoh,4.599989236,101.0649833,656227,Malaysia,1148668,168,Kroonstad,-27.66003131,27.2100081,88413.5,South Africa,1
170 | 237,Ipoh,4.599989236,101.0649833,656227,Malaysia,1148668,169,Ksar El Kebir,35.02038047,-5.909985801,207676.5,Morocco,1
171 | 237,Ipoh,4.599989236,101.0649833,656227,Malaysia,1148668,170,Kuala Lumpur,3.166665872,101.6999833,1448000,Malaysia,1
172 | 237,Ipoh,4.599989236,101.0649833,656227,Malaysia,1148668,171,Kuopio,62.89428632,27.69493974,90502,Finland,1
173 | 237,Ipoh,4.599989236,101.0649833,656227,Malaysia,1148668,172,Ceuta,35.88898378,-5.30699935,78674,Spain,1
174 | 237,Ipoh,4.599989236,101.0649833,656227,Malaysia,1148668,173,Chalkida,38.46399457,23.61239823,63200,Greece,1
175 | 237,Ipoh,4.599989236,101.0649833,656227,Malaysia,1148668,174,Changde,29.02999676,111.6800459,993390,China,1
176 | 237,Ipoh,4.599989236,101.0649833,656227,Malaysia,1148668,175,Charlottesville,38.02918907,-78.47692591,61314,United States of America,1
177 | 276,Lima,-12.04801268,-77.05006209,7385117,Peru,1222446,176,Helsingborg,56.05049217,12.70004106,91164.5,Sweden,1
178 | 276,Lima,-12.04801268,-77.05006209,7385117,Peru,1222446,177,Higuey,18.61599603,-68.70799749,123787,Dominican Republic,1
179 | 276,Lima,-12.04801268,-77.05006209,7385117,Peru,1222446,178,Hinthada,17.64826255,95.46785722,157837.5,Myanmar,1
180 | 276,Lima,-12.04801268,-77.05006209,7385117,Peru,1222446,179,Hirosaki,40.56999005,140.4700199,171700.5,Japan,1
181 | 276,Lima,-12.04801268,-77.05006209,7385117,Peru,1222446,180,Honiara,-9.437994295,159.9497657,66313,Solomon Islands,1
182 | 276,Lima,-12.04801268,-77.05006209,7385117,Peru,1222446,181,Hradec Kralove,50.20599617,15.81200153,95195,Czech Republic,1
183 | 276,Lima,-12.04801268,-77.05006209,7385117,Peru,1222446,182,Huanuco,-9.920028871,-76.24000818,153052,Peru,1
184 | 276,Lima,-12.04801268,-77.05006209,7385117,Peru,1222446,183,Huaraz,-9.530026836,-77.53000696,74986.5,Peru,1
185 | 276,Lima,-12.04801268,-77.05006209,7385117,Peru,1222446,184,Huelva,37.25037355,-6.929949383,119732,Spain,1
186 | 276,Lima,-12.04801268,-77.05006209,7385117,Peru,1222446,185,Ioanina,39.66790041,20.85086137,75158,Greece,1
187 | 276,Lima,-12.04801268,-77.05006209,7385117,Peru,1222446,186,Iowa City,41.66108624,-91.52997929,81343,United States of America,1
188 | 276,Lima,-12.04801268,-77.05006209,7385117,Peru,1222446,187,Ipatinga,-19.4796004,-42.51999923,318320,Brazil,1
189 | 276,Lima,-12.04801268,-77.05006209,7385117,Peru,1222446,188,Rock Island,41.49339622,-90.53461369,102055.5,United States of America,1
190 | 276,Lima,-12.04801268,-77.05006209,7385117,Peru,1222446,189,Sivas,39.74541506,37.03498979,245801.5,Turkey,1
191 | 276,Lima,-12.04801268,-77.05006209,7385117,Peru,1222446,190,Toulon,43.13418645,5.918821566,263197,France,1
192 | 276,Lima,-12.04801268,-77.05006209,7385117,Peru,1222446,191,Borisoglebsk,51.36871075,42.08873816,64995,Russia,1
193 | 276,Lima,-12.04801268,-77.05006209,7385117,Peru,1222446,192,Boston,42.32996014,-71.07001367,2528070.5,United States of America,1
194 | 276,Lima,-12.04801268,-77.05006209,7385117,Peru,1222446,193,Boulder,40.03844627,-105.246093,106897.5,United States of America,1
195 | 276,Lima,-12.04801268,-77.05006209,7385117,Peru,1222446,194,Butare,-2.589623597,29.73000932,77000,Rwanda,1
196 | 276,Lima,-12.04801268,-77.05006209,7385117,Peru,1222446,195,Bydgoszcz,53.12041262,18.01000118,366222,Poland,1
197 | 276,Lima,-12.04801268,-77.05006209,7385117,Peru,1222446,196,Bytom,50.35003908,18.90999792,425716.5,Poland,1
198 | 276,Lima,-12.04801268,-77.05006209,7385117,Peru,1222446,197,Caxias do Sul,-29.17999022,-51.17003972,377580.5,Brazil,1
199 | 276,Lima,-12.04801268,-77.05006209,7385117,Peru,1222446,198,Cerro de Pasco,-10.69000771,-76.26998051,108071,Peru,1
200 | 276,Lima,-12.04801268,-77.05006209,7385117,Peru,1222446,199,Ceske Budejovice,48.98001935,14.46003699,97452,Czech Republic,1
201 | 562,Reykjavík,64.15002362,-21.95001449,140059,Iceland,1241978,200,Hyderabad,25.379987,68.37498897,1422665,Pakistan,1
202 | 562,Reykjavík,64.15002362,-21.95001449,140059,Iceland,1241978,201,Iligan,8.171244119,124.2153531,464599,Philippines,1
203 | 562,Reykjavík,64.15002362,-21.95001449,140059,Iceland,1241978,202,Iloilo,10.70504295,122.5450158,387681,Philippines,1
204 | 562,Reykjavík,64.15002362,-21.95001449,140059,Iceland,1241978,203,Kupang,-10.17866941,123.5829886,270798,Indonesia,1
205 | 562,Reykjavík,64.15002362,-21.95001449,140059,Iceland,1241978,204,Kure,34.25097007,132.5655928,196807.5,Japan,1
206 | 562,Reykjavík,64.15002362,-21.95001449,140059,Iceland,1241978,205,Kushiro,42.97495953,144.3746911,191089,Japan,1
207 | 562,Reykjavík,64.15002362,-21.95001449,140059,Iceland,1241978,206,Kuwait,29.36971763,47.97830115,1061532,Kuwait,1
208 | 562,Reykjavík,64.15002362,-21.95001449,140059,Iceland,1241978,207,Kuznetsk,53.12041262,46.59998734,93027,Russia,1
209 | 562,Reykjavík,64.15002362,-21.95001449,140059,Iceland,1241978,208,Kwekwe,-18.92960814,29.79997921,80788,Zimbabwe,1
210 | 562,Reykjavík,64.15002362,-21.95001449,140059,Iceland,1241978,209,La Plata,-34.90961465,-57.95996118,440388.5,Argentina,1
211 | 562,Reykjavík,64.15002362,-21.95001449,140059,Iceland,1241978,210,La Rioja,-29.40995034,-66.84996118,147130,Argentina,1
212 | 562,Reykjavík,64.15002362,-21.95001449,140059,Iceland,1241978,211,Riyadh,24.64083315,46.77274166,4335480.5,Saudi Arabia,1
213 | 562,Reykjavík,64.15002362,-21.95001449,140059,Iceland,1241978,212,Rzeszow,50.07046958,22.00004187,202034,Poland,1
214 | 562,Reykjavík,64.15002362,-21.95001449,140059,Iceland,1241978,213,Siauliai,55.93863853,23.32502559,132057.5,Lithuania,1
215 | 562,Reykjavík,64.15002362,-21.95001449,140059,Iceland,1241978,214,Sonsonate,13.7199752,-89.7299858,139724,El Salvador,1
216 | 562,Reykjavík,64.15002362,-21.95001449,140059,Iceland,1241978,215,Toronto,43.69997988,-79.42002079,4573710.5,Canada,1
217 | 562,Reykjavík,64.15002362,-21.95001449,140059,Iceland,1241978,216,Tripoli,32.89250002,13.18001176,1209199,Libya,1
218 | 389,Miami,25.7876107,-80.22410608,2983947,United States of America,1354625,217,Chimoio,-19.12003579,33.47003943,242538.5,Mozambique,1
219 | 389,Miami,25.7876107,-80.22410608,2983947,United States of America,1354625,218,Clarksville,36.5300816,-87.35943282,122115,United States of America,1
220 | 389,Miami,25.7876107,-80.22410608,2983947,United States of America,1354625,219,Duluth,46.78333173,-92.10637822,82026.5,United States of America,1
221 | 389,Miami,25.7876107,-80.22410608,2983947,United States of America,1354625,220,Ipswich,52.07034751,1.169995482,139012,United Kingdom,1
222 | 389,Miami,25.7876107,-80.22410608,2983947,United States of America,1354625,221,Iquique,-20.24999266,-70.12996769,223012,Chile,1
223 | 389,Miami,25.7876107,-80.22410608,2983947,United States of America,1354625,222,Irkutsk,52.31997052,104.2450476,572325,Russia,1
224 | 389,Miami,25.7876107,-80.22410608,2983947,United States of America,1354625,223,Luxembourg,49.61166038,6.130002806,91972,Luxembourg,1
225 | 389,Miami,25.7876107,-80.22410608,2983947,United States of America,1354625,224,Lysychansk,48.92041058,38.42735958,118010.5,Ukraine,1
226 | 389,Miami,25.7876107,-80.22410608,2983947,United States of America,1354625,225,Macau,22.20299746,113.5450484,568700,Macau S.A.R,1
227 | 389,Miami,25.7876107,-80.22410608,2983947,United States of America,1354625,226,Machakos,-1.509534486,37.25998897,88448,Kenya,1
228 | 389,Miami,25.7876107,-80.22410608,2983947,United States of America,1354625,227,Macon,32.85038373,-83.63004806,104932.5,United States of America,1
229 | 389,Miami,25.7876107,-80.22410608,2983947,United States of America,1354625,228,Maebashi,36.39269981,139.0726892,313791,Japan,1
230 | 389,Miami,25.7876107,-80.22410608,2983947,United States of America,1354625,229,Magnitogorsk,53.42269391,58.98000688,308724.5,Russia,1
231 | 389,Miami,25.7876107,-80.22410608,2983947,United States of America,1354625,230,Nürnberg,49.44999066,11.0799849,618270.5,Germany,1
232 | 389,Miami,25.7876107,-80.22410608,2983947,United States of America,1354625,231,Naga,13.61915448,123.1813594,458283,Philippines,1
233 | 389,Miami,25.7876107,-80.22410608,2983947,United States of America,1354625,232,Nagaoka,37.45041302,138.8600406,187560,Japan,1
234 | 489,Phnom Penh,11.55003013,104.9166345,1466000,Cambodia,1504012,233,Rio Branco,-9.966589336,-67.80000655,257642,Brazil,1
235 | 489,Phnom Penh,11.55003013,104.9166345,1466000,Cambodia,1504012,234,Shenyeng,41.80497927,123.4499735,4149596,China,1
236 | 489,Phnom Penh,11.55003013,104.9166345,1466000,Cambodia,1504012,235,Tomakomai,42.6504057,141.5500057,161355.5,Japan,1
237 | 489,Phnom Penh,11.55003013,104.9166345,1466000,Cambodia,1504012,236,Santa Cruz,36.97194629,-122.0263904,101530.5,United States of America,1
238 | 489,Phnom Penh,11.55003013,104.9166345,1466000,Cambodia,1504012,237,Sucre,-19.04097085,-65.25951563,223287,Bolivia,1
239 | 489,Phnom Penh,11.55003013,104.9166345,1466000,Cambodia,1504012,238,Utica,43.10117922,-75.23306706,81870,United States of America,1
240 | 489,Phnom Penh,11.55003013,104.9166345,1466000,Cambodia,1504012,239,Nakuru,-0.279997132,36.06998409,312315,Kenya,1
241 | 489,Phnom Penh,11.55003013,104.9166345,1466000,Cambodia,1504012,240,Namur,50.47039349,4.870028034,97155.5,Belgium,1
242 | 489,Phnom Penh,11.55003013,104.9166345,1466000,Cambodia,1504012,241,Nanjing,32.05001914,118.7799743,3383005,China,1
243 | 489,Phnom Penh,11.55003013,104.9166345,1466000,Cambodia,1504012,242,National City,32.67194501,-117.0980052,104291,United States of America,1
244 | 489,Phnom Penh,11.55003013,104.9166345,1466000,Cambodia,1504012,243,Nazareth,32.70398439,35.2955094,108129.5,Israel,1
245 | 489,Phnom Penh,11.55003013,104.9166345,1466000,Cambodia,1504012,244,New Albany,38.3108773,-85.82128382,78381.5,United States of America,1
246 | 489,Phnom Penh,11.55003013,104.9166345,1466000,Cambodia,1504012,245,New London,41.3555235,-72.10002832,61236,United States of America,1
247 | 489,Phnom Penh,11.55003013,104.9166345,1466000,Cambodia,1504012,246,New Orleans,29.99500246,-90.03996688,527428.5,United States of America,1
248 | 489,Phnom Penh,11.55003013,104.9166345,1466000,Cambodia,1504012,247,Niagara Falls,43.09482302,-79.0369434,117567,United States of America,1
249 | 489,Phnom Penh,11.55003013,104.9166345,1466000,Cambodia,1504012,248,Niigata,37.91999676,139.0400297,537534.5,Japan,1
250 | 489,Phnom Penh,11.55003013,104.9166345,1466000,Cambodia,1504012,249,Nizhnekamsk,55.64043968,51.82003048,210363,Russia,1
251 | 489,Phnom Penh,11.55003013,104.9166345,1466000,Cambodia,1504012,250,Nizhyn,51.0540788,31.89029089,95893.5,Ukraine,1
252 | 489,Phnom Penh,11.55003013,104.9166345,1466000,Cambodia,1504012,251,Noginsk,64.48331077,91.23333533,229731,Russia,1
253 | 489,Phnom Penh,11.55003013,104.9166345,1466000,Cambodia,1504012,252,Noginsk,55.87042564,38.48001786,172855,Russia,1
254 | 489,Phnom Penh,11.55003013,104.9166345,1466000,Cambodia,1504012,253,Norman,35.22791302,-97.34414636,113525,United States of America,1
255 | 489,Phnom Penh,11.55003013,104.9166345,1466000,Cambodia,1504012,254,Norrköping,58.59542727,16.17869177,85771,Sweden,1
256 | 489,Phnom Penh,11.55003013,104.9166345,1466000,Cambodia,1504012,255,Norwich,52.63036501,1.300013386,184196,United Kingdom,1
257 | 489,Phnom Penh,11.55003013,104.9166345,1466000,Cambodia,1504012,256,Nova Lima,-19.98003497,-43.8500214,60413.5,Brazil,1
258 | 489,Phnom Penh,11.55003013,104.9166345,1466000,Cambodia,1504012,257,Novo Hamburgo,-29.70962197,-51.13998987,557017,Brazil,1
259 | 489,Phnom Penh,11.55003013,104.9166345,1466000,Cambodia,1504012,258,Santa Cruz do Sul,-29.71003538,-52.44003972,109869,Brazil,1
260 | 489,Phnom Penh,11.55003013,104.9166345,1466000,Cambodia,1504012,259,Sunderland,54.92001853,-1.380029746,315449.5,United Kingdom,1
261 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,260,Monrovia,6.31055666,-10.80475163,913331,Liberia,1
262 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,261,Monterey,36.6002582,-121.8935781,77297.5,United States of America,1
263 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,262,Montevideo,-34.85804157,-56.17105229,759162,Uruguay,1
264 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,263,Montréal,45.49999921,-73.58329696,3017278,Canada,1
265 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,264,Monywa,22.1049931,95.14999548,204116.5,Myanmar,1
266 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,265,Morioka,39.72001609,141.1300313,294782.5,Japan,1
267 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,266,Mtwara,-10.26961994,40.18999101,91674,Tanzania,1
268 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,267,Mudangiang,44.57501691,129.5900122,954957.5,China,1
269 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,268,Multan,30.19997703,71.45500769,1479615,Pakistan,1
270 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,269,Murfreesboro,35.84596315,-86.39026717,100237,United States of America,1
271 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,270,Curepipe,-20.31619017,57.51663367,192087.5,Mauritius,1
272 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,271,Brest,48.39044293,-4.49500757,142914,France,1
273 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,272,Sakarya,40.76666114,30.40000251,286787,Turkey,1
274 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,273,Spartanburg,34.94942873,-81.93227055,81059,United States of America,1
275 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,274,Tucumán,-26.81600014,-65.21662419,678803.5,Argentina,1
276 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,275,Salavat,53.37034568,55.92996049,111648,Russia,1
277 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,276,Springfield,39.82000999,-89.65001652,125345,United States of America,1
278 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,277,Tuscaloosa,33.22511538,-87.54417607,100594.5,United States of America,1
279 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,278,Capenda-Camulemba,-9.4195943,18.43002722,79842.5,Angola,1
280 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,279,Rochester,43.17042564,-77.61994979,483177,United States of America,1
281 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,280,Sittwe,20.13999676,92.88000484,178387.5,Myanmar,1
282 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,281,Tottori,35.50037701,134.2332946,142635.5,Japan,1
283 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,282,Cotonou,6.400008564,2.519990599,726292,Benin,1
284 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,283,Council Bluffs,41.26227338,-95.86080021,80284.5,United States of America,1
285 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,284,Coventry,52.42040367,-1.499996583,348292,United Kingdom,1
286 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,285,Geelong,-38.16749505,144.3956335,149336,Australia,1
287 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,286,Gent,51.02999758,3.700021931,337914.5,Belgium,1
288 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,287,George,-33.95003497,22.45004024,143915,South Africa,1
289 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,288,Kara Balta,42.83062726,73.88566036,68464.5,Kyrgyzstan,1
290 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,289,Karakol,42.49204327,78.38182003,63411.5,Kyrgyzstan,1
291 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,290,Karlstad,59.36713727,13.49994055,66703.5,Sweden,1
292 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,291,Kasama,-10.19959837,31.17994665,156500,Zambia,1
293 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,292,Katowice,50.26038047,19.02001705,1527362,Poland,1
294 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,293,Kaunas,54.95040428,23.88003048,363844.5,Lithuania,1
295 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,294,Kayes,14.44998232,-11.44001001,77207,Mali,1
296 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,295,Kayseri,38.73495994,35.49001949,562215.5,Turkey,1
297 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,296,Kecskemet,46.90004295,19.70002722,111871,Hungary,1
298 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,297,Kelang,3.020369892,101.5500183,917933.5,Malaysia,1
299 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,298,Kelowna,49.89998903,-119.4833118,110207.5,Canada,1
300 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,299,Kendu Bay,-0.359578838,34.63999385,91248,Kenya,1
301 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,300,Kericho,-0.359578838,35.28000647,67300,Kenya,1
302 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,301,Kharkiv,49.99998293,36.25002478,1338063.5,Ukraine,1
303 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,302,Khaskovo,41.94378216,25.5632869,72805,Bulgaria,1
304 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,303,Kiev,50.43336733,30.51662797,2185754,Ukraine,1
305 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,304,Otaru,43.18871909,140.9783093,139260.5,Japan,1
306 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,305,Pasay City,14.5504413,120.9999939,403064,Philippines,1
307 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,306,Corrientes,-27.48996417,-58.80998682,339945,Argentina,1
308 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,307,Corumba,-19.01601113,-57.65000594,70035.5,Brazil,1
309 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,308,Eindhoven,51.42997316,5.50001542,303836.5,Netherlands,1
310 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,309,El Jadida,33.2603587,-8.509982138,164009.5,Morocco,1
311 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,310,Santa Maria,-29.68331867,-53.80000838,239211.5,Brazil,1
312 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,311,Syzran,53.16999615,48.47997595,171589,Russia,1
313 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,312,Valdivia,-39.7950012,-73.24502303,146509,Chile,1
314 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,313,San Francisco,37.74000775,-122.4599777,2091036,United States of America,1
315 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,314,Stavanger,58.97000389,5.680004434,136999,Norway,1
316 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,315,Upington,-28.46003416,21.23001135,62086,South Africa,1
317 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,316,Rybinsk,58.05034426,38.81999711,203874.5,Russia,1
318 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,317,Songea,-10.68003416,35.65000972,120923,Tanzania,1
319 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,318,Trablous,34.42000368,35.8699963,361286,Lebanon,1
320 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,319,Coquimbo,-29.95291461,-71.34361454,159082.5,Chile,1
321 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,320,Santiago de Compostela,42.88289797,-8.541091351,87721,Spain,1
322 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,321,Szczecin,53.42039431,14.53000688,390241.5,Poland,1
323 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,322,Vallejo,38.11194887,-122.258052,133367.5,United States of America,1
324 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,323,Edinburg,26.30318646,-98.1599622,114573.5,United States of America,1
325 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,324,Muroran,42.34995892,140.9800146,125936.5,Japan,1
326 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,325,Mutare,-18.97001911,32.6500378,216785,Zimbabwe,1
327 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,326,Myeik,12.45408347,98.61148962,220009,Myanmar,1
328 | 35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,327,Santo Angelo,-28.30004393,-54.28003076,65013,Brazil,1
329 | 1,Alexandria,31.20001935,29.94999589,3988258,Egypt,3502678,328,Otsu,35.006402,135.8674068,437802.5,Japan,1
330 | 1,Alexandria,31.20001935,29.94999589,3988258,Egypt,3502678,329,Ouagadougou,12.37031598,-1.524723756,992228.5,Burkina Faso,1
331 | 1,Alexandria,31.20001935,29.94999589,3988258,Egypt,3502678,330,Oulu,64.99999758,25.47001094,132685,Finland,1
332 | 1,Alexandria,31.20001935,29.94999589,3988258,Egypt,3502678,331,Ovalle,-30.59003335,-71.20005742,72984,Chile,1
333 | 1,Alexandria,31.20001935,29.94999589,3988258,Egypt,3502678,332,Pakxe,15.12206016,105.8183365,95553.5,Laos,1
334 | 1,Alexandria,31.20001935,29.94999589,3988258,Egypt,3502678,333,Palmerston North,-40.35269326,175.6072033,66551.5,New Zealand,1
335 | 1,Alexandria,31.20001935,29.94999589,3988258,Egypt,3502678,334,Passos,-20.71001626,-46.60998214,85136.5,Brazil,1
336 | 1,Alexandria,31.20001935,29.94999589,3988258,Egypt,3502678,335,Paulo Afonso,-9.330659161,-38.26565943,85350,Brazil,1
337 | 1,Alexandria,31.20001935,29.94999589,3988258,Egypt,3502678,336,Pec,42.66032757,20.3107393,93481.5,Kosovo,1
338 | 1,Alexandria,31.20001935,29.94999589,3988258,Egypt,3502678,337,Penza,53.18002138,44.99998165,491943,Russia,1
339 | 1,Alexandria,31.20001935,29.94999589,3988258,Egypt,3502678,338,Pereira,4.81038983,-75.67999068,504434,Colombia,1
340 | 1,Alexandria,31.20001935,29.94999589,3988258,Egypt,3502678,339,Peterborough,52.58041974,-0.249995363,140141,United Kingdom,1
341 | 1,Alexandria,31.20001935,29.94999589,3988258,Egypt,3502678,340,Scarborough,54.28039349,-0.429984376,70571,United Kingdom,1
342 | 1,Alexandria,31.20001935,29.94999589,3988258,Egypt,3502678,341,Temirtau,50.06501772,72.96499304,167193.5,Kazakhstan,1
343 | 1,Alexandria,31.20001935,29.94999589,3988258,Egypt,3502678,342,Vitória,-20.32399331,-40.36599634,1008328,Brazil,1
344 | 1,Alexandria,31.20001935,29.94999589,3988258,Egypt,3502678,343,Cartagena,10.39973859,-75.51439356,887000,Colombia,1
345 | 1,Alexandria,31.20001935,29.94999589,3988258,Egypt,3502678,344,Schenectady,42.81458173,-73.93996769,104767.5,United States of America,1
346 | 1,Alexandria,31.20001935,29.94999589,3988258,Egypt,3502678,345,Temuco,-38.73000161,-72.57999903,252015,Chile,1
347 | 1,Alexandria,31.20001935,29.94999589,3988258,Egypt,3502678,346,Volsk,52.03471661,47.37430701,62027,Russia,1
348 | 1,Alexandria,31.20001935,29.94999589,3988258,Egypt,3502678,347,Badajoz,38.8804291,-6.96997278,115638.5,Spain,1
349 | 1,Alexandria,31.20001935,29.94999589,3988258,Egypt,3502678,348,Richmond,37.55001935,-77.449986,551443,United States of America,1
350 | 1,Alexandria,31.20001935,29.94999589,3988258,Egypt,3502678,349,Savannakhet,16.53758099,104.772974,75725.5,Laos,1
351 | 1,Alexandria,31.20001935,29.94999589,3988258,Egypt,3502678,350,Shangqiu,34.45041526,115.6500362,967109,China,1
352 | 1,Alexandria,31.20001935,29.94999589,3988258,Egypt,3502678,351,Taza,34.22037762,-4.019971966,170761.5,Morocco,1
353 | 1,Alexandria,31.20001935,29.94999589,3988258,Egypt,3502678,352,Tokushima,34.06738955,134.5525,355552.5,Japan,1
354 | 1,Alexandria,31.20001935,29.94999589,3988258,Egypt,3502678,353,Visalia,36.32502952,-119.3160094,114699.5,United States of America,1
355 | 1,Alexandria,31.20001935,29.94999589,3988258,Egypt,3502678,354,Daqing,46.57995913,125.0000081,948244,China,1
356 | 1,Alexandria,31.20001935,29.94999589,3988258,Egypt,3502678,355,Darwin,-12.42535398,130.8500386,82973,Australia,1
357 | 1,Alexandria,31.20001935,29.94999589,3988258,Egypt,3502678,356,Dayton,39.750376,-84.19998743,466067,United States of America,1
358 | 1,Alexandria,31.20001935,29.94999589,3988258,Egypt,3502678,357,Ordu,41.00042889,37.8699259,135952.5,Turkey,1
359 | 1,Alexandria,31.20001935,29.94999589,3988258,Egypt,3502678,358,Orsk,51.21001243,58.62731523,159353,Russia,1
360 | 1,Alexandria,31.20001935,29.94999589,3988258,Egypt,3502678,359,Osh,40.54040529,72.79001664,295638.5,Kyrgyzstan,1
361 | 1,Alexandria,31.20001935,29.94999589,3988258,Egypt,3502678,360,Oskemen,49.99003522,82.61494665,284350.5,Kazakhstan,1
362 | 1,Alexandria,31.20001935,29.94999589,3988258,Egypt,3502678,361,Osnabrück,52.28043805,8.049988972,198865,Germany,1
363 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,362,Groningen,53.22040651,6.580001179,198941,Netherlands,1
364 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,363,Groznyy,43.31868532,45.69869869,221237.5,Russia,1
365 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,364,Grudziadz,53.48039064,18.75000769,100964.5,Poland,1
366 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,365,Guangzhou,23.1449813,113.3250101,5990912.5,China,1
367 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,366,Gujranwala,32.16042584,74.18502193,1448735.5,Pakistan,1
368 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,367,Gweru,-19.45004148,29.82002966,164715.5,Zimbabwe,1
369 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,368,Gyor,47.70035585,17.63002437,132173,Hungary,1
370 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,369,Sarqan,45.42033999,79.91490474,61329,Kazakhstan,1
371 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,370,Tarragona,41.12036989,1.249990599,107957.5,Spain,1
372 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,371,Vientiane,17.96669273,102.59998,662174,Laos,1
373 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,372,Besancon,47.22999697,6.03000891,124193,France,1
374 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,373,Bethlehem,-28.21958372,28.29996741,66373,South Africa,1
375 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,374,Beziers,43.35049217,3.209974323,77759.5,France,1
376 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,375,Bialystok,53.15035911,23.1699963,288722.5,Poland,1
377 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,376,Biarritz,43.47327537,-1.561594891,89268,France,1
378 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,377,Billings,45.78830202,-108.5400004,102151.5,United States of America,1
379 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,378,Bishkek,42.87307945,74.58520422,820606,Kyrgyzstan,1
380 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,379,Bitola,41.03905703,21.33951371,75551,Macedonia,1
381 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,380,Biysk,52.53406598,85.18000972,209796.5,Russia,1
382 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,381,Bloemfontein,-29.11999388,26.22991288,459866.5,South Africa,1
383 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,382,Bloomington,40.48459475,-88.99359664,99842.5,United States of America,1
384 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,383,Blumenau,-26.9200248,-49.0899858,286326,Brazil,1
385 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,384,Bobo Dioulasso,11.1799752,-4.289981325,346035,Burkina Faso,1
386 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,385,Bonao,18.94200314,-70.40899757,73269,Dominican Republic,1
387 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,386,Borås,57.7304413,12.91997595,64115.5,Sweden,1
388 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,387,Bowling Green,36.99069948,-86.44364893,61349,United States of America,1
389 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,388,Bremerhaven,53.55043805,8.579982461,127598.5,Germany,1
390 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,389,Bridgeport,41.17997866,-73.19996118,578545,United States of America,1
391 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,390,Brighton,50.83034568,-0.169974407,321004.5,United Kingdom,1
392 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,391,Brikama,13.28036379,-16.65994979,136418,The Gambia,1
393 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,392,Brisbane,-27.45503091,153.0350927,1393176.5,Australia,1
394 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,393,Bristol,51.44999778,-2.583315472,492120.5,United Kingdom,1
395 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,394,Brownsville,25.91997988,-97.50000248,174707,United States of America,1
396 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,395,Brugge,51.22037355,3.230024779,131589,Belgium,1
397 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,396,Brusque,-27.12998615,-48.9300214,81163.5,Brazil,1
398 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,397,Bryan,30.67418581,-96.36968388,108156.5,United States of America,1
399 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,398,Bryansk,53.25999066,34.42998083,426510,Russia,1
400 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,399,Bucharest,44.4333718,26.09994665,1842097,Romania,1
401 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,400,Bulawayo,-20.16999754,28.58000199,697096,Zimbabwe,1
402 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,401,Burgos,42.35039817,-3.67996688,150251,Spain,1
403 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,402,Byumba,-1.579556052,30.06001501,70593,Rwanda,1
404 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,403,Cachoeira do Sul,-30.02996417,-52.90998519,61871,Brazil,1
405 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,404,Cachoeiro de Itapemirim,-20.85000771,-41.12998071,174808.5,Brazil,1
406 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,405,Cadiz,36.53499086,-6.225005332,153932.5,Spain,1
407 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,406,Calgary,51.08299176,-114.0799982,1012661,Canada,1
408 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,407,Cambridge,52.20039125,0.116623086,128488,United Kingdom,1
409 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,408,Campana,-34.15999632,-58.95997766,77149.5,Argentina,1
410 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,409,Campo Grande,-20.45003213,-54.61662521,687723,Brazil,1
411 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,410,Canoas,-29.91999673,-51.17998743,466661,Brazil,1
412 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,411,Cape Coral,26.60290977,-81.97968368,117387.5,United States of America,1
413 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,412,Cape Town,-33.92001097,18.43498816,2823929,South Africa,1
414 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,413,Cartagena,37.60042971,-0.980028322,166276.5,Spain,1
415 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,414,Castello,39.97041424,-0.05000757,176360,Spain,1
416 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,415,Catamarca,-28.47000771,-65.78000065,162586,Argentina,1
417 | 128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,416,Catania,37.49997072,15.07999914,482908,Italy,1
418 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,417,Reno,39.52997601,-119.8200096,265363.5,United States of America,1
419 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,418,Scranton,41.40929283,-75.66267908,114701,United States of America,1
420 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,419,Shakhty,47.72038047,40.2700378,206203.5,Russia,1
421 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,420,The Hague,52.08003684,4.269961302,953862.5,Netherlands,1
422 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,421,Tokmak,42.82987795,75.28459306,87953.5,Kyrgyzstan,1
423 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,422,Vryheid,-27.76002521,30.7899963,108364.5,South Africa,1
424 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,423,Waterbury,41.55000775,-73.05002202,174236,United States of America,1
425 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,424,Weifang,36.7204059,119.1001098,973866,China,1
426 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,425,Welkom,-27.96998655,26.72998572,279011.5,South Africa,1
427 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,426,Wiesbaden,50.08039146,8.250028441,444779,Germany,1
428 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,427,Wilmington,34.22551943,-77.94502039,126992,United States of America,1
429 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,428,Winnipeg,49.88298749,-97.16599186,603688,Canada,1
430 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,429,Wollongong,-34.41538125,150.890004,201319.5,Australia,1
431 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,430,Xapeco,-27.10001382,-52.64002751,154794,Brazil,1
432 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,431,Xian,34.27502545,108.8949963,3617406,China,1
433 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,432,Xinyi,34.38000612,118.3500264,962656,China,1
434 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,433,Yakutsk,62.03495892,129.7350162,220813,Russia,1
435 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,434,Yevpatoriya,45.19689109,33.36306921,90588,Ukraine,1
436 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,435,Yichun,27.8333333,114.4,982000,China,1
437 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,436,York,53.97038658,-1.080022218,151574.5,United Kingdom,1
438 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,437,Youngstown,41.09969932,-80.64973902,194765,United States of America,1
439 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,438,Yuzhno Sakhalinsk,46.96497438,142.7400105,174685,Russia,1
440 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,439,Zarate,-34.08956134,-59.04002446,86192,Argentina,1
441 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,440,Zheleznogorsk,52.3547746,35.40439164,94212,Russia,1
442 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,441,Zhezqazghan,47.77998924,67.77001298,104357,Kazakhstan,1
443 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,442,Zhytomyr,50.24557517,28.66216752,278581,Ukraine,1
444 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,443,Zlatoust,55.17499005,59.64999182,176285,Russia,1
445 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,444,Zlin,49.2304175,17.65002315,101893.5,Czech Republic,1
446 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,445,Balqash,46.8532241,74.95024654,80586,Kazakhstan,1
447 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,446,Banja Luka,44.78040489,17.17997432,221422,Bosnia and Herzegovina,1
448 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,447,Barahona,18.20037355,-71.099986,83644,Dominican Republic,1
449 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,448,Barranquilla,10.95998863,-74.79996688,1521245.5,Colombia,1
450 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,449,Barretos,-20.55002602,-48.58001693,97562,Brazil,1
451 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,450,Bata,1.870000833,9.769987344,135943.5,Equatorial Guinea,1
452 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,451,Bath,51.3837486,-2.350022218,92679,United Kingdom,1
453 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,452,Batman,37.89041201,41.14001054,276337.5,Turkey,1
454 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,453,Beaumont,30.08626304,-94.10168278,107455.5,United States of America,1
455 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,454,Beer Sheva,31.2500163,34.8300081,196504,Israel,1
456 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,455,Beijing,39.92889223,116.3882857,9293300.5,China,1
457 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,456,Belfast,54.60001223,-5.960034425,362588,United Kingdom,1
458 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,457,Belo Horizonte,-19.91502602,-43.91500452,3974112,Brazil,1
459 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,458,Bento Goncalves,-29.1694999,-51.51996668,92561.5,Brazil,1
460 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,459,Berkeley,37.87390139,-122.271152,298257,United States of America,1
461 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,460,Independence,39.09111391,-94.41528121,130695,United States of America,1
462 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,461,Ingolstadt,48.77041974,11.44998816,141991.5,Germany,1
463 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,462,Potosi,-19.56956907,-65.75002832,160576,Bolivia,1
464 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,463,Potsdam,52.40040489,13.06999263,181693.5,Germany,1
465 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,464,Poughkeepsie,41.70023114,-73.92141585,100670.5,United States of America,1
466 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,465,Prague,50.08333701,14.46597978,582043.5,Czech Republic,1
467 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,466,Prey Veng,11.48399998,105.3240036,74000,Cambodia,1
468 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,467,Pristina,42.66670961,21.16598425,331700,Kosovo,1
469 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,468,Provo,40.24889854,-111.63777,231238,United States of America,1
470 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,469,Pskov,57.82999595,28.32993974,189979.5,Russia,1
471 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,470,Puerto Plata,19.7902171,-70.69024747,119897,Dominican Republic,1
472 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,471,Punta del Este,-34.96997272,-54.94998987,84140,Uruguay,1
473 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,472,Québec,46.83996909,-71.24561019,576386,Canada,1
474 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,473,Qyzylorda,44.80001609,65.46498572,213259.5,Kazakhstan,1
475 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,474,Racine,42.72771364,-87.81183415,105458.5,United States of America,1
476 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,475,Ragusa,36.93003135,14.72999467,67361,Italy,1
477 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,476,Ramla,31.91670012,34.86670252,63860,Israel,1
478 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,477,Rancagua,-34.17002155,-70.73998214,222981.5,Chile,1
479 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,478,Rawalpindi,33.59997622,73.04002722,1800550.5,Pakistan,1
480 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,479,Reconquista,-29.13952757,-59.65001306,86640.5,Argentina,1
481 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,480,Red Deer,52.26664044,-113.8000411,74225,Canada,1
482 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,481,Regensburg,49.02040448,12.12002478,146755,Germany,1
483 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,482,Saidu,34.75003522,72.34999182,1860310,Pakistan,1
484 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,483,Saint-Etienne,45.43039105,4.380032103,220982,France,1
485 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,484,Settat,33.01042564,-7.620010622,140415,Morocco,1
486 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,485,South Bend,41.68330711,-86.25001734,171791,United States of America,1
487 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,486,Southampton,50.90003135,-1.399976849,384417,United Kingdom,1
488 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,487,Tiraspol,46.85309491,29.63998897,137097,Moldova,1
489 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,488,Tsuruoka,38.70041424,139.830214,88052.5,Japan,1
490 | 300,London,51.49999473,-0.116721844,7994104.5,United Kingdom,4021347,489,Tubarao,-28.48003294,-49.02001591,79760,Brazil,1
491 | 642,Tokyo,35.68501691,139.7514074,22006299.5,Japan,4512331,490,Saskatoon,52.17003135,-106.6699854,194075.5,Canada,1
492 | 642,Tokyo,35.68501691,139.7514074,22006299.5,Japan,4512331,491,Sete Lagoas,-19.44962807,-44.24999699,195032,Brazil,1
493 | 642,Tokyo,35.68501691,139.7514074,22006299.5,Japan,4512331,492,Tauranga,-37.69642129,176.1536299,84730,New Zealand,1
494 | 642,Tokyo,35.68501691,139.7514074,22006299.5,Japan,4512331,493,Timbuktu,16.7665851,-3.016596518,68872,Mali,1
495 | 642,Tokyo,35.68501691,139.7514074,22006299.5,Japan,4512331,494,Vilnius,54.68336631,25.31663529,524697.5,Lithuania,1
496 | 642,Tokyo,35.68501691,139.7514074,22006299.5,Japan,4512331,495,"Washington, D.C.",38.89954938,-77.00941858,2445216.5,United States of America,1
497 | 642,Tokyo,35.68501691,139.7514074,22006299.5,Japan,4512331,496,Aberdeen,57.17039797,-2.079987021,186577,United Kingdom,1
498 | 642,Tokyo,35.68501691,139.7514074,22006299.5,Japan,4512331,497,Abilene,32.4486253,-99.73278609,108008,United States of America,1
499 | 642,Tokyo,35.68501691,139.7514074,22006299.5,Japan,4512331,498,Ad Damman,26.42819175,50.09967037,1411656,Saudi Arabia,1
500 | 642,Tokyo,35.68501691,139.7514074,22006299.5,Japan,4512331,499,Almeria,36.83034751,-2.429991497,152032.5,Spain,1
501 | 642,Tokyo,35.68501691,139.7514074,22006299.5,Japan,4512331,500,Amiens,49.90037661,2.300004027,118908.5,France,1
502 | 642,Tokyo,35.68501691,139.7514074,22006299.5,Japan,4512331,501,Amsterdam,52.34996869,4.916640176,886318,Netherlands,1
503 | 642,Tokyo,35.68501691,139.7514074,22006299.5,Japan,4512331,502,An Najaf,32.00033225,44.33537105,612776,Iraq,1
504 | 642,Tokyo,35.68501691,139.7514074,22006299.5,Japan,4512331,503,Ankang,32.67998069,109.0200016,1025000,China,1
505 | 642,Tokyo,35.68501691,139.7514074,22006299.5,Japan,4512331,504,Annecy,45.89997479,6.116670287,77490.5,France,1
506 | 451,Oslo,59.91669029,10.74997921,707500,Norway,5121333,505,Riverside,33.94194501,-117.3980386,297554,United States of America,1
507 | 451,Oslo,59.91669029,10.74997921,707500,Norway,5121333,506,Sarnia,42.96663963,-82.3999681,113585,Canada,1
508 | 451,Oslo,59.91669029,10.74997921,707500,Norway,5121333,507,Shimonoseki,33.96543194,130.9454333,236198.5,Japan,1
509 | 451,Oslo,59.91669029,10.74997921,707500,Norway,5121333,508,Tanjungpandan,-2.750027243,107.6500077,61591,Indonesia,1
510 | 451,Oslo,59.91669029,10.74997921,707500,Norway,5121333,509,Topeka,39.05000531,-95.66998499,126830.5,United States of America,1
511 | 451,Oslo,59.91669029,10.74997921,707500,Norway,5121333,510,Vienna,48.20001528,16.36663896,2065500,Austria,1
512 | 451,Oslo,59.91669029,10.74997921,707500,Norway,5121333,511,Sakata,38.92003908,139.8500577,86507.5,Japan,1
513 | 451,Oslo,59.91669029,10.74997921,707500,Norway,5121333,512,Spokane,47.66999595,-117.4199494,272483.5,United States of America,1
514 | 451,Oslo,59.91669029,10.74997921,707500,Norway,5121333,513,Tukuyu,-9.249578838,33.64000321,77984,Tanzania,1
515 | 451,Oslo,59.91669029,10.74997921,707500,Norway,5121333,514,Bournemouth,50.72999005,-1.900049684,295272.5,United Kingdom,1
516 | 451,Oslo,59.91669029,10.74997921,707500,Norway,5121333,515,George Town,5.413613156,100.3293679,1610101,Malaysia,1
517 | 451,Oslo,59.91669029,10.74997921,707500,Norway,5121333,516,Innsbruck,47.28040733,11.4099906,133840.5,Austria,1
518 | 451,Oslo,59.91669029,10.74997921,707500,Norway,5121333,517,La Rochelle,46.16665102,-1.149992108,76903.5,France,1
519 | 451,Oslo,59.91669029,10.74997921,707500,Norway,5121333,518,La Romana,18.41700116,-68.96660201,202471.5,Dominican Republic,1
520 | 451,Oslo,59.91669029,10.74997921,707500,Norway,5121333,519,La Serena,-29.89999795,-71.24997685,151290,Chile,1
521 | 451,Oslo,59.91669029,10.74997921,707500,Norway,5121333,520,Laayoune,27.14998232,-13.20000594,182224.5,Morocco,1
522 | 451,Oslo,59.91669029,10.74997921,707500,Norway,5121333,521,Labe,11.31999249,-12.3000092,99612,Guinea,1
523 | 451,Oslo,59.91669029,10.74997921,707500,Norway,5121333,522,Lafayette,30.19997703,-92.01994938,135205.5,United States of America,1
524 | 451,Oslo,59.91669029,10.74997921,707500,Norway,5121333,523,Lahore,31.55997154,74.35002478,6443944,Pakistan,1
525 | 451,Oslo,59.91669029,10.74997921,707500,Norway,5121333,524,Lahti,60.99385968,25.66493445,97508,Finland,1
526 | 451,Oslo,59.91669029,10.74997921,707500,Norway,5121333,525,Lajes,-27.80958291,-50.30998885,139972,Brazil,1
527 | 451,Oslo,59.91669029,10.74997921,707500,Norway,5121333,526,Lansing,42.73352724,-84.54673629,198821.5,United States of America,1
528 | 451,Oslo,59.91669029,10.74997921,707500,Norway,5121333,527,Novoaltaysk,53.39925865,83.95884395,76218,Russia,1
529 | 451,Oslo,59.91669029,10.74997921,707500,Norway,5121333,528,Novocherkassk,47.41995953,40.08002356,159470.5,Russia,1
530 | 451,Oslo,59.91669029,10.74997921,707500,Norway,5121333,529,Nowra,-34.88284625,150.6000476,61036.5,Australia,1
531 | 451,Oslo,59.91669029,10.74997921,707500,Norway,5121333,530,Nueva San Salvador,13.67399699,-89.28999848,124694,El Salvador,1
532 | 451,Oslo,59.91669029,10.74997921,707500,Norway,5121333,531,Nyanza,-2.349586569,29.74003454,225209,Rwanda,1
533 | 451,Oslo,59.91669029,10.74997921,707500,Norway,5121333,532,Obihiro,42.93041445,143.1700101,169614,Japan,1
534 | 451,Oslo,59.91669029,10.74997921,707500,Norway,5121333,533,Oldenburg,53.1299986,8.220004434,163338,Germany,1
535 | 451,Oslo,59.91669029,10.74997921,707500,Norway,5121333,534,Olomouc,49.63003135,17.24999589,97829,Czech Republic,1
536 | 451,Oslo,59.91669029,10.74997921,707500,Norway,5121333,535,Malindi,-3.209999167,40.10002234,81160,Kenya,1
537 | 451,Oslo,59.91669029,10.74997921,707500,Norway,5121333,536,Manchester,53.50041526,-2.247987103,1312757.5,United Kingdom,1
538 | 451,Oslo,59.91669029,10.74997921,707500,Norway,5121333,537,Mangyshlak,43.69045506,51.14173561,147443,Kazakhstan,1
539 | 451,Oslo,59.91669029,10.74997921,707500,Norway,5121333,538,Manisa,38.63039268,27.43996822,237700,Turkey,1
540 | 451,Oslo,59.91669029,10.74997921,707500,Norway,5121333,539,Salzburg,47.81047833,13.0400203,178274,Austria,1
541 | 451,Oslo,59.91669029,10.74997921,707500,Norway,5121333,540,St. John’s,47.58498822,-52.68100692,115325.5,Canada,1
542 | 451,Oslo,59.91669029,10.74997921,707500,Norway,5121333,541,Uberaba,-19.7799955,-47.9500037,234807,Brazil,1
543 | 451,Oslo,59.91669029,10.74997921,707500,Norway,5121333,542,Blagoveshchensk,50.26660748,127.5333418,206711,Russia,1
544 | 516,Quito,-0.214988181,-78.50005111,1550407,Ecuador,5211978,543,Utrecht,52.10034568,5.120038614,478224,Netherlands,1
545 | 516,Quito,-0.214988181,-78.50005111,1550407,Ecuador,5211978,544,Regina,50.45003298,-104.6170099,176183,Canada,1
546 | 516,Quito,-0.214988181,-78.50005111,1550407,Ecuador,5211978,545,Severodvinsk,64.57002382,39.83001298,182077.5,Russia,1
547 | 516,Quito,-0.214988181,-78.50005111,1550407,Ecuador,5211978,546,Tiruvannamalai,12.26037437,79.09996741,138243,India,1
548 | 516,Quito,-0.214988181,-78.50005111,1550407,Ecuador,5211978,547,Kiffa,16.61997906,-11.39998661,73930,Mauritania,1
549 | 516,Quito,-0.214988181,-78.50005111,1550407,Ecuador,5211978,548,Kigali,-1.953590069,30.06053178,802630.5,Rwanda,1
550 | 516,Quito,-0.214988181,-78.50005111,1550407,Ecuador,5211978,549,Kilifi,-3.609613018,39.85001176,63228.5,Kenya,1
551 | 516,Quito,-0.214988181,-78.50005111,1550407,Ecuador,5211978,550,Killeen,31.11728538,-97.72748214,120464,United States of America,1
552 | 516,Quito,-0.214988181,-78.50005111,1550407,Ecuador,5211978,551,Kimberley,-28.74683836,24.77000199,153676.5,South Africa,1
553 | 516,Quito,-0.214988181,-78.50005111,1550407,Ecuador,5211978,552,Kindia,10.06001772,-12.86997441,93511,Guinea,1
554 | 516,Quito,-0.214988181,-78.50005111,1550407,Ecuador,5211978,553,Kisumu,-0.090034567,34.75001298,306047,Kenya,1
555 | 516,Quito,-0.214988181,-78.50005111,1550407,Ecuador,5211978,554,Kitale,1.030465514,34.98994665,112809,Kenya,1
556 | 516,Quito,-0.214988181,-78.50005111,1550407,Ecuador,5211978,555,Beira,-19.82004474,34.87000565,507196.5,Mozambique,1
557 | 516,Quito,-0.214988181,-78.50005111,1550407,Ecuador,5211978,556,Hawalli,29.33334002,47.99999756,164212,Kuwait,1
558 | 516,Quito,-0.214988181,-78.50005111,1550407,Ecuador,5211978,557,Haarlem,52.38043194,4.629991006,248773.5,Netherlands,1
559 | 516,Quito,-0.214988181,-78.50005111,1550407,Ecuador,5211978,558,Hachinohe,40.50999371,141.5400321,225575,Japan,1
560 | 516,Quito,-0.214988181,-78.50005111,1550407,Ecuador,5211978,559,Hamburg,53.55002464,9.999999144,1748058.5,Germany,1
561 | 516,Quito,-0.214988181,-78.50005111,1550407,Ecuador,5211978,560,Hamilton,-37.77000853,175.3000386,112145,New Zealand,1
562 | 516,Quito,-0.214988181,-78.50005111,1550407,Ecuador,5211978,561,Hamilton,43.24998151,-79.82999577,620501,Canada,1
563 | 516,Quito,-0.214988181,-78.50005111,1550407,Ecuador,5211978,562,Hania,35.51221092,24.01557776,66646.5,Greece,1
564 | 516,Quito,-0.214988181,-78.50005111,1550407,Ecuador,5211978,563,Hannover,52.36697023,9.716657266,618815,Germany,1
565 | 516,Quito,-0.214988181,-78.50005111,1550407,Ecuador,5211978,564,Hartford,41.77002016,-72.67996708,518509.5,United States of America,1
566 | 516,Quito,-0.214988181,-78.50005111,1550407,Ecuador,5211978,565,Hatay,36.2303583,36.12000688,305564,Turkey,1
567 | 516,Quito,-0.214988181,-78.50005111,1550407,Ecuador,5211978,566,San Juan,18.80700306,-71.22899657,72950,Dominican Republic,1
568 | 516,Quito,-0.214988181,-78.50005111,1550407,Ecuador,5211978,567,Sterlitamak,53.62999392,55.96003617,220040,Russia,1
569 | 516,Quito,-0.214988181,-78.50005111,1550407,Ecuador,5211978,568,Uruguaiana,-29.76961831,-57.08998845,97736.5,Brazil,1
570 | 516,Quito,-0.214988181,-78.50005111,1550407,Ecuador,5211978,569,Eldoret,0.520005716,35.26998124,285913.5,Kenya,1
571 | 516,Quito,-0.214988181,-78.50005111,1550407,Ecuador,5211978,570,Sarajevo,43.8500224,18.38300167,662816.5,Bosnia and Herzegovina,1
572 | 516,Quito,-0.214988181,-78.50005111,1550407,Ecuador,5211978,571,Takaoka,36.67002138,136.9999991,124437,Japan,1
573 | 516,Quito,-0.214988181,-78.50005111,1550407,Ecuador,5211978,572,Versailles,48.80046958,2.133347533,85416,France,1
574 | 516,Quito,-0.214988181,-78.50005111,1550407,Ecuador,5211978,573,Cologne,50.93000368,6.950004434,983697.5,Germany,1
575 | 516,Quito,-0.214988181,-78.50005111,1550407,Ecuador,5211978,574,Copiapo,-27.35999795,-70.33998071,117316.5,Chile,1
576 | 516,Quito,-0.214988181,-78.50005111,1550407,Ecuador,5211978,575,Coral Gables,25.71541872,-80.29107874,98700.5,United States of America,1
577 | 516,Quito,-0.214988181,-78.50005111,1550407,Ecuador,5211978,576,Dundee,56.47038902,-3.000008384,151013.5,United Kingdom,1
578 | 516,Quito,-0.214988181,-78.50005111,1550407,Ecuador,5211978,577,Durban,-29.865013,30.98001054,2729000,South Africa,1
579 | 516,Quito,-0.214988181,-78.50005111,1550407,Ecuador,5211978,578,Edmonton,53.55002464,-113.4999819,885195.5,Canada,1
580 | 516,Quito,-0.214988181,-78.50005111,1550407,Ecuador,5211978,579,Bucaramanga,7.1300932,-73.12588302,790410,Colombia,1
581 | 516,Quito,-0.214988181,-78.50005111,1550407,Ecuador,5211978,580,Bago,17.32001385,96.51497676,264347,Myanmar,1
582 | 516,Quito,-0.214988181,-78.50005111,1550407,Ecuador,5211978,581,Baguio City,16.42999066,120.5699426,360269,Philippines,1
583 | 516,Quito,-0.214988181,-78.50005111,1550407,Ecuador,5211978,582,Bahia Blanca,-38.74002684,-62.2650214,279041,Argentina,1
584 | 516,Quito,-0.214988181,-78.50005111,1550407,Ecuador,5211978,583,Baku,40.39527203,49.86221716,2007150,Azerbaijan,1
585 | 516,Quito,-0.214988181,-78.50005111,1550407,Ecuador,5211978,584,Balakovo,52.02998822,47.80001745,172821.5,Russia,1
586 | 516,Quito,-0.214988181,-78.50005111,1550407,Ecuador,5211978,585,Balikesir,39.6503821,27.89001827,249833.5,Turkey,1
587 | 516,Quito,-0.214988181,-78.50005111,1550407,Ecuador,5211978,586,Samara,53.19500755,50.15129512,996595,Russia,1
588 | 516,Quito,-0.214988181,-78.50005111,1550407,Ecuador,5211978,587,St. Paul,44.94398663,-93.08497481,509961,United States of America,1
589 | 516,Quito,-0.214988181,-78.50005111,1550407,Ecuador,5211978,588,Uberlandia,-18.89999754,-48.27998356,484862,Brazil,1
590 | 405,Moscow,55.75216412,37.61552283,10452000,Russia,6465542,589,Nairobi,-1.283346742,36.81665686,2880273.5,Kenya,1
591 | 405,Moscow,55.75216412,37.61552283,10452000,Russia,6465542,590,Nakhodka,67.75039817,77.51996049,159551,Russia,1
592 | 405,Moscow,55.75216412,37.61552283,10452000,Russia,6465542,591,Plymouth,50.38538576,-4.159989259,239436,United Kingdom,1
593 | 405,Moscow,55.75216412,37.61552283,10452000,Russia,6465542,592,Pointe-a-Pitre,16.24147504,-61.5329989,81887.5,France,1
594 | 405,Moscow,55.75216412,37.61552283,10452000,Russia,6465542,593,Poitier,46.58329226,0.333276529,85383.5,France,1
595 | 405,Moscow,55.75216412,37.61552283,10452000,Russia,6465542,594,Polatsk,55.48938946,28.78598425,79216,Belarus,1
596 | 405,Moscow,55.75216412,37.61552283,10452000,Russia,6465542,595,Pori,61.47889467,21.77493933,71526,Finland,1
597 | 405,Moscow,55.75216412,37.61552283,10452000,Russia,6465542,596,Port Elizabeth,-33.97003375,25.60002885,830527,South Africa,1
598 | 405,Moscow,55.75216412,37.61552283,10452000,Russia,6465542,597,Port Louis,-20.16663857,57.49999385,371953.5,Mauritius,1
599 | 405,Moscow,55.75216412,37.61552283,10452000,Russia,6465542,598,Port Moresby,-9.464707826,147.1925036,267434.5,Papua New Guinea,1
600 | 405,Moscow,55.75216412,37.61552283,10452000,Russia,6465542,599,Portland,43.67216158,-70.2455274,99504,United States of America,1
601 | 405,Moscow,55.75216412,37.61552283,10452000,Russia,6465542,600,Porto Alegre,-30.05001463,-51.20001205,2644870.5,Brazil,1
602 | 405,Moscow,55.75216412,37.61552283,10452000,Russia,6465542,601,Porto-Novo,6.483310973,2.616625528,267084,Benin,1
603 | 405,Moscow,55.75216412,37.61552283,10452000,Russia,6465542,602,Portsmouth,50.80034751,-1.080022218,323676,United Kingdom,1
604 | 405,Moscow,55.75216412,37.61552283,10452000,Russia,6465542,603,Potenza,40.64200213,15.7989965,69060,Italy,1
605 | 405,Moscow,55.75216412,37.61552283,10452000,Russia,6465542,604,Iskenderun,36.58041445,36.17002966,228954,Turkey,1
606 | 405,Moscow,55.75216412,37.61552283,10452000,Russia,6465542,605,Itajai,-26.89961261,-48.68001083,241421,Brazil,1
607 | 405,Moscow,55.75216412,37.61552283,10452000,Russia,6465542,606,Iwaki,37.0553467,140.8900459,324677,Japan,1
608 | 405,Moscow,55.75216412,37.61552283,10452000,Russia,6465542,607,Jönköping,57.7713432,14.16501623,86491,Sweden,1
609 | 405,Moscow,55.75216412,37.61552283,10452000,Russia,6465542,608,Jaén,37.77039349,-3.799985394,92909,Spain,1
610 | 405,Moscow,55.75216412,37.61552283,10452000,Russia,6465542,609,Jalal Abad,40.94288719,73.00251013,162299.5,Kyrgyzstan,1
611 | 405,Moscow,55.75216412,37.61552283,10452000,Russia,6465542,610,Jeddah,21.51688946,39.21919755,2939723,Saudi Arabia,1
612 | 405,Moscow,55.75216412,37.61552283,10452000,Russia,6465542,611,Jelgava,56.65270347,23.71280554,64499,Latvia,1
613 | 405,Moscow,55.75216412,37.61552283,10452000,Russia,6465542,612,Jianmen,30.65005292,113.1600073,937875,China,1
614 | 405,Moscow,55.75216412,37.61552283,10452000,Russia,6465542,613,Jilin,43.84997072,126.5500427,2138988.5,China,1
615 | 405,Moscow,55.75216412,37.61552283,10452000,Russia,6465542,614,Johor Bahru,1.480024637,103.7300402,838744.5,Malaysia,1
616 | 405,Moscow,55.75216412,37.61552283,10452000,Russia,6465542,615,Juazeiro,-9.420007712,-40.49996749,95132,Brazil,1
617 | 593,San Bernardino,34.12038373,-117.3000342,973690.5,United States of America,6546546,616,Ottawa,45.4166968,-75.7000153,978564.5,Canada,1
618 | 593,San Bernardino,34.12038373,-117.3000342,973690.5,United States of America,6546546,617,Ouahigouya,13.5704236,-2.419992108,70300,Burkina Faso,1
619 | 593,San Bernardino,34.12038373,-117.3000342,973690.5,United States of America,6546546,618,Ourense,42.32996014,-7.869995363,113095,Spain,1
620 | 593,San Bernardino,34.12038373,-117.3000342,973690.5,United States of America,6546546,619,Pabna,24.00038129,89.24999385,137888,Bangladesh,1
621 | 593,San Bernardino,34.12038373,-117.3000342,973690.5,United States of America,6546546,620,Palmas,-10.23773558,-48.2877867,215793.5,Brazil,1
622 | 593,San Bernardino,34.12038373,-117.3000342,973690.5,United States of America,6546546,621,Panevežys,55.74002016,24.37002641,122400,Lithuania,1
623 | 593,San Bernardino,34.12038373,-117.3000342,973690.5,United States of America,6546546,622,Pardubice,50.04041974,15.76000932,97902.5,Czech Republic,1
624 | 593,San Bernardino,34.12038373,-117.3000342,973690.5,United States of America,6546546,623,Pathein,16.77040916,94.74996822,216014.5,Myanmar,1
625 | 593,San Bernardino,34.12038373,-117.3000342,973690.5,United States of America,6546546,624,Pavlodar,52.29999758,76.95002112,316254,Kazakhstan,1
626 | 593,San Bernardino,34.12038373,-117.3000342,973690.5,United States of America,6546546,625,Pec,43.88973574,20.33011796,137332.5,Serbia,1
627 | 593,San Bernardino,34.12038373,-117.3000342,973690.5,United States of America,6546546,626,Peoria,40.69998212,-89.67004114,142622,United States of America,1
628 | 593,San Bernardino,34.12038373,-117.3000342,973690.5,United States of America,6546546,627,Perpignan,42.69998924,2.899967406,128663,France,1
629 | 593,San Bernardino,34.12038373,-117.3000342,973690.5,United States of America,6546546,628,Phoenix,33.53997988,-112.0699917,2436022.5,United States of America,1
630 | 593,San Bernardino,34.12038373,-117.3000342,973690.5,United States of America,6546546,629,Pietermaritzburg,-29.61004148,30.39002071,620898,South Africa,1
631 | 593,San Bernardino,34.12038373,-117.3000342,973690.5,United States of America,6546546,630,Bani,18.279999,-70.33100347,66709,Dominican Republic,1
632 | 593,San Bernardino,34.12038373,-117.3000342,973690.5,United States of America,6546546,631,San Fernando,-34.58002236,-70.98996688,60746,Chile,1
633 | 593,San Bernardino,34.12038373,-117.3000342,973690.5,United States of America,6546546,632,St.-Denis,-20.87889484,55.44807776,163621,France,1
634 | 593,San Bernardino,34.12038373,-117.3000342,973690.5,United States of America,6546546,633,Umeå,63.82999147,20.23999426,76101,Sweden,1
635 | 593,San Bernardino,34.12038373,-117.3000342,973690.5,United States of America,6546546,634,Leeuwarden,53.25037884,5.783357298,108601,Netherlands,1
636 | 593,San Bernardino,34.12038373,-117.3000342,973690.5,United States of America,6546546,635,Leon,42.57997072,-5.570006553,135014,Spain,1
637 | 593,San Bernardino,34.12038373,-117.3000342,973690.5,United States of America,6546546,636,Lexington,38.05001467,-84.50002079,244972,United States of America,1
638 | 593,San Bernardino,34.12038373,-117.3000342,973690.5,United States of America,6546546,637,Liberec,50.79995994,15.07999914,99972.5,Czech Republic,1
639 | 593,San Bernardino,34.12038373,-117.3000342,973690.5,United States of America,6546546,638,Lida,53.88847943,25.28464758,99126,Belarus,1
640 | 593,San Bernardino,34.12038373,-117.3000342,973690.5,United States of America,6546546,639,Lincoln,40.81997479,-96.68000086,244146,United States of America,1
641 | 593,San Bernardino,34.12038373,-117.3000342,973690.5,United States of America,6546546,640,Bologna,44.50042198,11.34002071,429694.5,Italy,1
642 | 593,San Bernardino,34.12038373,-117.3000342,973690.5,United States of America,6546546,641,Elazig,38.67997622,39.22999792,271492,Turkey,1
643 | 593,San Bernardino,34.12038373,-117.3000342,973690.5,United States of America,6546546,642,Ruhengeri,-1.499612611,29.63001542,86685,Rwanda,1
644 | 593,San Bernardino,34.12038373,-117.3000342,973690.5,United States of America,6546546,643,Soledad,10.92001691,-74.76999455,520704,Colombia,1
645 | 593,San Bernardino,34.12038373,-117.3000342,973690.5,United States of America,6546546,644,Toyama,36.69999371,137.2300109,329172,Japan,1
646 | 593,San Bernardino,34.12038373,-117.3000342,973690.5,United States of America,6546546,645,Criciuma,-28.68002073,-49.38996749,183085.5,Brazil,1
647 | 630,Seoul,37.5663491,126.999731,9796000,South Korea,7778584,646,Salamanca,40.97040489,-5.670000449,160456.5,Spain,1
648 | 630,Seoul,37.5663491,126.999731,9796000,South Korea,7778584,647,Spring Hill,28.47894513,-82.54771102,91887.5,United States of America,1
649 | 630,Seoul,37.5663491,126.999731,9796000,South Korea,7778584,648,Turkistan,43.30155458,68.25489294,86743.5,Kazakhstan,1
650 | 630,Seoul,37.5663491,126.999731,9796000,South Korea,7778584,649,Salt Lake City,40.7750163,-111.9300519,572013,United States of America,1
651 | 630,Seoul,37.5663491,126.999731,9796000,South Korea,7778584,650,St. George,37.10415509,-113.583336,79988,United States of America,1
652 | 630,Seoul,37.5663491,126.999731,9796000,South Korea,7778584,651,Tyler,32.35108604,-95.30078272,101561.5,United States of America,1
653 | 630,Seoul,37.5663491,126.999731,9796000,South Korea,7778584,652,Riga,56.95002382,24.09996537,723802.5,Latvia,1
654 | 630,Seoul,37.5663491,126.999731,9796000,South Korea,7778584,653,Sheffield,53.36667666,-1.499996583,922800,United Kingdom,1
655 | 630,Seoul,37.5663491,126.999731,9796000,South Korea,7778584,654,Tolyatti,53.48039064,49.53004106,648622,Russia,1
656 | 630,Seoul,37.5663491,126.999731,9796000,South Korea,7778584,655,Buenos Aires,-34.60250161,-58.39753137,11862073,Argentina,1
657 | 630,Seoul,37.5663491,126.999731,9796000,South Korea,7778584,656,Conselheiro Lafaiete,-20.6700187,-43.78999923,102926,Brazil,1
658 | 630,Seoul,37.5663491,126.999731,9796000,South Korea,7778584,657,Columbus,32.47043276,-84.98001734,202225,United States of America,1
659 | 432,New York,40.74997906,-73.98001693,13524139,United States of America,10445464,658,Sasebo,33.1631295,129.7177046,224347.5,Japan,1
660 | 432,New York,40.74997906,-73.98001693,13524139,United States of America,10445464,659,Semey,50.43499514,80.2750378,302066.5,Kazakhstan,1
661 | 432,New York,40.74997906,-73.98001693,13524139,United States of America,10445464,660,Taunggyi,20.78199907,97.03800065,160115,Myanmar,1
662 | 432,New York,40.74997906,-73.98001693,13524139,United States of America,10445464,661,Thimphu,27.47298586,89.63901404,88930.5,Bhutan,1
663 | 432,New York,40.74997906,-73.98001693,13524139,United States of America,10445464,662,Vila Velha,-20.36760822,-40.31798893,742413.5,Brazil,1
664 | 432,New York,40.74997906,-73.98001693,13524139,United States of America,10445464,663,Warsaw,52.25000063,20.99999955,1704569.5,Poland,1
665 | 432,New York,40.74997906,-73.98001693,13524139,United States of America,10445464,664,Antananarivo,-18.91663735,47.5166239,1544216.5,Madagascar,1
666 | 432,New York,40.74997906,-73.98001693,13524139,United States of America,10445464,665,Antsirabe,-19.85001707,47.03329423,307921,Madagascar,1
667 | 432,New York,40.74997906,-73.98001693,13524139,United States of America,10445464,666,Antsiranana,-12.27650152,49.3115261,76312,Madagascar,1
668 | 432,New York,40.74997906,-73.98001693,13524139,United States of America,10445464,667,Aqtobe,50.28001752,57.16998816,260493,Kazakhstan,1
669 | 432,New York,40.74997906,-73.98001693,13524139,United States of America,10445464,668,Arapiraca,-9.750013409,-36.66999455,177115,Brazil,1
670 | 432,New York,40.74997906,-73.98001693,13524139,United States of America,10445464,669,Araxa,-19.5795943,-46.95001306,70159.5,Brazil,1
671 | 432,New York,40.74997906,-73.98001693,13524139,United States of America,10445464,670,Örebro,59.2803467,15.2199906,95932,Sweden,1
672 | 432,New York,40.74997906,-73.98001693,13524139,United States of America,10445464,671,Arezzo,43.46172569,11.87497514,82613,Italy,1
673 | 432,New York,40.74997906,-73.98001693,13524139,United States of America,10445464,672,Arlington,32.68476076,-97.02023849,545107.5,United States of America,1
674 | 432,New York,40.74997906,-73.98001693,13524139,United States of America,10445464,673,Armavir,45.00039146,41.13003699,191813.5,Russia,1
675 | 432,New York,40.74997906,-73.98001693,13524139,United States of America,10445464,674,San Cristobal,18.4159981,-70.10900052,154040,Dominican Republic,1
676 | 432,New York,40.74997906,-73.98001693,13524139,United States of America,10445464,675,St. Petersburg,27.77053876,-82.67938257,523314.5,United States of America,1
677 | 432,New York,40.74997906,-73.98001693,13524139,United States of America,10445464,676,Ulm,48.40039064,9.999999144,146703,Germany,1
678 |
--------------------------------------------------------------------------------
/docs/csv-data/Flowmap_Cities_one_to_one.csv:
--------------------------------------------------------------------------------
1 | s_city_id,s_city,s_lat,s_lon,s_pop,s_country,s_Volume,s_Vol2,e_city_id,e_City,e_lat,e_lon,e_pop,e_country,e_vol,e_Vol2
2 | 1,Sarh,9.149969909,18.39002966,135862,Chad,33,505,238,Hechi,23.09653465,109.6091129,3275189.5,China,291099,10
3 | 10,Asheville,35.60119773,-82.55414474,105775,United States of America,3,832,623,San Jose,9.93501243,-84.08405135,642862,Costa Rica,302064,20
4 | 17,Ballarat,-37.55958209,143.8400468,73404,Australia,29,900,222,Haifa,32.8204114,34.98002478,639150,Israel,400017,30
5 | 23,Elkhart,41.68294537,-85.96879419,100295,United States of America,23,696,657,Ulaanbaatar,47.9166734,106.9166158,827306,Mongolia,645321,15
6 | 43,Chengdu,30.67000002,104.0700195,4036718.5,China,31,534,262,Johannesburg,-26.17004474,28.03000972,2730734.5,South Africa,666365,17
7 | 57,Beirut,33.87197512,35.50970821,1779062.5,Lebanon,3,946,183,Dakar,14.71583173,-17.47313013,2540200,Senegal,765122,9
8 | 96,Mar del Plata,-38.00002033,-57.57998438,554916,Argentina,20,842,579,Rome,41.89595563,12.48325842,1687226,Italy,800446,12
9 | 110,Tacoma,47.21131594,-122.5150131,460273,United States of America,29,885,103,Berlin,52.52181866,13.40154862,3250007,Germany,904561,36
10 | 150,Utsunomiya,36.54997703,139.8700048,558808.5,Japan,6,672,373,Mendoza,-32.88333006,-68.81661117,827815,Argentina,987654,36
11 | 175,Charlottesville,38.02918907,-78.47692591,61314,United States of America,17,532,237,Ipoh,4.599989236,101.0649833,656227,Malaysia,1148668,8
12 | 199,Ceske Budejovice,48.98001935,14.46003699,97452,Czech Republic,20,881,276,Lima,-12.04801268,-77.05006209,7385117,Peru,1222446,31
13 | 216,Tripoli,32.89250002,13.18001176,1209199,Libya,34,665,562,Reykjavík,64.15002362,-21.95001449,140059,Iceland,1241978,27
14 | 232,Nagaoka,37.45041302,138.8600406,187560,Japan,20,952,389,Miami,25.7876107,-80.22410608,2983947,United States of America,1354625,14
15 | 259,Sunderland,54.92001853,-1.380029746,315449.5,United Kingdom,29,877,489,Phnom Penh,11.55003013,104.9166345,1466000,Cambodia,1504012,24
16 | 327,Santo Angelo,-28.30004393,-54.28003076,65013,Brazil,24,826,35,Barcelona,41.38329958,2.183370319,3250797.5,Spain,2988556,22
17 | 361,Osnabrück,52.28043805,8.049988972,198865,Germany,1,852,1,Alexandria,31.20001935,29.94999589,3988258,Egypt,3502678,11
18 | 362,Groningen,53.22040651,6.580001179,198941,Netherlands,12,730,128,Chicago,41.82999066,-87.75005497,5915976,United States of America,3954100,11
19 | 504,Annecy,45.89997479,6.116670287,77490.5,France,3,874,642,Tokyo,35.68501691,139.7514074,22006299.5,Japan,4512331,26
20 | 542,Blagoveshchensk,50.26660748,127.5333418,206711,Russia,14,728,451,Oslo,59.91669029,10.74997921,707500,Norway,5121333,14
21 | 588,Uberlandia,-18.89999754,-48.27998356,484862,Brazil,20,916,516,Quito,-0.214988181,-78.50005111,1550407,Ecuador,5211978,6
22 | 615,Juazeiro,-9.420007712,-40.49996749,95132,Brazil,9,731,405,Moscow,55.75216412,37.61552283,10452000,Russia,6465542,33
23 | 645,Criciuma,-28.68002073,-49.38996749,183085.5,Brazil,3,777,593,San Bernardino,34.12038373,-117.3000342,973690.5,United States of America,6546546,7
24 | 657,Columbus,32.47043276,-84.98001734,202225,United States of America,22,931,630,Seoul,37.5663491,126.999731,9796000,South Korea,7778584,9
25 | 676,Ulm,48.40039064,9.999999144,146703,Germany,29,530,432,New York,40.74997906,-73.98001693,13524139,United States of America,10445464,34
26 |
--------------------------------------------------------------------------------
/docs/main/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Canvas Flowmap Layer with LeafletJS
10 |
11 |
12 |
13 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
121 |
122 |
123 |
124 |
125 |
--------------------------------------------------------------------------------
/img/img_01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jwasilgeo/Leaflet.Canvas-Flowmap-Layer/7ae3238d3bbe11512eeda5ce47b5593c172b23e6/img/img_01.png
--------------------------------------------------------------------------------
/src/CanvasFlowmapLayer.js:
--------------------------------------------------------------------------------
1 | (function(factory, window) {
2 | // module loaders support for LeafletJS plugins, see:
3 | // https://github.com/Leaflet/Leaflet/blob/master/PLUGIN-GUIDE.md#module-loaders
4 |
5 | // AMD module that relies on "leaflet"
6 | if (typeof define === 'function' && define.amd) {
7 | define(['leaflet'], factory);
8 |
9 | // Common JS module that relies on "leaflet"
10 | } else if (typeof exports === 'object') {
11 | module.exports = factory(require('leaflet'));
12 | }
13 |
14 | // attach plugin to the global leaflet "L" variable
15 | if (typeof window !== 'undefined' && window.L) {
16 | window.L.CanvasFlowmapLayer = factory(L);
17 |
18 | window.L.canvasFlowmapLayer = function(originAndDestinationGeoJsonPoints, opts) {
19 | return new window.L.CanvasFlowmapLayer(originAndDestinationGeoJsonPoints, opts);
20 | };
21 | }
22 | }(function(L) {
23 | // layer source code
24 | var canvasRenderer = L.canvas();
25 |
26 | var CanvasFlowmapLayer = L.GeoJSON.extend({
27 | options: {
28 | // this is only a default option example,
29 | // developers will most likely need to provide this
30 | // options object with values unique to their data
31 | originAndDestinationFieldIds: {
32 | originUniqueIdField: 'origin_id',
33 | originGeometry: {
34 | x: 'origin_lon',
35 | y: 'origin_lat'
36 | },
37 | destinationUniqueIdField: 'destination_id',
38 | destinationGeometry: {
39 | x: 'destination_lon',
40 | y: 'destination_lat'
41 | }
42 | },
43 |
44 | canvasBezierStyle: {
45 | type: 'simple',
46 | symbol: {
47 | // use canvas styling options (compare to CircleMarker styling below)
48 | strokeStyle: 'rgba(255, 0, 51, 0.8)',
49 | lineWidth: 0.75,
50 | lineCap: 'round',
51 | shadowColor: 'rgb(255, 0, 51)',
52 | shadowBlur: 1.5
53 | }
54 | },
55 |
56 | animatedCanvasBezierStyle: {
57 | type: 'simple',
58 | symbol: {
59 | // use canvas styling options (compare to CircleMarker styling below)
60 | strokeStyle: 'rgb(255, 46, 88)',
61 | lineWidth: 1.25,
62 | lineDashOffsetSize: 4, // custom property used with animation sprite sizes
63 | lineCap: 'round',
64 | shadowColor: 'rgb(255, 0, 51)',
65 | shadowBlur: 2
66 | }
67 | },
68 |
69 | // valid values: 'selection' or 'all'
70 | // use 'all' to display all Bezier paths immediately
71 | // use 'selection' if Bezier paths will be drawn with user interactions
72 | pathDisplayMode: 'all',
73 |
74 | wrapAroundCanvas: true,
75 |
76 | animationStarted: false,
77 |
78 | animationEasingFamily: 'Cubic',
79 |
80 | animationEasingType: 'In',
81 |
82 | animationDuration: 2000,
83 |
84 | pointToLayer: function(geoJsonPoint, latlng) {
85 | return L.circleMarker(latlng);
86 | },
87 |
88 | style: function(geoJsonFeature) {
89 | // use leaflet's path styling options
90 |
91 | // since the GeoJSON feature properties are modified by the layer,
92 | // developers can rely on the "isOrigin" property to set different
93 | // symbols for origin vs destination CircleMarker stylings
94 |
95 | if (geoJsonFeature.properties.isOrigin) {
96 | return {
97 | renderer: canvasRenderer, // recommended to use L.canvas()
98 | radius: 5,
99 | weight: 1,
100 | color: 'rgb(195, 255, 62)',
101 | fillColor: 'rgba(195, 255, 62, 0.6)',
102 | fillOpacity: 0.6
103 | };
104 | } else {
105 | return {
106 | renderer: canvasRenderer,
107 | radius: 2.5,
108 | weight: 0.25,
109 | color: 'rgb(17, 142, 170)',
110 | fillColor: 'rgb(17, 142, 170)',
111 | fillOpacity: 0.7
112 | };
113 | }
114 | }
115 | },
116 |
117 | _customCanvases: [],
118 |
119 | initialize: function(geoJson, options) {
120 | // same as L.GeoJSON intialize method, but first performs custom GeoJSON
121 | // data parsing and reformatting before finally calling L.GeoJSON addData method
122 | L.setOptions(this, options);
123 |
124 | this._animationPropertiesStatic = {
125 | offset: 0,
126 | resetOffset: 200,
127 | repeat: Infinity,
128 | yoyo: false
129 | };
130 |
131 | this._animationPropertiesDynamic = {
132 | duration: null,
133 | easingInfo: null
134 | };
135 |
136 | this._layers = {};
137 |
138 | // beginning of customized initialize method
139 | if (geoJson && this.options.originAndDestinationFieldIds) {
140 | this.setOriginAndDestinationGeoJsonPoints(geoJson);
141 | }
142 |
143 | // establish animation properties using Tween.js library
144 | // currently requires the developer to add it to their own app index.html
145 | // TODO: find better way to wrap it up in this layer source code
146 | if (window.hasOwnProperty('TWEEN')) {
147 | // set this._animationPropertiesDynamic.duration value
148 | this.setAnimationDuration(this.options.animationDuration);
149 | // set this._animationPropertiesDynamic.easingInfo value
150 | this.setAnimationEasing(this.options.animationEasingFamily, this.options.animationEasingType);
151 |
152 | // initiate the active animation tween
153 | this._animationTween = new TWEEN.Tween(this._animationPropertiesStatic)
154 | .to({
155 | offset: this._animationPropertiesStatic.resetOffset
156 | }, this._animationPropertiesDynamic.duration)
157 | .easing(this._animationPropertiesDynamic.easingInfo.tweenEasingFunction)
158 | .repeat(this._animationPropertiesStatic.repeat)
159 | .yoyo(this._animationPropertiesStatic.yoyo)
160 | .start();
161 | } else {
162 | // Tween.js lib isn't available,
163 | // ensure that animations aren't attempted at the beginning
164 | this.options.animationStarted = false;
165 | }
166 | },
167 |
168 | setOriginAndDestinationGeoJsonPoints: function(geoJsonFeatureCollection) {
169 | if (geoJsonFeatureCollection.features) {
170 | var configOriginGeometryObject = this.options.originAndDestinationFieldIds.originGeometry;
171 | var configDestinationGeometryObject = this.options.originAndDestinationFieldIds.destinationGeometry;
172 |
173 | geoJsonFeatureCollection.features.forEach(function(feature, index) {
174 | if (feature.type === 'Feature' && feature.geometry && feature.geometry.type === 'Point') {
175 | // origin feature -- modify attribute properties and geometry
176 | feature.properties.isOrigin = true;
177 | feature.properties._isSelectedForPathDisplay = this.options.pathDisplayMode === 'all' ? true : false;
178 | feature.properties._uniqueId = index + '_origin';
179 |
180 | feature.geometry.coordinates = [
181 | feature.properties[configOriginGeometryObject.x],
182 | feature.properties[configOriginGeometryObject.y]
183 | ];
184 |
185 | // destination feature -- clone, modify, and push to feature collection
186 | var destinationFeature = JSON.parse(JSON.stringify(feature));
187 |
188 | destinationFeature.properties.isOrigin = false;
189 | destinationFeature.properties._isSelectedForPathDisplay = false;
190 | destinationFeature.properties._uniqueId = index + '_destination';
191 |
192 | destinationFeature.geometry.coordinates = [
193 | destinationFeature.properties[configDestinationGeometryObject.x],
194 | destinationFeature.properties[configDestinationGeometryObject.y]
195 | ];
196 |
197 | geoJsonFeatureCollection.features.push(destinationFeature);
198 | }
199 | }, this);
200 |
201 | // all origin/destination features are available for future internal used
202 | // but only a filtered subset of these are drawn on the map
203 | this.originAndDestinationGeoJsonPoints = geoJsonFeatureCollection;
204 | var geoJsonPointsToDraw = this._filterGeoJsonPointsToDraw(geoJsonFeatureCollection);
205 | this.addData(geoJsonPointsToDraw);
206 | } else {
207 | // TODO: improved handling of invalid incoming GeoJson FeatureCollection?
208 | this.originAndDestinationGeoJsonPoints = null;
209 | }
210 |
211 | return this;
212 | },
213 |
214 | onAdd: function(map) {
215 | // call the L.GeoJSON onAdd method,
216 | // then continue with custom code
217 | L.GeoJSON.prototype.onAdd.call(this, map);
218 |
219 | // create new canvas element for optional, animated bezier curves
220 | this._animationCanvasElement = this._insertCustomCanvasElement(map, this.options);
221 |
222 | // create new canvas element for manually drawing bezier curves
223 | // - most of the magic happens in this canvas element
224 | // - this canvas element is established last because it will be
225 | // inserted before (underneath) the animation canvas element
226 | this._canvasElement = this._insertCustomCanvasElement(map, this.options);
227 |
228 | // create a reference to both canvas elements in an array for convenience
229 | this._customCanvases = [this._canvasElement, this._animationCanvasElement]
230 |
231 | // establish custom event listeners
232 | this.on('click mouseover', this._modifyInteractionEvent, this);
233 | map.on('move', this._resetCanvas, this);
234 | map.on('moveend', this._resetCanvasAndWrapGeoJsonCircleMarkers, this);
235 | map.on('resize', this._resizeCanvas, this);
236 | if (map.options.zoomAnimation && L.Browser.any3d) {
237 | map.on('zoomanim', this._animateZoom, this);
238 | }
239 |
240 | // calculate initial size and position of canvas
241 | // and draw its content for the first time
242 | this._resizeCanvas();
243 | this._resetCanvasAndWrapGeoJsonCircleMarkers();
244 |
245 | return this;
246 | },
247 |
248 | onRemove: function(map) {
249 | // call the L.GeoJSON onRemove method,
250 | // then continue with custom code
251 | L.GeoJSON.prototype.onRemove.call(this, map);
252 |
253 | this._clearCanvas();
254 |
255 | this._customCanvases.forEach(function(canvas) {
256 | L.DomUtil.remove(canvas);
257 | });
258 |
259 | // remove custom event listeners
260 | this.off('click mouseover', this._modifyInteractionEvent, this);
261 | map.off('move', this._resetCanvas, this);
262 | map.off('moveend', this._resetCanvasAndWrapGeoJsonCircleMarkers, this);
263 | map.off('resize', this._resizeCanvas, this);
264 | if (map.options.zoomAnimation) {
265 | map.off('zoomanim', this._animateZoom, this);
266 | }
267 |
268 | return this;
269 | },
270 |
271 | bringToBack: function() {
272 | // call the L.GeoJSON bringToBack method to manage the point graphics
273 | L.GeoJSON.prototype.bringToBack.call(this);
274 |
275 | // keep the animation canvas element on top of the main canvas element
276 | L.DomUtil.toBack(this._animationCanvasElement);
277 |
278 | // keep the main canvas element underneath the animation canvas element
279 | L.DomUtil.toBack(this._canvasElement);
280 |
281 | return this;
282 | },
283 |
284 | bringToFront: function() {
285 | // keep the main canvas element underneath the animation canvas element
286 | L.DomUtil.toFront(this._canvasElement);
287 |
288 | // keep the animation canvas element on top of the main canvas element
289 | L.DomUtil.toFront(this._animationCanvasElement);
290 |
291 | // call the L.GeoJSON bringToFront method to manage the point graphics
292 | L.GeoJSON.prototype.bringToFront.call(this);
293 |
294 | return this;
295 | },
296 |
297 | setAnimationDuration: function(milliseconds) {
298 | milliseconds = Number(milliseconds) || this.options.animationDuration;
299 |
300 | // change the tween duration on the active animation tween
301 | if (this._animationTween) {
302 | this._animationTween.to({
303 | offset: this._animationPropertiesStatic.resetOffset
304 | }, milliseconds);
305 | }
306 |
307 | this._animationPropertiesDynamic.duration = milliseconds;
308 | },
309 |
310 | setAnimationEasing: function(easingFamily, easingType) {
311 | var tweenEasingFunction;
312 | if (
313 | TWEEN.Easing.hasOwnProperty(easingFamily) &&
314 | TWEEN.Easing[easingFamily].hasOwnProperty(easingType)
315 | ) {
316 | tweenEasingFunction = TWEEN.Easing[easingFamily][easingType];
317 | } else {
318 | easingFamily = this.options.animationEasingFamily;
319 | easingType = this.options.animationEasingType;
320 | tweenEasingFunction = TWEEN.Easing[easingFamily][easingType];
321 | }
322 |
323 | // change the tween easing function on the active animation tween
324 | if (this._animationTween) {
325 | this._animationTween.easing(tweenEasingFunction);
326 | }
327 |
328 | this._animationPropertiesDynamic.easingInfo = {
329 | easingFamily: easingFamily,
330 | easingType: easingType,
331 | tweenEasingFunction: tweenEasingFunction
332 | };
333 | },
334 |
335 | getAnimationEasingOptions: function(prettyPrint) {
336 | var tweenEasingConsoleOptions = {};
337 | var tweenEasingOptions = {};
338 |
339 | Object.keys(TWEEN.Easing).forEach(function(family) {
340 | tweenEasingConsoleOptions[family] = {
341 | types: Object.keys(TWEEN.Easing[family]).join('", "')
342 | };
343 |
344 | tweenEasingOptions[family] = {
345 | types: Object.keys(TWEEN.Easing[family])
346 | };
347 | });
348 |
349 | if (!!prettyPrint) {
350 | console.table(tweenEasingConsoleOptions);
351 | }
352 |
353 | return tweenEasingOptions;
354 | },
355 |
356 | playAnimation: function() {
357 | this.options.animationStarted = true;
358 | this._redrawCanvas();
359 | },
360 |
361 | stopAnimation: function() {
362 | this.options.animationStarted = false;
363 | this._redrawCanvas();
364 | },
365 |
366 | selectFeaturesForPathDisplay: function(selectionFeatures, selectionMode) {
367 | this._applyFeaturesSelection(selectionFeatures, selectionMode, '_isSelectedForPathDisplay');
368 | },
369 |
370 | selectFeaturesForPathDisplayById: function(uniqueOriginOrDestinationIdField, idValue, originBoolean, selectionMode) {
371 | if (
372 | uniqueOriginOrDestinationIdField !== this.options.originAndDestinationFieldIds.originUniqueIdField &&
373 | uniqueOriginOrDestinationIdField !== this.options.originAndDestinationFieldIds.destinationUniqueIdField
374 | ) {
375 | console.error('Invalid unique id field supplied for origin or destination. It must be one of these: ' +
376 | this.options.originAndDestinationFieldIds.originUniqueIdField + ', ' + this.options.originAndDestinationFieldIds.destinationUniqueIdField);
377 | return;
378 | }
379 |
380 | var existingOriginOrDestinationFeature = this.originAndDestinationGeoJsonPoints.features.filter(function(feature) {
381 | return feature.properties.isOrigin === originBoolean &&
382 | feature.properties[uniqueOriginOrDestinationIdField] === idValue;
383 | })[0];
384 |
385 | var odInfo = this._getSharedOriginOrDestinationFeatures(existingOriginOrDestinationFeature);
386 |
387 | if (odInfo.isOriginFeature) {
388 | this.selectFeaturesForPathDisplay(odInfo.sharedOriginFeatures, selectionMode);
389 | } else {
390 | this.selectFeaturesForPathDisplay(odInfo.sharedDestinationFeatures, selectionMode);
391 | }
392 | },
393 |
394 | clearAllPathSelections: function() {
395 | this.originAndDestinationGeoJsonPoints.features.forEach(function(feature) {
396 | feature.properties._isSelectedForPathDisplay = false;
397 | });
398 |
399 | this._resetCanvas();
400 | },
401 |
402 | selectAllFeaturesForPathDisplay: function() {
403 | this.originAndDestinationGeoJsonPoints.features.forEach(function(feature) {
404 | if (feature.properties.isOrigin) {
405 | feature.properties._isSelectedForPathDisplay = true;
406 | } else {
407 | feature.properties._isSelectedForPathDisplay = false;
408 | }
409 | });
410 |
411 | this._resetCanvas();
412 | },
413 |
414 | _filterGeoJsonPointsToDraw: function(geoJsonFeatureCollection) {
415 | var newGeoJson = {
416 | type: 'FeatureCollection',
417 | features: []
418 | };
419 |
420 | var originUniqueIdValues = [];
421 | var destinationUniqueIdValues = [];
422 |
423 | var originUniqueIdField = this.options.originAndDestinationFieldIds.originUniqueIdField;
424 | var destinationUniqueIdField = this.options.originAndDestinationFieldIds.destinationUniqueIdField;
425 |
426 | geoJsonFeatureCollection.features.forEach(function(feature) {
427 | var isOrigin = feature.properties.isOrigin;
428 |
429 | if (isOrigin && originUniqueIdValues.indexOf(feature.properties[originUniqueIdField]) === -1) {
430 | originUniqueIdValues.push(feature.properties[originUniqueIdField]);
431 | newGeoJson.features.push(feature);
432 | } else if (!isOrigin && destinationUniqueIdValues.indexOf(feature.properties[destinationUniqueIdField]) === -1) {
433 | destinationUniqueIdValues.push(feature.properties[destinationUniqueIdField]);
434 | newGeoJson.features.push(feature);
435 | } else {
436 | // do not attempt to draw an origin or destination circle on the canvas if it is already in one of the tracking arrays
437 | return;
438 | }
439 | });
440 |
441 | return newGeoJson;
442 | },
443 |
444 | _insertCustomCanvasElement: function(map, options) {
445 | var canvas = L.DomUtil.create('canvas', 'leaflet-zoom-animated');
446 |
447 | var originProp = L.DomUtil.testProp(['transformOrigin', 'WebkitTransformOrigin', 'msTransformOrigin']);
448 | canvas.style[originProp] = '50% 50%';
449 |
450 | var pane = map.getPane(options.pane);
451 | pane.insertBefore(canvas, pane.firstChild);
452 |
453 | return canvas;
454 | },
455 |
456 | _modifyInteractionEvent: function(e) {
457 | var odInfo = this._getSharedOriginOrDestinationFeatures(e.layer.feature);
458 | e.isOriginFeature = odInfo.isOriginFeature;
459 | e.sharedOriginFeatures = odInfo.sharedOriginFeatures;
460 | e.sharedDestinationFeatures = odInfo.sharedDestinationFeatures;
461 | },
462 |
463 | _getSharedOriginOrDestinationFeatures: function(testFeature) {
464 | var isOriginFeature = testFeature.properties.isOrigin;
465 | var sharedOriginFeatures = [];
466 | var sharedDestinationFeatures = [];
467 |
468 | if (isOriginFeature) {
469 | // for an ORIGIN point that was interacted with,
470 | // make an array of all other ORIGIN features with the same ORIGIN ID field
471 | var originUniqueIdField = this.options.originAndDestinationFieldIds.originUniqueIdField;
472 | var testFeatureOriginId = testFeature.properties[originUniqueIdField];
473 | sharedOriginFeatures = this.originAndDestinationGeoJsonPoints.features.filter(function(feature) {
474 | return feature.properties.isOrigin &&
475 | feature.properties[originUniqueIdField] === testFeatureOriginId;
476 | });
477 | } else {
478 | // for a DESTINATION point that was interacted with,
479 | // make an array of all other ORIGIN features with the same DESTINATION ID field
480 | var destinationUniqueIdField = this.options.originAndDestinationFieldIds.destinationUniqueIdField;
481 | var testFeatureDestinationId = testFeature.properties[destinationUniqueIdField];
482 | sharedDestinationFeatures = this.originAndDestinationGeoJsonPoints.features.filter(function(feature) {
483 | return feature.properties.isOrigin &&
484 | feature.properties[destinationUniqueIdField] === testFeatureDestinationId;
485 | });
486 | }
487 |
488 | return {
489 | isOriginFeature: isOriginFeature, // Boolean
490 | sharedOriginFeatures: sharedOriginFeatures, // Array of features
491 | sharedDestinationFeatures: sharedDestinationFeatures // Array of features
492 | };
493 | },
494 |
495 | _applyFeaturesSelection: function(selectionFeatures, selectionMode, selectionAttributeName) {
496 | var selectionIds = selectionFeatures.map(function(feature) {
497 | return feature.properties._uniqueId;
498 | });
499 |
500 | if (selectionMode === 'SELECTION_NEW') {
501 | this.originAndDestinationGeoJsonPoints.features.forEach(function(feature) {
502 | if (selectionIds.indexOf(feature.properties._uniqueId) > -1) {
503 | feature.properties[selectionAttributeName] = true;
504 | } else {
505 | feature.properties[selectionAttributeName] = false;
506 | }
507 | });
508 | } else if (selectionMode === 'SELECTION_ADD') {
509 | this.originAndDestinationGeoJsonPoints.features.forEach(function(feature) {
510 | if (selectionIds.indexOf(feature.properties._uniqueId) > -1) {
511 | feature.properties[selectionAttributeName] = true;
512 | }
513 | });
514 | } else if (selectionMode === 'SELECTION_SUBTRACT') {
515 | this.originAndDestinationGeoJsonPoints.features.forEach(function(feature) {
516 | if (selectionIds.indexOf(feature.properties._uniqueId) > -1) {
517 | feature.properties[selectionAttributeName] = false;
518 | }
519 | });
520 | } else {
521 | return;
522 | }
523 |
524 | this._resetCanvas();
525 | },
526 |
527 | _animateZoom: function(e) {
528 | // see: https://github.com/Leaflet/Leaflet.heat
529 | var scale = this._map.getZoomScale(e.zoom);
530 | var offset = this._map._getCenterOffset(e.center)._multiplyBy(-scale).subtract(this._map._getMapPanePos());
531 |
532 | if (L.DomUtil.setTransform) {
533 | this._customCanvases.forEach(function(canvas) {
534 | L.DomUtil.setTransform(canvas, offset, scale);
535 | });
536 | } else {
537 | this._customCanvases.forEach(function(canvas) {
538 | canvas.style[L.DomUtil.TRANSFORM] = L.DomUtil.getTranslateString(offset) + ' scale(' + scale + ')';
539 | });
540 | }
541 | },
542 |
543 | _resizeCanvas: function() {
544 | // update the canvas size
545 | var size = this._map.getSize();
546 | this._customCanvases.forEach(function(canvas) {
547 | canvas.width = size.x;
548 | canvas.height = size.y;
549 | });
550 |
551 | this._resetCanvas();
552 | },
553 |
554 | _resetCanvas: function() {
555 | if (!this._map) {
556 | // stop early if the layer is not currently on the map
557 | return;
558 | }
559 |
560 | // update the canvas position and redraw its content
561 | var topLeft = this._map.containerPointToLayerPoint([0, 0]);
562 | this._customCanvases.forEach(function(canvas) {
563 | L.DomUtil.setPosition(canvas, topLeft);
564 | });
565 |
566 | this._redrawCanvas();
567 | },
568 |
569 | _resetCanvasAndWrapGeoJsonCircleMarkers: function() {
570 | this._resetCanvas();
571 | // Leaflet will redraw a CircleMarker when its latLng is changed
572 | // sometimes they are drawn 2+ times if this occurs during many "move" events
573 | // so for now, only chang CircleMarker latlng after a single "moveend" event
574 | this._wrapGeoJsonCircleMarkers();
575 | },
576 |
577 | _redrawCanvas: function() {
578 | // draw canvas content (only the Bezier curves)
579 | if (this._map && this.originAndDestinationGeoJsonPoints) {
580 | this._clearCanvas();
581 |
582 | // loop over each of the "selected" features and re-draw the canvas paths
583 | this._drawSelectedCanvasPaths(false);
584 |
585 | if (this._animationFrameId) {
586 | L.Util.cancelAnimFrame(this._animationFrameId);
587 | }
588 |
589 | if (
590 | this.options.animationStarted &&
591 | this.originAndDestinationGeoJsonPoints.features.some(function(feature) {
592 | return feature.properties._isSelectedForPathDisplay;
593 | })
594 | ) {
595 | // start animation loop if the layer is currently set for showing animations,
596 | // and if there is at least 1 feature selected for displaying paths
597 | this._animator();
598 | }
599 | }
600 | },
601 |
602 | _clearCanvas: function() {
603 | this._customCanvases.forEach(function(canvas) {
604 | canvas.getContext('2d').clearRect(0, 0, canvas.width, canvas.height);
605 | });
606 |
607 | if (this._animationFrameId) {
608 | L.Util.cancelAnimFrame(this._animationFrameId);
609 | }
610 | },
611 |
612 | _drawSelectedCanvasPaths: function(animate) {
613 | var ctx = animate ?
614 | this._animationCanvasElement.getContext('2d') :
615 | this._canvasElement.getContext('2d');
616 |
617 | var originAndDestinationFieldIds = this.options.originAndDestinationFieldIds;
618 |
619 | this.originAndDestinationGeoJsonPoints.features.forEach(function(feature) {
620 |
621 | if (feature.properties._isSelectedForPathDisplay) {
622 | var originXCoordinate = feature.properties[originAndDestinationFieldIds.originGeometry.x];
623 | var originYCoordinate = feature.properties[originAndDestinationFieldIds.originGeometry.y];
624 | var destinationXCoordinate = feature.properties[originAndDestinationFieldIds.destinationGeometry.x];
625 | var destinationYCoordinate = feature.properties[originAndDestinationFieldIds.destinationGeometry.y];
626 |
627 | // origin and destination points for drawing curved lines
628 | // ensure that canvas features will be drawn beyond +/-180 longitude
629 | var originLatLng = this._wrapAroundLatLng(L.latLng([originYCoordinate, originXCoordinate]));
630 | var destinationLatLng = this._wrapAroundLatLng(L.latLng([destinationYCoordinate, destinationXCoordinate]));
631 |
632 | // convert geometry to screen coordinates for canvas drawing
633 | var screenOriginPoint = this._map.latLngToContainerPoint(originLatLng);
634 | var screenDestinationPoint = this._map.latLngToContainerPoint(destinationLatLng);
635 |
636 | // get the canvas symbol properties,
637 | // and draw a curved canvas line
638 | var symbol;
639 | if (animate) {
640 | symbol = this._getSymbolProperties(feature, this.options.animatedCanvasBezierStyle);
641 | ctx.beginPath();
642 | this._animateCanvasLineSymbol(ctx, symbol, screenOriginPoint, screenDestinationPoint);
643 | ctx.stroke();
644 | ctx.closePath();
645 | } else {
646 | symbol = this._getSymbolProperties(feature, this.options.canvasBezierStyle);
647 | ctx.beginPath();
648 | this._applyCanvasLineSymbol(ctx, symbol, screenOriginPoint, screenDestinationPoint);
649 | ctx.stroke();
650 | ctx.closePath();
651 | }
652 | }
653 | }, this);
654 | },
655 |
656 | _getSymbolProperties: function(feature, canvasSymbolConfig) {
657 | // get the canvas symbol properties
658 | var symbol;
659 | var filteredSymbols;
660 | if (canvasSymbolConfig.type === 'simple') {
661 | symbol = canvasSymbolConfig.symbol;
662 | } else if (canvasSymbolConfig.type === 'uniqueValue') {
663 | filteredSymbols = canvasSymbolConfig.uniqueValueInfos.filter(function(info) {
664 | return info.value === feature.properties[canvasSymbolConfig.field];
665 | });
666 | symbol = filteredSymbols[0].symbol;
667 | } else if (canvasSymbolConfig.type === 'classBreaks') {
668 | filteredSymbols = canvasSymbolConfig.classBreakInfos.filter(function(info) {
669 | return (
670 | info.classMinValue <= feature.properties[canvasSymbolConfig.field] &&
671 | info.classMaxValue >= feature.properties[canvasSymbolConfig.field]
672 | );
673 | });
674 | if (filteredSymbols.length) {
675 | symbol = filteredSymbols[0].symbol;
676 | } else {
677 | symbol = canvasSymbolConfig.defaultSymbol;
678 | }
679 | }
680 | return symbol;
681 | },
682 |
683 | _applyCanvasLineSymbol: function(ctx, symbolObject, screenOriginPoint, screenDestinationPoint) {
684 | ctx.lineCap = symbolObject.lineCap;
685 | ctx.lineWidth = symbolObject.lineWidth;
686 | ctx.strokeStyle = symbolObject.strokeStyle;
687 | ctx.shadowBlur = symbolObject.shadowBlur;
688 | ctx.shadowColor = symbolObject.shadowColor;
689 | ctx.moveTo(screenOriginPoint.x, screenOriginPoint.y);
690 | ctx.bezierCurveTo(screenOriginPoint.x, screenDestinationPoint.y, screenDestinationPoint.x, screenDestinationPoint.y, screenDestinationPoint.x, screenDestinationPoint.y);
691 | },
692 |
693 | _animateCanvasLineSymbol: function(ctx, symbolObject, screenOriginPoint, screenDestinationPoint) {
694 | ctx.lineCap = symbolObject.lineCap;
695 | ctx.lineWidth = symbolObject.lineWidth;
696 | ctx.strokeStyle = symbolObject.strokeStyle;
697 | ctx.shadowBlur = symbolObject.shadowBlur;
698 | ctx.shadowColor = symbolObject.shadowColor;
699 | ctx.setLineDash([symbolObject.lineDashOffsetSize, (this._animationPropertiesStatic.resetOffset - symbolObject.lineDashOffsetSize)]);
700 | ctx.lineDashOffset = -this._animationPropertiesStatic.offset; // this makes the dot appear to move when the entire top canvas is redrawn
701 | ctx.moveTo(screenOriginPoint.x, screenOriginPoint.y);
702 | ctx.bezierCurveTo(screenOriginPoint.x, screenDestinationPoint.y, screenDestinationPoint.x, screenDestinationPoint.y, screenDestinationPoint.x, screenDestinationPoint.y);
703 | },
704 |
705 | _animator: function(time) {
706 | this._animationCanvasElement.getContext('2d')
707 | .clearRect(0, 0, this._animationCanvasElement.width, this._animationCanvasElement.height);
708 |
709 | this._drawSelectedCanvasPaths(true); // draw it again to give the appearance of a moving dot with a new lineDashOffset
710 |
711 | TWEEN.update(time);
712 |
713 | this._animationFrameId = L.Util.requestAnimFrame(this._animator, this);
714 | },
715 |
716 | _wrapGeoJsonCircleMarkers: function() {
717 | // ensure that the GeoJson point features,
718 | // which are drawn on the map as individual CircleMarker layers,
719 | // will be drawn beyond +/-180 longitude
720 | this.eachLayer(function(layer) {
721 | var wrappedLatLng = this._wrapAroundLatLng(layer.getLatLng());
722 | layer.setLatLng(wrappedLatLng);
723 | }, this);
724 | },
725 |
726 | _wrapAroundLatLng: function(latLng) {
727 | if (this._map && this.options.wrapAroundCanvas) {
728 | var wrappedLatLng = latLng.clone();
729 | var mapCenterLng = this._map.getCenter().lng;
730 | var wrapAroundDiff = mapCenterLng - wrappedLatLng.lng;
731 | if (wrapAroundDiff < -180 || wrapAroundDiff > 180) {
732 | wrappedLatLng.lng += (Math.round(wrapAroundDiff / 360) * 360);
733 | }
734 | return wrappedLatLng;
735 | } else {
736 | return latLng;
737 | }
738 | }
739 | });
740 |
741 | return CanvasFlowmapLayer;
742 |
743 | }, window));
744 |
--------------------------------------------------------------------------------