osm2geojson-lite 0.8.13 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- declare module "*.json" {
1
+ declare module '*.json' {
2
2
  const value: any;
3
3
  export default value;
4
4
  }
package/ts/src/utils.ts CHANGED
@@ -1,198 +1,235 @@
1
- import {Way} from "./osmobjs";
2
-
3
- export function purgeProps(obj: object, blacklist: string[]): object {
4
- if (obj) {
5
- let rs = Object.assign({}, obj);
6
- if (blacklist)
7
- for (let prop of blacklist) delete rs[prop];
8
- return rs;
9
- }
10
- return {};
1
+ import {Way} from './osmobjs';
2
+
3
+ export function purgeProps(obj: {[k: string]: any}, blacklist: string[]): {[k: string]: any} {
4
+ if (obj) {
5
+ const rs = Object.assign({}, obj);
6
+ if (blacklist) {
7
+ for (const prop of blacklist) {
8
+ delete rs[prop];
9
+ }
10
+ }
11
+ return rs;
12
+ }
13
+ return {};
11
14
  }
12
15
 
13
- export function mergeProps(obj1: object, obj2: object): object {
14
- obj1 = obj1? obj1 : {};
15
- obj2 = obj2? obj2 : {};
16
- return Object.assign(obj1, obj2);
16
+ export function mergeProps(obj1: {[k: string]: any}, obj2: {[k: string]: any}): {[k: string]: any} {
17
+ obj1 = obj1 ? obj1 : {};
18
+ obj2 = obj2 ? obj2 : {};
19
+ return Object.assign(obj1, obj2);
17
20
  }
18
21
 
19
- export function addPropToFeature(f: any, k: string, v: string) {
20
- if (f.properties && k && v) f.properties[k] = v;
22
+ export function addPropToFeature(f: {[k: string]: any}, k: string, v: any) {
23
+ if (f.properties && k && v) {
24
+ f.properties[k] = v;
25
+ }
21
26
  }
22
27
 
23
- export function addPropToFeatures(fs: any[], k: string, v: string) {
24
- for (let f of fs) addPropToFeature(f, k, v);
28
+ export function addPropToFeatures(fs: Array<{[k: string]: any}>, k: string, v: any) {
29
+ for (const f of fs) {
30
+ addPropToFeature(f, k, v);
31
+ }
25
32
  }
26
33
 
27
- export const first = a => a[0];
28
- export const last = a => a[a.length - 1];
29
- export const coordsToKey = a => a.join(',');
30
-
31
- export function addToMap(m: object, k: string, v: any) {
32
- let a = m[k];
33
- if (a) a.push(v);
34
- else m[k] = [v];
34
+ export const first = <T>(a: T[]): T => a[0];
35
+ export const last = <T>(a: T[]): T => a[a.length - 1];
36
+ export const coordsToKey = <T>(a: T[]): string => a.join(',');
37
+
38
+ export function addToMap<T>(m: {[k: string]: T[]}, k: string, v: T): void {
39
+ const a = m[k];
40
+ if (a) {
41
+ a.push(v);
42
+ } else {
43
+ m[k] = [v];
44
+ }
35
45
  }
36
46
 
37
- export function removeFromMap(m: object, k: string, v: any) {
38
- let a = m[k];
39
- let idx = null;
40
- if (a && (idx = a.indexOf(v)) >= 0)
41
- a.splice(idx, 1);
47
+ export function removeFromMap<T>(m: {[k: string]: T[]}, k: string, v: T): void {
48
+ const a = m[k];
49
+ let idx = -1;
50
+ if (a) {
51
+ idx = a.indexOf(v);
52
+ }
53
+ if (idx >= 0) {
54
+ a.splice(idx, 1);
55
+ }
42
56
  }
43
57
 
44
- export function getFirstFromMap(m: object, k: string): any {
45
- let a = m[k];
46
- if (a && a.length > 0) return a[0];
47
- return null;
58
+ export function getFirstFromMap<T>(m: {[k: string]: T[]}, k: string): T | undefined {
59
+ const a = m[k];
60
+ if (a && a.length > 0) {
61
+ return a[0];
62
+ }
63
+ return undefined;
48
64
  }
49
65
 
50
66
  // need 3+ different points to form a ring, here using > 3 is 'coz a the first and the last points are actually the same
51
- export const isRing = a => a.length > 3 && coordsToKey(first(a)) === coordsToKey(last(a));
52
-
53
- export const ringDirection = (a, xIdx?, yIdx?) => {
54
- xIdx = xIdx || 0, yIdx = yIdx || 1;
55
- // get the index of the point which has the maximum x value
56
- let m = a.reduce((maxxIdx, v, idx) => a[maxxIdx][xIdx] > v[xIdx] ? maxxIdx : idx, 0);
57
- // 'coz the first point is virtually the same one as the last point,
58
- // we need to skip a.length - 1 for left when m = 0,
59
- // and skip 0 for right when m = a.length - 1;
60
- let l = m <= 0? a.length - 2 : m - 1, r = m >= a.length - 1? 1 : m + 1;
61
- let xa = a[l][xIdx], xb = a[m][xIdx], xc = a[r][xIdx];
62
- let ya = a[l][yIdx], yb = a[m][yIdx], yc = a[r][yIdx];
63
- let det = (xb - xa) * (yc - ya) - (xc - xa) * (yb - ya);
64
- return det < 0 ? 'clockwise' : 'counterclockwise';
65
- }
66
-
67
- export const ptInsidePolygon = (pt, polygon, xIdx?, yIdx?) => {
68
- xIdx = xIdx || 0, yIdx = yIdx || 1;
69
- let result = false;
70
- for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
71
- if ((polygon[i][xIdx] <= pt[xIdx] && pt[xIdx] < polygon[j][xIdx] ||
72
- polygon[j][xIdx] <= pt[xIdx] && pt[xIdx] < polygon[i][xIdx]) &&
73
- pt[yIdx] < (polygon[j][yIdx] - polygon[i][yIdx]) * (pt[xIdx] - polygon[i][xIdx]) / (polygon[j][xIdx] - polygon[i][xIdx]) + polygon[i][yIdx])
74
- result = !result;
75
- }
76
- return result;
77
- }
78
-
79
- export const strToFloat = el => el instanceof Array? el.map(strToFloat) : parseFloat(el);
67
+ export const isRing = (a: number[][]): boolean => a.length > 3 && coordsToKey(first(a)) === coordsToKey(last(a));
68
+
69
+ export const ringDirection = (a: number[][], xIdx?: number, yIdx?: number): string => {
70
+ xIdx = xIdx || 0, yIdx = yIdx || 1;
71
+ // get the index of the point which has the maximum x value
72
+ const m = a.reduce((maxxIdx: number, v: number[], idx: number): number => a[maxxIdx][xIdx || 0] > v[xIdx || 0] ? maxxIdx : idx, 0);
73
+ // 'coz the first point is virtually the same one as the last point,
74
+ // we need to skip a.length - 1 for left when m = 0,
75
+ // and skip 0 for right when m = a.length - 1;
76
+ const l = m <= 0 ? a.length - 2 : m - 1;
77
+ const r = m >= a.length - 1 ? 1 : m + 1;
78
+ const xa = a[l][xIdx];
79
+ const xb = a[m][xIdx];
80
+ const xc = a[r][xIdx];
81
+ const ya = a[l][yIdx];
82
+ const yb = a[m][yIdx];
83
+ const yc = a[r][yIdx];
84
+ const det = (xb - xa) * (yc - ya) - (xc - xa) * (yb - ya);
85
+ return det < 0 ? 'clockwise' : 'counterclockwise';
86
+ };
87
+
88
+ export const ptInsidePolygon = (pt: number[], polygon: number[][], xIdx?: number, yIdx?: number): boolean => {
89
+ xIdx = xIdx || 0, yIdx = yIdx || 1;
90
+ let result = false;
91
+ for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
92
+ if ((polygon[i][xIdx] <= pt[xIdx] && pt[xIdx] < polygon[j][xIdx] ||
93
+ polygon[j][xIdx] <= pt[xIdx] && pt[xIdx] < polygon[i][xIdx]) &&
94
+ pt[yIdx] < (polygon[j][yIdx] - polygon[i][yIdx]) * (pt[xIdx] - polygon[i][xIdx]) / (polygon[j][xIdx] - polygon[i][xIdx]) + polygon[i][yIdx]) {
95
+ result = !result;
96
+ }
97
+ }
98
+ return result;
99
+ };
100
+
101
+ export const strToFloat = (el: any[] | string): any => el instanceof Array ? el.map(strToFloat) : parseFloat(el);
80
102
 
81
103
  export class LateBinder {
82
- container: Object;
83
- valueFunc: Function;
84
- ctx: Object;
85
- args: Object[];
86
-
87
- constructor(container: Object, valueFunc: Function, ctx: Object, args: Object[]) {
88
- this.container = container;
89
- this.valueFunc = valueFunc;
90
- this.ctx = ctx;
91
- this.args = args;
92
- }
93
-
94
- bind() {
95
- let v = this.valueFunc.apply(this.ctx, this.args);
96
- if (this.container instanceof Array) {
97
- let idx = this.container.indexOf(this);
98
- if (idx >= 0) {
99
- let args = [idx, 1];
100
- if (v) args.push(v);
101
- [].splice.apply(this.container, args);
102
- }
103
- } else if (typeof this.container === 'object') {
104
- let k = Object.keys(this.container).find(v => this.container[v] === this);
105
- if (k)
106
- if (v) this.container[k] = v;
107
- else delete this.container[k];
108
- }
109
- }
104
+ private container: any[] | {[k: string]: any};
105
+ private valueFunc: (...args) => any;
106
+ private ctx: any;
107
+ private args: any[];
108
+
109
+ constructor(container: any[] | {[k: string]: any}, valueFunc: (...args) => any, ctx: any, args: any[]) {
110
+ this.container = container;
111
+ this.valueFunc = valueFunc;
112
+ this.ctx = ctx;
113
+ this.args = args;
114
+ }
115
+
116
+ public bind() {
117
+ const v = this.valueFunc.apply(this.ctx, this.args);
118
+ if (this.container instanceof Array) {
119
+ const idx = this.container.indexOf(this);
120
+ if (idx >= 0) {
121
+ const args = [idx, 1];
122
+ if (v) {
123
+ args.push(v);
124
+ }
125
+ [].splice.apply(this.container, args);
126
+ }
127
+ } else if (typeof this.container === 'object') {
128
+ const k = Object.keys(this.container).find((nv) => this.container[nv] === this);
129
+ if (k) {
130
+ if (v) {
131
+ this.container[k] = v;
132
+ } else {
133
+ delete this.container[k];
134
+ }
135
+ }
136
+ }
137
+ }
110
138
  }
111
139
 
112
140
  export class RefElements extends Map {
113
- binders: LateBinder[];
141
+ private binders: LateBinder[];
114
142
 
115
- constructor() {
116
- super();
117
- this.binders = [];
118
- }
143
+ constructor() {
144
+ super();
145
+ this.binders = [];
146
+ }
119
147
 
120
- add(k: String, v: Object) {
121
- this.set(k, v);
122
- }
148
+ public add(k: string, v: any) {
149
+ this.set(k, v);
150
+ }
123
151
 
124
- addBinder(binder: LateBinder) {
125
- this.binders.push(binder);
126
- }
152
+ public addBinder(binder: LateBinder) {
153
+ this.binders.push(binder);
154
+ }
127
155
 
128
- bindAll() {
129
- this.binders.forEach(binder => binder.bind());
130
- }
156
+ public bindAll() {
157
+ this.binders.forEach((binder) => binder.bind());
158
+ }
131
159
  }
132
160
 
133
161
  export class WayCollection extends Array {
134
- firstMap: Object;
135
- lastMap: Object;
136
-
137
- constructor() {
138
- super();
139
- this.firstMap = {};
140
- this.lastMap = {};
141
- }
142
-
143
- addWay(way: Way) {
144
- let w = way.toCoordsArray();
145
- if (w.length > 0) {
146
- this.push(way);
147
- addToMap(this.firstMap, coordsToKey(first(w)), w);
148
- addToMap(this.lastMap, coordsToKey(last(w)), w);
149
- }
150
- }
151
-
152
- toStrings(): any[] {
153
- let strings: any[] = [], way = null;
154
- while (way = this.shift()) {
155
- removeFromMap(this.firstMap, coordsToKey(first(way)), way);
156
- removeFromMap(this.lastMap, coordsToKey(last(way)), way);
157
- let current: any[] = way, next: any[];
158
- do {
159
- let key = coordsToKey(last(current)), shouldReverse = false;
160
-
161
- next = getFirstFromMap(this.firstMap, key);
162
- if (!next) {
163
- next = getFirstFromMap(this.lastMap, key);
164
- shouldReverse = true;
165
- }
166
-
167
- if (next) {
168
- this.splice(this.indexOf(next), 1);
169
- removeFromMap(this.firstMap, coordsToKey(first(next)), next);
170
- removeFromMap(this.lastMap, coordsToKey(last(next)), next);
171
- if (shouldReverse) {
172
- // always reverse shorter one to save time
173
- if (next.length > current.length)
174
- [current, next] = [next, current];
175
- next.reverse();
176
- }
177
-
178
- current = current.concat(next.slice(1));
179
- }
180
- } while (next);
181
- strings.push(strToFloat(current));
182
- }
183
-
184
- return strings;
185
- }
186
-
187
- toRings(direction: String): any[] {
188
- let strings = this.toStrings();
189
- let rings: any[] = [], string: any[];
190
- while (string = strings.shift()) {
191
- if (isRing(string)) {
192
- if (ringDirection(string) !== direction) string.reverse();
193
- rings.push(string);
194
- }
195
- }
196
- return rings;
197
- }
162
+ private firstMap: {[k: string]: any};
163
+ private lastMap: {[k: string]: any};
164
+
165
+ constructor() {
166
+ super();
167
+ this.firstMap = {};
168
+ this.lastMap = {};
169
+ }
170
+
171
+ public addWay(way: Way) {
172
+ const w = way.toCoordsArray();
173
+ if (w.length > 0) {
174
+ this.push(way);
175
+ addToMap(this.firstMap, coordsToKey(first(w)), w);
176
+ addToMap(this.lastMap, coordsToKey(last(w)), w);
177
+ }
178
+ }
179
+
180
+ public toStrings(): number[][][] {
181
+ const strings: any[] = [];
182
+ let way = this.shift();
183
+ while (way) {
184
+ removeFromMap(this.firstMap, coordsToKey(first(way)), way);
185
+ removeFromMap(this.lastMap, coordsToKey(last(way)), way);
186
+ let current: any[] = way;
187
+ let next: any[] | undefined;
188
+ do {
189
+ const key = coordsToKey(last(current));
190
+ let shouldReverse = false;
191
+
192
+ next = getFirstFromMap(this.firstMap, key);
193
+ if (!next) {
194
+ next = getFirstFromMap(this.lastMap, key);
195
+ shouldReverse = true;
196
+ }
197
+
198
+ if (next) {
199
+ this.splice(this.indexOf(next), 1);
200
+ removeFromMap(this.firstMap, coordsToKey(first(next)), next);
201
+ removeFromMap(this.lastMap, coordsToKey(last(next)), next);
202
+ if (shouldReverse) {
203
+ // always reverse shorter one to save time
204
+ if (next.length > current.length) {
205
+ [current, next] = [next, current];
206
+ }
207
+ next.reverse();
208
+ }
209
+
210
+ current = current.concat(next.slice(1));
211
+ }
212
+ } while (next);
213
+ strings.push(strToFloat(current));
214
+ way = this.shift();
215
+ }
216
+
217
+ return strings;
218
+ }
219
+
220
+ public toRings(direction: string): number[][][] {
221
+ const strings = this.toStrings();
222
+ const rings: number[][][] = [];
223
+ let str = strings.shift();
224
+ while (str) {
225
+ if (isRing(str)) {
226
+ if (ringDirection(str) !== direction) {
227
+ str.reverse();
228
+ }
229
+ rings.push(str);
230
+ }
231
+ str = strings.shift();
232
+ }
233
+ return rings;
234
+ }
198
235
  }