Chooses a round starting size for a new curve or mesh from what the view shows, and checks that a voxel remesh is not too fine.
How the precision is kept
The starting size is a fifth of the view's height rounded to 1, 2 or 5 times a power of ten. The remesh takes the voxel size the person types and counts the grid cells it would need before starting. All 64-bit.
Calculations under this policy
4 calculations in 2 source files. The code is read from the released app when this page loads. It is the calculation people run, not a copy kept for this page.
Rounds a size to 1, 2, 5 or 10 times a power of ten.
p = 10^⌊log₁₀ x⌋; m = x ÷ p; result = (1 if m < 1.5, 2 if m < 3.5, 5 if m < 7.5, else 10) × p
If Math.log10 returns a value just under a whole number for an exact power of ten, m comes out as 10 and the result is still that power of ten. A size that is not above zero returns 1.
ws-curve.js
lines 148 to 152
ModelCraft 0.8.1
function niceSize(x) {
if (!(x > 0)) return 1;
const p = 10 ** Math.floor(Math.log10(x)), m = x / p;
return (m < 1.5 ? 1 : m < 3.5 ? 2 : m < 7.5 ? 5 : 10) * p;
}
Text as a curve object
64-bit
The letters' outlines as closed flat splines, filled and given a thickness.
extrude = height × 0.05; each outline point [x, y] becomes a spline point [x, y, 0]
The outline points are taken from the library's toPolygons as they come, without rounding (the 3D text tool rounds the same outlines to 1e-6). The thickness is a fixed twentieth of the height.
ws-curve.js
lines 153 to 163
ModelCraft 0.8.1
/** Text as a curve object: the letters' outlines (our single-stroke font given a pen width) as closed flat splines, filled. */
export async function textCurve(host, str, height, weight = 0.14) {
let M, T;
try { host.print(host.t('app.text3d.loading')); [T, M] = await Promise.all([import('./text3d.js'), import('./solids.js').then((L) => L.manifold())]); }
catch (e) { host.print(host.t('app.curve.text.failed')); return null; }
const cs = T.textOutlines(M, str, { height, weight }), loops = cs.toPolygons();
cs.delete?.();
if (!loops.length) { host.print(host.t('app.curve.text.empty')); return null; }
const splines = loops.map((L) => ({ type: 'poly', cyclic: true, resolution: 1, order: 4, points: L.map(([x, y]) => ({ p: [x, y, 0], hl: [x, y, 0], hr: [x, y, 0], h: 'vector', w: 1, radius: 1, tilt: 0 })) }));
return { dim: '2d', fill: true, extrude: height * 0.05, bevel: { depth: 0, resolution: 2 }, caps: true, taper: [1], splines, text: { string: str, height, weight } };
}
The voxel size is the typed length as parsed by the units module. The count is a product of three whole numbers and is compared with 24 000 000; above that the remesh is refused and a coarser size is suggested.