source-academy/modules

[CSG]: Infinite loop bug

Opened this issue · 0 comments

CSG sometimes seemingly gets stuck in an infinite loop. I suspect this is caused by unioning shapes with barely touching polygons (happens when working with spheres but not cubes). There may be some relation to floating point error that remains consistent between runs (changing the structure of the program while theoretically keeping the intended render the same, such as by abstracting a function or creating another shape that never gets rendered, changes whether it gets stuck).

Here is an example snippet. It's modified from #292 (no longer does what was originally intended):

import { union, render_grid_axes, sphere, scale, translate, empty_shape } from 'csg';

function beside(s1, s2) {
    return union(scale(s1, 0.5, 1, 1),
                 translate(scale(s2, 0.5, 1, 1),
                           0.5, 0, 0));
}
function beside_frac(f, s1, s2) {
    return union(scale(s1, f, 1, 1),
                 translate(scale(s2, 1 - f, 1, 1),
                           f, 0, 0));
}
function before(s1, s2) {
    return union(scale(s1, 1, 0.5, 1),
                 translate(scale(s2, 1, 0.5, 1),
                           0, 0.5, 0));
}
function before_frac(f, s1, s2) {
    return union(scale(s1, 1, f, 1),
                 translate(scale(s2, 1, 1 - f, 1),
                           0, f, 0));
}

function below(s1, s2) {
    return union(scale(s1, 1, 1, 0.5),
                 translate(scale(s2, 1, 1, 0.5),
                           0, 0, 0.5));
}
function below_frac(f, s1, s2) {
    return union(scale(s1, 1, 1, f),
                 translate(scale(s2, 1, 1, 1 - f),
                           0, 0, f));
}

const c = sphere('#88ccff');
const empty = empty_shape();

function mosely(s) {
    const f = 1 / 3;
    const outer_row = before_frac(f, empty,
                           before(s, empty));
    const inner_row = before_frac(f, s,
                           before(s, s));
    //const outer_layer = beside_frac(f, outer_row,
    //                         beside(inner_row,
    //                                outer_row));
    const center_row = before_frac(f, 
                           inner_row,
                           before(empty, 
                             inner_row));
    const inner_layer = beside_frac(f, 
                             inner_row,
                             beside(center_row,
                                inner_row));
    return inner_layer;
}  

render_grid_axes(mosely(c));

The snippet as it is will be able to render, but if I uncomment the outer_layer shape (that never gets used for rendering), then it gets stuck.

However, if I then keep outer_layer but move the contents of the function out, the program no longer gets stuck (so it doesn't seem creating outer_layer is causing it):

const s = sphere('#88ccff');
const empty = empty_shape();

const f = 1 / 3;
const outer_row = before_frac(f, empty,
                       before(s, empty));
const inner_row = before_frac(f, s,
                       before(s, s));
const outer_layer = beside_frac(f, outer_row,
                         beside(inner_row,
                                outer_row));
const center_row = before_frac(f, 
                       inner_row,
                       before(empty, 
                         inner_row));
const inner_layer = beside_frac(f, 
                         inner_row,
                         beside(center_row,
                            inner_row));

render_grid_axes(inner_layer);

When the program gets stuck, there is this error in the console (may just be generic when any program does so):

main.cffef817.js:2 TypeError: Cannot set properties of undefined (setting 'state')
    at eval (eval at <anonymous> (eval at <anonymous> (main.cffef817.js:65:41813)), <anonymous>:13944:51)
    at eval (eval at <anonymous> (eval at <anonymous> (main.cffef817.js:65:41813)), <anonymous>:13947:3)
    at eval (eval at <anonymous> (main.cffef817.js:65:41813), <anonymous>:3:26)
    at main.cffef817.js:65:41911
    at Generator.next (<anonymous>)
    at o (main.cffef817.js:65:37563)

See also: