Skip to content

Commit c1a02e0

Browse files
committed
First stab at d3.geo.clipView.
This is a simple stream transformation for the moment. Note that the clip region points should be specified in counterclockwise order as required by d3.geom.polygon, and unlike GeoJSON, the first and last points should not be coincident.
1 parent ed987d0 commit c1a02e0

4 files changed

Lines changed: 179 additions & 4 deletions

File tree

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ d3.geo.js: \
194194
src/geo/clip.js \
195195
src/geo/clip-antimeridian.js \
196196
src/geo/clip-circle.js \
197+
src/geo/clip-view.js \
197198
src/geo/compose.js \
198199
src/geo/equirectangular.js \
199200
src/geo/gnomonic.js \

d3.js

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6052,6 +6052,84 @@ d3 = function() {
60526052
return d3_geo_spherical(q);
60536053
}
60546054
}
6055+
d3.geo.clipView = function d3_geo_clipView(coordinates) {
6056+
var clipPolygon = d3.geom.polygon(coordinates).clip;
6057+
return function(listener) {
6058+
var clip = {
6059+
point: point,
6060+
lineStart: lineStart,
6061+
lineEnd: lineEnd,
6062+
polygonStart: function() {
6063+
clip.lineStart = ringStart;
6064+
clip.lineEnd = ringEnd;
6065+
clip.point = ringPoint;
6066+
},
6067+
polygonEnd: function() {
6068+
clip.point = point;
6069+
clip.lineEnd = lineEnd;
6070+
clip.lineStart = lineStart;
6071+
}
6072+
};
6073+
function visible(x, y) {
6074+
var p = [ x, y ], i = -1, n = coordinates.length, a = coordinates[n - 1];
6075+
while (++i < n) {
6076+
b = coordinates[i];
6077+
if (!d3_geom_polygonInside(p, a, b)) return false;
6078+
a = b;
6079+
}
6080+
return true;
6081+
}
6082+
function point(x, y) {
6083+
if (visible(x, y)) {
6084+
listener.point(x, y);
6085+
}
6086+
}
6087+
var x0, y0, v0, first;
6088+
function lineStart() {
6089+
clip.point = linePoint;
6090+
first = true;
6091+
v0 = false;
6092+
}
6093+
function lineEnd() {
6094+
clip.point = point;
6095+
if (v0) listener.lineEnd();
6096+
}
6097+
function linePoint(x, y) {
6098+
var v = visible(x, y);
6099+
if (v) {
6100+
if (first) listener.lineStart(); else if (v !== v0) {
6101+
listener.lineStart();
6102+
}
6103+
listener.point(x, y);
6104+
} else if (v0) {
6105+
listener.lineEnd();
6106+
}
6107+
first = false;
6108+
x0 = x, y0 = y, v0 = v;
6109+
}
6110+
var ring;
6111+
function ringStart() {
6112+
ring = [];
6113+
}
6114+
function ringEnd() {
6115+
ring.pop();
6116+
ring = clipPolygon(ring);
6117+
var n = ring.length;
6118+
if (n) {
6119+
listener.lineStart();
6120+
for (var i = 0, n = ring.length, p; i < n; ++i) {
6121+
listener.point((p = ring[i])[0], p[1]);
6122+
}
6123+
listener.point(ring[0][0], ring[0][1]);
6124+
listener.lineEnd();
6125+
}
6126+
}
6127+
function ringPoint(x, y) {
6128+
ring.push([ x, y ]);
6129+
}
6130+
return clip;
6131+
};
6132+
};
60556133
function d3_geo_compose(a, b) {
60566134
function compose(x, y) {
60576135
return x = a(x, y), b(x[0], x[1]);

d3.min.js

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/geo/clip-view.js

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
d3.geo.clipView = function d3_geo_clipView(coordinates) {
2+
var clipPolygon = d3.geom.polygon(coordinates).clip;
3+
4+
return function(listener) {
5+
var clip = {
6+
point: point,
7+
lineStart: lineStart,
8+
lineEnd: lineEnd,
9+
polygonStart: function() {
10+
clip.lineStart = ringStart;
11+
clip.lineEnd = ringEnd;
12+
clip.point = ringPoint;
13+
},
14+
polygonEnd: function() {
15+
clip.point = point;
16+
clip.lineEnd = lineEnd;
17+
clip.lineStart = lineStart;
18+
}
19+
};
20+
21+
function visible(x, y) {
22+
var p = [x, y],
23+
i = -1,
24+
n = coordinates.length,
25+
a = coordinates[n - 1];
26+
while (++i < n) {
27+
b = coordinates[i];
28+
if (!d3_geom_polygonInside(p, a, b)) return false;
29+
a = b;
30+
}
31+
return true;
32+
}
33+
34+
function point(x, y) {
35+
if (visible(x, y)) {
36+
listener.point(x, y);
37+
}
38+
}
39+
40+
var x0, y0, v0, first;
41+
42+
function lineStart() {
43+
clip.point = linePoint;
44+
first = true;
45+
v0 = false;
46+
}
47+
48+
function lineEnd() {
49+
clip.point = point;
50+
if (v0) listener.lineEnd();
51+
}
52+
53+
function linePoint(x, y) {
54+
var v = visible(x, y);
55+
if (v) {
56+
if (first) listener.lineStart();
57+
else if (v !== v0) {
58+
listener.lineStart();
59+
// TODO intersect
60+
}
61+
listener.point(x, y);
62+
} else if (v0) {
63+
// TODO intersect
64+
listener.lineEnd();
65+
}
66+
first = false;
67+
x0 = x, y0 = y, v0 = v;
68+
}
69+
70+
var ring;
71+
72+
function ringStart() {
73+
ring = [];
74+
}
75+
76+
function ringEnd() {
77+
ring.pop();
78+
ring = clipPolygon(ring);
79+
var n = ring.length;
80+
if (n) {
81+
listener.lineStart();
82+
for (var i = 0, n = ring.length, p; i < n; ++i) {
83+
listener.point((p = ring[i])[0], p[1]);
84+
}
85+
listener.point(ring[0][0], ring[0][1]);
86+
listener.lineEnd();
87+
}
88+
}
89+
90+
function ringPoint(x, y) {
91+
ring.push([x, y]);
92+
}
93+
94+
return clip;
95+
};
96+
}

0 commit comments

Comments
 (0)