'use strict'; export class Mat3 { constructor(arr = null) { if (arr == null) { this.identity(); } else { this.arr = arr; } } i(row, col) { const r = row-1 const c = col-1 const index = (3*r)+c return this.arr[index] } identity() { this.arr = [ 1, 0, 0, 0, 1, 0, 0, 0, 1, ]; return this; } mul(other) { const out = [] out[0] = (this.i(1,1)*other.i(1,1)) + (this.i(1,2)*other.i(2,1)) + (this.i(1,3)*other.i(3,1)); out[1] = (this.i(1,1)*other.i(1,2)) + (this.i(1,2)*other.i(2,2)) + (this.i(1,3)*other.i(3,2)); out[2] = (this.i(1,1)*other.i(1,3)) + (this.i(1,2)*other.i(2,3)) + (this.i(1,3)*other.i(3,3)); out[3] = (this.i(2,1)*other.i(1,1)) + (this.i(2,2)*other.i(2,1)) + (this.i(2,3)*other.i(3,1)); out[4] = (this.i(2,1)*other.i(1,2)) + (this.i(2,2)*other.i(2,2)) + (this.i(2,3)*other.i(3,2)); out[5] = (this.i(2,1)*other.i(1,3)) + (this.i(2,2)*other.i(2,3)) + (this.i(2,3)*other.i(3,3)); out[6] = (this.i(3,1)*other.i(1,1)) + (this.i(3,2)*other.i(2,1)) + (this.i(3,3)*other.i(3,1)); out[7] = (this.i(3,1)*other.i(1,2)) + (this.i(3,2)*other.i(2,2)) + (this.i(3,3)*other.i(3,2)); out[8] = (this.i(3,1)*other.i(1,3)) + (this.i(3,2)*other.i(2,3)) + (this.i(3,3)*other.i(3,3)); this.arr = out return this } mulv(vec) { const x = (this.i(1,1)*vec.x) + (this.i(1,2)*vec.y) + (this.i(1,3)*vec.z); const y = (this.i(2,1)*vec.x) + (this.i(2,2)*vec.y) + (this.i(2,3)*vec.z); const z = (this.i(3,1)*vec.x) + (this.i(3,2)*vec.y) + (this.i(3,3)*vec.z); return new Vec3(x, y, z); } rotation(axis, angle) { const cos = Math.cos(angle); const sin = Math.sin(angle); const mcos = 1-cos; const msin = 1-sin; this.arr[0] = cos + (axis.x * axis.x * mcos); this.arr[1] = (axis.x * axis.y * mcos) - (axis.z * sin); this.arr[2] = (axis.x * axis.z * mcos) + (axis.y * sin); this.arr[3] = (axis.y * axis.x * mcos) + (axis.z * sin); this.arr[4] = cos + (axis.y * axis.y * mcos); this.arr[5] = (axis.y * axis.z * mcos) - (axis.x * sin); this.arr[6] = (axis.z * axis.x * mcos) - (axis.y * sin); this.arr[7] = (axis.z * axis.y * mcos) + (axis.x * sin); this.arr[8] = cos + (axis.z * axis.z * mcos); return this } } export class Point { constructor(latitude, longitude) { this.lat = latitude; this.long = longitude; } normal() { const x = Math.cos(this.lat) * Math.cos(this.long) const y = Math.cos(this.lat) * Math.sin(this.long) const z = Math.sin(this.lat) return new Vec3(x, y, z) } } export class Vec3 { constructor(x, y, z) { this.x = x; this.y = y; this.z = z; } normalize() { const len2 = (this.x*this.x) + (this.y*this.y) + (this.z*this.z); const len = Math.sqrt(len2); this.x = this.x/len; this.y = this.y/len; this.z = this.z/len; return this; } point() { const latitude = Math.asin(this.z); const longitute = Math.sign(this.this.y) * Math.acos( this.x / Math.sqrt( (this.x*this.x) + (this.y*this.y) ) ) return new Point(latitude, longitude) } dot(vec) { return (this.x * vec.x) + (this.y * vec.y) + (this.z * vec.z); } cross(vec) { const x = (this.y*vec.z) - (this.z*vec.y); const y = (this.z*vec.x) - (this.x*vec.z); const z = (this.x*vec.y) - (this.y*vec.x); return new Vec3(x, y, z); } transform(matrix) { return matrix.mulv(this); } render(ct, view) { const viewNorm = view.mulv(this); if (viewNorm.z >= -0.01) { ct.beginPath() ct.arc(viewNorm.x, viewNorm.y, 0.01, 0, 2*Math.PI); ct.fill(); } } } export class Shape { constructor(normals) { this.normals = normals; let avgx = 0; let avgy = 0; let avgz = 0; for (let normal of normals) { avgx += normal.x; avgy += normal.y; avgz += normal.z; } avgx /= normals.length; avgy /= normals.length; avgz /= normals.length; this.center = new Vec3(avgx, avgy, avgz).normalize(); this.extent = 0 for (let normal of normals) { this.extent = Math.max(this.extent, normal.dot(this.center)); } } translate(circle, angle) { const transform = new Mat3().rotation(circle, angle); for (let i=0; i= -0.01) { if (i != start) { ct.stroke(); ct.beginPath(); ct.moveTo(v.x, v.y); } return [ i+1, v ]; } } return [null, null]; } render(ct, view) { ct.beginPath(); let i = 0; let v; [ i, v ] = this.getNextRenderPoint(ct, i, view); if (v == null) { // no renderable points return; } ct.moveTo(v.x, v.y); while(v != null) { ct.lineTo(v.x, v.y); [ i, v ] = this.getNextRenderPoint(ct, i, view); } ct.stroke(); } }