Skip to content

Commit 45dd02f

Browse files
authored
Merge pull request #29 from tschaub/improvements
Updated intersection handling
2 parents f0e097f + 6ef2dd8 commit 45dd02f

24 files changed

+328
-163
lines changed

lib/linestring.js

Lines changed: 48 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,37 +7,62 @@ exports.getBits = function(coordinates, options) {
77
const resolution = options.resolution || 1;
88
const origin = options.origin || [0, 0];
99
const quantized = prepare(coordinates, resolution, origin);
10-
const values = quantized.values;
10+
const segments = quantized.segments;
1111

1212
const ranges = {};
13-
for (let index = 0, length = values.length; index < length; index += 5) {
14-
const lowI = values[index];
15-
const lowJ = values[index + 1];
16-
const highI = values[index + 2];
17-
const highJ = values[index + 3];
13+
for (let index = 0, length = segments.length; index < length; ++index) {
14+
const segment = segments[index];
15+
const lowI = segment.lowI;
16+
const lowJ = segment.lowJ;
17+
const highI = segment.highI;
18+
const highJ = segment.highJ;
19+
20+
// horizontal segment
21+
if (lowJ === highJ) {
22+
if (!(lowJ in ranges)) {
23+
ranges[lowJ] = [];
24+
}
25+
ranges[lowJ].push(lowI, highI);
26+
continue;
27+
}
1828

19-
let lastIntersection = NaN;
2029
for (let j = lowJ; j <= highJ; ++j) {
21-
const intersection = Math.round(
22-
lowI + ((j - lowJ) * (highI - lowI)) / (highJ - lowJ)
23-
);
2430
if (!(j in ranges)) {
2531
ranges[j] = [];
2632
}
27-
if (isNaN(lastIntersection)) {
28-
ranges[j].push(intersection, intersection);
29-
} else {
30-
let delta;
31-
if (intersection > lastIntersection) {
32-
delta = 1;
33-
} else if (intersection < lastIntersection) {
34-
delta = -1;
35-
} else {
36-
delta = 0;
37-
}
38-
ranges[j].push(lastIntersection + delta, intersection);
33+
34+
const deltaX = segment.highX - segment.lowX;
35+
const lowCrossingY = j;
36+
const highCrossingY = j + 1;
37+
38+
// exits above row
39+
if (j === lowJ) {
40+
const along =
41+
(highCrossingY - segment.lowY) / (segment.highY - segment.lowY);
42+
const crossingI = Math.floor(segment.lowX + along * deltaX);
43+
ranges[j].push(lowI, crossingI);
44+
continue;
45+
}
46+
47+
// exits below row
48+
if (j === highJ) {
49+
const along =
50+
(lowCrossingY - segment.lowY) / (segment.highY - segment.lowY);
51+
const crossingI = Math.floor(segment.lowX + along * deltaX);
52+
ranges[j].push(crossingI, highI);
53+
continue;
3954
}
40-
lastIntersection = intersection;
55+
56+
// crosses row
57+
const lowAlong =
58+
(lowCrossingY - segment.lowY) / (segment.highY - segment.lowY);
59+
const lowCrossingI = Math.floor(segment.lowX + lowAlong * deltaX);
60+
61+
const highAlong =
62+
(highCrossingY - segment.lowY) / (segment.highY - segment.lowY);
63+
const highCrossingI = Math.floor(segment.lowX + highAlong * deltaX);
64+
65+
ranges[j].push(lowCrossingI, highCrossingI);
4166
}
4267
}
4368

lib/polygon.js

Lines changed: 75 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -12,45 +12,97 @@ exports.getBits = function(coordinates, options) {
1212
const resolution = options.resolution || 1;
1313
const origin = options.origin || [0, 0];
1414
const quantized = prepare(coordinates, resolution, origin);
15-
const values = quantized.values;
15+
const segments = quantized.segments;
1616
const ranges = {};
1717
const minJ = quantized.minJ;
1818
const maxJ = quantized.maxJ;
1919
for (let j = minJ; j <= maxJ; ++j) {
2020
const intersections = [];
21-
for (let index = 0, length = values.length; index < length; index += 5) {
22-
const lowI = values[index];
23-
const lowJ = values[index + 1];
24-
const highI = values[index + 2];
25-
const highJ = values[index + 3];
26-
const instruction = values[index + 4];
27-
if (j === lowJ && lowJ === highJ) {
21+
for (let index = 0, length = segments.length; index < length; ++index) {
22+
const segment = segments[index];
23+
const lowI = segment.lowI;
24+
const lowJ = segment.lowJ;
25+
const highI = segment.highI;
26+
const highJ = segment.highJ;
27+
if (j < lowJ) {
28+
break;
29+
}
30+
if (j > highJ) {
31+
continue;
32+
}
33+
34+
const instruction = segment.instruction;
35+
36+
// horizontal segment
37+
if (lowJ === highJ) {
2838
if (lowI === highI) {
2939
intersections.push(lowI, highI);
30-
} else {
31-
if (includes(instruction, instructions.USE_LOW_POINT)) {
32-
intersections.push(lowI);
33-
}
34-
if (includes(instruction, instructions.USE_HIGH_POINT)) {
35-
intersections.push(highI);
36-
}
40+
continue;
3741
}
38-
} else if (j === lowJ) {
3942
if (includes(instruction, instructions.USE_LOW_POINT)) {
4043
intersections.push(lowI);
4144
}
42-
} else if (j === highJ) {
4345
if (includes(instruction, instructions.USE_HIGH_POINT)) {
4446
intersections.push(highI);
4547
}
46-
} else if (j > lowJ && j < highJ) {
47-
intersections.push(
48-
Math.round(lowI + ((j - lowJ) * (highI - lowI)) / (highJ - lowJ))
49-
);
50-
} else if (j < lowJ) {
51-
break;
48+
continue;
49+
}
50+
51+
const deltaX = segment.highX - segment.lowX;
52+
const lowCrossingY = j;
53+
const highCrossingY = j + 1;
54+
const fillLeft = segment.fillLeft;
55+
56+
// exits above row
57+
if (j === lowJ) {
58+
if (includes(instruction, instructions.USE_LOW_POINT)) {
59+
const along =
60+
(highCrossingY - segment.lowY) / (segment.highY - segment.lowY);
61+
const crossingI = Math.floor(segment.lowX + along * deltaX);
62+
const crossesRight = crossingI > lowI;
63+
64+
if ((fillLeft && crossesRight) || (!fillLeft && !crossesRight)) {
65+
intersections.push(crossingI);
66+
} else {
67+
intersections.push(lowI);
68+
}
69+
}
70+
continue;
71+
}
72+
73+
// exits below row
74+
if (j === highJ) {
75+
if (includes(instruction, instructions.USE_HIGH_POINT)) {
76+
const along =
77+
(lowCrossingY - segment.lowY) / (segment.highY - segment.lowY);
78+
const crossingI = Math.floor(segment.lowX + along * deltaX);
79+
const crossesRight = crossingI > highI;
80+
if ((fillLeft && crossesRight) || (!fillLeft && !crossesRight)) {
81+
intersections.push(crossingI);
82+
} else {
83+
intersections.push(highI);
84+
}
85+
}
86+
continue;
87+
}
88+
89+
// crosses row
90+
const lowAlong =
91+
(lowCrossingY - segment.lowY) / (segment.highY - segment.lowY);
92+
const lowCrossingI = Math.floor(segment.lowX + lowAlong * deltaX);
93+
94+
const highAlong =
95+
(highCrossingY - segment.lowY) / (segment.highY - segment.lowY);
96+
const highCrossingI = Math.floor(segment.lowX + highAlong * deltaX);
97+
98+
const crossesRight = highCrossingI > lowCrossingI;
99+
if ((fillLeft && crossesRight) || (!fillLeft && !crossesRight)) {
100+
intersections.push(highCrossingI);
101+
} else {
102+
intersections.push(lowCrossingI);
52103
}
53104
}
105+
54106
if (intersections.length) {
55107
ranges[j] = sortAndMerge(intersections);
56108
}

0 commit comments

Comments
 (0)