Address review comments A bit more comment, but also a more robust protection against a divide by zero, which happens in the colinear double-cusp case, as exercised by tricky-strokes.
diff --git a/shader/flatten.wgsl b/shader/flatten.wgsl index 0998cc9..6ee46b3 100644 --- a/shader/flatten.wgsl +++ b/shader/flatten.wgsl
@@ -96,8 +96,8 @@ if cth0 * cth1 < 0.0 { return 2.0; } - let e0 = (2. / 3.) / (1.0 + cth0); - let e1 = (2. / 3.) / (1.0 + cth1); + let e0 = (2. / 3.) / max(1.0 + cth0, 1e-9); + let e1 = (2. / 3.) / max(1.0 + cth1, 1e-9); let s0 = sin(cparams.th0); let s1 = sin(cparams.th1); let s01 = cth0 * s1 + cth1 * s0;
diff --git a/src/cpu_shader/euler.rs b/src/cpu_shader/euler.rs index 08c8edd..17c6bc9 100644 --- a/src/cpu_shader/euler.rs +++ b/src/cpu_shader/euler.rs
@@ -85,10 +85,18 @@ // Rationale: this happens when fitting a cusp or near-cusp with // a near 180 degree u-turn. The actual ES is bounded in that case. // Further subdivision won't reduce the angles if actually a cusp. + // + // A value of 2.0 represents the approximate worst case distance + // from an Euler spiral with 0 and pi tangents to the chord. It + // is not very critical; doubling the value would result in one more + // subdivision in effectively a binary search for the cusp, while too + // small a value may result in the actual error exceeding the bound. return 2.0; } - let e0 = (2. / 3.) / (1.0 + cth0); - let e1 = (2. / 3.) / (1.0 + cth1); + // Protect against divide-by-zero. This happens with a double cusp, so + // should in the general case cause subdivisions. + let e0 = (2. / 3.) / (1.0 + cth0).max(1e-9); + let e1 = (2. / 3.) / (1.0 + cth1).max(1e-9); let s0 = self.th0.sin(); let s1 = self.th1.sin(); // Note: some other versions take sin of s0 + s1 instead. Those are incorrect.