add svg import dialog with options fixes #299

This commit is contained in:
Stewart Allen 2024-09-10 13:48:02 -04:00
commit 2239af159e
3 changed files with 49 additions and 16 deletions

View file

@ -848,17 +848,19 @@ function platformLoadFiles(files, group) {
api.function.parse(data.textDecode('utf-8'), 'gcode');
load_dec();
} else if (issvg) {
group = group || [];
let svg = load.SVG.parse(data.textDecode('utf-8'));
let ind = 0;
if (svg.length === 0) {
api.show.alert(`SVG contains no polylines`, 10);
api.show.alert(`Fonts must be converted to paths`, 10);
}
for (let v of svg) {
platformLoadWidget(group, svg[ind++], ind ? `${name}-${ind}` : name);
}
load_dec();
loadSVGDialog(opt => {
group = group || [];
let svg = load.SVG.parse(data.textDecode('utf-8'), opt);
let ind = 0;
if (svg.length === 0) {
api.show.alert(`SVG contains no polylines`, 10);
api.show.alert(`Fonts must be converted to paths`, 10);
}
for (let v of svg) {
platformLoadWidget(group, svg[ind++], ind ? `${name}-${ind}` : name);
}
load_dec();
});
}
else if (iskmz) api.settings.import_zip(data, true);
else if (isset) api.settings.import(data.textDecode('utf-8'), true);
@ -871,6 +873,30 @@ function platformLoadFiles(files, group) {
}
}
function loadSVGDialog(doit) {
const opt = {pre: [
"<div class='f-col a-center'>",
" <h3>Import SVG</h3>",
" <p class='t-just' style='width:300px;line-height:1.5em'>",
" This will create a 3D model from 2D SVG vectors.",
" Fonts must be converted to paths in an SVG editor.",
" Finer angle settings produce much larger models.",
" </p>",
" <div class='f-row t-right'><table>",
" <tr><th title='higher values results in more points. floating point values like 0.5 are accepted'>arc segments / mm</th><td><input id='svg-arcs' value='1' size='3'></td></tr>",
" <tr><th title='minimum number of segments in an arc. helps better represent small arcs'>min arc segments</th><td><input id='svg-marc' value='10' size='3'></td></tr>",
" <tr><th>nest shapes</th><td><input id='svg-nest' value='1' type='checkbox' checked></td></tr>",
" </table></div>",
"</div>"
]};
api.uc.confirm(undefined, {convert:true, cancel:false}, undefined, opt).then((ok) => {
let arcs = Math.max(0.01, parseFloat($('svg-arcs').value));
let marc = Math.max(1, parseInt($('svg-marc').value));
let soup = $('svg-nest').checked;
ok && doit({ soup, resolution: arcs, segmin: marc });
});
}
function fitDeviceToWidgets() {
let maxy = 0;
api.widgets.each(widget => {

View file

@ -16,9 +16,11 @@ function parseAsync(text, opt) {
});
}
function parse(text, opt = { soup: true }) {
function parse(text, opt = { }) {
const justPoly = opt.flat || false;
const fromSoup = opt.soup || justPoly;
const fromSoup = opt.soup !== false || justPoly;
const rez = (opt.resolution || 1);
const segmin = Math.max(1, opt.segmin || 10);
const objs = [];
const data = new THREE.SVGLoader().parse(text);
const paths = data.paths;
@ -38,9 +40,14 @@ function parse(text, opt = { soup: true }) {
if (fromSoup) {
for (let sub of path.subPaths) {
let length = sub.getLength();
let points = sub.getPoints(sub.curves ? Math.max(length/2, 12) : undefined);
let points = sub.curves.map(curve => {
let length = curve.getLength();
let segs = curve.type === 'LineCurve' ?
1 : Math.max(Math.ceil(length * rez), segmin);
return curve.getPoints(segs);
}).flat();
if (points.length < 3) {
console.log({ sub, length, points });
// console.log({ sub, length, points });
continue;
}
let poly = base.newPolygon().addPoints(points.map(p => base.newPoint(p.x, -p.y, 0)));

View file

@ -1468,7 +1468,7 @@ th, tr, td, label {
.mdialog {
display: none;
padding: 10px;
padding: 10px 20px 10px 20px;
min-height: 20px;
background-color: #fff;
}