UNPKG

2.97 kBJavaScriptView Raw
1import * as LineUtil from './LineUtil';
2import {toLatLng} from '../geo/LatLng';
3import {toPoint} from './Point';
4/*
5 * @namespace PolyUtil
6 * Various utility functions for polygon geometries.
7 */
8
9/* @function clipPolygon(points: Point[], bounds: Bounds, round?: Boolean): Point[]
10 * Clips the polygon geometry defined by the given `points` by the given bounds (using the [Sutherland-Hodgman algorithm](https://en.wikipedia.org/wiki/Sutherland%E2%80%93Hodgman_algorithm)).
11 * Used by Leaflet to only show polygon points that are on the screen or near, increasing
12 * performance. Note that polygon points needs different algorithm for clipping
13 * than polyline, so there's a separate method for it.
14 */
15export function clipPolygon(points, bounds, round) {
16 var clippedPoints,
17 edges = [1, 4, 2, 8],
18 i, j, k,
19 a, b,
20 len, edge, p;
21
22 for (i = 0, len = points.length; i < len; i++) {
23 points[i]._code = LineUtil._getBitCode(points[i], bounds);
24 }
25
26 // for each edge (left, bottom, right, top)
27 for (k = 0; k < 4; k++) {
28 edge = edges[k];
29 clippedPoints = [];
30
31 for (i = 0, len = points.length, j = len - 1; i < len; j = i++) {
32 a = points[i];
33 b = points[j];
34
35 // if a is inside the clip window
36 if (!(a._code & edge)) {
37 // if b is outside the clip window (a->b goes out of screen)
38 if (b._code & edge) {
39 p = LineUtil._getEdgeIntersection(b, a, edge, bounds, round);
40 p._code = LineUtil._getBitCode(p, bounds);
41 clippedPoints.push(p);
42 }
43 clippedPoints.push(a);
44
45 // else if b is inside the clip window (a->b enters the screen)
46 } else if (!(b._code & edge)) {
47 p = LineUtil._getEdgeIntersection(b, a, edge, bounds, round);
48 p._code = LineUtil._getBitCode(p, bounds);
49 clippedPoints.push(p);
50 }
51 }
52 points = clippedPoints;
53 }
54
55 return points;
56}
57
58/* @function polygonCenter(latlngs: LatLng[] crs: CRS): LatLng
59 * Returns the center ([centroid](http://en.wikipedia.org/wiki/Centroid)) of the passed LatLngs (first ring) from a polygon.
60 */
61export function polygonCenter(latlngs, crs) {
62 var i, j, p1, p2, f, area, x, y, center;
63
64 if (!latlngs || latlngs.length === 0) {
65 throw new Error('latlngs not passed');
66 }
67
68 if (!LineUtil.isFlat(latlngs)) {
69 console.warn('latlngs are not flat! Only the first ring will be used');
70 latlngs = latlngs[0];
71 }
72
73 var points = [];
74 for (var k in latlngs) {
75 points.push(crs.project(toLatLng(latlngs[k])));
76 }
77
78 var len = points.length;
79 area = x = y = 0;
80
81 // polygon centroid algorithm;
82 for (i = 0, j = len - 1; i < len; j = i++) {
83 p1 = points[i];
84 p2 = points[j];
85
86 f = p1.y * p2.x - p2.y * p1.x;
87 x += (p1.x + p2.x) * f;
88 y += (p1.y + p2.y) * f;
89 area += f * 3;
90 }
91
92 if (area === 0) {
93 // Polygon is so small that all points are on same pixel.
94 center = points[0];
95 } else {
96 center = [x / area, y / area];
97 }
98 return crs.unproject(toPoint(center));
99}