@dra2020/baseclient 1.0.46 → 1.0.49
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.
- package/dist/baseclient.js +75 -41
- package/dist/baseclient.js.map +1 -1
- package/lib/poly/polylabel.ts +66 -39
- package/lib/poly/topo.ts +7 -4
- package/package.json +1 -1
package/lib/poly/polylabel.ts
CHANGED
|
@@ -21,16 +21,66 @@ export function polyDistance(poly: any, x: number, y: number): number
|
|
|
21
21
|
let pp = P.polyNormalize(poly);
|
|
22
22
|
if (pp == null) return 0;
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
24
|
+
// First find if it is contained in one of the outer polygons, or outside all outer polygons
|
|
25
|
+
let iContaining = -1;
|
|
26
|
+
let maxOutside = - Infinity;
|
|
27
|
+
let minInside = Infinity;
|
|
28
|
+
let noholes = true;
|
|
29
|
+
PP.polyPackEachRing(pp, (b: Float64Array, iPoly: number, iRing: number, iOffset: number, nPoints: number) => {
|
|
30
|
+
// If we have determined we are inside this polygon, keep track of whether it has holes
|
|
31
|
+
if (iContaining == iPoly && iRing > 0)
|
|
32
|
+
noholes = false;
|
|
33
|
+
// Don't process rings
|
|
34
|
+
if (iRing > 0) return;
|
|
35
|
+
// OK, get distance
|
|
36
|
+
let forEachPointPair = (iter: any) => {
|
|
37
|
+
PP.polyPackEachRing(pp, (b: Float64Array, iInteriorPoly: number, iRing: number, iOffset: number, nPoints: number) => {
|
|
38
|
+
if (iRing || iInteriorPoly != iPoly) return;
|
|
39
|
+
let iFirst = iOffset;
|
|
40
|
+
let iLast = iOffset + nPoints * 2;
|
|
41
|
+
let iSecond = iLast - 2;
|
|
42
|
+
for (; iFirst < iLast; iSecond = iFirst, iFirst += 2)
|
|
43
|
+
iter(b[iFirst], b[iFirst+1], b[iSecond], b[iSecond+1]);
|
|
44
|
+
});
|
|
45
|
+
};
|
|
46
|
+
let dist = pointToPolygonDist(x, y, forEachPointPair);
|
|
47
|
+
// If inside, is it closest inside (deal with multipolygons that self-contain - think filled donut)
|
|
48
|
+
if (dist > 0 && dist < minInside)
|
|
49
|
+
{
|
|
50
|
+
iContaining = iPoly;
|
|
51
|
+
minInside = dist;
|
|
52
|
+
noholes = true;
|
|
53
|
+
}
|
|
54
|
+
else if (dist < 0)
|
|
55
|
+
maxOutside = Math.max(maxOutside, dist);
|
|
56
|
+
});
|
|
57
|
+
if (iContaining < 0)
|
|
58
|
+
return maxOutside;
|
|
59
|
+
if (noholes)
|
|
60
|
+
return minInside;
|
|
61
|
+
|
|
62
|
+
// OK, now need to worry about holes in the polygon it is contained in
|
|
63
|
+
PP.polyPackEachRing(pp, (b: Float64Array, iPoly: number, iRing: number, iOffset: number, nPoints: number) => {
|
|
64
|
+
// Only want to look at the holes for the containing polygon
|
|
65
|
+
if (iPoly != iContaining || iRing == 0) return;
|
|
66
|
+
// Compute distance to those holes
|
|
67
|
+
let forEachPointPair = (iter: any) => {
|
|
68
|
+
PP.polyPackEachRing(pp, (b: Float64Array, iInteriorPoly: number, iRing: number, iOffset: number, nPoints: number) => {
|
|
69
|
+
if (iInteriorPoly != iContaining || iRing == 0) return;
|
|
70
|
+
let iFirst = iOffset;
|
|
71
|
+
let iLast = iOffset + nPoints * 2;
|
|
72
|
+
let iSecond = iLast - 2;
|
|
73
|
+
for (; iFirst < iLast; iSecond = iFirst, iFirst += 2)
|
|
74
|
+
iter(b[iFirst], b[iFirst+1], b[iSecond], b[iSecond+1]);
|
|
75
|
+
});
|
|
76
|
+
};
|
|
77
|
+
// Negate distance since dealing with holes
|
|
78
|
+
let dist = - pointToPolygonDist(x, y, forEachPointPair);
|
|
79
|
+
// We take the min to either get a negative value (inside hole) or a smaller positive value
|
|
80
|
+
// (outside hole but close to hole boundary).
|
|
81
|
+
minInside = Math.min(minInside, dist);
|
|
82
|
+
});
|
|
83
|
+
return minInside;
|
|
34
84
|
}
|
|
35
85
|
|
|
36
86
|
//
|
|
@@ -69,7 +119,7 @@ export function polyLabel(poly: any, precision?: number, debug?: boolean): PolyL
|
|
|
69
119
|
let iLast = iOffset + nPoints * 2;
|
|
70
120
|
let iSecond = iLast - 2;
|
|
71
121
|
for (; iFirst < iLast; iSecond = iFirst, iFirst += 2)
|
|
72
|
-
iter(
|
|
122
|
+
iter(b[iFirst], b[iFirst+1], b[iSecond], b[iSecond+1]);
|
|
73
123
|
});
|
|
74
124
|
};
|
|
75
125
|
|
|
@@ -164,38 +214,15 @@ class Cell
|
|
|
164
214
|
// signed distance from point to polygon outline (negative if point is outside)
|
|
165
215
|
function pointToPolygonDist(x: number, y: number, forEachPointPair: any): number
|
|
166
216
|
{
|
|
167
|
-
let iPolyLast = -1;
|
|
168
|
-
let iRingLast = -1;
|
|
169
217
|
let inside = false;
|
|
170
|
-
let
|
|
171
|
-
let useInside = false;
|
|
172
|
-
let isHole = false;
|
|
173
|
-
let minDistSq: number = Infinity;
|
|
218
|
+
let minDistSq = Infinity;
|
|
174
219
|
|
|
175
|
-
forEachPointPair((
|
|
176
|
-
if (iPoly != iPolyLast || iRing != iRingLast)
|
|
177
|
-
{
|
|
178
|
-
if (useInside)
|
|
179
|
-
inside = isHole ? ! thisInside : thisInside;
|
|
180
|
-
iPolyLast = iPoly;
|
|
181
|
-
iRingLast = iRing;
|
|
182
|
-
thisInside = false;
|
|
183
|
-
useInside = false;
|
|
184
|
-
isHole = false;
|
|
185
|
-
}
|
|
220
|
+
forEachPointPair((ax: number, ay: number, bx: number, by: number) => {
|
|
186
221
|
if ((ay > y !== by > y) && (x < (bx - ax) * (y - ay) / (by - ay) + ax))
|
|
187
|
-
|
|
222
|
+
inside = !inside;
|
|
188
223
|
|
|
189
|
-
|
|
190
|
-
if (thisDistSq < minDistSq)
|
|
191
|
-
{
|
|
192
|
-
minDistSq = thisDistSq;
|
|
193
|
-
useInside = true;
|
|
194
|
-
isHole = iRing != 0;
|
|
195
|
-
}
|
|
224
|
+
minDistSq = Math.min(minDistSq, getSegDistSq(x, y, ax, ay, bx, by));
|
|
196
225
|
});
|
|
197
|
-
if (useInside)
|
|
198
|
-
inside = isHole ? ! thisInside : thisInside;
|
|
199
226
|
|
|
200
227
|
return (inside ? 1 : -1) * Math.sqrt(minDistSq);
|
|
201
228
|
}
|
|
@@ -209,7 +236,7 @@ function getCentroidCell(forEachPointPair: any): Cell
|
|
|
209
236
|
let fx: number;
|
|
210
237
|
let fy: number;
|
|
211
238
|
|
|
212
|
-
forEachPointPair((
|
|
239
|
+
forEachPointPair((ax: number, ay: number, bx: number, by: number) => {
|
|
213
240
|
if (fx === undefined) fx = ax, fy = ay;
|
|
214
241
|
let f: number = ax * by - bx * ay;
|
|
215
242
|
x += (ax + bx) * f;
|
package/lib/poly/topo.ts
CHANGED
|
@@ -313,6 +313,7 @@ export function topoSimplifyCollection(col: any, options?: SimplifyOptions): any
|
|
|
313
313
|
if (! bDecided)
|
|
314
314
|
{
|
|
315
315
|
let pp = PP.polyPackTopoArcs(testtopo, arcs);
|
|
316
|
+
P.polyRewindRings(pp);
|
|
316
317
|
if (selfIntersectFast(pp))
|
|
317
318
|
{
|
|
318
319
|
keepArcs(topo, oOld.arcs, keepweight);
|
|
@@ -321,11 +322,13 @@ export function topoSimplifyCollection(col: any, options?: SimplifyOptions): any
|
|
|
321
322
|
else
|
|
322
323
|
{
|
|
323
324
|
let {x,y} = intpt(f);
|
|
324
|
-
|
|
325
|
+
let d = PL.polyDistance(pp, x, y);
|
|
326
|
+
if (d < 0.00001) // d is negative if outside the polygon, so that qualifies here
|
|
325
327
|
{
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
328
|
+
keepTiny.set(f, f);
|
|
329
|
+
keepArcs(topo, oOld.arcs, 0); // keeps all points to avoid reprocessing these tiny shapes
|
|
330
|
+
nBad++, nTiny++;
|
|
331
|
+
log(`topoSimplifyCollection: ${f.properties.id}: increasing feature fidelity because intpt dist is ${d}`);
|
|
329
332
|
}
|
|
330
333
|
}
|
|
331
334
|
}
|