From 1e054cd0751dfadb545550948a9ab3847328f93c Mon Sep 17 00:00:00 2001 From: Lars Huttar Date: Wed, 8 Oct 2025 23:43:48 -0400 Subject: [PATCH 1/2] Attempt to animate the canonicalization process. (Also fix tiny HTML typo.) --- geo_operators.js | 60 ++++++++++++++++++++++++--------------------- polyhedronisme.html | 2 +- polyhedronisme.js | 60 ++++++++++++++++++++++++--------------------- 3 files changed, 65 insertions(+), 57 deletions(-) diff --git a/geo_operators.js b/geo_operators.js index 7fcc07d..4f7d9ac 100644 --- a/geo_operators.js +++ b/geo_operators.js @@ -88,35 +88,39 @@ const planarize = function(vertices, faces) { }; // combines above three constraint adjustments in iterative cycle -const canonicalize = function(poly, Niter) { - if (!Niter) { - Niter = 1; - } - console.log(`Canonicalizing ${poly.name}...`); - const faces = poly.faces; - const edges = poly.edges(); - let newVs = poly.vertices; - let maxChange = 1.0; // convergence tracker - for (let i = 0; i <= Niter; i++) { - const oldVs = copyVecArray(newVs); //copy vertices - newVs = tangentify(newVs, edges); - newVs = recenter(newVs, edges); - newVs = planarize(newVs, faces); - maxChange = _.max(_.map(_.zip(newVs, oldVs), - ([x, y])=>mag(sub(x, y)) - )); - if (maxChange < 1e-8) { - break; +const canonicalize = async function (poly, Niter) { + if (!Niter) { + Niter = 1; } - } - // one should now rescale, but not rescaling here makes for very interesting numerical - // instabilities that make interesting mutants on multiple applications... - // more experience will tell what to do - //newVs = rescale(newVs) - console.log(`[canonicalization done, last |deltaV|=${maxChange}]`); - const newpoly = new polyhedron(newVs, poly.faces, poly.name); - console.log("canonicalize" , newpoly); - return newpoly; + console.log(`Canonicalizing ${poly.name}...`); + const faces = poly.faces; + const edges = poly.edges(); + let newVs = poly.vertices; + let maxChange = 1.0; // convergence tracker + for (let i = 0; i <= Niter; i++) { + const oldVs = copyVecArray(newVs); //copy vertices + newVs = tangentify(newVs, edges); + newVs = recenter(newVs, edges); + newVs = planarize(newVs, faces); + maxChange = _.max(_.map(_.zip(newVs, oldVs), + ([x, y]) => mag(sub(x, y)) + )); + if (maxChange < 1e-8) { + break; + } + // update the display to show animated progress + // TODO: test and debug + drawShape(); + await scheduler.yield(); + } + // one should now rescale, but not rescaling here makes for very interesting numerical + // instabilities that make interesting mutants on multiple applications... + // more experience will tell what to do + //newVs = rescale(newVs) + console.log(`[canonicalization done, last |deltaV|=${maxChange}]`); + const newpoly = new polyhedron(newVs, poly.faces, poly.name); + console.log("canonicalize", newpoly); + return newpoly; }; // Hacky Canonicalization Algorithm diff --git a/polyhedronisme.html b/polyhedronisme.html index f588acb..fc8b55b 100644 --- a/polyhedronisme.html +++ b/polyhedronisme.html @@ -16,7 +16,7 @@

- polyHédronismev0.2.1 + polyHédronismev0.2.1

diff --git a/polyhedronisme.js b/polyhedronisme.js index b5f92ff..2739c7f 100644 --- a/polyhedronisme.js +++ b/polyhedronisme.js @@ -7055,35 +7055,39 @@ const planarize = function(vertices, faces) { }; // combines above three constraint adjustments in iterative cycle -const canonicalize = function(poly, Niter) { - if (!Niter) { - Niter = 1; - } - console.log(`Canonicalizing ${poly.name}...`); - const faces = poly.faces; - const edges = poly.edges(); - let newVs = poly.vertices; - let maxChange = 1.0; // convergence tracker - for (let i = 0; i <= Niter; i++) { - const oldVs = copyVecArray(newVs); //copy vertices - newVs = tangentify(newVs, edges); - newVs = recenter(newVs, edges); - newVs = planarize(newVs, faces); - maxChange = _.max(_.map(_.zip(newVs, oldVs), - ([x, y])=>mag(sub(x, y)) - )); - if (maxChange < 1e-8) { - break; +const canonicalize = async function (poly, Niter) { + if (!Niter) { + Niter = 1; } - } - // one should now rescale, but not rescaling here makes for very interesting numerical - // instabilities that make interesting mutants on multiple applications... - // more experience will tell what to do - //newVs = rescale(newVs) - console.log(`[canonicalization done, last |deltaV|=${maxChange}]`); - const newpoly = new polyhedron(newVs, poly.faces, poly.name); - console.log("canonicalize" , newpoly); - return newpoly; + console.log(`Canonicalizing ${poly.name}...`); + const faces = poly.faces; + const edges = poly.edges(); + let newVs = poly.vertices; + let maxChange = 1.0; // convergence tracker + for (let i = 0; i <= Niter; i++) { + const oldVs = copyVecArray(newVs); //copy vertices + newVs = tangentify(newVs, edges); + newVs = recenter(newVs, edges); + newVs = planarize(newVs, faces); + maxChange = _.max(_.map(_.zip(newVs, oldVs), + ([x, y]) => mag(sub(x, y)) + )); + if (maxChange < 1e-8) { + break; + } + // update the display to show animated progress + // TODO: test and debug + drawShape(); + await scheduler.yield(); + } + // one should now rescale, but not rescaling here makes for very interesting numerical + // instabilities that make interesting mutants on multiple applications... + // more experience will tell what to do + //newVs = rescale(newVs) + console.log(`[canonicalization done, last |deltaV|=${maxChange}]`); + const newpoly = new polyhedron(newVs, poly.faces, poly.name); + console.log("canonicalize", newpoly); + return newpoly; }; // Hacky Canonicalization Algorithm From c21d764fa4f8a142d7d63f30ed4fa2e2cbe3385a Mon Sep 17 00:00:00 2001 From: Lars Huttar Date: Thu, 9 Oct 2025 00:24:25 -0400 Subject: [PATCH 2/2] Try a way to animate canonicalization that's more likely to succeed. --- geo_operators.js | 6 +++++- polyhedronisme.js | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/geo_operators.js b/geo_operators.js index 4f7d9ac..3978098 100644 --- a/geo_operators.js +++ b/geo_operators.js @@ -108,10 +108,14 @@ const canonicalize = async function (poly, Niter) { if (maxChange < 1e-8) { break; } + + // Update the polyhedron vertices to show progress + poly.vertices = newVs; // update the display to show animated progress // TODO: test and debug drawShape(); - await scheduler.yield(); + // Yield to browser to allow display update + await new Promise(resolve => setTimeout(resolve, 0)); } // one should now rescale, but not rescaling here makes for very interesting numerical // instabilities that make interesting mutants on multiple applications... diff --git a/polyhedronisme.js b/polyhedronisme.js index 2739c7f..04defe9 100644 --- a/polyhedronisme.js +++ b/polyhedronisme.js @@ -7075,10 +7075,14 @@ const canonicalize = async function (poly, Niter) { if (maxChange < 1e-8) { break; } + + // Update the polyhedron vertices to show progress + poly.vertices = newVs; // update the display to show animated progress // TODO: test and debug drawShape(); - await scheduler.yield(); + // Yield to browser to allow display update + await new Promise(resolve => setTimeout(resolve, 0)); } // one should now rescale, but not rescaling here makes for very interesting numerical // instabilities that make interesting mutants on multiple applications...