xxxxxxxxxx
197
let consts = {
triangles: [],
half_w: 300,
half_h: 300,
crmin: 20, // Radius range of the circle
crmax: 80, // enclosing the triangle
rotation_speed: 3.14/500, // Maximum rotation increment per frame
translation_speed: 0.5, // Maximum motion increment per frame
triangle_count: 300,
root_boundary: undefined
}
function setup() {
// noLoop() ; run_tests() ; return;
createCanvas(2*consts.half_w, 2*consts.half_h)
consts.root_boundary = new Boundary(
new VPoint(-consts.half_w, +consts.half_h),
new VPoint(+consts.half_w, -consts.half_h)
)
stroke(100,100,100)
for(let i = 0; i < consts.triangle_count; ++i) {
consts.triangles[i] = create_triangle()
}
}
function draw() {
// return;
background("black")
// crossings()
qtcrossings()
}
// Check for, and color in triangle clashes
function crossings() {
for(let t of consts.triangles) {
t.crossed = t.embedded = false
}
for(let i = 0; i < consts.triangles.length-1; ++i) {
let a = consts.triangles[i]
for(let j = i+1; j < consts.triangles.length; ++j) {
let b = consts.triangles[j]
if(a.triangle_cross(b)) {
a.crossed = b.crossed = true
}
else if(a.triangle_within(b)) {
b.embedded = true
}
}
}
for(let t of consts.triangles) {
t.render()
t.move()
}
}
// Implement the quad tree for detecting embedded triangles
function qtcrossings() {
let QT = new QuadTree(consts.root_boundary)
for(let t of consts.triangles) {
t.crossed = t.embedded = t.outer = false
QT.insert(new Shape(t, t.circumcenter))
}
for(let t of consts.triangles) {
// For embedded triangles we only need to search within
// the enclosing circle
let search_radius = t.circumradius
// let search_radius = consts.crmax;
let nearby = new Boundary(
new VPoint( t.circumcenter.x - search_radius,
t.circumcenter.y + search_radius ),
new VPoint( t.circumcenter.x + search_radius,
t.circumcenter.y - search_radius ))
let neighbors = QT.query(nearby)
for(let neighbor of neighbors) {
if(neighbor.shape == t) {
break
}
/*
if(t.triangle_cross(neighbor.shape)) {
t.crossed = true
neighbor.shape.crossed = true
} else
*/
if(t.triangle_within(neighbor.shape)) {
neighbor.shape.embedded = true
t.outer = true
}
}
}
for(let t of consts.triangles) {
t.render()
t.move()
}
}
// Get a random triangle of size, shape and position
function create_triangle() {
// Circle containing the triangle
let radius = random(consts.crmin, consts.crmax)
let circumcenter = new VPoint(
random(-consts.half_w, consts.half_w),
random(-consts.half_h, consts.half_h) )
// Generate 3 points on the circle
let angA = 0*PI + random(19/30*PI)
let A = new VPoint(cos(angA), sin(angA))
.scale(radius) .add(circumcenter)
let angB = 2/3*PI + random(19/30*PI)
let B = new VPoint(cos(angB), sin(angB))
.scale(radius) .add(circumcenter)
let angC = 4/3*PI + random(19/30*PI)
let C = new VPoint(cos(angC), sin(angC))
.scale(radius) .add(circumcenter)
// Rotation increment angle
let rot_ang = random(-consts.rotation_speed, consts.rotation_speed)
// Rotation increment unit vector
let Ui = new VPoint(cos(rot_ang), sin(rot_ang))
// Translation increment
let Ti = new VPoint(
random(-consts.translation_speed, consts.translation_speed),
random(-consts.translation_speed, consts.translation_speed)
)
return new FloatingTriangle(A, B, C, circumcenter,
radius, Ui, Ti)
}
class FloatingTriangle extends Triangle {
constructor(A, B, C, circumcenter, circumradius,
rotation_increment, translation_increment ) {
super(A, B, C)
this.circumcenter = circumcenter
this.circumradius = circumradius
this.rot_i = rotation_increment
this.mov_i = translation_increment
this.crossed = false
this.embedded = false
this.outer = false
}
// Draws the current triangle
render() {
let t = this
if (t.embedded) fill(255,255,0,150)
else if(t.outer) fill(255,255,255,60)
else if(t.crossed) fill(200,100)
else noFill()
triangle(consts.half_w + t.A.x, consts.half_h - t.A.y,
consts.half_w + t.B.x, consts.half_h - t.B.y,
consts.half_w + t.C.x, consts.half_h - t.C.y )
}
// Wraps moving triangle around the canvas
wrap(axis) {
let extent = (axis == 'x') ? width : height
let bound = (axis == 'x') ? consts.half_w : consts.half_h
if(this.circumcenter [axis] > bound) {
for(let k of ['A','B','C','circumcenter'])
this[k][axis] -= extent
}
else if(this.circumcenter [axis] < -bound) {
for(let k of ['A','B','C','circumcenter'])
this[k][axis] += extent
}
}
// Move by the translation increment
move() {
let t = this
// Rotate triangle about its circumcenter, then move
let A = t.A .subtract(t.circumcenter)
.rotate(t.rot_i) .add(t.circumcenter) .add(t.mov_i)
let B = t.B .subtract(t.circumcenter)
.rotate(t.rot_i) .add(t.circumcenter) .add(t.mov_i)
let C = t.C .subtract(t.circumcenter)
.rotate(t.rot_i) .add(t.circumcenter) .add(t.mov_i)
t.assign(A, B, C)
t.circumcenter = t.circumcenter .add(t.mov_i)
t.wrap('x')
t.wrap('y')
}
}