UNPKG

rwt-orthographic-earth

Version:

An orthographic projection of Earth, a standards-based DOM Component

205 lines (192 loc) 9.38 kB
/* Copyright (c) 2022 Read Write Tools. Legal use subject to the JavaScript Orthographic Earth Software License Agreement. */ import BaseFeature from './base-feature.class.js'; import * as st from '../spherical-earth/spherical-trigonometry.js'; import RS from '../enum/rendering-state.enum.js'; import expect from '../dev/expect.js'; export default class PolygonFeature extends BaseFeature { constructor() { super(), this.outerRing = [], this.innerRings = []; } get featureType() { return 'region'; } addPoint(e) { expect(e, 'ProjectedPoint'), this.outerRing.push(e); } computeFeatureStyle(e, t, i, r, n, s) { if (expect(e, 'RenderClock'), expect(t, 'vssStyleSheet'), expect(i, 'String'), expect(r, 'String'), expect(n, 'Number'), expect(s, 'Number'), 0 == this.featureIsOnNearSide(e.renderingState)) return; if (0 == this.featureIsOnCanvas(e.renderingState)) return; let a = t.computeStyle('polygon', i, r, this.isSelected, this.featureName, this.kvPairs, n); expect(a, 'vssCanvasParameters'), this.canvasParams.set(s, a); } runCourtesyValidator(e, t, i, r, n) { e.runCourtesyValidator('polygon', t, i, this.featureName, this.kvPairs, r); } static courtesyValidator(e) { switch (e) { case 'visibility': case 'scale': case 'transparency': case 'stroke-width': case 'stroke-color': case 'stroke-type': case 'fill-color': case 'fill-type': return !0; default: return !1; } } toGeoCoords(e, t) { for (var i = 0; i < this.outerRing.length; i++) t.toPhiLambda(this.outerRing[i]); for (i = 0; i < this.innerRings.length; i++) for (var r = this.innerRings[i], n = 0; n < r.outerRing.length; n++) { let e = r.outerRing[n]; t.toPhiLambda(e); } } toPlane(e, t) { expect(e, 'RenderClock'), expect(t, 'OrthographicProjection'), this.pointsOnNearSide = 0, this.pointsOnFarSide = 0; for (var i = 0; i < this.outerRing.length; i++) { let r = this.outerRing[i]; if (t.toEastingNorthing(r), r.isOnNearSide) this.pointsOnNearSide++; else if (this.pointsOnFarSide++, e.renderingState == RS.SKETCHING) return; } for (i = 0; i < this.innerRings.length; i++) for (var r = this.innerRings[i], n = 0; n < r.outerRing.length; n++) { let i = r.outerRing[n]; if (t.toEastingNorthing(i), i.isOnNearSide) this.pointsOnNearSide++; else if (this.pointsOnFarSide++, e.renderingState == RS.SKETCHING) return; } } toPixels(e, t) { if (expect(e, 'RenderClock'), expect(t, 'CartesianTransformation'), 0 != this.featureIsOnNearSide(e.renderingState)) { for (var i = 0; i < this.outerRing.length; i++) t.toEarthXY(this.outerRing[i], !0, !0, !0); for (i = 0; i < this.innerRings.length; i++) this.innerRings[i].toPixels(e, t); } } toViewportCanvas(e, t) { if (expect(e, 'RenderClock'), expect(t, 'Viewport'), 0 != this.featureIsOnNearSide(e.renderingState)) { this.pointsOnCanvas = 0, this.pointsOffCanvas = 0; for (var i = 0; i < this.outerRing.length; i++) { let r = this.outerRing[i]; if (t.toCanvasXY(r), r.isOnNearSide) if (r.isOnCanvas) this.pointsOnCanvas++; else if (this.pointsOffCanvas++, e.renderingState == RS.SKETCHING) return; } for (i = 0; i < this.innerRings.length; i++) for (var r = this.innerRings[i], n = 0; n < r.outerRing.length; n++) { let i = r.outerRing[n]; if (t.toCanvasXY(i), i.isOnNearSide) if (i.isOnCanvas) this.pointsOnCanvas++; else if (this.pointsOffCanvas++, e.renderingState == RS.SKETCHING) return; } } } drawFeature(e, t, i) { if (expect(e, 'RenderClock'), expect(t, 'Earth'), expect(i, 'Number'), 0 == this.featureIsOnNearSide(e.renderingState)) return; if (0 == this.featureIsOnCanvas(e.renderingState)) return; let r = this.canvasParams.get(i); if (0 != this.hasSomethingToDraw(r) && ('none' != r['fill-color'] || 'none' != r['stroke-width'])) { var n = t.canvas.getContext('2d'); n.beginPath(), this.drawRing(t, n, !1); for (var s = 0; s < this.innerRings.length; s++) { this.innerRings[s].drawRing(t, n, !0); } if (n.closePath(), n.fillStyle = r.computeFillPlusTransparency(), null != r['stroke-color'] && 'none' != r['stroke-color']) { switch (n.strokeStyle = r['stroke-color'], r['stroke-type']) { case 'solid': n.setLineDash([]); break; case 'dotted': n.setLineDash([ 3, 3 ]); break; case 'short-dash': n.setLineDash([ 10, 10 ]); break; case 'long-dash': n.setLineDash([ 20, 5 ]); break; case 'dot-dash': n.setLineDash([ 15, 3, 3, 3 ]); break; case 'dot-dot-dash': n.setLineDash([ 15, 3, 3, 3, 3, 3 ]); break; case 'dot-dot-dot-dash': n.setLineDash([ 15, 3, 3, 3, 3, 3, 3, 3 ]); break; case 'dot-dash-dot': n.setLineDash([ 3, 3, 12, 3, 3, 12 ]); break; default: n.setLineDash([]); } if (null != r['stroke-width'] && 'none' != r['stroke-width'] && 0 != r['stroke-width']) { var a = Number(r.scale); isNaN(a) && (a = 1); var o = Number(r['stroke-width']); n.lineWidth = o * a, n.stroke(); } n.setLineDash([]); } n.globalCompositeOperation = r['fill-type'], 'none' != r['fill-color'] && n.fill(), n.globalCompositeOperation = 'source-over'; } } drawRing(e, t, i) { for (var r = e.carte.translate.a * e.carte.multiplier, n = e.carte.translate.b * e.carte.multiplier, s = e.viewport.centerPoint.x + r, a = e.viewport.centerPoint.y + n, o = e.getVisualizedRadius(), h = !1, l = !1, u = !0, c = null, g = null, d = null, f = 0; f < this.outerRing.length; f++) { var p = this.outerRing[f], R = this.outerRing[f - 1]; if (l = p.isOnNearSide, 1 == u) 1 == l && (t.moveTo(p.canvasX, p.canvasY), f > 0 && (c = p.projectedTheta), u = !1); else if (1 == l && 1 == h) t.lineTo(p.canvasX, p.canvasY); else if (0 == l && 1 == h) { g = R.projectedTheta; let e = s + o * Math.cos(g), i = a + o * Math.sin(g); t.lineTo(e, i); } else if (1 == l && 0 == h) { if (g != (d = p.projectedTheta)) { var v = g, S = d; 'night' == this.featureName ? t.arc(s, a, o, v, S, !0) : this.drawArc(t, s, a, o, v, S, i); let e = s + o * Math.cos(d), r = a + o * Math.sin(d); t.lineTo(e, r); } g = null, d = null; } h = p.isOnNearSide; } if (null != g && null != c) { if (g != c) { v = g, S = c; 'night' == this.featureName ? t.arc(s, a, o, v, S, !0) : this.drawArc(t, s, a, o, v, S, i); let e = s + o * Math.cos(c), r = a + o * Math.sin(c); t.lineTo(e, r); } g = null, c = null; } } drawArc(e, t, i, r, n, s, a) { 1 != a && (Math.abs(s - n) > Math.PI ? n > s ? e.arc(t, i, r, n, s, !1) : e.arc(t, i, r, n, s, !0) : n < s ? e.arc(t, i, r, n, s, !1) : e.arc(t, i, r, n, s, !0)); } isPointerInsidePolygon(e, t) { var i = this.outerRing.length, r = !1, n = 0; for (let e = 0; e < i && n < 3; e++) 1 == this.outerRing[e].isOnNearSide && n++; if (n < 3) return !1; var s = null; for (let e = 0; e < i; e++) if (1 == this.outerRing[e].isOnNearSide) { s = e; break; } var a = s; for (let n = a + 1; n < i; n++) { if (0 == this.outerRing[n].isOnNearSide) continue; let i = a; var o = this.outerRing[n].canvasX, h = this.outerRing[n].canvasY, l = this.outerRing[i].canvasX; if (h > t != (u = this.outerRing[i].canvasY) > t) e < (l - o) * (t - h) / (u - h) + o && (r = !r); a = n; } var u; o = this.outerRing[s].canvasX, h = this.outerRing[s].canvasY, l = this.outerRing[a].canvasX; h > t != (u = this.outerRing[a].canvasY) > t && (e < (l - o) * (t - h) / (u - h) + o && (r = !r)); return r; } roughAndReadyPoint() { var e = this.outerRing[0], t = Math.round(this.outerRing.length / 2), i = this.outerRing[t]; return st.sphericalMidpoint(e.latitude, e.longitude, i.latitude, i.longitude); } }