source: node_modules/d3-geo/src/clip/index.js@ e4c61dd

Last change on this file since e4c61dd was e4c61dd, checked in by istevanoska <ilinastevanoska@…>, 6 months ago

Prototype 1.1

  • Property mode set to 100644
File size: 3.5 KB
Line 
1import clipBuffer from "./buffer.js";
2import clipRejoin from "./rejoin.js";
3import {epsilon, halfPi} from "../math.js";
4import polygonContains from "../polygonContains.js";
5import {merge} from "d3-array";
6
7export default function(pointVisible, clipLine, interpolate, start) {
8 return function(sink) {
9 var line = clipLine(sink),
10 ringBuffer = clipBuffer(),
11 ringSink = clipLine(ringBuffer),
12 polygonStarted = false,
13 polygon,
14 segments,
15 ring;
16
17 var clip = {
18 point: point,
19 lineStart: lineStart,
20 lineEnd: lineEnd,
21 polygonStart: function() {
22 clip.point = pointRing;
23 clip.lineStart = ringStart;
24 clip.lineEnd = ringEnd;
25 segments = [];
26 polygon = [];
27 },
28 polygonEnd: function() {
29 clip.point = point;
30 clip.lineStart = lineStart;
31 clip.lineEnd = lineEnd;
32 segments = merge(segments);
33 var startInside = polygonContains(polygon, start);
34 if (segments.length) {
35 if (!polygonStarted) sink.polygonStart(), polygonStarted = true;
36 clipRejoin(segments, compareIntersection, startInside, interpolate, sink);
37 } else if (startInside) {
38 if (!polygonStarted) sink.polygonStart(), polygonStarted = true;
39 sink.lineStart();
40 interpolate(null, null, 1, sink);
41 sink.lineEnd();
42 }
43 if (polygonStarted) sink.polygonEnd(), polygonStarted = false;
44 segments = polygon = null;
45 },
46 sphere: function() {
47 sink.polygonStart();
48 sink.lineStart();
49 interpolate(null, null, 1, sink);
50 sink.lineEnd();
51 sink.polygonEnd();
52 }
53 };
54
55 function point(lambda, phi) {
56 if (pointVisible(lambda, phi)) sink.point(lambda, phi);
57 }
58
59 function pointLine(lambda, phi) {
60 line.point(lambda, phi);
61 }
62
63 function lineStart() {
64 clip.point = pointLine;
65 line.lineStart();
66 }
67
68 function lineEnd() {
69 clip.point = point;
70 line.lineEnd();
71 }
72
73 function pointRing(lambda, phi) {
74 ring.push([lambda, phi]);
75 ringSink.point(lambda, phi);
76 }
77
78 function ringStart() {
79 ringSink.lineStart();
80 ring = [];
81 }
82
83 function ringEnd() {
84 pointRing(ring[0][0], ring[0][1]);
85 ringSink.lineEnd();
86
87 var clean = ringSink.clean(),
88 ringSegments = ringBuffer.result(),
89 i, n = ringSegments.length, m,
90 segment,
91 point;
92
93 ring.pop();
94 polygon.push(ring);
95 ring = null;
96
97 if (!n) return;
98
99 // No intersections.
100 if (clean & 1) {
101 segment = ringSegments[0];
102 if ((m = segment.length - 1) > 0) {
103 if (!polygonStarted) sink.polygonStart(), polygonStarted = true;
104 sink.lineStart();
105 for (i = 0; i < m; ++i) sink.point((point = segment[i])[0], point[1]);
106 sink.lineEnd();
107 }
108 return;
109 }
110
111 // Rejoin connected segments.
112 // TODO reuse ringBuffer.rejoin()?
113 if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift()));
114
115 segments.push(ringSegments.filter(validSegment));
116 }
117
118 return clip;
119 };
120}
121
122function validSegment(segment) {
123 return segment.length > 1;
124}
125
126// Intersections are sorted along the clip edge. For both antimeridian cutting
127// and circle clipping, the same comparison is used.
128function compareIntersection(a, b) {
129 return ((a = a.x)[0] < 0 ? a[1] - halfPi - epsilon : halfPi - a[1])
130 - ((b = b.x)[0] < 0 ? b[1] - halfPi - epsilon : halfPi - b[1]);
131}
Note: See TracBrowser for help on using the repository browser.