Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
for (const edge of points) {
const curve = new THREE.LineCurve3(edge[0], edge[1]);
const geometry = new THREE.TubeGeometry(curve, 1, LINE_RADIUS, LINE_SEGMENTS);
obj.add(new THREE.Mesh(geometry, material));
}
return obj;
}
// -----------------------------------------------------------------------------
// Custom Element
@register('x-solid')
export class Solid extends CustomElementView {
private isReady = false;
object!: THREE.Object3D;
scene!: Graphics3D;
async ready() {
const size = this.attr('size').split(',');
const width = +size[0];
const height = size.length > 1 ? +size[1] : width;
this.css({width: width + 'px', height: height + 'px'});
this.scene = await create3D(this, 35, 2 * width, 2 * height);
this.scene.camera.position.set(0, 3, 6);
this.scene.camera.up = new THREE.Vector3(0, 1, 0);
this.scene.camera.lookAt(new THREE.Vector3(0, 0, 0));
$fullDots[i].addClass('warning');
$fullDots[i].animate({transform: `translate(50px, 50px) scale(2)`}, 400, 400)
.promise.then(() => $fullDots[i].exit('pop'));
$antiDots[i].addClass('warning');
$antiDots[i].animate({transform: `translate(50px, 50px) scale(2)`}, 400, 400)
.promise.then(() => $antiDots[i].exit('pop'));
}, i * 600);
setTimeout(() => annihilateAudio.play(), i * 600 + 500);
}
}
}
// -----------------------------------------------------------------------------
@register('x-dot-machine')
export class DotMachine extends CustomElementView {
$wrap!: ElementView;
base!: number;
spacing!: number;
cells: Cell[] = [];
ready() {
const cellString = (this.attr('cells') || '000');
const cells = cellString.replace('…', '').split('.');
this.base = (+this.attr('type') || 10);
this.spacing = this.hasClass('tiny') ? 14 : 20;
this.$wrap = $N('div', {class: 'dot-wrap'}, this);
if (cellString[0] === '…') $N('div', {class: 'dot-ellipses'}, this.$wrap);
3: 0xfd8c00, // yellow
4: 0x0f82f2, // blue
5: 0x22ab24, // green
6: 0xcd0e66, // red
8: 0x6f27cc, // violet
10: 0x18aa93 // teal
};
const scales: Obj = {
StellatedDodecahedron: 2,
Octahedron: 1.3,
Tetrahedron: 1.1
};
@register('x-polyhedron')
export class Polyhedron extends Solid {
created() {
const shape = this.attr('shape');
const data = PolyhedronData[shape];
if (!data) return console.error('Unknown polyhedron:', shape);
const scale = scales[shape] || 1.65;
this.setAttr('rotate', '1');
this.addMesh((scene) => {
const polyhedron = new THREE.Object3D();
const vertices = data.vertex.map(v =>
new THREE.Vector3(v[0], v[1], v[2]).multiplyScalar(scale));
const faceGeometry = new THREE.Geometry();
// =============================================================================
// Anibutton Component
// (c) Mathigon
// =============================================================================
import {$N, CustomElementView, register, animate, ease, ElementView, SVGParentView} from '@mathigon/boost';
import {Burst} from '../../shared/components/burst';
@register('x-anibutton', {attributes: ['text']})
export class Anibutton extends CustomElementView {
$text!: ElementView;
burst!: Burst;
ready() {
const $svg = $N('svg', {width: 160, height: 160}, this) as SVGParentView;
this.$text = $N('span', {html: this.attr('text')}, this);
this.burst = new Burst($svg, 20);
this.on('attr:text', e => this.$text.text = e.newVal);
}
play() {
if (this.burst.isAnimating) return;
this.posn = p;
this.angle = a;
this.$el.setTransform(p, a * Math.PI / 180);
}
hasIntersects(polygon: Polygon) {
for (let p of this.$parent.shapes) {
if (p !== this && Polygon.collision(p.transformed, polygon)) return true;
}
return false;
}
}
// -----------------------------------------------------------------------------
@register('x-tessellation', {templateId: '#tessellation'})
export class Tessellation extends CustomElementView {
shapes: Shape[] = [];
$svg!: SVGParentView;
ready() {
this.$svg = this.$('svg') as SVGParentView;
for (let c of INITIAL) new Shape(SHAPES[c.p], c, this);
for (let $a of this.$$('.add')) {
const s = +$a.data.shape!;
const shape = SHAPES[s];
$a.css('background', shape.colour);
const transform = `transform: translate(25px, 25px) scale(${1 / (1 + .4 *
s)})`;
$N('polygon', {points: shape.points, style: transform}, $a.$('svg'));
// =============================================================================
// Tetrahedron Component
// (c) Mathigon
// =============================================================================
import {register} from '@mathigon/boost';
import {Solid} from '../../shared/components/solid';
import {trianglePoints, triangleOffset} from './polygons';
const COLOURS = [0xff941f, 0xec7031, 0xd94c44, 0xc62857, 0xb30469]; // TODO New Colours
@register('x-tetrahedron')
export class Tetrahedron extends Solid {
created() {
const layers = +this.attr('layers');
if (layers > 1) this.setAttr('rotate', '1');
this.addMesh(() => {
const tetrahedron = new THREE.Object3D();
const geometry = new THREE.SphereGeometry(0.34, 64, 64);
for (let i = 0; i < layers; ++i) {
const points = trianglePoints(i);
const dy = triangleOffset(i, layers) + 0.5;
const material = new THREE.MeshPhongMaterial({
transparent: true,
// =============================================================================
// Water Ripples Component
// (c) Mathigon
// =============================================================================
import {repeat2D, tabulate2D} from '@mathigon/core';
import {isBetween, clamp, Point} from '@mathigon/fermat';
import {CustomElementView, register, $N, slide, animate, CanvasView} from '@mathigon/boost';
const THRESHOLD = 0.05;
let TIMEOUT: number;
@register('x-water-canvas')
export class WaterCanvas extends CustomElementView {
private $canvas!: CanvasView;
private imagePixels?: Uint8ClampedArray;
private isAnimating = false;
private damping!: number;
private clipping!: number;
private refraction!: number; // Number of pixels used by refraction.
private reflection!: number; // Amount of color highlighting.
private touchSize = 10;
private sx!: number;
private sy!: number;
private rx!: number;
private ry!: number;
const px = this.c.x - line.p1.x;
const py = this.c.y - line.p1.y;
const A = (dx / this.a) ** 2 + (dy / this.b) ** 2;
const B = 2 * px * dx / (this.a) ** 2 + 2 * py * dy / (this.b) ** 2;
const C = (px / this.a) ** 2 + (py / this.b) ** 2 - 1;
const points = quadratic(A, B, C);
return points.map(t => line.at(t));
}
}
// -----------------------------------------------------------------------------
@register('x-pool-table')
export class PoolTable extends CustomElementView {
private $path!: SVGView;
private $end!: SVGView;
ready() {
const $svg = this.$('svg') as SVGParentView;
$N('ellipse', {cx: 380, cy: 220, rx: 366, ry: 206, class: 'pool-table'}, $svg);
this.$path = $N('path', {fill: 'transparent', stroke: 'white'}, $svg) as SVGView;
const $start = $N('circle', {r: 20, fill: '#fd8c00'}, $svg);
const drag = new Draggable($start, $svg, {useTransform: true});
this.$end = $N('circle', {r: 20, fill: '#0f82f2'}, $svg) as SVGView;
drag.on('move', (p) => this.drawPath(p));
geometry.faces.push(new THREE.Face3(0, 1, 2));
geometry.faces.push(new THREE.Face3(2, 3, 0));
return geometry;
}
function getTubeGeo(angle = 0) {
const points = tabulate((i) => getPointAt(i / 120, angle), 121);
const curve = new THREE.CatmullRomCurve3(points, false);
return new THREE.TubeGeometry(curve, 120, 0.3, 8, false);
}
// -----------------------------------------------------------------------------
// Component
@register('x-conic-section')
export class ConicSection extends CustomElementView {
update!: (a: number) => void;
async ready() {
const scene = await create3D(this, 25, width, height);
scene.camera.position.set(centerX, 32, 66);
scene.camera.lookAt(centerX, 0, 0);
// Ambient Lights
const ambientLight = new THREE.AmbientLight(0x888888);
scene.add(ambientLight);
// Point Light
const pointLight = new THREE.PointLight(0xaaaaaa);
pointLight.position.set(centerX, 20, 65);
scene.add(pointLight);
return points;
}
function addSpheres(points: Point3D[], color: number, atom: THREE.Object3D) {
const material = new THREE.MeshPhongMaterial({specular: 0x222222, color});
const geometry = new THREE.SphereGeometry(0.7, 64, 64);
for (const p of points) {
const sphere = new THREE.Mesh(geometry, material);
sphere.position.set(...p);
atom.add(sphere);
}
}
@register('x-atom')
export class Atom extends Solid {
created() {
this.addMesh(() => {
const atom = new THREE.Object3D();
const protons = +this.attr('protons');
const neutrons = +this.attr('neutrons');
const points = Random.shuffle(distribute(protons + neutrons)) as [number, number, number][];
const color = parseInt(this.attr('color'), 16);
addSpheres(points.slice(0, protons), color || BLUE, atom);
addSpheres(points.slice(protons), color || RED, atom);
return [atom];
});
}