From fb6b8aa33cbbe0d46d858c192f43b036f8b291ab Mon Sep 17 00:00:00 2001 From: root <> Date: Thu, 24 Apr 2025 12:39:51 +0000 Subject: [PATCH 01/10] adjust constant --- sketch.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sketch.js b/sketch.js index 362e59f..e89068d 100644 --- a/sketch.js +++ b/sketch.js @@ -35,7 +35,7 @@ function move_charges() { charges[i].position, charges[j].position, ); - const acceleration_mag = 1 / displacement.mag() * 0.005; + const acceleration_mag = 1 / displacement.mag() * 0.001; let ai = displacement.copy().normalize().mult(acceleration_mag); let aj = p5.Vector.mult(ai, -1); project_onto_plane(ai, charges[i].position); From 6cbdb04786b381c948abd4f6b82d802f9de373b7 Mon Sep 17 00:00:00 2001 From: root <> Date: Fri, 25 Apr 2025 08:56:49 +0000 Subject: [PATCH 02/10] move charge repelling stuff to its own file --- index.html | 1 + sketch.js | 42 +----------------------------------------- thomson-problem.js | 44 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 41 deletions(-) create mode 100644 thomson-problem.js diff --git a/index.html b/index.html index cf15339..6129f5f 100644 --- a/index.html +++ b/index.html @@ -16,6 +16,7 @@ body {
+ diff --git a/sketch.js b/sketch.js index e89068d..cf036fc 100644 --- a/sketch.js +++ b/sketch.js @@ -19,52 +19,12 @@ function draw() { make_lights(); if (physics) { - move_charges(); + move_charges(charges); } draw_charges(sphere_radius); draw_sphere(sphere_radius, 25); } -function move_charges() { - for (charge of charges) { - charge.acceleration.setMag(0); - } - for (let i = 0; i < charges.length; i += 1) { - for (let j = 0; j < i; j += 1) { - const displacement = p5.Vector.sub( - charges[i].position, - charges[j].position, - ); - const acceleration_mag = 1 / displacement.mag() * 0.001; - let ai = displacement.copy().normalize().mult(acceleration_mag); - let aj = p5.Vector.mult(ai, -1); - project_onto_plane(ai, charges[i].position); - project_onto_plane(aj, charges[j].position); - charges[i].acceleration.add(ai); - charges[j].acceleration.add(aj); - } - } - for (let i = 0; i < charges.length; i += 1) { - let charge = charges[i]; - charge.velocity = charge.velocity.add(charge.acceleration); - //project_onto_plane(charge.velocity, charge.position); - charge.position = charge.position.add(charge.velocity); - charge.position.normalize(); - } -} - -function project_onto_unit_vector(v, unit_vector) { - let size = p5.Vector.dot(v, unit_vector); - return p5.Vector.mult(unit_vector, size); -} - -/// Project `v` onto the plane normal to `unit_vector` -/// Mutates `v` -function project_onto_plane(v, unit_vector) { - let v_proj = project_onto_unit_vector(v, unit_vector); - v.sub(v_proj) -} - function make_charges(n) { charges = []; for (let i = 0; i < n; i += 1) { diff --git a/thomson-problem.js b/thomson-problem.js new file mode 100644 index 0000000..0cbbdaa --- /dev/null +++ b/thomson-problem.js @@ -0,0 +1,44 @@ +function move_charges(charges) { + for (charge of charges) { + charge.acceleration.setMag(0); + } + for (let i = 0; i < charges.length; i += 1) { + for (let j = 0; j < i; j += 1) { + const displacement = p5.Vector.sub( + charges[i].position, + charges[j].position, + ); + let acceleration_mag = 1 / displacement.mag() * 0.001; + let ai; + if (acceleration_mag === Infinity) { + ai = createVector(random(-1, 1), random(-1, 1), random(-1, 1)); + } else { + ai = displacement.copy(); + } + ai = ai.normalize().mult(acceleration_mag); + let aj = p5.Vector.mult(ai, -1); + project_onto_plane(ai, charges[i].position); + project_onto_plane(aj, charges[j].position); + charges[i].acceleration.add(ai); + charges[j].acceleration.add(aj); + } + } + for (let i = 0; i < charges.length; i += 1) { + let charge = charges[i]; + charge.velocity = charge.velocity.add(charge.acceleration); + charge.position = charge.position.add(charge.velocity); + charge.position.normalize(); + } +} + +function project_onto_unit_vector(v, unit_vector) { + let size = p5.Vector.dot(v, unit_vector); + return p5.Vector.mult(unit_vector, size); +} + +/// Project `v` onto the plane normal to `unit_vector` +/// Mutates `v` +function project_onto_plane(v, unit_vector) { + let v_proj = project_onto_unit_vector(v, unit_vector); + v.sub(v_proj) +} From c20044c4598e99f095fc56cfb7711d24794f54a9 Mon Sep 17 00:00:00 2001 From: root <> Date: Fri, 25 Apr 2025 08:58:35 +0000 Subject: [PATCH 03/10] skeleton --- sketch.js | 43 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/sketch.js b/sketch.js index cf036fc..65842a6 100644 --- a/sketch.js +++ b/sketch.js @@ -1,12 +1,13 @@ let charges = []; -let sphere_mode = 'circles'; let sphere_radius = 200; let physics = false; +let earth = false; +let skeleton = false; function preload() { - earth = loadImage("atlas1.jpg"); + earth_image = loadImage("atlas1.jpg"); } function setup() { @@ -21,10 +22,32 @@ function draw() { if (physics) { move_charges(charges); } + if (skeleton) { + draw_skeleton(sphere_radius); + } draw_charges(sphere_radius); draw_sphere(sphere_radius, 25); } +function draw_skeleton(radius) { + push(); + noStroke(); + fill(0xff); + sphere(4); + stroke(0xbf); + for (let charge of charges) { + line( + 0, + 0, + 0, + charge.position.x * radius, + charge.position.y * radius, + charge.position.z * radius, + ); + } + pop(); +} + function make_charges(n) { charges = []; for (let i = 0; i < n; i += 1) { @@ -71,7 +94,7 @@ function draw_sphere(radius, n_axis_circles) { rotateX(TAU / 4); draw_circles( radius, - sphere_mode === 'earth' ? 2 : n_axis_circles, + earth ? 2 : n_axis_circles, color(0x00, 0x9f, 0xff), color(0xff, 0x9f, 0x00), ); @@ -80,17 +103,17 @@ function draw_sphere(radius, n_axis_circles) { rotateY(TAU / 4); draw_circles( radius, - sphere_mode === 'earth' ? 2 : n_axis_circles, + earth ? 2 : n_axis_circles, color(0xff, 0x00, 0xff), color(0x00, 0xff, 0x00), ); pop(); - if (sphere_mode === 'earth') { + if (earth) { noStroke(); noFill(); tint(0xff, 0x9f); - texture(earth); + texture(earth_image); push(); rotateY(TAU / 4); sphere(radius); @@ -127,10 +150,12 @@ function make_lights() { } function keyPressed() { - if (key == 'd') { - sphere_mode = sphere_mode === 'earth' ? 'circles' : 'earth'; - } else if (key == ' ') { + if (key == ' ') { physics = !physics; + } else if (key == 'd') { + earth = !earth; + } else if (key == 'f') { + skeleton = !skeleton; } else if (key >= '0' && key <= '9') { make_charges(int(key)); } From 620896fb49506ae8357c9f9048d73808eebed4bc Mon Sep 17 00:00:00 2001 From: root <> Date: Fri, 25 Apr 2025 14:47:03 +0000 Subject: [PATCH 04/10] begin drawing faces --- sketch.js | 50 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/sketch.js b/sketch.js index 65842a6..479ebf8 100644 --- a/sketch.js +++ b/sketch.js @@ -5,6 +5,10 @@ let sphere_radius = 200; let physics = false; let earth = false; let skeleton = false; +let planes = false; + +let red; +let yellow; function preload() { earth_image = loadImage("atlas1.jpg"); @@ -12,6 +16,8 @@ function preload() { function setup() { createCanvas(600, 600, WEBGL); + red = color(0xbf, 0x00, 0x00); + yellow = color(0xff, 0xff, 0x00); } function draw() { @@ -25,6 +31,41 @@ function draw() { if (skeleton) { draw_skeleton(sphere_radius); } + + if (planes) { + let p = charges[0]; + let a = charges[1]; + let b = charges[2]; + p.color = yellow; + a.color = yellow; + b.color = yellow; + let n = p5.Vector.sub(p.position, a.position).cross(p5.Vector.sub(p.position, b.position)); + n.normalize(); // unnecessary + push(); + strokeWeight(5); + stroke(0x7f); + line( + 0,0,0, + n.x*sphere_radius,n.y*sphere_radius,n.z*sphere_radius, + ) + fill(0xff); + strokeWeight(3); + stroke(0x00); + beginShape(TRIANGLES); + const v1 = p5.Vector.mult(p.position, sphere_radius); + const v2 = p5.Vector.mult(a.position, sphere_radius); + const v3 = p5.Vector.mult(b.position, sphere_radius); + vertex(v1.x, v1.y, v1.z); + vertex(v2.x, v2.y, v2.z); + vertex(v3.x, v3.y, v3.z); + endShape(); + pop(); + } else { + for (let charge of charges) { + charge.color = red; + } + } + draw_charges(sphere_radius); draw_sphere(sphere_radius, 25); } @@ -67,6 +108,7 @@ function make_charges(n) { position: position, velocity: createVector(), acceleration: createVector(), + color: red, }); } } @@ -74,8 +116,8 @@ function make_charges(n) { function draw_charges(radius) { push(); noStroke(); - ambientMaterial(0xbf, 0x00, 0x00); for (let charge of charges.values()) { + ambientMaterial(charge.color); let position = charge.position.copy(); position.mult(radius); push(); @@ -156,7 +198,13 @@ function keyPressed() { earth = !earth; } else if (key == 'f') { skeleton = !skeleton; + } else if (key == 'g') { + planes = !planes; } else if (key >= '0' && key <= '9') { make_charges(int(key)); } } + +// TODO draw faces +// algorithm: choose 3 vertices until 2-partition of other vertices has one empty set +// done when V - E + F = 2. V is known. count E and F while creating faces From 838eae2cbf198548d4e6c37865badac8dd25c440 Mon Sep 17 00:00:00 2001 From: root <> Date: Fri, 25 Apr 2025 14:59:51 +0000 Subject: [PATCH 05/10] polyhedron alg progress: face separates vertices the algorithm so far: - select 3 vertices - draw a triangle between them - for all vertex pairs (non-triangle vertices): -- draw a line between them -- if line intersects with triangle plane, red -- otherwise, green if the line is red the two vertices are on other sides of the triangle plane, and this triangle can't be a face, because we want the polyhedron to be convex to demo: press 9, press g, press space; press 9 over and over --- sketch.js | 51 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/sketch.js b/sketch.js index 479ebf8..f97897e 100644 --- a/sketch.js +++ b/sketch.js @@ -33,33 +33,60 @@ function draw() { } if (planes) { - let p = charges[0]; - let a = charges[1]; - let b = charges[2]; - p.color = yellow; - a.color = yellow; - b.color = yellow; - let n = p5.Vector.sub(p.position, a.position).cross(p5.Vector.sub(p.position, b.position)); + let p_charge = charges[0]; + let a_charge = charges[1]; + let b_charge = charges[2]; + p_charge.color = yellow; + a_charge.color = yellow; + b_charge.color = yellow; + let p = p_charge.position; + let a = a_charge.position; + let b = b_charge.position; + let n = p5.Vector.sub(p, a).cross(p5.Vector.sub(p, b)); n.normalize(); // unnecessary push(); strokeWeight(5); stroke(0x7f); line( - 0,0,0, - n.x*sphere_radius,n.y*sphere_radius,n.z*sphere_radius, + 0, 0, 0, + n.x * sphere_radius, n.y * sphere_radius, n.z * sphere_radius, ) fill(0xff); strokeWeight(3); stroke(0x00); beginShape(TRIANGLES); - const v1 = p5.Vector.mult(p.position, sphere_radius); - const v2 = p5.Vector.mult(a.position, sphere_radius); - const v3 = p5.Vector.mult(b.position, sphere_radius); + const v1 = p5.Vector.mult(p, sphere_radius); + const v2 = p5.Vector.mult(a, sphere_radius); + const v3 = p5.Vector.mult(b, sphere_radius); vertex(v1.x, v1.y, v1.z); vertex(v2.x, v2.y, v2.z); vertex(v3.x, v3.y, v3.z); endShape(); pop(); + for (let i = 4; i < charges.length; i += 1) { + for (let j = 3; j < i; j += 1) { + push(); + const u = charges[i].position; + const v = charges[j].position; + const t = p5.Vector.dot(p5.Vector.sub(p, u), n) / p5.Vector.dot(p5.Vector.sub(v, u), n); + const intersects_plane = t >= 0 && t <= 1; + if (intersects_plane) { + stroke(0xff, 0x1f, 0x00); + } else { + stroke(0x00, 0xff, 0x00); + } + strokeWeight(3); + line( + charges[i].position.x * sphere_radius, + charges[i].position.y * sphere_radius, + charges[i].position.z * sphere_radius, + charges[j].position.x * sphere_radius, + charges[j].position.y * sphere_radius, + charges[j].position.z * sphere_radius, + ); + pop(); + } + } } else { for (let charge of charges) { charge.color = red; From cec27160f4e75883f5353ebf273f3b092b6609a4 Mon Sep 17 00:00:00 2001 From: root <> Date: Fri, 25 Apr 2025 17:14:31 +0000 Subject: [PATCH 06/10] convex polyhedron --- sketch.js | 149 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 83 insertions(+), 66 deletions(-) diff --git a/sketch.js b/sketch.js index f97897e..db98094 100644 --- a/sketch.js +++ b/sketch.js @@ -1,3 +1,6 @@ +let camera; +let red; + let charges = []; let sphere_radius = 200; @@ -7,8 +10,6 @@ let earth = false; let skeleton = false; let planes = false; -let red; -let yellow; function preload() { earth_image = loadImage("atlas1.jpg"); @@ -16,8 +17,8 @@ function preload() { function setup() { createCanvas(600, 600, WEBGL); + camera = createCamera(); red = color(0xbf, 0x00, 0x00); - yellow = color(0xff, 0xff, 0x00); } function draw() { @@ -25,76 +26,92 @@ function draw() { background(50); make_lights(); - if (physics) { - move_charges(charges); - } - if (skeleton) { - draw_skeleton(sphere_radius); - } + if (physics) move_charges(charges); - if (planes) { - let p_charge = charges[0]; - let a_charge = charges[1]; - let b_charge = charges[2]; - p_charge.color = yellow; - a_charge.color = yellow; - b_charge.color = yellow; - let p = p_charge.position; - let a = a_charge.position; - let b = b_charge.position; - let n = p5.Vector.sub(p, a).cross(p5.Vector.sub(p, b)); - n.normalize(); // unnecessary - push(); - strokeWeight(5); - stroke(0x7f); - line( - 0, 0, 0, - n.x * sphere_radius, n.y * sphere_radius, n.z * sphere_radius, - ) - fill(0xff); - strokeWeight(3); - stroke(0x00); + draw_charges(sphere_radius); + draw_sphere(sphere_radius, 25); + if (skeleton) draw_skeleton(sphere_radius); + if (planes) draw_planes(sphere_radius); +} + +function face_dist_sq([v1, v2, v3]) { + const center = p5.Vector.add(v1, v2).add(v3).mult(1 / 3); + return createVector(camera.eyeX, camera.eyeY, camera.eyeZ).sub(center).magSq(); +}; + +function draw_planes(radius) { + let faces = []; + for (let i = 2; i < charges.length; i += 1) { + for (let j = 1; j < i; j += 1) { + for (let k = 0; k < j; k += 1) { + // Check if p1 p2 p3 form a face of the convex polyhedron + // enclosing all vertices ... + const p1 = charges[i].position; + const p2 = charges[j].position; + const p3 = charges[k].position; + const normal = p5.Vector.sub(p2, p1).cross(p5.Vector.sub(p3, p1)); + // ... by checking if the other vertices are on the same + // side of the plane generated by p1 p2 p3 + let plane_separates_vertices = false; + for (let r = 1; r < charges.length; r += 1) { + for (let s = 0; s < r; s += 1) { + if ( + r === i || r === j || r === k || + s === i || s === j || s === k + ) continue; + const q1 = charges[r].position; + const q2 = charges[s].position; + // Let l(t) := q1 + (q2 - q1) * t. + // L := { l(t) : 0 <= t <= 1 } is the line segment + // between q1 and q2. L intersects the plane + // generated by p1 p2 p3 iff l(t) intersects with + // the plane for some 0 <= t <= 1. + // + // If L intersects the plane, q1 and q2 are on + // opposite sides of the plane generated by p1 p2 p3, + // so p1 p2 p3 can't be a face. If we want the + // polyhedron to be convex. Which we do. + // + // A point k is on the plane generated by p1 p2 p3 iff + // dot(k - p1, normal) = 0. Let n := normal. + // + // dot(l(t) - p1, n) = 0 + // iff dot(q1 + (q2 - q1) * t - p1, n) = 0 + // iff dot(q1 - p1, n) + dot(q2 - q2, n) * t = 0 + // iff t = dot(p1 - q1, n) / dot(q2 - q2, n) + const t = ( + p5.Vector.dot(p5.Vector.sub(p1, q1), normal) / + p5.Vector.dot(p5.Vector.sub(q2, q1), normal) + ); + plane_separates_vertices ||= t >= 0 && t <= 1; + if (plane_separates_vertices) break; + } + if (plane_separates_vertices) break; + } + if (!plane_separates_vertices) { + faces.push([ + p5.Vector.mult(p1, radius), + p5.Vector.mult(p2, radius), + p5.Vector.mult(p3, radius), + ]); + } + } + } + } + // fix OpenGL stacking alpha behaviour + faces.sort((a, b) => face_dist_sq(b) - face_dist_sq(a)); + push(); + strokeWeight(2); + stroke(0x00); + for ([v1, v2, v3] of faces) { + fill(0xbf, 0x7f); beginShape(TRIANGLES); - const v1 = p5.Vector.mult(p, sphere_radius); - const v2 = p5.Vector.mult(a, sphere_radius); - const v3 = p5.Vector.mult(b, sphere_radius); vertex(v1.x, v1.y, v1.z); vertex(v2.x, v2.y, v2.z); vertex(v3.x, v3.y, v3.z); endShape(); - pop(); - for (let i = 4; i < charges.length; i += 1) { - for (let j = 3; j < i; j += 1) { - push(); - const u = charges[i].position; - const v = charges[j].position; - const t = p5.Vector.dot(p5.Vector.sub(p, u), n) / p5.Vector.dot(p5.Vector.sub(v, u), n); - const intersects_plane = t >= 0 && t <= 1; - if (intersects_plane) { - stroke(0xff, 0x1f, 0x00); - } else { - stroke(0x00, 0xff, 0x00); - } - strokeWeight(3); - line( - charges[i].position.x * sphere_radius, - charges[i].position.y * sphere_radius, - charges[i].position.z * sphere_radius, - charges[j].position.x * sphere_radius, - charges[j].position.y * sphere_radius, - charges[j].position.z * sphere_radius, - ); - pop(); - } - } - } else { - for (let charge of charges) { - charge.color = red; - } } - - draw_charges(sphere_radius); - draw_sphere(sphere_radius, 25); + pop(); } function draw_skeleton(radius) { From 34e1de68f1913d0c737aa2589b4981c78c556c3a Mon Sep 17 00:00:00 2001 From: root <> Date: Sat, 26 Apr 2025 04:08:10 +0000 Subject: [PATCH 07/10] hide sphere; euler's forumla trick; cache faces --- sketch.js | 68 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 45 insertions(+), 23 deletions(-) diff --git a/sketch.js b/sketch.js index db98094..1d684e6 100644 --- a/sketch.js +++ b/sketch.js @@ -2,13 +2,18 @@ let camera; let red; let charges = []; +let faces = []; let sphere_radius = 200; +const SURFACE_NONE = 0; +const SURFACE_CIRCLES = 1; +const SURFACE_EARTH = 2; + +let surface = SURFACE_CIRCLES; let physics = false; -let earth = false; let skeleton = false; -let planes = false; +let polyhedron = false; function preload() { @@ -16,11 +21,15 @@ function preload() { } function setup() { - createCanvas(600, 600, WEBGL); + createCanvas(windowWidth, windowHeight, WEBGL); camera = createCamera(); red = color(0xbf, 0x00, 0x00); } +function windowResized() { + resizeCanvas(windowWidth, windowHeight); +} + function draw() { orbitControl(); background(50); @@ -29,9 +38,12 @@ function draw() { if (physics) move_charges(charges); draw_charges(sphere_radius); - draw_sphere(sphere_radius, 25); if (skeleton) draw_skeleton(sphere_radius); - if (planes) draw_planes(sphere_radius); + if (polyhedron) { + if (physics || faces.length === 0) find_faces(); + draw_faces(sphere_radius); + } + draw_sphere(sphere_radius, 25); } function face_dist_sq([v1, v2, v3]) { @@ -39,8 +51,8 @@ function face_dist_sq([v1, v2, v3]) { return createVector(camera.eyeX, camera.eyeY, camera.eyeZ).sub(center).magSq(); }; -function draw_planes(radius) { - let faces = []; +function find_faces() { + faces = []; for (let i = 2; i < charges.length; i += 1) { for (let j = 1; j < i; j += 1) { for (let k = 0; k < j; k += 1) { @@ -53,6 +65,7 @@ function draw_planes(radius) { // ... by checking if the other vertices are on the same // side of the plane generated by p1 p2 p3 let plane_separates_vertices = false; + let euler_formula = false; for (let r = 1; r < charges.length; r += 1) { for (let s = 0; s < r; s += 1) { if ( @@ -85,30 +98,32 @@ function draw_planes(radius) { ); plane_separates_vertices ||= t >= 0 && t <= 1; if (plane_separates_vertices) break; + euler_formula ||= charges.length * 2 - faces.length == 4; + if (euler_formula) break; } - if (plane_separates_vertices) break; + if (plane_separates_vertices || euler_formula) break; } + if (euler_formula) return; if (!plane_separates_vertices) { - faces.push([ - p5.Vector.mult(p1, radius), - p5.Vector.mult(p2, radius), - p5.Vector.mult(p3, radius), - ]); + faces.push([p1, p2, p3]); } } } } +} + +function draw_faces(radius) { // fix OpenGL stacking alpha behaviour faces.sort((a, b) => face_dist_sq(b) - face_dist_sq(a)); push(); strokeWeight(2); stroke(0x00); - for ([v1, v2, v3] of faces) { + for ([p1, p2, p3] of faces) { fill(0xbf, 0x7f); beginShape(TRIANGLES); - vertex(v1.x, v1.y, v1.z); - vertex(v2.x, v2.y, v2.z); - vertex(v3.x, v3.y, v3.z); + vertex(p1.x * radius, p1.y * radius, p1.z * radius); + vertex(p2.x * radius, p2.y * radius, p2.z * radius); + vertex(p3.x * radius, p3.y * radius, p3.z * radius); endShape(); } pop(); @@ -176,11 +191,14 @@ function draw_sphere(radius, n_axis_circles) { stroke(0x3f); noFill(); + if (surface === SURFACE_NONE) n_axis_circles = 0; + else if (surface === SURFACE_EARTH) n_axis_circles = 2; + push(); rotateX(TAU / 4); draw_circles( radius, - earth ? 2 : n_axis_circles, + n_axis_circles, color(0x00, 0x9f, 0xff), color(0xff, 0x9f, 0x00), ); @@ -189,13 +207,13 @@ function draw_sphere(radius, n_axis_circles) { rotateY(TAU / 4); draw_circles( radius, - earth ? 2 : n_axis_circles, + n_axis_circles, color(0xff, 0x00, 0xff), color(0x00, 0xff, 0x00), ); pop(); - if (earth) { + if (surface === SURFACE_EARTH) { noStroke(); noFill(); tint(0xff, 0x9f); @@ -239,16 +257,20 @@ function keyPressed() { if (key == ' ') { physics = !physics; } else if (key == 'd') { - earth = !earth; + surface = (surface + 1) % 3; } else if (key == 'f') { skeleton = !skeleton; } else if (key == 'g') { - planes = !planes; + polyhedron = !polyhedron; } else if (key >= '0' && key <= '9') { - make_charges(int(key)); + make_charges(Math.pow(int(key), 2)); + faces = []; } } // TODO draw faces // algorithm: choose 3 vertices until 2-partition of other vertices has one empty set // done when V - E + F = 2. V is known. count E and F while creating faces +// when the graph is finished: E = F * 3 / 2 +// V - E + F = V - F * 3 / 2 + F = V - F / 2 +// V * 2 - F = 4 From d0be92d50ecd336643879a793964a178edb8f01a Mon Sep 17 00:00:00 2001 From: root <> Date: Sat, 26 Apr 2025 04:12:55 +0000 Subject: [PATCH 08/10] charges should not have earth texture, lol --- sketch.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sketch.js b/sketch.js index 1d684e6..cbc9252 100644 --- a/sketch.js +++ b/sketch.js @@ -214,11 +214,11 @@ function draw_sphere(radius, n_axis_circles) { pop(); if (surface === SURFACE_EARTH) { + push(); noStroke(); noFill(); tint(0xff, 0x9f); texture(earth_image); - push(); rotateY(TAU / 4); sphere(radius); pop(); From e51d5df1dc684062d4b23ff59fdfce1e11d155f3 Mon Sep 17 00:00:00 2001 From: root <> Date: Sat, 26 Apr 2025 04:15:57 +0000 Subject: [PATCH 09/10] cleanup --- sketch.js | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/sketch.js b/sketch.js index cbc9252..1d3cb0a 100644 --- a/sketch.js +++ b/sketch.js @@ -263,14 +263,7 @@ function keyPressed() { } else if (key == 'g') { polyhedron = !polyhedron; } else if (key >= '0' && key <= '9') { - make_charges(Math.pow(int(key), 2)); + make_charges(int(key)); faces = []; } } - -// TODO draw faces -// algorithm: choose 3 vertices until 2-partition of other vertices has one empty set -// done when V - E + F = 2. V is known. count E and F while creating faces -// when the graph is finished: E = F * 3 / 2 -// V - E + F = V - F * 3 / 2 + F = V - F / 2 -// V * 2 - F = 4 From eeb1beaea3d8ade3e5c835df68973bcaac7cf34a Mon Sep 17 00:00:00 2001 From: root <> Date: Sat, 26 Apr 2025 04:20:00 +0000 Subject: [PATCH 10/10] fix: firefox scrollbar --- index.html | 1 + 1 file changed, 1 insertion(+) diff --git a/index.html b/index.html index 6129f5f..ff66bc9 100644 --- a/index.html +++ b/index.html @@ -10,6 +10,7 @@ body { padding: 0; margin: 0; background-color: #1b1b1b; + overflow-y: hidden; }