add dxf import
This commit is contained in:
parent
8c8afaba69
commit
3aa8b77e77
5 changed files with 418 additions and 5 deletions
|
|
@ -126,7 +126,7 @@ function content(actions) {
|
||||||
menuItem(actions, { id: 'file-recent', lk: 'recent', text: 'recent', iconClass: 'fas fa-list' }),
|
menuItem(actions, { id: 'file-recent', lk: 'recent', text: 'recent', iconClass: 'fas fa-list' }),
|
||||||
menuItem(actions, {
|
menuItem(actions, {
|
||||||
id: 'file-import', lk: 'import', text: 'import', iconClass: 'fas fa-file-upload', children:
|
id: 'file-import', lk: 'import', text: 'import', iconClass: 'fas fa-file-upload', children:
|
||||||
input({ id: 'load-file', type: 'file', name: 'loadme', style: 'display:none', accept: '.km,.kmz,.stl,.obj,.svg,.png,.jpg,.jpeg,.gcode,.nc' })
|
input({ id: 'load-file', type: 'file', name: 'loadme', style: 'display:none', accept: '.km,.kmz,.stl,.obj,.svg,.dxf,.png,.jpg,.jpeg,.gcode,.nc' })
|
||||||
}),
|
}),
|
||||||
hr(),
|
hr(),
|
||||||
menuItem(actions, { id: 'mesh-export-obj', lk: 'export-obj', text: 'save as OBJ', iconClass: 'fas fa-dice-d20' }),
|
menuItem(actions, { id: 'mesh-export-obj', lk: 'export-obj', text: 'save as OBJ', iconClass: 'fas fa-dice-d20' }),
|
||||||
|
|
|
||||||
|
|
@ -979,6 +979,7 @@ function load_files(files, group) {
|
||||||
isobj = lower.endsWith(".obj"),
|
isobj = lower.endsWith(".obj"),
|
||||||
is3mf = lower.endsWith(".3mf"),
|
is3mf = lower.endsWith(".3mf"),
|
||||||
issvg = lower.endsWith(".svg"),
|
issvg = lower.endsWith(".svg"),
|
||||||
|
isdxf = lower.endsWith(".dxf"),
|
||||||
ispng = lower.endsWith(".png"),
|
ispng = lower.endsWith(".png"),
|
||||||
isjpg = lower.endsWith(".jpg"),
|
isjpg = lower.endsWith(".jpg"),
|
||||||
iskmz = lower.endsWith(".kmz"),
|
iskmz = lower.endsWith(".kmz"),
|
||||||
|
|
@ -1080,6 +1081,19 @@ function load_files(files, group) {
|
||||||
}
|
}
|
||||||
load_dec();
|
load_dec();
|
||||||
});
|
});
|
||||||
|
} else if (isdxf) {
|
||||||
|
loadDXFDialog(opt => {
|
||||||
|
group = group || [];
|
||||||
|
let dxf = file_load.DXF.parse(data.textDecode('utf-8'), opt);
|
||||||
|
let ind = 0;
|
||||||
|
if (dxf.length === 0) {
|
||||||
|
api.show.alert(`DXF contains no supported entities`, 10);
|
||||||
|
}
|
||||||
|
for (let v of dxf) {
|
||||||
|
load_verts(group, dxf[ind++], ind ? `${name}-${ind}` : name);
|
||||||
|
}
|
||||||
|
load_dec();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
else if (iskmz) api.settings.import_zip(data, true);
|
else if (iskmz) api.settings.import_zip(data, true);
|
||||||
else if (isset) api.settings.import(data.textDecode('utf-8'), true);
|
else if (isset) api.settings.import(data.textDecode('utf-8'), true);
|
||||||
|
|
@ -1125,6 +1139,37 @@ function loadSVGDialog(doit) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show dialog to configure DXF import settings.
|
||||||
|
* Prompts for extrusion depth, arc segment size, and nesting.
|
||||||
|
* @param {Function} doit - Callback with options: {soup, depth, segmentSize, minSegments}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
function loadDXFDialog(doit) {
|
||||||
|
const opt = {pre: [
|
||||||
|
"<div class='f-col a-center'>",
|
||||||
|
" <h3>Import DXF</h3>",
|
||||||
|
" <p class='t-just' style='width:300px;line-height:1.5em'>",
|
||||||
|
" Extrude a 3D model from a 2D DXF.",
|
||||||
|
" Supports POLYLINE, LWPOLYLINE, LINE, CIRCLE, and ARC entities.",
|
||||||
|
" </p>",
|
||||||
|
" <div class='f-row t-right'><table>",
|
||||||
|
" <tr><th>z height in mm</th><td><input id='dxf-depth' value='5' size='3'></td></tr>",
|
||||||
|
" <tr><th title='target length of each line segment when converting arcs and circles'>arc segment size in mm</th><td><input id='dxf-seg' value='1' size='3'></td></tr>",
|
||||||
|
" <tr><th title='minimum number of segments for very small arcs to avoid degenerate geometry'>minimum arc segments</th><td><input id='dxf-min' value='4' size='3'></td></tr>",
|
||||||
|
" <tr><th>nest shapes</th><td><input id='dxf-nest' value='1' type='checkbox' checked></td></tr>",
|
||||||
|
" </table></div>",
|
||||||
|
"</div>"
|
||||||
|
]};
|
||||||
|
api.uc.confirm(undefined, {convert:true, cancel:false}, undefined, opt).then((ok) => {
|
||||||
|
let depth = Math.max(0.1, parseFloat($('dxf-depth').value));
|
||||||
|
let segmentSize = Math.max(0.01, parseFloat($('dxf-seg').value));
|
||||||
|
let minSegments = Math.max(3, parseInt($('dxf-min').value));
|
||||||
|
let soup = $('dxf-nest').checked;
|
||||||
|
ok && doit({ soup, depth, segmentSize, minSegments });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expand platform bed depth to fit widgets (belt mode only).
|
* Expand platform bed depth to fit widgets (belt mode only).
|
||||||
* Finds maximum Y dimension of all widgets and expands bed if needed.
|
* Finds maximum Y dimension of all widgets and expands bed if needed.
|
||||||
|
|
|
||||||
359
src/load/dxf.js
Normal file
359
src/load/dxf.js
Normal file
|
|
@ -0,0 +1,359 @@
|
||||||
|
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||||
|
|
||||||
|
import { newPolygon } from '../geo/polygon.js';
|
||||||
|
import { newPoint } from '../geo/point.js';
|
||||||
|
import { polygons } from '../geo/polygons.js';
|
||||||
|
|
||||||
|
export function parseAsync(text, opt) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
try {
|
||||||
|
resolve(parse(text, opt));
|
||||||
|
} catch (e) {
|
||||||
|
reject(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function parse(text, opt = { }) {
|
||||||
|
const justPoly = opt.flat || false;
|
||||||
|
const fromSoup = opt.soup !== false || justPoly;
|
||||||
|
const depth = parseFloat(opt.depth || 5);
|
||||||
|
const segmentSize = parseFloat(opt.segmentSize || 1); // default 1mm segments
|
||||||
|
const minSegments = parseInt(opt.minSegments || 4); // minimum segments for very small arcs
|
||||||
|
const objs = [];
|
||||||
|
const polys = [];
|
||||||
|
|
||||||
|
// Parse DXF file - normalize line endings and split
|
||||||
|
const lines = text.replace(/\r\n/g, '\n').replace(/\r/g, '\n').split('\n').map(l => l.trim());
|
||||||
|
const entities = extractEntities(lines);
|
||||||
|
|
||||||
|
// Convert entities to polygons
|
||||||
|
for (let entity of entities) {
|
||||||
|
if (entity.type === 'POLYLINE' || entity.type === 'LWPOLYLINE') {
|
||||||
|
if (entity.points.length < 2) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let poly = newPolygon().addPoints(
|
||||||
|
entity.points.map(p => newPoint(p.x, p.y, p.z || 0))
|
||||||
|
).clean();
|
||||||
|
|
||||||
|
// Check if closed
|
||||||
|
if (entity.closed && poly.appearsClosed()) {
|
||||||
|
poly.points.pop();
|
||||||
|
} else if (!entity.closed) {
|
||||||
|
poly.setOpen(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
polys.push(poly);
|
||||||
|
} else if (entity.type === 'LINE') {
|
||||||
|
// Convert line to polyline
|
||||||
|
let poly = newPolygon().addPoints([
|
||||||
|
newPoint(entity.start.x, entity.start.y, entity.start.z || 0),
|
||||||
|
newPoint(entity.end.x, entity.end.y, entity.end.z || 0)
|
||||||
|
]);
|
||||||
|
poly.setOpen(true);
|
||||||
|
polys.push(poly);
|
||||||
|
} else if (entity.type === 'CIRCLE') {
|
||||||
|
// Convert circle to polygon with points
|
||||||
|
// Calculate segments based on circumference and desired segment size
|
||||||
|
const circumference = 2 * Math.PI * entity.radius;
|
||||||
|
const segments = Math.max(minSegments, Math.ceil(circumference / segmentSize));
|
||||||
|
let points = [];
|
||||||
|
for (let i = 0; i < segments; i++) {
|
||||||
|
const angle = (i / segments) * Math.PI * 2;
|
||||||
|
points.push(newPoint(
|
||||||
|
entity.center.x + Math.cos(angle) * entity.radius,
|
||||||
|
entity.center.y + Math.sin(angle) * entity.radius,
|
||||||
|
entity.center.z || 0
|
||||||
|
));
|
||||||
|
}
|
||||||
|
let poly = newPolygon().addPoints(points).clean();
|
||||||
|
polys.push(poly);
|
||||||
|
} else if (entity.type === 'ARC') {
|
||||||
|
// Convert arc to polyline
|
||||||
|
// Calculate segments based on arc length and desired segment size
|
||||||
|
const arcLength = Math.abs(entity.endAngle - entity.startAngle) * entity.radius;
|
||||||
|
const segments = Math.max(minSegments, Math.ceil(arcLength / segmentSize));
|
||||||
|
let points = [];
|
||||||
|
for (let i = 0; i <= segments; i++) {
|
||||||
|
const angle = entity.startAngle + (i / segments) * (entity.endAngle - entity.startAngle);
|
||||||
|
points.push(newPoint(
|
||||||
|
entity.center.x + Math.cos(angle) * entity.radius,
|
||||||
|
entity.center.y + Math.sin(angle) * entity.radius,
|
||||||
|
entity.center.z || 0
|
||||||
|
));
|
||||||
|
}
|
||||||
|
let poly = newPolygon().addPoints(points);
|
||||||
|
poly.setOpen(true);
|
||||||
|
polys.push(poly);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nest polygons to identify holes vs outlines
|
||||||
|
const sub = fromSoup ? polygons.nest(polys) : polys;
|
||||||
|
const nest = sub.filter(p => {
|
||||||
|
for (let pc of polys) {
|
||||||
|
if (pc === p) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return !pc.isEquivalent(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (justPoly) {
|
||||||
|
return nest;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extrude polygons to 3D
|
||||||
|
for (let poly of nest) {
|
||||||
|
let obj = poly.extrude(depth);
|
||||||
|
objs.push(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
return objs;
|
||||||
|
}
|
||||||
|
|
||||||
|
function extractEntities(lines) {
|
||||||
|
const entities = [];
|
||||||
|
let inEntities = false;
|
||||||
|
let i = 0;
|
||||||
|
|
||||||
|
while (i < lines.length - 1) {
|
||||||
|
const code = lines[i];
|
||||||
|
const value = lines[i + 1];
|
||||||
|
|
||||||
|
// Check if we're in the ENTITIES section
|
||||||
|
if (code === '0' && value === 'SECTION') {
|
||||||
|
if (i + 3 < lines.length && lines[i + 2] === '2' && lines[i + 3] === 'ENTITIES') {
|
||||||
|
inEntities = true;
|
||||||
|
i += 4;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (code === '0' && value === 'ENDSEC' && inEntities) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inEntities && code === '0') {
|
||||||
|
if (value === 'POLYLINE') {
|
||||||
|
const entity = parsePolyline(lines, i);
|
||||||
|
if (entity) {
|
||||||
|
entities.push(entity);
|
||||||
|
i = entity.endIndex;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else if (value === 'LWPOLYLINE') {
|
||||||
|
const entity = parseLWPolyline(lines, i);
|
||||||
|
if (entity) {
|
||||||
|
entities.push(entity);
|
||||||
|
i = entity.endIndex;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else if (value === 'LINE') {
|
||||||
|
const entity = parseLine(lines, i);
|
||||||
|
if (entity) {
|
||||||
|
entities.push(entity);
|
||||||
|
i = entity.endIndex;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else if (value === 'CIRCLE') {
|
||||||
|
const entity = parseCircle(lines, i);
|
||||||
|
if (entity) {
|
||||||
|
entities.push(entity);
|
||||||
|
i = entity.endIndex;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else if (value === 'ARC') {
|
||||||
|
const entity = parseArc(lines, i);
|
||||||
|
if (entity) {
|
||||||
|
entities.push(entity);
|
||||||
|
i = entity.endIndex;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return entities;
|
||||||
|
}
|
||||||
|
|
||||||
|
function parsePolyline(lines, start) {
|
||||||
|
let i = start + 2;
|
||||||
|
let closed = false;
|
||||||
|
const points = [];
|
||||||
|
|
||||||
|
// Read polyline flags
|
||||||
|
while (i < lines.length - 1) {
|
||||||
|
const code = lines[i];
|
||||||
|
const value = lines[i + 1];
|
||||||
|
|
||||||
|
if (code === '70') {
|
||||||
|
// Polyline flag: 1 = closed
|
||||||
|
closed = (parseInt(value) & 1) === 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (code === '0' && value === 'VERTEX') {
|
||||||
|
const vertex = parseVertex(lines, i);
|
||||||
|
if (vertex) {
|
||||||
|
points.push(vertex.point);
|
||||||
|
i = vertex.endIndex;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (code === '0' && value === 'SEQEND') {
|
||||||
|
return { type: 'POLYLINE', points, closed, endIndex: i + 2 };
|
||||||
|
}
|
||||||
|
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseVertex(lines, start) {
|
||||||
|
let i = start + 2;
|
||||||
|
const point = { x: 0, y: 0, z: 0 };
|
||||||
|
|
||||||
|
while (i < lines.length - 1) {
|
||||||
|
const code = lines[i];
|
||||||
|
const value = lines[i + 1];
|
||||||
|
|
||||||
|
if (code === '10') point.x = parseFloat(value);
|
||||||
|
if (code === '20') point.y = parseFloat(value);
|
||||||
|
if (code === '30') point.z = parseFloat(value);
|
||||||
|
|
||||||
|
if (code === '0') {
|
||||||
|
return { point, endIndex: i };
|
||||||
|
}
|
||||||
|
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return { point, endIndex: i };
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseLWPolyline(lines, start) {
|
||||||
|
let i = start + 2;
|
||||||
|
let closed = false;
|
||||||
|
const points = [];
|
||||||
|
let currentPoint = null;
|
||||||
|
|
||||||
|
while (i < lines.length - 1) {
|
||||||
|
const code = lines[i];
|
||||||
|
const value = lines[i + 1];
|
||||||
|
|
||||||
|
if (code === '70') {
|
||||||
|
closed = (parseInt(value) & 1) === 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (code === '10') {
|
||||||
|
if (currentPoint) {
|
||||||
|
points.push(currentPoint);
|
||||||
|
}
|
||||||
|
currentPoint = { x: parseFloat(value), y: 0, z: 0 };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (code === '20' && currentPoint) {
|
||||||
|
currentPoint.y = parseFloat(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (code === '0') {
|
||||||
|
if (currentPoint) {
|
||||||
|
points.push(currentPoint);
|
||||||
|
}
|
||||||
|
return { type: 'LWPOLYLINE', points, closed, endIndex: i };
|
||||||
|
}
|
||||||
|
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentPoint) {
|
||||||
|
points.push(currentPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
return { type: 'LWPOLYLINE', points, closed, endIndex: i };
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseLine(lines, start) {
|
||||||
|
let i = start + 2;
|
||||||
|
const start_point = { x: 0, y: 0, z: 0 };
|
||||||
|
const end_point = { x: 0, y: 0, z: 0 };
|
||||||
|
|
||||||
|
while (i < lines.length - 1) {
|
||||||
|
const code = lines[i];
|
||||||
|
const value = lines[i + 1];
|
||||||
|
|
||||||
|
if (code === '10') start_point.x = parseFloat(value);
|
||||||
|
if (code === '20') start_point.y = parseFloat(value);
|
||||||
|
if (code === '30') start_point.z = parseFloat(value);
|
||||||
|
if (code === '11') end_point.x = parseFloat(value);
|
||||||
|
if (code === '21') end_point.y = parseFloat(value);
|
||||||
|
if (code === '31') end_point.z = parseFloat(value);
|
||||||
|
|
||||||
|
if (code === '0') {
|
||||||
|
return { type: 'LINE', start: start_point, end: end_point, endIndex: i };
|
||||||
|
}
|
||||||
|
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return { type: 'LINE', start: start_point, end: end_point, endIndex: i };
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseCircle(lines, start) {
|
||||||
|
let i = start + 2;
|
||||||
|
const center = { x: 0, y: 0, z: 0 };
|
||||||
|
let radius = 0;
|
||||||
|
|
||||||
|
while (i < lines.length - 1) {
|
||||||
|
const code = lines[i];
|
||||||
|
const value = lines[i + 1];
|
||||||
|
|
||||||
|
if (code === '10') center.x = parseFloat(value);
|
||||||
|
if (code === '20') center.y = parseFloat(value);
|
||||||
|
if (code === '30') center.z = parseFloat(value);
|
||||||
|
if (code === '40') radius = parseFloat(value);
|
||||||
|
|
||||||
|
if (code === '0') {
|
||||||
|
return { type: 'CIRCLE', center, radius, endIndex: i };
|
||||||
|
}
|
||||||
|
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return { type: 'CIRCLE', center, radius, endIndex: i };
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseArc(lines, start) {
|
||||||
|
let i = start + 2;
|
||||||
|
const center = { x: 0, y: 0, z: 0 };
|
||||||
|
let radius = 0;
|
||||||
|
let startAngle = 0;
|
||||||
|
let endAngle = 0;
|
||||||
|
|
||||||
|
while (i < lines.length - 1) {
|
||||||
|
const code = lines[i];
|
||||||
|
const value = lines[i + 1];
|
||||||
|
|
||||||
|
if (code === '10') center.x = parseFloat(value);
|
||||||
|
if (code === '20') center.y = parseFloat(value);
|
||||||
|
if (code === '30') center.z = parseFloat(value);
|
||||||
|
if (code === '40') radius = parseFloat(value);
|
||||||
|
if (code === '50') startAngle = parseFloat(value) * Math.PI / 180; // Convert to radians
|
||||||
|
if (code === '51') endAngle = parseFloat(value) * Math.PI / 180; // Convert to radians
|
||||||
|
|
||||||
|
if (code === '0') {
|
||||||
|
return { type: 'ARC', center, radius, startAngle, endAngle, endIndex: i };
|
||||||
|
}
|
||||||
|
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return { type: 'ARC', center, radius, startAngle, endAngle, endIndex: i };
|
||||||
|
}
|
||||||
|
|
@ -6,6 +6,7 @@ import { STL } from './stl.js';
|
||||||
import * as OBJ from './obj.js';
|
import * as OBJ from './obj.js';
|
||||||
import * as TMF from './3mf.js';
|
import * as TMF from './3mf.js';
|
||||||
import * as SVG from './svg.js';
|
import * as SVG from './svg.js';
|
||||||
|
import * as DXF from './dxf.js';
|
||||||
import * as GBR from './gbr.js';
|
import * as GBR from './gbr.js';
|
||||||
import { load as pngLoad } from './png.js';
|
import { load as pngLoad } from './png.js';
|
||||||
|
|
||||||
|
|
@ -36,6 +37,11 @@ const types = {
|
||||||
resolve(opt.flat ? out : out.map(m => { return { mesh: m.toFloat32(), file } }));
|
resolve(opt.flat ? out : out.map(m => { return { mesh: m.toFloat32(), file } }));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
dxf(data, file, resolve, reject, opt = {}) {
|
||||||
|
let out = DXF.parse(data, opt);
|
||||||
|
resolve(opt.flat ? out : out.map(m => { return { mesh: m.toFloat32(), file } }));
|
||||||
|
},
|
||||||
|
|
||||||
png(data, file, resolve, reject, opt = {}) {
|
png(data, file, resolve, reject, opt = {}) {
|
||||||
pngLoad.PNG.parse(data, {
|
pngLoad.PNG.parse(data, {
|
||||||
...opt,
|
...opt,
|
||||||
|
|
@ -100,6 +106,6 @@ function load_file(file, opt) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.assign(load_file, { SVG, OBJ, STL, TMF, GBR, PNG: pngLoad.PNG });
|
Object.assign(load_file, { SVG, DXF, OBJ, STL, TMF, GBR, PNG: pngLoad.PNG });
|
||||||
|
|
||||||
export { types, as_buffer, load_data, load_file, load_file as load };
|
export { types, as_buffer, load_data, load_file, load_file as load };
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
import { load_file } from './file.js';
|
import { load_file } from './file.js';
|
||||||
|
|
||||||
const { STL, OBJ, TMF, SVG } = load_file;
|
const { STL, OBJ, TMF, SVG, DXF } = load_file;
|
||||||
const CDH = 'Content-Disposition';
|
const CDH = 'Content-Disposition';
|
||||||
|
|
||||||
export function load_url(url, options = {}) {
|
export function load_url(url, options = {}) {
|
||||||
|
|
@ -12,7 +12,7 @@ export function load_url(url, options = {}) {
|
||||||
let xhr = new XMLHttpRequest();
|
let xhr = new XMLHttpRequest();
|
||||||
let file = options.file || options.filename || (((url.split('?')[0]).split('#')[0]).split('/')).pop();
|
let file = options.file || options.filename || (((url.split('?')[0]).split('#')[0]).split('/')).pop();
|
||||||
let ext = file.split('.').pop().toLowerCase();
|
let ext = file.split('.').pop().toLowerCase();
|
||||||
let deftype = ext === "obj" || ext === 'svg' ? "text" : "arraybuffer";
|
let deftype = ext === "obj" || ext === 'svg' || ext === 'dxf' ? "text" : "arraybuffer";
|
||||||
let datatype = options.datatype || deftype;
|
let datatype = options.datatype || deftype;
|
||||||
let formdata = options.formdata;
|
let formdata = options.formdata;
|
||||||
|
|
||||||
|
|
@ -55,6 +55,9 @@ export function load_url(url, options = {}) {
|
||||||
case "svg":
|
case "svg":
|
||||||
resolve(SVG.parse(data).map(m => { return {mesh: m.toFloat32(), file} }));
|
resolve(SVG.parse(data).map(m => { return {mesh: m.toFloat32(), file} }));
|
||||||
break;
|
break;
|
||||||
|
case "dxf":
|
||||||
|
resolve(DXF.parse(data).map(m => { return {mesh: m.toFloat32(), file} }));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
reject(`unknown file type: "${ext}" from ${url}`);
|
reject(`unknown file type: "${ext}" from ${url}`);
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue