merge development branch
This commit is contained in:
commit
9b0fa9dedf
128 changed files with 3943 additions and 4261 deletions
306
app.js
306
app.js
|
|
@ -10,7 +10,7 @@ const fs = require('fs');
|
||||||
const uglify = require('uglify-es');
|
const uglify = require('uglify-es');
|
||||||
const moment = require('moment');
|
const moment = require('moment');
|
||||||
const agent = require('express-useragent');
|
const agent = require('express-useragent');
|
||||||
const license = require_fresh('./js/license.js');
|
const license = require_fresh('./src/license.js');
|
||||||
const version = license.VERSION || "rogue";
|
const version = license.VERSION || "rogue";
|
||||||
|
|
||||||
const fileCache = {};
|
const fileCache = {};
|
||||||
|
|
@ -18,12 +18,8 @@ const code_src = {};
|
||||||
const code = {};
|
const code = {};
|
||||||
const mods = {};
|
const mods = {};
|
||||||
const load = [];
|
const load = [];
|
||||||
const device = {
|
const synth = {};
|
||||||
fdm: [],
|
const api = {};
|
||||||
sla: [],
|
|
||||||
cam: [],
|
|
||||||
laser: []
|
|
||||||
};
|
|
||||||
|
|
||||||
let level;
|
let level;
|
||||||
let cacheDir;
|
let cacheDir;
|
||||||
|
|
@ -72,7 +68,7 @@ function init(mod) {
|
||||||
]));
|
]));
|
||||||
mod.add(fixedmap("/api/", api));
|
mod.add(fixedmap("/api/", api));
|
||||||
if (debug) {
|
if (debug) {
|
||||||
mod.static("/js/", "js");
|
mod.static("/src/", "src");
|
||||||
mod.static("/mod/", "mod");
|
mod.static("/mod/", "mod");
|
||||||
mod.sync("/reload", () => {
|
mod.sync("/reload", () => {
|
||||||
mod.reload();
|
mod.reload();
|
||||||
|
|
@ -130,6 +126,7 @@ function initModule(mod, file, dir) {
|
||||||
},
|
},
|
||||||
const: {
|
const: {
|
||||||
args: {},
|
args: {},
|
||||||
|
meta: mod.meta,
|
||||||
debug: debug,
|
debug: debug,
|
||||||
script: script,
|
script: script,
|
||||||
moddir: dir,
|
moddir: dir,
|
||||||
|
|
@ -210,139 +207,118 @@ function initModule(mod, file, dir) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const api = {
|
|
||||||
"filters-fdm": (req, res, next) => {
|
|
||||||
res.setHeader("Content-Type", "application/javascript");
|
|
||||||
res.end(JSON.stringify(device.fdm));
|
|
||||||
},
|
|
||||||
|
|
||||||
"filters-sla": (req, res, next) => {
|
|
||||||
res.setHeader("Content-Type", "application/javascript");
|
|
||||||
res.end(JSON.stringify(device.sla));
|
|
||||||
},
|
|
||||||
|
|
||||||
"filters-cam": (req, res, next) => {
|
|
||||||
res.setHeader("Content-Type", "application/javascript");
|
|
||||||
res.end(JSON.stringify(device.cam));
|
|
||||||
},
|
|
||||||
|
|
||||||
"filters-laser": (req, res, next) => {
|
|
||||||
res.setHeader("Content-Type", "application/javascript");
|
|
||||||
res.end(JSON.stringify(device.laser));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const script = {
|
const script = {
|
||||||
kiri : [
|
kiri : [
|
||||||
"ext-three",
|
|
||||||
"license",
|
|
||||||
"ext-clip2",
|
|
||||||
"ext-tween",
|
|
||||||
"ext-fsave",
|
|
||||||
"ext-earcut",
|
|
||||||
"add-array",
|
|
||||||
"add-three",
|
|
||||||
"geo",
|
|
||||||
"geo-debug",
|
|
||||||
"geo-render",
|
|
||||||
"geo-point",
|
|
||||||
"geo-slope",
|
|
||||||
"geo-line",
|
|
||||||
"geo-bounds",
|
|
||||||
"geo-polygon",
|
|
||||||
"geo-polygons",
|
|
||||||
"geo-gyroid",
|
|
||||||
"moto-kv",
|
|
||||||
"moto-ajax",
|
|
||||||
"moto-ctrl",
|
|
||||||
"moto-space",
|
|
||||||
"moto-load-stl",
|
|
||||||
"moto-db",
|
|
||||||
"moto-ui",
|
|
||||||
"kiri-icons",
|
|
||||||
"kiri-lang",
|
|
||||||
"kiri-lang-en",
|
|
||||||
"kiri-fill",
|
|
||||||
"kiri-db",
|
|
||||||
"kiri-slice",
|
|
||||||
"kiri-slicer",
|
|
||||||
"kiri-driver-fdm",
|
|
||||||
"kiri-driver-sla",
|
|
||||||
"kiri-driver-cam",
|
|
||||||
"kiri-driver-laser",
|
|
||||||
"kiri-pack",
|
|
||||||
"kiri-layer",
|
|
||||||
"kiri-widget",
|
|
||||||
"kiri-print",
|
|
||||||
"kiri-codec",
|
|
||||||
"kiri-work",
|
|
||||||
"kiri-conf",
|
|
||||||
"kiri",
|
"kiri",
|
||||||
"kiri-init",
|
"ext/three",
|
||||||
"kiri-export"
|
|
||||||
].map(p => `js/${p}.js`),
|
|
||||||
work : [
|
|
||||||
"ext-three",
|
|
||||||
"ext-pngjs",
|
|
||||||
"license",
|
"license",
|
||||||
"ext-clip2",
|
"ext/clip2",
|
||||||
"add-array",
|
"ext/tween",
|
||||||
"add-three",
|
"ext/fsave",
|
||||||
"add-class",
|
"ext/earcut",
|
||||||
"geo",
|
"add/array",
|
||||||
// "geo-wasm",
|
"add/three",
|
||||||
"geo-debug",
|
"geo/base",
|
||||||
"geo-point",
|
"geo/debug",
|
||||||
"geo-slope",
|
"geo/render",
|
||||||
"geo-line",
|
"geo/point",
|
||||||
"geo-bounds",
|
"geo/slope",
|
||||||
"geo-polygon",
|
"geo/line",
|
||||||
"geo-polygons",
|
"geo/bounds",
|
||||||
"geo-gyroid",
|
"geo/polygon",
|
||||||
"kiri-fill",
|
"geo/polygons",
|
||||||
"kiri-slice",
|
"geo/gyroid",
|
||||||
"kiri-slicer",
|
"moto/kv",
|
||||||
"kiri-driver-fdm",
|
"moto/ajax",
|
||||||
"kiri-driver-sla",
|
"moto/ctrl",
|
||||||
"kiri-driver-cam",
|
"moto/pack",
|
||||||
"kiri-driver-laser",
|
"moto/space",
|
||||||
"kiri-pack",
|
"moto/load-stl",
|
||||||
"kiri-widget",
|
"moto/db",
|
||||||
"kiri-print",
|
"kiri/ui",
|
||||||
"kiri-codec"
|
"kiri/lang",
|
||||||
].map(p => `js/${p}.js`),
|
"kiri/lang-en",
|
||||||
|
"kiri/fill",
|
||||||
|
"kiri/db",
|
||||||
|
"kiri/slice",
|
||||||
|
"kiri/slicer",
|
||||||
|
"mode/fdm/driver",
|
||||||
|
"mode/sla/driver",
|
||||||
|
"mode/cam/driver",
|
||||||
|
"mode/laser/driver",
|
||||||
|
"kiri/layer",
|
||||||
|
"kiri/widget",
|
||||||
|
"kiri/print",
|
||||||
|
"kiri/codec",
|
||||||
|
"kiri/work",
|
||||||
|
"kiri/conf",
|
||||||
|
"kiri/main",
|
||||||
|
"kiri/init",
|
||||||
|
"kiri/export",
|
||||||
|
"@devices",
|
||||||
|
"@icons"
|
||||||
|
].map(p => p.charAt(0) !== '@' ? `src/${p}.js` : p),
|
||||||
worker : [
|
worker : [
|
||||||
"kiri-worker"
|
"kiri",
|
||||||
].map(p => `js/${p}.js`),
|
"ext/three",
|
||||||
meta : [
|
"ext/pngjs",
|
||||||
"ext-three",
|
|
||||||
"license",
|
"license",
|
||||||
"ext-tween",
|
"ext/clip2",
|
||||||
"ext-fsave",
|
"add/array",
|
||||||
"ext-earcut",
|
"add/three",
|
||||||
"add-array",
|
"add/class",
|
||||||
"add-three",
|
"geo/base",
|
||||||
"geo",
|
// "geo/wasm",
|
||||||
"geo-debug",
|
"geo/debug",
|
||||||
"geo-render",
|
"geo/point",
|
||||||
"geo-point",
|
"geo/slope",
|
||||||
"geo-slope",
|
"geo/line",
|
||||||
"geo-line",
|
"geo/bounds",
|
||||||
"geo-bounds",
|
"geo/polygon",
|
||||||
"geo-polygon",
|
"geo/polygons",
|
||||||
"geo-polygons",
|
"geo/gyroid",
|
||||||
"geo-gyroid",
|
"moto/pack",
|
||||||
"kiri-layer",
|
"kiri/fill",
|
||||||
"moto-kv",
|
"kiri/slice",
|
||||||
"moto-ajax",
|
"kiri/slicer",
|
||||||
"moto-ctrl",
|
"mode/fdm/driver",
|
||||||
"moto-space",
|
"mode/sla/driver",
|
||||||
"moto-load-stl",
|
"mode/cam/driver",
|
||||||
"moto-db",
|
"mode/laser/driver",
|
||||||
"moto-ui",
|
"kiri/widget",
|
||||||
"kiri-db",
|
"kiri/print",
|
||||||
|
"kiri/codec",
|
||||||
|
"kiri/worker"
|
||||||
|
].map(p => `src/${p}.js`),
|
||||||
|
meta : [
|
||||||
|
"ext/three",
|
||||||
|
"license",
|
||||||
|
"ext/tween",
|
||||||
|
"ext/fsave",
|
||||||
|
"ext/earcut",
|
||||||
|
"add/array",
|
||||||
|
"add/three",
|
||||||
|
"geo/base",
|
||||||
|
"geo/debug",
|
||||||
|
"geo/render",
|
||||||
|
"geo/point",
|
||||||
|
"geo/slope",
|
||||||
|
"geo/line",
|
||||||
|
"geo/bounds",
|
||||||
|
"geo/polygon",
|
||||||
|
"geo/polygons",
|
||||||
|
"geo/gyroid",
|
||||||
|
"kiri/layer",
|
||||||
|
"moto/kv",
|
||||||
|
"moto/ajax",
|
||||||
|
"moto/ctrl",
|
||||||
|
"moto/space",
|
||||||
|
"moto/load-stl",
|
||||||
|
"moto/db",
|
||||||
|
"moto/ui",
|
||||||
|
"kiri/db",
|
||||||
"meta"
|
"meta"
|
||||||
].map(p => `js/${p}.js`)
|
].map(p => `src/${p}.js`)
|
||||||
};
|
};
|
||||||
|
|
||||||
const db = {
|
const db = {
|
||||||
|
|
@ -531,8 +507,13 @@ function handleData(req, res, next) {
|
||||||
dbVersion = parseInt(version || "0") + 1;
|
dbVersion = parseInt(version || "0") + 1;
|
||||||
checkDone();
|
checkDone();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
next();
|
next();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -611,36 +592,46 @@ function serveCode(req, res, code) {
|
||||||
res.end(code.code);
|
res.end(code.code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function generateIcons() {
|
||||||
|
let root = `${dir}/src/ico`;
|
||||||
|
let icos = {};
|
||||||
|
fs.readdirSync(root).forEach(file => {
|
||||||
|
let name = file.split(".")[0] ;
|
||||||
|
icos[name] = fs.readFileSync(`${root}/${file}`).toString();
|
||||||
|
});
|
||||||
|
synth.icons = `self.icons = ${JSON.stringify(icos)};`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateDevices() {
|
||||||
|
let root = `${dir}/src/dev`;
|
||||||
|
let devs = {};
|
||||||
|
fs.readdirSync(root).forEach(type => {
|
||||||
|
let map = devs[type] = devs[type] || {};
|
||||||
|
fs.readdirSync(`${root}/${type}`).forEach(device => {
|
||||||
|
map[device] = JSON.parse(fs.readFileSync(`${root}/${type}/${device}`));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
synth.devices = `self.devices = ${JSON.stringify(devs)};`;
|
||||||
|
}
|
||||||
|
|
||||||
function prepareScripts() {
|
function prepareScripts() {
|
||||||
|
generateIcons();
|
||||||
|
generateDevices();
|
||||||
code.meta = concatCode(script.meta);
|
code.meta = concatCode(script.meta);
|
||||||
code.kiri = concatCode(script.kiri);
|
code.kiri = concatCode(script.kiri);
|
||||||
code.work = concatCode(script.work);
|
|
||||||
code.worker = concatCode(script.worker);
|
code.worker = concatCode(script.worker);
|
||||||
fs.readdir(dir + "/web/kiri/filter/FDM", function(err, files) {
|
|
||||||
device.fdm = files || device.fdm;
|
|
||||||
});
|
|
||||||
fs.readdir(dir + "/web/kiri/filter/SLA", function(err, files) {
|
|
||||||
device.sla = files || device.sla;
|
|
||||||
});
|
|
||||||
fs.readdir(dir + "/web/kiri/filter/CAM", function(err, files) {
|
|
||||||
device.cam = files || device.cam;
|
|
||||||
});
|
|
||||||
fs.readdir(dir + "/web/kiri/filter/LASER", function(err, files) {
|
|
||||||
device.laser = files || device.laser;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function concatCode(array) {
|
function concatCode(array) {
|
||||||
let code = [];
|
let code = [];
|
||||||
|
let direct = array.filter(f => f.charAt(0) !== '@');
|
||||||
|
let inject = array.filter(f => f.charAt(0) === '@').map(f => f.substring(1));
|
||||||
|
|
||||||
// in debug mode, the script should load dependent
|
// in debug mode, the script should load dependent
|
||||||
// scripts instead of serving a complete bundle
|
// scripts instead of serving a complete bundle
|
||||||
if (debug) {
|
if (debug) {
|
||||||
let code = [ `(function() { let load = [ `];
|
let code = [ '(function() { let load = [ ' ];
|
||||||
array.forEach(file => {
|
direct.forEach(file => {
|
||||||
// if (file.indexOf(":\\") > 0) {
|
|
||||||
// file = `/${file}`;
|
|
||||||
// }
|
|
||||||
code.push(`"/${file.replace(/\\/g,'/')}?${version}",`);
|
code.push(`"/${file.replace(/\\/g,'/')}?${version}",`);
|
||||||
});
|
});
|
||||||
code.push([
|
code.push([
|
||||||
|
|
@ -653,19 +644,26 @@ function concatCode(array) {
|
||||||
's.src = file;',
|
's.src = file;',
|
||||||
's.onload = load_next;',
|
's.onload = load_next;',
|
||||||
'document.head.appendChild(s);',
|
'document.head.appendChild(s);',
|
||||||
'}; load_next(); })();',
|
'} load_next(); })();',
|
||||||
'self.debug=true;'
|
'self.debug=true;'
|
||||||
].join('\n'));
|
].join('\n'));
|
||||||
|
inject.forEach(key => {
|
||||||
|
code.push(synth[key]);
|
||||||
|
});
|
||||||
return code.join('\n');
|
return code.join('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
array.forEach(file => {
|
direct.forEach(file => {
|
||||||
let cached = getCachedFile(file, function(path) {
|
let cached = getCachedFile(file, function(path) {
|
||||||
return minify(`${dir}/${file}`);
|
return minify(`${dir}/${file}`);
|
||||||
});
|
});
|
||||||
code.push(cached);
|
code.push(cached);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
inject.forEach(key => {
|
||||||
|
code.push(synth[key]);
|
||||||
|
});
|
||||||
|
|
||||||
return code.join('');
|
return code.join('');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../node_modules/earcut/src/earcut.js
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../node_modules/three/build/three.min.js
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../node_modules/tween.js/index.js
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
"use strict";
|
|
||||||
|
|
||||||
let gs_kiri_ico = exports;
|
|
||||||
|
|
||||||
(function() {
|
|
||||||
|
|
||||||
if (!self.kiri) self.kiri = { };
|
|
||||||
if (!self.kiri.icon) self.kiri.icons = {
|
|
||||||
|
|
||||||
fdm:atob('PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+CjxzdmcgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJ4TWlkWU1pZCBtZWV0IiB2aWV3Qm94PSIwIDAgMTcwIDE3MCIgd2lkdGg9Ijc1cHgiIGhlaWdodD0iNzVweCI+PGRlZnM+PHBhdGggZD0iTTE1IDM4LjMzQzE1IDM4LjMzIDE1IDM4LjMzIDE1IDM4LjMzQzE1IDI1LjQ1IDI1LjQ1IDE1IDM4LjMzIDE1QzQ0LjU2IDE1IDc1LjY3IDE1IDEzMS42NyAxNUMxMzEuNjcgMTUgMTMxLjY3IDE1IDEzMS42NyAxNUMxMzcuODUgMTUgMTQzLjc5IDE3LjQ2IDE0OC4xNyAyMS44M0MxNTIuNTQgMjYuMjEgMTU1IDMyLjE1IDE1NSAzOC4zM0MxNTUgNDcuNjcgMTU1IDEyMi4zMyAxNTUgMTMxLjY3QzE1NSAxNDQuNTUgMTQ0LjU1IDE1NSAxMzEuNjcgMTU1QzEyMi4zMyAxNTUgNDcuNjcgMTU1IDM4LjMzIDE1NUMyNS40NSAxNTUgMTUgMTQ0LjU1IDE1IDEzMS42N0MxNSAxMTkuMjIgMTUgODguMTEgMTUgMzguMzNaIiBpZD0iYTE0R2FsdjlVRiI+PC9wYXRoPjxwYXRoIGQ9Ik00NSAxNUwxMjUgMTVMMTI1IDc1TDQ1IDc1TDQ1IDE1WiIgaWQ9ImMzcTgzOUxVMyI+PC9wYXRoPjxwYXRoIGQ9Ik0zNSAxNDEuNDhDNTMuMTEgMTQxLjQ4IDY0LjQzIDE0MS40OCA2OC45NiAxNDEuNDhDNzcuODIgMTQxLjQ4IDg1IDEzNC4zIDg1IDEyNS40NUM4NSAxMjUuNDUgODUgMTI1LjQ1IDg1IDEyNS40NSIgaWQ9ImNoRTB0MXhmTCI+PC9wYXRoPjxwYXRoIGQ9Ik0xMDUgOTVMODUgMTE1TDY1IDk1TDEwNSA5NVoiIGlkPSJhNks5OThGM0dUIj48L3BhdGg+PHBhdGggZD0iTTc1IDc1TDk1IDc1TDk1IDk1TDc1IDk1TDc1IDc1WiIgaWQ9ImUxaWlNRVJxQWgiPjwvcGF0aD48L2RlZnM+PGc+PGc+PGc+PGc+PHVzZSB4bGluazpocmVmPSIjYTE0R2FsdjlVRiIgb3BhY2l0eT0iMSIgZmlsbD0iIzAwMDAwMCIgZmlsbC1vcGFjaXR5PSIwIj48L3VzZT48Zz48dXNlIHhsaW5rOmhyZWY9IiNhMTRHYWx2OVVGIiBvcGFjaXR5PSIxIiBmaWxsLW9wYWNpdHk9IjAiIHN0cm9rZT0iIzc3Nzc3NyIgc3Ryb2tlLXdpZHRoPSI4IiBzdHJva2Utb3BhY2l0eT0iMSI+PC91c2U+PC9nPjwvZz48Zz48dXNlIHhsaW5rOmhyZWY9IiNjM3E4MzlMVTMiIG9wYWNpdHk9IjEiIGZpbGw9IiMwMDAwMDAiIGZpbGwtb3BhY2l0eT0iMCI+PC91c2U+PGc+PHVzZSB4bGluazpocmVmPSIjYzNxODM5TFUzIiBvcGFjaXR5PSIxIiBmaWxsLW9wYWNpdHk9IjAiIHN0cm9rZT0iIzc3Nzc3NyIgc3Ryb2tlLXdpZHRoPSI4IiBzdHJva2Utb3BhY2l0eT0iMSI+PC91c2U+PC9nPjwvZz48Zz48Zz48dXNlIHhsaW5rOmhyZWY9IiNjaEUwdDF4ZkwiIG9wYWNpdHk9IjEiIGZpbGwtb3BhY2l0eT0iMCIgc3Ryb2tlPSIjNzc3Nzc3IiBzdHJva2Utd2lkdGg9IjguMDEiIHN0cm9rZS1vcGFjaXR5PSIxIj48L3VzZT48L2c+PC9nPjxnPjxnPjx1c2UgeGxpbms6aHJlZj0iI2E2Szk5OEYzR1QiIG9wYWNpdHk9IjEiIGZpbGwtb3BhY2l0eT0iMCIgc3Ryb2tlPSIjNzc3Nzc3IiBzdHJva2Utd2lkdGg9IjguMDEiIHN0cm9rZS1vcGFjaXR5PSIxIj48L3VzZT48L2c+PC9nPjxnPjx1c2UgeGxpbms6aHJlZj0iI2UxaWlNRVJxQWgiIG9wYWNpdHk9IjEiIGZpbGw9IiMwMDAwMDAiIGZpbGwtb3BhY2l0eT0iMCI+PC91c2U+PGc+PHVzZSB4bGluazpocmVmPSIjZTFpaU1FUnFBaCIgb3BhY2l0eT0iMSIgZmlsbC1vcGFjaXR5PSIwIiBzdHJva2U9IiM3Nzc3NzciIHN0cm9rZS13aWR0aD0iOCIgc3Ryb2tlLW9wYWNpdHk9IjEiPjwvdXNlPjwvZz48L2c+PC9nPjwvZz48L2c+PC9zdmc+Cg=='),
|
|
||||||
|
|
||||||
cam:atob('PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+CjxzdmcgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJ4TWlkWU1pZCBtZWV0IiB2aWV3Qm94PSIwIDAgMTcwIDE3MCIgd2lkdGg9Ijc1cHgiIGhlaWdodD0iNzVweCI+PGRlZnM+PHBhdGggZD0iTTE1IDM4LjMzQzE1IDM4LjMzIDE1IDM4LjMzIDE1IDM4LjMzQzE1IDI1LjQ1IDI1LjQ1IDE1IDM4LjMzIDE1QzQ0LjU2IDE1IDc1LjY3IDE1IDEzMS42NyAxNUMxMzEuNjcgMTUgMTMxLjY3IDE1IDEzMS42NyAxNUMxMzcuODUgMTUgMTQzLjc5IDE3LjQ2IDE0OC4xNyAyMS44M0MxNTIuNTQgMjYuMjEgMTU1IDMyLjE1IDE1NSAzOC4zM0MxNTUgNDcuNjcgMTU1IDEyMi4zMyAxNTUgMTMxLjY3QzE1NSAxNDQuNTUgMTQ0LjU1IDE1NSAxMzEuNjcgMTU1QzEyMi4zMyAxNTUgNDcuNjcgMTU1IDM4LjMzIDE1NUMyNS40NSAxNTUgMTUgMTQ0LjU1IDE1IDEzMS42N0MxNSAxMTkuMjIgMTUgODguMTEgMTUgMzguMzNaIiBpZD0iZTNpckhhWHI0Ij48L3BhdGg+PHBhdGggZD0iTTY1IDE1TDEwNSAxNUwxMDUgMTI1TDY1IDEyNUw2NSAxNVoiIGlkPSJjMVlrTG9sMTBkIj48L3BhdGg+PHBhdGggZD0iTTEwNSAyNUw2NSA1NSIgaWQ9ImI0aHhqQ0sxenkiPjwvcGF0aD48cGF0aCBkPSJNMTA1IDU1TDY1IDg1IiBpZD0iYXBVYVY4bVp1Ij48L3BhdGg+PHBhdGggZD0iTTEwNSA4NUw2NSAxMTUiIGlkPSJiazIxZElxT3EiPjwvcGF0aD48L2RlZnM+PGc+PGc+PGc+PGc+PHVzZSB4bGluazpocmVmPSIjZTNpckhhWHI0IiBvcGFjaXR5PSIxIiBmaWxsPSIjMDAwMDAwIiBmaWxsLW9wYWNpdHk9IjAiPjwvdXNlPjxnPjx1c2UgeGxpbms6aHJlZj0iI2UzaXJIYVhyNCIgb3BhY2l0eT0iMSIgZmlsbC1vcGFjaXR5PSIwIiBzdHJva2U9IiM3Nzc3NzciIHN0cm9rZS13aWR0aD0iOCIgc3Ryb2tlLW9wYWNpdHk9IjEiPjwvdXNlPjwvZz48L2c+PGc+PHVzZSB4bGluazpocmVmPSIjYzFZa0xvbDEwZCIgb3BhY2l0eT0iMSIgZmlsbD0iIzAwMDAwMCIgZmlsbC1vcGFjaXR5PSIwIj48L3VzZT48Zz48dXNlIHhsaW5rOmhyZWY9IiNjMVlrTG9sMTBkIiBvcGFjaXR5PSIxIiBmaWxsLW9wYWNpdHk9IjAiIHN0cm9rZT0iIzc3Nzc3NyIgc3Ryb2tlLXdpZHRoPSI4IiBzdHJva2Utb3BhY2l0eT0iMSI+PC91c2U+PC9nPjwvZz48Zz48Zz48dXNlIHhsaW5rOmhyZWY9IiNiNGh4akNLMXp5IiBvcGFjaXR5PSIxIiBmaWxsLW9wYWNpdHk9IjAiIHN0cm9rZT0iIzc3Nzc3NyIgc3Ryb2tlLXdpZHRoPSI4LjAxIiBzdHJva2Utb3BhY2l0eT0iMSI+PC91c2U+PC9nPjwvZz48Zz48Zz48dXNlIHhsaW5rOmhyZWY9IiNhcFVhVjhtWnUiIG9wYWNpdHk9IjEiIGZpbGwtb3BhY2l0eT0iMCIgc3Ryb2tlPSIjNzc3Nzc3IiBzdHJva2Utd2lkdGg9IjguMDEiIHN0cm9rZS1vcGFjaXR5PSIxIj48L3VzZT48L2c+PC9nPjxnPjxnPjx1c2UgeGxpbms6aHJlZj0iI2JrMjFkSXFPcSIgb3BhY2l0eT0iMSIgZmlsbC1vcGFjaXR5PSIwIiBzdHJva2U9IiM3Nzc3NzciIHN0cm9rZS13aWR0aD0iOC4wMSIgc3Ryb2tlLW9wYWNpdHk9IjEiPjwvdXNlPjwvZz48L2c+PC9nPjwvZz48L2c+PC9zdmc+Cg=='),
|
|
||||||
|
|
||||||
laser:atob('PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+CjxzdmcgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJ4TWlkWU1pZCBtZWV0IiB2aWV3Qm94PSIwIDAgMTcwIDE3MCIgd2lkdGg9Ijc1cHgiIGhlaWdodD0iNzVweCI+PGRlZnM+PHBhdGggZD0iTTE1IDM4LjMzQzE1IDM4LjMzIDE1IDM4LjMzIDE1IDM4LjMzQzE1IDI1LjQ1IDI1LjQ1IDE1IDM4LjMzIDE1QzQ0LjU2IDE1IDc1LjY3IDE1IDEzMS42NyAxNUMxMzEuNjcgMTUgMTMxLjY3IDE1IDEzMS42NyAxNUMxMzcuODUgMTUgMTQzLjc5IDE3LjQ2IDE0OC4xNyAyMS44M0MxNTIuNTQgMjYuMjEgMTU1IDMyLjE1IDE1NSAzOC4zM0MxNTUgNDcuNjcgMTU1IDEyMi4zMyAxNTUgMTMxLjY3QzE1NSAxNDQuNTUgMTQ0LjU1IDE1NSAxMzEuNjcgMTU1QzEyMi4zMyAxNTUgNDcuNjcgMTU1IDM4LjMzIDE1NUMyNS40NSAxNTUgMTUgMTQ0LjU1IDE1IDEzMS42N0MxNSAxMTkuMjIgMTUgODguMTEgMTUgMzguMzNaIiBpZD0iYTRsMDBtbkVueSI+PC9wYXRoPjxwYXRoIGQ9Ik02NSAxNUwxMDUgMTVMMTA1IDU1TDY1IDU1TDY1IDE1WiIgaWQ9ImJxOG9CV3JmRyI+PC9wYXRoPjxwYXRoIGQ9Ik04NSAxMjVMODUgNjUiIGlkPSJhWHpIdEdic0QiPjwvcGF0aD48cGF0aCBkPSJNNTUgMTA1TDc1IDEzNSIgaWQ9ImFrU3poMFFLeCI+PC9wYXRoPjxwYXRoIGQ9Ik0xMTUgMTA1TDk1IDEzNSIgaWQ9ImJsb0FzOWdpWiI+PC9wYXRoPjxwYXRoIGQ9Ik0zNSAxMjVMNzUgMTQ1IiBpZD0iZ2s2b2hqMEpMIj48L3BhdGg+PHBhdGggZD0iTTEzNSAxMjMuOTZMOTUgMTQ1IiBpZD0iZTQwNGVvajdMIj48L3BhdGg+PC9kZWZzPjxnPjxnPjxnPjxnPjx1c2UgeGxpbms6aHJlZj0iI2E0bDAwbW5FbnkiIG9wYWNpdHk9IjEiIGZpbGw9IiMwMDAwMDAiIGZpbGwtb3BhY2l0eT0iMCI+PC91c2U+PGc+PHVzZSB4bGluazpocmVmPSIjYTRsMDBtbkVueSIgb3BhY2l0eT0iMSIgZmlsbC1vcGFjaXR5PSIwIiBzdHJva2U9IiM3Nzc3NzciIHN0cm9rZS13aWR0aD0iOCIgc3Ryb2tlLW9wYWNpdHk9IjEiPjwvdXNlPjwvZz48L2c+PGc+PHVzZSB4bGluazpocmVmPSIjYnE4b0JXcmZHIiBvcGFjaXR5PSIxIiBmaWxsPSIjMDAwMDAwIiBmaWxsLW9wYWNpdHk9IjAiPjwvdXNlPjxnPjx1c2UgeGxpbms6aHJlZj0iI2JxOG9CV3JmRyIgb3BhY2l0eT0iMSIgZmlsbC1vcGFjaXR5PSIwIiBzdHJva2U9IiM3Nzc3NzciIHN0cm9rZS13aWR0aD0iOCIgc3Ryb2tlLW9wYWNpdHk9IjEiPjwvdXNlPjwvZz48L2c+PGc+PGc+PHVzZSB4bGluazpocmVmPSIjYVh6SHRHYnNEIiBvcGFjaXR5PSIxIiBmaWxsLW9wYWNpdHk9IjAiIHN0cm9rZT0iIzc3Nzc3NyIgc3Ryb2tlLXdpZHRoPSI4LjAxIiBzdHJva2Utb3BhY2l0eT0iMSI+PC91c2U+PC9nPjwvZz48Zz48Zz48dXNlIHhsaW5rOmhyZWY9IiNha1N6aDBRS3giIG9wYWNpdHk9IjEiIGZpbGwtb3BhY2l0eT0iMCIgc3Ryb2tlPSIjNzc3Nzc3IiBzdHJva2Utd2lkdGg9IjguMDEiIHN0cm9rZS1vcGFjaXR5PSIxIj48L3VzZT48L2c+PC9nPjxnPjxnPjx1c2UgeGxpbms6aHJlZj0iI2Jsb0FzOWdpWiIgb3BhY2l0eT0iMSIgZmlsbC1vcGFjaXR5PSIwIiBzdHJva2U9IiM3Nzc3NzciIHN0cm9rZS13aWR0aD0iOC4wMSIgc3Ryb2tlLW9wYWNpdHk9IjEiPjwvdXNlPjwvZz48L2c+PGc+PGc+PHVzZSB4bGluazpocmVmPSIjZ2s2b2hqMEpMIiBvcGFjaXR5PSIxIiBmaWxsLW9wYWNpdHk9IjAiIHN0cm9rZT0iIzc3Nzc3NyIgc3Ryb2tlLXdpZHRoPSI4LjAxIiBzdHJva2Utb3BhY2l0eT0iMSI+PC91c2U+PC9nPjwvZz48Zz48Zz48dXNlIHhsaW5rOmhyZWY9IiNlNDA0ZW9qN0wiIG9wYWNpdHk9IjEiIGZpbGwtb3BhY2l0eT0iMCIgc3Ryb2tlPSIjNzc3Nzc3IiBzdHJva2Utd2lkdGg9IjguMDEiIHN0cm9rZS1vcGFjaXR5PSIxIj48L3VzZT48L2c+PC9nPjwvZz48L2c+PC9nPjwvc3ZnPgo='),
|
|
||||||
|
|
||||||
sla:atob('PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+CjxzdmcgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJ4TWlkWU1pZCBtZWV0IiB2aWV3Qm94PSIwIDAgMTcwIDE3MCIgd2lkdGg9Ijc1cHgiIGhlaWdodD0iNzVweCI+PGRlZnM+PHBhdGggZD0iTTE1IDM4LjMzQzE1IDM4LjMzIDE1IDM4LjMzIDE1IDM4LjMzQzE1IDI1LjQ1IDI1LjQ1IDE1IDM4LjMzIDE1QzQ0LjU2IDE1IDc1LjY3IDE1IDEzMS42NyAxNUMxMzEuNjcgMTUgMTMxLjY3IDE1IDEzMS42NyAxNUMxMzcuODUgMTUgMTQzLjc5IDE3LjQ2IDE0OC4xNyAyMS44M0MxNTIuNTQgMjYuMjEgMTU1IDMyLjE1IDE1NSAzOC4zM0MxNTUgNDcuNjcgMTU1IDEyMi4zMyAxNTUgMTMxLjY3QzE1NSAxNDQuNTUgMTQ0LjU1IDE1NSAxMzEuNjcgMTU1QzEyMi4zMyAxNTUgNDcuNjcgMTU1IDM4LjMzIDE1NUMyNS40NSAxNTUgMTUgMTQ0LjU1IDE1IDEzMS42N0MxNSAxMTkuMjIgMTUgODguMTEgMTUgMzguMzNaIiBpZD0iYjNUUk5IeWJ4WCI+PC9wYXRoPjxwYXRoIGQ9Ik0zMS44OCA0Mi41TDEzOC4xMiA0Mi41TDEzOC4xMiA0Ny44MUwzMS44OCA0Ny44MUwzMS44OCA0Mi41WiIgaWQ9ImFOTWt6THdiIj48L3BhdGg+PHBhdGggZD0iTTc1IDIxLjg3TDk1IDIxLjg3TDk1IDQxLjg4TDc1IDQxLjg4TDc1IDIxLjg3WiIgaWQ9ImQxZktLZzJKcnUiPjwvcGF0aD48cGF0aCBkPSJNMTE1LjkzIDEwNy4xOUMxMTUuOTMgMTI0LjI3IDEwMi4wNyAxMzguMTMgODUgMTM4LjEzQzY3LjkzIDEzOC4xMyA1NC4wNyAxMjQuMjcgNTQuMDcgMTA3LjE5QzU0LjA3IDkwLjEyIDY3LjkzIDc2LjI2IDg1IDc2LjI2QzEwMi4wNyA3Ni4yNiAxMTUuOTMgOTAuMTIgMTE1LjkzIDEwNy4xOVoiIGlkPSJjbnlyY1RRTWciPjwvcGF0aD48cGF0aCBkPSJNNTMuODcgNDcuODFMNTMuODcgMTA3LjA4IiBpZD0iYTRHOVJyNlZRTCI+PC9wYXRoPjxwYXRoIGQ9Ik0xMTUuNzYgNTEuMjdMMTE1Ljc2IDExMC41MyIgaWQ9ImQ0aHl0eVNReFoiPjwvcGF0aD48cGF0aCBkPSJNNjkuMDYgNzkuNjlMNjkuMDYgNDcuODEiIGlkPSJiMVdRODNFTEFBIj48L3BhdGg+PHBhdGggZD0iTTEwMC45NCA3OS42OUwxMDAuOTQgNDcuODEiIGlkPSJmMmtOSHNsYUxhIj48L3BhdGg+PHBhdGggZD0iTTY5LjA2IDU4LjQ0TDUzLjEzIDc0LjM4IiBpZD0iZzY3dkZKd0FGeSI+PC9wYXRoPjxwYXRoIGQ9Ik0xMTQuNjggNTguNDRMMTAwLjk0IDY5LjA2IiBpZD0iYUFjcDN6NUt2Ij48L3BhdGg+PC9kZWZzPjxnPjxnPjxnPjx1c2UgeGxpbms6aHJlZj0iI2IzVFJOSHlieFgiIG9wYWNpdHk9IjEiIGZpbGw9IiMwMDAwMDAiIGZpbGwtb3BhY2l0eT0iMCI+PC91c2U+PGc+PHVzZSB4bGluazpocmVmPSIjYjNUUk5IeWJ4WCIgb3BhY2l0eT0iMSIgZmlsbC1vcGFjaXR5PSIwIiBzdHJva2U9IiM3Nzc3NzciIHN0cm9rZS13aWR0aD0iOCIgc3Ryb2tlLW9wYWNpdHk9IjEiPjwvdXNlPjwvZz48L2c+PGc+PHVzZSB4bGluazpocmVmPSIjYU5Na3pMd2IiIG9wYWNpdHk9IjEiIGZpbGw9IiMwMDAwMDAiIGZpbGwtb3BhY2l0eT0iMCI+PC91c2U+PGc+PHVzZSB4bGluazpocmVmPSIjYU5Na3pMd2IiIG9wYWNpdHk9IjEiIGZpbGwtb3BhY2l0eT0iMCIgc3Ryb2tlPSIjNzc3Nzc3IiBzdHJva2Utd2lkdGg9IjgiIHN0cm9rZS1vcGFjaXR5PSIxIj48L3VzZT48L2c+PC9nPjxnPjx1c2UgeGxpbms6aHJlZj0iI2QxZktLZzJKcnUiIG9wYWNpdHk9IjEiIGZpbGw9IiMwMDAwMDAiIGZpbGwtb3BhY2l0eT0iMCI+PC91c2U+PGc+PHVzZSB4bGluazpocmVmPSIjZDFmS0tnMkpydSIgb3BhY2l0eT0iMSIgZmlsbC1vcGFjaXR5PSIwIiBzdHJva2U9IiM3Nzc3NzciIHN0cm9rZS13aWR0aD0iOCIgc3Ryb2tlLW9wYWNpdHk9IjEiPjwvdXNlPjwvZz48L2c+PGc+PHVzZSB4bGluazpocmVmPSIjY255cmNUUU1nIiBvcGFjaXR5PSIxIiBmaWxsPSIjMWVhNWU2IiBmaWxsLW9wYWNpdHk9IjAiPjwvdXNlPjxnPjx1c2UgeGxpbms6aHJlZj0iI2NueXJjVFFNZyIgb3BhY2l0eT0iMSIgZmlsbC1vcGFjaXR5PSIwIiBzdHJva2U9IiM3Nzc3NzciIHN0cm9rZS13aWR0aD0iOCIgc3Ryb2tlLW9wYWNpdHk9IjEiPjwvdXNlPjwvZz48L2c+PGc+PGc+PHVzZSB4bGluazpocmVmPSIjYTRHOVJyNlZRTCIgb3BhY2l0eT0iMSIgZmlsbC1vcGFjaXR5PSIwIiBzdHJva2U9IiM3Nzc3NzciIHN0cm9rZS13aWR0aD0iOCIgc3Ryb2tlLW9wYWNpdHk9IjEiPjwvdXNlPjwvZz48L2c+PGc+PGc+PHVzZSB4bGluazpocmVmPSIjZDRoeXR5U1F4WiIgb3BhY2l0eT0iMSIgZmlsbC1vcGFjaXR5PSIwIiBzdHJva2U9IiM3Nzc3NzciIHN0cm9rZS13aWR0aD0iOCIgc3Ryb2tlLW9wYWNpdHk9IjEiPjwvdXNlPjwvZz48L2c+PGc+PGc+PHVzZSB4bGluazpocmVmPSIjYjFXUTgzRUxBQSIgb3BhY2l0eT0iMSIgZmlsbC1vcGFjaXR5PSIwIiBzdHJva2U9IiM3Nzc3NzciIHN0cm9rZS13aWR0aD0iOCIgc3Ryb2tlLW9wYWNpdHk9IjEiPjwvdXNlPjwvZz48L2c+PGc+PGc+PHVzZSB4bGluazpocmVmPSIjZjJrTkhzbGFMYSIgb3BhY2l0eT0iMSIgZmlsbC1vcGFjaXR5PSIwIiBzdHJva2U9IiM3Nzc3NzciIHN0cm9rZS13aWR0aD0iOCIgc3Ryb2tlLW9wYWNpdHk9IjEiPjwvdXNlPjwvZz48L2c+PGc+PGc+PHVzZSB4bGluazpocmVmPSIjZzY3dkZKd0FGeSIgb3BhY2l0eT0iMSIgZmlsbC1vcGFjaXR5PSIwIiBzdHJva2U9IiM3Nzc3NzciIHN0cm9rZS13aWR0aD0iNiIgc3Ryb2tlLW9wYWNpdHk9IjEiPjwvdXNlPjwvZz48L2c+PGc+PGc+PHVzZSB4bGluazpocmVmPSIjYUFjcDN6NUt2IiBvcGFjaXR5PSIxIiBmaWxsLW9wYWNpdHk9IjAiIHN0cm9rZT0iIzc3Nzc3NyIgc3Ryb2tlLXdpZHRoPSI2IiBzdHJva2Utb3BhY2l0eT0iMSI+PC91c2U+PC9nPjwvZz48L2c+PC9nPjwvc3ZnPgo=')
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
})();
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../web/kiri/lang/en.js
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
var exports = {
|
|
||||||
COPYRIGHT:"Copyright (C) Stewart Allen <sa@grid.space> - All Rights Reserved",
|
|
||||||
LICENSE:"See the license.md file included with the source distribution",
|
|
||||||
VERSION:"2.0.5"
|
|
||||||
};
|
|
||||||
if (!module) var module = {};
|
|
||||||
module.exports = exports;
|
|
||||||
1432
js/web-server.js
1432
js/web-server.js
File diff suppressed because it is too large
Load diff
5
notes.md
5
notes.md
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
## `C` cosmetic, `F` functional, `P` performance, `B` bug fix
|
## `C` cosmetic, `F` functional, `P` performance, `B` bug fix
|
||||||
|
|
||||||
|
* `C` hover mode to see device / settings selections
|
||||||
* `F` implement an in-app bug reporting system
|
* `F` implement an in-app bug reporting system
|
||||||
* `F` extend mesh object to store raw + annotations (rot,scale,pos)
|
* `F` extend mesh object to store raw + annotations (rot,scale,pos)
|
||||||
* share raw data w/ dups, encode/decode
|
* share raw data w/ dups, encode/decode
|
||||||
|
|
@ -15,6 +16,8 @@
|
||||||
|
|
||||||
# FDM
|
# FDM
|
||||||
|
|
||||||
|
* `B` fix adaptive slicing with multi-extruder
|
||||||
|
* `B` fix supports with grouped parts
|
||||||
* `F` control for size of purge block (with 0=disabled)
|
* `F` control for size of purge block (with 0=disabled)
|
||||||
* `F` add separate fill speed control
|
* `F` add separate fill speed control
|
||||||
* `F` manual support addition / control
|
* `F` manual support addition / control
|
||||||
|
|
@ -29,6 +32,7 @@
|
||||||
* `F` determine start point from gcode preamble
|
* `F` determine start point from gcode preamble
|
||||||
* `F` trim support offset from layer below
|
* `F` trim support offset from layer below
|
||||||
* `F` option to support interior bridges when 0% infill
|
* `F` option to support interior bridges when 0% infill
|
||||||
|
* `F` calculate filament use per extruder per print
|
||||||
* `P` refactor thin fill to use outline and inside poly normal dist to self
|
* `P` refactor thin fill to use outline and inside poly normal dist to self
|
||||||
* `P` segment large polygons for extremely large parts / infill
|
* `P` segment large polygons for extremely large parts / infill
|
||||||
* `P` implement infill clipping in wasm
|
* `P` implement infill clipping in wasm
|
||||||
|
|
@ -44,7 +48,6 @@
|
||||||
* `B` linear finishing should extend beyond part boundaries by tool radius
|
* `B` linear finishing should extend beyond part boundaries by tool radius
|
||||||
* `B` outside cutting direction in roughing mode inverted
|
* `B` outside cutting direction in roughing mode inverted
|
||||||
* `F` z bounded slices (extension of z bottom offset feature)
|
* `F` z bounded slices (extension of z bottom offset feature)
|
||||||
* `F` do not mill out thru-pockets. cut outline only.
|
|
||||||
* `F` use arcs to connect hard angles
|
* `F` use arcs to connect hard angles
|
||||||
* `F` do not rough areas that go all the way through the part
|
* `F` do not rough areas that go all the way through the part
|
||||||
https://github.com/GridSpace/grid-apps/issues/20
|
https://github.com/GridSpace/grid-apps/issues/20
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "grid-apps",
|
"name": "grid-apps",
|
||||||
"version": "1.1.3",
|
"version": "3.0.0-dev",
|
||||||
"description": "grid.space 3d slice & modeling tools",
|
"description": "grid.space 3d slice & modeling tools",
|
||||||
"author": "Stewart Allen <sa@grid.space>",
|
"author": "Stewart Allen <sa@grid.space>",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|
|
||||||
1
src/ext/earcut.js
Symbolic link
1
src/ext/earcut.js
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../../node_modules/earcut/src/earcut.js
|
||||||
1
src/ext/three.js
Symbolic link
1
src/ext/three.js
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../../node_modules/three/build/three.min.js
|
||||||
1
src/ext/tween.js
Symbolic link
1
src/ext/tween.js
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../../node_modules/tween.js/index.js
|
||||||
|
|
@ -1,22 +1,19 @@
|
||||||
/** Copyright 2014-2019 Stewart Allen -- All Rights Reserved */
|
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var gs_base = exports;
|
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
if (!self.base) self.base = {};
|
if (self.base) return;
|
||||||
if (self.base.util) return;
|
|
||||||
|
|
||||||
var BASE = self.base,
|
const BASE = self.base = {},
|
||||||
round_decimal_precision = 8;
|
round_decimal_precision = 8;
|
||||||
|
|
||||||
/** ******************************************************************
|
/** ******************************************************************
|
||||||
* Utility Functions
|
* Utility Functions
|
||||||
******************************************************************* */
|
******************************************************************* */
|
||||||
|
|
||||||
function time() { return new Date().getTime() }
|
function time() { return Date.now() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* call function with all combinations of a1, a2
|
* call function with all combinations of a1, a2
|
||||||
|
|
@ -29,7 +26,7 @@ var gs_base = exports;
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
function doCombinations(a1, a2, arg, fn) {
|
function doCombinations(a1, a2, arg, fn) {
|
||||||
var i, j;
|
let i, j;
|
||||||
for (i = 0; i < a1.length; i++) {
|
for (i = 0; i < a1.length; i++) {
|
||||||
for (j = (a1 === a2 ? i + 1 : 0); j < a2.length; j++) {
|
for (j = (a1 === a2 ? i + 1 : 0); j < a2.length; j++) {
|
||||||
fn(a1[i], a2[j], arg);
|
fn(a1[i], a2[j], arg);
|
||||||
|
|
@ -151,7 +148,7 @@ var gs_base = exports;
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
function inRange(value, min, max) {
|
function inRange(value, min, max) {
|
||||||
var val = parseFloat(value);
|
let val = parseFloat(value);
|
||||||
return val >= min && val <= max;
|
return val >= min && val <= max;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -162,7 +159,7 @@ var gs_base = exports;
|
||||||
* @returns {number}
|
* @returns {number}
|
||||||
*/
|
*/
|
||||||
function round(v, zeros) {
|
function round(v, zeros) {
|
||||||
var pow = Math.pow(10,zeros || round_decimal_precision);
|
let pow = Math.pow(10,zeros || round_decimal_precision);
|
||||||
return Math.round(v * pow) / pow;
|
return Math.round(v * pow) / pow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -178,7 +175,7 @@ var gs_base = exports;
|
||||||
* @returns {?Point | String}
|
* @returns {?Point | String}
|
||||||
*/
|
*/
|
||||||
function intersect(p1, p2, p3, p4, test, parallelok) {
|
function intersect(p1, p2, p3, p4, test, parallelok) {
|
||||||
var keys = BASE.key,
|
let keys = BASE.key,
|
||||||
p1x = p1.x,
|
p1x = p1.x,
|
||||||
p1y = p1.y,
|
p1y = p1.y,
|
||||||
p2x = p2.x,
|
p2x = p2.x,
|
||||||
|
|
@ -199,7 +196,7 @@ var gs_base = exports;
|
||||||
return test && !parallelok ? null : keys.PARALLEL;
|
return test && !parallelok ? null : keys.PARALLEL;
|
||||||
}
|
}
|
||||||
|
|
||||||
var a = p1y - p3y, // origin dy
|
let a = p1y - p3y, // origin dy
|
||||||
b = p1x - p3x, // origin dx
|
b = p1x - p3x, // origin dx
|
||||||
n1 = (d2x * a) - (d2y * b),
|
n1 = (d2x * a) - (d2y * b),
|
||||||
n2 = (d1x * a) - (d1y * b);
|
n2 = (d1x * a) - (d1y * b);
|
||||||
|
|
@ -207,7 +204,7 @@ var gs_base = exports;
|
||||||
a = n1 / d; // roughly distance from l1 origin to l2 intersection
|
a = n1 / d; // roughly distance from l1 origin to l2 intersection
|
||||||
b = n2 / d; // roughly distance from l2 origin to l1 intersection
|
b = n2 / d; // roughly distance from l2 origin to l1 intersection
|
||||||
|
|
||||||
var ia = a >= -0.0001 && a <= 1.0001,
|
let ia = a >= -0.0001 && a <= 1.0001,
|
||||||
ib = b >= -0.0001 && b <= 1.0001,
|
ib = b >= -0.0001 && b <= 1.0001,
|
||||||
segint = (ia && ib),
|
segint = (ia && ib),
|
||||||
rayint = (a >= 0 && b >= 0);
|
rayint = (a >= 0 && b >= 0);
|
||||||
|
|
@ -215,7 +212,7 @@ var gs_base = exports;
|
||||||
if (test === keys.SEGINT && !segint) return null;
|
if (test === keys.SEGINT && !segint) return null;
|
||||||
if (test === keys.RAYINT && !rayint) return null;
|
if (test === keys.RAYINT && !rayint) return null;
|
||||||
|
|
||||||
var ip = BASE.newPoint(
|
let ip = BASE.newPoint(
|
||||||
p1x + (a * d1x), // x
|
p1x + (a * d1x), // x
|
||||||
p1y + (a * d1y), // y
|
p1y + (a * d1y), // y
|
||||||
p3.z || p4.z, // z
|
p3.z || p4.z, // z
|
||||||
|
|
@ -240,7 +237,7 @@ var gs_base = exports;
|
||||||
* @returns {?Point}
|
* @returns {?Point}
|
||||||
*/
|
*/
|
||||||
function intersectRayLine(ro, s1, p1, p2, infinite) {
|
function intersectRayLine(ro, s1, p1, p2, infinite) {
|
||||||
var keys = BASE.key,
|
let keys = BASE.key,
|
||||||
p1x = ro.x,
|
p1x = ro.x,
|
||||||
p1y = ro.y,
|
p1y = ro.y,
|
||||||
s1x = s1.dx,
|
s1x = s1.dx,
|
||||||
|
|
@ -253,7 +250,7 @@ var gs_base = exports;
|
||||||
s2y = p4y - p3y,
|
s2y = p4y - p3y,
|
||||||
d = (s2y * s1x) - (s2x * s1y);
|
d = (s2y * s1x) - (s2x * s1y);
|
||||||
|
|
||||||
var a = p1y - p3y,
|
let a = p1y - p3y,
|
||||||
b = p1x - p3x,
|
b = p1x - p3x,
|
||||||
n1 = (s2x * a) - (s2y * b),
|
n1 = (s2x * a) - (s2y * b),
|
||||||
n2 = (s1x * a) - (s1y * b);
|
n2 = (s1x * a) - (s1y * b);
|
||||||
|
|
@ -267,7 +264,7 @@ var gs_base = exports;
|
||||||
b = n2 / d;
|
b = n2 / d;
|
||||||
|
|
||||||
if (infinite || (inCloseRange(b,0,1) && a >= 0)) {
|
if (infinite || (inCloseRange(b,0,1) && a >= 0)) {
|
||||||
var ip = BASE.newPoint(
|
let ip = BASE.newPoint(
|
||||||
p1x + (a * s1x),
|
p1x + (a * s1x),
|
||||||
p1y + (a * s1y),
|
p1y + (a * s1y),
|
||||||
p2.z || ro.z,
|
p2.z || ro.z,
|
||||||
|
|
@ -289,7 +286,7 @@ var gs_base = exports;
|
||||||
* @returns {number}
|
* @returns {number}
|
||||||
*/
|
*/
|
||||||
function determinant(p1, p2, p3, p4) {
|
function determinant(p1, p2, p3, p4) {
|
||||||
var d1x = (p2.x - p1.x),
|
let d1x = (p2.x - p1.x),
|
||||||
d1y = (p2.y - p1.y),
|
d1y = (p2.y - p1.y),
|
||||||
d2x = (p4.x - p3.x),
|
d2x = (p4.x - p3.x),
|
||||||
d2y = (p4.y - p3.y);
|
d2y = (p4.y - p3.y);
|
||||||
|
|
@ -2,11 +2,8 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var gs_base_bounds = exports;
|
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
if (!self.base) self.base = {};
|
|
||||||
if (self.base.Bounds) return;
|
if (self.base.Bounds) return;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -21,12 +18,9 @@ var gs_base_bounds = exports;
|
||||||
this.leftMost = null;
|
this.leftMost = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var BASE = self.base,
|
const BASE = self.base,
|
||||||
UTIL = BASE.util,
|
UTIL = BASE.util,
|
||||||
CONF = BASE.config,
|
CONF = BASE.config,
|
||||||
ABS = Math.abs,
|
|
||||||
MIN = Math.min,
|
|
||||||
MAX = Math.max,
|
|
||||||
PRO = Bounds.prototype;
|
PRO = Bounds.prototype;
|
||||||
|
|
||||||
BASE.Bounds = Bounds;
|
BASE.Bounds = Bounds;
|
||||||
|
|
@ -40,7 +34,7 @@ var gs_base_bounds = exports;
|
||||||
* @returns {Bounds}
|
* @returns {Bounds}
|
||||||
*/
|
*/
|
||||||
PRO.clone = function() {
|
PRO.clone = function() {
|
||||||
var b = new Bounds();
|
let b = new Bounds();
|
||||||
b.minx = this.minx;
|
b.minx = this.minx;
|
||||||
b.miny = this.miny;
|
b.miny = this.miny;
|
||||||
b.maxx = this.maxx;
|
b.maxx = this.maxx;
|
||||||
|
|
@ -60,20 +54,20 @@ var gs_base_bounds = exports;
|
||||||
* @param {Bounds} b
|
* @param {Bounds} b
|
||||||
*/
|
*/
|
||||||
PRO.merge = function(b) {
|
PRO.merge = function(b) {
|
||||||
this.minx = MIN(this.minx, b.minx);
|
this.minx = Math.min(this.minx, b.minx);
|
||||||
this.maxx = MAX(this.maxx, b.maxx);
|
this.maxx = Math.max(this.maxx, b.maxx);
|
||||||
this.miny = MIN(this.miny, b.miny);
|
this.miny = Math.min(this.miny, b.miny);
|
||||||
this.maxy = MAX(this.maxy, b.maxy);
|
this.maxy = Math.max(this.maxy, b.maxy);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Point} p
|
* @param {Point} p
|
||||||
*/
|
*/
|
||||||
PRO.update = function(p) {
|
PRO.update = function(p) {
|
||||||
this.minx = MIN(this.minx, p.x);
|
this.minx = Math.min(this.minx, p.x);
|
||||||
this.maxx = MAX(this.maxx, p.x);
|
this.maxx = Math.max(this.maxx, p.x);
|
||||||
this.miny = MIN(this.miny, p.y);
|
this.miny = Math.min(this.miny, p.y);
|
||||||
this.maxy = MAX(this.maxy, p.y);
|
this.maxy = Math.max(this.maxy, p.y);
|
||||||
if (this.minx === p.x) this.leftMost = p;
|
if (this.minx === p.x) this.leftMost = p;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -109,8 +103,8 @@ var gs_base_bounds = exports;
|
||||||
*/
|
*/
|
||||||
PRO.overlaps = function(b, precision) {
|
PRO.overlaps = function(b, precision) {
|
||||||
return (
|
return (
|
||||||
ABS(this.centerx() - b.centerx()) * 2 - precision < this.width() + b.width() &&
|
Math.abs(this.centerx() - b.centerx()) * 2 - precision < this.width() + b.width() &&
|
||||||
ABS(this.centery() - b.centery()) * 2 - precision < this.height() + b.height()
|
Math.abs(this.centery() - b.centery()) * 2 - precision < this.height() + b.height()
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -2,21 +2,19 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var gs_base_debug = exports;
|
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
if (!self.base) self.base = {};
|
|
||||||
if (self.base.debug) return;
|
if (self.base.debug) return;
|
||||||
|
|
||||||
var base = self.base,
|
const base = self.base,
|
||||||
enabled = false,
|
|
||||||
flags = {},
|
flags = {},
|
||||||
stash = [],
|
stash = [],
|
||||||
size = 20,
|
|
||||||
next_debug_color = 0,
|
|
||||||
debug_colors = [0xff0000, 0x00ff00, 0x0000ff, 0x00ffff, 0xff00ff, 0xffff00];
|
debug_colors = [0xff0000, 0x00ff00, 0x0000ff, 0x00ffff, 0xff00ff, 0xffff00];
|
||||||
|
|
||||||
|
let size = 20,
|
||||||
|
enabled = false,
|
||||||
|
next_debug_color = 0;
|
||||||
|
|
||||||
/** ******************************************************************
|
/** ******************************************************************
|
||||||
* Debug Functions
|
* Debug Functions
|
||||||
******************************************************************* */
|
******************************************************************* */
|
||||||
|
|
@ -69,7 +67,7 @@ var gs_base_debug = exports;
|
||||||
|
|
||||||
function set(f, value) {
|
function set(f, value) {
|
||||||
if (Array.isArray(f)) {
|
if (Array.isArray(f)) {
|
||||||
for (var i=0; i<f.length; i++) flags[f[i]] = (value || 1);
|
for (let i=0; i<f.length; i++) flags[f[i]] = (value || 1);
|
||||||
} else {
|
} else {
|
||||||
flags[f] = (value || 1);
|
flags[f] = (value || 1);
|
||||||
}
|
}
|
||||||
|
|
@ -77,14 +75,14 @@ var gs_base_debug = exports;
|
||||||
|
|
||||||
function clear(f) {
|
function clear(f) {
|
||||||
if (Array.isArray(f)) {
|
if (Array.isArray(f)) {
|
||||||
for (var i = 0; i < f.length; i++) delete flags[f[i]];
|
for (let i = 0; i < f.length; i++) delete flags[f[i]];
|
||||||
} else {
|
} else {
|
||||||
delete flags[f];
|
delete flags[f];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function test(isSet, isNotSet) {
|
function test(isSet, isNotSet) {
|
||||||
var i;
|
let i;
|
||||||
if (isNotSet) {
|
if (isNotSet) {
|
||||||
if (Array.isArray(isNotSet)) {
|
if (Array.isArray(isNotSet)) {
|
||||||
for (i=0; i<isNotSet.length; i++) {
|
for (i=0; i<isNotSet.length; i++) {
|
||||||
|
|
@ -154,7 +152,7 @@ var gs_base_debug = exports;
|
||||||
* @param {boolean} [creep]
|
* @param {boolean} [creep]
|
||||||
*/
|
*/
|
||||||
function xray(poly, z, v, deep, creep) {
|
function xray(poly, z, v, deep, creep) {
|
||||||
var colors = [
|
let colors = [
|
||||||
0xaa0000,
|
0xaa0000,
|
||||||
0x0,
|
0x0,
|
||||||
0xaaaa00,
|
0xaaaa00,
|
||||||
|
|
@ -1,16 +1,13 @@
|
||||||
/** Copyright 2014-2019 Stewart Allen -- All Rights Reserved */
|
/** Copyright Stewart Allen -- All Rights Reserved */
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var gs_base_gyroid = exports;
|
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
if (!self.base) self.base = {};
|
|
||||||
if (self.base.gyroid) return;
|
if (self.base.gyroid) return;
|
||||||
|
|
||||||
var base = self.base;
|
const base = self.base,
|
||||||
|
PI2 = Math.PI * 2;
|
||||||
let PI2 = Math.PI * 2;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param off {number} z offset value from 0-1
|
* @param off {number} z offset value from 0-1
|
||||||
|
|
@ -1,14 +1,17 @@
|
||||||
/** Copyright 2014-2019 Stewart Allen -- All Rights Reserved */
|
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var gs_base_line = exports;
|
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
if (!self.base) self.base = {};
|
|
||||||
if (self.base.Line) return;
|
if (self.base.Line) return;
|
||||||
|
|
||||||
|
const BASE = self.base, PRO = Line.prototype;
|
||||||
|
|
||||||
|
BASE.Line = Line;
|
||||||
|
BASE.newLine = newLine;
|
||||||
|
BASE.newOrderedLine = newOrderedLine;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {Point} p1
|
* @param {Point} p1
|
||||||
|
|
@ -26,13 +29,6 @@ var gs_base_line = exports;
|
||||||
this.del = false;
|
this.del = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var BASE = self.base,
|
|
||||||
PRO = Line.prototype;
|
|
||||||
|
|
||||||
BASE.Line = Line;
|
|
||||||
BASE.newLine = newLine;
|
|
||||||
BASE.newOrderedLine = newOrderedLine;
|
|
||||||
|
|
||||||
/** ******************************************************************
|
/** ******************************************************************
|
||||||
* Line Prototype Functions
|
* Line Prototype Functions
|
||||||
******************************************************************* */
|
******************************************************************* */
|
||||||
|
|
@ -62,7 +58,7 @@ var gs_base_line = exports;
|
||||||
* @returns {Line}
|
* @returns {Line}
|
||||||
*/
|
*/
|
||||||
PRO.reverse = function() {
|
PRO.reverse = function() {
|
||||||
var t = this.p1;
|
let t = this.p1;
|
||||||
this.p1 = this.p2;
|
this.p1 = this.p2;
|
||||||
this.p2 = t;
|
this.p2 = t;
|
||||||
return this;
|
return this;
|
||||||
|
|
@ -80,7 +76,7 @@ var gs_base_line = exports;
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
PRO.isCollinear = function(line) {
|
PRO.isCollinear = function(line) {
|
||||||
var p1 = this.p1,
|
let p1 = this.p1,
|
||||||
p2 = this.p2,
|
p2 = this.p2,
|
||||||
p3 = line.p1,
|
p3 = line.p1,
|
||||||
p4 = line.p2,
|
p4 = line.p2,
|
||||||
|
|
@ -1,14 +1,21 @@
|
||||||
/** Copyright 2014-2019 Stewart Allen -- All Rights Reserved */
|
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var gs_base_point = exports;
|
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
if (!self.base) self.base = {};
|
|
||||||
if (self.base.Point) return;
|
if (self.base.Point) return;
|
||||||
|
|
||||||
|
const BASE = self.base,
|
||||||
|
UTIL = BASE.util,
|
||||||
|
CONF = BASE.config,
|
||||||
|
KEYS = BASE.key,
|
||||||
|
ROUND = UTIL.round,
|
||||||
|
PRO = Point.prototype;
|
||||||
|
|
||||||
|
BASE.Point = Point;
|
||||||
|
BASE.newPoint = newPoint;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {number} x
|
* @param {number} x
|
||||||
|
|
@ -44,16 +51,6 @@ var gs_base_point = exports;
|
||||||
this.group = null; // for grouping in slice intersect, offset lines in trace
|
this.group = null; // for grouping in slice intersect, offset lines in trace
|
||||||
}
|
}
|
||||||
|
|
||||||
var BASE = self.base,
|
|
||||||
UTIL = BASE.util,
|
|
||||||
CONF = BASE.config,
|
|
||||||
KEYS = BASE.key,
|
|
||||||
ROUND = UTIL.round,
|
|
||||||
PRO = Point.prototype;
|
|
||||||
|
|
||||||
BASE.Point = Point;
|
|
||||||
BASE.newPoint = newPoint;
|
|
||||||
|
|
||||||
/** ******************************************************************
|
/** ******************************************************************
|
||||||
* Point Prototype Functions
|
* Point Prototype Functions
|
||||||
******************************************************************* */
|
******************************************************************* */
|
||||||
|
|
@ -64,14 +61,14 @@ var gs_base_point = exports;
|
||||||
}
|
}
|
||||||
|
|
||||||
PRO.swapXZ = function() {
|
PRO.swapXZ = function() {
|
||||||
var p = this,
|
let p = this,
|
||||||
t = p.x;
|
t = p.x;
|
||||||
p.x = p.z;
|
p.x = p.z;
|
||||||
p.z = t;
|
p.z = t;
|
||||||
};
|
};
|
||||||
|
|
||||||
PRO.swapYZ = function() {
|
PRO.swapYZ = function() {
|
||||||
var p = this,
|
let p = this,
|
||||||
t = p.y;
|
t = p.y;
|
||||||
p.y = p.z;
|
p.y = p.z;
|
||||||
p.z = t;
|
p.z = t;
|
||||||
|
|
@ -163,10 +160,10 @@ var gs_base_point = exports;
|
||||||
* @returns {number}
|
* @returns {number}
|
||||||
*/
|
*/
|
||||||
PRO.distToLineSq = function(p1, p2) {
|
PRO.distToLineSq = function(p1, p2) {
|
||||||
var p = this,
|
let p = this,
|
||||||
d = UTIL.distSq(p1, p2);
|
d = UTIL.distSq(p1, p2);
|
||||||
|
|
||||||
var t = ((p.x - p1.x) * (p2.x - p1.x) + (p.y - p1.y) * (p2.y - p1.y)) / d;
|
let t = ((p.x - p1.x) * (p2.x - p1.x) + (p.y - p1.y) * (p2.y - p1.y)) / d;
|
||||||
|
|
||||||
if (t < 0) return UTIL.distSq(p, p1);
|
if (t < 0) return UTIL.distSq(p, p1);
|
||||||
if (t > 1) return UTIL.distSq(p, p2);
|
if (t > 1) return UTIL.distSq(p, p2);
|
||||||
|
|
@ -189,16 +186,16 @@ var gs_base_point = exports;
|
||||||
}
|
}
|
||||||
|
|
||||||
function p2l(p, l1, l2) {
|
function p2l(p, l1, l2) {
|
||||||
var v = {x: l2.x - l1.x, y: l2.y - l1.y};
|
let v = {x: l2.x - l1.x, y: l2.y - l1.y};
|
||||||
var w = {x: p.x - l1.x, y: p.y - l1.y};
|
let w = {x: p.x - l1.x, y: p.y - l1.y};
|
||||||
var c1 = dot(w, v);
|
let c1 = dot(w, v);
|
||||||
var c2 = dot(v, v);
|
let c2 = dot(v, v);
|
||||||
var b = c1 / c2;
|
let b = c1 / c2;
|
||||||
if (isNaN(b)) {
|
if (isNaN(b)) {
|
||||||
// console.log('nan', {p, l1, l2, v, w, c1, c2});
|
// console.log('nan', {p, l1, l2, v, w, c1, c2});
|
||||||
b = 0;
|
b = 0;
|
||||||
}
|
}
|
||||||
var pb = {x: l1.x + b * v.x, y: l1.y + b * v.y};
|
let pb = {x: l1.x + b * v.x, y: l1.y + b * v.y};
|
||||||
return d(p, pb);
|
return d(p, pb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -212,7 +209,7 @@ var gs_base_point = exports;
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
PRO.withinDist2 = function(p1, p2, dist2) {
|
PRO.withinDist2 = function(p1, p2, dist2) {
|
||||||
var ll2 = p1.distToSq2D(p2),
|
let ll2 = p1.distToSq2D(p2),
|
||||||
dp1 = this.distToSq2D(p1),
|
dp1 = this.distToSq2D(p1),
|
||||||
dp2 = this.distToSq2D(p2);
|
dp2 = this.distToSq2D(p2);
|
||||||
// if the line segment described is less than dist2
|
// if the line segment described is less than dist2
|
||||||
|
|
@ -277,7 +274,7 @@ var gs_base_point = exports;
|
||||||
* @param dist
|
* @param dist
|
||||||
*/
|
*/
|
||||||
PRO.offsetPointFrom = function(p2, dist) {
|
PRO.offsetPointFrom = function(p2, dist) {
|
||||||
var p1 = this,
|
let p1 = this,
|
||||||
dx = p2.x - p1.x,
|
dx = p2.x - p1.x,
|
||||||
dy = p2.y - p1.y,
|
dy = p2.y - p1.y,
|
||||||
ls = dist / Math.sqrt(dx * dx + dy * dy),
|
ls = dist / Math.sqrt(dx * dx + dy * dy),
|
||||||
|
|
@ -313,7 +310,7 @@ var gs_base_point = exports;
|
||||||
* @returns {Line}
|
* @returns {Line}
|
||||||
*/
|
*/
|
||||||
PRO.offsetLineTo = function(p2, offset) {
|
PRO.offsetLineTo = function(p2, offset) {
|
||||||
var p1 = this,
|
let p1 = this,
|
||||||
dx = p2.x - p1.x,
|
dx = p2.x - p1.x,
|
||||||
dy = p2.y - p1.y,
|
dy = p2.y - p1.y,
|
||||||
ls = offset / Math.sqrt(dx * dx + dy * dy),
|
ls = offset / Math.sqrt(dx * dx + dy * dy),
|
||||||
|
|
@ -340,7 +337,7 @@ var gs_base_point = exports;
|
||||||
PRO.inPolygon = function(poly) {
|
PRO.inPolygon = function(poly) {
|
||||||
if (!poly.bounds.containsXY(this.x, this.y)) return false;
|
if (!poly.bounds.containsXY(this.x, this.y)) return false;
|
||||||
|
|
||||||
var p = poly.points, pl = p.length, p1, p2, i, inside = false;
|
let p = poly.points, pl = p.length, p1, p2, i, inside = false;
|
||||||
|
|
||||||
for (i=0; i<pl; i++) {
|
for (i=0; i<pl; i++) {
|
||||||
p1 = p[i];
|
p1 = p[i];
|
||||||
|
|
@ -363,14 +360,14 @@ var gs_base_point = exports;
|
||||||
* @return {boolean} true if inside outer but not inner
|
* @return {boolean} true if inside outer but not inner
|
||||||
*/
|
*/
|
||||||
PRO.isInPolygon = function(poly) {
|
PRO.isInPolygon = function(poly) {
|
||||||
var point = this, i;
|
let point = this, i;
|
||||||
if (Array.isArray(poly)) {
|
if (Array.isArray(poly)) {
|
||||||
for (i=0; i<poly.length; i++) {
|
for (i=0; i<poly.length; i++) {
|
||||||
if (point.isInPolygon(poly[i])) return true;
|
if (point.isInPolygon(poly[i])) return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
var holes = poly.inner;
|
let holes = poly.inner;
|
||||||
if (point.inPolygon(poly) || point.nearPolygon(poly, CONF.precision_merge_sq)) {
|
if (point.inPolygon(poly) || point.nearPolygon(poly, CONF.precision_merge_sq)) {
|
||||||
for (i=0; holes && i < holes.length; i++) {
|
for (i=0; holes && i < holes.length; i++) {
|
||||||
if (point.inPolygon(holes[i]) && !point.nearPolygon(holes[i], CONF.precision_merge_sq)) return false;
|
if (point.inPolygon(holes[i]) && !point.nearPolygon(holes[i], CONF.precision_merge_sq)) return false;
|
||||||
|
|
@ -388,14 +385,14 @@ var gs_base_point = exports;
|
||||||
* @return {boolean} true if inside outer but not inner
|
* @return {boolean} true if inside outer but not inner
|
||||||
*/
|
*/
|
||||||
PRO.isInPolygonOnly = function(poly) {
|
PRO.isInPolygonOnly = function(poly) {
|
||||||
var point = this, i;
|
let point = this, i;
|
||||||
if (Array.isArray(poly)) {
|
if (Array.isArray(poly)) {
|
||||||
for (i=0; i<poly.length; i++) {
|
for (i=0; i<poly.length; i++) {
|
||||||
if (point.isInPolygonOnly(poly[i])) return true;
|
if (point.isInPolygonOnly(poly[i])) return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
var holes = poly.inner;
|
let holes = poly.inner;
|
||||||
if (point.inPolygon(poly)) {
|
if (point.inPolygon(poly)) {
|
||||||
for (i=0; holes && i < holes.length; i++) {
|
for (i=0; holes && i < holes.length; i++) {
|
||||||
if (point.inPolygon(holes[i])) return false;
|
if (point.inPolygon(holes[i])) return false;
|
||||||
|
|
@ -415,13 +412,13 @@ var gs_base_point = exports;
|
||||||
*/
|
*/
|
||||||
PRO.nearPolygon = function(poly, dist2, inner) {
|
PRO.nearPolygon = function(poly, dist2, inner) {
|
||||||
// throw new Error("nearPolygon");
|
// throw new Error("nearPolygon");
|
||||||
for (var i=0, p=poly.points, pl=p.length ; i<pl; i++) {
|
for (let i=0, p=poly.points, pl=p.length ; i<pl; i++) {
|
||||||
if (this.withinDist2(p[i], p[(i+1)%pl], dist2)) {
|
if (this.withinDist2(p[i], p[(i+1)%pl], dist2)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (inner && poly.inner) {
|
if (inner && poly.inner) {
|
||||||
for (var i=0; i<poly.inner.length; i++) {
|
for (let i=0; i<poly.inner.length; i++) {
|
||||||
if (this.nearPolygon(poly.inner[i], dist2)) return true;
|
if (this.nearPolygon(poly.inner[i], dist2)) return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -449,7 +446,7 @@ var gs_base_point = exports;
|
||||||
* @returns {Point}
|
* @returns {Point}
|
||||||
*/
|
*/
|
||||||
PRO.follow = function(slope, distance) {
|
PRO.follow = function(slope, distance) {
|
||||||
var ls = distance / Math.sqrt(slope.dx * slope.dx + slope.dy * slope.dy);
|
let ls = distance / Math.sqrt(slope.dx * slope.dx + slope.dy * slope.dy);
|
||||||
return newPoint(this.x + slope.dx * ls, this.y + slope.dy * ls, this.z);
|
return newPoint(this.x + slope.dx * ls, this.y + slope.dy * ls, this.z);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -461,7 +458,7 @@ var gs_base_point = exports;
|
||||||
* @returns {Point}
|
* @returns {Point}
|
||||||
*/
|
*/
|
||||||
PRO.intersectZ = function(p, z) {
|
PRO.intersectZ = function(p, z) {
|
||||||
var dx = p.x - this.x,
|
let dx = p.x - this.x,
|
||||||
dy = p.y - this.y,
|
dy = p.y - this.y,
|
||||||
dz = p.z - this.z,
|
dz = p.z - this.z,
|
||||||
pct = 1 - ((p.z - z) / dz);
|
pct = 1 - ((p.z - z) / dz);
|
||||||
|
|
@ -525,7 +522,7 @@ var gs_base_point = exports;
|
||||||
* @param {number} [threshold] stop looking if under threshold
|
* @param {number} [threshold] stop looking if under threshold
|
||||||
*/
|
*/
|
||||||
PRO.distToPolySegments = function(poly, threshold) {
|
PRO.distToPolySegments = function(poly, threshold) {
|
||||||
var point = this,
|
let point = this,
|
||||||
mindist = Infinity;
|
mindist = Infinity;
|
||||||
poly.forEachSegment(function(p1, p2) {
|
poly.forEachSegment(function(p1, p2) {
|
||||||
const nextdist = Math.min(mindist, point.distToLine(p1, p2));
|
const nextdist = Math.min(mindist, point.distToLine(p1, p2));
|
||||||
|
|
@ -541,7 +538,7 @@ var gs_base_point = exports;
|
||||||
* @param {number} [threshold] stop looking if under threshold
|
* @param {number} [threshold] stop looking if under threshold
|
||||||
*/
|
*/
|
||||||
PRO.distToPolyPoints = function(poly, threshold) {
|
PRO.distToPolyPoints = function(poly, threshold) {
|
||||||
var point = this, mindist = Infinity;
|
let point = this, mindist = Infinity;
|
||||||
poly.forEachPoint(function(pp) {
|
poly.forEachPoint(function(pp) {
|
||||||
mindist = Math.min(mindist, point.distTo2D(pp));
|
mindist = Math.min(mindist, point.distTo2D(pp));
|
||||||
if (mindist < threshold) return true;
|
if (mindist < threshold) return true;
|
||||||
|
|
@ -556,7 +553,7 @@ var gs_base_point = exports;
|
||||||
*/
|
*/
|
||||||
PRO.nearestTo = function(points, max) {
|
PRO.nearestTo = function(points, max) {
|
||||||
if (!max) throw "missing max";
|
if (!max) throw "missing max";
|
||||||
var mind = Infinity,
|
let mind = Infinity,
|
||||||
minp = null,
|
minp = null,
|
||||||
i, p, d;
|
i, p, d;
|
||||||
for (i=0; i<points.length; i++) {
|
for (i=0; i<points.length; i++) {
|
||||||
|
|
@ -576,7 +573,7 @@ var gs_base_point = exports;
|
||||||
* @return {number} average square dist to cloud of points
|
* @return {number} average square dist to cloud of points
|
||||||
*/
|
*/
|
||||||
PRO.averageDistTo = function(points) {
|
PRO.averageDistTo = function(points) {
|
||||||
var sum = 0.0, count = 0, i;
|
let sum = 0.0, count = 0, i;
|
||||||
for (i = 0; i < points.length; i++) {
|
for (i = 0; i < points.length; i++) {
|
||||||
if (points[i] != this) {
|
if (points[i] != this) {
|
||||||
sum += this.distToSq2D(points[i]);
|
sum += this.distToSq2D(points[i]);
|
||||||
|
|
@ -593,7 +590,7 @@ var gs_base_point = exports;
|
||||||
* @returns {number}
|
* @returns {number}
|
||||||
*/
|
*/
|
||||||
PRO.distTo2D = function(p) {
|
PRO.distTo2D = function(p) {
|
||||||
var dx = this.x - p.x,
|
let dx = this.x - p.x,
|
||||||
dy = this.y - p.y;
|
dy = this.y - p.y;
|
||||||
return Math.sqrt(dx * dx + dy * dy);
|
return Math.sqrt(dx * dx + dy * dy);
|
||||||
};
|
};
|
||||||
|
|
@ -605,13 +602,13 @@ var gs_base_point = exports;
|
||||||
* @returns {number}
|
* @returns {number}
|
||||||
*/
|
*/
|
||||||
PRO.distToSq2D = function(p) {
|
PRO.distToSq2D = function(p) {
|
||||||
var dx = this.x - p.x,
|
let dx = this.x - p.x,
|
||||||
dy = this.y - p.y;
|
dy = this.y - p.y;
|
||||||
return dx * dx + dy * dy;
|
return dx * dx + dy * dy;
|
||||||
};
|
};
|
||||||
|
|
||||||
PRO.distTo3D = function(p) {
|
PRO.distTo3D = function(p) {
|
||||||
var dx = this.x - p.x,
|
let dx = this.x - p.x,
|
||||||
dy = this.y - p.y,
|
dy = this.y - p.y,
|
||||||
dz = this.z - p.z;
|
dz = this.z - p.z;
|
||||||
return Math.sqrt(dx * dx + dy * dy + dz * dz);
|
return Math.sqrt(dx * dx + dy * dy + dz * dz);
|
||||||
|
|
@ -624,7 +621,7 @@ var gs_base_point = exports;
|
||||||
* @returns {number}
|
* @returns {number}
|
||||||
*/
|
*/
|
||||||
PRO.distToSq3D = function(p) {
|
PRO.distToSq3D = function(p) {
|
||||||
var dx = this.x - p.x,
|
let dx = this.x - p.x,
|
||||||
dy = this.y - p.y,
|
dy = this.y - p.y,
|
||||||
dz = this.z - p.z;
|
dz = this.z - p.z;
|
||||||
return dx * dx + dy * dy + dz * dz;
|
return dx * dx + dy * dy + dz * dz;
|
||||||
|
|
@ -639,7 +636,7 @@ var gs_base_point = exports;
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
PRO.inTriangle = function(a, b, c) {
|
PRO.inTriangle = function(a, b, c) {
|
||||||
var as_x = this.x - a.x,
|
let as_x = this.x - a.x,
|
||||||
as_y = this.y - a.y,
|
as_y = this.y - a.y,
|
||||||
s_ab = (b.x - a.x) * as_y - (b.y - a.y) * as_x > 0;
|
s_ab = (b.x - a.x) * as_y - (b.y - a.y) * as_x > 0;
|
||||||
if ((c.x - a.x) * as_y - (c.y - a.y) * as_x > 0 == s_ab) return false;
|
if ((c.x - a.x) * as_y - (c.y - a.y) * as_x > 0 == s_ab) return false;
|
||||||
|
|
@ -1,15 +1,12 @@
|
||||||
/** Copyright 2014-2019 Stewart Allen -- All Rights Reserved */
|
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var gs_base_polygon = exports;
|
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
if (!self.base) self.base = {};
|
|
||||||
if (self.base.Polygon) return;
|
if (self.base.Polygon) return;
|
||||||
|
|
||||||
var BASE = self.base,
|
const BASE = self.base,
|
||||||
CONF = BASE.config,
|
CONF = BASE.config,
|
||||||
UTIL = BASE.util,
|
UTIL = BASE.util,
|
||||||
DBUG = BASE.debug,
|
DBUG = BASE.debug,
|
||||||
|
|
@ -21,12 +18,11 @@ var gs_base_polygon = exports;
|
||||||
MAX = Math.max,
|
MAX = Math.max,
|
||||||
PI = Math.PI,
|
PI = Math.PI,
|
||||||
DEG2RAD = PI / 180,
|
DEG2RAD = PI / 180,
|
||||||
Bounds = BASE.Bounds,
|
|
||||||
newPoint = BASE.newPoint,
|
newPoint = BASE.newPoint,
|
||||||
PRO = Polygon.prototype,
|
Bounds = BASE.Bounds,
|
||||||
nest_test_slope = BASE.newSlope(newPoint(0,0,0,KEYS.NONE), newPoint(1,0,0,KEYS.NONE)),
|
PRO = Polygon.prototype;
|
||||||
min_area_mult = 2.0,
|
|
||||||
seqid = 1;
|
let seqid = 1;
|
||||||
|
|
||||||
BASE.Polygon = Polygon;
|
BASE.Polygon = Polygon;
|
||||||
BASE.newPolygon = newPolygon;
|
BASE.newPolygon = newPolygon;
|
||||||
|
|
@ -97,9 +93,9 @@ var gs_base_polygon = exports;
|
||||||
|
|
||||||
Polygon.filterChain = function(filters) {
|
Polygon.filterChain = function(filters) {
|
||||||
return function() {
|
return function() {
|
||||||
var f = filters;
|
let f = filters;
|
||||||
return function(p) {
|
return function(p) {
|
||||||
var len = f.length,
|
let len = f.length,
|
||||||
idx = 0;
|
idx = 0;
|
||||||
while (idx < len && (p = f[idx++](p)))
|
while (idx < len && (p = f[idx++](p)))
|
||||||
;
|
;
|
||||||
|
|
@ -213,8 +209,8 @@ var gs_base_polygon = exports;
|
||||||
|
|
||||||
PRO.createConvexHull = function(points) {
|
PRO.createConvexHull = function(points) {
|
||||||
function removeMiddle(a, b, c) {
|
function removeMiddle(a, b, c) {
|
||||||
var cross = (a.x - b.x) * (c.y - b.y) - (a.y - b.y) * (c.x - b.x);
|
let cross = (a.x - b.x) * (c.y - b.y) - (a.y - b.y) * (c.x - b.x);
|
||||||
var dot = (a.x - b.x) * (c.x - b.x) + (a.y - b.y) * (c.y - b.y);
|
let dot = (a.x - b.x) * (c.x - b.x) + (a.y - b.y) * (c.y - b.y);
|
||||||
return cross < 0 || cross == 0 && dot <= 0;
|
return cross < 0 || cross == 0 && dot <= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -222,11 +218,11 @@ var gs_base_polygon = exports;
|
||||||
return a.x != b.x ? a.x - b.x : a.y - b.y;
|
return a.x != b.x ? a.x - b.x : a.y - b.y;
|
||||||
});
|
});
|
||||||
|
|
||||||
var n = points.length;
|
let n = points.length;
|
||||||
var hull = [];
|
let hull = [];
|
||||||
|
|
||||||
for (var i = 0; i < 2 * n; i++) {
|
for (let i = 0; i < 2 * n; i++) {
|
||||||
var j = i < n ? i : 2 * n - 1 - i;
|
let j = i < n ? i : 2 * n - 1 - i;
|
||||||
while (hull.length >= 2 && removeMiddle(hull[hull.length - 2], hull[hull.length - 1], points[j]))
|
while (hull.length >= 2 && removeMiddle(hull[hull.length - 2], hull[hull.length - 1], points[j]))
|
||||||
hull.pop();
|
hull.pop();
|
||||||
hull.push(points[j]);
|
hull.push(points[j]);
|
||||||
|
|
@ -239,7 +235,7 @@ var gs_base_polygon = exports;
|
||||||
};
|
};
|
||||||
|
|
||||||
PRO.stepsFromRoot = function() {
|
PRO.stepsFromRoot = function() {
|
||||||
var p = this.parent, steps = 0;
|
let p = this.parent, steps = 0;
|
||||||
while (p) {
|
while (p) {
|
||||||
if (p.inner && p.inner.length > 1) steps++;
|
if (p.inner && p.inner.length > 1) steps++;
|
||||||
p = p.parent;
|
p = p.parent;
|
||||||
|
|
@ -256,11 +252,11 @@ var gs_base_polygon = exports;
|
||||||
};
|
};
|
||||||
|
|
||||||
PRO.swap = function(x,y) {
|
PRO.swap = function(x,y) {
|
||||||
var poly = this,
|
let poly = this,
|
||||||
points = poly.points,
|
points = poly.points,
|
||||||
length = points.length;
|
length = points.length;
|
||||||
poly.bounds = new Bounds();
|
poly.bounds = new Bounds();
|
||||||
for (var i=0; i<length; i++) {
|
for (let i=0; i<length; i++) {
|
||||||
let p = points[i];
|
let p = points[i];
|
||||||
if (x) p.swapXZ();
|
if (x) p.swapXZ();
|
||||||
else if (y) p.swapYZ();
|
else if (y) p.swapYZ();
|
||||||
|
|
@ -291,7 +287,7 @@ var gs_base_polygon = exports;
|
||||||
* @returns {Polygon|Point} a new polygon centered on x=0, y=0, z=0
|
* @returns {Polygon|Point} a new polygon centered on x=0, y=0, z=0
|
||||||
*/
|
*/
|
||||||
PRO.center = function(point) {
|
PRO.center = function(point) {
|
||||||
var ap = newPoint(0,0,0,null), np = newPolygon(), pa = this.points;
|
let ap = newPoint(0,0,0,null), np = newPolygon(), pa = this.points;
|
||||||
pa.forEach(function(p) {
|
pa.forEach(function(p) {
|
||||||
ap.x += p.x;
|
ap.x += p.x;
|
||||||
ap.y += p.y;
|
ap.y += p.y;
|
||||||
|
|
@ -315,7 +311,7 @@ var gs_base_polygon = exports;
|
||||||
* @returns {Point} center of a polygon assuming it's a circle
|
* @returns {Point} center of a polygon assuming it's a circle
|
||||||
*/
|
*/
|
||||||
PRO.circleCenter = function() {
|
PRO.circleCenter = function() {
|
||||||
var points = this.points,
|
let points = this.points,
|
||||||
length = points.length,
|
length = points.length,
|
||||||
incr = Math.floor(length / 3),
|
incr = Math.floor(length / 3),
|
||||||
A = points[0],
|
A = points[0],
|
||||||
|
|
@ -387,7 +383,7 @@ var gs_base_polygon = exports;
|
||||||
* @param {boolean} clockwise
|
* @param {boolean} clockwise
|
||||||
*/
|
*/
|
||||||
PRO.centerCircle = function(center, radius, points, clockwise) {
|
PRO.centerCircle = function(center, radius, points, clockwise) {
|
||||||
var angle = 0, add = 360 / points;
|
let angle = 0, add = 360 / points;
|
||||||
if (clockwise) add = -add;
|
if (clockwise) add = -add;
|
||||||
while (points-- > 0) {
|
while (points-- > 0) {
|
||||||
this.push(newPoint(
|
this.push(newPoint(
|
||||||
|
|
@ -406,7 +402,7 @@ var gs_base_polygon = exports;
|
||||||
* @returns {Polygon}
|
* @returns {Polygon}
|
||||||
*/
|
*/
|
||||||
PRO.move = function(offset) {
|
PRO.move = function(offset) {
|
||||||
var scope = this,
|
let scope = this,
|
||||||
bounds = scope.bounds = new Bounds();
|
bounds = scope.bounds = new Bounds();
|
||||||
scope.points.forEach(function(p) {
|
scope.points.forEach(function(p) {
|
||||||
p.move(offset);
|
p.move(offset);
|
||||||
|
|
@ -417,7 +413,7 @@ var gs_base_polygon = exports;
|
||||||
};
|
};
|
||||||
|
|
||||||
PRO.scale = function(scale, round) {
|
PRO.scale = function(scale, round) {
|
||||||
var scope = this,
|
let scope = this,
|
||||||
bounds = scope.bounds = new Bounds();
|
bounds = scope.bounds = new Bounds();
|
||||||
scope.points.forEach(function(p) {
|
scope.points.forEach(function(p) {
|
||||||
p.x *= scale;
|
p.x *= scale;
|
||||||
|
|
@ -437,7 +433,7 @@ var gs_base_polygon = exports;
|
||||||
* hint fill angle hinting from longest segment
|
* hint fill angle hinting from longest segment
|
||||||
*/
|
*/
|
||||||
PRO.hintFillAngle = function() {
|
PRO.hintFillAngle = function() {
|
||||||
var index = 0,
|
let index = 0,
|
||||||
points = this.points,
|
points = this.points,
|
||||||
length = points.length,
|
length = points.length,
|
||||||
prev,
|
prev,
|
||||||
|
|
@ -471,7 +467,7 @@ var gs_base_polygon = exports;
|
||||||
* @returns {Polygon}
|
* @returns {Polygon}
|
||||||
*/
|
*/
|
||||||
PRO.clone = function(deep) {
|
PRO.clone = function(deep) {
|
||||||
var np = newPolygon(),
|
let np = newPolygon(),
|
||||||
ln = this.length,
|
ln = this.length,
|
||||||
i = 0;
|
i = 0;
|
||||||
|
|
||||||
|
|
@ -495,7 +491,7 @@ var gs_base_polygon = exports;
|
||||||
* @returns {Polygon} this
|
* @returns {Polygon} this
|
||||||
*/
|
*/
|
||||||
PRO.setZ = function(z) {
|
PRO.setZ = function(z) {
|
||||||
var ar = this.points,
|
let ar = this.points,
|
||||||
ln = ar.length,
|
ln = ar.length,
|
||||||
i = 0;
|
i = 0;
|
||||||
while (i < ln) ar[i++].z = z;
|
while (i < ln) ar[i++].z = z;
|
||||||
|
|
@ -545,7 +541,7 @@ var gs_base_polygon = exports;
|
||||||
* @returns {Polygon}
|
* @returns {Polygon}
|
||||||
*/
|
*/
|
||||||
PRO.addPoints = function(points) {
|
PRO.addPoints = function(points) {
|
||||||
var poly = this,
|
let poly = this,
|
||||||
length = points.length,
|
length = points.length,
|
||||||
i = 0;
|
i = 0;
|
||||||
while (i < length) {
|
while (i < length) {
|
||||||
|
|
@ -667,7 +663,7 @@ var gs_base_polygon = exports;
|
||||||
*/
|
*/
|
||||||
PRO.isNested = function(parent) {
|
PRO.isNested = function(parent) {
|
||||||
if (parent.bounds.contains(this.bounds)) {
|
if (parent.bounds.contains(this.bounds)) {
|
||||||
//var int = POLY().rayIntersect(this.bounds.leftMost, nest_test_slope, [parent], false);
|
//let int = POLY().rayIntersect(this.bounds.leftMost, nest_test_slope, [parent], false);
|
||||||
//return int.length % 2 === 1 || this.isInside(parent, CONF.precision_nested_sq);
|
//return int.length % 2 === 1 || this.isInside(parent, CONF.precision_nested_sq);
|
||||||
return this.isInside(parent, CONF.precision_nested_sq);
|
return this.isInside(parent, CONF.precision_nested_sq);
|
||||||
}
|
}
|
||||||
|
|
@ -675,7 +671,7 @@ var gs_base_polygon = exports;
|
||||||
};
|
};
|
||||||
|
|
||||||
PRO.forEachPointEaseDown = function(fn, fromPoint) {
|
PRO.forEachPointEaseDown = function(fn, fromPoint) {
|
||||||
var index = this.findClosestPointTo(fromPoint).index,
|
let index = this.findClosestPointTo(fromPoint).index,
|
||||||
fromZ = fromPoint.z,
|
fromZ = fromPoint.z,
|
||||||
offset = 0,
|
offset = 0,
|
||||||
points = this.points,
|
points = this.points,
|
||||||
|
|
@ -690,7 +686,7 @@ var gs_base_polygon = exports;
|
||||||
while (true) {
|
while (true) {
|
||||||
next = points[index % length];
|
next = points[index % length];
|
||||||
if (last && next.z < fromZ) {
|
if (last && next.z < fromZ) {
|
||||||
var deltaZ = fromZ - next.z;
|
let deltaZ = fromZ - next.z;
|
||||||
dist2next = last.distTo2D(next);
|
dist2next = last.distTo2D(next);
|
||||||
if (dist2next > deltaZ * 2) {
|
if (dist2next > deltaZ * 2) {
|
||||||
// too long: synth intermediate
|
// too long: synth intermediate
|
||||||
|
|
@ -716,7 +712,7 @@ var gs_base_polygon = exports;
|
||||||
};
|
};
|
||||||
|
|
||||||
PRO.forEachPoint = function(fn, close, start) {
|
PRO.forEachPoint = function(fn, close, start) {
|
||||||
var index = start || 0,
|
let index = start || 0,
|
||||||
points = this.points,
|
points = this.points,
|
||||||
length = points.length,
|
length = points.length,
|
||||||
count = close ? length + 1 : length,
|
count = close ? length + 1 : length,
|
||||||
|
|
@ -731,7 +727,7 @@ var gs_base_polygon = exports;
|
||||||
};
|
};
|
||||||
|
|
||||||
PRO.forEachSegment = function(fn, open, start) {
|
PRO.forEachSegment = function(fn, open, start) {
|
||||||
var index = start || 0,
|
let index = start || 0,
|
||||||
points = this.points,
|
points = this.points,
|
||||||
length = points.length,
|
length = points.length,
|
||||||
count = open ? length - 1 : length,
|
count = open ? length - 1 : length,
|
||||||
|
|
@ -749,9 +745,9 @@ var gs_base_polygon = exports;
|
||||||
* returns intersections sorted by closest to lp1
|
* returns intersections sorted by closest to lp1
|
||||||
*/
|
*/
|
||||||
PRO.intersections = function(lp1, lp2) {
|
PRO.intersections = function(lp1, lp2) {
|
||||||
var list = [];
|
let list = [];
|
||||||
this.forEachSegment(function(pp1, pp2, ip1, ip2) {
|
this.forEachSegment(function(pp1, pp2, ip1, ip2) {
|
||||||
var int = UTIL.intersect(lp1, lp2, pp1, pp2, BASE.key.SEGINT, false);
|
let int = UTIL.intersect(lp1, lp2, pp1, pp2, BASE.key.SEGINT, false);
|
||||||
if (int) {
|
if (int) {
|
||||||
list.push(int);
|
list.push(int);
|
||||||
pp1.pos = ip1;
|
pp1.pos = ip1;
|
||||||
|
|
@ -771,9 +767,9 @@ var gs_base_polygon = exports;
|
||||||
PRO.bisect = function(p1, p2) {
|
PRO.bisect = function(p1, p2) {
|
||||||
if (this.isOpen()) return null;
|
if (this.isOpen()) return null;
|
||||||
|
|
||||||
var copy = this.clone().setClockwise();
|
let copy = this.clone().setClockwise();
|
||||||
|
|
||||||
var int = copy.intersections(p1, p2);
|
let int = copy.intersections(p1, p2);
|
||||||
if (!int || int.length !== 2) return null;
|
if (!int || int.length !== 2) return null;
|
||||||
|
|
||||||
return [ copy.emitSegment(int[0], int[1]), copy.emitSegment(int[1], int[0]).reverse() ];
|
return [ copy.emitSegment(int[0], int[1]), copy.emitSegment(int[1], int[0]).reverse() ];
|
||||||
|
|
@ -784,7 +780,7 @@ var gs_base_polygon = exports;
|
||||||
* used in cam tabs and fdm output perimeter traces on infill
|
* used in cam tabs and fdm output perimeter traces on infill
|
||||||
*/
|
*/
|
||||||
PRO.emitSegment = function(i1, i2) {
|
PRO.emitSegment = function(i1, i2) {
|
||||||
var poly = newPolygon(),
|
let poly = newPolygon(),
|
||||||
start = i1.p2.pos,
|
start = i1.p2.pos,
|
||||||
end = i2.p1.pos;
|
end = i2.p1.pos;
|
||||||
poly.setOpen();
|
poly.setOpen();
|
||||||
|
|
@ -805,7 +801,7 @@ var gs_base_polygon = exports;
|
||||||
PRO.hasPointsInside = function(poly, tolerance) {
|
PRO.hasPointsInside = function(poly, tolerance) {
|
||||||
if (!poly.overlaps(this)) return false;
|
if (!poly.overlaps(this)) return false;
|
||||||
|
|
||||||
var mid, exit = false;
|
let mid, exit = false;
|
||||||
|
|
||||||
this.forEachSegment(function(prev, next) {
|
this.forEachSegment(function(prev, next) {
|
||||||
// check midpoint on long lines
|
// check midpoint on long lines
|
||||||
|
|
@ -837,7 +833,7 @@ var gs_base_polygon = exports;
|
||||||
this.bounds.isNested(poly.bounds)
|
this.bounds.isNested(poly.bounds)
|
||||||
)) return false;
|
)) return false;
|
||||||
|
|
||||||
var mid,
|
let mid,
|
||||||
midcheck,
|
midcheck,
|
||||||
exit = true;
|
exit = true;
|
||||||
|
|
||||||
|
|
@ -875,7 +871,7 @@ var gs_base_polygon = exports;
|
||||||
*/
|
*/
|
||||||
PRO.containedBySet = function(polys) {
|
PRO.containedBySet = function(polys) {
|
||||||
if (!polys) return false;
|
if (!polys) return false;
|
||||||
for (var i=0; i<polys.length; i++) {
|
for (let i=0; i<polys.length; i++) {
|
||||||
if (polys[i].contains(this)) return true;
|
if (polys[i].contains(this)) return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -919,7 +915,7 @@ var gs_base_polygon = exports;
|
||||||
};
|
};
|
||||||
|
|
||||||
PRO.newUndeleted = function() {
|
PRO.newUndeleted = function() {
|
||||||
var poly = newPolygon();
|
let poly = newPolygon();
|
||||||
this.forEachPoint(function(p) {
|
this.forEachPoint(function(p) {
|
||||||
if (!p.del) poly.push(p);
|
if (!p.del) poly.push(p);
|
||||||
});
|
});
|
||||||
|
|
@ -946,7 +942,7 @@ var gs_base_polygon = exports;
|
||||||
return this.perim;
|
return this.perim;
|
||||||
}
|
}
|
||||||
|
|
||||||
var len = 0.0;
|
let len = 0.0;
|
||||||
|
|
||||||
this.forEachSegment(function(prev,next) {
|
this.forEachSegment(function(prev,next) {
|
||||||
len += SQRT(prev.distToSq2D(next));
|
len += SQRT(prev.distToSq2D(next));
|
||||||
|
|
@ -956,7 +952,7 @@ var gs_base_polygon = exports;
|
||||||
};
|
};
|
||||||
|
|
||||||
PRO.perimeterDeep = function() {
|
PRO.perimeterDeep = function() {
|
||||||
var len = this.perimeter();
|
let len = this.perimeter();
|
||||||
if (this.inner) this.inner.forEach(function(p) { len += p.perimeter() });
|
if (this.inner) this.inner.forEach(function(p) { len += p.perimeter() });
|
||||||
return len;
|
return len;
|
||||||
};
|
};
|
||||||
|
|
@ -972,7 +968,7 @@ var gs_base_polygon = exports;
|
||||||
PRO.area = function(raw) {
|
PRO.area = function(raw) {
|
||||||
if (this.length < 3) return 0;
|
if (this.length < 3) return 0;
|
||||||
if (this.area2 === 0.0) {
|
if (this.area2 === 0.0) {
|
||||||
for (var p=this.points,pl=p.length,pi=0,p1,p2; pi<pl; pi++) {
|
for (let p=this.points,pl=p.length,pi=0,p1,p2; pi<pl; pi++) {
|
||||||
p1 = p[pi];
|
p1 = p[pi];
|
||||||
p2 = p[(pi+1)%pl];
|
p2 = p[(pi+1)%pl];
|
||||||
this.area2 += (p2.x - p1.x) * (p2.y + p1.y);
|
this.area2 += (p2.x - p1.x) * (p2.y + p1.y);
|
||||||
|
|
@ -989,7 +985,7 @@ var gs_base_polygon = exports;
|
||||||
*/
|
*/
|
||||||
PRO.areaDeep = function() {
|
PRO.areaDeep = function() {
|
||||||
if (!this.inner) return this.area();
|
if (!this.inner) return this.area();
|
||||||
var i, c = this.inner, a = this.area();
|
let i, c = this.inner, a = this.area();
|
||||||
for (i=0; i<c.length; i++) {
|
for (i=0; i<c.length; i++) {
|
||||||
a -= c[i].area();
|
a -= c[i].area();
|
||||||
}
|
}
|
||||||
|
|
@ -1011,7 +1007,7 @@ var gs_base_polygon = exports;
|
||||||
* @param {number} [z]
|
* @param {number} [z]
|
||||||
*/
|
*/
|
||||||
PRO.fromXYArray = function(arr,z) {
|
PRO.fromXYArray = function(arr,z) {
|
||||||
var i = 0;
|
let i = 0;
|
||||||
while (i < arr.length) {
|
while (i < arr.length) {
|
||||||
this.add(arr[i++], arr[i++], z || 0);
|
this.add(arr[i++], arr[i++], z || 0);
|
||||||
}
|
}
|
||||||
|
|
@ -1019,7 +1015,7 @@ var gs_base_polygon = exports;
|
||||||
};
|
};
|
||||||
|
|
||||||
function fromClipperPath(path,z) {
|
function fromClipperPath(path,z) {
|
||||||
var poly = newPolygon(), i = 0, l = path.length;
|
let poly = newPolygon(), i = 0, l = path.length;
|
||||||
while (i < l) poly.push(newPoint(null,null,z,null,path[i++]));
|
while (i < l) poly.push(newPoint(null,null,z,null,path[i++]));
|
||||||
return poly;
|
return poly;
|
||||||
};
|
};
|
||||||
|
|
@ -1042,11 +1038,11 @@ var gs_base_polygon = exports;
|
||||||
};
|
};
|
||||||
|
|
||||||
PRO.toClipper = function(inout,debug) {
|
PRO.toClipper = function(inout,debug) {
|
||||||
var poly = this,
|
let poly = this,
|
||||||
cur = [],
|
cur = [],
|
||||||
out = inout || [];
|
out = inout || [];
|
||||||
if (debug) {
|
if (debug) {
|
||||||
var d = [],
|
let d = [],
|
||||||
points = poly.points,
|
points = poly.points,
|
||||||
len = points.length,
|
len = points.length,
|
||||||
i = 0,
|
i = 0,
|
||||||
|
|
@ -1101,14 +1097,14 @@ var gs_base_polygon = exports;
|
||||||
this.bounds.equals(poly.bounds, precision || CONF.precision_poly_bounds))
|
this.bounds.equals(poly.bounds, precision || CONF.precision_poly_bounds))
|
||||||
{
|
{
|
||||||
// use circularity near 1 to eliminate the extensive check below
|
// use circularity near 1 to eliminate the extensive check below
|
||||||
var c1 = this.circularity(),
|
let c1 = this.circularity(),
|
||||||
c2 = poly.circularity();
|
c2 = poly.circularity();
|
||||||
if (ABS(c1-c2) < CONF.precision_circularity && ((1-c1) < CONF.precision_circularity)) {
|
if (ABS(c1-c2) < CONF.precision_circularity && ((1-c1) < CONF.precision_circularity)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (recurse) {
|
if (recurse) {
|
||||||
var i, ai = this.inner, bi = poly.inner;
|
let i, ai = this.inner, bi = poly.inner;
|
||||||
if (ai !== bi) {
|
if (ai !== bi) {
|
||||||
if (ai === null || bi === null || ai.length != bi.length) return false;
|
if (ai === null || bi === null || ai.length != bi.length) return false;
|
||||||
for (i=0; i < ai.length; i++) {
|
for (i=0; i < ai.length; i++) {
|
||||||
|
|
@ -1117,7 +1113,7 @@ var gs_base_polygon = exports;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var exit = true,
|
let exit = true,
|
||||||
pointok,
|
pointok,
|
||||||
dist,
|
dist,
|
||||||
min;
|
min;
|
||||||
|
|
@ -1153,7 +1149,7 @@ var gs_base_polygon = exports;
|
||||||
* @return {Object} {point:point, distance:distance}
|
* @return {Object} {point:point, distance:distance}
|
||||||
*/
|
*/
|
||||||
PRO.findClosestPointTo = function(target) {
|
PRO.findClosestPointTo = function(target) {
|
||||||
var dist,
|
let dist,
|
||||||
index,
|
index,
|
||||||
closest,
|
closest,
|
||||||
mindist = Infinity;
|
mindist = Infinity;
|
||||||
|
|
@ -1181,7 +1177,7 @@ var gs_base_polygon = exports;
|
||||||
};
|
};
|
||||||
|
|
||||||
PRO.shortestSegmentLength = function() {
|
PRO.shortestSegmentLength = function() {
|
||||||
var len = Infinity;
|
let len = Infinity;
|
||||||
this.forEachSegment(function(p1, p2) {
|
this.forEachSegment(function(p1, p2) {
|
||||||
len = Math.min(len, p1.distTo2D(p2));
|
len = Math.min(len, p1.distTo2D(p2));
|
||||||
});
|
});
|
||||||
|
|
@ -1193,7 +1189,7 @@ var gs_base_polygon = exports;
|
||||||
* @returns {?Polygon[]}
|
* @returns {?Polygon[]}
|
||||||
*/
|
*/
|
||||||
PRO.diff = function(poly) {
|
PRO.diff = function(poly) {
|
||||||
var fillang = this.fillang && this.area() > poly.area() ? this.fillang : poly.fillang,
|
let fillang = this.fillang && this.area() > poly.area() ? this.fillang : poly.fillang,
|
||||||
clib = self.ClipperLib,
|
clib = self.ClipperLib,
|
||||||
ctyp = clib.ClipType,
|
ctyp = clib.ClipType,
|
||||||
ptyp = clib.PolyType,
|
ptyp = clib.PolyType,
|
||||||
|
|
@ -1222,7 +1218,7 @@ var gs_base_polygon = exports;
|
||||||
* @returns {?Polygon[]}
|
* @returns {?Polygon[]}
|
||||||
*/
|
*/
|
||||||
PRO.mask = function(poly) {
|
PRO.mask = function(poly) {
|
||||||
var fillang = this.fillang && this.area() > poly.area() ? this.fillang : poly.fillang,
|
let fillang = this.fillang && this.area() > poly.area() ? this.fillang : poly.fillang,
|
||||||
clib = self.ClipperLib,
|
clib = self.ClipperLib,
|
||||||
ctyp = clib.ClipType,
|
ctyp = clib.ClipType,
|
||||||
ptyp = clib.PolyType,
|
ptyp = clib.PolyType,
|
||||||
|
|
@ -1287,7 +1283,7 @@ var gs_base_polygon = exports;
|
||||||
PRO.union = function(poly, min) {
|
PRO.union = function(poly, min) {
|
||||||
if (!this.overlaps(poly)) return null;
|
if (!this.overlaps(poly)) return null;
|
||||||
|
|
||||||
var fillang = this.fillang && this.area() > poly.area() ? this.fillang : poly.fillang,
|
let fillang = this.fillang && this.area() > poly.area() ? this.fillang : poly.fillang,
|
||||||
clib = self.ClipperLib,
|
clib = self.ClipperLib,
|
||||||
ctyp = clib.ClipType,
|
ctyp = clib.ClipType,
|
||||||
ptyp = clib.PolyType,
|
ptyp = clib.PolyType,
|
||||||
|
|
@ -1318,7 +1314,7 @@ var gs_base_polygon = exports;
|
||||||
* furthest apart and lowest when there is a tie breaker
|
* furthest apart and lowest when there is a tie breaker
|
||||||
*/
|
*/
|
||||||
PRO.spread = function() {
|
PRO.spread = function() {
|
||||||
var poly = this,
|
let poly = this,
|
||||||
points = poly.points,
|
points = poly.points,
|
||||||
plen = points.length,
|
plen = points.length,
|
||||||
i, pp, np, p, mdelta, newmax, max, shift, maxd;
|
i, pp, np, p, mdelta, newmax, max, shift, maxd;
|
||||||
|
|
@ -1,15 +1,13 @@
|
||||||
/** Copyright 2014-2019 Stewart Allen -- All Rights Reserved */
|
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var gs_base_polygons = exports;
|
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
if (!self.base) self.base = {};
|
if (!self.base) self.base = {};
|
||||||
if (self.base.polygons) return;
|
if (self.base.polygons) return;
|
||||||
|
|
||||||
var BASE = self.base,
|
const BASE = self.base,
|
||||||
UTIL = BASE.util,
|
UTIL = BASE.util,
|
||||||
CONF = BASE.config,
|
CONF = BASE.config,
|
||||||
DEG2RAD = Math.PI / 180,
|
DEG2RAD = Math.PI / 180,
|
||||||
|
|
@ -30,6 +28,7 @@ var gs_base_polygons = exports;
|
||||||
trimTo : trimTo,
|
trimTo : trimTo,
|
||||||
expand2 : expand2,
|
expand2 : expand2,
|
||||||
expand : expand,
|
expand : expand,
|
||||||
|
expand_lines: expand_lines,
|
||||||
union : union,
|
union : union,
|
||||||
nest : nest,
|
nest : nest,
|
||||||
diff : doDiff,
|
diff : doDiff,
|
||||||
|
|
@ -48,13 +47,13 @@ var gs_base_polygons = exports;
|
||||||
******************************************************************* */
|
******************************************************************* */
|
||||||
|
|
||||||
function toClipper(polys,debug) {
|
function toClipper(polys,debug) {
|
||||||
var out = [];
|
let out = [];
|
||||||
polys.forEach(function(poly) { poly.toClipper(out,debug) });
|
polys.forEach(function(poly) { poly.toClipper(out,debug) });
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
function fromClipperNode(tnode, z) {
|
function fromClipperNode(tnode, z) {
|
||||||
var poly = BASE.newPolygon();
|
let poly = BASE.newPolygon();
|
||||||
tnode.m_polygon.forEach(function(p) {
|
tnode.m_polygon.forEach(function(p) {
|
||||||
poly.push(newPoint(null, null, z, null, p));
|
poly.push(newPoint(null, null, z, null, p));
|
||||||
});
|
});
|
||||||
|
|
@ -63,7 +62,7 @@ var gs_base_polygons = exports;
|
||||||
};
|
};
|
||||||
|
|
||||||
function fromClipperTree(tnode, z, tops, parent, minarea) {
|
function fromClipperTree(tnode, z, tops, parent, minarea) {
|
||||||
var polys = tops || [],
|
let polys = tops || [],
|
||||||
poly,
|
poly,
|
||||||
min = minarea || 0.1;
|
min = minarea || 0.1;
|
||||||
|
|
||||||
|
|
@ -108,7 +107,7 @@ var gs_base_polygons = exports;
|
||||||
};
|
};
|
||||||
|
|
||||||
function cleanClipperTree(tree) {
|
function cleanClipperTree(tree) {
|
||||||
var clib = self.ClipperLib,
|
let clib = self.ClipperLib,
|
||||||
clip = clib.Clipper;
|
clip = clib.Clipper;
|
||||||
|
|
||||||
if (tree.m_Childs) tree.m_Childs.forEach(function(child) {
|
if (tree.m_Childs) tree.m_Childs.forEach(function(child) {
|
||||||
|
|
@ -151,7 +150,7 @@ var gs_base_polygons = exports;
|
||||||
polygons.sort(function (a, b) {
|
polygons.sort(function (a, b) {
|
||||||
return a.area() - b.area();
|
return a.area() - b.area();
|
||||||
});
|
});
|
||||||
var i, poly;
|
let i, poly;
|
||||||
// clear parent/child links if they exist
|
// clear parent/child links if they exist
|
||||||
for (i = 0; i < polygons.length; i++) {
|
for (i = 0; i < polygons.length; i++) {
|
||||||
poly = polygons[i];
|
poly = polygons[i];
|
||||||
|
|
@ -162,8 +161,8 @@ var gs_base_polygons = exports;
|
||||||
for (i = 0; i < polygons.length - 1; i++) {
|
for (i = 0; i < polygons.length - 1; i++) {
|
||||||
poly = polygons[i];
|
poly = polygons[i];
|
||||||
// find the smallest suitable parent
|
// find the smallest suitable parent
|
||||||
for (var j = i + 1; j < polygons.length; j++) {
|
for (let j = i + 1; j < polygons.length; j++) {
|
||||||
var parent = polygons[j];
|
let parent = polygons[j];
|
||||||
// prevent open polys from having inners
|
// prevent open polys from having inners
|
||||||
if (opentop && parent.isOpen()) continue;
|
if (opentop && parent.isOpen()) continue;
|
||||||
if (poly.isNested(parent)) {
|
if (poly.isNested(parent)) {
|
||||||
|
|
@ -173,7 +172,7 @@ var gs_base_polygons = exports;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// tops have an even # depth
|
// tops have an even # depth
|
||||||
var tops = [],
|
let tops = [],
|
||||||
p;
|
p;
|
||||||
// assign a depth level to each group
|
// assign a depth level to each group
|
||||||
for (i = 0; i < polygons.length; i++) {
|
for (i = 0; i < polygons.length; i++) {
|
||||||
|
|
@ -207,7 +206,7 @@ var gs_base_polygons = exports;
|
||||||
*/
|
*/
|
||||||
function setWinding(array, CW, recurse) {
|
function setWinding(array, CW, recurse) {
|
||||||
if (!array) return;
|
if (!array) return;
|
||||||
var poly, i = 0;
|
let poly, i = 0;
|
||||||
while (i < array.length) {
|
while (i < array.length) {
|
||||||
poly = array[i++];
|
poly = array[i++];
|
||||||
if (poly.isClockwise() !== CW) poly.reverse();
|
if (poly.isClockwise() !== CW) poly.reverse();
|
||||||
|
|
@ -223,7 +222,7 @@ var gs_base_polygons = exports;
|
||||||
* @return {boolean} true if aligned clockwise
|
* @return {boolean} true if aligned clockwise
|
||||||
*/
|
*/
|
||||||
function alignWindings(polys) {
|
function alignWindings(polys) {
|
||||||
var len = polys.length,
|
let len = polys.length,
|
||||||
fwd = 0,
|
fwd = 0,
|
||||||
pts = 0,
|
pts = 0,
|
||||||
i = 0,
|
i = 0,
|
||||||
|
|
@ -244,7 +243,7 @@ var gs_base_polygons = exports;
|
||||||
}
|
}
|
||||||
|
|
||||||
function setContains(setA, poly) {
|
function setContains(setA, poly) {
|
||||||
for (var i=0; i<setA.length; i++) {
|
for (let i=0; i<setA.length; i++) {
|
||||||
if (setA[i].contains(poly)) return true;
|
if (setA[i].contains(poly)) return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -272,7 +271,7 @@ var gs_base_polygons = exports;
|
||||||
* @returns {Polygon[]} out
|
* @returns {Polygon[]} out
|
||||||
*/
|
*/
|
||||||
function subtract(setA, setB, outA, outB, z, minArea) {
|
function subtract(setA, setB, outA, outB, z, minArea) {
|
||||||
var clib = self.ClipperLib,
|
let clib = self.ClipperLib,
|
||||||
ctyp = clib.ClipType,
|
ctyp = clib.ClipType,
|
||||||
ptyp = clib.PolyType,
|
ptyp = clib.PolyType,
|
||||||
cfil = clib.PolyFillType,
|
cfil = clib.PolyFillType,
|
||||||
|
|
@ -333,7 +332,7 @@ var gs_base_polygons = exports;
|
||||||
function union(polys, minarea) {
|
function union(polys, minarea) {
|
||||||
if (polys.length < 2) return polys;
|
if (polys.length < 2) return polys;
|
||||||
|
|
||||||
var out = polys.slice(), i, j, union, uset = [];
|
let out = polys.slice(), i, j, union, uset = [];
|
||||||
|
|
||||||
outer: for (i=0; i<out.length; i++) {
|
outer: for (i=0; i<out.length; i++) {
|
||||||
if (!out[i]) continue;
|
if (!out[i]) continue;
|
||||||
|
|
@ -361,7 +360,7 @@ var gs_base_polygons = exports;
|
||||||
* @returns {?Polygon[]}
|
* @returns {?Polygon[]}
|
||||||
*/
|
*/
|
||||||
function doDiff(setA, setB, z) {
|
function doDiff(setA, setB, z) {
|
||||||
var clib = self.ClipperLib,
|
let clib = self.ClipperLib,
|
||||||
ctyp = clib.ClipType,
|
ctyp = clib.ClipType,
|
||||||
ptyp = clib.PolyType,
|
ptyp = clib.PolyType,
|
||||||
cfil = clib.PolyFillType,
|
cfil = clib.PolyFillType,
|
||||||
|
|
@ -391,7 +390,7 @@ var gs_base_polygons = exports;
|
||||||
// handle null/empty slices
|
// handle null/empty slices
|
||||||
if (setA === setB || setA === null || setB === null) return null;
|
if (setA === setB || setA === null || setB === null) return null;
|
||||||
|
|
||||||
var out = [], tmp;
|
let out = [], tmp;
|
||||||
UTIL.doCombinations(setA, setB, {}, function(a, b) {
|
UTIL.doCombinations(setA, setB, {}, function(a, b) {
|
||||||
if (tmp = a.mask(b)) {
|
if (tmp = a.mask(b)) {
|
||||||
out.appendAll(tmp);
|
out.appendAll(tmp);
|
||||||
|
|
@ -402,13 +401,32 @@ var gs_base_polygons = exports;
|
||||||
}
|
}
|
||||||
|
|
||||||
function sumCirc(polys) {
|
function sumCirc(polys) {
|
||||||
var sum = 0.0;
|
let sum = 0.0;
|
||||||
polys.forEach(function(poly) {
|
polys.forEach(function(poly) {
|
||||||
sum += poly.circularityDeep();
|
sum += poly.circularityDeep();
|
||||||
});
|
});
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Polygon[]} polys
|
||||||
|
* @param {number} distance offset
|
||||||
|
* @param {number} [z] defaults to 0
|
||||||
|
*/
|
||||||
|
function expand_lines(poly, distance, z) {
|
||||||
|
let fact = CONF.clipper,
|
||||||
|
clib = self.ClipperLib,
|
||||||
|
cjnt = clib.JoinType,
|
||||||
|
cety = clib.EndType,
|
||||||
|
coff = new clib.ClipperOffset(),
|
||||||
|
ctre = new clib.PolyTree();
|
||||||
|
|
||||||
|
coff.AddPaths(poly.toClipper(), cjnt.jtMiter, cety.etOpenSquare);
|
||||||
|
coff.Execute(ctre, distance * fact);
|
||||||
|
|
||||||
|
return fromClipperTree(ctre, z, null, null, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Polygon[]} polys
|
* @param {Polygon[]} polys
|
||||||
* @param {number} distance offset
|
* @param {number} distance offset
|
||||||
|
|
@ -426,7 +444,7 @@ var gs_base_polygons = exports;
|
||||||
if (poly.inner) setWinding(poly.inner, !poly.isClockwise());
|
if (poly.inner) setWinding(poly.inner, !poly.isClockwise());
|
||||||
});
|
});
|
||||||
|
|
||||||
var fact = CONF.clipper,
|
let fact = CONF.clipper,
|
||||||
clib = self.ClipperLib,
|
clib = self.ClipperLib,
|
||||||
clip = clib.Clipper,
|
clip = clib.Clipper,
|
||||||
cpft = clib.PolyFillType,
|
cpft = clib.PolyFillType,
|
||||||
|
|
@ -437,8 +455,8 @@ var gs_base_polygons = exports;
|
||||||
circ = sumCirc(polys);
|
circ = sumCirc(polys);
|
||||||
|
|
||||||
polys.forEach(function(poly) {
|
polys.forEach(function(poly) {
|
||||||
var clean = clip.CleanPolygons(poly.toClipper(), CONF.clipperClean);
|
let clean = clip.CleanPolygons(poly.toClipper(), CONF.clipperClean);
|
||||||
var simple = clip.SimplifyPolygons(clean, cpft.pftNonZero);
|
let simple = clip.SimplifyPolygons(clean, cpft.pftNonZero);
|
||||||
coff.AddPaths(simple, cjnt.jtMiter, cety.etClosedPolygon);
|
coff.AddPaths(simple, cjnt.jtMiter, cety.etClosedPolygon);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -476,7 +494,7 @@ var gs_base_polygons = exports;
|
||||||
if (poly.inner) setWinding(poly.inner, !poly.isClockwise());
|
if (poly.inner) setWinding(poly.inner, !poly.isClockwise());
|
||||||
});
|
});
|
||||||
|
|
||||||
var fact = CONF.clipper,
|
let fact = CONF.clipper,
|
||||||
clib = self.ClipperLib,
|
clib = self.ClipperLib,
|
||||||
clip = clib.Clipper,
|
clip = clib.Clipper,
|
||||||
cpft = clib.PolyFillType,
|
cpft = clib.PolyFillType,
|
||||||
|
|
@ -489,8 +507,8 @@ var gs_base_polygons = exports;
|
||||||
|
|
||||||
// inset
|
// inset
|
||||||
polys.forEach(function(poly) {
|
polys.forEach(function(poly) {
|
||||||
var clean = clip.CleanPolygons(poly.toClipper(), CONF.clipperClean);
|
let clean = clip.CleanPolygons(poly.toClipper(), CONF.clipperClean);
|
||||||
var simple = clip.SimplifyPolygons(clean, cpft.pftNonZero);
|
let simple = clip.SimplifyPolygons(clean, cpft.pftNonZero);
|
||||||
coff.AddPaths(simple, cjnt.jtMiter, cety.etClosedPolygon);
|
coff.AddPaths(simple, cjnt.jtMiter, cety.etClosedPolygon);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -501,8 +519,8 @@ var gs_base_polygons = exports;
|
||||||
coff = new clib.ClipperOffset();
|
coff = new clib.ClipperOffset();
|
||||||
ctre = new clib.PolyTree();
|
ctre = new clib.PolyTree();
|
||||||
polys.forEach(function(poly) {
|
polys.forEach(function(poly) {
|
||||||
var clean = clip.CleanPolygons(poly.toClipper(), CONF.clipperClean);
|
let clean = clip.CleanPolygons(poly.toClipper(), CONF.clipperClean);
|
||||||
var simple = clip.SimplifyPolygons(clean, cpft.pftNonZero);
|
let simple = clip.SimplifyPolygons(clean, cpft.pftNonZero);
|
||||||
coff.AddPaths(simple, cjnt.jtMiter, cety.etClosedPolygon);
|
coff.AddPaths(simple, cjnt.jtMiter, cety.etClosedPolygon);
|
||||||
});
|
});
|
||||||
coff.Execute(ctre, -over * fact);
|
coff.Execute(ctre, -over * fact);
|
||||||
|
|
@ -510,7 +528,7 @@ var gs_base_polygons = exports;
|
||||||
|
|
||||||
// detect possible thin walls
|
// detect possible thin walls
|
||||||
if (thins) {
|
if (thins) {
|
||||||
var circ1 = sumCirc(orig),
|
let circ1 = sumCirc(orig),
|
||||||
circ2 = sumCirc(polys),
|
circ2 = sumCirc(polys),
|
||||||
diff = Math.abs(1 - (circ1 / circ2));
|
diff = Math.abs(1 - (circ1 / circ2));
|
||||||
|
|
||||||
|
|
@ -545,7 +563,7 @@ var gs_base_polygons = exports;
|
||||||
}
|
}
|
||||||
|
|
||||||
// offset polygon to outer traces array
|
// offset polygon to outer traces array
|
||||||
var calcoff = depth === 0 && last ? offset / 2 : offset,
|
let calcoff = depth === 0 && last ? offset / 2 : offset,
|
||||||
outer = poly.offset(calcoff, []),
|
outer = poly.offset(calcoff, []),
|
||||||
inner = [],
|
inner = [],
|
||||||
j;
|
j;
|
||||||
|
|
@ -563,7 +581,7 @@ var gs_base_polygons = exports;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var newouter = [], newinner = [];
|
let newouter = [], newinner = [];
|
||||||
subtract(outer, inner, newouter, newinner, poly.getZ());
|
subtract(outer, inner, newouter, newinner, poly.getZ());
|
||||||
|
|
||||||
if (newouter.length > 0) {
|
if (newouter.length > 0) {
|
||||||
|
|
@ -596,7 +614,7 @@ var gs_base_polygons = exports;
|
||||||
function fillArea(polys, angle, spacing, output, minLen, maxLen) {
|
function fillArea(polys, angle, spacing, output, minLen, maxLen) {
|
||||||
if (polys.length === 0) return;
|
if (polys.length === 0) return;
|
||||||
|
|
||||||
var i = 1,
|
let i = 1,
|
||||||
p0 = polys[0],
|
p0 = polys[0],
|
||||||
zpos = p0.getZ(),
|
zpos = p0.getZ(),
|
||||||
bounds = p0.bounds.clone(),
|
bounds = p0.bounds.clone(),
|
||||||
|
|
@ -616,7 +634,7 @@ var gs_base_polygons = exports;
|
||||||
while (i < polys.length) bounds.merge(polys[i++].bounds);
|
while (i < polys.length) bounds.merge(polys[i++].bounds);
|
||||||
|
|
||||||
// ray stepping is an axis from the line perpendicular to the ray
|
// ray stepping is an axis from the line perpendicular to the ray
|
||||||
var rayint = output || [],
|
let rayint = output || [],
|
||||||
stepX = -raySlope.dy,
|
stepX = -raySlope.dy,
|
||||||
stepY = raySlope.dx,
|
stepY = raySlope.dx,
|
||||||
iterX = ABS(ABS(stepX) > 0 ? bounds.width() / stepX : 0),
|
iterX = ABS(ABS(stepX) > 0 ? bounds.width() / stepX : 0),
|
||||||
|
|
@ -639,7 +657,7 @@ var gs_base_polygons = exports;
|
||||||
rayint.origin = newPoint(start.x, start.y, start.z);
|
rayint.origin = newPoint(start.x, start.y, start.z);
|
||||||
|
|
||||||
for (i = 0; i < steps; i++) {
|
for (i = 0; i < steps; i++) {
|
||||||
var p1 = newPoint(start.x - raySlope.dx * 1000, start.y - raySlope.dy * 1000, zpos, NOKEY),
|
let p1 = newPoint(start.x - raySlope.dx * 1000, start.y - raySlope.dy * 1000, zpos, NOKEY),
|
||||||
p2 = newPoint(start.x + raySlope.dx * 1000, start.y + raySlope.dy * 1000, zpos, NOKEY);
|
p2 = newPoint(start.x + raySlope.dx * 1000, start.y + raySlope.dy * 1000, zpos, NOKEY);
|
||||||
|
|
||||||
lines.push([p1,p2]);
|
lines.push([p1,p2]);
|
||||||
|
|
@ -655,13 +673,13 @@ var gs_base_polygons = exports;
|
||||||
if (clip.Execute(ctyp.ctIntersection, ctre, cfil.pftNonZero, cfil.pftEvenOdd)) {
|
if (clip.Execute(ctyp.ctIntersection, ctre, cfil.pftNonZero, cfil.pftEvenOdd)) {
|
||||||
ctre.m_AllPolys.forEach(function(poly) {
|
ctre.m_AllPolys.forEach(function(poly) {
|
||||||
if (minlen || maxlen) {
|
if (minlen || maxlen) {
|
||||||
var plen = clib.JS.PerimeterOfPath(poly.m_polygon, false, 1);
|
let plen = clib.JS.PerimeterOfPath(poly.m_polygon, false, 1);
|
||||||
if (minlen && plen < minlen) return;
|
if (minlen && plen < minlen) return;
|
||||||
if (maxlen && plen > maxlen) return;
|
if (maxlen && plen > maxlen) return;
|
||||||
}
|
}
|
||||||
var p1 = newPoint(null,null,zpos,null,poly.m_polygon[0]);
|
let p1 = newPoint(null,null,zpos,null,poly.m_polygon[0]);
|
||||||
var p2 = newPoint(null,null,zpos,null,poly.m_polygon[1]);
|
let p2 = newPoint(null,null,zpos,null,poly.m_polygon[1]);
|
||||||
var od = rayint.origin.distToLineNew(p1,p2) / spacing;
|
let od = rayint.origin.distToLineNew(p1,p2) / spacing;
|
||||||
lines.push([p1, p2, od]);
|
lines.push([p1, p2, od]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -671,7 +689,7 @@ var gs_base_polygons = exports;
|
||||||
})
|
})
|
||||||
|
|
||||||
lines.forEach(function(line) {
|
lines.forEach(function(line) {
|
||||||
var dist = Math.round(line[2]);
|
let dist = Math.round(line[2]);
|
||||||
line[0].index = dist;
|
line[0].index = dist;
|
||||||
line[1].index = dist;
|
line[1].index = dist;
|
||||||
rayint.push(line[0]);
|
rayint.push(line[0]);
|
||||||
|
|
@ -692,7 +710,7 @@ var gs_base_polygons = exports;
|
||||||
* @returns {Point[]}
|
* @returns {Point[]}
|
||||||
*/
|
*/
|
||||||
function rayIntersect(start, slope, polygons, for_fill) {
|
function rayIntersect(start, slope, polygons, for_fill) {
|
||||||
var i = 0,
|
let i = 0,
|
||||||
flat = [],
|
flat = [],
|
||||||
points = [],
|
points = [],
|
||||||
conf = BASE.config,
|
conf = BASE.config,
|
||||||
|
|
@ -703,13 +721,13 @@ var gs_base_polygons = exports;
|
||||||
});
|
});
|
||||||
polygons = flat;
|
polygons = flat;
|
||||||
while (i < polygons.length) {
|
while (i < polygons.length) {
|
||||||
var polygon = polygons[i++],
|
let polygon = polygons[i++],
|
||||||
pp = polygon.points,
|
pp = polygon.points,
|
||||||
pl = pp.length,
|
pl = pp.length,
|
||||||
dbug = BASE.debug,
|
dbug = BASE.debug,
|
||||||
debug = false;
|
debug = false;
|
||||||
for (var j = 0; j < pl; j++) {
|
for (let j = 0; j < pl; j++) {
|
||||||
var j2 = (j + 1) % pl,
|
let j2 = (j + 1) % pl,
|
||||||
ip = UTIL.intersectRayLine(start, slope, pp[j], pp[j2]);
|
ip = UTIL.intersectRayLine(start, slope, pp[j], pp[j2]);
|
||||||
if (ip) {
|
if (ip) {
|
||||||
// add group object to point for cull detection
|
// add group object to point for cull detection
|
||||||
|
|
@ -732,12 +750,12 @@ var gs_base_polygons = exports;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (points.length > 0) {
|
if (points.length > 0) {
|
||||||
var del = false;
|
let del = false;
|
||||||
// sort on distance from ray origin
|
// sort on distance from ray origin
|
||||||
points.sort(function (p1, p2) {
|
points.sort(function (p1, p2) {
|
||||||
// handle passing through line-common end points
|
// handle passing through line-common end points
|
||||||
if (!(p1.del || p2.del) && p1.isNear(p2, merge_dist)) {
|
if (!(p1.del || p2.del) && p1.isNear(p2, merge_dist)) {
|
||||||
var line = [];
|
let line = [];
|
||||||
if (!p1.isNear(p1.p1, merge_dist)) line.push(p1.p1);
|
if (!p1.isNear(p1.p1, merge_dist)) line.push(p1.p1);
|
||||||
if (!p1.isNear(p1.p2, merge_dist)) line.push(p1.p2);
|
if (!p1.isNear(p1.p2, merge_dist)) line.push(p1.p2);
|
||||||
if (!p2.isNear(p2.p1, merge_dist)) line.push(p2.p1);
|
if (!p2.isNear(p2.p1, merge_dist)) line.push(p2.p1);
|
||||||
|
|
@ -780,7 +798,7 @@ var gs_base_polygons = exports;
|
||||||
* ok = diff level (even-odd)
|
* ok = diff level (even-odd)
|
||||||
*/
|
*/
|
||||||
if (for_fill) {
|
if (for_fill) {
|
||||||
var p1, p2;
|
let p1, p2;
|
||||||
i = 0;
|
i = 0;
|
||||||
pl = points.length;
|
pl = points.length;
|
||||||
while (i < pl) {
|
while (i < pl) {
|
||||||
|
|
@ -789,7 +807,7 @@ var gs_base_polygons = exports;
|
||||||
p2 = points[i++];
|
p2 = points[i++];
|
||||||
while (p2 && p2.del && i < pl) p2 = points[i++];
|
while (p2 && p2.del && i < pl) p2 = points[i++];
|
||||||
if (p1 && p2 && p1.group && p1.group) {
|
if (p1 && p2 && p1.group && p1.group) {
|
||||||
var p1g = p1.group,
|
let p1g = p1.group,
|
||||||
p2g = p2.group,
|
p2g = p2.group,
|
||||||
even = (p1g.depth % 2 === 0), // point is on an even depth group
|
even = (p1g.depth % 2 === 0), // point is on an even depth group
|
||||||
same = (p1g === p2g); // points intersect same group
|
same = (p1g === p2g); // points intersect same group
|
||||||
|
|
@ -803,7 +821,7 @@ var gs_base_polygons = exports;
|
||||||
//}
|
//}
|
||||||
// check cull co-linear with group edge
|
// check cull co-linear with group edge
|
||||||
if (same && p1.mod && p2.mod) {
|
if (same && p1.mod && p2.mod) {
|
||||||
var diff = ABS(p1.pos - p2.pos);
|
let diff = ABS(p1.pos - p2.pos);
|
||||||
if (diff === 1 || diff === p1.mod - 1) {
|
if (diff === 1 || diff === p1.mod - 1) {
|
||||||
p1.del = true;
|
p1.del = true;
|
||||||
p2.del = true;
|
p2.del = true;
|
||||||
|
|
@ -817,9 +835,9 @@ var gs_base_polygons = exports;
|
||||||
}
|
}
|
||||||
// handle deletions, if found
|
// handle deletions, if found
|
||||||
if (del) {
|
if (del) {
|
||||||
var np = [];
|
let np = [];
|
||||||
for (i = 0; i < points.length; i++) {
|
for (i = 0; i < points.length; i++) {
|
||||||
var p = points[i];
|
let p = points[i];
|
||||||
if (!p.del) {
|
if (!p.del) {
|
||||||
np.push(p);
|
np.push(p);
|
||||||
}
|
}
|
||||||
|
|
@ -1,17 +1,15 @@
|
||||||
/** Copyright 2014-2019 Stewart Allen -- All Rights Reserved */
|
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var gs_base_render = exports;
|
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
if (!self.base) self.base = {};
|
if (!self.base) self.base = {};
|
||||||
if (self.base.render) return;
|
if (self.base.render) return;
|
||||||
|
|
||||||
var BASE = self.base,
|
const BASE = self.base,
|
||||||
line_width = 1,
|
materialCache = {},
|
||||||
materialCache = {};
|
line_width = 1;
|
||||||
|
|
||||||
BASE.render = {
|
BASE.render = {
|
||||||
wireframe : wireframe
|
wireframe : wireframe
|
||||||
|
|
@ -32,11 +30,11 @@ var gs_base_render = exports;
|
||||||
*/
|
*/
|
||||||
function wireframe(group, points, color) {
|
function wireframe(group, points, color) {
|
||||||
if (points.length % 3 != 0) throw "invalid line : "+points.length;
|
if (points.length % 3 != 0) throw "invalid line : "+points.length;
|
||||||
var lines = new THREE.Geometry(),
|
let lines = new THREE.Geometry(),
|
||||||
hash = {},
|
hash = {},
|
||||||
added = 0;
|
added = 0;
|
||||||
for (var i = 0; i < points.length; i += 3) {
|
for (let i = 0; i < points.length; i += 3) {
|
||||||
var p1 = points[i],
|
let p1 = points[i],
|
||||||
p2 = points[i + 1],
|
p2 = points[i + 1],
|
||||||
p3 = points[i + 2],
|
p3 = points[i + 2],
|
||||||
l1 = newOrderedLine(p1, p2),
|
l1 = newOrderedLine(p1, p2),
|
||||||
|
|
@ -59,7 +57,7 @@ var gs_base_render = exports;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lines.verticesNeedUpdate = true;
|
lines.verticesNeedUpdate = true;
|
||||||
var mesh = new THREE.LineSegments(lines, getMaterial(color));
|
let mesh = new THREE.LineSegments(lines, getMaterial(color));
|
||||||
group.add(mesh);
|
group.add(mesh);
|
||||||
return mesh;
|
return mesh;
|
||||||
}
|
}
|
||||||
|
|
@ -73,7 +71,7 @@ var gs_base_render = exports;
|
||||||
* @returns {THREE.LineBasicMaterial}
|
* @returns {THREE.LineBasicMaterial}
|
||||||
*/
|
*/
|
||||||
function getMaterial(color) {
|
function getMaterial(color) {
|
||||||
var material = materialCache[color];
|
let material = materialCache[color];
|
||||||
if (!material) {
|
if (!material) {
|
||||||
material = new THREE.LineBasicMaterial({
|
material = new THREE.LineBasicMaterial({
|
||||||
fog:false,
|
fog:false,
|
||||||
|
|
@ -1,14 +1,27 @@
|
||||||
/** Copyright 2014-2019 Stewart Allen -- All Rights Reserved */
|
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var gs_base_slope = exports;
|
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
if (!self.base) self.base = {};
|
|
||||||
if (self.base.Slope) return;
|
if (self.base.Slope) return;
|
||||||
|
|
||||||
|
const BASE = self.base,
|
||||||
|
CONF = BASE.config,
|
||||||
|
ABS = Math.abs,
|
||||||
|
PRO = Slope.prototype,
|
||||||
|
DEG2RAD = Math.PI / 180,
|
||||||
|
RAD2DEG = 180 / Math.PI;
|
||||||
|
|
||||||
|
BASE.Slope = Slope;
|
||||||
|
BASE.newSlope = newSlope;
|
||||||
|
BASE.newSlopeFromAngle = function(angle) {
|
||||||
|
return newSlope(0,0,
|
||||||
|
Math.cos(angle * DEG2RAD),
|
||||||
|
Math.sin(angle * DEG2RAD)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param p1
|
* @param p1
|
||||||
|
|
@ -23,23 +36,6 @@ var gs_base_slope = exports;
|
||||||
this.angle = Math.atan2(this.dy, this.dx) * RAD2DEG;
|
this.angle = Math.atan2(this.dy, this.dx) * RAD2DEG;
|
||||||
}
|
}
|
||||||
|
|
||||||
var BASE = self.base,
|
|
||||||
CONF = BASE.config,
|
|
||||||
ABS = Math.abs,
|
|
||||||
PRO = Slope.prototype,
|
|
||||||
DEG2RAD = Math.PI / 180,
|
|
||||||
RAD2DEG = 180 / Math.PI;
|
|
||||||
|
|
||||||
BASE.Slope = Slope;
|
|
||||||
BASE.newSlope = newSlope;
|
|
||||||
|
|
||||||
BASE.newSlopeFromAngle = function(angle) {
|
|
||||||
return newSlope(0,0,
|
|
||||||
Math.cos(angle * DEG2RAD),
|
|
||||||
Math.sin(angle * DEG2RAD)
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
/** ******************************************************************
|
/** ******************************************************************
|
||||||
* Slope Prototype Functions
|
* Slope Prototype Functions
|
||||||
******************************************************************* */
|
******************************************************************* */
|
||||||
|
|
@ -57,7 +53,7 @@ var gs_base_slope = exports;
|
||||||
if (ABS(this.dx) <= CONF.precision_merge && ABS(s.dx) <= CONF.precision_merge) return true;
|
if (ABS(this.dx) <= CONF.precision_merge && ABS(s.dx) <= CONF.precision_merge) return true;
|
||||||
if (ABS(this.dy) <= CONF.precision_merge && ABS(s.dy) <= CONF.precision_merge) return true;
|
if (ABS(this.dy) <= CONF.precision_merge && ABS(s.dy) <= CONF.precision_merge) return true;
|
||||||
// check angle within a range
|
// check angle within a range
|
||||||
var prec = Math.min(1/Math.sqrt(this.dx * this.dx + this.dy * this.dy), CONF.precision_slope_merge);
|
let prec = Math.min(1/Math.sqrt(this.dx * this.dx + this.dy * this.dy), CONF.precision_slope_merge);
|
||||||
return angleWithinDelta(this.angle, s.angle, prec || CONF.precision_slope);
|
return angleWithinDelta(this.angle, s.angle, prec || CONF.precision_slope);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -67,7 +63,7 @@ var gs_base_slope = exports;
|
||||||
* @returns {Slope}
|
* @returns {Slope}
|
||||||
*/
|
*/
|
||||||
PRO.normal = function() {
|
PRO.normal = function() {
|
||||||
var t = this.dx;
|
let t = this.dx;
|
||||||
this.dx = -this.dy;
|
this.dx = -this.dy;
|
||||||
this.dy = t;
|
this.dy = t;
|
||||||
this.angle = Math.atan2(this.dy, this.dx) * RAD2DEG;
|
this.angle = Math.atan2(this.dy, this.dx) * RAD2DEG;
|
||||||
|
|
@ -75,7 +71,7 @@ var gs_base_slope = exports;
|
||||||
};
|
};
|
||||||
|
|
||||||
PRO.toUnit = function() {
|
PRO.toUnit = function() {
|
||||||
var max = Math.max(ABS(this.dx), ABS(this.dy));
|
let max = Math.max(ABS(this.dx), ABS(this.dy));
|
||||||
this.dx = this.dx / max;
|
this.dx = this.dx / max;
|
||||||
this.dy = this.dy / max;
|
this.dy = this.dy / max;
|
||||||
return this;
|
return this;
|
||||||
|
|
@ -1,10 +1,9 @@
|
||||||
|
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var gs_wasm = exports;
|
|
||||||
|
|
||||||
// only active in workers
|
// only active in workers
|
||||||
if (!self.window)
|
if (!self.window) (function() {
|
||||||
(function() {
|
|
||||||
|
|
||||||
if (!self.geo) self.geo = {};
|
if (!self.geo) self.geo = {};
|
||||||
|
|
||||||
3
src/ico/cnc.svg
Normal file
3
src/ico/cnc.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid meet" viewBox="0 0 170 170" width="75px" height="75px"><defs><path d="M15 38.33C15 38.33 15 38.33 15 38.33C15 25.45 25.45 15 38.33 15C44.56 15 75.67 15 131.67 15C131.67 15 131.67 15 131.67 15C137.85 15 143.79 17.46 148.17 21.83C152.54 26.21 155 32.15 155 38.33C155 47.67 155 122.33 155 131.67C155 144.55 144.55 155 131.67 155C122.33 155 47.67 155 38.33 155C25.45 155 15 144.55 15 131.67C15 119.22 15 88.11 15 38.33Z" id="e3irHaXr4"></path><path d="M65 15L105 15L105 125L65 125L65 15Z" id="c1YkLol10d"></path><path d="M105 25L65 55" id="b4hxjCK1zy"></path><path d="M105 55L65 85" id="apUaV8mZu"></path><path d="M105 85L65 115" id="bk21dIqOq"></path></defs><g><g><g><g><use xlink:href="#e3irHaXr4" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#e3irHaXr4" opacity="1" fill-opacity="0" stroke="currentColor" stroke-width="8" stroke-opacity="1"></use></g></g><g><use xlink:href="#c1YkLol10d" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#c1YkLol10d" opacity="1" fill-opacity="0" stroke="currentColor" stroke-width="8" stroke-opacity="1"></use></g></g><g><g><use xlink:href="#b4hxjCK1zy" opacity="1" fill-opacity="0" stroke="currentColor" stroke-width="8.01" stroke-opacity="1"></use></g></g><g><g><use xlink:href="#apUaV8mZu" opacity="1" fill-opacity="0" stroke="currentColor" stroke-width="8.01" stroke-opacity="1"></use></g></g><g><g><use xlink:href="#bk21dIqOq" opacity="1" fill-opacity="0" stroke="currentColor" stroke-width="8.01" stroke-opacity="1"></use></g></g></g></g></g></svg>
|
||||||
|
After Width: | Height: | Size: 1.8 KiB |
3
src/ico/fdm.svg
Normal file
3
src/ico/fdm.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid meet" viewBox="0 0 170 170" width="75px" height="75px"><defs><path d="M15 38.33C15 38.33 15 38.33 15 38.33C15 25.45 25.45 15 38.33 15C44.56 15 75.67 15 131.67 15C131.67 15 131.67 15 131.67 15C137.85 15 143.79 17.46 148.17 21.83C152.54 26.21 155 32.15 155 38.33C155 47.67 155 122.33 155 131.67C155 144.55 144.55 155 131.67 155C122.33 155 47.67 155 38.33 155C25.45 155 15 144.55 15 131.67C15 119.22 15 88.11 15 38.33Z" id="a14Galv9UF"></path><path d="M45 15L125 15L125 75L45 75L45 15Z" id="c3q839LU3"></path><path d="M35 141.48C53.11 141.48 64.43 141.48 68.96 141.48C77.82 141.48 85 134.3 85 125.45C85 125.45 85 125.45 85 125.45" id="chE0t1xfL"></path><path d="M105 95L85 115L65 95L105 95Z" id="a6K998F3GT"></path><path d="M75 75L95 75L95 95L75 95L75 75Z" id="e1iiMERqAh"></path></defs><g><g><g><g><use xlink:href="#a14Galv9UF" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#a14Galv9UF" opacity="1" fill-opacity="0" stroke="currentColor" stroke-width="8" stroke-opacity="1"></use></g></g><g><use xlink:href="#c3q839LU3" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#c3q839LU3" opacity="1" fill-opacity="0" stroke="currentColor" stroke-width="8" stroke-opacity="1"></use></g></g><g><g><use xlink:href="#chE0t1xfL" opacity="1" fill-opacity="0" stroke="currentColor" stroke-width="8.01" stroke-opacity="1"></use></g></g><g><g><use xlink:href="#a6K998F3GT" opacity="1" fill-opacity="0" stroke="currentColor" stroke-width="8.01" stroke-opacity="1"></use></g></g><g><use xlink:href="#e1iiMERqAh" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#e1iiMERqAh" opacity="1" fill-opacity="0" stroke="currentColor" stroke-width="8" stroke-opacity="1"></use></g></g></g></g></g></svg>
|
||||||
|
After Width: | Height: | Size: 2 KiB |
3
src/ico/laser.svg
Normal file
3
src/ico/laser.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid meet" viewBox="0 0 170 170" width="75px" height="75px"><defs><path d="M15 38.33C15 38.33 15 38.33 15 38.33C15 25.45 25.45 15 38.33 15C44.56 15 75.67 15 131.67 15C131.67 15 131.67 15 131.67 15C137.85 15 143.79 17.46 148.17 21.83C152.54 26.21 155 32.15 155 38.33C155 47.67 155 122.33 155 131.67C155 144.55 144.55 155 131.67 155C122.33 155 47.67 155 38.33 155C25.45 155 15 144.55 15 131.67C15 119.22 15 88.11 15 38.33Z" id="a4l00mnEny"></path><path d="M65 15L105 15L105 55L65 55L65 15Z" id="bq8oBWrfG"></path><path d="M85 125L85 65" id="aXzHtGbsD"></path><path d="M55 105L75 135" id="akSzh0QKx"></path><path d="M115 105L95 135" id="bloAs9giZ"></path><path d="M35 125L75 145" id="gk6ohj0JL"></path><path d="M135 123.96L95 145" id="e404eoj7L"></path></defs><g><g><g><g><use xlink:href="#a4l00mnEny" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#a4l00mnEny" opacity="1" fill-opacity="0" stroke="currentColor" stroke-width="8" stroke-opacity="1"></use></g></g><g><use xlink:href="#bq8oBWrfG" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#bq8oBWrfG" opacity="1" fill-opacity="0" stroke="currentColor" stroke-width="8" stroke-opacity="1"></use></g></g><g><g><use xlink:href="#aXzHtGbsD" opacity="1" fill-opacity="0" stroke="currentColor" stroke-width="8.01" stroke-opacity="1"></use></g></g><g><g><use xlink:href="#akSzh0QKx" opacity="1" fill-opacity="0" stroke="currentColor" stroke-width="8.01" stroke-opacity="1"></use></g></g><g><g><use xlink:href="#bloAs9giZ" opacity="1" fill-opacity="0" stroke="currentColor" stroke-width="8.01" stroke-opacity="1"></use></g></g><g><g><use xlink:href="#gk6ohj0JL" opacity="1" fill-opacity="0" stroke="currentColor" stroke-width="8.01" stroke-opacity="1"></use></g></g><g><g><use xlink:href="#e404eoj7L" opacity="1" fill-opacity="0" stroke="currentColor" stroke-width="8.01" stroke-opacity="1"></use></g></g></g></g></g></svg>
|
||||||
|
After Width: | Height: | Size: 2.1 KiB |
3
src/ico/sla.svg
Normal file
3
src/ico/sla.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid meet" viewBox="0 0 170 170" width="75px" height="75px"><defs><path d="M15 38.33C15 38.33 15 38.33 15 38.33C15 25.45 25.45 15 38.33 15C44.56 15 75.67 15 131.67 15C131.67 15 131.67 15 131.67 15C137.85 15 143.79 17.46 148.17 21.83C152.54 26.21 155 32.15 155 38.33C155 47.67 155 122.33 155 131.67C155 144.55 144.55 155 131.67 155C122.33 155 47.67 155 38.33 155C25.45 155 15 144.55 15 131.67C15 119.22 15 88.11 15 38.33Z" id="b3TRNHybxX"></path><path d="M31.88 42.5L138.12 42.5L138.12 47.81L31.88 47.81L31.88 42.5Z" id="aNMkzLwb"></path><path d="M75 21.87L95 21.87L95 41.88L75 41.88L75 21.87Z" id="d1fKKg2Jru"></path><path d="M115.93 107.19C115.93 124.27 102.07 138.13 85 138.13C67.93 138.13 54.07 124.27 54.07 107.19C54.07 90.12 67.93 76.26 85 76.26C102.07 76.26 115.93 90.12 115.93 107.19Z" id="cnyrcTQMg"></path><path d="M53.87 47.81L53.87 107.08" id="a4G9Rr6VQL"></path><path d="M115.76 51.27L115.76 110.53" id="d4hytySQxZ"></path><path d="M69.06 79.69L69.06 47.81" id="b1WQ83ELAA"></path><path d="M100.94 79.69L100.94 47.81" id="f2kNHslaLa"></path><path d="M69.06 58.44L53.13 74.38" id="g67vFJwAFy"></path><path d="M114.68 58.44L100.94 69.06" id="aAcp3z5Kv"></path></defs><g><g><g><use xlink:href="#b3TRNHybxX" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#b3TRNHybxX" opacity="1" fill-opacity="0" stroke="currentColor" stroke-width="8" stroke-opacity="1"></use></g></g><g><use xlink:href="#aNMkzLwb" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#aNMkzLwb" opacity="1" fill-opacity="0" stroke="currentColor" stroke-width="8" stroke-opacity="1"></use></g></g><g><use xlink:href="#d1fKKg2Jru" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#d1fKKg2Jru" opacity="1" fill-opacity="0" stroke="currentColor" stroke-width="8" stroke-opacity="1"></use></g></g><g><use xlink:href="#cnyrcTQMg" opacity="1" fill="#1ea5e6" fill-opacity="0"></use><g><use xlink:href="#cnyrcTQMg" opacity="1" fill-opacity="0" stroke="currentColor" stroke-width="8" stroke-opacity="1"></use></g></g><g><g><use xlink:href="#a4G9Rr6VQL" opacity="1" fill-opacity="0" stroke="currentColor" stroke-width="8" stroke-opacity="1"></use></g></g><g><g><use xlink:href="#d4hytySQxZ" opacity="1" fill-opacity="0" stroke="currentColor" stroke-width="8" stroke-opacity="1"></use></g></g><g><g><use xlink:href="#b1WQ83ELAA" opacity="1" fill-opacity="0" stroke="currentColor" stroke-width="8" stroke-opacity="1"></use></g></g><g><g><use xlink:href="#f2kNHslaLa" opacity="1" fill-opacity="0" stroke="currentColor" stroke-width="8" stroke-opacity="1"></use></g></g><g><g><use xlink:href="#g67vFJwAFy" opacity="1" fill-opacity="0" stroke="currentColor" stroke-width="6" stroke-opacity="1"></use></g></g><g><g><use xlink:href="#aAcp3z5Kv" opacity="1" fill-opacity="0" stroke="currentColor" stroke-width="6" stroke-opacity="1"></use></g></g></g></g></svg>
|
||||||
|
After Width: | Height: | Size: 3.1 KiB |
11
src/kiri.js
Normal file
11
src/kiri.js
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
(function () {
|
||||||
|
|
||||||
|
if (self.kiri) return;
|
||||||
|
|
||||||
|
self.kiri = { };
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
@ -1,19 +1,14 @@
|
||||||
/** Copyright 2014-2019 Stewart Allen -- All Rights Reserved */
|
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var gs_kiri_codec = exports;
|
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
if (!self.kiri) self.kiri = {};
|
|
||||||
if (self.kiri.codec) return;
|
if (self.kiri.codec) return;
|
||||||
|
|
||||||
var base = self.base,
|
const BASE = self.base, KIRI = self.kiri, handlers = {};
|
||||||
kiri = self.kiri,
|
|
||||||
handlers = {};
|
|
||||||
|
|
||||||
kiri.codec = {
|
KIRI.codec = {
|
||||||
encode: encode,
|
encode: encode,
|
||||||
decode: decode,
|
decode: decode,
|
||||||
registerDecoder: registerDecoder
|
registerDecoder: registerDecoder
|
||||||
|
|
@ -24,7 +19,7 @@ var gs_kiri_codec = exports;
|
||||||
if (o === null) return null;
|
if (o === null) return null;
|
||||||
if (o === undefined) return undefined;
|
if (o === undefined) return undefined;
|
||||||
if (Array.isArray(o)) {
|
if (Array.isArray(o)) {
|
||||||
var arr = new Array(o.length), i=0;
|
let arr = new Array(o.length), i=0;
|
||||||
while (i < o.length) arr[i] = encode(o[i++], state);
|
while (i < o.length) arr[i] = encode(o[i++], state);
|
||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
|
|
@ -44,7 +39,7 @@ var gs_kiri_codec = exports;
|
||||||
if (o === null) return null;
|
if (o === null) return null;
|
||||||
if (o === undefined) return undefined;
|
if (o === undefined) return undefined;
|
||||||
if (Array.isArray(o)) {
|
if (Array.isArray(o)) {
|
||||||
for (var i=0; i < o.length; i++) o[i] = decode(o[i],state);
|
for (let i=0; i < o.length; i++) o[i] = decode(o[i],state);
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
switch (typeof(o)) {
|
switch (typeof(o)) {
|
||||||
|
|
@ -64,8 +59,8 @@ var gs_kiri_codec = exports;
|
||||||
|
|
||||||
function genOEncode(o, state) {
|
function genOEncode(o, state) {
|
||||||
if (o instanceof Float32Array) return o;
|
if (o instanceof Float32Array) return o;
|
||||||
var out = {};
|
let out = {};
|
||||||
for (var k in o) {
|
for (let k in o) {
|
||||||
if (o.hasOwnProperty(k)) out[k] = encode(o[k], state);
|
if (o.hasOwnProperty(k)) out[k] = encode(o[k], state);
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
|
|
@ -73,8 +68,8 @@ var gs_kiri_codec = exports;
|
||||||
|
|
||||||
function genODecode(o, state) {
|
function genODecode(o, state) {
|
||||||
if (o instanceof Float32Array) return o;
|
if (o instanceof Float32Array) return o;
|
||||||
var out = {};
|
let out = {};
|
||||||
for (var k in o) {
|
for (let k in o) {
|
||||||
if (o.hasOwnProperty(k)) out[k] = decode(o[k], state);
|
if (o.hasOwnProperty(k)) out[k] = decode(o[k], state);
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
|
|
@ -84,7 +79,7 @@ var gs_kiri_codec = exports;
|
||||||
* Object CODEC Functions
|
* Object CODEC Functions
|
||||||
******************************************************************* */
|
******************************************************************* */
|
||||||
|
|
||||||
kiri.Slice.prototype.encode = function(state) {
|
KIRI.Slice.prototype.encode = function(state) {
|
||||||
return {
|
return {
|
||||||
type: 'slice',
|
type: 'slice',
|
||||||
z: this.z,
|
z: this.z,
|
||||||
|
|
@ -100,7 +95,7 @@ var gs_kiri_codec = exports;
|
||||||
};
|
};
|
||||||
|
|
||||||
registerDecoder('slice', function(v, state) {
|
registerDecoder('slice', function(v, state) {
|
||||||
var slice = kiri.newSlice(v.z, state.mesh ? state.mesh.newGroup() : null);
|
let slice = KIRI.newSlice(v.z, state.mesh ? state.mesh.newGroup() : null);
|
||||||
|
|
||||||
slice.index = v.index;
|
slice.index = v.index;
|
||||||
slice.camMode = v.camMode;
|
slice.camMode = v.camMode;
|
||||||
|
|
@ -114,7 +109,7 @@ var gs_kiri_codec = exports;
|
||||||
return slice;
|
return slice;
|
||||||
});
|
});
|
||||||
|
|
||||||
kiri.Top.prototype.encode = function(state) {
|
KIRI.Top.prototype.encode = function(state) {
|
||||||
return {
|
return {
|
||||||
type: 'top',
|
type: 'top',
|
||||||
poly: encode(this.poly, state),
|
poly: encode(this.poly, state),
|
||||||
|
|
@ -129,7 +124,7 @@ var gs_kiri_codec = exports;
|
||||||
};
|
};
|
||||||
|
|
||||||
registerDecoder('top', function(v, state) {
|
registerDecoder('top', function(v, state) {
|
||||||
var top = kiri.newTop(decode(v.poly, state));
|
let top = KIRI.newTop(decode(v.poly, state));
|
||||||
|
|
||||||
top.traces = decode(v.traces, state);
|
top.traces = decode(v.traces, state);
|
||||||
top.inner = decode(v.inner, state);
|
top.inner = decode(v.inner, state);
|
||||||
|
|
@ -145,7 +140,7 @@ var gs_kiri_codec = exports;
|
||||||
function encodePointArray(points, state) {
|
function encodePointArray(points, state) {
|
||||||
if (!points) return null;
|
if (!points) return null;
|
||||||
|
|
||||||
var array = new Float32Array(points.length * 3),
|
let array = new Float32Array(points.length * 3),
|
||||||
pos = 0;
|
pos = 0;
|
||||||
|
|
||||||
points.forEach(function(point) {
|
points.forEach(function(point) {
|
||||||
|
|
@ -174,21 +169,21 @@ var gs_kiri_codec = exports;
|
||||||
function decodePointArray(array) {
|
function decodePointArray(array) {
|
||||||
if (!array) return null;
|
if (!array) return null;
|
||||||
|
|
||||||
var vid = 0,
|
let vid = 0,
|
||||||
pid = 0,
|
pid = 0,
|
||||||
points = new Array(array.length/3);
|
points = new Array(array.length/3);
|
||||||
|
|
||||||
while (vid < array.length) {
|
while (vid < array.length) {
|
||||||
points[pid++] = base.newPoint(array[vid++], array[vid++], array[vid++]);
|
points[pid++] = BASE.newPoint(array[vid++], array[vid++], array[vid++]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return points;
|
return points;
|
||||||
}
|
}
|
||||||
|
|
||||||
base.Polygon.prototype.encode = function(state) {
|
BASE.Polygon.prototype.encode = function(state) {
|
||||||
if (!state.poly) state.poly = {};
|
if (!state.poly) state.poly = {};
|
||||||
|
|
||||||
var cached = state.poly[this.id];
|
let cached = state.poly[this.id];
|
||||||
|
|
||||||
if (cached) {
|
if (cached) {
|
||||||
return {
|
return {
|
||||||
|
|
@ -216,11 +211,11 @@ var gs_kiri_codec = exports;
|
||||||
|
|
||||||
if (v.ref) return state.poly[v.ref];
|
if (v.ref) return state.poly[v.ref];
|
||||||
|
|
||||||
var poly = base.newPolygon(),
|
let poly = BASE.newPolygon(),
|
||||||
vid = 0;
|
vid = 0;
|
||||||
|
|
||||||
while (vid < v.array.length) {
|
while (vid < v.array.length) {
|
||||||
poly.push(base.newPoint(v.array[vid++], v.array[vid++], v.array[vid++]));
|
poly.push(BASE.newPoint(v.array[vid++], v.array[vid++], v.array[vid++]));
|
||||||
}
|
}
|
||||||
|
|
||||||
poly.id = v.id;
|
poly.id = v.id;
|
||||||
|
|
@ -1,17 +1,12 @@
|
||||||
/** Copyright Stewart Allen -- All Rights Reserved */
|
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
let gs_kiri_conf = exports;
|
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
if (!self.kiri) self.kiri = {};
|
|
||||||
if (self.kiri.conf) return;
|
if (self.kiri.conf) return;
|
||||||
|
|
||||||
let KIRI = self.kiri,
|
const KIRI = self.kiri, CVER = 185, clone = Object.clone;
|
||||||
CVER = 185,
|
|
||||||
clone = Object.clone;
|
|
||||||
|
|
||||||
function genID() {
|
function genID() {
|
||||||
while (true) {
|
while (true) {
|
||||||
|
|
@ -352,6 +347,7 @@ let gs_kiri_conf = exports;
|
||||||
p:{
|
p:{
|
||||||
processName: "default",
|
processName: "default",
|
||||||
camFastFeed: 6000,
|
camFastFeed: 6000,
|
||||||
|
camFastFeedZ: 300,
|
||||||
roughingTool: 1000,
|
roughingTool: 1000,
|
||||||
roughingSpindle: 1000,
|
roughingSpindle: 1000,
|
||||||
roughingDown: 2,
|
roughingDown: 2,
|
||||||
|
|
@ -542,14 +538,17 @@ let gs_kiri_conf = exports;
|
||||||
view: null,
|
view: null,
|
||||||
dark: false,
|
dark: false,
|
||||||
expert: false,
|
expert: false,
|
||||||
compact: false,
|
|
||||||
zoomSpeed: 1.0,
|
zoomSpeed: 1.0,
|
||||||
|
thinRender: false,
|
||||||
reverseZoom: true,
|
reverseZoom: true,
|
||||||
showOrigin: false,
|
showOrigin: false,
|
||||||
freeLayout: true,
|
freeLayout: true,
|
||||||
autoLayout: true,
|
autoLayout: true,
|
||||||
alignTop: true,
|
alignTop: true,
|
||||||
units: "mm"
|
units: "mm",
|
||||||
|
exportOcto: true,
|
||||||
|
exportGhost: false,
|
||||||
|
exportLocal: false
|
||||||
},
|
},
|
||||||
// for passing temporary slice hints (topo currently)
|
// for passing temporary slice hints (topo currently)
|
||||||
synth: {},
|
synth: {},
|
||||||
|
|
@ -1,18 +1,16 @@
|
||||||
/** Copyright 2014-2019 Stewart Allen -- All Rights Reserved */
|
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var gs_kiri_db = exports;
|
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
if (!self.kiri) self.kiri = { };
|
const KIRI = self.kiri, DP = Catalog.prototype;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
function Catalog(motodb, decimate) {
|
function Catalog(motodb, decimate) {
|
||||||
var store = this;
|
let store = this;
|
||||||
store.db = motodb;
|
store.db = motodb;
|
||||||
store.files = {};
|
store.files = {};
|
||||||
store.listeners = [];
|
store.listeners = [];
|
||||||
|
|
@ -21,15 +19,12 @@ var gs_kiri_db = exports;
|
||||||
store.refresh();
|
store.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
var kiri = self.kiri,
|
KIRI.openCatalog = function(motodb,decimate) {
|
||||||
DP = Catalog.prototype;
|
|
||||||
|
|
||||||
kiri.openCatalog = function(motodb,decimate) {
|
|
||||||
return new Catalog(motodb,decimate);
|
return new Catalog(motodb,decimate);
|
||||||
};
|
};
|
||||||
|
|
||||||
DP.refresh = function() {
|
DP.refresh = function() {
|
||||||
var store = this;
|
let store = this;
|
||||||
store.db.get('files', function(files) {
|
store.db.get('files', function(files) {
|
||||||
if (files) {
|
if (files) {
|
||||||
store.files = files;
|
store.files = files;
|
||||||
|
|
@ -39,7 +34,7 @@ var gs_kiri_db = exports;
|
||||||
};
|
};
|
||||||
|
|
||||||
DP.wipe = function() {
|
DP.wipe = function() {
|
||||||
var key, files = this.files;
|
let key, files = this.files;
|
||||||
for (key in files) {
|
for (key in files) {
|
||||||
if (files.hasOwnProperty(key)) this.deleteFile(key);
|
if (files.hasOwnProperty(key)) this.deleteFile(key);
|
||||||
}
|
}
|
||||||
|
|
@ -66,14 +61,14 @@ var gs_kiri_db = exports;
|
||||||
}
|
}
|
||||||
|
|
||||||
function notifyFileListeners(store) {
|
function notifyFileListeners(store) {
|
||||||
for (var i=0; i<store.listeners.length; i++) {
|
for (let i=0; i<store.listeners.length; i++) {
|
||||||
store.listeners[i](store.files);
|
store.listeners[i](store.files);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DP.decimate = function(vertices, callback) {
|
DP.decimate = function(vertices, callback) {
|
||||||
if (vertices.length < 500000) return callback(vertices);
|
if (vertices.length < 500000) return callback(vertices);
|
||||||
kiri.work.decimate(vertices, function(reply) {
|
KIRI.work.decimate(vertices, function(reply) {
|
||||||
callback(reply);
|
callback(reply);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
@ -96,7 +91,7 @@ var gs_kiri_db = exports;
|
||||||
* @param {Function} [callback]
|
* @param {Function} [callback]
|
||||||
*/
|
*/
|
||||||
DP.putFile = function(name, vertices, callback) {
|
DP.putFile = function(name, vertices, callback) {
|
||||||
var store = this;
|
let store = this;
|
||||||
store.db.put('file-'+name, vertices, function(ok) {
|
store.db.put('file-'+name, vertices, function(ok) {
|
||||||
if (ok) {
|
if (ok) {
|
||||||
store.files[name] = {
|
store.files[name] = {
|
||||||
|
|
@ -114,12 +109,39 @@ var gs_kiri_db = exports;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
DP.rename = function(name, newname, callback) {
|
||||||
|
if (!this.files[name]) return callback({error: 'no such file'});
|
||||||
|
if (!newname || newname == name) return callback({error: 'invalid new name'});
|
||||||
|
let done = 0;
|
||||||
|
let error = [];
|
||||||
|
let store = this;
|
||||||
|
function complete(ok, err) {
|
||||||
|
if (err) error.push(err);
|
||||||
|
if (++done === 2) {
|
||||||
|
store.files[newname] = store.files[name];
|
||||||
|
delete store.files[name];
|
||||||
|
saveFileList(store);
|
||||||
|
store.db.remove(`fdec-${name}`);
|
||||||
|
store.db.remove(`file-${name}`);
|
||||||
|
callback(error.length ? {error} : {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
store.db.get(`fdec-${name}`, (vertices) => {
|
||||||
|
if (!vertices) return complete(false, 'no decimation');
|
||||||
|
store.db.put(`fdec-${newname}`, vertices, complete);
|
||||||
|
});
|
||||||
|
store.db.get(`file-${name}`, (vertices) => {
|
||||||
|
if (!vertices) return complete(false, 'no raw file');
|
||||||
|
store.db.put(`file-${newname}`, vertices, complete);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {String} name
|
* @param {String} name
|
||||||
* @param {Function} callback
|
* @param {Function} callback
|
||||||
*/
|
*/
|
||||||
DP.getFile = function(name, callback) {
|
DP.getFile = function(name, callback) {
|
||||||
var store = this,
|
let store = this,
|
||||||
rec = store.files[name];
|
rec = store.files[name];
|
||||||
if (rec && rec.deferred) {
|
if (rec && rec.deferred) {
|
||||||
if (store.deferredHandler) return store.deferredHandler(rec.deferred, name, callback);
|
if (store.deferredHandler) return store.deferredHandler(rec.deferred, name, callback);
|
||||||
|
|
@ -152,7 +174,7 @@ var gs_kiri_db = exports;
|
||||||
* @param {Function} callback
|
* @param {Function} callback
|
||||||
*/
|
*/
|
||||||
DP.deleteFile = function(name, callback) {
|
DP.deleteFile = function(name, callback) {
|
||||||
var store = this;
|
let store = this;
|
||||||
if (store.files[name]) {
|
if (store.files[name]) {
|
||||||
delete store.files[name];
|
delete store.files[name];
|
||||||
store.db.remove('fdec-'+name);
|
store.db.remove('fdec-'+name);
|
||||||
|
|
@ -1,26 +1,24 @@
|
||||||
/** Copyright Stewart Allen -- All Rights Reserved */
|
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
let gs_kiri_export = exports;
|
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
if (!self.kiri) self.kiri = { };
|
|
||||||
if (self.kiri.export) return;
|
if (self.kiri.export) return;
|
||||||
|
|
||||||
let KIRI = self.kiri,
|
const KIRI = self.kiri,
|
||||||
BASE = self.base,
|
BASE = self.base,
|
||||||
UTIL = BASE.util,
|
UTIL = BASE.util,
|
||||||
API = KIRI.api,
|
API = KIRI.api,
|
||||||
SDB = API.sdb,
|
SDB = API.sdb,
|
||||||
UI = API.ui,
|
UI = API.ui,
|
||||||
STATS = API.stats,
|
STATS = API.stats,
|
||||||
MODES = API.const.MODES,
|
MODES = API.const.MODES;
|
||||||
printSeq = parseInt(SDB['kiri-print-seq'] || SDB['print-seq'] || "0") + 1;
|
|
||||||
|
|
||||||
KIRI.export = exportPrint;
|
KIRI.export = exportPrint;
|
||||||
|
|
||||||
|
let printSeq = parseInt(SDB['kiri-print-seq'] || SDB['print-seq'] || "0") + 1;
|
||||||
|
|
||||||
function exportPrint() {
|
function exportPrint() {
|
||||||
let currentPrint = API.print.get();
|
let currentPrint = API.print.get();
|
||||||
if (currentPrint) {
|
if (currentPrint) {
|
||||||
|
|
@ -56,8 +54,12 @@ let gs_kiri_export = exports;
|
||||||
}
|
}
|
||||||
segment = line.message;
|
segment = line.message;
|
||||||
}
|
}
|
||||||
if (line.progress) API.show.progress(line.progress, "exporting");
|
if (line.progress) {
|
||||||
if (line.data) lines.push(line.data);
|
API.show.progress(line.progress, "exporting");
|
||||||
|
}
|
||||||
|
if (line.data) {
|
||||||
|
lines.push(line.data);
|
||||||
|
}
|
||||||
}, function(done) {
|
}, function(done) {
|
||||||
currentPrint.exported = true;
|
currentPrint.exported = true;
|
||||||
times[`${seq++}_${segment}`] = Date.now() - mark;
|
times[`${seq++}_${segment}`] = Date.now() - mark;
|
||||||
|
|
@ -115,7 +117,6 @@ let gs_kiri_export = exports;
|
||||||
UI.print.innerHTML = html;
|
UI.print.innerHTML = html;
|
||||||
$('print-filename').value = filename;
|
$('print-filename').value = filename;
|
||||||
$('print-lines').value = UTIL.comma(segments);
|
$('print-lines').value = UTIL.comma(segments);
|
||||||
$('print-close').onclick = API.modal.hide;
|
|
||||||
$('print-svg').onclick = download_svg;
|
$('print-svg').onclick = download_svg;
|
||||||
$('print-dxf').onclick = download_dxf;
|
$('print-dxf').onclick = download_dxf;
|
||||||
$('print-lg').onclick = download_gcode;
|
$('print-lg').onclick = download_gcode;
|
||||||
|
|
@ -183,6 +184,7 @@ let gs_kiri_export = exports;
|
||||||
} else {
|
} else {
|
||||||
API.show.alert("octoprint error\nstatus: "+status+"\nmessage: "+ajax.responseText);
|
API.show.alert("octoprint error\nstatus: "+status+"\nmessage: "+ajax.responseText);
|
||||||
}
|
}
|
||||||
|
API.show.progress(0);
|
||||||
}
|
}
|
||||||
API.show.progress(0);
|
API.show.progress(0);
|
||||||
};
|
};
|
||||||
|
|
@ -216,7 +218,15 @@ let gs_kiri_export = exports;
|
||||||
let dev = devs[uuid];
|
let dev = devs[uuid];
|
||||||
html.push(`<option id="gl-${uuid}" value="${uuid}">${dev.stat.device.name}</option>`);
|
html.push(`<option id="gl-${uuid}" value="${uuid}">${dev.stat.device.name}</option>`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (html.length) {
|
||||||
$('grid-local').innerHTML = html.join('\n');
|
$('grid-local').innerHTML = html.join('\n');
|
||||||
|
$('send-to-gridhead').style.display = 'flex';
|
||||||
|
$('send-to-gridspool').style.display = 'flex';
|
||||||
|
} else {
|
||||||
|
$('send-to-gridhead').style.display = '';
|
||||||
|
$('send-to-gridspool').style.display = '';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendto_gridlocal() {
|
function sendto_gridlocal() {
|
||||||
|
|
@ -415,33 +425,39 @@ let gs_kiri_export = exports;
|
||||||
mins = floor(newtime / 60),
|
mins = floor(newtime / 60),
|
||||||
secs = newtime - mins * 60;
|
secs = newtime - mins * 60;
|
||||||
|
|
||||||
$('mill-time').value = $('print-time').value = [pad(hours),pad(mins),pad(secs)].join(':');
|
$('output-time').value = [pad(hours),pad(mins),pad(secs)].join(':');
|
||||||
}
|
}
|
||||||
|
|
||||||
API.ajax("/kiri/output-gcode.html", function(html) {
|
fetch("/kiri/output-gcode.html").then(r => r.text()).then(html => {
|
||||||
UI.print.innerHTML = html;
|
UI.print.innerHTML = html;
|
||||||
$('print-close').onclick = API.modal.hide;
|
let set = API.conf.get();
|
||||||
|
let fdm = MODE === MODES.FDM;
|
||||||
|
let octo = set.controller.exportOcto && MODE !== MODES.CAM;
|
||||||
|
let ghost = set.controller.exportGhost;
|
||||||
|
let local = set.controller.exportLocal;
|
||||||
$('print-download').onclick = download;
|
$('print-download').onclick = download;
|
||||||
$('print-octoprint').onclick = sendto_octoprint;
|
$('print-filament-head').style.display = fdm ? '' : 'none';
|
||||||
$('print-gridhost').onclick = sendto_gridhost;
|
$('print-filament-info').style.display = fdm ? '' : 'none';
|
||||||
$('print-gridlocal').onclick = sendto_gridlocal;
|
|
||||||
$('admin-gridlocal').onclick = admin_gridlocal;
|
|
||||||
$('print-filament-row').style.display = MODE === MODES.FDM ? '' : 'none';
|
|
||||||
$('mill-info').style.display = MODE === MODES.CAM ? '' : 'none';
|
|
||||||
$('print-filename').value = filename;
|
$('print-filename').value = filename;
|
||||||
$('print-filesize').value = UTIL.comma(currentPrint.bytes);
|
$('print-filesize').value = UTIL.comma(currentPrint.bytes);
|
||||||
$('print-filament').value = Math.round(currentPrint.distance);
|
$('print-filament').value = Math.round(currentPrint.distance);
|
||||||
$('grid-host').onkeyup = gridhost_probe;
|
|
||||||
$('grid-apik').onkeyup = gridhost_probe;
|
|
||||||
calcTime();
|
calcTime();
|
||||||
if (MODE === MODES.FDM) {
|
if (fdm) {
|
||||||
calcWeight();
|
calcWeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// octoprint setup
|
||||||
|
$('send-to-octohead').style.display = octo ? '' : 'none';
|
||||||
|
$('send-to-octoprint').style.display = octo ? '' : 'none';
|
||||||
|
if (octo) try {
|
||||||
|
$('print-octoprint').onclick = sendto_octoprint;
|
||||||
octo_host = $('octo-host');
|
octo_host = $('octo-host');
|
||||||
octo_apik = $('octo-apik');
|
octo_apik = $('octo-apik');
|
||||||
if (MODE === MODES.CAM) {
|
if (MODE === MODES.CAM) {
|
||||||
|
$('send-to-octohead').style.display = 'none';
|
||||||
$('send-to-octoprint').style.display = 'none';
|
$('send-to-octoprint').style.display = 'none';
|
||||||
} else {
|
} else {
|
||||||
|
$('send-to-octohead').style.display = '';
|
||||||
$('send-to-octoprint').style.display = '';
|
$('send-to-octoprint').style.display = '';
|
||||||
}
|
}
|
||||||
// hide octoprint when hard-coded in the url
|
// hide octoprint when hard-coded in the url
|
||||||
|
|
@ -453,6 +469,15 @@ let gs_kiri_export = exports;
|
||||||
}
|
}
|
||||||
octo_host.value = SDB['octo-host'] || '';
|
octo_host.value = SDB['octo-host'] || '';
|
||||||
octo_apik.value = SDB['octo-apik'] || '';
|
octo_apik.value = SDB['octo-apik'] || '';
|
||||||
|
} catch (e) { console.log(e) }
|
||||||
|
|
||||||
|
// grid:host setup
|
||||||
|
$('send-to-hosthead').style.display = ghost ? '' : 'none';
|
||||||
|
$('send-to-gridhost').style.display = ghost ? '' : 'none';
|
||||||
|
if (ghost) try {
|
||||||
|
$('print-gridhost').onclick = sendto_gridhost;
|
||||||
|
$('grid-host').onkeyup = gridhost_probe;
|
||||||
|
$('grid-apik').onkeyup = gridhost_probe;
|
||||||
grid_host = $('grid-host');
|
grid_host = $('grid-host');
|
||||||
grid_apik = $('grid-apik');
|
grid_apik = $('grid-apik');
|
||||||
grid_target = $('grid-target');
|
grid_target = $('grid-target');
|
||||||
|
|
@ -462,7 +487,16 @@ let gs_kiri_export = exports;
|
||||||
grid_host.value = SDB['grid-host'] || '';
|
grid_host.value = SDB['grid-host'] || '';
|
||||||
grid_apik.value = SDB['grid-apik'] || '';
|
grid_apik.value = SDB['grid-apik'] || '';
|
||||||
gridhost_probe();
|
gridhost_probe();
|
||||||
|
} catch (e) { console.log(e) }
|
||||||
|
|
||||||
|
// grid:local setup
|
||||||
|
if (local) try {
|
||||||
gridlocal_probe();
|
gridlocal_probe();
|
||||||
|
$('print-gridlocal').onclick = sendto_gridlocal;
|
||||||
|
$('admin-gridlocal').onclick = admin_gridlocal;
|
||||||
|
} catch (e) { console.log(e) }
|
||||||
|
|
||||||
|
// show dialog
|
||||||
API.modal.show('print');
|
API.modal.show('print');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -1,15 +1,12 @@
|
||||||
/** Copyright 2014-2019 Stewart Allen -- All Rights Reserved */
|
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var gs_kiri_fill = exports;
|
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
if (!self.kiri) self.kiri = {};
|
|
||||||
if (self.kiri.fill) return;
|
if (self.kiri.fill) return;
|
||||||
|
|
||||||
let KIRI = self.kiri,
|
const KIRI = self.kiri,
|
||||||
BASE = self.base,
|
BASE = self.base,
|
||||||
UTIL = BASE.util,
|
UTIL = BASE.util,
|
||||||
ROUND = UTIL.round,
|
ROUND = UTIL.round,
|
||||||
File diff suppressed because it is too large
Load diff
1
src/kiri/lang-en.js
Symbolic link
1
src/kiri/lang-en.js
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../../web/kiri/lang/en.js
|
||||||
|
|
@ -1,17 +1,14 @@
|
||||||
/** Copyright 2014-2019 Stewart Allen -- All Rights Reserved */
|
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
let gs_kiri_lang = exports;
|
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
if (!self.kiri) self.kiri = {};
|
|
||||||
if (self.kiri.lang) return;
|
if (self.kiri.lang) return;
|
||||||
|
|
||||||
let KIRI = self.kiri,
|
const KIRI = self.kiri, LANG = self.kiri.lang = { current: {} };
|
||||||
LANG = self.kiri.lang = { current: {} },
|
|
||||||
lset = navigator.language.toLocaleLowerCase();
|
let lset = navigator.language.toLocaleLowerCase();
|
||||||
|
|
||||||
LANG.get = function() {
|
LANG.get = function() {
|
||||||
return lset;
|
return lset;
|
||||||
|
|
@ -1,15 +1,12 @@
|
||||||
/** Copyright 2014-2019 Stewart Allen -- All Rights Reserved */
|
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
let gs_kiri_layer = exports;
|
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
if (!self.kiri) self.kiri = {};
|
|
||||||
if (self.kiri.Layer) return;
|
if (self.kiri.Layer) return;
|
||||||
|
|
||||||
let KIRI = self.kiri,
|
const KIRI = self.kiri,
|
||||||
POLY = self.base.polygons,
|
POLY = self.base.polygons,
|
||||||
LP = Layer.prototype,
|
LP = Layer.prototype,
|
||||||
mcache = {};
|
mcache = {};
|
||||||
|
|
@ -82,30 +79,35 @@ let gs_kiri_layer = exports;
|
||||||
this.view = view;
|
this.view = view;
|
||||||
this.bycolor = {};
|
this.bycolor = {};
|
||||||
this.opacity = 0.15,
|
this.opacity = 0.15,
|
||||||
this.specular = 0x181818,
|
this.specular = 0x181818;
|
||||||
this.shininess = 100,
|
this.shininess = 100;
|
||||||
this.transparent = true;
|
this.transparent = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
LP.setOpacity = function(v) {
|
LP.setOpacity = function(v) {
|
||||||
this.opacity = v;
|
this.opacity = v;
|
||||||
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
LP.setSpecular = function(v) {
|
LP.setSpecular = function(v) {
|
||||||
this.specular = v;
|
this.specular = v;
|
||||||
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
LP.setShininess = function(v) {
|
LP.setShininess = function(v) {
|
||||||
this.shininess = v;
|
this.shininess = v;
|
||||||
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
LP.setTransparent = function(b) {
|
LP.setTransparent = function(b) {
|
||||||
this.transparent = b;
|
this.transparent = b;
|
||||||
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
LP.setVisible = function(vis) {
|
LP.setVisible = function(vis) {
|
||||||
if (this.group) this.group.visible = vis;
|
if (this.group) this.group.visible = vis;
|
||||||
if (this.solids) this.solids.visible = vis;
|
if (this.solids) this.solids.visible = vis;
|
||||||
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
LP.clear = function() {
|
LP.clear = function() {
|
||||||
|
|
@ -117,6 +119,7 @@ let gs_kiri_layer = exports;
|
||||||
let ca = this.bycolor[color];
|
let ca = this.bycolor[color];
|
||||||
if (!ca) ca = this.bycolor[color] = [];
|
if (!ca) ca = this.bycolor[color] = [];
|
||||||
ca.push(obj);
|
ca.push(obj);
|
||||||
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
LP.poly = function(poly, color, deep, open) {
|
LP.poly = function(poly, color, deep, open) {
|
||||||
|
|
@ -127,14 +130,17 @@ let gs_kiri_layer = exports;
|
||||||
this.add(color, {poly:poly, deep:deep, open:open});
|
this.add(color, {poly:poly, deep:deep, open:open});
|
||||||
this.changed = true;
|
this.changed = true;
|
||||||
}
|
}
|
||||||
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
LP.solid = function(poly, color) {
|
LP.solid = function(poly, color) {
|
||||||
this.add(color, {solid: poly});
|
this.add(color, {solid: poly});
|
||||||
this.changed = true;
|
this.changed = true;
|
||||||
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
LP.noodle = function(poly, offset, color, traceColor, open) {
|
LP.noodle = function(poly, offset, color, traceColor, open) {
|
||||||
|
if (!poly) return;
|
||||||
if (Array.isArray(poly)) {
|
if (Array.isArray(poly)) {
|
||||||
poly = POLY.flatten(poly, [], true);
|
poly = POLY.flatten(poly, [], true);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -148,11 +154,38 @@ let gs_kiri_layer = exports;
|
||||||
POLY.expand([p], -offset, z-0.01, exp, 1);
|
POLY.expand([p], -offset, z-0.01, exp, 1);
|
||||||
POLY.nest(exp).forEach((p,i) => {
|
POLY.nest(exp).forEach((p,i) => {
|
||||||
this.add(color, {solid: p});
|
this.add(color, {solid: p});
|
||||||
p = p.clone(true).setZ(z + 0.01);
|
this.add(traceColor, {poly: p.clone(true).setZ(z + 0.01), deep: true, open});
|
||||||
this.add(traceColor, {poly: p, deep: true, open});
|
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
this.changed = true;
|
this.changed = true;
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
LP.noodle_open = function(poly, offset, color, traceColor, z) {
|
||||||
|
poly = POLY.expand_lines(poly, offset, z);
|
||||||
|
poly.forEach(p => {
|
||||||
|
this.add(color, {solid: p});
|
||||||
|
this.add(traceColor, {poly: p.clone().setZ(z + 0.01), deep: false, open: false});
|
||||||
|
})
|
||||||
|
this.changed = true;
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
LP.noodle_lines = function(points, offset, color, traceColor, z) {
|
||||||
|
if (!(points && points.length)) return;
|
||||||
|
for (let i=0; i<points.length; i += 2) {
|
||||||
|
let p1 = points[i];
|
||||||
|
let p2 = points[i+1];
|
||||||
|
let l1 = p1.offsetLineTo(p2, offset);
|
||||||
|
let l2 = p2.offsetLineTo(p1, offset);
|
||||||
|
let poly = base.newPolygon().addPoints([
|
||||||
|
l1.p1, l1.p2, l2.p1, l2.p2
|
||||||
|
]);
|
||||||
|
this.add(color, {solid: poly});
|
||||||
|
this.add(traceColor, {poly: poly.clone().setZ(z + 0.01), deep: false, open: false});
|
||||||
|
}
|
||||||
|
this.changed = true;
|
||||||
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
LP.points = function(points, color, size, opacity) {
|
LP.points = function(points, color, size, opacity) {
|
||||||
|
|
@ -188,11 +221,13 @@ let gs_kiri_layer = exports;
|
||||||
toVector({x:p.x-sz, y:p.y-sz, z:p.z-sz}),
|
toVector({x:p.x-sz, y:p.y-sz, z:p.z-sz}),
|
||||||
], color);
|
], color);
|
||||||
});
|
});
|
||||||
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
LP.lines = function(points, color) {
|
LP.lines = function(points, color) {
|
||||||
this.add(color, {lines:points});
|
this.add(color, {lines:points});
|
||||||
this.changed = true;
|
this.changed = true;
|
||||||
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
LP.renderAll = function() {
|
LP.renderAll = function() {
|
||||||
|
|
@ -1,10 +1,6 @@
|
||||||
/** Copyright Stewart Allen -- All Rights Reserved */
|
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||||
"use strict";
|
|
||||||
|
|
||||||
self.kiri = (self.kiri || {});
|
"use strict";
|
||||||
self.kiri.version = exports.VERSION;
|
|
||||||
self.kiri.license = exports.LICENSE;
|
|
||||||
self.kiri.copyright = exports.COPYRIGHT;
|
|
||||||
|
|
||||||
(function () {
|
(function () {
|
||||||
|
|
||||||
|
|
@ -43,8 +39,9 @@ self.kiri.copyright = exports.COPYRIGHT;
|
||||||
newWidget = kiri.newWidget,
|
newWidget = kiri.newWidget,
|
||||||
// ---------------
|
// ---------------
|
||||||
UI = {},
|
UI = {},
|
||||||
UC = MOTO.ui.prefix('kiri').inputAction(updateSettings).hideAction(updateDialogLeft),
|
UC = KIRI.ui.prefix('kiri').inputAction(updateSettings).hideAction(updateDialogLeft),
|
||||||
MODE = MODES.FDM,
|
MODE = MODES.FDM,
|
||||||
|
DRIVER = undefined,
|
||||||
onEvent = {},
|
onEvent = {},
|
||||||
currentPrint = null,
|
currentPrint = null,
|
||||||
selectedMeshes = [],
|
selectedMeshes = [],
|
||||||
|
|
@ -180,18 +177,17 @@ self.kiri.copyright = exports.COPYRIGHT;
|
||||||
SECURE
|
SECURE
|
||||||
},
|
},
|
||||||
var: {
|
var: {
|
||||||
layer_at: Infinity,
|
layer_lo: 0,
|
||||||
layer_max: 0,
|
layer_hi: 0,
|
||||||
layer_range: 0
|
layer_max: 0
|
||||||
},
|
},
|
||||||
device: {
|
device: {
|
||||||
get: currentDeviceName,
|
get: currentDeviceName,
|
||||||
set: undefined // set during init
|
set: undefined // set during init
|
||||||
},
|
},
|
||||||
dialog: {
|
dialog: {
|
||||||
show: showDialog,
|
show: showModal,
|
||||||
hide: hideDialog,
|
hide: hideModal
|
||||||
update: updateDialogLeft
|
|
||||||
},
|
},
|
||||||
help: {
|
help: {
|
||||||
show: showHelp,
|
show: showHelp,
|
||||||
|
|
@ -212,7 +208,7 @@ self.kiri.copyright = exports.COPYRIGHT;
|
||||||
clear: clearWidgetCache
|
clear: clearWidgetCache
|
||||||
},
|
},
|
||||||
hide: {
|
hide: {
|
||||||
import: function() { UI.import.style.display = 'none' }
|
import: function() { }
|
||||||
},
|
},
|
||||||
language: KIRI.lang,
|
language: KIRI.lang,
|
||||||
lists,
|
lists,
|
||||||
|
|
@ -262,6 +258,7 @@ self.kiri.copyright = exports.COPYRIGHT;
|
||||||
view: {
|
view: {
|
||||||
get: function() { return viewMode },
|
get: function() { return viewMode },
|
||||||
set: setViewMode,
|
set: setViewMode,
|
||||||
|
update_slider: updateSlider,
|
||||||
update_fields: updateFields,
|
update_fields: updateFields,
|
||||||
wireframe: toggleWireframe,
|
wireframe: toggleWireframe,
|
||||||
snapshot: null
|
snapshot: null
|
||||||
|
|
@ -466,8 +463,21 @@ self.kiri.copyright = exports.COPYRIGHT;
|
||||||
return Math.max(min,Math.min(max,v));
|
return Math.max(min,Math.min(max,v));
|
||||||
}
|
}
|
||||||
|
|
||||||
function setVisibleLayer(v) {
|
function updateSlider() {
|
||||||
showSlices(API.var.layer_at = bound(v, 0, API.var.layer_max));
|
API.event.emit("slider.set", {
|
||||||
|
start: 1 - (API.var.layer_hi / API.var.layer_max),
|
||||||
|
end: 1 - (API.var.layer_lo / API.var.layer_max)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function setVisibleLayer(h, l) {
|
||||||
|
h = h >= 0 ? h : API.var.layer_hi;
|
||||||
|
l = l >= 0 ? l : API.var.layer_lo;
|
||||||
|
API.var.layer_hi = bound(h, 0, API.var.layer_max);
|
||||||
|
API.var.layer_lo = bound(l, 0, h);
|
||||||
|
API.event.emit("slider.label");
|
||||||
|
updateSlider();
|
||||||
|
showSlices();
|
||||||
}
|
}
|
||||||
|
|
||||||
function meshArray() {
|
function meshArray() {
|
||||||
|
|
@ -494,9 +504,11 @@ self.kiri.copyright = exports.COPYRIGHT;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function forSelectedWidgets(f) {
|
function forSelectedWidgets(f,noauto) {
|
||||||
let m = selectedMeshes;
|
let m = selectedMeshes;
|
||||||
if (m.length === 0 && WIDGETS.length === 1) m = [ WIDGETS[0].mesh ];
|
if (m.length === 0 && WIDGETS.length === 1) {
|
||||||
|
m = noauto ? [] : [ WIDGETS[0].mesh ];
|
||||||
|
}
|
||||||
m.slice().forEach(function (mesh) { f(mesh.widget) });
|
m.slice().forEach(function (mesh) { f(mesh.widget) });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -520,16 +532,11 @@ self.kiri.copyright = exports.COPYRIGHT;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
max = Math.max(0, max - 1);
|
max = Math.max(0, max - 1);
|
||||||
API.var.layer_max = max;
|
API.var.layer_max = UI.sliderMax.innerText = max;
|
||||||
if (UI.layerID.convert() > max || API.var.layer_at > max) {
|
if (set || max < API.var.layer_hi) {
|
||||||
API.var.layer_at = max;
|
API.var.layer_hi = API.var.layer_max;
|
||||||
UI.layerID.value = max;
|
API.event.emit("slider.label");
|
||||||
UI.layerSlider.value = API.var.layer_max;
|
updateSlider();
|
||||||
}
|
|
||||||
UI.layerSlider.max = max;
|
|
||||||
if (set) {
|
|
||||||
API.var.layer_at = API.var.layer_max;
|
|
||||||
UI.layerSlider.value = API.var.layer_max;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -544,83 +551,67 @@ self.kiri.copyright = exports.COPYRIGHT;
|
||||||
return showing;
|
return showing;
|
||||||
}
|
}
|
||||||
|
|
||||||
function showSlice(index, range, layer) {
|
|
||||||
if (range) {
|
|
||||||
return index <= layer && index > layer-range;
|
|
||||||
} else {
|
|
||||||
return index <= layer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* hide or show slice-layers and their sub-elements
|
* hide or show slice-layers and their sub-elements
|
||||||
*
|
*
|
||||||
* @param {number} [layer]
|
* @param {number} [layer]
|
||||||
*/
|
*/
|
||||||
function showSlices(layer) {
|
function showSlices(layer) {
|
||||||
|
if (viewMode === VIEWS.ARRANGE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
showSlider();
|
||||||
|
|
||||||
if (typeof(layer) === 'string' || typeof(layer) === 'number') {
|
if (typeof(layer) === 'string' || typeof(layer) === 'number') {
|
||||||
layer = parseInt(layer);
|
layer = parseInt(layer);
|
||||||
} else {
|
} else {
|
||||||
layer = API.var.layer_at;
|
layer = API.var.layer_hi;
|
||||||
}
|
}
|
||||||
|
|
||||||
layer = bound(layer, 0, API.var.layer_max);
|
layer = bound(layer, 0, API.var.layer_max);
|
||||||
|
API.var.layer_hi = layer;
|
||||||
|
API.event.emit("slider.label");
|
||||||
|
|
||||||
UI.layerID.value = layer;
|
let print = UI.layerPrint.checked,
|
||||||
UI.layerSlider.value = layer;
|
moves = UI.layerMoves.checked,
|
||||||
|
cam = MODE === MODES.CAM,
|
||||||
|
hi = cam ? API.var.layer_max - API.var.layer_lo : API.var.layer_hi,
|
||||||
|
lo = cam ? API.var.layer_max - API.var.layer_hi : API.var.layer_lo;
|
||||||
|
|
||||||
let j,
|
updateSlider();
|
||||||
slice,
|
|
||||||
slices,
|
|
||||||
layers,
|
|
||||||
range = UI.layerRange.checked ? UI.layerSpan.convert() || 1 : 0,
|
|
||||||
print = UI.layerPrint.checked,
|
|
||||||
moves = UI.layerMoves.checked;
|
|
||||||
|
|
||||||
if (MODE === MODES.CAM && API.var.layer_range !== range && range && layer === API.var.layer_max) {
|
|
||||||
layer = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
API.var.layer_range = range;
|
|
||||||
API.var.layer_at = layer;
|
|
||||||
|
|
||||||
forAllWidgets(function(widget) {
|
forAllWidgets(function(widget) {
|
||||||
if (print) return widget.hideSlices();
|
if (print) return widget.hideSlices();
|
||||||
|
|
||||||
slices = widget.slices;
|
let slices = widget.slices;
|
||||||
if (!slices) return;
|
if (!slices) return;
|
||||||
|
|
||||||
for (j = 0; j < slices.length; j++) {
|
for (let j = 0; j < slices.length; j++) {
|
||||||
slice = slices[j];
|
let slice = slices[j];
|
||||||
slice.view.visible = showSlice(j, range, layer);
|
slice.view.visible = j >= lo && j <= hi;
|
||||||
layers = slice.layers;
|
let layers = slice.layers;
|
||||||
layers.outline.setVisible(
|
layers.outline.setVisible(cam ?
|
||||||
MODE === MODES.CAM ?
|
UI.layerOutline.checked :
|
||||||
UI.layerOutline.checked && LOCAL :
|
|
||||||
UI.layerOutline.checked
|
UI.layerOutline.checked
|
||||||
);
|
);
|
||||||
layers.trace.setVisible(
|
layers.trace.setVisible(cam ?
|
||||||
MODE === MODES.CAM ?
|
|
||||||
UI.layerRough.checked :
|
UI.layerRough.checked :
|
||||||
UI.layerTrace.checked
|
UI.layerTrace.checked
|
||||||
);
|
);
|
||||||
layers.bridge.setVisible(
|
layers.bridge.setVisible(cam ?
|
||||||
MODE === MODES.CAM ?
|
|
||||||
UI.layerFinishX.checked :
|
UI.layerFinishX.checked :
|
||||||
UI.layerDelta.checked
|
UI.layerDelta.checked
|
||||||
);
|
);
|
||||||
layers.flat.setVisible(
|
layers.flat.setVisible(cam ?
|
||||||
MODE === MODES.CAM ?
|
|
||||||
UI.layerFinishY.checked :
|
UI.layerFinishY.checked :
|
||||||
UI.layerDelta.checked
|
UI.layerDelta.checked
|
||||||
);
|
);
|
||||||
layers.solid.setVisible(
|
layers.solid.setVisible(cam ?
|
||||||
MODE === MODES.CAM ?
|
|
||||||
UI.layerFinish.checked :
|
UI.layerFinish.checked :
|
||||||
UI.layerSolid.checked
|
UI.layerSolid.checked
|
||||||
);
|
);
|
||||||
layers.fill.setVisible(
|
layers.fill.setVisible(cam ?
|
||||||
MODE === MODES.CAM ?
|
|
||||||
UI.layerFacing.checked :
|
UI.layerFacing.checked :
|
||||||
UI.layerFill.checked
|
UI.layerFill.checked
|
||||||
);
|
);
|
||||||
|
|
@ -631,10 +622,11 @@ self.kiri.copyright = exports.COPYRIGHT;
|
||||||
|
|
||||||
if (currentPrint) {
|
if (currentPrint) {
|
||||||
let len = currentPrint.getLayerCount();
|
let len = currentPrint.getLayerCount();
|
||||||
for (j = 0; j < len; j++) {
|
for (let j = 0; j < len; j++) {
|
||||||
currentPrint.showLayer(j, print && showSlice(j, range, layer), moves);
|
currentPrint.showLayer(j, print && j >= lo && j <= hi, moves);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UI.layerPrint.parentNode.style.display = currentPrint ? '' : 'none';
|
UI.layerPrint.parentNode.style.display = currentPrint ? '' : 'none';
|
||||||
UI.layerMoves.parentNode.style.display = currentPrint ? '' : 'none';
|
UI.layerMoves.parentNode.style.display = currentPrint ? '' : 'none';
|
||||||
|
|
||||||
|
|
@ -671,6 +663,7 @@ self.kiri.copyright = exports.COPYRIGHT;
|
||||||
|
|
||||||
function preparePrint(callback) {
|
function preparePrint(callback) {
|
||||||
if (viewMode === VIEWS.PREVIEW) return;
|
if (viewMode === VIEWS.PREVIEW) return;
|
||||||
|
hideSlider(true);
|
||||||
|
|
||||||
// kick off slicing it hasn't been done already
|
// kick off slicing it hasn't been done already
|
||||||
for (let i=0; i < WIDGETS.length; i++) {
|
for (let i=0; i < WIDGETS.length; i++) {
|
||||||
|
|
@ -746,6 +739,18 @@ self.kiri.copyright = exports.COPYRIGHT;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function showSlider() {
|
||||||
|
UI.layers.style.display = 'flex';
|
||||||
|
UI.slider.style.display = 'flex';
|
||||||
|
UI.setMenu.style.display = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideSlider(andmenu) {
|
||||||
|
UI.layers.style.display = 'none';
|
||||||
|
UI.slider.style.display = 'none';
|
||||||
|
UI.setMenu.style.display = andmenu ? 'none' : 'flex';
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* incrementally slice all meshes then incrementally update them
|
* incrementally slice all meshes then incrementally update them
|
||||||
*
|
*
|
||||||
|
|
@ -757,7 +762,11 @@ self.kiri.copyright = exports.COPYRIGHT;
|
||||||
API.view.snapshot = snap.substring(snap.indexOf(",")+1);
|
API.view.snapshot = snap.substring(snap.indexOf(",")+1);
|
||||||
KIRI.work.snap(API.view.snapshot);
|
KIRI.work.snap(API.view.snapshot);
|
||||||
}
|
}
|
||||||
|
if (MODE === MODES.SLA && !callback) {
|
||||||
|
callback = preparePrint;
|
||||||
|
}
|
||||||
|
|
||||||
|
hideSlider(true);
|
||||||
clearPrint();
|
clearPrint();
|
||||||
platform.deselect();
|
platform.deselect();
|
||||||
setViewMode(VIEWS.SLICE);
|
setViewMode(VIEWS.SLICE);
|
||||||
|
|
@ -766,7 +775,7 @@ self.kiri.copyright = exports.COPYRIGHT;
|
||||||
let firstMesh = true,
|
let firstMesh = true,
|
||||||
countdown = WIDGETS.length,
|
countdown = WIDGETS.length,
|
||||||
preserveMax = API.var.layer_max,
|
preserveMax = API.var.layer_max,
|
||||||
preserveLayer = API.var.layer_at,
|
preserveLayer = API.var.layer_hi,
|
||||||
totalProgress,
|
totalProgress,
|
||||||
track = {},
|
track = {},
|
||||||
now = UTIL.time();
|
now = UTIL.time();
|
||||||
|
|
@ -789,7 +798,7 @@ self.kiri.copyright = exports.COPYRIGHT;
|
||||||
widget.slice(settings, function(sliced, error) {
|
widget.slice(settings, function(sliced, error) {
|
||||||
let mark = UTIL.time();
|
let mark = UTIL.time();
|
||||||
// on done
|
// on done
|
||||||
widget.render(renderMode, MODE === MODES.CAM);
|
widget.render();
|
||||||
// clear wireframe
|
// clear wireframe
|
||||||
widget.setWireframe(false, color.wireframe, color.wireframe_opacity);
|
widget.setWireframe(false, color.wireframe, color.wireframe_opacity);
|
||||||
widget.setOpacity(settings.mode === 'CAM' ? color.cam_sliced_opacity : color.sliced_opacity);
|
widget.setOpacity(settings.mode === 'CAM' ? color.cam_sliced_opacity : color.sliced_opacity);
|
||||||
|
|
@ -816,8 +825,6 @@ self.kiri.copyright = exports.COPYRIGHT;
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// update slider window
|
|
||||||
API.dialog.update();
|
|
||||||
// handle slicing errors
|
// handle slicing errors
|
||||||
if (error && !errored) {
|
if (error && !errored) {
|
||||||
errored = true;
|
errored = true;
|
||||||
|
|
@ -880,7 +887,7 @@ self.kiri.copyright = exports.COPYRIGHT;
|
||||||
|
|
||||||
function setOpacity(value) {
|
function setOpacity(value) {
|
||||||
forAllWidgets(function (w) { w.setOpacity(value) });
|
forAllWidgets(function (w) { w.setOpacity(value) });
|
||||||
UI.modelOpacity.value = value * 100;
|
// UI.modelOpacity.value = value * 100;
|
||||||
SPACE.update();
|
SPACE.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -998,7 +1005,9 @@ self.kiri.copyright = exports.COPYRIGHT;
|
||||||
}
|
}
|
||||||
|
|
||||||
function platformSelect(widget, shift) {
|
function platformSelect(widget, shift) {
|
||||||
if (viewMode !== VIEWS.ARRANGE) return;
|
if (viewMode !== VIEWS.ARRANGE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
let mesh = widget.mesh,
|
let mesh = widget.mesh,
|
||||||
sel = (selectedMeshes.indexOf(mesh) >= 0);
|
sel = (selectedMeshes.indexOf(mesh) >= 0);
|
||||||
if (sel) {
|
if (sel) {
|
||||||
|
|
@ -1026,19 +1035,24 @@ self.kiri.copyright = exports.COPYRIGHT;
|
||||||
}
|
}
|
||||||
|
|
||||||
function platformUpdateSelected() {
|
function platformUpdateSelected() {
|
||||||
UI.selection.style.display = platform.selected_count() ? 'inline' : 'none';
|
|
||||||
$('ext-sel').style.display = (MODE === MODES.FDM) ? 'inline-block' : 'none';
|
|
||||||
let extruders = settings.device.extruders;
|
let extruders = settings.device.extruders;
|
||||||
|
let menu_show = platform.selected_count() ? 'flex': '';
|
||||||
|
let ext_show = platform.selected_count() && MODE === 'FDM' ? 'flex': '';
|
||||||
|
UI.scale.style.display = menu_show;
|
||||||
|
UI.rotate.style.display = menu_show;
|
||||||
|
UI.nozzle.style.display = extruders && extruders.length > 1 ? menu_show : '';
|
||||||
|
UI.menusep.style.display = menu_show;
|
||||||
if (extruders) {
|
if (extruders) {
|
||||||
for (let i=0; i<extruders.length; i++) {
|
for (let i=0; i<extruders.length; i++) {
|
||||||
let b = $(`sel-ext-${i}`);
|
let b = $(`sel-ext-${i}`);
|
||||||
if (b) b.classList.remove('buton');
|
if (b) b.classList.remove('pop-sel');
|
||||||
}
|
}
|
||||||
forSelectedWidgets(w => {
|
forSelectedWidgets(w => {
|
||||||
|
w.setColor(color.selected, settings);
|
||||||
let ext = (settings.widget[w.id] || {}).extruder || 0;
|
let ext = (settings.widget[w.id] || {}).extruder || 0;
|
||||||
let b = $(`sel-ext-${ext}`);
|
let b = $(`sel-ext-${ext}`);
|
||||||
if (b) b.classList.add('buton');
|
if (b) b.classList.add('pop-sel');
|
||||||
});
|
}, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1233,7 +1247,7 @@ self.kiri.copyright = exports.COPYRIGHT;
|
||||||
camTopZ = topZ;
|
camTopZ = topZ;
|
||||||
// create/inject cam stock if stock size other than default
|
// create/inject cam stock if stock size other than default
|
||||||
if (MODE === MODES.CAM && stockSet && WIDGETS.length) {
|
if (MODE === MODES.CAM && stockSet && WIDGETS.length) {
|
||||||
UI.stock.style.display = offset ? 'inline-block' : 'none';
|
// UI.stock.style.display = offset ? 'inline-block' : 'none';
|
||||||
let csx = sd.camStockX * scale;
|
let csx = sd.camStockX * scale;
|
||||||
let csy = sd.camStockY * scale;
|
let csy = sd.camStockY * scale;
|
||||||
let csz = sd.camStockZ * scale;
|
let csz = sd.camStockZ * scale;
|
||||||
|
|
@ -1261,9 +1275,9 @@ self.kiri.copyright = exports.COPYRIGHT;
|
||||||
csz += max.z - min.z;
|
csz += max.z - min.z;
|
||||||
csox = min.x + ((max.x - min.x) / 2);
|
csox = min.x + ((max.x - min.x) / 2);
|
||||||
csoy = min.y + ((max.y - min.y) / 2);
|
csoy = min.y + ((max.y - min.y) / 2);
|
||||||
$('stock-width').innerText = (csx/scale).toFixed(2);
|
// $('stock-width').innerText = (csx/scale).toFixed(2);
|
||||||
$('stock-depth').innerText = (csy/scale).toFixed(2);
|
// $('stock-depth').innerText = (csy/scale).toFixed(2);
|
||||||
$('stock-height').innerText = (csz/scale).toFixed(2);
|
// $('stock-height').innerText = (csz/scale).toFixed(2);
|
||||||
}
|
}
|
||||||
if (!camStock) {
|
if (!camStock) {
|
||||||
let geo = new THREE.BoxGeometry(1, 1, 1);
|
let geo = new THREE.BoxGeometry(1, 1, 1);
|
||||||
|
|
@ -1286,7 +1300,7 @@ self.kiri.copyright = exports.COPYRIGHT;
|
||||||
camStock.material.visible = settings.mode === 'CAM';
|
camStock.material.visible = settings.mode === 'CAM';
|
||||||
camTopZ = csz;
|
camTopZ = csz;
|
||||||
} else if (camStock) {
|
} else if (camStock) {
|
||||||
UI.stock.style.display = 'none';
|
// UI.stock.style.display = 'none';
|
||||||
SPACE.platform.remove(camStock);
|
SPACE.platform.remove(camStock);
|
||||||
camStock = null;
|
camStock = null;
|
||||||
camTopZ = topZ;
|
camTopZ = topZ;
|
||||||
|
|
@ -1435,6 +1449,8 @@ self.kiri.copyright = exports.COPYRIGHT;
|
||||||
}
|
}
|
||||||
API.conf.save();
|
API.conf.save();
|
||||||
platform.update_stock();
|
platform.update_stock();
|
||||||
|
$('mode-device').innerText = settings.device.deviceName;
|
||||||
|
$('mode-profile').innerText = settings.process.processName;
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveSettings() {
|
function saveSettings() {
|
||||||
|
|
@ -1626,36 +1642,53 @@ self.kiri.copyright = exports.COPYRIGHT;
|
||||||
}
|
}
|
||||||
|
|
||||||
function modalShowing() {
|
function modalShowing() {
|
||||||
let showing = $('modal').style.display !== 'none';
|
return UI.modal.style.display === 'flex';
|
||||||
return showing || UC.isPopped();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function showModal(which) {
|
function showModal(which) {
|
||||||
UI.modal.style.display = 'block';
|
let mod = UI.modal,
|
||||||
["print","help","local"].forEach(function(modal) {
|
style = mod.style,
|
||||||
UI[modal].style.display = (modal === which ? 'block' : 'none');
|
visible = modalShowing(),
|
||||||
|
info = { pct: 0 };
|
||||||
|
|
||||||
|
["help","setup","tools","prefs","saves","files","print","local"].forEach(function(name) {
|
||||||
|
UI[name].style.display = name === which ? 'flex' : '';
|
||||||
});
|
});
|
||||||
if (which) API.event.emit('modal.show', which);
|
|
||||||
|
function ondone() {
|
||||||
|
API.event.emit('modal.show', which);
|
||||||
}
|
}
|
||||||
|
|
||||||
function hideDialog() {
|
if (visible) {
|
||||||
showDialog(null);
|
return ondone();
|
||||||
}
|
}
|
||||||
|
|
||||||
function showDialog(which, force) {
|
style.height = '0';
|
||||||
if (UC.isPopped()) {
|
style.display = 'flex';
|
||||||
UC.hidePop();
|
|
||||||
|
new TWEEN.Tween(info).
|
||||||
|
easing(TWEEN.Easing.Quadratic.InOut).
|
||||||
|
to({ pct: 100 }, 100).
|
||||||
|
onUpdate(() => { style.height = `${info.pct}%` }).
|
||||||
|
onComplete(ondone).
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideModal() {
|
||||||
|
if (!modalShowing()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
["catalog","devices","tools","settings"].forEach(function(dialog) {
|
let mod = UI.modal, style = mod.style, info={pct:100};
|
||||||
let style = UI[dialog].style;
|
new TWEEN.Tween(info).
|
||||||
style.display = (dialog === which && (force || style.display !== 'flex') ? 'flex' : 'none');
|
easing(TWEEN.Easing.Quadratic.InOut).
|
||||||
});
|
to({pct:0}, 100).
|
||||||
if (which) API.event.emit('dialog.show', which);
|
onUpdate(() => { style.height = `${info.pct}%` }).
|
||||||
|
onComplete(() => { style.display = '' }).
|
||||||
|
start();
|
||||||
}
|
}
|
||||||
|
|
||||||
function showCatalog() {
|
function showCatalog() {
|
||||||
showDialog("catalog");
|
showModal("files");
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSettings() {
|
function getSettings() {
|
||||||
|
|
@ -1691,7 +1724,6 @@ self.kiri.copyright = exports.COPYRIGHT;
|
||||||
let mode = getMode(),
|
let mode = getMode(),
|
||||||
name = e ? e.target.getAttribute("load") : named || settings.cproc[mode],
|
name = e ? e.target.getAttribute("load") : named || settings.cproc[mode],
|
||||||
load = settings.sproc[mode][name];
|
load = settings.sproc[mode][name];
|
||||||
|
|
||||||
if (!load) return;
|
if (!load) return;
|
||||||
|
|
||||||
settings.process = clone(load);
|
settings.process = clone(load);
|
||||||
|
|
@ -1701,20 +1733,11 @@ self.kiri.copyright = exports.COPYRIGHT;
|
||||||
// associate named process with the current device
|
// associate named process with the current device
|
||||||
settings.devproc[currentDeviceName()] = name;
|
settings.devproc[currentDeviceName()] = name;
|
||||||
|
|
||||||
// update selection display
|
|
||||||
$('selected-mode').innerHTML = API.mode.get();
|
|
||||||
$('selected-device').innerHTML = API.device.get();
|
|
||||||
$('selected-process').innerHTML = name;
|
|
||||||
|
|
||||||
// FDM process settings overridden by device
|
// FDM process settings overridden by device
|
||||||
if (mode == "FDM") {
|
if (mode == "FDM") {
|
||||||
settings.process.outputOriginCenter = (settings.device.originCenter || false);
|
settings.process.outputOriginCenter = (settings.device.originCenter || false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!named) {
|
|
||||||
hideDialog();
|
|
||||||
}
|
|
||||||
|
|
||||||
updateFields();
|
updateFields();
|
||||||
API.conf.update();
|
API.conf.update();
|
||||||
if (e) triggerSettingsEvent();
|
if (e) triggerSettingsEvent();
|
||||||
|
|
@ -1742,7 +1765,10 @@ self.kiri.copyright = exports.COPYRIGHT;
|
||||||
name = sk;
|
name = sk;
|
||||||
|
|
||||||
load.setAttribute('load', sk);
|
load.setAttribute('load', sk);
|
||||||
load.onclick = API.conf.load;
|
load.onclick = (ev) => {
|
||||||
|
API.conf.load(undefined, sk);
|
||||||
|
updateSettingsList();
|
||||||
|
}
|
||||||
load.appendChild(DOC.createTextNode(sk));
|
load.appendChild(DOC.createTextNode(sk));
|
||||||
if (sk == settings.process.processName) {
|
if (sk == settings.process.processName) {
|
||||||
load.setAttribute('class', 'selected')
|
load.setAttribute('class', 'selected')
|
||||||
|
|
@ -1764,15 +1790,15 @@ self.kiri.copyright = exports.COPYRIGHT;
|
||||||
row.appendChild(del);
|
row.appendChild(del);
|
||||||
table.appendChild(row);
|
table.appendChild(row);
|
||||||
});
|
});
|
||||||
API.dialog.update();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function showSettings() {
|
function showSettings() {
|
||||||
updateSettingsList();
|
updateSettingsList();
|
||||||
showDialog("settings");
|
showModal("saves");
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateDialogLeft() {
|
function updateDialogLeft() {
|
||||||
|
return console.log('TODO updateDialogLeft');
|
||||||
let left = UI.ctrlLeft.getBoundingClientRect();
|
let left = UI.ctrlLeft.getBoundingClientRect();
|
||||||
let right = UI.ctrlRight.getBoundingClientRect();
|
let right = UI.ctrlRight.getBoundingClientRect();
|
||||||
UI.catalog.style.left = (left.width + 5) + 'px';
|
UI.catalog.style.left = (left.width + 5) + 'px';
|
||||||
|
|
@ -1781,35 +1807,31 @@ self.kiri.copyright = exports.COPYRIGHT;
|
||||||
UI.settings.style.right = (right.width + 5) + 'px';
|
UI.settings.style.right = (right.width + 5) + 'px';
|
||||||
}
|
}
|
||||||
|
|
||||||
function hideModal() {
|
|
||||||
UI.modal.style.display = 'none';
|
|
||||||
}
|
|
||||||
|
|
||||||
function showHelp() {
|
function showHelp() {
|
||||||
showHelpFile(`/kiri/lang/${KIRI.lang.get()}-help.html?${KIRI.version}`);
|
showHelpFile(`/kiri/lang/${KIRI.lang.get()}-help.html?${KIRI.version}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
function showHelpFile(local) {
|
function showHelpFile(local) {
|
||||||
hideDialog();
|
|
||||||
if (!local) {
|
if (!local) {
|
||||||
WIN.open("//wiki.grid.space/wiki/Kiri:Moto", "_help");
|
WIN.open("//wiki.grid.space/wiki/Kiri:Moto", "_help");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ajax(local, function(html) {
|
ajax(local, function(html) {
|
||||||
UI.help.innerHTML = html;
|
UI.help.innerHTML = html;
|
||||||
try { $('help-close').onclick = hideModal; } catch (e) { console.log(e, html) }
|
try {
|
||||||
try { $('kiri-version').innerHTML = `<i>${LANG.version} ${KIRI.version}</i>`; } catch (e) { }
|
$('kiri-version').innerHTML = `${LANG.version} ${KIRI.version}`;
|
||||||
|
} catch (e) { }
|
||||||
showModal('help');
|
showModal('help');
|
||||||
});
|
});
|
||||||
API.event.emit('help.show', local);
|
API.event.emit('help.show', local);
|
||||||
}
|
}
|
||||||
|
|
||||||
function showLocal() {
|
function showLocal() {
|
||||||
$('local-close').onclick = hideModal;
|
|
||||||
showModal('local');
|
showModal('local');
|
||||||
fetch("/api/grid_local")
|
fetch("/api/grid_local")
|
||||||
.then(r => r.json())
|
.then(r => r.json())
|
||||||
.then(j => {
|
.then(j => {
|
||||||
|
let devc = 0;
|
||||||
let bind = [];
|
let bind = [];
|
||||||
let html = ['<table>'];
|
let html = ['<table>'];
|
||||||
html.push(`<thead><tr><th>device</th><th>type</th><th>status</th><th></th></tr></thead>`);
|
html.push(`<thead><tr><th>device</th><th>type</th><th>status</th><th></th></tr></thead>`);
|
||||||
|
|
@ -1823,10 +1845,15 @@ self.kiri.copyright = exports.COPYRIGHT;
|
||||||
html.push(`<td>${r.state}</td>`);
|
html.push(`<td>${r.state}</td>`);
|
||||||
html.push(`<td><button id="${r.device.uuid}">admin</button></td>`);
|
html.push(`<td><button id="${r.device.uuid}">admin</button></td>`);
|
||||||
html.push(`</tr>`);
|
html.push(`</tr>`);
|
||||||
|
devc++;
|
||||||
}
|
}
|
||||||
html.push(`</tbody>`);
|
html.push(`</tbody>`);
|
||||||
html.push(`</table>`);
|
html.push(`</table>`);
|
||||||
$('local-dev').innerHTML = html.join('');
|
if (devc) {
|
||||||
|
$('mod-local').innerHTML = html.join('');
|
||||||
|
} else {
|
||||||
|
$('mod-local').innerHTML = `<br><b>no local devices</b>`;
|
||||||
|
}
|
||||||
bind.forEach(rec => {
|
bind.forEach(rec => {
|
||||||
$(rec.uuid).onclick = () => {
|
$(rec.uuid).onclick = () => {
|
||||||
window.open(`http://${rec.host}:${rec.port||4080}/`);
|
window.open(`http://${rec.host}:${rec.port||4080}/`);
|
||||||
|
|
@ -1836,7 +1863,7 @@ self.kiri.copyright = exports.COPYRIGHT;
|
||||||
}
|
}
|
||||||
|
|
||||||
function setFocus(el) {
|
function setFocus(el) {
|
||||||
el = [ el || UI.load, UI.import, UI.ctrlLeft, UI.container, UI.assets, UI.control, UI.modeFDM, UI.reverseZoom, UI.modelOpacity, DOC.body ];
|
el = [ el || UI.focuser, UI.load, UI.sizeX, DOC.body ];
|
||||||
for (let es, i=0; i<el.length; i++) {
|
for (let es, i=0; i<el.length; i++) {
|
||||||
es = el[i];
|
es = el[i];
|
||||||
es.focus();
|
es.focus();
|
||||||
|
|
@ -1853,20 +1880,18 @@ self.kiri.copyright = exports.COPYRIGHT;
|
||||||
updateSelectedInfo();
|
updateSelectedInfo();
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case VIEWS.ARRANGE:
|
case VIEWS.ARRANGE:
|
||||||
|
$('lt-back').style.display = '';
|
||||||
KIRI.work.clear();
|
KIRI.work.clear();
|
||||||
|
hideSlider();
|
||||||
clearWidgetCache();
|
clearWidgetCache();
|
||||||
showLayerView(false);
|
|
||||||
updateSliderMax();
|
updateSliderMax();
|
||||||
showModeActive(UI.modeArrange);
|
|
||||||
break;
|
break;
|
||||||
case VIEWS.SLICE:
|
case VIEWS.SLICE:
|
||||||
showLayerView(true);
|
$('lt-back').style.display = 'flex';
|
||||||
updateSliderMax();
|
updateSliderMax();
|
||||||
showModeActive(UI.modeSlice);
|
|
||||||
break;
|
break;
|
||||||
case VIEWS.PREVIEW:
|
case VIEWS.PREVIEW:
|
||||||
showLayerView(true);
|
$('lt-back').style.display = 'flex';
|
||||||
showModeActive(UI.modePreview);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
DBUG.log("invalid view mode: "+mode);
|
DBUG.log("invalid view mode: "+mode);
|
||||||
|
|
@ -1875,22 +1900,10 @@ self.kiri.copyright = exports.COPYRIGHT;
|
||||||
DOC.activeElement.blur();
|
DOC.activeElement.blur();
|
||||||
}
|
}
|
||||||
|
|
||||||
function showModeActive(el) {
|
|
||||||
[ UI.modeArrange, UI.modeSlice, UI.modePreview, UI.modeExport ].forEach(function(b) {
|
|
||||||
if (b === el) {
|
|
||||||
b.classList.add('buton');
|
|
||||||
} else {
|
|
||||||
b.classList.remove('buton');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function showLayerView(bool) {
|
|
||||||
UI.layerView.style.display = bool ? 'flex' : 'none';
|
|
||||||
}
|
|
||||||
|
|
||||||
function setExpert(bool) {
|
function setExpert(bool) {
|
||||||
UC.setExpert(UI.expert.checked = control.expert = bool);
|
UC.setExpert(UI.expert.checked = settings.controller.expert = bool);
|
||||||
|
$('lt-sep-help').style.display = bool ? 'none' : '';
|
||||||
|
$('set-help').style.display = bool ? 'none' : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
function getMode() {
|
function getMode() {
|
||||||
|
|
@ -1906,51 +1919,54 @@ self.kiri.copyright = exports.COPYRIGHT;
|
||||||
}
|
}
|
||||||
|
|
||||||
function setMode(mode, lock, then) {
|
function setMode(mode, lock, then) {
|
||||||
hideModal();
|
|
||||||
hideDialog();
|
|
||||||
if (!MODES[mode]) {
|
if (!MODES[mode]) {
|
||||||
DBUG.log("invalid mode: "+mode);
|
DBUG.log("invalid mode: "+mode);
|
||||||
mode = 'FDM';
|
mode = 'FDM';
|
||||||
}
|
}
|
||||||
|
// change mode constants
|
||||||
settings.mode = mode;
|
settings.mode = mode;
|
||||||
|
MODE = MODES[mode];
|
||||||
|
DRIVER = KIRI.driver[mode];
|
||||||
|
// update mode display
|
||||||
|
$('app-mode-name').innerHTML = mode;
|
||||||
|
// highlight relevant device mode button
|
||||||
|
["fdm","sla","cam","laser"].forEach(dev => {
|
||||||
|
let cl = $(`mode-${dev}`).classList;
|
||||||
|
if (dev === mode.toLowerCase()) {
|
||||||
|
cl.add("dev-sel");
|
||||||
|
} else {
|
||||||
|
cl.remove("dev-sel");
|
||||||
|
}
|
||||||
|
});
|
||||||
// restore cached device profile for this mode
|
// restore cached device profile for this mode
|
||||||
if (settings.cdev[mode]) {
|
if (settings.cdev[mode]) {
|
||||||
settings.device = clone(settings.cdev[mode]);
|
settings.device = clone(settings.cdev[mode]);
|
||||||
API.event.emit('device.set', currentDeviceName());
|
API.event.emit('device.set', currentDeviceName());
|
||||||
}
|
}
|
||||||
if (MODE === MODES.CAM) {
|
// really belongs in CAM driver (lots of work / abstraction needed)
|
||||||
SPACE.platform.setColor(0xeeeeee);
|
|
||||||
} else {
|
|
||||||
SPACE.platform.setColor(0xcccccc);
|
|
||||||
}
|
|
||||||
MODE = MODES[mode];
|
|
||||||
// updates right-hand menu by enabling/disabling fields
|
|
||||||
setViewMode(VIEWS.ARRANGE);
|
|
||||||
UC.setMode(MODE);
|
|
||||||
API.conf.load();
|
|
||||||
API.conf.save();
|
|
||||||
clearWidgetCache();
|
|
||||||
SPACE.update();
|
|
||||||
UI.modeFDM.setAttribute('class', MODE === MODES.FDM ? 'buton' : '');
|
|
||||||
UI.modeSLA.setAttribute('class', MODE === MODES.SLA ? 'buton' : '');
|
|
||||||
UI.modeCAM.setAttribute('class', MODE === MODES.CAM ? 'buton' : '');
|
|
||||||
UI.modeLASER.setAttribute('class', MODE === MODES.LASER ? 'buton' : '');
|
|
||||||
UI.mode.style.display = lock ? 'none' : '';
|
|
||||||
UI.modeTable.style.display = lock ? 'none' : '';
|
|
||||||
UI.modelOpacity.style.display = MODE === MODES.SLA ? 'none' : '';
|
|
||||||
UI.modePreview.style.display = MODE === MODES.SLA ? 'none' : '';
|
|
||||||
if (camStock) {
|
if (camStock) {
|
||||||
camStock.material.visible = settings.mode === 'CAM';
|
camStock.material.visible = settings.mode === 'CAM';
|
||||||
}
|
}
|
||||||
API.space.restore(null, true);
|
// updates right-hand menu by enabling/disabling fields
|
||||||
if (then) then();
|
setViewMode(VIEWS.ARRANGE);
|
||||||
|
UC.setMode(MODE);
|
||||||
|
// sanitize and persist settings
|
||||||
|
API.conf.load();
|
||||||
|
API.conf.save();
|
||||||
|
// other housekeeping
|
||||||
|
clearWidgetCache();
|
||||||
triggerSettingsEvent();
|
triggerSettingsEvent();
|
||||||
platformUpdateSelected();
|
platformUpdateSelected();
|
||||||
updateFields();
|
updateFields();
|
||||||
if (settings.device.new) {
|
// because device dialog, if showing, needs to be updated
|
||||||
|
if (modalShowing()) {
|
||||||
API.show.devices();
|
API.show.devices();
|
||||||
}
|
}
|
||||||
|
API.space.restore(null, true);
|
||||||
API.event.emit("mode.set", mode);
|
API.event.emit("mode.set", mode);
|
||||||
|
if (then) {
|
||||||
|
then();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function currentDeviceName() {
|
function currentDeviceName() {
|
||||||
|
|
@ -1958,8 +1974,8 @@ self.kiri.copyright = exports.COPYRIGHT;
|
||||||
}
|
}
|
||||||
|
|
||||||
function setControlsVisible(show) {
|
function setControlsVisible(show) {
|
||||||
UI.ctrlLeft.style.display = show ? 'block' : 'none';
|
$('mid-lcol').style.display = show ? 'flex' : 'none';
|
||||||
UI.ctrlRight.style.display = show ? 'block' : 'none';
|
$('mid-rcol').style.display = show ? 'flex' : 'none';
|
||||||
}
|
}
|
||||||
|
|
||||||
// prevent safari from exiting full screen mode
|
// prevent safari from exiting full screen mode
|
||||||
|
|
@ -1,14 +1,12 @@
|
||||||
/** Copyright 2014-2019 Stewart Allen -- All Rights Reserved */
|
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
let gs_kiri_print = exports;
|
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
if (!self.kiri) self.kiri = {};
|
if (self.kiri.newPrint) return;
|
||||||
|
|
||||||
let KIRI = self.kiri,
|
const KIRI = self.kiri,
|
||||||
DRIVERS = KIRI.driver,
|
DRIVERS = KIRI.driver,
|
||||||
LASER = DRIVERS.LASER,
|
LASER = DRIVERS.LASER,
|
||||||
CAM = DRIVERS.CAM,
|
CAM = DRIVERS.CAM,
|
||||||
|
|
@ -22,8 +20,9 @@ let gs_kiri_print = exports;
|
||||||
PI = Math.PI,
|
PI = Math.PI,
|
||||||
PRO = Print.prototype,
|
PRO = Print.prototype,
|
||||||
Polygon = BASE.Polygon,
|
Polygon = BASE.Polygon,
|
||||||
newPoint = BASE.newPoint,
|
newPoint = BASE.newPoint;
|
||||||
lastPoint = null,
|
|
||||||
|
let lastPoint = null,
|
||||||
lastEmit = null;
|
lastEmit = null;
|
||||||
|
|
||||||
KIRI.newPrint = function(settings, widgets, id) {
|
KIRI.newPrint = function(settings, widgets, id) {
|
||||||
|
|
@ -51,6 +50,8 @@ let gs_kiri_print = exports;
|
||||||
this.distance = 0;
|
this.distance = 0;
|
||||||
this.bounds = null;
|
this.bounds = null;
|
||||||
this.imported = null;
|
this.imported = null;
|
||||||
|
|
||||||
|
this.hsv2rgb = hsv2rgb;
|
||||||
}
|
}
|
||||||
|
|
||||||
PRO.addOutput = addOutput;
|
PRO.addOutput = addOutput;
|
||||||
|
|
@ -228,6 +229,8 @@ let gs_kiri_print = exports;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// executed from kiri-worker.js
|
// executed from kiri-worker.js
|
||||||
|
// uses encodeOutput in this class to produce scope.output above
|
||||||
|
// this encoding could be made vastly more efficient
|
||||||
let driver = KIRI.driver[mode];
|
let driver = KIRI.driver[mode];
|
||||||
if (driver) driver.printSetup(scope, onupdate);
|
if (driver) driver.printSetup(scope, onupdate);
|
||||||
else console.log({missing_print_driver: mode});
|
else console.log({missing_print_driver: mode});
|
||||||
|
|
@ -317,7 +320,8 @@ let gs_kiri_print = exports;
|
||||||
emit: out.emit,
|
emit: out.emit,
|
||||||
speed: out.speed * 60,
|
speed: out.speed * 60,
|
||||||
retract: out.retract,
|
retract: out.retract,
|
||||||
point: {x: out.point.x, y: out.point.y, z: out.point.z}
|
point: {x: out.point.x, y: out.point.y, z: out.point.z},
|
||||||
|
tool: out.tool
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -327,25 +331,17 @@ let gs_kiri_print = exports;
|
||||||
};
|
};
|
||||||
|
|
||||||
PRO.render = function() {
|
PRO.render = function() {
|
||||||
let scope = this,
|
let settings = this.settings,
|
||||||
settings = scope.settings,
|
|
||||||
process = settings.process,
|
|
||||||
origin = settings.origin,
|
origin = settings.origin,
|
||||||
mode = settings.mode,
|
mode = settings.mode,
|
||||||
|
tools = [],
|
||||||
driver = KIRI.driver[mode];
|
driver = KIRI.driver[mode];
|
||||||
|
|
||||||
switch (mode) {
|
if (mode === 'FDM') {
|
||||||
case 'SLA':
|
tools = settings.device.extruders || [];
|
||||||
driver.printRender(scope);
|
|
||||||
break;
|
|
||||||
case 'CAM':
|
|
||||||
case 'FDM':
|
|
||||||
scope.renderMoves(true, 0x888888);
|
|
||||||
break;
|
|
||||||
case 'LASER':
|
|
||||||
scope.renderMoves(false, 0x0088aa);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
driver.printRender(this, {tools});
|
||||||
};
|
};
|
||||||
|
|
||||||
function pref(a,b) {
|
function pref(a,b) {
|
||||||
|
|
@ -425,69 +421,6 @@ let gs_kiri_print = exports;
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
PRO.renderMoves = function(showMoves, moveColor, firstPoint) {
|
|
||||||
let debug = KIRI.api.const.LOCAL;
|
|
||||||
let scope = this, emits, moves, last = firstPoint;
|
|
||||||
// render layered output
|
|
||||||
scope.lines = 0;
|
|
||||||
scope.output.forEach(function(layerout) {
|
|
||||||
let move = [], print = {}, z;
|
|
||||||
layerout.forEach(function(out, index) {
|
|
||||||
let point = out.point;
|
|
||||||
if (last) {
|
|
||||||
if (UTIL.distSq(last, point) < 0.001 && point.z === last.z) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (out.emit > 0) {
|
|
||||||
let spd = out.speed || 4000;
|
|
||||||
let arr = print[spd] || [];
|
|
||||||
print[spd] = arr;
|
|
||||||
arr.push(last);
|
|
||||||
arr.push(point);
|
|
||||||
} else {
|
|
||||||
move.push(last);
|
|
||||||
move.push(point);
|
|
||||||
}
|
|
||||||
if (debug && showMoves && last.z == point.z) {
|
|
||||||
let rs = BASE.newSlope(
|
|
||||||
{x: point.x, y: point.y},
|
|
||||||
{x: last.x, y: last.y}
|
|
||||||
);
|
|
||||||
let ao1 = BASE.newSlopeFromAngle(rs.angle + 25);
|
|
||||||
let ao2 = BASE.newSlopeFromAngle(rs.angle - 25);
|
|
||||||
let sp = BASE.newPoint(point.x, point.y, point.z);
|
|
||||||
move.push(sp);
|
|
||||||
move.push(sp.projectOnSlope(ao1, 0.5));
|
|
||||||
move.push(sp);
|
|
||||||
move.push(sp.projectOnSlope(ao2, 0.5));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
z = point.z;
|
|
||||||
}
|
|
||||||
last = point;
|
|
||||||
});
|
|
||||||
emits = KIRI.newLayer(scope.group);
|
|
||||||
scope.printView.push(emits);
|
|
||||||
if (showMoves) {
|
|
||||||
moves = KIRI.newLayer(scope.group);
|
|
||||||
moves.lines(move, moveColor);
|
|
||||||
scope.movesView.push(moves);
|
|
||||||
moves.render();
|
|
||||||
}
|
|
||||||
for (let speed in print) {
|
|
||||||
let sint = Math.min(6000, parseInt(speed));
|
|
||||||
let rgb = hsv2rgb({h:sint/6000, s:1, v:0.6});
|
|
||||||
emits.lines(print[speed],
|
|
||||||
((rgb.r * 0xff) << 16) |
|
|
||||||
((rgb.g * 0xff) << 8) |
|
|
||||||
((rgb.b * 0xff) << 0)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
emits.render();
|
|
||||||
scope.lines += print.length;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
PRO.getLayerCount = function() {
|
PRO.getLayerCount = function() {
|
||||||
return this.output.length;
|
return this.output.length;
|
||||||
}
|
}
|
||||||
|
|
@ -1,26 +1,21 @@
|
||||||
/** Copyright 2014-2019 Stewart Allen -- All Rights Reserved */
|
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
let gs_kiri_slice = exports;
|
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
if (!self.kiri) self.kiri = {};
|
|
||||||
if (self.kiri.Slice) return;
|
if (self.kiri.Slice) return;
|
||||||
|
|
||||||
let KIRI = self.kiri,
|
const KIRI = self.kiri,
|
||||||
FILL = KIRI.fill,
|
FILL = KIRI.fill,
|
||||||
FILLFIXED = KIRI.fill_fixed,
|
FILLFIXED = KIRI.fill_fixed,
|
||||||
|
PRO = Slice.prototype,
|
||||||
BASE = self.base,
|
BASE = self.base,
|
||||||
UTIL = BASE.util,
|
UTIL = BASE.util,
|
||||||
POLY = BASE.polygons,
|
POLY = BASE.polygons,
|
||||||
PRO = Slice.prototype,
|
NOKEY = BASE.key.NONE,
|
||||||
fillArea = POLY.fillArea,
|
fillArea = POLY.fillArea,
|
||||||
newPoint = BASE.newPoint,
|
newPoint = BASE.newPoint,
|
||||||
MIN = Math.min,
|
|
||||||
MAX = Math.max,
|
|
||||||
NOKEY = BASE.key.NONE,
|
|
||||||
outline_colors = [
|
outline_colors = [
|
||||||
0xeeee00,
|
0xeeee00,
|
||||||
0xeebb00,
|
0xeebb00,
|
||||||
|
|
@ -1,15 +1,12 @@
|
||||||
/** Copyright 2014-2019 Stewart Allen -- All Rights Reserved */
|
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
let gs_kiri_slicer = exports;
|
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
if (!self.kiri) self.kiri = {};
|
|
||||||
if (self.kiri.slicer) return;
|
if (self.kiri.slicer) return;
|
||||||
|
|
||||||
let slicer = self.kiri.slicer = {
|
self.kiri.slicer = {
|
||||||
slice: slice,
|
slice: slice,
|
||||||
sliceWidget: sliceWidget,
|
sliceWidget: sliceWidget,
|
||||||
connectLines: connectLines
|
connectLines: connectLines
|
||||||
|
|
@ -271,6 +268,7 @@ let gs_kiri_slicer = exports;
|
||||||
// copy to store original z
|
// copy to store original z
|
||||||
zHeights = zIndexes.slice();
|
zHeights = zIndexes.slice();
|
||||||
} else if (zIncMin) {
|
} else if (zIncMin) {
|
||||||
|
// console.log('adaptive slicing', zIncMin, ':', zInc, 'from', zMin, 'to', zMax);
|
||||||
// FDM adaptive slicing
|
// FDM adaptive slicing
|
||||||
let zPos = zMin + zIncFirst,
|
let zPos = zMin + zIncFirst,
|
||||||
zOI = 0,
|
zOI = 0,
|
||||||
|
|
@ -311,6 +309,7 @@ let gs_kiri_slicer = exports;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// console.log('fixed slicing', zInc, 'from', zMin, 'to', zMax);
|
||||||
// FDM fixed slicing
|
// FDM fixed slicing
|
||||||
if (options.firstHeight) {
|
if (options.firstHeight) {
|
||||||
zIndexes.push(options.firstHeight / 2);
|
zIndexes.push(options.firstHeight / 2);
|
||||||
|
|
@ -322,6 +321,7 @@ let gs_kiri_slicer = exports;
|
||||||
zHeights.push(zInc);
|
zHeights.push(zInc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// create a Slice for each z offset in the zIndexes array
|
// create a Slice for each z offset in the zIndexes array
|
||||||
for (let i = 0; i < zIndexes.length; i++) {
|
for (let i = 0; i < zIndexes.length; i++) {
|
||||||
let ik = zIndexes[i].toFixed(5),
|
let ik = zIndexes[i].toFixed(5),
|
||||||
586
src/kiri/ui.js
Normal file
586
src/kiri/ui.js
Normal file
|
|
@ -0,0 +1,586 @@
|
||||||
|
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
|
||||||
|
if (kiri.ui) return;
|
||||||
|
|
||||||
|
let SELF = self,
|
||||||
|
KIRI = self.kiri,
|
||||||
|
lastGroup = null,
|
||||||
|
lastDiv = null,
|
||||||
|
addTo = null,
|
||||||
|
hideAction = null,
|
||||||
|
inputAction = null,
|
||||||
|
groups = {},
|
||||||
|
groupShow = {},
|
||||||
|
groupName = undefined,
|
||||||
|
poppable = {},
|
||||||
|
hasModes = [],
|
||||||
|
isExpert = [],
|
||||||
|
letMode = null,
|
||||||
|
letExpert = false,
|
||||||
|
DOC = SELF.document,
|
||||||
|
state = {},
|
||||||
|
prefix = "tab",
|
||||||
|
NOMODE = "nomode",
|
||||||
|
exitimer = undefined;
|
||||||
|
|
||||||
|
SELF.$ = (SELF.$ || function (id) { return DOC.getElementById(id) } );
|
||||||
|
|
||||||
|
KIRI.ui = {
|
||||||
|
prefix: function(pre) { prefix = pre; return kiri.ui },
|
||||||
|
hideAction: function(fn) { hideAction = fn; return kiri.ui },
|
||||||
|
inputAction: function(fn) { inputAction = fn; return kiri.ui },
|
||||||
|
setMode: setMode,
|
||||||
|
setExpert: setExpert,
|
||||||
|
bound: bound,
|
||||||
|
toInt: toInt,
|
||||||
|
toFloat: toFloat,
|
||||||
|
hidePop: hidePop,
|
||||||
|
isPopped: isPopped,
|
||||||
|
newText: newTextArea,
|
||||||
|
newLabel: newLabel,
|
||||||
|
newRange: newRange,
|
||||||
|
newInput: newInputField,
|
||||||
|
newButton: newButton,
|
||||||
|
newBoolean: newBooleanField,
|
||||||
|
newSelect: newSelect,
|
||||||
|
newTable: newTables,
|
||||||
|
newTableRow: newTableRow,
|
||||||
|
newRow: newRow,
|
||||||
|
newBlank: newBlank,
|
||||||
|
newGroup: newGroup,
|
||||||
|
setGroup: setGroup,
|
||||||
|
hidePoppers: hidePoppers,
|
||||||
|
checkpoint,
|
||||||
|
restore
|
||||||
|
};
|
||||||
|
|
||||||
|
function setMode(mode) {
|
||||||
|
Object.keys(groupShow).forEach(group => {
|
||||||
|
updateGroupShow(group);
|
||||||
|
});
|
||||||
|
letMode = mode;
|
||||||
|
hasModes.forEach(function(div) {
|
||||||
|
div.setMode(div._group && !groupShow[div._group] ? NOMODE : mode);
|
||||||
|
});
|
||||||
|
hidePoppers();
|
||||||
|
}
|
||||||
|
|
||||||
|
function setExpert(bool) {
|
||||||
|
letExpert = bool;
|
||||||
|
setMode(letMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkpoint() {
|
||||||
|
return { addTo, lastDiv, lastGroup, groupName };
|
||||||
|
}
|
||||||
|
|
||||||
|
function restore(opt) {
|
||||||
|
if (opt) {
|
||||||
|
addTo = opt.addTo;
|
||||||
|
lastDiv = opt.lastDiv;
|
||||||
|
lastGroup = opt.lastGroup;
|
||||||
|
groupName = opt.groupName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// at present only used by the layers popup menu
|
||||||
|
function setGroup(div) {
|
||||||
|
addTo = lastDiv = div;
|
||||||
|
groupName = undefined;
|
||||||
|
lastGroup = [];
|
||||||
|
return div;
|
||||||
|
}
|
||||||
|
|
||||||
|
function newGroup(label, div, options) {
|
||||||
|
lastDiv = div || lastDiv;
|
||||||
|
return addCollapsableGroup(label, lastDiv, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addCollapsableGroup(label, div, options) {
|
||||||
|
let opt = options || {};
|
||||||
|
let group = opt.group || label;
|
||||||
|
poppable[group] = opt.inline === true ? false : true;
|
||||||
|
|
||||||
|
let row = DOC.createElement('div'),
|
||||||
|
a = DOC.createElement('a'),
|
||||||
|
dbkey = `beta-${prefix}-show-${group}`,
|
||||||
|
popper = !opt.inline;
|
||||||
|
|
||||||
|
if (popper) {
|
||||||
|
let pop = DOC.createElement('div');
|
||||||
|
pop.classList.add('set-pop');
|
||||||
|
row.appendChild(pop);
|
||||||
|
row.setAttribute("class", "set-group noselect");
|
||||||
|
addTo = pop;
|
||||||
|
} else {
|
||||||
|
row.setAttribute("class", "set-header col");
|
||||||
|
addTo = lastDiv;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.appendChild(row);
|
||||||
|
row.appendChild(a);
|
||||||
|
a.appendChild(DOC.createTextNode(label));
|
||||||
|
addModeControls(row, opt);
|
||||||
|
lastGroup = groups[group] = [];
|
||||||
|
lastGroup.key = dbkey;
|
||||||
|
groupName = group;
|
||||||
|
groupShow[group] = popper ? state[dbkey] === 'true' : state[dbkey] !== 'false';
|
||||||
|
row.onclick = function(ev) {
|
||||||
|
if (ev.target !== a && ev.target !== row) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
toggleGroup(group, dbkey);
|
||||||
|
};
|
||||||
|
if (popper) {
|
||||||
|
row.onmouseenter = function(ev) {
|
||||||
|
if (ev.target !== a && ev.target !== row) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
clearTimeout(exitimer);
|
||||||
|
showGroup(group);
|
||||||
|
};
|
||||||
|
row.onmouseleave = function(ev) {
|
||||||
|
if (ev.target !== a && ev.target !== row) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
clearTimeout(exitimer);
|
||||||
|
exitimer = setTimeout(showGroup, 1000);
|
||||||
|
};
|
||||||
|
addTo._group = group;
|
||||||
|
addModeControls(addTo, opt);
|
||||||
|
lastGroup.push(addTo);
|
||||||
|
}
|
||||||
|
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
|
||||||
|
function hidePoppers() {
|
||||||
|
showGroup(undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
function showGroup(groupname) {
|
||||||
|
Object.keys(groups).forEach(name => {
|
||||||
|
let group = groups[name];
|
||||||
|
groupShow[name] = state[group.key] = (groupname === name);
|
||||||
|
updateGroupShow(name);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleGroup(groupname, dbkey) {
|
||||||
|
let show = state[dbkey] === 'false';
|
||||||
|
groupShow[groupname] = poppable[groupname] ? state[dbkey] = show : true;
|
||||||
|
updateGroupShow(groupname);
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateGroupShow(groupname) {
|
||||||
|
let show = groupShow[groupname] || !poppable[groupname];
|
||||||
|
let group = groups[groupname];
|
||||||
|
group.forEach(div => {
|
||||||
|
if (show) div.setMode(letMode);
|
||||||
|
else div.setMode(NOMODE);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function toInt() {
|
||||||
|
let nv = this.value !== '' ? parseInt(this.value) : null;
|
||||||
|
if (isNaN(nv)) nv = 0;
|
||||||
|
if (nv !== null && this.bound) nv = this.bound(nv);
|
||||||
|
this.value = nv;
|
||||||
|
return nv;
|
||||||
|
}
|
||||||
|
|
||||||
|
function toFloat() {
|
||||||
|
let nv = this.value !== '' ? parseFloat(this.value) : null;
|
||||||
|
if (nv !== null && this.bound) nv = this.bound(nv);
|
||||||
|
this.value = nv;
|
||||||
|
return nv;
|
||||||
|
}
|
||||||
|
|
||||||
|
function bound(low,high) {
|
||||||
|
return function(v) {
|
||||||
|
if (isNaN(v)) return low;
|
||||||
|
return v < low ? low : v > high ? high : v;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function raw() {
|
||||||
|
return this.value !== '' ? this.value : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function newLabel(text) {
|
||||||
|
let label = DOC.createElement('label');
|
||||||
|
label.appendChild(DOC.createTextNode(text));
|
||||||
|
label.setAttribute("class", "noselect");
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
|
||||||
|
function addId(el, options) {
|
||||||
|
if (options && options.id) {
|
||||||
|
el.setAttribute("id", options.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function addModeControls(el, options) {
|
||||||
|
options = options || {};
|
||||||
|
el.__show = true;
|
||||||
|
el.__modeSave = null;
|
||||||
|
el.showMe = function() {
|
||||||
|
if (el.__show) return;
|
||||||
|
el.style.display = el.__modeSave;
|
||||||
|
el.__show = true;
|
||||||
|
el.__modeSave = null;
|
||||||
|
};
|
||||||
|
el.hideMe = function() {
|
||||||
|
if (!el.__show) return;
|
||||||
|
el.__show = false;
|
||||||
|
el.__modeSave = el.style.display;
|
||||||
|
el.style.display = 'none';
|
||||||
|
};
|
||||||
|
el.setVisible = function(show) {
|
||||||
|
if (show) el.showMe();
|
||||||
|
else el.hideMe();
|
||||||
|
};
|
||||||
|
el.setMode = function(mode) {
|
||||||
|
let show = options.expert === undefined || (options.expert === letExpert);
|
||||||
|
el.setVisible(el.hasMode(mode) && show);
|
||||||
|
}
|
||||||
|
el.hasMode = function(mode) {
|
||||||
|
if (mode === NOMODE) return false;
|
||||||
|
if (!el.modes) return true;
|
||||||
|
return el.modes.contains(mode);
|
||||||
|
}
|
||||||
|
if (options.modes) {
|
||||||
|
el.modes = options.modes;
|
||||||
|
hasModes.push(el);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function newDiv(options) {
|
||||||
|
let div = DOC.createElement('div');
|
||||||
|
addModeControls(div, options);
|
||||||
|
addTo.appendChild(div);
|
||||||
|
lastGroup.push(div);
|
||||||
|
div._group = groupName;
|
||||||
|
return div;
|
||||||
|
}
|
||||||
|
|
||||||
|
let lastTxt = null;
|
||||||
|
let lastPop = null;
|
||||||
|
let savePop = null;
|
||||||
|
|
||||||
|
function hidePop() {
|
||||||
|
if (lastPop) {
|
||||||
|
lastPop.style.display = "none";
|
||||||
|
}
|
||||||
|
if (savePop) {
|
||||||
|
savePop();
|
||||||
|
savePop = null;
|
||||||
|
}
|
||||||
|
lastPop = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isPopped() {
|
||||||
|
return lastPop !== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function newTextArea(label, options) {
|
||||||
|
let opt = options || {},
|
||||||
|
row = newDiv(options),
|
||||||
|
btn = DOC.createElement("button"),
|
||||||
|
pop = DOC.createElement("div"),
|
||||||
|
txt = DOC.createElement("textarea"),
|
||||||
|
area = opt.area;
|
||||||
|
|
||||||
|
txt.setAttribute("wrap", "off");
|
||||||
|
txt.setAttribute("spellcheck", "false");
|
||||||
|
txt.setAttribute("style", "resize: none");
|
||||||
|
txt.onblur = inputAction;
|
||||||
|
|
||||||
|
btn.appendChild(DOC.createTextNode("edit"));
|
||||||
|
|
||||||
|
btn.onclick = function(ev) {
|
||||||
|
ev.stopPropagation();
|
||||||
|
if (ev.target === txt) {
|
||||||
|
// drop clicks on TextArea
|
||||||
|
ev.target.focus();
|
||||||
|
} else {
|
||||||
|
let fc = area.firstChild;
|
||||||
|
if (fc) area.removeChild(fc);
|
||||||
|
area.appendChild(txt);
|
||||||
|
// first time, button click / show
|
||||||
|
btn.parentNode.onclick = btn.onclick;
|
||||||
|
txt.scrollTop = 0;
|
||||||
|
txt.scrollLeft = 0;
|
||||||
|
txt.selectionEnd = 0;
|
||||||
|
let rows = txt.value.split('\n');
|
||||||
|
let cols = 0;
|
||||||
|
rows.forEach(row => {
|
||||||
|
cols = Math.max(cols, row.length);
|
||||||
|
});
|
||||||
|
txt.setAttribute("cols", Math.max(30, cols + 1));
|
||||||
|
txt.setAttribute("rows", Math.max(10, rows.length + 1));
|
||||||
|
|
||||||
|
let showing = pop === lastPop;
|
||||||
|
hidePop();
|
||||||
|
if (!showing) {
|
||||||
|
if (lastTxt) {
|
||||||
|
lastTxt.classList.remove('txt-sel');
|
||||||
|
}
|
||||||
|
row.classList.add('txt-sel');
|
||||||
|
savePop = inputAction;
|
||||||
|
pop.style.display = "flex";
|
||||||
|
lastPop = pop;
|
||||||
|
lastTxt = row;
|
||||||
|
txt.focus();
|
||||||
|
} else {
|
||||||
|
inputAction();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
addModeControls(btn, opt);
|
||||||
|
addId(btn, opt);
|
||||||
|
|
||||||
|
row.appendChild(newLabel(label));
|
||||||
|
row.appendChild(btn);
|
||||||
|
row.setAttribute("class", "var-row");
|
||||||
|
if (opt.title) row.setAttribute("title", options.title);
|
||||||
|
btn.setVisible = row.setVisible;
|
||||||
|
|
||||||
|
return txt;
|
||||||
|
}
|
||||||
|
|
||||||
|
function newInputField(label, options) {
|
||||||
|
let opt = options || {},
|
||||||
|
row = newDiv(opt),
|
||||||
|
hide = opt && opt.hide,
|
||||||
|
size = opt ? opt.size || 5 : 5,
|
||||||
|
height = opt ? opt.height : 0,
|
||||||
|
ip = height > 1 ? DOC.createElement('textarea') : DOC.createElement('input'),
|
||||||
|
action = opt.action || inputAction;
|
||||||
|
|
||||||
|
row.appendChild(newLabel(label));
|
||||||
|
row.appendChild(ip);
|
||||||
|
row.setAttribute("class", "var-row");
|
||||||
|
if (height > 1) {
|
||||||
|
ip.setAttribute("cols", size);
|
||||||
|
ip.setAttribute("rows", height);
|
||||||
|
ip.setAttribute("wrap", "off");
|
||||||
|
} else {
|
||||||
|
if (Number.isInteger(size)) {
|
||||||
|
ip.setAttribute("size", size);
|
||||||
|
} else {
|
||||||
|
ip.setAttribute("style", `width:${size}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ip.setAttribute("type", "text");
|
||||||
|
ip.setAttribute("spellcheck", "false");
|
||||||
|
row.style.display = hide ? 'none' : '';
|
||||||
|
if (opt) {
|
||||||
|
if (opt.disabled) ip.setAttribute("disabled", "true");
|
||||||
|
if (opt.title) row.setAttribute("title", opt.title);
|
||||||
|
if (opt.convert) ip.convert = opt.convert.bind(ip);
|
||||||
|
if (opt.bound) ip.bound = opt.bound;
|
||||||
|
if (opt.action) action = opt.action;
|
||||||
|
}
|
||||||
|
ip.addEventListener('focus', function(event) {
|
||||||
|
hidePop();
|
||||||
|
});
|
||||||
|
if (action) {
|
||||||
|
ip.addEventListener('keydown', function(event) {
|
||||||
|
let key = event.key;
|
||||||
|
if (
|
||||||
|
opt.text ||
|
||||||
|
(key >= '0' && key <= '9') ||
|
||||||
|
key === '.' ||
|
||||||
|
key === '-' ||
|
||||||
|
key === 'Backspace' ||
|
||||||
|
key === 'Delete' ||
|
||||||
|
key === 'ArrowLeft' ||
|
||||||
|
key === 'ArrowRight' ||
|
||||||
|
key === 'Tab' ||
|
||||||
|
event.metaKey ||
|
||||||
|
event.ctrlKey ||
|
||||||
|
(key === ',' && options.comma)
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
});
|
||||||
|
ip.addEventListener('keyup', function(event) {
|
||||||
|
if (event.keyCode === 13) {
|
||||||
|
// action(event);
|
||||||
|
ip.blur();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
ip.addEventListener('blur', function(event) {
|
||||||
|
action(event);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (!ip.convert) ip.convert = raw.bind(ip);
|
||||||
|
ip.setVisible = row.setVisible;
|
||||||
|
|
||||||
|
return ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
function newRange(label, options) {
|
||||||
|
let row = newDiv(options),
|
||||||
|
ip = DOC.createElement('input'),
|
||||||
|
hide = options && options.hide,
|
||||||
|
action = inputAction;
|
||||||
|
|
||||||
|
if (label) row.appendChild(newLabel(label));
|
||||||
|
row.appendChild(ip);
|
||||||
|
row.setAttribute("class", "var-row");
|
||||||
|
ip.setAttribute("type", "range");
|
||||||
|
ip.setAttribute("min", (options && options.min ? options.min : 0));
|
||||||
|
ip.setAttribute("max", (options && options.max ? options.max : 100));
|
||||||
|
ip.setAttribute("value", 0);
|
||||||
|
row.style.display = hide ? 'none' : '';
|
||||||
|
if (options) {
|
||||||
|
if (options.title) {
|
||||||
|
ip.setAttribute("title", options.title);
|
||||||
|
row.setAttribute("title", options.title);
|
||||||
|
}
|
||||||
|
if (options.action) action = options.action;
|
||||||
|
}
|
||||||
|
ip.setVisible = row.setVisible;
|
||||||
|
|
||||||
|
return ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
function newSelect(label, options, source) {
|
||||||
|
let row = newDiv(options),
|
||||||
|
ip = DOC.createElement('select'),
|
||||||
|
hide = options && options.hide,
|
||||||
|
action = inputAction;
|
||||||
|
|
||||||
|
row.appendChild(newLabel(label));
|
||||||
|
row.appendChild(ip);
|
||||||
|
row.setAttribute("source", source || "tools");
|
||||||
|
row.setAttribute("class", "var-row");
|
||||||
|
row.style.display = hide ? 'none' : '';
|
||||||
|
if (options) {
|
||||||
|
if (options.convert) ip.convert = options.convert.bind(ip);
|
||||||
|
if (options.disabled) ip.setAttribute("disabled", "true");
|
||||||
|
if (options.title) row.setAttribute("title", options.title);
|
||||||
|
if (options.action) action = options.action;
|
||||||
|
}
|
||||||
|
ip.onchange = function() { action() };
|
||||||
|
ip.setVisible = row.setVisible;
|
||||||
|
|
||||||
|
return ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
function newBooleanField(label, action, options) {
|
||||||
|
let row = newDiv(options),
|
||||||
|
ip = DOC.createElement('input'),
|
||||||
|
hide = options && options.hide;
|
||||||
|
|
||||||
|
if (label) {
|
||||||
|
row.appendChild(newLabel(label));
|
||||||
|
}
|
||||||
|
row.appendChild(ip);
|
||||||
|
row.setAttribute("class", "var-row");
|
||||||
|
row.style.display = hide ? 'none' : '';
|
||||||
|
ip.setAttribute("type", "checkbox");
|
||||||
|
ip.checked = false;
|
||||||
|
if (options) {
|
||||||
|
if (options.disabled) ip.setAttribute("disabled", "true");
|
||||||
|
if (options.title) {
|
||||||
|
ip.setAttribute("title", options.title);
|
||||||
|
row.setAttribute("title", options.title);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (action) ip.onclick = function() { action() };
|
||||||
|
ip.setVisible = row.setVisible;
|
||||||
|
|
||||||
|
return ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
function newBlank(options) {
|
||||||
|
let row = newDiv(options),
|
||||||
|
hide = options && options.hide;
|
||||||
|
|
||||||
|
row.setAttribute("class", "var-row");
|
||||||
|
row.style.display = hide ? 'none' : '';
|
||||||
|
ip.setVisible = row.setVisible;
|
||||||
|
|
||||||
|
return ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
function newButton(label, action, options) {
|
||||||
|
let opt = options || {},
|
||||||
|
b = DOC.createElement('button');
|
||||||
|
|
||||||
|
b.onclick = function() {
|
||||||
|
hidePoppers();
|
||||||
|
if (action) action();
|
||||||
|
};
|
||||||
|
|
||||||
|
if (opt.class) {
|
||||||
|
opt.class.split(' ').forEach(ce => {
|
||||||
|
b.classList.add(ce);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (opt.icon) {
|
||||||
|
let d = DOC.createElement('div');
|
||||||
|
d.innerHTML = opt.icon;
|
||||||
|
b.appendChild(d);
|
||||||
|
}
|
||||||
|
if (label) {
|
||||||
|
b.appendChild(DOC.createTextNode(label));
|
||||||
|
}
|
||||||
|
|
||||||
|
addModeControls(b, options);
|
||||||
|
addId(b, options);
|
||||||
|
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
function newTableRow(arrayOfArrays, options) {
|
||||||
|
return newRow(newTables(arrayOfArrays), options);
|
||||||
|
}
|
||||||
|
|
||||||
|
function newTables(arrayOfArrays) {
|
||||||
|
let array = [];
|
||||||
|
for (let i=0; i<arrayOfArrays.length; i++) {
|
||||||
|
array.push(newRowTable(arrayOfArrays[i]));
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
function newRowTable(array) {
|
||||||
|
let div = newDiv();
|
||||||
|
div.setAttribute("class", "table-row");
|
||||||
|
array.forEach(function(c) {
|
||||||
|
div.appendChild(c);
|
||||||
|
});
|
||||||
|
return div;
|
||||||
|
}
|
||||||
|
|
||||||
|
function newRow(children, options) {
|
||||||
|
let row = addCollapsableElement((options && options.noadd) ? null : addTo);
|
||||||
|
if (children) children.forEach(function (c) { row.appendChild(c) });
|
||||||
|
addModeControls(row, options);
|
||||||
|
if (options && options.class) {
|
||||||
|
options.class.split(' ').forEach(ce => {
|
||||||
|
row.classList.add(ce);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
|
||||||
|
function addCollapsableElement(parent) {
|
||||||
|
let row = newDiv();
|
||||||
|
if (parent) parent.appendChild(row);
|
||||||
|
if (lastGroup) lastGroup.push(row);
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
@ -1,15 +1,12 @@
|
||||||
/** Copyright 2014-2019 Stewart Allen -- All Rights Reserved */
|
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
let gs_kiri_widget = exports;
|
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
if (!self.kiri) self.kiri = {};
|
|
||||||
if (self.kiri.Widget) return;
|
if (self.kiri.Widget) return;
|
||||||
|
|
||||||
let KIRI = self.kiri,
|
const KIRI = self.kiri,
|
||||||
DRIVERS = KIRI.driver,
|
DRIVERS = KIRI.driver,
|
||||||
BASE = self.base,
|
BASE = self.base,
|
||||||
CONF = BASE.config,
|
CONF = BASE.config,
|
||||||
|
|
@ -20,8 +17,9 @@ let gs_kiri_widget = exports;
|
||||||
SQRT = MATH.sqrt,
|
SQRT = MATH.sqrt,
|
||||||
PRO = Widget.prototype,
|
PRO = Widget.prototype,
|
||||||
time = UTIL.time,
|
time = UTIL.time,
|
||||||
solid_opacity = 1.0,
|
solid_opacity = 1.0;
|
||||||
nextId = 0,
|
|
||||||
|
let nextId = 0,
|
||||||
groups = [];
|
groups = [];
|
||||||
|
|
||||||
KIRI.Widget = Widget;
|
KIRI.Widget = Widget;
|
||||||
|
|
@ -713,34 +711,9 @@ let gs_kiri_widget = exports;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* render all slice and processed data
|
* render all slice and processed data
|
||||||
* @param {number} renderMode
|
|
||||||
* @param {boolean} cam mode
|
|
||||||
*/
|
*/
|
||||||
PRO.render = function(renderMode, cam) {
|
PRO.render = function() {
|
||||||
let slices = this.slices;
|
DRIVERS[this.settings.mode.toUpperCase()].sliceRender(this);
|
||||||
if (!slices) return;
|
|
||||||
|
|
||||||
let settings = this.settings,
|
|
||||||
driver = DRIVERS[settings.mode.toUpperCase()];
|
|
||||||
|
|
||||||
// allow driver to override widget slice rendering (new in SLA)
|
|
||||||
if (driver.sliceRender) return driver.sliceRender(this);
|
|
||||||
|
|
||||||
let extruder = this.getExtruder(settings);
|
|
||||||
// render outline
|
|
||||||
slices.forEach(function(s) { s.renderOutline(renderMode,extruder) });
|
|
||||||
// render shells
|
|
||||||
slices.forEach(function(s) { s.renderShells(renderMode) });
|
|
||||||
// render diff
|
|
||||||
if (!cam) slices.forEach(function(s) { s.renderDiff() });
|
|
||||||
// render solid fill (include solid flats/bridges)
|
|
||||||
slices.forEach(function(s) { s.renderSolidFill() });
|
|
||||||
// render solid fill outlines
|
|
||||||
if (!cam) slices.forEach(function(s) { s.renderSolidOutlines() });
|
|
||||||
// render sparse fill
|
|
||||||
if (!cam) slices.forEach(function(s) { s.renderSparseFill() });
|
|
||||||
// render supports
|
|
||||||
if (!cam) slices.forEach(function(s) { s.renderSupport() });
|
|
||||||
};
|
};
|
||||||
|
|
||||||
PRO.hideSlices = function() {
|
PRO.hideSlices = function() {
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue