rwt-orthographic-earth
Version:
An orthographic projection of Earth, a standards-based DOM Component
227 lines (210 loc) • 9.96 kB
JavaScript
/* 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 ProjectedPoint from '../projection/projected-point.class.js';
import RS from '../enum/rendering-state.enum.js';
import expect from '../dev/expect.js';
const degreesToRadians = Math.PI / 180;
export default class PointFeature extends BaseFeature {
constructor() {
super(), this.discretePoint = new ProjectedPoint(0, 0), this.mouseEpsilon = 3;
}
get featureType() {
return 'place';
}
setPoint(e) {
expect(e, 'ProjectedPoint'), this.discretePoint = e;
}
computeFeatureStyle(e, t, a, s, i, r) {
if (expect(e, 'RenderClock'), expect(t, 'vssStyleSheet'), expect(a, 'String'), expect(s, 'String'),
expect(i, 'Number'), expect(r, 'Number'), 0 == this.featureIsOnNearSide(e.renderingState)) return;
if (0 == this.featureIsOnCanvas(e.renderingState)) return;
let n = t.computeStyle('point', a, s, this.isSelected, this.featureName, this.kvPairs, i);
expect(n, 'vssCanvasParameters'), this.canvasParams.set(r, n);
let o = 'circle' == n['symbol-type'] ? 1 : 2, c = Number(n.size);
isNaN(c) || (o += c);
let d = Number(n['stroke-width']);
isNaN(d) || (o += d), this.mouseEpsilon = Math.max(this.mouseEpsilon, o);
}
runCourtesyValidator(e, t, a, s, i) {
e.runCourtesyValidator('point', t, a, this.featureName, this.kvPairs, s);
}
static courtesyValidator(e) {
switch (e) {
case 'visibility':
case 'scale':
case 'symbol-type':
case 'stroke-width':
case 'stroke-color':
case 'fill-color':
case 'size':
case 'inner-size':
case 'node-count':
case 'code-point':
return !0;
default:
return !1;
}
}
toGeoCoords(e, t) {
t.toPhiLambda(this.discretePoint);
}
toPlane(e, t) {
expect(e, 'RenderClock'), expect(t, 'OrthographicProjection'), this.pointsOnNearSide = 0,
this.pointsOnFarSide = 0;
let a = this.discretePoint;
if (t.toEastingNorthing(a), a.isOnNearSide) this.pointsOnNearSide++; else if (this.pointsOnFarSide++,
e.renderingState == RS.SKETCHING) return;
}
toPixels(e, t) {
expect(e, 'RenderClock'), expect(t, 'CartesianTransformation'), 0 != this.featureIsOnNearSide(e.renderingState) && t.toEarthXY(this.discretePoint, !0, !0, !0);
}
toViewportCanvas(e, t) {
if (expect(e, 'RenderClock'), expect(t, 'Viewport'), 0 == this.featureIsOnNearSide(e.renderingState)) return;
this.pointsOnCanvas = 0, this.pointsOffCanvas = 0;
let a = this.discretePoint;
t.toCanvasXY(a), a.isOnNearSide && (a.isOnCanvas ? this.pointsOnCanvas++ : this.pointsOffCanvas++);
}
drawFeature(e, t, a) {
if (expect(e, 'RenderClock'), expect(t, 'Earth'), expect(a, 'Number'), 0 == this.featureIsOnNearSide(e.renderingState)) return;
if (0 == this.featureIsOnCanvas(e.renderingState)) return;
let s = this.canvasParams.get(a);
if (0 != this.hasSomethingToDraw(s)) {
var i = t.canvas.getContext('2d'), r = this.discretePoint, n = Number(s.scale);
isNaN(n) && (n = 1);
var o = !1;
null != s['stroke-width'] && 'none' != s['stroke-width'] && 0 != s['stroke-width'] && (i.lineWidth = Number(s['stroke-width']) * n,
i.strokeStyle = s['stroke-color'], o = !0);
var c = !1;
null != s['fill-color'] && 'none' != s['fill-color'] && (i.fillStyle = s['fill-color'],
c = !0);
var d = s['symbol-type'];
null == d && (d = 'circle');
var l = 'circle' == d, h = [ 'polygon', 'triangle', 'rhombus', 'pentagon', 'hexagon' ].includes(d), u = [ 'star', 'diamond', 'trigram', 'shuriken', 'pentagram', 'hexagram' ].includes(d), v = [ 'crosshair', 'x-mark' ].includes(d), p = 'unicode' == d;
if (l) {
let e = Number(s.size);
isNaN(e) && (e = 1);
let t = e + 1;
this.drawCircle(i, r.canvasX, r.canvasY, t, n, o, c);
} else {
if (h) {
let e = parseInt(s['node-count']);
isNaN(e) && (e = 3);
let t = Number(s.size);
isNaN(t) && (t = 1);
let a = t + 2;
switch (d) {
case 'triangle':
return void this.drawPolygon(i, r.canvasX, r.canvasY, 3, a, n, o, c);
case 'rhombus':
return void this.drawPolygon(i, r.canvasX, r.canvasY, 4, a, n, o, c);
case 'pentagon':
return void this.drawPolygon(i, r.canvasX, r.canvasY, 5, a, n, o, c);
case 'hexagon':
return void this.drawPolygon(i, r.canvasX, r.canvasY, 6, a, n, o, c);
case 'polygon':
default:
return void this.drawPolygon(i, r.canvasX, r.canvasY, e, a, n, o, c);
}
}
if (u) {
let e = parseInt(s['node-count']);
isNaN(e) && (e = 5);
let t = Number(s.size);
isNaN(t) && (t = 1);
let a = t + 2, l = Number(s['inner-size']);
switch (isNaN(l) && (l = a - 3), d) {
case 'diamond':
return void this.drawStar(i, r.canvasX, r.canvasY, 2, a, .5 * a, n, o, c);
case 'trigram':
return void this.drawStar(i, r.canvasX, r.canvasY, 3, a, .25 * a, n, o, c);
case 'shuriken':
return void this.drawStar(i, r.canvasX, r.canvasY, 4, a, .5 * a, n, o, c);
case 'pentagram':
return void this.drawStar(i, r.canvasX, r.canvasY, 5, a, .5 * a, n, o, c);
case 'hexagram':
return void this.drawStar(i, r.canvasX, r.canvasY, 6, a, .5 * a, n, o, c);
case 'star':
default:
return void this.drawStar(i, r.canvasX, r.canvasY, e, a, l, n, o, c);
}
}
if (v) {
let e = Number(s.size);
isNaN(e) && (e = 1);
let t = e + 2;
switch (d) {
case 'crosshair':
return this.drawOneLine(i, r.canvasX, r.canvasY, t, n, 0), void this.drawOneLine(i, r.canvasX, r.canvasY, t, n, 90);
case 'x-mark':
return this.drawOneLine(i, r.canvasX, r.canvasY, t, n, 45), void this.drawOneLine(i, r.canvasX, r.canvasY, t, n, 135);
default:
return;
}
}
if (p) {
let e = Number(s.size);
isNaN(e) && (e = 1);
var m = null == s['code-point'] ? 'A' : s['code-point'];
this.drawText(i, r.canvasX, r.canvasY, e, n, m, o, c);
} else ;
}
}
}
drawCircle(e, t, a, s, i, r, n) {
e.beginPath(), e.arc(t, a, s * i, 0, 2 * Math.PI, !1), e.closePath(), r && e.stroke(),
n && e.fill();
}
drawPolygon(e, t, a, s, i, r, n, o) {
if (!(s < 3)) {
var c = [], d = 360 / s, l = 270;
for (let e = 0; e < s; e++) {
var h = l * degreesToRadians;
c.push({
x: Math.cos(h) * i * r,
y: Math.sin(h) * i * r
}), l += d;
}
e.beginPath(), e.moveTo(t + c[0].x, a + c[0].y);
for (let i = 1; i < s; i++) e.lineTo(t + c[i].x, a + c[i].y);
e.closePath(), n && e.stroke(), o && e.fill();
}
}
drawStar(e, t, a, s, i, r, n, o, c) {
if (!(s < 2)) {
var d = 2 * s, l = [], h = 360 / d, u = 270;
for (let e = 0; e < d; e++) {
var v = u * degreesToRadians;
e % 2 == 0 ? l.push({
x: Math.cos(v) * i * n,
y: Math.sin(v) * i * n
}) : l.push({
x: Math.cos(v) * r * n,
y: Math.sin(v) * r * n
}), u += h;
}
e.beginPath(), e.moveTo(t + l[0].x, a + l[0].y);
for (let s = 1; s < d; s++) e.lineTo(t + l[s].x, a + l[s].y);
e.closePath(), o && e.stroke(), c && e.fill();
}
}
drawOneLine(e, t, a, s, i, r) {
var n = r * degreesToRadians, o = Math.cos(n) * s * i, c = Math.sin(n) * s * i, d = (r + 180) * degreesToRadians, l = Math.cos(d) * s * i, h = Math.sin(d) * s * i;
e.beginPath(), e.moveTo(t + o, a + c), e.lineTo(t + l, a + h), e.stroke();
}
drawText(e, t, a, s, i, r, n, o) {
let c = Math.round(5 + s * i * 2);
e.font = `${c}px sans-serif`, e.textAlign = 'center', e.textBaseline = 'middle',
n && e.strokeText(r, t, a), o && e.fillText(r, t, a);
}
isPointerAtPoint(e, t) {
if (0 == this.discretePoint.isOnNearSide) return !1;
var a = this.discretePoint.canvasX, s = this.discretePoint.canvasY;
return e - this.mouseEpsilon < a && a < e + this.mouseEpsilon && t - this.mouseEpsilon < s && s < t + this.mouseEpsilon;
}
roughAndReadyPoint() {
return {
latitude: this.discretePoint.latitude,
longitude: this.discretePoint.longitude
};
}
}