Skip to content

Commit 7b9ef15

Browse files
author
Lucas Wojciechowski
committed
Refactoring
1 parent c2d5d04 commit 7b9ef15

File tree

2 files changed

+74
-60
lines changed

2 files changed

+74
-60
lines changed

js/util/classify_rings.js

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,8 @@
22

33
var quickselect = require('quickselect');
44

5-
module.exports = classifyRings;
6-
75
// classifies an array of rings into polygons with outer rings and holes
8-
9-
function classifyRings(rings, maxRings) {
6+
module.exports = function classifyRings(rings, maxRings) {
107
var len = rings.length;
118

129
if (len <= 1) return [rings];
@@ -16,7 +13,7 @@ function classifyRings(rings, maxRings) {
1613
ccw;
1714

1815
for (var i = 0; i < len; i++) {
19-
var area = signedArea(rings[i]);
16+
var area = calculateSignedArea(rings[i]);
2017
if (area === 0) continue;
2118

2219
rings[i].area = Math.abs(area);
@@ -33,23 +30,24 @@ function classifyRings(rings, maxRings) {
3330
}
3431
if (polygon) polygons.push(polygon);
3532

33+
// Earcut performance degrages with the # of rings in a polygon. For this
34+
// reason, we limit strip out all but the `maxRings` largest rings.
3635
if (maxRings > 1) {
37-
len = polygons.length;
38-
for (var j = 0; j < len; j++) {
36+
for (var j = 0; j < polygons.length; j++) {
3937
if (polygons[j].length <= maxRings) continue;
40-
quickselect(polygons[j], maxRings - 1, 1, polygon.length - 1, sortByArea);
38+
quickselect(polygons[j], maxRings - 1, 1, polygon.length - 1, compareAreas);
4139
polygons[j] = polygon.slice(0, maxRings);
4240
}
4341
}
4442

4543
return polygons;
46-
}
44+
};
4745

48-
function sortByArea(a, b) {
46+
function compareAreas(a, b) {
4947
return b.area - a.area;
5048
}
5149

52-
function signedArea(ring) {
50+
function calculateSignedArea(ring) {
5351
var sum = 0;
5452
for (var i = 0, len = ring.length, j = len - 1, p1, p2; i < len; j = i++) {
5553
p1 = ring[i];

test/js/util/classify_rings.test.js

Lines changed: 65 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -77,59 +77,75 @@ test('classifyRings', function(assert) {
7777
assert.end();
7878
});
7979

80-
test('classifyRings + maxRings', function(assert) {
81-
var geometry;
82-
var classified;
80+
test('classifyRings + maxRings', function(t) {
8381

84-
geometry = [
85-
[
86-
{x:0, y:0},
87-
{x:0, y:40},
88-
{x:40, y:40},
89-
{x:40, y:0},
90-
{x:0, y:0}
91-
],
92-
[
93-
{x:30, y:30},
94-
{x:32, y:30},
95-
{x:32, y:32},
96-
{x:30, y:30}
97-
],
98-
[
99-
{x:10, y:10},
100-
{x:20, y:10},
101-
{x:20, y:20},
102-
{x:10, y:10}
103-
]
104-
];
105-
classified = classifyRings(geometry);
106-
assert.equal(classified.length, 1, '1 polygon');
107-
assert.equal(classified[0].length, 3, 'polygon 1 has 1 exterior, 2 interior');
108-
assert.equal(classified[0][0].area, 3200, 'polygon 1 exterior ring has area=3200');
109-
assert.equal(classified[0][1].area, 4, 'polygon 1 interior ring1 has area=4');
110-
assert.equal(classified[0][2].area, 100, 'polygon 1 interior ring2 has area=100');
82+
function createGeometry(options) {
83+
var geometry = [
84+
// Outer ring, area = 3200
85+
[ {x:0, y:0}, {x:0, y:40}, {x:40, y:40}, {x:40, y:0}, {x:0, y:0} ],
86+
// Inner ring, area = 100
87+
[ {x:30, y:30}, {x:32, y:30}, {x:32, y:32}, {x:30, y:30} ],
88+
// Inner ring, area = 4
89+
[ {x:10, y:10}, {x:20, y:10}, {x:20, y:20}, {x:10, y:10} ]
90+
];
91+
if (options && options.reverse) {
92+
geometry[0].reverse();
93+
geometry[1].reverse();
94+
geometry[2].reverse();
95+
}
96+
return geometry;
97+
}
11198

112-
classified = classifyRings(geometry, 2);
113-
assert.equal(classified.length, 1, '1 polygon');
114-
assert.equal(classified[0].length, 2, 'polygon 1 has 1 exterior, 1 interior');
115-
assert.equal(classified[0][0].area, 3200, 'polygon 1 exterior ring has area=3200');
116-
assert.equal(classified[0][1].area, 100, 'polygon 1 interior ring has area=100');
11799

118-
geometry[0].reverse();
119-
geometry[1].reverse();
120-
geometry[2].reverse();
121-
classified = classifyRings(geometry, 2);
122-
assert.equal(classified.length, 1, '1 polygon');
123-
assert.equal(classified[0].length, 2, 'polygon 1 has 1 exterior, 1 interior');
124-
assert.equal(classified[0][0].area, 3200, 'polygon 1 exterior ring has area=3200');
125-
assert.equal(classified[0][1].area, 100, 'polygon 1 interior ring has area=100');
100+
t.test('maxRings=undefined', function(t) {
101+
var geometry = sortRings(classifyRings(createGeometry()));
102+
t.equal(geometry.length, 1);
103+
t.equal(geometry[0].length, 3);
104+
t.equal(geometry[0][0].area, 3200);
105+
t.equal(geometry[0][1].area, 100);
106+
t.equal(geometry[0][2].area, 4);
107+
t.end();
108+
});
126109

127-
geometry = feature.loadGeometry();
128-
classified = classifyRings(geometry, 5);
129-
assert.equal(classified.length, 2, '2 polygons');
130-
assert.equal(classified[0].length, 1, 'polygon 1 has 1 exterior');
131-
assert.equal(classified[1].length, 5, 'polygon 2 has 1 exterior, 4 interior');
110+
t.test('maxRings=2', function(t) {
111+
var geometry = sortRings(classifyRings(createGeometry(), 2));
112+
t.equal(geometry.length, 1);
113+
t.equal(geometry[0].length, 2);
114+
t.equal(geometry[0][0].area, 3200);
115+
t.equal(geometry[0][1].area, 100);
116+
t.end();
117+
});
132118

133-
assert.end();
119+
t.test('maxRings=2, reversed geometry', function(t) {
120+
var geometry = sortRings(classifyRings(createGeometry({reverse: true}), 2));
121+
t.equal(geometry.length, 1);
122+
t.equal(geometry[0].length, 2);
123+
t.equal(geometry[0][0].area, 3200);
124+
t.equal(geometry[0][1].area, 100);
125+
t.end();
126+
});
127+
128+
t.test('maxRings=5, geometry from fixture', function(t) {
129+
var geometry = sortRings(classifyRings(feature.loadGeometry(), 5));
130+
t.equal(geometry.length, 2);
131+
t.equal(geometry[0].length, 1);
132+
t.equal(geometry[1].length, 5);
133+
134+
var areas = geometry[1].map(function(ring) { return ring.area; });
135+
t.deepEqual(areas, [2763951, 21600, 8298, 4758, 3411]);
136+
t.end();
137+
});
138+
139+
t.end();
134140
});
135141

142+
function sortRings(geometry) {
143+
for (var i = 0; i < geometry.length; i++) {
144+
geometry[i] = geometry[i].sort(compareArea);
145+
}
146+
return geometry;
147+
}
148+
149+
function compareAreas(a, b) {
150+
return b.area - a.area;
151+
}

0 commit comments

Comments
 (0)