grid-apps-cmms/web/kiri/engine.html
bakedpotatolord e25a21c4df add laser demo
2025-05-15 11:38:27 -06:00

376 lines
13 KiB
HTML

<html>
<head lang="en">
<title>Kiri:Moto Javascript Engine API</title>
<meta charset="UTF-8" />
<meta name="keywords" content="browser,slicer,3d print,free,3d slicer,3d slicing,fdm,sla,cnc,cam,machining,toolpaths,toolpath generation,construction systems,kirimoto,metamoto,kiri:moto,kiri,gridbot" />
<meta name="description" content="Kiri:Moto Javascript Engine API" />
<meta property="og:description" content="Embed the Kiri:Moto slicing engine with a Javascript API">
<meta property="og:title" content="Kiri:Moto Javascript Engine API">
<meta property="og:type" content="website">
<meta property="og:url" content="https://grid.space/kiri/engine.html">
<meta property="og:image" content="//static.grid.space/img/logo_gs_og.png">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" href="//static.grid.space/img/favicon.ico">
<link rel="apple-touch-icon" href="//static.grid.space/img/favicon-mobile.png">
<style>
body {
display: flex;
flex-direction: column;
align-items: center;
font-family: sans-serif;
}
#demo {
display: flex;
flex-direction: row;
}
#loadExample #examples {
display:flex;
flex-direction: row;
}
#loadExample #examples button {
margin-right: 1rem;
}
#jcode, #gcode {
width: 400px;
height: 400px;
margin: 5px;
border-radius: 3px;
border: 1px solid #aaa;
}
#jcode, #gcode {
display: flex;
flex-direction: column;
}
#jhead, #ghead {
padding: 3px;
text-align: center;
background-color: rgba(61,133,198,0.25);
border-bottom: 1px solid #aaa;
}
#jbody, #gbody {
flex-grow: 1;
}
#jfoot, #dfoot {
display: flex;
flex-direction: row;
justify-content: center;
}
#jfoot button, #dfoot button {
width: 100%;
}
#gbody {
font-family: monospace;
font-size: smaller;
white-space: pre;
overflow: auto;
}
#gfoot {
display: none;
background-color: rgba(61,133,198,0.25);
border-top: 1px solid #aaa;
padding: 3px;
text-align: center;
}
#api, #loadExample {
width: 812px;
}
#download {
display: none;
}
li {
list-style: circle;
}
li label {
white-space: pre;
font-family: monospace;
}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/ace.js"></script>
<script src="/code/engine.js"></script>
<script>
let edit, saveit = "";
function $(id) { return document.getElementById(id) }
function onload() {
edit = ace.edit($("jbody"), {
mode: "ace/mode/javascript",
theme: "ace/theme/chrome",
selectionStyle: "text"
});
edit.session.setTabSize(4);
edit.session.setUseSoftTabs(true);
let FDMExample = loadExample(demoFDM)
}
function display_message(msg) {
console.log({msg})
$('gfoot').innerText = msg ? Object.keys(msg).join(' - ') : '';
}
function display_gcode(gcode) {
$('gbody').innerText = saveit = gcode;
display_message();
$('dfoot').style.display = 'block';
$('gfoot').style.display = '';
}
function loadExample(func){
let fnstr = func.toString().split("\n");
edit.session.setValue(
fnstr
.slice(1,fnstr.length - 1)
.map(l => l.replace(" ",""))
.join('\n')
)
}
function run_code() {
$('dfoot').style.display = 'none';
$('gfoot').style.display = 'block';
let code = edit.session.getValue();
eval(`(function(){${code}})()`);
}
function demoFDM() {
kiri.newEngine()
.setListener(display_message)
.load("/obj/cube.stl")
.then(eng => eng.setProcess({
}))
.then(eng => eng.setDevice({
gcodePre: [ "M82", "M104 S220" ],
gcodePost: [ "M107" ]
}))
.then(eng => eng.slice())
.then(eng => eng.prepare())
.then(eng => eng.export())
.then(display_gcode);
}
function demoCAM(){
kiri.newEngine()
.setListener(display_message)
.load("/obj/cube.stl")
// should to call widget.setTopZ here ideally
.then(eng => eng.setMode("CAM"))
.then(eng => eng.setStock({
"x": 25,
"y": 25,
"z": 24.999998092651367,
"center": {
"x": 0,
"y": 0,
"z": 12.499999046325684
}
}))
.then(eng=> eng.setTools([
{
"id": 1000,
"number": 1,
"type": "endmill",
"name": "end 1/4",
"metric": false,
"shaft_diam": 0.25,
"shaft_len": 1,
"flute_diam": 0.25,
"flute_len": 2,
"taper_tip": 0,
"order": 5
}
]))
.then(eng => eng.setProcess({
camEaseAngle:10,
camEaseDown:true,
camZAnchor: "bottom",
camDepthFirst : false,
camZThru: 1.524,
camZBottom:-25, // temp hack to get around setTopZ bug
origin: {
"x": -12.5,
"y": 12.5,
"z": 25.00999809265137
},
ops:[{
"type": "outline",
"tool": 1000,
"spindle": 13000,
"step": 0.4,
"steps": 1,
"down": 5.08,
"rate": 635,
"plunge": 51,
"dogbones": false,
"omitvoid": false,
"omitthru": false,
"outside": false,
"inside": false,
"wide": false,
"top": false,
"ov_topz": 0,
"ov_botz": 0,
"ov_conv": true
}
]
}))
.then(eng => eng.setDevice({
"mode": "CAM",
"internal": 0,
"bedHeight": 2.5,
"bedWidth": 678.18,
"bedDepth": 1524,
"maxHeight": 150,
"originCenter": false,
"spindleMax": 24000,
"gcodePre": [
"G20 ; set units to inches (required)",
"G90 ; absolute position mode (required)"
],
"gcodePost": [
"M05 ; spindle off",
"M30 ; program end"
],
"gcodeDwell": [
"G4 P{time} ; dwell for {time}ms"
],
"gcodeSpindle": [
"M3 S{speed} ; spindle on at {spindle} rpm"
],
"gcodeChange": [
"M05 ; spindle off",
"M6 T{tool} ; change tool to '{tool_name}'",
"G37; get tool offset with ETS"
],
"gcodeFExt": "nc",
"gcodeSpace": true,
"gcodeStrip": false,
"deviceName": "Tormach.24R",
"imageURL": "",
"useLaser": false
}))
.then(eng => eng.slice())
.then(eng => eng.prepare())
.then(eng => eng.export())
.then(display_gcode);
}
function demoLASER(){
kiri.newEngine()
.setListener(display_message)
.load("/obj/cube.stl")
// should to call widget.setTopZ here ideally
.then(eng => eng.setMode("LASER"))
.then(eng => eng.setStock({
"x": 25,
"y": 25,
"z": 24.999998092651367,
"center": {
"x": 0,
"y": 0,
"z": 12.499999046325684
}
}))
.then(eng => eng.setProcess({
"processName": "default",
"ctSliceKerf": 0.1,
"ctSliceHeight": 0.5,
"ctSliceHeightMin": 0,
"ctSliceSingle": false,
"ctOutTileSpacing": 1,
"ctOutPower": 100,
"ctOutSpeed": 1000,
"ctOutGroup": true,
"ctOutZColor": false,
"ctOutLayer": false,
"ctOutMark": false,
"ctOutStack": false,
"ctOutMerged": false,
"ctOriginCenter": false,
"ctOriginBounds": false,
"outputInvertX": false,
"outputInvertY": false,
"ctOutKnifeDepth": 1,
"ctOutKnifePasses": 1,
"ctOutKnifeTip": 2,
"ctOutInches": false,
"ctOutShaper": false
}))
.then(eng => eng.setDevice({
"mode": "LASER",
"internal": 0,
"bedHeight": 2.5,
"bedWidth": 600,
"bedDepth": 308,
"maxHeight": 150,
"gcodePre": [],
"gcodePost": [],
"gcodeFExt": "svg",
"gcodeSpace": true,
"gcodeLaserOn": [],
"gcodeLaserOff": [],
"new": false,
"deviceName": "Xtool.P2",
"imageURL": "",
"laserMaxPower": 255,
"bedBelt": false,
"bedRound": false,
"originCenter": false,
"fwRetract": false
}))
.then(eng => eng.slice())
.then(eng => eng.prepare())
.then(eng => eng.export())
.then(display_gcode);
}
function download() {
let blob = new Blob([saveit], {type: "octet/stream"});
let url = window.URL.createObjectURL(blob);
let filename = window.prompt("Enter filename", "sample.gcode");
$('download').innerHTML = `<a id="xo" href="${url}" download="${filename}"></a>`;
$('xo').click();
}
</script>
</head>
<body onload="onload()">
<h2 id="title">Kiri:Moto Javascript Engine <a href="https://docs.grid.space/projects/kiri-moto/apis">API</a></h2>
<div id="demo">
<div id="jcode">
<div id="jhead">javascript</div>
<div id="jbody"></div>
<div id="jfoot"><button onclick="run_code()">run code</button></div>
</div>
<div id="gcode">
<div id="ghead">Output</div>
<div id="gbody"></div>
<div id="gfoot"></div>
<div id="dfoot"><button onclick="download()">download</button></div>
</div>
</div>
<div id="loadExample">
<h2>Load Examples</h2>
<div id="examples">
<button onclick="loadExample(demoFDM)">Load FDM Example</button>
<button onclick="loadExample(demoCAM)">Load CAM Example</button>
<button onclick="loadExample(demoLASER)">Load LASER Example</button>
</div>
</div>
<div id="api">
<h2>Engine Methods</h2>
<li><label>load(url)</label> - where URL points to an STL</li>
<li><label>parse(data)</label> - where data is a string or binary STL</li>
<li><label>setMode(mode)</label> - FDM, CAM, LASER, SLA</li>
<li><label>setListener(fn)</label> - function to receive engine progress messages</li>
<li><label>setDevice(options)</label> - change default object parameters</li>
<li><label>setProcess(options)</label> - change default process parameters</li>
<li><label>setStock(options)</label> - set stock dimensions for CAM mode</li>
<li><label>setTools(tools)</label> - set available tools for CAM operations</li>
<li><label>moveTo(x,y,z)</label> - absolute move origin of loaded object</li>
<li><label>move(x,y,z)</label> - relative move origin of loaded object</li>
<li><label>scale(x,y,z)</label> - scale axes of loaded object</li>
<li><label>rotate(x,y,z)</label> - rotate axes of loaded object in radians</li>
<li><label>slice()</label> - async slice loaded object</li>
<li><label>prepare()</label> - async path routing of slice data</li>
<li><label>export()</label> - async gcode generation from path routing</li>
</div>
<a id="download"></a>
</body>
</html>