|
5397 | 5397 | while (++i < n) d3_geo_streamLine(coordinates[i], listener, 1); |
5398 | 5398 | listener.polygonEnd(); |
5399 | 5399 | } |
5400 | | - function d3_geo_streamRadians(stream) { |
5401 | | - return d3_geo_streamTransform(stream, function(x, y) { |
5402 | | - stream.point(x * d3_radians, y * d3_radians); |
5403 | | - }); |
5404 | | - } |
5405 | | - function d3_geo_streamRotate(rotate, stream) { |
5406 | | - return d3_geo_streamTransform(stream, function(x, y) { |
5407 | | - x = rotate(x, y); |
5408 | | - stream.point(x[0], x[1]); |
5409 | | - }); |
5410 | | - } |
5411 | | - function d3_geo_streamTransform(stream, point) { |
5412 | | - return { |
5413 | | - point: point, |
5414 | | - sphere: stream.sphere, |
5415 | | - lineStart: stream.lineStart, |
5416 | | - lineEnd: stream.lineEnd, |
5417 | | - polygonStart: stream.polygonStart, |
5418 | | - polygonEnd: stream.polygonEnd |
5419 | | - }; |
5420 | | - } |
5421 | 5400 | function d3_geo_spherical(cartesian) { |
5422 | 5401 | return [ Math.atan2(cartesian[1], cartesian[0]), Math.asin(Math.max(-1, Math.min(1, cartesian[2]))) ]; |
5423 | 5402 | } |
5424 | 5403 | function d3_geo_sphericalEqual(a, b) { |
5425 | | - return !a || Math.abs(a[0] - b[0]) < ε && Math.abs(a[1] - b[1]) < ε; |
| 5404 | + return Math.abs(a[0] - b[0]) < ε && Math.abs(a[1] - b[1]) < ε; |
5426 | 5405 | } |
5427 | 5406 | function d3_geo_cartesian(spherical) { |
5428 | 5407 | var λ = spherical[0], φ = spherical[1], cosφ = Math.cos(φ); |
|
5528 | 5507 | }; |
5529 | 5508 | function d3_geo_clip(pointVisible, clipLine, interpolate) { |
5530 | 5509 | return function(listener) { |
5531 | | - var line = clipLine(listener); |
| 5510 | + var line = clipLine(listener), polygon = [], ring; |
5532 | 5511 | var clip = { |
5533 | 5512 | point: point, |
5534 | 5513 | lineStart: lineStart, |
|
5539 | 5518 | clip.lineEnd = d3_noop; |
5540 | 5519 | }, |
5541 | 5520 | polygonEnd: function() { |
5542 | | - return; |
5543 | 5521 | clip.point = point; |
5544 | 5522 | clip.lineStart = lineStart; |
5545 | 5523 | clip.lineEnd = lineEnd; |
|
5577 | 5555 | polygon.push(ring = []); |
5578 | 5556 | } |
5579 | 5557 | }; |
5580 | | - var subject = [], clip = [], segments = [], visibleArea = 0, invisibleArea = 0, invisible = false; |
| 5558 | + } |
| 5559 | + function d3_geo_clipPolygon(polygon, clipRing, interpolate, listener) { |
| 5560 | + var subject = [], clip = [], segments = [], visibleArea = 0, invisibleArea = 0, invisible = false, buffer = d3_geo_clipBufferListener(), ringListener = clipRing(buffer); |
| 5561 | + listener.polygonStart(); |
5581 | 5562 | var segments = d3.merge(polygon.map(function(ring) { |
5582 | | - var x = clipRing(ring, bufferListener), ringSegments = x[1], segment, n = ringSegments.length; |
| 5563 | + ringListener.lineStart(); |
| 5564 | + ring.forEach(function(point) { |
| 5565 | + ringListener.point(point[0], point[1]); |
| 5566 | + }); |
| 5567 | + ringListener.lineEnd(); |
| 5568 | + var clean = ringListener.clean(), ringSegments = buffer.buffer(), segment, n = ringSegments.length; |
5583 | 5569 | if (!n) { |
5584 | 5570 | invisible = true; |
5585 | | - invisibleArea += d3_geo_areaRing(ring.map(d3_geo_clipRotationInvisible)); |
| 5571 | + invisibleArea += d3_geo_clipAreaRing(ring, d3_geo_clipRotationInvisible); |
5586 | 5572 | return []; |
5587 | 5573 | } |
5588 | | - if (x[0] & 1) { |
| 5574 | + if (clean & 1) { |
5589 | 5575 | segment = ringSegments[0]; |
5590 | | - visibleArea += d3_geo_areaRing(segment.map(d3_geo_clipRotation)); |
5591 | | - var n = segment.length - 1, i = -1, point; |
| 5576 | + visibleArea += d3_geo_clipAreaRing(segment, d3_geo_clipRotation); |
| 5577 | + var n = segment.length, i = -1, point; |
5592 | 5578 | listener.lineStart(); |
5593 | 5579 | while (++i < n) listener.point((point = segment[i])[0], point[1]); |
5594 | 5580 | listener.lineEnd(); |
5595 | 5581 | return []; |
5596 | 5582 | } |
5597 | | - if (n > 1 && x[0] & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift())); |
| 5583 | + if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift())); |
5598 | 5584 | return ringSegments.filter(d3_geo_clipSegmentLength1); |
5599 | 5585 | })); |
5600 | 5586 | if (!segments.length && (visibleArea < -ε2 || invisible && invisibleArea < -ε2)) { |
| 5587 | + listener.lineStart(); |
5601 | 5588 | interpolate(null, null, 1, listener); |
| 5589 | + listener.lineEnd(); |
5602 | 5590 | } |
5603 | 5591 | segments.forEach(function(segment) { |
5604 | 5592 | var n = segment.length; |
|
5644 | 5632 | clip.sort(d3_geo_clipSort); |
5645 | 5633 | d3_geo_clipLinkCircular(subject); |
5646 | 5634 | d3_geo_clipLinkCircular(clip); |
5647 | | - if (!subject.length) return; |
5648 | | - var start = subject[0], current, points; |
| 5635 | + if (!subject.length) return listener.polygonEnd(); |
| 5636 | + var start = subject[0], current, points, point; |
5649 | 5637 | while (1) { |
5650 | 5638 | current = start; |
5651 | 5639 | while (current.visited) if ((current = current.next) === start) return listener.polygonEnd(); |
|
5676 | 5664 | } |
5677 | 5665 | listener.polygonEnd(); |
5678 | 5666 | } |
5679 | | - function d3_geo_clipPolygon(polygon, clipRing, interpolate, listener) {} |
5680 | | - function d3_geo_clipRotation(point) { |
5681 | | - var λ = point[0], φ = point[1], cosφ = Math.cos(φ); |
5682 | | - return [ Math.atan2(Math.sin(λ) * cosφ, Math.sin(φ)), Math.asin(Math.max(-1, Math.min(1, -Math.cos(λ) * cosφ))) ]; |
5683 | | - } |
5684 | | - function d3_geo_clipRotationInvisible(point) { |
5685 | | - var λ = point[0] + π, φ = point[1], cosφ = Math.cos(φ); |
5686 | | - return [ Math.atan2(Math.sin(λ) * cosφ, Math.sin(φ)), Math.asin(Math.max(-1, Math.min(1, -Math.cos(λ) * cosφ))) ]; |
5687 | | - } |
5688 | 5667 | function d3_geo_clipLinkCircular(array) { |
5689 | 5668 | if (!(n = array.length)) return; |
5690 | 5669 | var n, i = 0, a = array[0], b; |
|
5702 | 5681 | function d3_geo_clipSegmentLength1(segment) { |
5703 | 5682 | return segment.length > 1; |
5704 | 5683 | } |
5705 | | - var d3_geo_cut = d3_geo_clip(d3_identity, d3_geo_cutLine, d3_geo_cutInterpolate); |
| 5684 | + function d3_geo_clipBufferListener() { |
| 5685 | + var lines = [], line; |
| 5686 | + return { |
| 5687 | + lineStart: function() { |
| 5688 | + lines.push(line = []); |
| 5689 | + }, |
| 5690 | + point: function(λ, φ) { |
| 5691 | + line.push([ λ, φ ]); |
| 5692 | + }, |
| 5693 | + lineEnd: d3_noop, |
| 5694 | + buffer: function() { |
| 5695 | + var buffer = lines; |
| 5696 | + lines = []; |
| 5697 | + line = null; |
| 5698 | + return buffer; |
| 5699 | + } |
| 5700 | + }; |
| 5701 | + } |
| 5702 | + function d3_geo_clipAreaRing(ring, rotate) { |
| 5703 | + d3_geo_area.polygonStart(); |
| 5704 | + d3_geo_area.lineStart(); |
| 5705 | + for (var i = 0, n = ring.length, p; i < n; ++i) { |
| 5706 | + p = rotate(ring[i]); |
| 5707 | + d3_geo_area.point(p[0] * d3_degrees, p[1] * d3_degrees); |
| 5708 | + } |
| 5709 | + d3_geo_area.lineEnd(); |
| 5710 | + d3_geo_area.polygonEnd(); |
| 5711 | + return d3_geo_areaRing; |
| 5712 | + } |
| 5713 | + function d3_geo_clipRotation(point) { |
| 5714 | + var λ = point[0], φ = point[1], cosφ = Math.cos(φ); |
| 5715 | + return [ Math.atan2(Math.sin(λ) * cosφ, Math.sin(φ)), Math.asin(Math.max(-1, Math.min(1, -Math.cos(λ) * cosφ))) ]; |
| 5716 | + } |
| 5717 | + function d3_geo_clipRotationInvisible(point) { |
| 5718 | + var λ = point[0] + π, φ = point[1], cosφ = Math.cos(φ); |
| 5719 | + return [ Math.atan2(Math.sin(λ) * cosφ, Math.sin(φ)), Math.asin(Math.max(-1, Math.min(1, -Math.cos(λ) * cosφ))) ]; |
| 5720 | + } |
| 5721 | + var d3_geo_cut = d3_geo_clip(d3_true, d3_geo_cutLine, d3_geo_cutInterpolate); |
5706 | 5722 | function d3_geo_cutLine(listener) { |
5707 | | - var λ0 = NaN, φ0 = NaN, sλ0 = NaN, clean = 1; |
| 5723 | + var λ0 = NaN, φ0 = NaN, sλ0 = NaN, clean; |
5708 | 5724 | return { |
5709 | 5725 | lineStart: function() { |
5710 | 5726 | listener.lineStart(); |
| 5727 | + clean = 1; |
5711 | 5728 | }, |
5712 | 5729 | point: function(λ1, φ1) { |
5713 | 5730 | var sλ1 = λ1 > 0 ? π : -π, dλ = Math.abs(λ1 - λ0); |
|
5733 | 5750 | sλ0 = sλ1; |
5734 | 5751 | }, |
5735 | 5752 | lineEnd: function() { |
5736 | | - λ0 = φ0 = NaN; |
5737 | 5753 | listener.lineEnd(); |
| 5754 | + λ0 = φ0 = NaN; |
| 5755 | + }, |
| 5756 | + clean: function() { |
| 5757 | + return 2 - clean; |
5738 | 5758 | } |
5739 | 5759 | }; |
5740 | 5760 | } |
|
5779 | 5799 | resample.point = resamplePoint; |
5780 | 5800 | listener.lineEnd(); |
5781 | 5801 | }, |
5782 | | - polygonStart: d3_noop, |
5783 | | - polygonEnd: d3_noop |
| 5802 | + polygonStart: function() { |
| 5803 | + listener.polygonStart(); |
| 5804 | + }, |
| 5805 | + polygonEnd: function() { |
| 5806 | + listener.polygonEnd(); |
| 5807 | + } |
5784 | 5808 | }; |
5785 | 5809 | function resamplePoint(λ, φ) { |
5786 | 5810 | var point = projectPoint(λ, φ); |
|
6032 | 6056 | function d3_geo_circleClip(degrees) { |
6033 | 6057 | var radians = degrees * d3_radians, cr = Math.cos(radians), interpolate = d3_geo_circleInterpolate(radians, 6 * d3_radians); |
6034 | 6058 | return d3_geo_clip(visible, clipLine, interpolate); |
6035 | | - function visible(point) { |
6036 | | - return Math.cos(point[1]) * Math.cos(point[0]) > cr; |
| 6059 | + function visible(λ, φ) { |
| 6060 | + return Math.cos(λ) * Math.cos(φ) > cr; |
6037 | 6061 | } |
6038 | 6062 | function clipLine(listener) { |
6039 | | - var point0, v0 = false, v00 = false, clean = 1; |
| 6063 | + var point0, v0, v00, clean; |
6040 | 6064 | return { |
6041 | | - lineStart: d3_noop, |
| 6065 | + lineStart: function() { |
| 6066 | + v00 = v0 = false; |
| 6067 | + clean = 1; |
| 6068 | + }, |
6042 | 6069 | point: function(λ, φ) { |
6043 | | - var point1 = [ λ, φ ], point2, v = visible(point1); |
| 6070 | + var point1 = [ λ, φ ], point2, v = visible(λ, φ); |
6044 | 6071 | if (!point0 && (v00 = v0 = v)) listener.lineStart(); |
6045 | 6072 | if (v !== v0) { |
6046 | 6073 | point2 = intersect(point0, point1); |
6047 | 6074 | if (d3_geo_sphericalEqual(point0, point2) || d3_geo_sphericalEqual(point1, point2)) { |
6048 | 6075 | point1[0] += ε; |
6049 | 6076 | point1[1] += ε; |
6050 | | - v = visible(point1); |
| 6077 | + v = visible(point1[0], point1[1]); |
6051 | 6078 | } |
6052 | 6079 | } |
6053 | 6080 | if (v !== v0) { |
|
6063 | 6090 | } |
6064 | 6091 | point0 = point2; |
6065 | 6092 | } |
6066 | | - if (v && !d3_geo_sphericalEqual(point0, point1)) listener.point(point1[0], point1[1]); |
| 6093 | + if (v && (!point0 || !d3_geo_sphericalEqual(point0, point1))) listener.point(point1[0], point1[1]); |
6067 | 6094 | point0 = point1; |
6068 | 6095 | }, |
6069 | 6096 | lineEnd: function() { |
6070 | 6097 | if (v0) listener.lineEnd(); |
6071 | | - v0 = v00 = false; |
6072 | 6098 | point0 = null; |
6073 | | - clean = 1; |
| 6099 | + }, |
| 6100 | + clean: function() { |
| 6101 | + return clean | (v00 && v0) << 1; |
6074 | 6102 | } |
6075 | 6103 | }; |
6076 | 6104 | } |
|
6260 | 6288 | d3.geo.path = function() { |
6261 | 6289 | var pointRadius = 4.5, pointCircle = d3_geo_pathCircle(pointRadius), projection = d3.geo.albersUsa(), context, buffer = []; |
6262 | 6290 | function path(object) { |
| 6291 | + if (object == null) return; |
6263 | 6292 | var radius = typeof pointRadius === "function" ? pointRadius.apply(this, arguments) : pointRadius; |
6264 | 6293 | d3.geo.stream(object, projection.stream(context == null ? new d3_geo_pathBuffer(buffer, radius) : new d3_geo_pathContext(context, radius))); |
6265 | 6294 | if (buffer.length) { |
|
6439 | 6468 | x00 = x0 = x, y00 = y0 = y; |
6440 | 6469 | }; |
6441 | 6470 | function nextPoint(x, y) { |
6442 | | - var dx = x - x0, dy = y - y0, z = y0 * x - x0 * y; |
| 6471 | + var z = y0 * x - x0 * y; |
6443 | 6472 | d3_geo_centroidX += z * (x0 + x); |
6444 | 6473 | d3_geo_centroidY += z * (y0 + y); |
6445 | 6474 | d3_geo_centroidZ += z * 3; |
|
6472 | 6501 | } |
6473 | 6502 | }; |
6474 | 6503 | function d3_geo_areaRingStart() { |
6475 | | - var λ00, φ00, λ1, λ0, φ0, cosφ0, sinφ0; |
| 6504 | + var λ00, φ00, λ1, φ1, λ0, φ0, cosφ0, sinφ0; |
6476 | 6505 | d3_geo_area.point = function(λ, φ) { |
6477 | 6506 | d3_geo_area.point = nextPoint; |
6478 | 6507 | λ1 = λ0 = (λ00 = λ) * d3_radians, φ0 = (φ00 = φ) * d3_radians, cosφ0 = Math.cos(φ0), |
|
6500 | 6529 | })(); |
6501 | 6530 | } |
6502 | 6531 | function d3_geo_projectionMutator(projectAt) { |
6503 | | - var project, projectRotate, k = 150, x = 480, y = 250, λ = 0, φ = 0, δλ = 0, δφ = 0, δγ = 0, δx, δy, clip = d3_geo_cut, clipAngle = null, projectResample = d3_geo_resample(projectPoint); |
| 6532 | + var project, projectRotate, rotate, k = 150, x = 480, y = 250, λ = 0, φ = 0, δλ = 0, δφ = 0, δγ = 0, δx, δy, clip = d3_geo_cut, clipAngle = null, projectResample = d3_geo_resample(projectPoint); |
6504 | 6533 | function projection(coordinates) { |
6505 | 6534 | coordinates = projectRotate(coordinates[0] * d3_radians, coordinates[1] * d3_radians); |
6506 | 6535 | return [ coordinates[0] * k + δx, δy - coordinates[1] * k ]; |
|
6510 | 6539 | return [ coordinates[0] * d3_degrees, coordinates[1] * d3_degrees ]; |
6511 | 6540 | } |
6512 | 6541 | projection.stream = function(listener) { |
6513 | | - return d3_geo_streamRadians(d3_geo_streamRotate(rotate, clip(projectResample(listener)))); |
| 6542 | + return d3_geo_projectionRadiansRotate(rotate, clip(projectResample(listener))); |
6514 | 6543 | }; |
6515 | 6544 | projection.clipAngle = function(_) { |
6516 | 6545 | if (!arguments.length) return clipAngle; |
|
6559 | 6588 | return reset(); |
6560 | 6589 | }; |
6561 | 6590 | } |
| 6591 | + function d3_geo_projectionRadiansRotate(rotate, stream) { |
| 6592 | + return { |
| 6593 | + point: function(λ, φ) { |
| 6594 | + var p = rotate(λ * d3_radians, φ * d3_radians); |
| 6595 | + stream.point(p[0], p[1]); |
| 6596 | + }, |
| 6597 | + sphere: function() { |
| 6598 | + stream.sphere(); |
| 6599 | + }, |
| 6600 | + lineStart: function() { |
| 6601 | + stream.lineStart(); |
| 6602 | + }, |
| 6603 | + lineEnd: function() { |
| 6604 | + stream.lineEnd(); |
| 6605 | + }, |
| 6606 | + polygonStart: function() { |
| 6607 | + stream.polygonStart(); |
| 6608 | + }, |
| 6609 | + polygonEnd: function() { |
| 6610 | + stream.polygonEnd(); |
| 6611 | + } |
| 6612 | + }; |
| 6613 | + } |
6562 | 6614 | function d3_geo_rotation(δλ, δφ, δγ) { |
6563 | 6615 | return δλ ? δφ || δγ ? d3_geo_compose(d3_geo_rotationλ(δλ), d3_geo_rotationφγ(δφ, δγ)) : d3_geo_rotationλ(δλ) : δφ || δγ ? d3_geo_rotationφγ(δφ, δγ) : d3_geo_identityRotation; |
6564 | 6616 | } |
|
0 commit comments