Moved octoprint sources to "src" folder, adjusted setup.py and run script accordingly
|
|
@ -1,2 +1,2 @@
|
|||
recursive-include octoprint/static *
|
||||
recursive-include octoprint/templates *
|
||||
recursive-include src/octoprint/static *
|
||||
recursive-include src/octoprint/templates *
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
|
||||
|
|
@ -6,3 +6,5 @@ PyYAML==3.10
|
|||
Flask-Login==0.2.2
|
||||
Flask-Principal==0.3.5
|
||||
netaddr>=0.7.10
|
||||
mock>=1.0.1
|
||||
nose>=1.3.0
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ sockjs-tornado>=1.0.0
|
|||
PyYAML==3.10
|
||||
Flask-Login==0.2.2
|
||||
Flask-Principal==0.3.5
|
||||
numpy>=1.6.2
|
||||
pyserial>=2.6
|
||||
netaddr>=0.7.10
|
||||
mock>=1.0.1
|
||||
|
|
|
|||
75
run
|
|
@ -1,65 +1,16 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
print """
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!!! You are using an old startup method for OctoPrint. !!!
|
||||
!!! Please perform 'sudo python setup.py install' and !!!
|
||||
!!! use the 'octoprint' executable instead. !!!
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
"""
|
||||
|
||||
import sys
|
||||
from octoprint.daemon import Daemon
|
||||
from octoprint.server import Server
|
||||
sys.path.append("src")
|
||||
|
||||
class Main(Daemon):
|
||||
def __init__(self, pidfile, configfile, basedir, host, port, debug):
|
||||
Daemon.__init__(self, pidfile)
|
||||
|
||||
self._configfile = configfile
|
||||
self._basedir = basedir
|
||||
self._host = host
|
||||
self._port = port
|
||||
self._debug = debug
|
||||
|
||||
def run(self):
|
||||
octoprint = Server(self._configfile, self._basedir, self._host, self._port, self._debug)
|
||||
octoprint.run()
|
||||
|
||||
def main():
|
||||
import argparse
|
||||
|
||||
parser = argparse.ArgumentParser(prog="run")
|
||||
|
||||
parser.add_argument("-d", "--debug", action="store_true", dest="debug",
|
||||
help="Enable debug mode")
|
||||
|
||||
parser.add_argument("--host", action="store", type=str, dest="host",
|
||||
help="Specify the host on which to bind the server")
|
||||
parser.add_argument("--port", action="store", type=int, dest="port",
|
||||
help="Specify the port on which to bind the server")
|
||||
|
||||
parser.add_argument("-c", "--config", action="store", dest="config",
|
||||
help="Specify the config file to use. OctoPrint needs to have write access for the settings dialog to work. Defaults to ~/.octoprint/config.yaml")
|
||||
parser.add_argument("-b", "--basedir", action="store", dest="basedir",
|
||||
help="Specify the basedir to use for uploads, timelapses etc. OctoPrint needs to have write access. Defaults to ~/.octoprint")
|
||||
|
||||
parser.add_argument("--daemon", action="store", type=str, choices=["start", "stop", "restart"],
|
||||
help="Daemonize/control daemonized OctoPrint instance (only supported under Linux right now)")
|
||||
parser.add_argument("--pid", action="store", type=str, dest="pidfile", default="/tmp/octoprint.pid",
|
||||
help="Pidfile to use for daemonizing, defaults to /tmp/octoprint.pid")
|
||||
|
||||
parser.add_argument("--iknowwhatimdoing", action="store_true", dest="allowRoot",
|
||||
help="Allow OctoPrint to run as user root")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.daemon:
|
||||
if sys.platform == "darwin" or sys.platform == "win32":
|
||||
print >> sys.stderr, "Sorry, daemon mode is only supported under Linux right now"
|
||||
sys.exit(2)
|
||||
|
||||
daemon = Main(args.pidfile, args.config, args.basedir, args.host, args.port, args.debug)
|
||||
if "start" == args.daemon:
|
||||
daemon.start()
|
||||
elif "stop" == args.daemon:
|
||||
daemon.stop()
|
||||
elif "restart" == args.daemon:
|
||||
daemon.restart()
|
||||
else:
|
||||
octoprint = Server(args.config, args.basedir, args.host, args.port, args.debug, args.allowRoot)
|
||||
octoprint.run()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
import octoprint
|
||||
octoprint.main()
|
||||
|
|
|
|||
0
octoprint.init → scripts/octoprint.init
Executable file → Normal file
16
setup.py
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
from setuptools import setup, find_packages
|
||||
|
||||
VERSION = "0.1.0"
|
||||
VERSION = "1.1.0-dev"
|
||||
|
||||
def params():
|
||||
name = "OctoPrint"
|
||||
|
|
@ -34,11 +34,23 @@ def params():
|
|||
url = "http://octoprint.org"
|
||||
license = "AGPLv3"
|
||||
|
||||
packages = find_packages()
|
||||
packages = find_packages(where="src")
|
||||
package_dir = {"octoprint": "src/octoprint"}
|
||||
|
||||
include_package_data = True
|
||||
zip_safe = False
|
||||
install_requires = open("requirements.txt").read().split("\n")
|
||||
|
||||
entry_points = {
|
||||
"console_scripts": [
|
||||
"octoprint = octoprint:main"
|
||||
]
|
||||
}
|
||||
|
||||
#scripts = {
|
||||
# "scripts/octoprint.init": "/etc/init.d/octoprint"
|
||||
#}
|
||||
|
||||
return locals()
|
||||
|
||||
setup(**params())
|
||||
|
|
|
|||
66
src/octoprint/__init__.py
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
#!/usr/bin/env python
|
||||
import sys
|
||||
from octoprint.daemon import Daemon
|
||||
from octoprint.server import Server
|
||||
|
||||
class Main(Daemon):
|
||||
def __init__(self, pidfile, configfile, basedir, host, port, debug):
|
||||
Daemon.__init__(self, pidfile)
|
||||
|
||||
self._configfile = configfile
|
||||
self._basedir = basedir
|
||||
self._host = host
|
||||
self._port = port
|
||||
self._debug = debug
|
||||
|
||||
def run(self):
|
||||
octoprint = Server(self._configfile, self._basedir, self._host, self._port, self._debug)
|
||||
octoprint.run()
|
||||
|
||||
def main():
|
||||
import argparse
|
||||
|
||||
parser = argparse.ArgumentParser(prog="run")
|
||||
|
||||
parser.add_argument("-d", "--debug", action="store_true", dest="debug",
|
||||
help="Enable debug mode")
|
||||
|
||||
parser.add_argument("--host", action="store", type=str, dest="host",
|
||||
help="Specify the host on which to bind the server")
|
||||
parser.add_argument("--port", action="store", type=int, dest="port",
|
||||
help="Specify the port on which to bind the server")
|
||||
|
||||
parser.add_argument("-c", "--config", action="store", dest="config",
|
||||
help="Specify the config file to use. OctoPrint needs to have write access for the settings dialog to work. Defaults to ~/.octoprint/config.yaml")
|
||||
parser.add_argument("-b", "--basedir", action="store", dest="basedir",
|
||||
help="Specify the basedir to use for uploads, timelapses etc. OctoPrint needs to have write access. Defaults to ~/.octoprint")
|
||||
|
||||
parser.add_argument("--daemon", action="store", type=str, choices=["start", "stop", "restart"],
|
||||
help="Daemonize/control daemonized OctoPrint instance (only supported under Linux right now)")
|
||||
parser.add_argument("--pid", action="store", type=str, dest="pidfile", default="/tmp/octoprint.pid",
|
||||
help="Pidfile to use for daemonizing, defaults to /tmp/octoprint.pid")
|
||||
|
||||
parser.add_argument("--iknowwhatimdoing", action="store_true", dest="allowRoot",
|
||||
help="Allow OctoPrint to run as user root")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.daemon:
|
||||
if sys.platform == "darwin" or sys.platform == "win32":
|
||||
print >> sys.stderr, "Sorry, daemon mode is only supported under Linux right now"
|
||||
sys.exit(2)
|
||||
|
||||
daemon = Main(args.pidfile, args.config, args.basedir, args.host, args.port, args.debug)
|
||||
if "start" == args.daemon:
|
||||
daemon.start()
|
||||
elif "stop" == args.daemon:
|
||||
daemon.stop()
|
||||
elif "restart" == args.daemon:
|
||||
daemon.restart()
|
||||
else:
|
||||
octoprint = Server(args.config, args.basedir, args.host, args.port, args.debug, args.allowRoot)
|
||||
octoprint.run()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
|
Before Width: | Height: | Size: 135 KiB After Width: | Height: | Size: 135 KiB |
|
Before Width: | Height: | Size: 890 B After Width: | Height: | Size: 890 B |
|
Before Width: | Height: | Size: 251 B After Width: | Height: | Size: 251 B |
|
Before Width: | Height: | Size: 212 B After Width: | Height: | Size: 212 B |
|
Before Width: | Height: | Size: 119 B After Width: | Height: | Size: 119 B |
|
Before Width: | Height: | Size: 131 B After Width: | Height: | Size: 131 B |
|
Before Width: | Height: | Size: 124 B After Width: | Height: | Size: 124 B |
|
Before Width: | Height: | Size: 103 B After Width: | Height: | Size: 103 B |
|
Before Width: | Height: | Size: 118 B After Width: | Height: | Size: 118 B |
|
Before Width: | Height: | Size: 104 B After Width: | Height: | Size: 104 B |
|
Before Width: | Height: | Size: 119 B After Width: | Height: | Size: 119 B |
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
|
Before Width: | Height: | Size: 112 B After Width: | Height: | Size: 112 B |
|
|
@ -1,161 +1,161 @@
|
|||
/*body,*/
|
||||
/*#wrap {*/
|
||||
/*width:1000px;*/
|
||||
/*height: 680px;*/
|
||||
/*position: absolute;*/
|
||||
/*top: 50%;*/
|
||||
/*margin-top: -350px;*/
|
||||
/*left: 50%;*/
|
||||
/*margin-left: -500px;*/
|
||||
/**/
|
||||
/*background:#ffffff;*/
|
||||
/*border: 5px outset #bbb;*/
|
||||
/*-moz-border-radius: 5px;*/
|
||||
/*-webkit-border-radius: 5px;*/
|
||||
/*border-radius: 5px;*/
|
||||
/*}*/
|
||||
/*#control {*/
|
||||
/*float:left;*/
|
||||
/*width:300px;*/
|
||||
/*margin-top: 10px;*/
|
||||
/*margin-left: 10px;*/
|
||||
/*background:#ffffff;*/
|
||||
/*margin-right: 10px;*/
|
||||
/*height: 680px;*/
|
||||
/*}*/
|
||||
#file_block {
|
||||
/*margin-top: 20px;*/
|
||||
/*margin-left: 20px;*/
|
||||
}
|
||||
|
||||
#control_bottom {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 300px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
#options{
|
||||
float: left;
|
||||
margin-left: 5px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
/*#gcode {
|
||||
background: #ffffff;
|
||||
float:right;
|
||||
width: 680px;
|
||||
height: 680px;
|
||||
border-width: 2px;
|
||||
border-style: none none none solid;
|
||||
}*/
|
||||
|
||||
#canvas{
|
||||
/*float: left;*/
|
||||
clear:none;
|
||||
}
|
||||
|
||||
#drop_zone {
|
||||
border: 2px dashed #bbb;
|
||||
-moz-border-radius: 5px;
|
||||
-webkit-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
padding: 40px;
|
||||
margin: 5px;
|
||||
text-align: center;
|
||||
font: 20pt bold;
|
||||
color: #bbb
|
||||
}
|
||||
#slider-vertical {
|
||||
/*position: absolute;*/
|
||||
/*right: 0;*/
|
||||
/*top: 0;*/
|
||||
height: 580px;
|
||||
width: 10px;
|
||||
float: right;
|
||||
}
|
||||
#slider-horizontal {
|
||||
height: 10px;
|
||||
width: 570px;
|
||||
/*position: absolute;*/
|
||||
/*bottom: 0;*/
|
||||
}
|
||||
|
||||
#main_button_block {
|
||||
/*float: right;*/
|
||||
margin-bottom: 5px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
#gcode .mbut{
|
||||
height:60px;
|
||||
width: 250px;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
#tabs-min {
|
||||
height: 680px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
#gcode .mtab{
|
||||
background: transparent;
|
||||
border: none;
|
||||
font-weight: normal;
|
||||
font-size: 0.5em;
|
||||
}
|
||||
|
||||
#gcode .mtab-defstate{
|
||||
background: transparent;
|
||||
border: none;
|
||||
|
||||
}
|
||||
|
||||
#gcode .mtab-content{
|
||||
background: #ffffff;
|
||||
background-image: none;
|
||||
border: 0px none #dddddd;
|
||||
border-bottom-style: none;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
#gcode .bar {
|
||||
-webkit-transition: width 0s linear !important;
|
||||
-moz-transition: width 0s linear !important;
|
||||
-o-transition: width 0s linear !important;
|
||||
transition: width 0s linear !important;
|
||||
}
|
||||
|
||||
#gcode .nav {
|
||||
margin-bottom: 0px !important;
|
||||
}
|
||||
|
||||
#gcode .tab-content {
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
#gcode .aboutpage {
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
#accordion_top .ui-accordion-content{
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
#tabs-min .ui-tabs-panel {
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
#progressBlock {
|
||||
margin-left: 10px;
|
||||
margin-right: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
#gcode .colorBox {
|
||||
width: 50px;
|
||||
height: 15px;
|
||||
border: 1px solid #000000;
|
||||
float:left;
|
||||
}
|
||||
|
||||
#gcode .activeline {background: #fff0b6 !important;}
|
||||
|
||||
/*body,*/
|
||||
/*#wrap {*/
|
||||
/*width:1000px;*/
|
||||
/*height: 680px;*/
|
||||
/*position: absolute;*/
|
||||
/*top: 50%;*/
|
||||
/*margin-top: -350px;*/
|
||||
/*left: 50%;*/
|
||||
/*margin-left: -500px;*/
|
||||
/**/
|
||||
/*background:#ffffff;*/
|
||||
/*border: 5px outset #bbb;*/
|
||||
/*-moz-border-radius: 5px;*/
|
||||
/*-webkit-border-radius: 5px;*/
|
||||
/*border-radius: 5px;*/
|
||||
/*}*/
|
||||
/*#control {*/
|
||||
/*float:left;*/
|
||||
/*width:300px;*/
|
||||
/*margin-top: 10px;*/
|
||||
/*margin-left: 10px;*/
|
||||
/*background:#ffffff;*/
|
||||
/*margin-right: 10px;*/
|
||||
/*height: 680px;*/
|
||||
/*}*/
|
||||
#file_block {
|
||||
/*margin-top: 20px;*/
|
||||
/*margin-left: 20px;*/
|
||||
}
|
||||
|
||||
#control_bottom {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 300px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
#options{
|
||||
float: left;
|
||||
margin-left: 5px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
/*#gcode {
|
||||
background: #ffffff;
|
||||
float:right;
|
||||
width: 680px;
|
||||
height: 680px;
|
||||
border-width: 2px;
|
||||
border-style: none none none solid;
|
||||
}*/
|
||||
|
||||
#canvas{
|
||||
/*float: left;*/
|
||||
clear:none;
|
||||
}
|
||||
|
||||
#drop_zone {
|
||||
border: 2px dashed #bbb;
|
||||
-moz-border-radius: 5px;
|
||||
-webkit-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
padding: 40px;
|
||||
margin: 5px;
|
||||
text-align: center;
|
||||
font: 20pt bold;
|
||||
color: #bbb
|
||||
}
|
||||
#slider-vertical {
|
||||
/*position: absolute;*/
|
||||
/*right: 0;*/
|
||||
/*top: 0;*/
|
||||
height: 580px;
|
||||
width: 10px;
|
||||
float: right;
|
||||
}
|
||||
#slider-horizontal {
|
||||
height: 10px;
|
||||
width: 570px;
|
||||
/*position: absolute;*/
|
||||
/*bottom: 0;*/
|
||||
}
|
||||
|
||||
#main_button_block {
|
||||
/*float: right;*/
|
||||
margin-bottom: 5px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
#gcode .mbut{
|
||||
height:60px;
|
||||
width: 250px;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
#tabs-min {
|
||||
height: 680px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
#gcode .mtab{
|
||||
background: transparent;
|
||||
border: none;
|
||||
font-weight: normal;
|
||||
font-size: 0.5em;
|
||||
}
|
||||
|
||||
#gcode .mtab-defstate{
|
||||
background: transparent;
|
||||
border: none;
|
||||
|
||||
}
|
||||
|
||||
#gcode .mtab-content{
|
||||
background: #ffffff;
|
||||
background-image: none;
|
||||
border: 0px none #dddddd;
|
||||
border-bottom-style: none;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
#gcode .bar {
|
||||
-webkit-transition: width 0s linear !important;
|
||||
-moz-transition: width 0s linear !important;
|
||||
-o-transition: width 0s linear !important;
|
||||
transition: width 0s linear !important;
|
||||
}
|
||||
|
||||
#gcode .nav {
|
||||
margin-bottom: 0px !important;
|
||||
}
|
||||
|
||||
#gcode .tab-content {
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
#gcode .aboutpage {
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
#accordion_top .ui-accordion-content{
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
#tabs-min .ui-tabs-panel {
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
#progressBlock {
|
||||
margin-left: 10px;
|
||||
margin-right: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
#gcode .colorBox {
|
||||
width: 50px;
|
||||
height: 15px;
|
||||
border: 1px solid #000000;
|
||||
float:left;
|
||||
}
|
||||
|
||||
#gcode .activeline {background: #fff0b6 !important;}
|
||||
|
||||
|
|
@ -1,473 +1,473 @@
|
|||
/**
|
||||
* User: hudbrog (hudbrog@gmail.com)
|
||||
* Date: 10/24/12
|
||||
* Time: 12:18 PM
|
||||
*/
|
||||
|
||||
var gcode;
|
||||
var firstReport;
|
||||
var z_heights = {};
|
||||
var model = [];
|
||||
var gCodeOptions = {
|
||||
sortLayers: false,
|
||||
purgeEmptyLayers: true,
|
||||
analyzeModel: false
|
||||
};
|
||||
var max = {x: undefined, y: undefined, z: undefined};
|
||||
var min = {x: undefined, y: undefined, z: undefined};
|
||||
var modelSize = {x: undefined, y: undefined, z: undefined};
|
||||
var filamentByLayer = {};
|
||||
var totalFilament=0;
|
||||
var printTime=0;
|
||||
var printTimeByLayer = {};
|
||||
var layerHeight=0;
|
||||
var layerCnt = 0;
|
||||
var speeds = {extrude: [], retract: [], move: []};
|
||||
var speedsByLayer = {extrude: {}, retract: {}, move: {}};
|
||||
|
||||
|
||||
|
||||
var sendLayerToParent = function(layerNum, z, progress){
|
||||
self.postMessage({
|
||||
"cmd": "returnLayer",
|
||||
"msg": {
|
||||
cmds: model[layerNum],
|
||||
layerNum: layerNum,
|
||||
zHeightObject: {zValue: z, layer: z_heights[z]},
|
||||
isEmpty: false,
|
||||
progress: progress
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var sendMultiLayerToParent = function(layerNum, z, progress){
|
||||
var tmpModel = [];
|
||||
var tmpZHeight = {};
|
||||
|
||||
for(var i=0;i<layerNum.length;i++){
|
||||
tmpModel[layerNum[i]] = model[layerNum[i]];
|
||||
tmpZHeight[layerNum[i]] = z_heights[z[i]];
|
||||
}
|
||||
|
||||
self.postMessage({
|
||||
"cmd": "returnMultiLayer",
|
||||
"msg": {
|
||||
model: tmpModel,
|
||||
layerNum: layerNum,
|
||||
zHeightObject: {zValue: z, layer: tmpZHeight},
|
||||
isEmpty: false,
|
||||
progress: progress
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
var sendSizeProgress = function(progress){
|
||||
self.postMessage({
|
||||
"cmd": "analyzeProgress",
|
||||
"msg": {
|
||||
progress: progress,
|
||||
printTime: printTime
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var sendAnalyzeDone = function(){
|
||||
self.postMessage({
|
||||
"cmd": "analyzeDone",
|
||||
"msg": {
|
||||
max: max,
|
||||
min: min,
|
||||
modelSize: modelSize,
|
||||
totalFilament:totalFilament,
|
||||
filamentByLayer: filamentByLayer,
|
||||
printTime: printTime,
|
||||
layerHeight: layerHeight,
|
||||
layerCnt: layerCnt,
|
||||
layerTotal: model.length,
|
||||
speeds: speeds,
|
||||
speedsByLayer: speedsByLayer,
|
||||
printTimeByLayer: printTimeByLayer
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var purgeLayers = function(){
|
||||
var purge=true;
|
||||
for(var i=0;i<model.length;i++){
|
||||
purge=true;
|
||||
if(!model[i])purge=true;
|
||||
else {
|
||||
for(var j=0;j<model[i].length;j++){
|
||||
if(model[i][j].extrude)purge=false;
|
||||
}
|
||||
}
|
||||
if(!purge){
|
||||
layerCnt+=1;
|
||||
}
|
||||
}
|
||||
// self.postMessage('LayerCnt: ' + layerCnt);
|
||||
};
|
||||
|
||||
|
||||
var analyzeModel = function(){
|
||||
var i,j;
|
||||
var x_ok=false, y_ok=false;
|
||||
var cmds;
|
||||
var tmp1= 0, tmp2=0;
|
||||
var speedIndex=0;
|
||||
var type;
|
||||
var printTimeAdd=0;
|
||||
// var moveTime=0;
|
||||
|
||||
for(i=0;i<model.length;i++){
|
||||
cmds = model[i];
|
||||
if(!cmds)continue;
|
||||
for(j=0;j<cmds.length;j++){
|
||||
x_ok=false;
|
||||
y_ok=false;
|
||||
if(typeof(cmds[j].x) !== 'undefined'&&typeof(cmds[j].prevX) !== 'undefined'&&typeof(cmds[j].extrude) !== 'undefined'&&cmds[j].extrude&&!isNaN(cmds[j].x))
|
||||
{
|
||||
max.x = parseFloat(max.x)>parseFloat(cmds[j].x)?parseFloat(max.x):parseFloat(cmds[j].x);
|
||||
max.x = parseFloat(max.x)>parseFloat(cmds[j].prevX)?parseFloat(max.x):parseFloat(cmds[j].prevX);
|
||||
min.x = parseFloat(min.x)<parseFloat(cmds[j].x)?parseFloat(min.x):parseFloat(cmds[j].x);
|
||||
min.x = parseFloat(min.x)<parseFloat(cmds[j].prevX)?parseFloat(min.x):parseFloat(cmds[j].prevX);
|
||||
x_ok=true;
|
||||
}
|
||||
|
||||
if(typeof(cmds[j].y) !== 'undefined'&&typeof(cmds[j].prevY) !== 'undefined'&&typeof(cmds[j].extrude) !== 'undefined'&&cmds[j].extrude&&!isNaN(cmds[j].y)){
|
||||
max.y = parseFloat(max.y)>parseFloat(cmds[j].y)?parseFloat(max.y):parseFloat(cmds[j].y);
|
||||
max.y = parseFloat(max.y)>parseFloat(cmds[j].prevY)?parseFloat(max.y):parseFloat(cmds[j].prevY);
|
||||
min.y = parseFloat(min.y)<parseFloat(cmds[j].y)?parseFloat(min.y):parseFloat(cmds[j].y);
|
||||
min.y = parseFloat(min.y)<parseFloat(cmds[j].prevY)?parseFloat(min.y):parseFloat(cmds[j].prevY);
|
||||
y_ok=true;
|
||||
}
|
||||
|
||||
if(typeof(cmds[j].prevZ) !== 'undefined'&&typeof(cmds[j].extrude) !== 'undefined'&&cmds[j].extrude&&!isNaN(cmds[j].prevZ)){
|
||||
max.z = parseFloat(max.z)>parseFloat(cmds[j].prevZ)?parseFloat(max.z):parseFloat(cmds[j].prevZ);
|
||||
min.z = parseFloat(min.z)<parseFloat(cmds[j].prevZ)?parseFloat(min.z):parseFloat(cmds[j].prevZ);
|
||||
}
|
||||
|
||||
if(typeof(cmds[j].extrude) !== 'undefined'||cmds[j].retract!=0){
|
||||
totalFilament+=cmds[j].extrusion;
|
||||
if(!filamentByLayer[cmds[j].prevZ])filamentByLayer[cmds[j].prevZ]=0;
|
||||
filamentByLayer[cmds[j].prevZ]+=cmds[j].extrusion;
|
||||
}
|
||||
|
||||
if(x_ok&&y_ok){
|
||||
printTimeAdd = Math.sqrt(Math.pow(parseFloat(cmds[j].x)-parseFloat(cmds[j].prevX),2)+Math.pow(parseFloat(cmds[j].y)-parseFloat(cmds[j].prevY),2))/(cmds[j].speed/60);
|
||||
}else if(cmds[j].retract===0&&cmds[j].extrusion!==0){
|
||||
tmp1 = Math.sqrt(Math.pow(parseFloat(cmds[j].x)-parseFloat(cmds[j].prevX),2)+Math.pow(parseFloat(cmds[j].y)-parseFloat(cmds[j].prevY),2))/(cmds[j].speed/60);
|
||||
tmp2 = Math.abs(parseFloat(cmds[j].extrusion)/(cmds[j].speed/60));
|
||||
printTimeAdd = tmp1>=tmp2?tmp1:tmp2;
|
||||
}else if(cmds[j].retract!==0){
|
||||
printTimeAdd = Math.abs(parseFloat(cmds[j].extrusion)/(cmds[j].speed/60));
|
||||
}
|
||||
|
||||
printTime += printTimeAdd;
|
||||
if(typeof(printTimeByLayer[cmds[j].prevZ])==='undefined'){printTimeByLayer[cmds[j].prevZ]=0;}
|
||||
printTimeByLayer[cmds[j].prevZ] += printTimeAdd;
|
||||
|
||||
if(cmds[j].extrude&&cmds[j].retract===0){
|
||||
type = 'extrude';
|
||||
}else if(cmds[j].retract!==0){
|
||||
type = 'retract';
|
||||
}else if(!cmds[j].extrude&&cmds[j].retract===0){
|
||||
type = 'move';
|
||||
// if(cmds[j].prevZ == '17.1'){
|
||||
// self.postMessage({cmd: 'Got speed ' + cmds[j].speed + 'with line ' + cmds[j].gcodeLine});
|
||||
// }
|
||||
}else {
|
||||
self.postMessage({cmd: 'unknown type of move'});
|
||||
type = 'unknown';
|
||||
}
|
||||
speedIndex = speeds[type].indexOf(cmds[j].speed);
|
||||
if (speedIndex === -1) {
|
||||
speeds[type].push(cmds[j].speed);
|
||||
speedIndex = speeds[type].indexOf(cmds[j].speed);
|
||||
}
|
||||
if(typeof(speedsByLayer[type][cmds[j].prevZ]) === 'undefined'){
|
||||
speedsByLayer[type][cmds[j].prevZ] = [];
|
||||
}
|
||||
if(speedsByLayer[type][cmds[j].prevZ].indexOf(cmds[j].speed) === -1){
|
||||
speedsByLayer[type][cmds[j].prevZ][speedIndex] = cmds[j].speed;
|
||||
}
|
||||
|
||||
}
|
||||
sendSizeProgress(i/model.length*100);
|
||||
|
||||
}
|
||||
purgeLayers();
|
||||
|
||||
modelSize.x = Math.abs(max.x - min.x);
|
||||
modelSize.y = Math.abs(max.y - min.y);
|
||||
modelSize.z = Math.abs(max.z - min.z);
|
||||
layerHeight = (max.z-min.z)/(layerCnt-1);
|
||||
|
||||
sendAnalyzeDone();
|
||||
};
|
||||
|
||||
var doParse = function(){
|
||||
var argChar, numSlice;
|
||||
model=[];
|
||||
var sendLayer = undefined;
|
||||
var sendLayerZ = 0;
|
||||
var sendMultiLayer = [];
|
||||
var sendMultiLayerZ = [];
|
||||
var lastSend = 0;
|
||||
// console.time("parseGCode timer");
|
||||
var reg = new RegExp(/^(?:G0|G1)\s/i);
|
||||
var comment = new RegExp()
|
||||
var j, layer= 0, extrude=false, prevRetract= 0, retract=0, x, y, z=0, f, prevZ=0, prevX, prevY,lastF=4000, prev_extrude = {a: undefined, b: undefined, c: undefined, e: undefined, abs: undefined}, extrudeRelative=false;
|
||||
var dcExtrude=false;
|
||||
var assumeNonDC = false;
|
||||
|
||||
for(var i=0;i<gcode.length;i++){
|
||||
x=undefined;
|
||||
y=undefined;
|
||||
z=undefined;
|
||||
retract = 0;
|
||||
|
||||
var line = gcode[i].line;
|
||||
var percentage = gcode[i].percentage;
|
||||
|
||||
extrude=false;
|
||||
line = line.split(/[\(;]/)[0];
|
||||
|
||||
if(reg.test(line)){
|
||||
var args = line.split(/\s/);
|
||||
for(j=0;j<args.length;j++){
|
||||
switch(argChar = args[j].charAt(0).toLowerCase()){
|
||||
case 'x':
|
||||
x=args[j].slice(1);
|
||||
break;
|
||||
case 'y':
|
||||
y=args[j].slice(1);
|
||||
break;
|
||||
case 'z':
|
||||
z=args[j].slice(1);
|
||||
z = Number(z);
|
||||
if(z == prevZ) continue;
|
||||
if(z_heights.hasOwnProperty(z)){
|
||||
layer = z_heights[z];
|
||||
}else{
|
||||
layer = model.length;
|
||||
z_heights[z] = layer;
|
||||
}
|
||||
sendLayer = layer;
|
||||
sendLayerZ = z;
|
||||
prevZ = z;
|
||||
break;
|
||||
case 'e':
|
||||
case 'a':
|
||||
case 'b':
|
||||
case 'c':
|
||||
assumeNonDC = true;
|
||||
numSlice = parseFloat(args[j].slice(1)).toFixed(3);
|
||||
|
||||
if(!extrudeRelative){
|
||||
// absolute extrusion positioning
|
||||
prev_extrude["abs"] = parseFloat(numSlice)-parseFloat(prev_extrude[argChar]);
|
||||
|
||||
}else{
|
||||
prev_extrude["abs"] = parseFloat(numSlice);
|
||||
}
|
||||
extrude = prev_extrude["abs"]>0;
|
||||
if(prev_extrude["abs"]<0){
|
||||
prevRetract = -1;
|
||||
retract = -1;
|
||||
}
|
||||
else if(prev_extrude["abs"]==0){
|
||||
retract = 0;
|
||||
}else if(prev_extrude["abs"]>0&&prevRetract < 0){
|
||||
prevRetract = 0;
|
||||
retract = 1;
|
||||
} else {
|
||||
retract = 0;
|
||||
}
|
||||
prev_extrude[argChar] = numSlice;
|
||||
|
||||
break;
|
||||
case 'f':
|
||||
numSlice = args[j].slice(1);
|
||||
lastF = numSlice;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(dcExtrude&&!assumeNonDC){
|
||||
extrude = true;
|
||||
prev_extrude["abs"] = Math.sqrt((prevX-x)*(prevX-x)+(prevY-y)*(prevY-y));
|
||||
}
|
||||
if(!model[layer])model[layer]=[];
|
||||
if(typeof(x) !== 'undefined' || typeof(y) !== 'undefined' ||typeof(z) !== 'undefined'||retract!=0) model[layer][model[layer].length] = {x: Number(x), y: Number(y), z: Number(z), extrude: extrude, retract: Number(retract), noMove: false, extrusion: (extrude||retract)?Number(prev_extrude["abs"]):0, prevX: Number(prevX), prevY: Number(prevY), prevZ: Number(prevZ), speed: Number(lastF), gcodeLine: Number(i), percentage: percentage};
|
||||
//{x: x, y: y, z: z, extrude: extrude, retract: retract, noMove: false, extrusion: (extrude||retract)?prev_extrude["abs"]:0, prevX: prevX, prevY: prevY, prevZ: prevZ, speed: lastF, gcodeLine: i};
|
||||
if(typeof(x) !== 'undefined') prevX = x;
|
||||
if(typeof(y) !== 'undefined') prevY = y;
|
||||
} else if(line.match(/^(?:M82)/i)){
|
||||
extrudeRelative = false;
|
||||
}else if(line.match(/^(?:G91)/i)){
|
||||
extrudeRelative=true;
|
||||
}else if(line.match(/^(?:G90)/i)){
|
||||
extrudeRelative=false;
|
||||
}else if(line.match(/^(?:M83)/i)){
|
||||
extrudeRelative=true;
|
||||
}else if(line.match(/^(?:M101)/i)){
|
||||
dcExtrude=true;
|
||||
}else if(line.match(/^(?:M103)/i)){
|
||||
dcExtrude=false;
|
||||
}else if(line.match(/^(?:G92)/i)){
|
||||
var args = line.split(/\s/);
|
||||
for(j=0;j<args.length;j++){
|
||||
switch(argChar = args[j].charAt(0).toLowerCase()){
|
||||
case 'x':
|
||||
x=args[j].slice(1);
|
||||
break;
|
||||
case 'y':
|
||||
y=args[j].slice(1);
|
||||
break;
|
||||
case 'z':
|
||||
z=args[j].slice(1);
|
||||
prevZ = z;
|
||||
break;
|
||||
case 'e'||'a'||'b'||'c':
|
||||
numSlice = args[j].slice(1);
|
||||
if(!extrudeRelative)
|
||||
prev_extrude[argChar] = 0;
|
||||
else {
|
||||
prev_extrude[argChar] = numSlice;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!model[layer])model[layer]=[];
|
||||
if(typeof(x) !== 'undefined' || typeof(y) !== 'undefined' ||typeof(z) !== 'undefined') model[layer][model[layer].length] = {x: parseFloat(x), y: parseFloat(y), z: parseFloat(z), extrude: extrude, retract: parseFloat(retract), noMove: true, extrusion: (extrude||retract)?parseFloat(prev_extrude["abs"]):0, prevX: parseFloat(prevX), prevY: parseFloat(prevY), prevZ: parseFloat(prevZ), speed: parseFloat(lastF),gcodeLine: parseFloat(i), percentage: percentage};
|
||||
}else if(line.match(/^(?:G28)/i)){
|
||||
var args = line.split(/\s/);
|
||||
for(j=0;j<args.length;j++){
|
||||
switch(argChar = args[j].charAt(0).toLowerCase()){
|
||||
case 'x':
|
||||
x=args[j].slice(1);
|
||||
break;
|
||||
case 'y':
|
||||
y=args[j].slice(1);
|
||||
break;
|
||||
case 'z':
|
||||
z=args[j].slice(1);
|
||||
z = Number(z);
|
||||
if(z === prevZ)continue;
|
||||
sendLayer = layer;
|
||||
sendLayerZ = z;//}
|
||||
if(z_heights.hasOwnProperty(z)){
|
||||
layer = z_heights[z];
|
||||
}else{
|
||||
layer = model.length;
|
||||
z_heights[z] = layer;
|
||||
}
|
||||
prevZ = z;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
// G28 with no arguments
|
||||
if(args.length == 1){
|
||||
//need to init values to default here
|
||||
}
|
||||
// if it's the first layer and G28 was without
|
||||
if(layer==0&&typeof(z) === 'undefined'){
|
||||
z=0;
|
||||
if(z_heights.hasOwnProperty(z)){
|
||||
layer = z_heights[z];
|
||||
}else{
|
||||
layer = model.length;
|
||||
z_heights[z] = layer;
|
||||
}
|
||||
prevZ = z;
|
||||
}
|
||||
|
||||
if(!model[layer])model[layer]=[];
|
||||
if(typeof(x) !== 'undefined' || typeof(y) !== 'undefined' ||typeof(z) !== 'undefined'||retract!=0) model[layer][model[layer].length] = {x: Number(x), y: Number(y), z: Number(z), extrude: extrude, retract: Number(retract), noMove: false, extrusion: (extrude||retract)?Number(prev_extrude["abs"]):0, prevX: Number(prevX), prevY: Number(prevY), prevZ: Number(prevZ), speed: Number(lastF), gcodeLine: Number(i), percentage: percentage};
|
||||
}
|
||||
if(typeof(sendLayer) !== "undefined"){
|
||||
|
||||
if(i-lastSend > gcode.length*0.02 && sendMultiLayer.length != 0){
|
||||
lastSend = i;
|
||||
sendMultiLayerToParent(sendMultiLayer, sendMultiLayerZ, i/gcode.length*100);
|
||||
sendMultiLayer = [];
|
||||
sendMultiLayerZ = [];
|
||||
}
|
||||
sendMultiLayer[sendMultiLayer.length] = sendLayer;
|
||||
sendMultiLayerZ[sendMultiLayerZ.length] = sendLayerZ;
|
||||
sendLayer = undefined;
|
||||
sendLayerZ = undefined;
|
||||
}
|
||||
}
|
||||
sendMultiLayerToParent(sendMultiLayer, sendMultiLayerZ, i/gcode.length*100);
|
||||
};
|
||||
|
||||
|
||||
var parseGCode = function(message){
|
||||
gcode = message.gcode;
|
||||
firstReport = message.options.firstReport;
|
||||
|
||||
|
||||
doParse();
|
||||
gcode = [];
|
||||
self.postMessage({
|
||||
"cmd": "returnModel",
|
||||
"msg": {
|
||||
// model: model
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
var runAnalyze = function(message){
|
||||
analyzeModel();
|
||||
model = [];
|
||||
z_heights = [];
|
||||
gcode = undefined;
|
||||
firstReport = undefined;
|
||||
z_heights = {};
|
||||
model = [];
|
||||
max = {x: undefined, y: undefined, z: undefined};
|
||||
min = {x: undefined, y: undefined, z: undefined};
|
||||
modelSize = {x: undefined, y: undefined, z: undefined};
|
||||
filamentByLayer = {};
|
||||
totalFilament=0;
|
||||
printTime=0;
|
||||
printTimeByLayer = {};
|
||||
layerHeight=0;
|
||||
layerCnt = 0;
|
||||
speeds = {extrude: [], retract: [], move: []};
|
||||
speedsByLayer = {extrude: {}, retract: {}, move: {}};
|
||||
};
|
||||
var setOption = function(options){
|
||||
for(var opt in options){
|
||||
gCodeOptions[opt] = options[opt];
|
||||
}
|
||||
};
|
||||
|
||||
onmessage = function (e){
|
||||
var data = e.data;
|
||||
// for some reason firefox doesn't garbage collect when something inside closures is deleted, so we delete and recreate whole object eaech time
|
||||
switch (data.cmd) {
|
||||
case 'parseGCode':
|
||||
parseGCode(data.msg);
|
||||
break;
|
||||
case 'setOption':
|
||||
setOption(data.msg);
|
||||
break;
|
||||
case 'analyzeModel':
|
||||
runAnalyze(data.msg);
|
||||
break;
|
||||
|
||||
default:
|
||||
self.postMessage('Unknown command: ' + data.msg);
|
||||
}
|
||||
|
||||
};
|
||||
/**
|
||||
* User: hudbrog (hudbrog@gmail.com)
|
||||
* Date: 10/24/12
|
||||
* Time: 12:18 PM
|
||||
*/
|
||||
|
||||
var gcode;
|
||||
var firstReport;
|
||||
var z_heights = {};
|
||||
var model = [];
|
||||
var gCodeOptions = {
|
||||
sortLayers: false,
|
||||
purgeEmptyLayers: true,
|
||||
analyzeModel: false
|
||||
};
|
||||
var max = {x: undefined, y: undefined, z: undefined};
|
||||
var min = {x: undefined, y: undefined, z: undefined};
|
||||
var modelSize = {x: undefined, y: undefined, z: undefined};
|
||||
var filamentByLayer = {};
|
||||
var totalFilament=0;
|
||||
var printTime=0;
|
||||
var printTimeByLayer = {};
|
||||
var layerHeight=0;
|
||||
var layerCnt = 0;
|
||||
var speeds = {extrude: [], retract: [], move: []};
|
||||
var speedsByLayer = {extrude: {}, retract: {}, move: {}};
|
||||
|
||||
|
||||
|
||||
var sendLayerToParent = function(layerNum, z, progress){
|
||||
self.postMessage({
|
||||
"cmd": "returnLayer",
|
||||
"msg": {
|
||||
cmds: model[layerNum],
|
||||
layerNum: layerNum,
|
||||
zHeightObject: {zValue: z, layer: z_heights[z]},
|
||||
isEmpty: false,
|
||||
progress: progress
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var sendMultiLayerToParent = function(layerNum, z, progress){
|
||||
var tmpModel = [];
|
||||
var tmpZHeight = {};
|
||||
|
||||
for(var i=0;i<layerNum.length;i++){
|
||||
tmpModel[layerNum[i]] = model[layerNum[i]];
|
||||
tmpZHeight[layerNum[i]] = z_heights[z[i]];
|
||||
}
|
||||
|
||||
self.postMessage({
|
||||
"cmd": "returnMultiLayer",
|
||||
"msg": {
|
||||
model: tmpModel,
|
||||
layerNum: layerNum,
|
||||
zHeightObject: {zValue: z, layer: tmpZHeight},
|
||||
isEmpty: false,
|
||||
progress: progress
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
var sendSizeProgress = function(progress){
|
||||
self.postMessage({
|
||||
"cmd": "analyzeProgress",
|
||||
"msg": {
|
||||
progress: progress,
|
||||
printTime: printTime
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var sendAnalyzeDone = function(){
|
||||
self.postMessage({
|
||||
"cmd": "analyzeDone",
|
||||
"msg": {
|
||||
max: max,
|
||||
min: min,
|
||||
modelSize: modelSize,
|
||||
totalFilament:totalFilament,
|
||||
filamentByLayer: filamentByLayer,
|
||||
printTime: printTime,
|
||||
layerHeight: layerHeight,
|
||||
layerCnt: layerCnt,
|
||||
layerTotal: model.length,
|
||||
speeds: speeds,
|
||||
speedsByLayer: speedsByLayer,
|
||||
printTimeByLayer: printTimeByLayer
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var purgeLayers = function(){
|
||||
var purge=true;
|
||||
for(var i=0;i<model.length;i++){
|
||||
purge=true;
|
||||
if(!model[i])purge=true;
|
||||
else {
|
||||
for(var j=0;j<model[i].length;j++){
|
||||
if(model[i][j].extrude)purge=false;
|
||||
}
|
||||
}
|
||||
if(!purge){
|
||||
layerCnt+=1;
|
||||
}
|
||||
}
|
||||
// self.postMessage('LayerCnt: ' + layerCnt);
|
||||
};
|
||||
|
||||
|
||||
var analyzeModel = function(){
|
||||
var i,j;
|
||||
var x_ok=false, y_ok=false;
|
||||
var cmds;
|
||||
var tmp1= 0, tmp2=0;
|
||||
var speedIndex=0;
|
||||
var type;
|
||||
var printTimeAdd=0;
|
||||
// var moveTime=0;
|
||||
|
||||
for(i=0;i<model.length;i++){
|
||||
cmds = model[i];
|
||||
if(!cmds)continue;
|
||||
for(j=0;j<cmds.length;j++){
|
||||
x_ok=false;
|
||||
y_ok=false;
|
||||
if(typeof(cmds[j].x) !== 'undefined'&&typeof(cmds[j].prevX) !== 'undefined'&&typeof(cmds[j].extrude) !== 'undefined'&&cmds[j].extrude&&!isNaN(cmds[j].x))
|
||||
{
|
||||
max.x = parseFloat(max.x)>parseFloat(cmds[j].x)?parseFloat(max.x):parseFloat(cmds[j].x);
|
||||
max.x = parseFloat(max.x)>parseFloat(cmds[j].prevX)?parseFloat(max.x):parseFloat(cmds[j].prevX);
|
||||
min.x = parseFloat(min.x)<parseFloat(cmds[j].x)?parseFloat(min.x):parseFloat(cmds[j].x);
|
||||
min.x = parseFloat(min.x)<parseFloat(cmds[j].prevX)?parseFloat(min.x):parseFloat(cmds[j].prevX);
|
||||
x_ok=true;
|
||||
}
|
||||
|
||||
if(typeof(cmds[j].y) !== 'undefined'&&typeof(cmds[j].prevY) !== 'undefined'&&typeof(cmds[j].extrude) !== 'undefined'&&cmds[j].extrude&&!isNaN(cmds[j].y)){
|
||||
max.y = parseFloat(max.y)>parseFloat(cmds[j].y)?parseFloat(max.y):parseFloat(cmds[j].y);
|
||||
max.y = parseFloat(max.y)>parseFloat(cmds[j].prevY)?parseFloat(max.y):parseFloat(cmds[j].prevY);
|
||||
min.y = parseFloat(min.y)<parseFloat(cmds[j].y)?parseFloat(min.y):parseFloat(cmds[j].y);
|
||||
min.y = parseFloat(min.y)<parseFloat(cmds[j].prevY)?parseFloat(min.y):parseFloat(cmds[j].prevY);
|
||||
y_ok=true;
|
||||
}
|
||||
|
||||
if(typeof(cmds[j].prevZ) !== 'undefined'&&typeof(cmds[j].extrude) !== 'undefined'&&cmds[j].extrude&&!isNaN(cmds[j].prevZ)){
|
||||
max.z = parseFloat(max.z)>parseFloat(cmds[j].prevZ)?parseFloat(max.z):parseFloat(cmds[j].prevZ);
|
||||
min.z = parseFloat(min.z)<parseFloat(cmds[j].prevZ)?parseFloat(min.z):parseFloat(cmds[j].prevZ);
|
||||
}
|
||||
|
||||
if(typeof(cmds[j].extrude) !== 'undefined'||cmds[j].retract!=0){
|
||||
totalFilament+=cmds[j].extrusion;
|
||||
if(!filamentByLayer[cmds[j].prevZ])filamentByLayer[cmds[j].prevZ]=0;
|
||||
filamentByLayer[cmds[j].prevZ]+=cmds[j].extrusion;
|
||||
}
|
||||
|
||||
if(x_ok&&y_ok){
|
||||
printTimeAdd = Math.sqrt(Math.pow(parseFloat(cmds[j].x)-parseFloat(cmds[j].prevX),2)+Math.pow(parseFloat(cmds[j].y)-parseFloat(cmds[j].prevY),2))/(cmds[j].speed/60);
|
||||
}else if(cmds[j].retract===0&&cmds[j].extrusion!==0){
|
||||
tmp1 = Math.sqrt(Math.pow(parseFloat(cmds[j].x)-parseFloat(cmds[j].prevX),2)+Math.pow(parseFloat(cmds[j].y)-parseFloat(cmds[j].prevY),2))/(cmds[j].speed/60);
|
||||
tmp2 = Math.abs(parseFloat(cmds[j].extrusion)/(cmds[j].speed/60));
|
||||
printTimeAdd = tmp1>=tmp2?tmp1:tmp2;
|
||||
}else if(cmds[j].retract!==0){
|
||||
printTimeAdd = Math.abs(parseFloat(cmds[j].extrusion)/(cmds[j].speed/60));
|
||||
}
|
||||
|
||||
printTime += printTimeAdd;
|
||||
if(typeof(printTimeByLayer[cmds[j].prevZ])==='undefined'){printTimeByLayer[cmds[j].prevZ]=0;}
|
||||
printTimeByLayer[cmds[j].prevZ] += printTimeAdd;
|
||||
|
||||
if(cmds[j].extrude&&cmds[j].retract===0){
|
||||
type = 'extrude';
|
||||
}else if(cmds[j].retract!==0){
|
||||
type = 'retract';
|
||||
}else if(!cmds[j].extrude&&cmds[j].retract===0){
|
||||
type = 'move';
|
||||
// if(cmds[j].prevZ == '17.1'){
|
||||
// self.postMessage({cmd: 'Got speed ' + cmds[j].speed + 'with line ' + cmds[j].gcodeLine});
|
||||
// }
|
||||
}else {
|
||||
self.postMessage({cmd: 'unknown type of move'});
|
||||
type = 'unknown';
|
||||
}
|
||||
speedIndex = speeds[type].indexOf(cmds[j].speed);
|
||||
if (speedIndex === -1) {
|
||||
speeds[type].push(cmds[j].speed);
|
||||
speedIndex = speeds[type].indexOf(cmds[j].speed);
|
||||
}
|
||||
if(typeof(speedsByLayer[type][cmds[j].prevZ]) === 'undefined'){
|
||||
speedsByLayer[type][cmds[j].prevZ] = [];
|
||||
}
|
||||
if(speedsByLayer[type][cmds[j].prevZ].indexOf(cmds[j].speed) === -1){
|
||||
speedsByLayer[type][cmds[j].prevZ][speedIndex] = cmds[j].speed;
|
||||
}
|
||||
|
||||
}
|
||||
sendSizeProgress(i/model.length*100);
|
||||
|
||||
}
|
||||
purgeLayers();
|
||||
|
||||
modelSize.x = Math.abs(max.x - min.x);
|
||||
modelSize.y = Math.abs(max.y - min.y);
|
||||
modelSize.z = Math.abs(max.z - min.z);
|
||||
layerHeight = (max.z-min.z)/(layerCnt-1);
|
||||
|
||||
sendAnalyzeDone();
|
||||
};
|
||||
|
||||
var doParse = function(){
|
||||
var argChar, numSlice;
|
||||
model=[];
|
||||
var sendLayer = undefined;
|
||||
var sendLayerZ = 0;
|
||||
var sendMultiLayer = [];
|
||||
var sendMultiLayerZ = [];
|
||||
var lastSend = 0;
|
||||
// console.time("parseGCode timer");
|
||||
var reg = new RegExp(/^(?:G0|G1)\s/i);
|
||||
var comment = new RegExp()
|
||||
var j, layer= 0, extrude=false, prevRetract= 0, retract=0, x, y, z=0, f, prevZ=0, prevX, prevY,lastF=4000, prev_extrude = {a: undefined, b: undefined, c: undefined, e: undefined, abs: undefined}, extrudeRelative=false;
|
||||
var dcExtrude=false;
|
||||
var assumeNonDC = false;
|
||||
|
||||
for(var i=0;i<gcode.length;i++){
|
||||
x=undefined;
|
||||
y=undefined;
|
||||
z=undefined;
|
||||
retract = 0;
|
||||
|
||||
var line = gcode[i].line;
|
||||
var percentage = gcode[i].percentage;
|
||||
|
||||
extrude=false;
|
||||
line = line.split(/[\(;]/)[0];
|
||||
|
||||
if(reg.test(line)){
|
||||
var args = line.split(/\s/);
|
||||
for(j=0;j<args.length;j++){
|
||||
switch(argChar = args[j].charAt(0).toLowerCase()){
|
||||
case 'x':
|
||||
x=args[j].slice(1);
|
||||
break;
|
||||
case 'y':
|
||||
y=args[j].slice(1);
|
||||
break;
|
||||
case 'z':
|
||||
z=args[j].slice(1);
|
||||
z = Number(z);
|
||||
if(z == prevZ) continue;
|
||||
if(z_heights.hasOwnProperty(z)){
|
||||
layer = z_heights[z];
|
||||
}else{
|
||||
layer = model.length;
|
||||
z_heights[z] = layer;
|
||||
}
|
||||
sendLayer = layer;
|
||||
sendLayerZ = z;
|
||||
prevZ = z;
|
||||
break;
|
||||
case 'e':
|
||||
case 'a':
|
||||
case 'b':
|
||||
case 'c':
|
||||
assumeNonDC = true;
|
||||
numSlice = parseFloat(args[j].slice(1)).toFixed(3);
|
||||
|
||||
if(!extrudeRelative){
|
||||
// absolute extrusion positioning
|
||||
prev_extrude["abs"] = parseFloat(numSlice)-parseFloat(prev_extrude[argChar]);
|
||||
|
||||
}else{
|
||||
prev_extrude["abs"] = parseFloat(numSlice);
|
||||
}
|
||||
extrude = prev_extrude["abs"]>0;
|
||||
if(prev_extrude["abs"]<0){
|
||||
prevRetract = -1;
|
||||
retract = -1;
|
||||
}
|
||||
else if(prev_extrude["abs"]==0){
|
||||
retract = 0;
|
||||
}else if(prev_extrude["abs"]>0&&prevRetract < 0){
|
||||
prevRetract = 0;
|
||||
retract = 1;
|
||||
} else {
|
||||
retract = 0;
|
||||
}
|
||||
prev_extrude[argChar] = numSlice;
|
||||
|
||||
break;
|
||||
case 'f':
|
||||
numSlice = args[j].slice(1);
|
||||
lastF = numSlice;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(dcExtrude&&!assumeNonDC){
|
||||
extrude = true;
|
||||
prev_extrude["abs"] = Math.sqrt((prevX-x)*(prevX-x)+(prevY-y)*(prevY-y));
|
||||
}
|
||||
if(!model[layer])model[layer]=[];
|
||||
if(typeof(x) !== 'undefined' || typeof(y) !== 'undefined' ||typeof(z) !== 'undefined'||retract!=0) model[layer][model[layer].length] = {x: Number(x), y: Number(y), z: Number(z), extrude: extrude, retract: Number(retract), noMove: false, extrusion: (extrude||retract)?Number(prev_extrude["abs"]):0, prevX: Number(prevX), prevY: Number(prevY), prevZ: Number(prevZ), speed: Number(lastF), gcodeLine: Number(i), percentage: percentage};
|
||||
//{x: x, y: y, z: z, extrude: extrude, retract: retract, noMove: false, extrusion: (extrude||retract)?prev_extrude["abs"]:0, prevX: prevX, prevY: prevY, prevZ: prevZ, speed: lastF, gcodeLine: i};
|
||||
if(typeof(x) !== 'undefined') prevX = x;
|
||||
if(typeof(y) !== 'undefined') prevY = y;
|
||||
} else if(line.match(/^(?:M82)/i)){
|
||||
extrudeRelative = false;
|
||||
}else if(line.match(/^(?:G91)/i)){
|
||||
extrudeRelative=true;
|
||||
}else if(line.match(/^(?:G90)/i)){
|
||||
extrudeRelative=false;
|
||||
}else if(line.match(/^(?:M83)/i)){
|
||||
extrudeRelative=true;
|
||||
}else if(line.match(/^(?:M101)/i)){
|
||||
dcExtrude=true;
|
||||
}else if(line.match(/^(?:M103)/i)){
|
||||
dcExtrude=false;
|
||||
}else if(line.match(/^(?:G92)/i)){
|
||||
var args = line.split(/\s/);
|
||||
for(j=0;j<args.length;j++){
|
||||
switch(argChar = args[j].charAt(0).toLowerCase()){
|
||||
case 'x':
|
||||
x=args[j].slice(1);
|
||||
break;
|
||||
case 'y':
|
||||
y=args[j].slice(1);
|
||||
break;
|
||||
case 'z':
|
||||
z=args[j].slice(1);
|
||||
prevZ = z;
|
||||
break;
|
||||
case 'e'||'a'||'b'||'c':
|
||||
numSlice = args[j].slice(1);
|
||||
if(!extrudeRelative)
|
||||
prev_extrude[argChar] = 0;
|
||||
else {
|
||||
prev_extrude[argChar] = numSlice;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!model[layer])model[layer]=[];
|
||||
if(typeof(x) !== 'undefined' || typeof(y) !== 'undefined' ||typeof(z) !== 'undefined') model[layer][model[layer].length] = {x: parseFloat(x), y: parseFloat(y), z: parseFloat(z), extrude: extrude, retract: parseFloat(retract), noMove: true, extrusion: (extrude||retract)?parseFloat(prev_extrude["abs"]):0, prevX: parseFloat(prevX), prevY: parseFloat(prevY), prevZ: parseFloat(prevZ), speed: parseFloat(lastF),gcodeLine: parseFloat(i), percentage: percentage};
|
||||
}else if(line.match(/^(?:G28)/i)){
|
||||
var args = line.split(/\s/);
|
||||
for(j=0;j<args.length;j++){
|
||||
switch(argChar = args[j].charAt(0).toLowerCase()){
|
||||
case 'x':
|
||||
x=args[j].slice(1);
|
||||
break;
|
||||
case 'y':
|
||||
y=args[j].slice(1);
|
||||
break;
|
||||
case 'z':
|
||||
z=args[j].slice(1);
|
||||
z = Number(z);
|
||||
if(z === prevZ)continue;
|
||||
sendLayer = layer;
|
||||
sendLayerZ = z;//}
|
||||
if(z_heights.hasOwnProperty(z)){
|
||||
layer = z_heights[z];
|
||||
}else{
|
||||
layer = model.length;
|
||||
z_heights[z] = layer;
|
||||
}
|
||||
prevZ = z;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
// G28 with no arguments
|
||||
if(args.length == 1){
|
||||
//need to init values to default here
|
||||
}
|
||||
// if it's the first layer and G28 was without
|
||||
if(layer==0&&typeof(z) === 'undefined'){
|
||||
z=0;
|
||||
if(z_heights.hasOwnProperty(z)){
|
||||
layer = z_heights[z];
|
||||
}else{
|
||||
layer = model.length;
|
||||
z_heights[z] = layer;
|
||||
}
|
||||
prevZ = z;
|
||||
}
|
||||
|
||||
if(!model[layer])model[layer]=[];
|
||||
if(typeof(x) !== 'undefined' || typeof(y) !== 'undefined' ||typeof(z) !== 'undefined'||retract!=0) model[layer][model[layer].length] = {x: Number(x), y: Number(y), z: Number(z), extrude: extrude, retract: Number(retract), noMove: false, extrusion: (extrude||retract)?Number(prev_extrude["abs"]):0, prevX: Number(prevX), prevY: Number(prevY), prevZ: Number(prevZ), speed: Number(lastF), gcodeLine: Number(i), percentage: percentage};
|
||||
}
|
||||
if(typeof(sendLayer) !== "undefined"){
|
||||
|
||||
if(i-lastSend > gcode.length*0.02 && sendMultiLayer.length != 0){
|
||||
lastSend = i;
|
||||
sendMultiLayerToParent(sendMultiLayer, sendMultiLayerZ, i/gcode.length*100);
|
||||
sendMultiLayer = [];
|
||||
sendMultiLayerZ = [];
|
||||
}
|
||||
sendMultiLayer[sendMultiLayer.length] = sendLayer;
|
||||
sendMultiLayerZ[sendMultiLayerZ.length] = sendLayerZ;
|
||||
sendLayer = undefined;
|
||||
sendLayerZ = undefined;
|
||||
}
|
||||
}
|
||||
sendMultiLayerToParent(sendMultiLayer, sendMultiLayerZ, i/gcode.length*100);
|
||||
};
|
||||
|
||||
|
||||
var parseGCode = function(message){
|
||||
gcode = message.gcode;
|
||||
firstReport = message.options.firstReport;
|
||||
|
||||
|
||||
doParse();
|
||||
gcode = [];
|
||||
self.postMessage({
|
||||
"cmd": "returnModel",
|
||||
"msg": {
|
||||
// model: model
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
var runAnalyze = function(message){
|
||||
analyzeModel();
|
||||
model = [];
|
||||
z_heights = [];
|
||||
gcode = undefined;
|
||||
firstReport = undefined;
|
||||
z_heights = {};
|
||||
model = [];
|
||||
max = {x: undefined, y: undefined, z: undefined};
|
||||
min = {x: undefined, y: undefined, z: undefined};
|
||||
modelSize = {x: undefined, y: undefined, z: undefined};
|
||||
filamentByLayer = {};
|
||||
totalFilament=0;
|
||||
printTime=0;
|
||||
printTimeByLayer = {};
|
||||
layerHeight=0;
|
||||
layerCnt = 0;
|
||||
speeds = {extrude: [], retract: [], move: []};
|
||||
speedsByLayer = {extrude: {}, retract: {}, move: {}};
|
||||
};
|
||||
var setOption = function(options){
|
||||
for(var opt in options){
|
||||
gCodeOptions[opt] = options[opt];
|
||||
}
|
||||
};
|
||||
|
||||
onmessage = function (e){
|
||||
var data = e.data;
|
||||
// for some reason firefox doesn't garbage collect when something inside closures is deleted, so we delete and recreate whole object eaech time
|
||||
switch (data.cmd) {
|
||||
case 'parseGCode':
|
||||
parseGCode(data.msg);
|
||||
break;
|
||||
case 'setOption':
|
||||
setOption(data.msg);
|
||||
break;
|
||||
case 'analyzeModel':
|
||||
runAnalyze(data.msg);
|
||||
break;
|
||||
|
||||
default:
|
||||
self.postMessage('Unknown command: ' + data.msg);
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -1,207 +1,207 @@
|
|||
/**
|
||||
* User: hudbrog (hudbrog@gmail.com)
|
||||
* Date: 10/21/12
|
||||
* Time: 7:31 AM
|
||||
*/
|
||||
|
||||
GCODE.gCodeReader = (function(){
|
||||
// ***** PRIVATE ******
|
||||
var gcode, lines;
|
||||
var z_heights = {};
|
||||
var model = [];
|
||||
var max = {x: undefined, y: undefined, z: undefined};
|
||||
var min = {x: undefined, y: undefined, z: undefined};
|
||||
var modelSize = {x: undefined, y: undefined, z: undefined};
|
||||
var filamentByLayer = {};
|
||||
var printTimeByLayer;
|
||||
var totalFilament=0;
|
||||
var printTime=0;
|
||||
var speeds = {};
|
||||
var speedsByLayer = {};
|
||||
var gCodeOptions = {
|
||||
sortLayers: false,
|
||||
purgeEmptyLayers: true,
|
||||
analyzeModel: false
|
||||
};
|
||||
|
||||
var percentageTree = undefined;
|
||||
|
||||
var prepareGCode = function(totalSize){
|
||||
if(!lines)return;
|
||||
gcode = [];
|
||||
var i, tmp, byteCount;
|
||||
|
||||
byteCount = 0;
|
||||
for(i=0;i<lines.length;i++){
|
||||
byteCount += lines[i].length + 1; // line length + \n
|
||||
tmp = lines[i].indexOf(";");
|
||||
if(tmp > 1 || tmp === -1) {
|
||||
gcode.push({line: lines[i], percentage: byteCount * 100 / totalSize});
|
||||
}
|
||||
}
|
||||
lines = [];
|
||||
};
|
||||
|
||||
var sortLayers = function(){
|
||||
var sortedZ = [];
|
||||
var tmpModel = [];
|
||||
|
||||
for(var layer in z_heights){
|
||||
sortedZ[z_heights[layer]] = layer;
|
||||
}
|
||||
|
||||
sortedZ.sort(function(a,b){
|
||||
return a-b;
|
||||
});
|
||||
|
||||
for(var i=0;i<sortedZ.length;i++){
|
||||
if(typeof(z_heights[sortedZ[i]]) === 'undefined')continue;
|
||||
tmpModel[i] = model[z_heights[sortedZ[i]]];
|
||||
}
|
||||
model = tmpModel;
|
||||
delete tmpModel;
|
||||
};
|
||||
|
||||
var prepareLinesIndex = function(){
|
||||
percentageTree = undefined;
|
||||
|
||||
for (var l in model) {
|
||||
for (var i=0; i< model[l].length; i++) {
|
||||
var percentage = model[l][i].percentage;
|
||||
var value = {layer: l, cmd: i};
|
||||
if (!percentageTree) {
|
||||
percentageTree = new AVLTree({key: percentage, value: value}, "key");
|
||||
} else {
|
||||
percentageTree.add({key: percentage, value: value});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var searchInPercentageTree = function(key) {
|
||||
if (percentageTree === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var elements = percentageTree.findBest(key);
|
||||
if (elements.length == 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return elements[0];
|
||||
};
|
||||
|
||||
var purgeLayers = function(){
|
||||
var purge=true;
|
||||
if(!model){
|
||||
console.log("Something terribly wring just happened.");
|
||||
return;
|
||||
}
|
||||
for(var i=0;i<model.length;i++){
|
||||
purge=true;
|
||||
if(typeof(model[i])==='undefined')purge=true;
|
||||
else {
|
||||
for(var j=0;j<model[i].length;j++){
|
||||
if(model[i][j].extrude)purge=false;
|
||||
}
|
||||
}
|
||||
if(purge){
|
||||
model.splice(i,1);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
// ***** PUBLIC *******
|
||||
return {
|
||||
|
||||
loadFile: function(reader){
|
||||
model = [];
|
||||
z_heights = [];
|
||||
|
||||
var totalSize = reader.target.result.length;
|
||||
lines = reader.target.result.split(/\n/);
|
||||
reader.target.result = null;
|
||||
prepareGCode(totalSize);
|
||||
|
||||
worker.postMessage({
|
||||
"cmd":"parseGCode",
|
||||
"msg":{
|
||||
gcode: gcode,
|
||||
options: {
|
||||
firstReport: 5
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
delete lines;
|
||||
delete gcode;
|
||||
},
|
||||
setOption: function(options){
|
||||
for(var opt in options){
|
||||
gCodeOptions[opt] = options[opt];
|
||||
}
|
||||
},
|
||||
passDataToRenderer: function(){
|
||||
if(gCodeOptions["sortLayers"])sortLayers();
|
||||
if(gCodeOptions["purgeEmptyLayers"])purgeLayers();
|
||||
prepareLinesIndex();
|
||||
GCODE.renderer.doRender(model, 0);
|
||||
|
||||
},
|
||||
processLayerFromWorker: function(msg){
|
||||
model[msg.layerNum] = msg.cmds;
|
||||
z_heights[msg.zHeightObject.zValue] = msg.zHeightObject.layer;
|
||||
},
|
||||
processMultiLayerFromWorker: function(msg){
|
||||
for(var i=0;i<msg.layerNum.length;i++){
|
||||
model[msg.layerNum[i]] = msg.model[msg.layerNum[i]];
|
||||
z_heights[msg.zHeightObject.zValue[i]] = msg.layerNum[i];
|
||||
}
|
||||
},
|
||||
processAnalyzeModelDone: function(msg){
|
||||
min = msg.min;
|
||||
max = msg.max;
|
||||
modelSize = msg.modelSize;
|
||||
totalFilament = msg.totalFilament;
|
||||
filamentByLayer = msg.filamentByLayer;
|
||||
speeds = msg.speeds;
|
||||
speedsByLayer = msg.speedsByLayer;
|
||||
printTime = msg.printTime;
|
||||
printTimeByLayer = msg.printTimeByLayer;
|
||||
},
|
||||
getLayerFilament: function(z){
|
||||
return filamentByLayer[z];
|
||||
},
|
||||
getLayerSpeeds: function(z){
|
||||
return speedsByLayer[z]?speedsByLayer[z]:{};
|
||||
},
|
||||
getModelInfo: function(){
|
||||
return {
|
||||
min: min,
|
||||
max: max,
|
||||
modelSize: modelSize,
|
||||
totalFilament: totalFilament,
|
||||
speeds: speeds,
|
||||
speedsByLayer: speedsByLayer,
|
||||
printTime: printTime,
|
||||
printTimeByLayer: printTimeByLayer
|
||||
};
|
||||
},
|
||||
getGCodeLines: function(layer, fromSegments, toSegments){
|
||||
var i=0;
|
||||
var result = {first: model[layer][fromSegments].gcodeLine, last: model[layer][toSegments].gcodeLine};
|
||||
return result;
|
||||
},
|
||||
getCmdIndexForPercentage: function(percentage) {
|
||||
var command = searchInPercentageTree(percentage);
|
||||
if (command === undefined) {
|
||||
return undefined
|
||||
} else {
|
||||
return command.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}());
|
||||
/**
|
||||
* User: hudbrog (hudbrog@gmail.com)
|
||||
* Date: 10/21/12
|
||||
* Time: 7:31 AM
|
||||
*/
|
||||
|
||||
GCODE.gCodeReader = (function(){
|
||||
// ***** PRIVATE ******
|
||||
var gcode, lines;
|
||||
var z_heights = {};
|
||||
var model = [];
|
||||
var max = {x: undefined, y: undefined, z: undefined};
|
||||
var min = {x: undefined, y: undefined, z: undefined};
|
||||
var modelSize = {x: undefined, y: undefined, z: undefined};
|
||||
var filamentByLayer = {};
|
||||
var printTimeByLayer;
|
||||
var totalFilament=0;
|
||||
var printTime=0;
|
||||
var speeds = {};
|
||||
var speedsByLayer = {};
|
||||
var gCodeOptions = {
|
||||
sortLayers: false,
|
||||
purgeEmptyLayers: true,
|
||||
analyzeModel: false
|
||||
};
|
||||
|
||||
var percentageTree = undefined;
|
||||
|
||||
var prepareGCode = function(totalSize){
|
||||
if(!lines)return;
|
||||
gcode = [];
|
||||
var i, tmp, byteCount;
|
||||
|
||||
byteCount = 0;
|
||||
for(i=0;i<lines.length;i++){
|
||||
byteCount += lines[i].length + 1; // line length + \n
|
||||
tmp = lines[i].indexOf(";");
|
||||
if(tmp > 1 || tmp === -1) {
|
||||
gcode.push({line: lines[i], percentage: byteCount * 100 / totalSize});
|
||||
}
|
||||
}
|
||||
lines = [];
|
||||
};
|
||||
|
||||
var sortLayers = function(){
|
||||
var sortedZ = [];
|
||||
var tmpModel = [];
|
||||
|
||||
for(var layer in z_heights){
|
||||
sortedZ[z_heights[layer]] = layer;
|
||||
}
|
||||
|
||||
sortedZ.sort(function(a,b){
|
||||
return a-b;
|
||||
});
|
||||
|
||||
for(var i=0;i<sortedZ.length;i++){
|
||||
if(typeof(z_heights[sortedZ[i]]) === 'undefined')continue;
|
||||
tmpModel[i] = model[z_heights[sortedZ[i]]];
|
||||
}
|
||||
model = tmpModel;
|
||||
delete tmpModel;
|
||||
};
|
||||
|
||||
var prepareLinesIndex = function(){
|
||||
percentageTree = undefined;
|
||||
|
||||
for (var l in model) {
|
||||
for (var i=0; i< model[l].length; i++) {
|
||||
var percentage = model[l][i].percentage;
|
||||
var value = {layer: l, cmd: i};
|
||||
if (!percentageTree) {
|
||||
percentageTree = new AVLTree({key: percentage, value: value}, "key");
|
||||
} else {
|
||||
percentageTree.add({key: percentage, value: value});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var searchInPercentageTree = function(key) {
|
||||
if (percentageTree === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var elements = percentageTree.findBest(key);
|
||||
if (elements.length == 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return elements[0];
|
||||
};
|
||||
|
||||
var purgeLayers = function(){
|
||||
var purge=true;
|
||||
if(!model){
|
||||
console.log("Something terribly wring just happened.");
|
||||
return;
|
||||
}
|
||||
for(var i=0;i<model.length;i++){
|
||||
purge=true;
|
||||
if(typeof(model[i])==='undefined')purge=true;
|
||||
else {
|
||||
for(var j=0;j<model[i].length;j++){
|
||||
if(model[i][j].extrude)purge=false;
|
||||
}
|
||||
}
|
||||
if(purge){
|
||||
model.splice(i,1);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
// ***** PUBLIC *******
|
||||
return {
|
||||
|
||||
loadFile: function(reader){
|
||||
model = [];
|
||||
z_heights = [];
|
||||
|
||||
var totalSize = reader.target.result.length;
|
||||
lines = reader.target.result.split(/\n/);
|
||||
reader.target.result = null;
|
||||
prepareGCode(totalSize);
|
||||
|
||||
worker.postMessage({
|
||||
"cmd":"parseGCode",
|
||||
"msg":{
|
||||
gcode: gcode,
|
||||
options: {
|
||||
firstReport: 5
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
delete lines;
|
||||
delete gcode;
|
||||
},
|
||||
setOption: function(options){
|
||||
for(var opt in options){
|
||||
gCodeOptions[opt] = options[opt];
|
||||
}
|
||||
},
|
||||
passDataToRenderer: function(){
|
||||
if(gCodeOptions["sortLayers"])sortLayers();
|
||||
if(gCodeOptions["purgeEmptyLayers"])purgeLayers();
|
||||
prepareLinesIndex();
|
||||
GCODE.renderer.doRender(model, 0);
|
||||
|
||||
},
|
||||
processLayerFromWorker: function(msg){
|
||||
model[msg.layerNum] = msg.cmds;
|
||||
z_heights[msg.zHeightObject.zValue] = msg.zHeightObject.layer;
|
||||
},
|
||||
processMultiLayerFromWorker: function(msg){
|
||||
for(var i=0;i<msg.layerNum.length;i++){
|
||||
model[msg.layerNum[i]] = msg.model[msg.layerNum[i]];
|
||||
z_heights[msg.zHeightObject.zValue[i]] = msg.layerNum[i];
|
||||
}
|
||||
},
|
||||
processAnalyzeModelDone: function(msg){
|
||||
min = msg.min;
|
||||
max = msg.max;
|
||||
modelSize = msg.modelSize;
|
||||
totalFilament = msg.totalFilament;
|
||||
filamentByLayer = msg.filamentByLayer;
|
||||
speeds = msg.speeds;
|
||||
speedsByLayer = msg.speedsByLayer;
|
||||
printTime = msg.printTime;
|
||||
printTimeByLayer = msg.printTimeByLayer;
|
||||
},
|
||||
getLayerFilament: function(z){
|
||||
return filamentByLayer[z];
|
||||
},
|
||||
getLayerSpeeds: function(z){
|
||||
return speedsByLayer[z]?speedsByLayer[z]:{};
|
||||
},
|
||||
getModelInfo: function(){
|
||||
return {
|
||||
min: min,
|
||||
max: max,
|
||||
modelSize: modelSize,
|
||||
totalFilament: totalFilament,
|
||||
speeds: speeds,
|
||||
speedsByLayer: speedsByLayer,
|
||||
printTime: printTime,
|
||||
printTimeByLayer: printTimeByLayer
|
||||
};
|
||||
},
|
||||
getGCodeLines: function(layer, fromSegments, toSegments){
|
||||
var i=0;
|
||||
var result = {first: model[layer][fromSegments].gcodeLine, last: model[layer][toSegments].gcodeLine};
|
||||
return result;
|
||||
},
|
||||
getCmdIndexForPercentage: function(percentage) {
|
||||
var command = searchInPercentageTree(percentage);
|
||||
if (command === undefined) {
|
||||
return undefined
|
||||
} else {
|
||||
return command.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}());
|
||||
|
|
@ -1,417 +1,417 @@
|
|||
/**
|
||||
* User: hudbrog (hudbrog@gmail.com)
|
||||
* Date: 10/20/12
|
||||
* Time: 1:36 PM
|
||||
* To change this template use File | Settings | File Templates.
|
||||
*/
|
||||
|
||||
|
||||
GCODE.renderer = (function(){
|
||||
// ***** PRIVATE ******
|
||||
var canvas;
|
||||
var ctx;
|
||||
var zoomFactor= 2.8, zoomFactorDelta = 0.4;
|
||||
var gridSizeX=200,gridSizeY=200,gridStep=10;
|
||||
var ctxHeight, ctxWidth;
|
||||
var prevX=0, prevY=0;
|
||||
|
||||
// var colorGrid="#bbbbbb", colorLine="#000000";
|
||||
var sliderHor, sliderVer;
|
||||
var layerNumStore, progressStore={from: 0, to: -1};
|
||||
var lastX, lastY;
|
||||
var dragStart,dragged;
|
||||
var scaleFactor = 1.1;
|
||||
var model;
|
||||
var initialized=false;
|
||||
var renderOptions = {
|
||||
showMoves: true,
|
||||
showRetracts: true,
|
||||
colorGrid: "#bbbbbb",
|
||||
extrusionWidth: 1,
|
||||
// colorLine: ["#000000", "#aabb88", "#ffe7a0", "#6e7700", "#331a00", "#44ba97", "#08262f", "#db0e00", "#ff9977"],
|
||||
colorLine: ["#000000", "#45c7ba", "#a9533a", "#ff44cc", "#dd1177", "#eeee22", "#ffbb55", "#ff5511", "#777788"],
|
||||
colorMove: "#00ff00",
|
||||
colorRetract: "#ff0000",
|
||||
colorRestart: "#0000ff",
|
||||
sizeRetractSpot: 2,
|
||||
modelCenter: {x: 0, y: 0},
|
||||
moveModel: true,
|
||||
differentiateColors: true,
|
||||
showNextLayer: false
|
||||
};
|
||||
|
||||
var offsetModelX=0, offsetModelY=0;
|
||||
var speeds = [];
|
||||
var speedsByLayer = {};
|
||||
|
||||
|
||||
var reRender = function(){
|
||||
var p1 = ctx.transformedPoint(0,0);
|
||||
var p2 = ctx.transformedPoint(canvas.width,canvas.height);
|
||||
ctx.clearRect(p1.x,p1.y,p2.x-p1.x,p2.y-p1.y);
|
||||
drawGrid();
|
||||
if(renderOptions['showNextLayer'] && layerNumStore < model.length - 1) {
|
||||
drawLayer(layerNumStore+1, 0, GCODE.renderer.getLayerNumSegments(layerNumStore+1), true);
|
||||
}
|
||||
drawLayer(layerNumStore, progressStore.from, progressStore.to);
|
||||
};
|
||||
|
||||
function trackTransforms(ctx){
|
||||
var svg = document.createElementNS("http://www.w3.org/2000/svg",'svg');
|
||||
var xform = svg.createSVGMatrix();
|
||||
ctx.getTransform = function(){ return xform; };
|
||||
|
||||
var savedTransforms = [];
|
||||
var save = ctx.save;
|
||||
ctx.save = function(){
|
||||
savedTransforms.push(xform.translate(0,0));
|
||||
return save.call(ctx);
|
||||
};
|
||||
var restore = ctx.restore;
|
||||
ctx.restore = function(){
|
||||
xform = savedTransforms.pop();
|
||||
return restore.call(ctx);
|
||||
};
|
||||
|
||||
var scale = ctx.scale;
|
||||
ctx.scale = function(sx,sy){
|
||||
xform = xform.scaleNonUniform(sx,sy);
|
||||
return scale.call(ctx,sx,sy);
|
||||
};
|
||||
var rotate = ctx.rotate;
|
||||
ctx.rotate = function(radians){
|
||||
xform = xform.rotate(radians*180/Math.PI);
|
||||
return rotate.call(ctx,radians);
|
||||
};
|
||||
var translate = ctx.translate;
|
||||
ctx.translate = function(dx,dy){
|
||||
xform = xform.translate(dx,dy);
|
||||
return translate.call(ctx,dx,dy);
|
||||
};
|
||||
var transform = ctx.transform;
|
||||
ctx.transform = function(a,b,c,d,e,f){
|
||||
var m2 = svg.createSVGMatrix();
|
||||
m2.a=a; m2.b=b; m2.c=c; m2.d=d; m2.e=e; m2.f=f;
|
||||
xform = xform.multiply(m2);
|
||||
return transform.call(ctx,a,b,c,d,e,f);
|
||||
};
|
||||
var setTransform = ctx.setTransform;
|
||||
ctx.setTransform = function(a,b,c,d,e,f){
|
||||
xform.a = a;
|
||||
xform.b = b;
|
||||
xform.c = c;
|
||||
xform.d = d;
|
||||
xform.e = e;
|
||||
xform.f = f;
|
||||
return setTransform.call(ctx,a,b,c,d,e,f);
|
||||
};
|
||||
var pt = svg.createSVGPoint();
|
||||
ctx.transformedPoint = function(x,y){
|
||||
pt.x=x; pt.y=y;
|
||||
return pt.matrixTransform(xform.inverse());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var startCanvas = function() {
|
||||
canvas = document.getElementById('canvas');
|
||||
|
||||
// Проверяем понимает ли браузер canvas
|
||||
if (!canvas.getContext) {
|
||||
throw "exception";
|
||||
}
|
||||
|
||||
ctx = canvas.getContext('2d'); // Получаем 2D контекст
|
||||
ctxHeight = canvas.height;
|
||||
ctxWidth = canvas.width;
|
||||
lastX = ctxWidth/2;
|
||||
lastY = ctxHeight/2;
|
||||
ctx.lineWidth = 2;
|
||||
ctx.lineCap = 'round';
|
||||
trackTransforms(ctx);
|
||||
|
||||
canvas.addEventListener('mousedown',function(evt){
|
||||
document.body.style.mozUserSelect = document.body.style.webkitUserSelect = document.body.style.userSelect = 'none';
|
||||
lastX = evt.offsetX || (evt.pageX - canvas.offsetLeft);
|
||||
lastY = evt.offsetY || (evt.pageY - canvas.offsetTop);
|
||||
dragStart = ctx.transformedPoint(lastX,lastY);
|
||||
dragged = false;
|
||||
},false);
|
||||
canvas.addEventListener('mousemove',function(evt){
|
||||
lastX = evt.offsetX || (evt.pageX - canvas.offsetLeft);
|
||||
lastY = evt.offsetY || (evt.pageY - canvas.offsetTop);
|
||||
dragged = true;
|
||||
if (dragStart){
|
||||
var pt = ctx.transformedPoint(lastX,lastY);
|
||||
ctx.translate(pt.x-dragStart.x,pt.y-dragStart.y);
|
||||
reRender();
|
||||
}
|
||||
},false);
|
||||
canvas.addEventListener('mouseup',function(evt){
|
||||
dragStart = null;
|
||||
if (!dragged) zoom(evt.shiftKey ? -1 : 1 );
|
||||
},false);
|
||||
var zoom = function(clicks){
|
||||
var pt = ctx.transformedPoint(lastX,lastY);
|
||||
ctx.translate(pt.x,pt.y);
|
||||
var factor = Math.pow(scaleFactor,clicks);
|
||||
ctx.scale(factor,factor);
|
||||
ctx.translate(-pt.x,-pt.y);
|
||||
reRender();
|
||||
};
|
||||
var handleScroll = function(evt){
|
||||
var delta;
|
||||
if(evt.detail<0 || evt.wheelDelta>0)delta=zoomFactorDelta;
|
||||
else delta=-1*zoomFactorDelta;
|
||||
if (delta) zoom(delta);
|
||||
return evt.preventDefault() && false;
|
||||
};
|
||||
canvas.addEventListener('DOMMouseScroll',handleScroll,false);
|
||||
canvas.addEventListener('mousewheel',handleScroll,false);
|
||||
|
||||
};
|
||||
|
||||
var drawGrid = function() {
|
||||
var i;
|
||||
ctx.strokeStyle = renderOptions["colorGrid"];
|
||||
ctx.lineWidth = 1;
|
||||
var offsetX=0, offsetY=0;
|
||||
if(renderOptions["moveModel"]){
|
||||
offsetX = offsetModelX;
|
||||
offsetY = offsetModelY;
|
||||
}
|
||||
|
||||
ctx.beginPath();
|
||||
for(i=0;i<=gridSizeX;i+=gridStep){
|
||||
ctx.moveTo(i*zoomFactor-offsetX, 0-offsetY);
|
||||
ctx.lineTo(i*zoomFactor-offsetX, -gridSizeY*zoomFactor-offsetY);
|
||||
}
|
||||
ctx.stroke();
|
||||
|
||||
ctx.beginPath();
|
||||
for(i=0;i<=gridSizeY;i+=gridStep){
|
||||
ctx.moveTo(0-offsetX, -i*zoomFactor-offsetY);
|
||||
ctx.lineTo(gridSizeX*zoomFactor-offsetX, -i*zoomFactor-offsetY);
|
||||
}
|
||||
ctx.stroke();
|
||||
|
||||
};
|
||||
|
||||
var drawLayer = function(layerNum, fromProgress, toProgress, isNextLayer){
|
||||
var i, speedIndex= 0, prevZ = 0;
|
||||
isNextLayer = typeof isNextLayer !== 'undefined' ? isNextLayer : false;
|
||||
if(!isNextLayer){
|
||||
layerNumStore=layerNum;
|
||||
progressStore = {from: fromProgress, to: toProgress};
|
||||
}
|
||||
if(!model||!model[layerNum])return;
|
||||
|
||||
var cmds = model[layerNum];
|
||||
var x, y;
|
||||
|
||||
// if(toProgress === -1){
|
||||
// toProgress=cmds.length;
|
||||
// }
|
||||
|
||||
if(fromProgress>0){
|
||||
prevX = cmds[fromProgress-1].x*zoomFactor;
|
||||
prevY = -cmds[fromProgress-1].y*zoomFactor;
|
||||
}else if(fromProgress===0 && layerNum==0){
|
||||
if(model[0]&&model[0].x !== undefined &&model[0].y !== undefined){
|
||||
prevX = model[0].x*zoomFactor;
|
||||
prevY = -model[0].y*zoomFactor;
|
||||
}else {
|
||||
prevX = 0;
|
||||
prevY = 0;
|
||||
}
|
||||
}else if(typeof(cmds[0].prevX) !== 'undefined' && typeof(cmds[0].prevY) !== 'undefined'){
|
||||
prevX = cmds[0].prevX*zoomFactor;
|
||||
prevY = -cmds[0].prevY*zoomFactor;
|
||||
}else{
|
||||
if(model[layerNum-1]){
|
||||
prevX=undefined;
|
||||
prevY=undefined;
|
||||
for(i=model[layerNum-1].length-1;i>=0;i--){
|
||||
if(prevX === undefined && model[layerNum-1][i].x!==undefined)prevX=model[layerNum-1][i].x*zoomFactor;
|
||||
if(prevY === undefined && model[layerNum-1][i].y!==undefined)prevY=-model[layerNum-1][i].y*zoomFactor;
|
||||
}
|
||||
if(prevX === undefined)prevX=0;
|
||||
if(prevY === undefined)prevY=0;
|
||||
}else{
|
||||
prevX=0;
|
||||
prevY=0;
|
||||
}
|
||||
}
|
||||
|
||||
prevZ = GCODE.renderer.getZ(layerNum);
|
||||
|
||||
// ctx.strokeStyle = renderOptions["colorLine"];
|
||||
for(i=fromProgress;i<=toProgress;i++){
|
||||
ctx.lineWidth = 1;
|
||||
|
||||
if(typeof(cmds[i]) === 'undefined')continue;
|
||||
|
||||
if(typeof(cmds[i].prevX) !== 'undefined' && typeof(cmds[i].prevY) !== 'undefined'){
|
||||
prevX = cmds[i].prevX*zoomFactor;
|
||||
prevY = -cmds[i].prevY*zoomFactor;
|
||||
}
|
||||
// console.log(cmds[i]);
|
||||
if(typeof(cmds[i].x)==='undefined'||isNaN(cmds[i].x))x=prevX/zoomFactor;
|
||||
else x = cmds[i].x;
|
||||
if(typeof(cmds[i].y) === 'undefined'||isNaN(cmds[i].y))y=prevY/zoomFactor;
|
||||
else y = -cmds[i].y;
|
||||
if(renderOptions["differentiateColors"]&&!renderOptions['showNextLayer']){
|
||||
// if(speedsByLayer['extrude'][prevZ]){
|
||||
speedIndex = speeds['extrude'].indexOf(cmds[i].speed);
|
||||
// speedIndex = GCODE.ui.ArrayIndexOf(speedsByLayer['extrude'][prevZ], function(obj) {return obj.speed === cmds[i].speed;});
|
||||
// } else {
|
||||
// speedIndex = -1;
|
||||
// }
|
||||
if(speedIndex === -1){
|
||||
speedIndex = 0;
|
||||
}else if(speedIndex > renderOptions["colorLine"].length -1){
|
||||
speedIndex = speedIndex % (renderOptions["colorLine"].length-1);
|
||||
// console.log("Too much colors");
|
||||
}
|
||||
}else if(renderOptions['showNextLayer']&&isNextLayer){
|
||||
speedIndex=3;
|
||||
}else{
|
||||
speedIndex=0;
|
||||
}
|
||||
|
||||
|
||||
if(!cmds[i].extrude&&!cmds[i].noMove){
|
||||
// ctx.stroke();
|
||||
if(cmds[i].retract == -1){
|
||||
if(renderOptions["showRetracts"]){
|
||||
|
||||
ctx.strokeStyle = renderOptions["colorRetract"];
|
||||
ctx.fillStyle = renderOptions["colorRetract"];
|
||||
ctx.beginPath();
|
||||
ctx.arc(prevX, prevY, renderOptions["sizeRetractSpot"], 0, Math.PI*2, true);
|
||||
ctx.stroke();
|
||||
ctx.fill();
|
||||
}
|
||||
}
|
||||
if(renderOptions["showMoves"]){
|
||||
ctx.strokeStyle = renderOptions["colorMove"];
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(prevX, prevY);
|
||||
ctx.lineTo(x*zoomFactor,y*zoomFactor);
|
||||
ctx.stroke();
|
||||
}
|
||||
// ctx.strokeStyle = renderOptions["colorLine"][0];
|
||||
// ctx.beginPath();
|
||||
// console.log("moveto: "+cmds[i].x+":"+cmds[i].y)
|
||||
// ctx.moveTo(cmds[i].x*zoomFactor,cmds[i].y*zoomFactor);
|
||||
}
|
||||
else if(cmds[i].extrude){
|
||||
if(cmds[i].retract==0){
|
||||
ctx.strokeStyle = renderOptions["colorLine"][speedIndex];
|
||||
ctx.lineWidth = renderOptions['extrusionWidth'];
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(prevX, prevY);
|
||||
ctx.lineTo(x*zoomFactor,y*zoomFactor);
|
||||
ctx.stroke();
|
||||
}else {
|
||||
if(renderOptions["showRetracts"]){
|
||||
// ctx.stroke();
|
||||
ctx.strokeStyle = renderOptions["colorRestart"];
|
||||
ctx.fillStyle = renderOptions["colorRestart"];
|
||||
ctx.beginPath();
|
||||
ctx.arc(prevX, prevY, renderOptions["sizeRetractSpot"], 0, Math.PI*2, true);
|
||||
ctx.stroke();
|
||||
ctx.fill();
|
||||
// ctx.strokeStyle = renderOptions["colorLine"][0];
|
||||
// ctx.beginPath();
|
||||
}
|
||||
}
|
||||
}
|
||||
prevX = x*zoomFactor;
|
||||
prevY = y*zoomFactor;
|
||||
}
|
||||
ctx.stroke();
|
||||
};
|
||||
|
||||
|
||||
// ***** PUBLIC *******
|
||||
return {
|
||||
init: function(){
|
||||
startCanvas();
|
||||
initialized = true;
|
||||
ctx.translate(10,gridSizeY*zoomFactor+20);
|
||||
},
|
||||
setOption: function(options){
|
||||
for(var opt in options){
|
||||
if(options.hasOwnProperty(opt))renderOptions[opt] = options[opt];
|
||||
};
|
||||
|
||||
if(initialized)reRender();
|
||||
},
|
||||
getOptions: function(){
|
||||
return renderOptions;
|
||||
},
|
||||
debugGetModel: function(){
|
||||
return model;
|
||||
},
|
||||
render: function(layerNum, fromProgress, toProgress){
|
||||
if(!initialized)this.init();
|
||||
if(!model){
|
||||
drawGrid();
|
||||
}else{
|
||||
if(layerNum < model.length){
|
||||
var p1 = ctx.transformedPoint(0,0);
|
||||
var p2 = ctx.transformedPoint(canvas.width,canvas.height);
|
||||
ctx.clearRect(p1.x,p1.y,p2.x-p1.x,p2.y-p1.y);
|
||||
drawGrid();
|
||||
// ctx.globalAlpha = 0.5;
|
||||
if(renderOptions['showNextLayer'] && layerNum < model.length - 1) {
|
||||
drawLayer(layerNum+1, 0, this.getLayerNumSegments(layerNum+1), true);
|
||||
}
|
||||
drawLayer(layerNum, fromProgress, toProgress);
|
||||
}else{
|
||||
console.log("Got request to render non-existent layer!!");
|
||||
}
|
||||
}
|
||||
},
|
||||
getModelNumLayers: function(){
|
||||
return model?model.length:1;
|
||||
},
|
||||
getLayerNumSegments: function(layer){
|
||||
if(model){
|
||||
return model[layer]?model[layer].length:1;
|
||||
}else{
|
||||
return 1;
|
||||
}
|
||||
},
|
||||
doRender: function(mdl, layerNum){
|
||||
var mdlInfo;
|
||||
model = mdl;
|
||||
prevX=0;
|
||||
prevY=0;
|
||||
if(!initialized)this.init();
|
||||
|
||||
mdlInfo = GCODE.gCodeReader.getModelInfo();
|
||||
speeds = mdlInfo.speeds;
|
||||
speedsByLayer = mdlInfo.speedsByLayer;
|
||||
// console.log(speeds);
|
||||
// console.log(mdlInfo.min.x + ' ' + mdlInfo.modelSize.x);
|
||||
offsetModelX = (gridSizeX/2-(mdlInfo.min.x+mdlInfo.modelSize.x/2))*zoomFactor;
|
||||
offsetModelY = (mdlInfo.min.y+mdlInfo.modelSize.y/2)*zoomFactor-gridSizeY/2*zoomFactor;
|
||||
if(ctx)ctx.translate(offsetModelX, offsetModelY);
|
||||
|
||||
this.render(layerNum, 0, model[layerNum].length);
|
||||
},
|
||||
getZ: function(layerNum){
|
||||
if(!model&&!model[layerNum]){
|
||||
return '-1';
|
||||
}
|
||||
var cmds = model[layerNum];
|
||||
for(var i=0;i<cmds.length;i++){
|
||||
if(cmds[i].prevZ!==undefined)return cmds[i].prevZ;
|
||||
}
|
||||
return '-1';
|
||||
}
|
||||
|
||||
}
|
||||
}());
|
||||
/**
|
||||
* User: hudbrog (hudbrog@gmail.com)
|
||||
* Date: 10/20/12
|
||||
* Time: 1:36 PM
|
||||
* To change this template use File | Settings | File Templates.
|
||||
*/
|
||||
|
||||
|
||||
GCODE.renderer = (function(){
|
||||
// ***** PRIVATE ******
|
||||
var canvas;
|
||||
var ctx;
|
||||
var zoomFactor= 2.8, zoomFactorDelta = 0.4;
|
||||
var gridSizeX=200,gridSizeY=200,gridStep=10;
|
||||
var ctxHeight, ctxWidth;
|
||||
var prevX=0, prevY=0;
|
||||
|
||||
// var colorGrid="#bbbbbb", colorLine="#000000";
|
||||
var sliderHor, sliderVer;
|
||||
var layerNumStore, progressStore={from: 0, to: -1};
|
||||
var lastX, lastY;
|
||||
var dragStart,dragged;
|
||||
var scaleFactor = 1.1;
|
||||
var model;
|
||||
var initialized=false;
|
||||
var renderOptions = {
|
||||
showMoves: true,
|
||||
showRetracts: true,
|
||||
colorGrid: "#bbbbbb",
|
||||
extrusionWidth: 1,
|
||||
// colorLine: ["#000000", "#aabb88", "#ffe7a0", "#6e7700", "#331a00", "#44ba97", "#08262f", "#db0e00", "#ff9977"],
|
||||
colorLine: ["#000000", "#45c7ba", "#a9533a", "#ff44cc", "#dd1177", "#eeee22", "#ffbb55", "#ff5511", "#777788"],
|
||||
colorMove: "#00ff00",
|
||||
colorRetract: "#ff0000",
|
||||
colorRestart: "#0000ff",
|
||||
sizeRetractSpot: 2,
|
||||
modelCenter: {x: 0, y: 0},
|
||||
moveModel: true,
|
||||
differentiateColors: true,
|
||||
showNextLayer: false
|
||||
};
|
||||
|
||||
var offsetModelX=0, offsetModelY=0;
|
||||
var speeds = [];
|
||||
var speedsByLayer = {};
|
||||
|
||||
|
||||
var reRender = function(){
|
||||
var p1 = ctx.transformedPoint(0,0);
|
||||
var p2 = ctx.transformedPoint(canvas.width,canvas.height);
|
||||
ctx.clearRect(p1.x,p1.y,p2.x-p1.x,p2.y-p1.y);
|
||||
drawGrid();
|
||||
if(renderOptions['showNextLayer'] && layerNumStore < model.length - 1) {
|
||||
drawLayer(layerNumStore+1, 0, GCODE.renderer.getLayerNumSegments(layerNumStore+1), true);
|
||||
}
|
||||
drawLayer(layerNumStore, progressStore.from, progressStore.to);
|
||||
};
|
||||
|
||||
function trackTransforms(ctx){
|
||||
var svg = document.createElementNS("http://www.w3.org/2000/svg",'svg');
|
||||
var xform = svg.createSVGMatrix();
|
||||
ctx.getTransform = function(){ return xform; };
|
||||
|
||||
var savedTransforms = [];
|
||||
var save = ctx.save;
|
||||
ctx.save = function(){
|
||||
savedTransforms.push(xform.translate(0,0));
|
||||
return save.call(ctx);
|
||||
};
|
||||
var restore = ctx.restore;
|
||||
ctx.restore = function(){
|
||||
xform = savedTransforms.pop();
|
||||
return restore.call(ctx);
|
||||
};
|
||||
|
||||
var scale = ctx.scale;
|
||||
ctx.scale = function(sx,sy){
|
||||
xform = xform.scaleNonUniform(sx,sy);
|
||||
return scale.call(ctx,sx,sy);
|
||||
};
|
||||
var rotate = ctx.rotate;
|
||||
ctx.rotate = function(radians){
|
||||
xform = xform.rotate(radians*180/Math.PI);
|
||||
return rotate.call(ctx,radians);
|
||||
};
|
||||
var translate = ctx.translate;
|
||||
ctx.translate = function(dx,dy){
|
||||
xform = xform.translate(dx,dy);
|
||||
return translate.call(ctx,dx,dy);
|
||||
};
|
||||
var transform = ctx.transform;
|
||||
ctx.transform = function(a,b,c,d,e,f){
|
||||
var m2 = svg.createSVGMatrix();
|
||||
m2.a=a; m2.b=b; m2.c=c; m2.d=d; m2.e=e; m2.f=f;
|
||||
xform = xform.multiply(m2);
|
||||
return transform.call(ctx,a,b,c,d,e,f);
|
||||
};
|
||||
var setTransform = ctx.setTransform;
|
||||
ctx.setTransform = function(a,b,c,d,e,f){
|
||||
xform.a = a;
|
||||
xform.b = b;
|
||||
xform.c = c;
|
||||
xform.d = d;
|
||||
xform.e = e;
|
||||
xform.f = f;
|
||||
return setTransform.call(ctx,a,b,c,d,e,f);
|
||||
};
|
||||
var pt = svg.createSVGPoint();
|
||||
ctx.transformedPoint = function(x,y){
|
||||
pt.x=x; pt.y=y;
|
||||
return pt.matrixTransform(xform.inverse());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var startCanvas = function() {
|
||||
canvas = document.getElementById('canvas');
|
||||
|
||||
// Проверяем понимает ли браузер canvas
|
||||
if (!canvas.getContext) {
|
||||
throw "exception";
|
||||
}
|
||||
|
||||
ctx = canvas.getContext('2d'); // Получаем 2D контекст
|
||||
ctxHeight = canvas.height;
|
||||
ctxWidth = canvas.width;
|
||||
lastX = ctxWidth/2;
|
||||
lastY = ctxHeight/2;
|
||||
ctx.lineWidth = 2;
|
||||
ctx.lineCap = 'round';
|
||||
trackTransforms(ctx);
|
||||
|
||||
canvas.addEventListener('mousedown',function(evt){
|
||||
document.body.style.mozUserSelect = document.body.style.webkitUserSelect = document.body.style.userSelect = 'none';
|
||||
lastX = evt.offsetX || (evt.pageX - canvas.offsetLeft);
|
||||
lastY = evt.offsetY || (evt.pageY - canvas.offsetTop);
|
||||
dragStart = ctx.transformedPoint(lastX,lastY);
|
||||
dragged = false;
|
||||
},false);
|
||||
canvas.addEventListener('mousemove',function(evt){
|
||||
lastX = evt.offsetX || (evt.pageX - canvas.offsetLeft);
|
||||
lastY = evt.offsetY || (evt.pageY - canvas.offsetTop);
|
||||
dragged = true;
|
||||
if (dragStart){
|
||||
var pt = ctx.transformedPoint(lastX,lastY);
|
||||
ctx.translate(pt.x-dragStart.x,pt.y-dragStart.y);
|
||||
reRender();
|
||||
}
|
||||
},false);
|
||||
canvas.addEventListener('mouseup',function(evt){
|
||||
dragStart = null;
|
||||
if (!dragged) zoom(evt.shiftKey ? -1 : 1 );
|
||||
},false);
|
||||
var zoom = function(clicks){
|
||||
var pt = ctx.transformedPoint(lastX,lastY);
|
||||
ctx.translate(pt.x,pt.y);
|
||||
var factor = Math.pow(scaleFactor,clicks);
|
||||
ctx.scale(factor,factor);
|
||||
ctx.translate(-pt.x,-pt.y);
|
||||
reRender();
|
||||
};
|
||||
var handleScroll = function(evt){
|
||||
var delta;
|
||||
if(evt.detail<0 || evt.wheelDelta>0)delta=zoomFactorDelta;
|
||||
else delta=-1*zoomFactorDelta;
|
||||
if (delta) zoom(delta);
|
||||
return evt.preventDefault() && false;
|
||||
};
|
||||
canvas.addEventListener('DOMMouseScroll',handleScroll,false);
|
||||
canvas.addEventListener('mousewheel',handleScroll,false);
|
||||
|
||||
};
|
||||
|
||||
var drawGrid = function() {
|
||||
var i;
|
||||
ctx.strokeStyle = renderOptions["colorGrid"];
|
||||
ctx.lineWidth = 1;
|
||||
var offsetX=0, offsetY=0;
|
||||
if(renderOptions["moveModel"]){
|
||||
offsetX = offsetModelX;
|
||||
offsetY = offsetModelY;
|
||||
}
|
||||
|
||||
ctx.beginPath();
|
||||
for(i=0;i<=gridSizeX;i+=gridStep){
|
||||
ctx.moveTo(i*zoomFactor-offsetX, 0-offsetY);
|
||||
ctx.lineTo(i*zoomFactor-offsetX, -gridSizeY*zoomFactor-offsetY);
|
||||
}
|
||||
ctx.stroke();
|
||||
|
||||
ctx.beginPath();
|
||||
for(i=0;i<=gridSizeY;i+=gridStep){
|
||||
ctx.moveTo(0-offsetX, -i*zoomFactor-offsetY);
|
||||
ctx.lineTo(gridSizeX*zoomFactor-offsetX, -i*zoomFactor-offsetY);
|
||||
}
|
||||
ctx.stroke();
|
||||
|
||||
};
|
||||
|
||||
var drawLayer = function(layerNum, fromProgress, toProgress, isNextLayer){
|
||||
var i, speedIndex= 0, prevZ = 0;
|
||||
isNextLayer = typeof isNextLayer !== 'undefined' ? isNextLayer : false;
|
||||
if(!isNextLayer){
|
||||
layerNumStore=layerNum;
|
||||
progressStore = {from: fromProgress, to: toProgress};
|
||||
}
|
||||
if(!model||!model[layerNum])return;
|
||||
|
||||
var cmds = model[layerNum];
|
||||
var x, y;
|
||||
|
||||
// if(toProgress === -1){
|
||||
// toProgress=cmds.length;
|
||||
// }
|
||||
|
||||
if(fromProgress>0){
|
||||
prevX = cmds[fromProgress-1].x*zoomFactor;
|
||||
prevY = -cmds[fromProgress-1].y*zoomFactor;
|
||||
}else if(fromProgress===0 && layerNum==0){
|
||||
if(model[0]&&model[0].x !== undefined &&model[0].y !== undefined){
|
||||
prevX = model[0].x*zoomFactor;
|
||||
prevY = -model[0].y*zoomFactor;
|
||||
}else {
|
||||
prevX = 0;
|
||||
prevY = 0;
|
||||
}
|
||||
}else if(typeof(cmds[0].prevX) !== 'undefined' && typeof(cmds[0].prevY) !== 'undefined'){
|
||||
prevX = cmds[0].prevX*zoomFactor;
|
||||
prevY = -cmds[0].prevY*zoomFactor;
|
||||
}else{
|
||||
if(model[layerNum-1]){
|
||||
prevX=undefined;
|
||||
prevY=undefined;
|
||||
for(i=model[layerNum-1].length-1;i>=0;i--){
|
||||
if(prevX === undefined && model[layerNum-1][i].x!==undefined)prevX=model[layerNum-1][i].x*zoomFactor;
|
||||
if(prevY === undefined && model[layerNum-1][i].y!==undefined)prevY=-model[layerNum-1][i].y*zoomFactor;
|
||||
}
|
||||
if(prevX === undefined)prevX=0;
|
||||
if(prevY === undefined)prevY=0;
|
||||
}else{
|
||||
prevX=0;
|
||||
prevY=0;
|
||||
}
|
||||
}
|
||||
|
||||
prevZ = GCODE.renderer.getZ(layerNum);
|
||||
|
||||
// ctx.strokeStyle = renderOptions["colorLine"];
|
||||
for(i=fromProgress;i<=toProgress;i++){
|
||||
ctx.lineWidth = 1;
|
||||
|
||||
if(typeof(cmds[i]) === 'undefined')continue;
|
||||
|
||||
if(typeof(cmds[i].prevX) !== 'undefined' && typeof(cmds[i].prevY) !== 'undefined'){
|
||||
prevX = cmds[i].prevX*zoomFactor;
|
||||
prevY = -cmds[i].prevY*zoomFactor;
|
||||
}
|
||||
// console.log(cmds[i]);
|
||||
if(typeof(cmds[i].x)==='undefined'||isNaN(cmds[i].x))x=prevX/zoomFactor;
|
||||
else x = cmds[i].x;
|
||||
if(typeof(cmds[i].y) === 'undefined'||isNaN(cmds[i].y))y=prevY/zoomFactor;
|
||||
else y = -cmds[i].y;
|
||||
if(renderOptions["differentiateColors"]&&!renderOptions['showNextLayer']){
|
||||
// if(speedsByLayer['extrude'][prevZ]){
|
||||
speedIndex = speeds['extrude'].indexOf(cmds[i].speed);
|
||||
// speedIndex = GCODE.ui.ArrayIndexOf(speedsByLayer['extrude'][prevZ], function(obj) {return obj.speed === cmds[i].speed;});
|
||||
// } else {
|
||||
// speedIndex = -1;
|
||||
// }
|
||||
if(speedIndex === -1){
|
||||
speedIndex = 0;
|
||||
}else if(speedIndex > renderOptions["colorLine"].length -1){
|
||||
speedIndex = speedIndex % (renderOptions["colorLine"].length-1);
|
||||
// console.log("Too much colors");
|
||||
}
|
||||
}else if(renderOptions['showNextLayer']&&isNextLayer){
|
||||
speedIndex=3;
|
||||
}else{
|
||||
speedIndex=0;
|
||||
}
|
||||
|
||||
|
||||
if(!cmds[i].extrude&&!cmds[i].noMove){
|
||||
// ctx.stroke();
|
||||
if(cmds[i].retract == -1){
|
||||
if(renderOptions["showRetracts"]){
|
||||
|
||||
ctx.strokeStyle = renderOptions["colorRetract"];
|
||||
ctx.fillStyle = renderOptions["colorRetract"];
|
||||
ctx.beginPath();
|
||||
ctx.arc(prevX, prevY, renderOptions["sizeRetractSpot"], 0, Math.PI*2, true);
|
||||
ctx.stroke();
|
||||
ctx.fill();
|
||||
}
|
||||
}
|
||||
if(renderOptions["showMoves"]){
|
||||
ctx.strokeStyle = renderOptions["colorMove"];
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(prevX, prevY);
|
||||
ctx.lineTo(x*zoomFactor,y*zoomFactor);
|
||||
ctx.stroke();
|
||||
}
|
||||
// ctx.strokeStyle = renderOptions["colorLine"][0];
|
||||
// ctx.beginPath();
|
||||
// console.log("moveto: "+cmds[i].x+":"+cmds[i].y)
|
||||
// ctx.moveTo(cmds[i].x*zoomFactor,cmds[i].y*zoomFactor);
|
||||
}
|
||||
else if(cmds[i].extrude){
|
||||
if(cmds[i].retract==0){
|
||||
ctx.strokeStyle = renderOptions["colorLine"][speedIndex];
|
||||
ctx.lineWidth = renderOptions['extrusionWidth'];
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(prevX, prevY);
|
||||
ctx.lineTo(x*zoomFactor,y*zoomFactor);
|
||||
ctx.stroke();
|
||||
}else {
|
||||
if(renderOptions["showRetracts"]){
|
||||
// ctx.stroke();
|
||||
ctx.strokeStyle = renderOptions["colorRestart"];
|
||||
ctx.fillStyle = renderOptions["colorRestart"];
|
||||
ctx.beginPath();
|
||||
ctx.arc(prevX, prevY, renderOptions["sizeRetractSpot"], 0, Math.PI*2, true);
|
||||
ctx.stroke();
|
||||
ctx.fill();
|
||||
// ctx.strokeStyle = renderOptions["colorLine"][0];
|
||||
// ctx.beginPath();
|
||||
}
|
||||
}
|
||||
}
|
||||
prevX = x*zoomFactor;
|
||||
prevY = y*zoomFactor;
|
||||
}
|
||||
ctx.stroke();
|
||||
};
|
||||
|
||||
|
||||
// ***** PUBLIC *******
|
||||
return {
|
||||
init: function(){
|
||||
startCanvas();
|
||||
initialized = true;
|
||||
ctx.translate(10,gridSizeY*zoomFactor+20);
|
||||
},
|
||||
setOption: function(options){
|
||||
for(var opt in options){
|
||||
if(options.hasOwnProperty(opt))renderOptions[opt] = options[opt];
|
||||
};
|
||||
|
||||
if(initialized)reRender();
|
||||
},
|
||||
getOptions: function(){
|
||||
return renderOptions;
|
||||
},
|
||||
debugGetModel: function(){
|
||||
return model;
|
||||
},
|
||||
render: function(layerNum, fromProgress, toProgress){
|
||||
if(!initialized)this.init();
|
||||
if(!model){
|
||||
drawGrid();
|
||||
}else{
|
||||
if(layerNum < model.length){
|
||||
var p1 = ctx.transformedPoint(0,0);
|
||||
var p2 = ctx.transformedPoint(canvas.width,canvas.height);
|
||||
ctx.clearRect(p1.x,p1.y,p2.x-p1.x,p2.y-p1.y);
|
||||
drawGrid();
|
||||
// ctx.globalAlpha = 0.5;
|
||||
if(renderOptions['showNextLayer'] && layerNum < model.length - 1) {
|
||||
drawLayer(layerNum+1, 0, this.getLayerNumSegments(layerNum+1), true);
|
||||
}
|
||||
drawLayer(layerNum, fromProgress, toProgress);
|
||||
}else{
|
||||
console.log("Got request to render non-existent layer!!");
|
||||
}
|
||||
}
|
||||
},
|
||||
getModelNumLayers: function(){
|
||||
return model?model.length:1;
|
||||
},
|
||||
getLayerNumSegments: function(layer){
|
||||
if(model){
|
||||
return model[layer]?model[layer].length:1;
|
||||
}else{
|
||||
return 1;
|
||||
}
|
||||
},
|
||||
doRender: function(mdl, layerNum){
|
||||
var mdlInfo;
|
||||
model = mdl;
|
||||
prevX=0;
|
||||
prevY=0;
|
||||
if(!initialized)this.init();
|
||||
|
||||
mdlInfo = GCODE.gCodeReader.getModelInfo();
|
||||
speeds = mdlInfo.speeds;
|
||||
speedsByLayer = mdlInfo.speedsByLayer;
|
||||
// console.log(speeds);
|
||||
// console.log(mdlInfo.min.x + ' ' + mdlInfo.modelSize.x);
|
||||
offsetModelX = (gridSizeX/2-(mdlInfo.min.x+mdlInfo.modelSize.x/2))*zoomFactor;
|
||||
offsetModelY = (mdlInfo.min.y+mdlInfo.modelSize.y/2)*zoomFactor-gridSizeY/2*zoomFactor;
|
||||
if(ctx)ctx.translate(offsetModelX, offsetModelY);
|
||||
|
||||
this.render(layerNum, 0, model[layerNum].length);
|
||||
},
|
||||
getZ: function(layerNum){
|
||||
if(!model&&!model[layerNum]){
|
||||
return '-1';
|
||||
}
|
||||
var cmds = model[layerNum];
|
||||
for(var i=0;i<cmds.length;i++){
|
||||
if(cmds[i].prevZ!==undefined)return cmds[i].prevZ;
|
||||
}
|
||||
return '-1';
|
||||
}
|
||||
|
||||
}
|
||||
}());
|
||||
|
|
@ -1,345 +1,345 @@
|
|||
/**
|
||||
* User: hudbrog (hudbrog@gmail.com)
|
||||
* Date: 10/21/12
|
||||
* Time: 7:45 AM
|
||||
*/
|
||||
|
||||
var GCODE = {};
|
||||
|
||||
GCODE.ui = (function(){
|
||||
var reader;
|
||||
var myCodeMirror;
|
||||
var sliderVer;
|
||||
var sliderHor;
|
||||
var gCodeLines = {first: 0, last: 0};
|
||||
var showGCode = false;
|
||||
|
||||
var setProgress = function(id, progress){
|
||||
$('#'+id).width(parseInt(progress)+'%');
|
||||
$('#'+id).text(parseInt(progress)+'%');
|
||||
|
||||
};
|
||||
|
||||
var chooseAccordion = function(id){
|
||||
// debugger;
|
||||
$('#'+id).collapse("show");
|
||||
};
|
||||
|
||||
var setLinesColor = function(toggle){
|
||||
// var i=0;
|
||||
// for(i=gCodeLines.first;i<gCodeLines.last; i++){
|
||||
// if(toggle){
|
||||
// myCodeMirror.setLineClass(Number(i), null, "activeline");
|
||||
// }else{
|
||||
// myCodeMirror.setLineClass(Number(i), null, null);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
var printLayerInfo = function(layerNum){
|
||||
var z = GCODE.renderer.getZ(layerNum);
|
||||
var segments = GCODE.renderer.getLayerNumSegments(layerNum);
|
||||
var filament = GCODE.gCodeReader.getLayerFilament(z);
|
||||
var layerSpeeds = GCODE.gCodeReader.getModelInfo().speedsByLayer;
|
||||
var renderOptions = GCODE.renderer.getOptions();
|
||||
var colors = renderOptions["colorLine"];
|
||||
var speedIndex = 0;
|
||||
var keys, type;
|
||||
var showMove=false;
|
||||
var i = 0;
|
||||
var output = [];
|
||||
output.push("Layer number: " + layerNum);
|
||||
output.push("Layer height (mm): " + z);
|
||||
output.push("GCODE commands in layer: " + segments);
|
||||
output.push("Filament used by layer (mm): " + filament.toFixed(2));
|
||||
output.push("Print time for layer: " + parseFloat(GCODE.gCodeReader.getModelInfo().printTimeByLayer[z]).toFixed(1) + "sec");
|
||||
output.push("Extrude speeds:");
|
||||
for(i=0;i<layerSpeeds['extrude'][z].length;i++){
|
||||
if(typeof(layerSpeeds['extrude'][z][i])==='undefined'){continue;}
|
||||
speedIndex = i;
|
||||
if(speedIndex > colors.length -1){speedIndex = speedIndex % (colors.length-1);}
|
||||
output.push("<div id='colorBox"+i+"' class='colorBox' style='background-color: "+colors[speedIndex] + "'></div> = " + (parseFloat(layerSpeeds['extrude'][z][i])/60).toFixed(2)+"mm/s");
|
||||
}
|
||||
if(typeof(layerSpeeds['move'][z]) !== 'undefined'){
|
||||
output.push("Move speeds:");
|
||||
for(i=0;i<layerSpeeds['move'][z].length;i++){
|
||||
if(typeof(layerSpeeds['move'][z][i])==='undefined'){continue;}
|
||||
speedIndex = i;
|
||||
if(speedIndex > colors.length -1){speedIndex = speedIndex % (colors.length-1);}
|
||||
output.push("<div id='colorBox"+i+"' class='colorBox' style='background-color: "+renderOptions['colorMove'] + "'></div> = " + (parseFloat(layerSpeeds['move'][z][i])/60).toFixed(2)+"mm/s");
|
||||
}
|
||||
}
|
||||
if(typeof(layerSpeeds['retract'][z]) !== 'undefined'){
|
||||
output.push("Retract speeds:");
|
||||
for(i=0;i<layerSpeeds['retract'][z].length;i++){
|
||||
if(typeof(layerSpeeds['retract'][z][i])==='undefined'){continue;}
|
||||
speedIndex = i;
|
||||
if(speedIndex > colors.length -1){speedIndex = speedIndex % (colors.length-1);}
|
||||
output.push("<span style='color: " + renderOptions['colorRetract'] +"'>●</span> <span style='color: " + renderOptions['colorRestart'] +"'>●</span> = " +(parseFloat(layerSpeeds['retract'][z][i])/60).toFixed(2)+"mm/s");
|
||||
}
|
||||
}
|
||||
|
||||
$('#layerInfo').html(output.join('<br>'));
|
||||
// chooseAccordion('layerAccordionTab');
|
||||
};
|
||||
|
||||
var handleFileSelect = function(evt) {
|
||||
// console.log("handleFileSelect");
|
||||
evt.stopPropagation();
|
||||
evt.preventDefault();
|
||||
|
||||
var files = evt.dataTransfer?evt.dataTransfer.files:evt.target.files; // FileList object.
|
||||
|
||||
var output = [];
|
||||
for (var i = 0, f; f = files[i]; i++) {
|
||||
if(f.name.toLowerCase().match(/^.*\.(?:gcode|g|txt)$/)){
|
||||
output.push('<li>File extensions suggests GCODE</li>');
|
||||
}else{
|
||||
output.push('<li><strong>You should only upload *.gcode files! I will not work with this one!</strong></li>');
|
||||
document.getElementById('errorList').innerHTML = '<ul>' + output.join('') + '</ul>';
|
||||
return;
|
||||
}
|
||||
|
||||
reader = new FileReader();
|
||||
reader.onload = function(theFile){
|
||||
chooseAccordion('progressAccordionTab');
|
||||
setProgress('loadProgress', 0);
|
||||
setProgress('analyzeProgress', 0);
|
||||
// myCodeMirror.setValue(theFile.target.result);
|
||||
GCODE.gCodeReader.loadFile(theFile);
|
||||
if(showGCode){
|
||||
myCodeMirror.setValue(theFile.target.result);
|
||||
}else{
|
||||
myCodeMirror.setValue("GCode view is disabled. You can enable it in 'GCode analyzer options' section.")
|
||||
}
|
||||
|
||||
};
|
||||
reader.readAsText(f);
|
||||
}
|
||||
};
|
||||
|
||||
var handleDragOver = function(evt) {
|
||||
evt.stopPropagation();
|
||||
evt.preventDefault();
|
||||
evt.target.dropEffect = 'copy'; // Explicitly show this is a copy.
|
||||
};
|
||||
|
||||
var initSliders = function(){
|
||||
var prevX=0;
|
||||
var prevY=0;
|
||||
var handle;
|
||||
sliderVer = $( "#slider-vertical" );
|
||||
sliderHor = $( "#slider-horizontal" );
|
||||
|
||||
var onLayerChange = function(val){
|
||||
var progress = GCODE.renderer.getLayerNumSegments(val)-1;
|
||||
GCODE.renderer.render(val,0, progress);
|
||||
sliderHor.slider({max: progress, values: [0,progress]});
|
||||
setLinesColor(false); //clear current selection
|
||||
gCodeLines = GCODE.gCodeReader.getGCodeLines(val, sliderHor.slider("values",0), sliderHor.slider("values",1));
|
||||
setLinesColor(true); // highlight lines
|
||||
printLayerInfo(val);
|
||||
};
|
||||
|
||||
sliderVer.slider({
|
||||
orientation: "vertical",
|
||||
range: "min",
|
||||
min: 0,
|
||||
max: GCODE.renderer.getModelNumLayers()-1,
|
||||
value: 0,
|
||||
slide: function( event, ui ) {
|
||||
onLayerChange(ui.value);
|
||||
}
|
||||
});
|
||||
|
||||
//this stops slider reacting to arrow keys, since we do it below manually
|
||||
$( "#slider-vertical .ui-slider-handle" ).unbind('keydown');
|
||||
|
||||
sliderHor.slider({
|
||||
orientation: "horizontal",
|
||||
range: "min",
|
||||
min: 0,
|
||||
max: GCODE.renderer.getLayerNumSegments(0)-1,
|
||||
values: [0,GCODE.renderer.getLayerNumSegments(0)-1],
|
||||
slide: function( event, ui ) {
|
||||
setLinesColor(false); //clear current selection
|
||||
gCodeLines = GCODE.gCodeReader.getGCodeLines(sliderVer.slider("value"),ui.values[0], ui.values[1]);
|
||||
setLinesColor(true); // highlight lines
|
||||
GCODE.renderer.render(sliderVer.slider("value"), ui.values[0], ui.values[1]);
|
||||
}
|
||||
});
|
||||
|
||||
window.onkeydown = function (event){
|
||||
if(event.keyCode === 38 || event.keyCode === 33){
|
||||
if(sliderVer.slider('value') < sliderVer.slider('option', 'max')){
|
||||
sliderVer.slider('value', sliderVer.slider('value')+1);
|
||||
onLayerChange(sliderVer.slider('value'));
|
||||
}
|
||||
}else if(event.keyCode === 40 || event.keyCode === 34){
|
||||
if(sliderVer.slider('value') > 0){
|
||||
sliderVer.slider('value', sliderVer.slider('value')-1);
|
||||
onLayerChange(sliderVer.slider('value'));
|
||||
}
|
||||
}
|
||||
event.stopPropagation()
|
||||
}
|
||||
};
|
||||
|
||||
var processMessage = function(e){
|
||||
var data = e.data;
|
||||
switch (data.cmd) {
|
||||
case 'returnModel':
|
||||
setProgress('loadProgress', 100);
|
||||
worker.postMessage({
|
||||
"cmd":"analyzeModel",
|
||||
"msg":{
|
||||
}
|
||||
}
|
||||
);
|
||||
break;
|
||||
case 'analyzeDone':
|
||||
var resultSet = [];
|
||||
|
||||
setProgress('analyzeProgress',100);
|
||||
GCODE.gCodeReader.processAnalyzeModelDone(data.msg);
|
||||
GCODE.gCodeReader.passDataToRenderer();
|
||||
initSliders();
|
||||
resultSet.push("Model size is: " + data.msg.modelSize.x.toFixed(2) + 'x' + data.msg.modelSize.y.toFixed(2) + 'x' + data.msg.modelSize.z.toFixed(2)+'mm<br>');
|
||||
resultSet.push("Total filament used: " + data.msg.totalFilament.toFixed(2) + "mm<br>");
|
||||
resultSet.push("Estimated print time: " + parseInt(parseFloat(data.msg.printTime)/60/60) + ":" + parseInt((parseFloat(data.msg.printTime)/60)%60) + ":" + parseInt(parseFloat(data.msg.printTime)%60) + "<br>");
|
||||
resultSet.push("Estimated layer height: " + data.msg.layerHeight.toFixed(2) + "mm<br>");
|
||||
resultSet.push("Layer count: " + data.msg.layerCnt.toFixed(0) + "printed, " + data.msg.layerTotal.toFixed(0) + 'visited<br>');
|
||||
document.getElementById('list').innerHTML = resultSet.join('');
|
||||
chooseAccordion('infoAccordionTab');
|
||||
$('#myTab a[href="#tab2d"]').tab('show');
|
||||
break;
|
||||
case 'returnLayer':
|
||||
GCODE.gCodeReader.processLayerFromWorker(data.msg);
|
||||
setProgress('loadProgress',data.msg.progress);
|
||||
break;
|
||||
case 'returnMultiLayer':
|
||||
GCODE.gCodeReader.processMultiLayerFromWorker(data.msg);
|
||||
setProgress('loadProgress',data.msg.progress);
|
||||
break;
|
||||
case "analyzeProgress":
|
||||
setProgress('analyzeProgress',data.msg.progress);
|
||||
break;
|
||||
default:
|
||||
console.log("default msg received" + data.cmd);
|
||||
}
|
||||
};
|
||||
|
||||
var checkCapabilities = function(){
|
||||
var warnings = [];
|
||||
var fatal = [];
|
||||
|
||||
Modernizr.addTest('filereader', function () {
|
||||
return !!(window.File && window.FileList && window.FileReader);
|
||||
});
|
||||
|
||||
if(!Modernizr.canvas)fatal.push("<li>Your browser doesn't seem to support HTML5 Canvas, this application won't work without it.</li>");
|
||||
//if(!Modernizr.filereader)fatal.push("<li>Your browser doesn't seem to support HTML5 File API, this application won't work without it.</li>");
|
||||
if(!Modernizr.webworkers)fatal.push("<li>Your browser doesn't seem to support HTML5 Web Workers, this application won't work without it.</li>");
|
||||
if(!Modernizr.svg)fatal.push("<li>Your browser doesn't seem to support HTML5 SVG, this application won't work without it.</li>");
|
||||
|
||||
if(fatal.length>0){
|
||||
document.getElementById('errorList').innerHTML = '<ul>' + fatal.join('') + '</ul>';
|
||||
console.log("Initialization failed: unsupported browser.")
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!Modernizr.webgl && GCODE.renderer3d){
|
||||
warnings.push("<li>Your browser doesn't seem to support HTML5 Web GL, 3d mode is not recommended, going to be SLOW!</li>");
|
||||
GCODE.renderer3d.setOption({rendererType: "canvas"});
|
||||
}
|
||||
if(!Modernizr.draganddrop)warnings.push("<li>Your browser doesn't seem to support HTML5 Drag'n'Drop, Drop area will not work.</li>");
|
||||
|
||||
if(warnings.length>0){
|
||||
document.getElementById('errorList').innerHTML = '<ul>' + wanings.join('') + '</ul>';
|
||||
console.log("Initialization succeeded with warnings.")
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
return {
|
||||
worker: undefined,
|
||||
initHandlers: function(){
|
||||
var capabilitiesResult = checkCapabilities();
|
||||
if(!capabilitiesResult){
|
||||
return;
|
||||
}
|
||||
|
||||
setProgress('loadProgress', 0);
|
||||
setProgress('analyzeProgress', 0);
|
||||
|
||||
worker = new Worker('static/gcodeviewer/js/Worker.js');
|
||||
|
||||
worker.addEventListener('message', processMessage, false);
|
||||
|
||||
GCODE.ui.processOptions();
|
||||
GCODE.renderer.render(0,0);
|
||||
|
||||
console.log("Application initialized");
|
||||
|
||||
},
|
||||
|
||||
ArrayIndexOf: function(a, fnc) {
|
||||
if (!fnc || typeof (fnc) != 'function') {
|
||||
return -1;
|
||||
}
|
||||
if (!a || !a.length || a.length < 1) return -1;
|
||||
for (var i = 0; i < a.length; i++) {
|
||||
if(!a[i]) continue;
|
||||
if (fnc(a[i])) return i;
|
||||
}
|
||||
return -1;
|
||||
},
|
||||
updateLayerInfo: function(layerNum){
|
||||
printLayerInfo(layerNum);
|
||||
},
|
||||
|
||||
processOptions: function(){
|
||||
if(document.getElementById('sortLayersCheckbox').checked)GCODE.gCodeReader.setOption({sortLayers: true});
|
||||
else GCODE.gCodeReader.setOption({sortLayers: false});
|
||||
|
||||
if(document.getElementById('purgeEmptyLayersCheckbox').checked)GCODE.gCodeReader.setOption({purgeEmptyLayers: true});
|
||||
else GCODE.gCodeReader.setOption({purgeEmptyLayers: false});
|
||||
|
||||
if(document.getElementById('showGCodeCheckbox').checked)showGCode = true;
|
||||
else showGCode = false;
|
||||
|
||||
|
||||
// if(document.getElementById('sortLayersCheckbox').checked) worker.postMessage({"cmd":"setOption", "msg":{sortLayers: true}});
|
||||
// else worker.postMessage({"cmd":"setOption", "msg":{sortLayers: false}});
|
||||
//
|
||||
// if(document.getElementById('purgeEmptyLayersCheckbox').checked)worker.postMessage({"cmd":"setOption", "msg":{purgeEmptyLayers: true}});
|
||||
// else worker.postMessage({"cmd":"setOption", "msg":{purgeEmptyLayers: false}});
|
||||
|
||||
// if(document.getElementById('analyzeModelCheckbox').checked)worker.postMessage({"cmd":"setOption", "msg":{analyzeModel: true}});
|
||||
// else worker.postMessage({"cmd":"setOption", "msg":{analyzeModel: false}});
|
||||
|
||||
|
||||
if(document.getElementById('moveModelCheckbox').checked)GCODE.renderer.setOption({moveModel: true});
|
||||
else GCODE.renderer.setOption({moveModel: false});
|
||||
|
||||
if(document.getElementById('showMovesCheckbox').checked)GCODE.renderer.setOption({showMoves: true});
|
||||
else GCODE.renderer.setOption({showMoves: false});
|
||||
|
||||
if(document.getElementById('showRetractsCheckbox').checked)GCODE.renderer.setOption({showRetracts: true});
|
||||
else GCODE.renderer.setOption({showRetracts: false});
|
||||
|
||||
if(document.getElementById('differentiateColorsCheckbox').checked)GCODE.renderer.setOption({differentiateColors: true});
|
||||
else GCODE.renderer.setOption({differentiateColors: false});
|
||||
|
||||
var widthMod = 2;
|
||||
if(Number($('#widthModifier').attr('value'))) {widthMod = Number($('#widthModifier').attr('value'));}
|
||||
if(document.getElementById('thickExtrusionCheckbox').checked)GCODE.renderer.setOption({extrusionWidth: widthMod});
|
||||
else GCODE.renderer.setOption({extrusionWidth: 1});
|
||||
|
||||
if(document.getElementById('showNextLayer').checked)GCODE.renderer.setOption({showNextLayer: true});
|
||||
else GCODE.renderer.setOption({showNextLayer: false});
|
||||
}
|
||||
}
|
||||
/**
|
||||
* User: hudbrog (hudbrog@gmail.com)
|
||||
* Date: 10/21/12
|
||||
* Time: 7:45 AM
|
||||
*/
|
||||
|
||||
var GCODE = {};
|
||||
|
||||
GCODE.ui = (function(){
|
||||
var reader;
|
||||
var myCodeMirror;
|
||||
var sliderVer;
|
||||
var sliderHor;
|
||||
var gCodeLines = {first: 0, last: 0};
|
||||
var showGCode = false;
|
||||
|
||||
var setProgress = function(id, progress){
|
||||
$('#'+id).width(parseInt(progress)+'%');
|
||||
$('#'+id).text(parseInt(progress)+'%');
|
||||
|
||||
};
|
||||
|
||||
var chooseAccordion = function(id){
|
||||
// debugger;
|
||||
$('#'+id).collapse("show");
|
||||
};
|
||||
|
||||
var setLinesColor = function(toggle){
|
||||
// var i=0;
|
||||
// for(i=gCodeLines.first;i<gCodeLines.last; i++){
|
||||
// if(toggle){
|
||||
// myCodeMirror.setLineClass(Number(i), null, "activeline");
|
||||
// }else{
|
||||
// myCodeMirror.setLineClass(Number(i), null, null);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
var printLayerInfo = function(layerNum){
|
||||
var z = GCODE.renderer.getZ(layerNum);
|
||||
var segments = GCODE.renderer.getLayerNumSegments(layerNum);
|
||||
var filament = GCODE.gCodeReader.getLayerFilament(z);
|
||||
var layerSpeeds = GCODE.gCodeReader.getModelInfo().speedsByLayer;
|
||||
var renderOptions = GCODE.renderer.getOptions();
|
||||
var colors = renderOptions["colorLine"];
|
||||
var speedIndex = 0;
|
||||
var keys, type;
|
||||
var showMove=false;
|
||||
var i = 0;
|
||||
var output = [];
|
||||
output.push("Layer number: " + layerNum);
|
||||
output.push("Layer height (mm): " + z);
|
||||
output.push("GCODE commands in layer: " + segments);
|
||||
output.push("Filament used by layer (mm): " + filament.toFixed(2));
|
||||
output.push("Print time for layer: " + parseFloat(GCODE.gCodeReader.getModelInfo().printTimeByLayer[z]).toFixed(1) + "sec");
|
||||
output.push("Extrude speeds:");
|
||||
for(i=0;i<layerSpeeds['extrude'][z].length;i++){
|
||||
if(typeof(layerSpeeds['extrude'][z][i])==='undefined'){continue;}
|
||||
speedIndex = i;
|
||||
if(speedIndex > colors.length -1){speedIndex = speedIndex % (colors.length-1);}
|
||||
output.push("<div id='colorBox"+i+"' class='colorBox' style='background-color: "+colors[speedIndex] + "'></div> = " + (parseFloat(layerSpeeds['extrude'][z][i])/60).toFixed(2)+"mm/s");
|
||||
}
|
||||
if(typeof(layerSpeeds['move'][z]) !== 'undefined'){
|
||||
output.push("Move speeds:");
|
||||
for(i=0;i<layerSpeeds['move'][z].length;i++){
|
||||
if(typeof(layerSpeeds['move'][z][i])==='undefined'){continue;}
|
||||
speedIndex = i;
|
||||
if(speedIndex > colors.length -1){speedIndex = speedIndex % (colors.length-1);}
|
||||
output.push("<div id='colorBox"+i+"' class='colorBox' style='background-color: "+renderOptions['colorMove'] + "'></div> = " + (parseFloat(layerSpeeds['move'][z][i])/60).toFixed(2)+"mm/s");
|
||||
}
|
||||
}
|
||||
if(typeof(layerSpeeds['retract'][z]) !== 'undefined'){
|
||||
output.push("Retract speeds:");
|
||||
for(i=0;i<layerSpeeds['retract'][z].length;i++){
|
||||
if(typeof(layerSpeeds['retract'][z][i])==='undefined'){continue;}
|
||||
speedIndex = i;
|
||||
if(speedIndex > colors.length -1){speedIndex = speedIndex % (colors.length-1);}
|
||||
output.push("<span style='color: " + renderOptions['colorRetract'] +"'>●</span> <span style='color: " + renderOptions['colorRestart'] +"'>●</span> = " +(parseFloat(layerSpeeds['retract'][z][i])/60).toFixed(2)+"mm/s");
|
||||
}
|
||||
}
|
||||
|
||||
$('#layerInfo').html(output.join('<br>'));
|
||||
// chooseAccordion('layerAccordionTab');
|
||||
};
|
||||
|
||||
var handleFileSelect = function(evt) {
|
||||
// console.log("handleFileSelect");
|
||||
evt.stopPropagation();
|
||||
evt.preventDefault();
|
||||
|
||||
var files = evt.dataTransfer?evt.dataTransfer.files:evt.target.files; // FileList object.
|
||||
|
||||
var output = [];
|
||||
for (var i = 0, f; f = files[i]; i++) {
|
||||
if(f.name.toLowerCase().match(/^.*\.(?:gcode|g|txt)$/)){
|
||||
output.push('<li>File extensions suggests GCODE</li>');
|
||||
}else{
|
||||
output.push('<li><strong>You should only upload *.gcode files! I will not work with this one!</strong></li>');
|
||||
document.getElementById('errorList').innerHTML = '<ul>' + output.join('') + '</ul>';
|
||||
return;
|
||||
}
|
||||
|
||||
reader = new FileReader();
|
||||
reader.onload = function(theFile){
|
||||
chooseAccordion('progressAccordionTab');
|
||||
setProgress('loadProgress', 0);
|
||||
setProgress('analyzeProgress', 0);
|
||||
// myCodeMirror.setValue(theFile.target.result);
|
||||
GCODE.gCodeReader.loadFile(theFile);
|
||||
if(showGCode){
|
||||
myCodeMirror.setValue(theFile.target.result);
|
||||
}else{
|
||||
myCodeMirror.setValue("GCode view is disabled. You can enable it in 'GCode analyzer options' section.")
|
||||
}
|
||||
|
||||
};
|
||||
reader.readAsText(f);
|
||||
}
|
||||
};
|
||||
|
||||
var handleDragOver = function(evt) {
|
||||
evt.stopPropagation();
|
||||
evt.preventDefault();
|
||||
evt.target.dropEffect = 'copy'; // Explicitly show this is a copy.
|
||||
};
|
||||
|
||||
var initSliders = function(){
|
||||
var prevX=0;
|
||||
var prevY=0;
|
||||
var handle;
|
||||
sliderVer = $( "#slider-vertical" );
|
||||
sliderHor = $( "#slider-horizontal" );
|
||||
|
||||
var onLayerChange = function(val){
|
||||
var progress = GCODE.renderer.getLayerNumSegments(val)-1;
|
||||
GCODE.renderer.render(val,0, progress);
|
||||
sliderHor.slider({max: progress, values: [0,progress]});
|
||||
setLinesColor(false); //clear current selection
|
||||
gCodeLines = GCODE.gCodeReader.getGCodeLines(val, sliderHor.slider("values",0), sliderHor.slider("values",1));
|
||||
setLinesColor(true); // highlight lines
|
||||
printLayerInfo(val);
|
||||
};
|
||||
|
||||
sliderVer.slider({
|
||||
orientation: "vertical",
|
||||
range: "min",
|
||||
min: 0,
|
||||
max: GCODE.renderer.getModelNumLayers()-1,
|
||||
value: 0,
|
||||
slide: function( event, ui ) {
|
||||
onLayerChange(ui.value);
|
||||
}
|
||||
});
|
||||
|
||||
//this stops slider reacting to arrow keys, since we do it below manually
|
||||
$( "#slider-vertical .ui-slider-handle" ).unbind('keydown');
|
||||
|
||||
sliderHor.slider({
|
||||
orientation: "horizontal",
|
||||
range: "min",
|
||||
min: 0,
|
||||
max: GCODE.renderer.getLayerNumSegments(0)-1,
|
||||
values: [0,GCODE.renderer.getLayerNumSegments(0)-1],
|
||||
slide: function( event, ui ) {
|
||||
setLinesColor(false); //clear current selection
|
||||
gCodeLines = GCODE.gCodeReader.getGCodeLines(sliderVer.slider("value"),ui.values[0], ui.values[1]);
|
||||
setLinesColor(true); // highlight lines
|
||||
GCODE.renderer.render(sliderVer.slider("value"), ui.values[0], ui.values[1]);
|
||||
}
|
||||
});
|
||||
|
||||
window.onkeydown = function (event){
|
||||
if(event.keyCode === 38 || event.keyCode === 33){
|
||||
if(sliderVer.slider('value') < sliderVer.slider('option', 'max')){
|
||||
sliderVer.slider('value', sliderVer.slider('value')+1);
|
||||
onLayerChange(sliderVer.slider('value'));
|
||||
}
|
||||
}else if(event.keyCode === 40 || event.keyCode === 34){
|
||||
if(sliderVer.slider('value') > 0){
|
||||
sliderVer.slider('value', sliderVer.slider('value')-1);
|
||||
onLayerChange(sliderVer.slider('value'));
|
||||
}
|
||||
}
|
||||
event.stopPropagation()
|
||||
}
|
||||
};
|
||||
|
||||
var processMessage = function(e){
|
||||
var data = e.data;
|
||||
switch (data.cmd) {
|
||||
case 'returnModel':
|
||||
setProgress('loadProgress', 100);
|
||||
worker.postMessage({
|
||||
"cmd":"analyzeModel",
|
||||
"msg":{
|
||||
}
|
||||
}
|
||||
);
|
||||
break;
|
||||
case 'analyzeDone':
|
||||
var resultSet = [];
|
||||
|
||||
setProgress('analyzeProgress',100);
|
||||
GCODE.gCodeReader.processAnalyzeModelDone(data.msg);
|
||||
GCODE.gCodeReader.passDataToRenderer();
|
||||
initSliders();
|
||||
resultSet.push("Model size is: " + data.msg.modelSize.x.toFixed(2) + 'x' + data.msg.modelSize.y.toFixed(2) + 'x' + data.msg.modelSize.z.toFixed(2)+'mm<br>');
|
||||
resultSet.push("Total filament used: " + data.msg.totalFilament.toFixed(2) + "mm<br>");
|
||||
resultSet.push("Estimated print time: " + parseInt(parseFloat(data.msg.printTime)/60/60) + ":" + parseInt((parseFloat(data.msg.printTime)/60)%60) + ":" + parseInt(parseFloat(data.msg.printTime)%60) + "<br>");
|
||||
resultSet.push("Estimated layer height: " + data.msg.layerHeight.toFixed(2) + "mm<br>");
|
||||
resultSet.push("Layer count: " + data.msg.layerCnt.toFixed(0) + "printed, " + data.msg.layerTotal.toFixed(0) + 'visited<br>');
|
||||
document.getElementById('list').innerHTML = resultSet.join('');
|
||||
chooseAccordion('infoAccordionTab');
|
||||
$('#myTab a[href="#tab2d"]').tab('show');
|
||||
break;
|
||||
case 'returnLayer':
|
||||
GCODE.gCodeReader.processLayerFromWorker(data.msg);
|
||||
setProgress('loadProgress',data.msg.progress);
|
||||
break;
|
||||
case 'returnMultiLayer':
|
||||
GCODE.gCodeReader.processMultiLayerFromWorker(data.msg);
|
||||
setProgress('loadProgress',data.msg.progress);
|
||||
break;
|
||||
case "analyzeProgress":
|
||||
setProgress('analyzeProgress',data.msg.progress);
|
||||
break;
|
||||
default:
|
||||
console.log("default msg received" + data.cmd);
|
||||
}
|
||||
};
|
||||
|
||||
var checkCapabilities = function(){
|
||||
var warnings = [];
|
||||
var fatal = [];
|
||||
|
||||
Modernizr.addTest('filereader', function () {
|
||||
return !!(window.File && window.FileList && window.FileReader);
|
||||
});
|
||||
|
||||
if(!Modernizr.canvas)fatal.push("<li>Your browser doesn't seem to support HTML5 Canvas, this application won't work without it.</li>");
|
||||
//if(!Modernizr.filereader)fatal.push("<li>Your browser doesn't seem to support HTML5 File API, this application won't work without it.</li>");
|
||||
if(!Modernizr.webworkers)fatal.push("<li>Your browser doesn't seem to support HTML5 Web Workers, this application won't work without it.</li>");
|
||||
if(!Modernizr.svg)fatal.push("<li>Your browser doesn't seem to support HTML5 SVG, this application won't work without it.</li>");
|
||||
|
||||
if(fatal.length>0){
|
||||
document.getElementById('errorList').innerHTML = '<ul>' + fatal.join('') + '</ul>';
|
||||
console.log("Initialization failed: unsupported browser.")
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!Modernizr.webgl && GCODE.renderer3d){
|
||||
warnings.push("<li>Your browser doesn't seem to support HTML5 Web GL, 3d mode is not recommended, going to be SLOW!</li>");
|
||||
GCODE.renderer3d.setOption({rendererType: "canvas"});
|
||||
}
|
||||
if(!Modernizr.draganddrop)warnings.push("<li>Your browser doesn't seem to support HTML5 Drag'n'Drop, Drop area will not work.</li>");
|
||||
|
||||
if(warnings.length>0){
|
||||
document.getElementById('errorList').innerHTML = '<ul>' + wanings.join('') + '</ul>';
|
||||
console.log("Initialization succeeded with warnings.")
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
return {
|
||||
worker: undefined,
|
||||
initHandlers: function(){
|
||||
var capabilitiesResult = checkCapabilities();
|
||||
if(!capabilitiesResult){
|
||||
return;
|
||||
}
|
||||
|
||||
setProgress('loadProgress', 0);
|
||||
setProgress('analyzeProgress', 0);
|
||||
|
||||
worker = new Worker('static/gcodeviewer/js/Worker.js');
|
||||
|
||||
worker.addEventListener('message', processMessage, false);
|
||||
|
||||
GCODE.ui.processOptions();
|
||||
GCODE.renderer.render(0,0);
|
||||
|
||||
console.log("Application initialized");
|
||||
|
||||
},
|
||||
|
||||
ArrayIndexOf: function(a, fnc) {
|
||||
if (!fnc || typeof (fnc) != 'function') {
|
||||
return -1;
|
||||
}
|
||||
if (!a || !a.length || a.length < 1) return -1;
|
||||
for (var i = 0; i < a.length; i++) {
|
||||
if(!a[i]) continue;
|
||||
if (fnc(a[i])) return i;
|
||||
}
|
||||
return -1;
|
||||
},
|
||||
updateLayerInfo: function(layerNum){
|
||||
printLayerInfo(layerNum);
|
||||
},
|
||||
|
||||
processOptions: function(){
|
||||
if(document.getElementById('sortLayersCheckbox').checked)GCODE.gCodeReader.setOption({sortLayers: true});
|
||||
else GCODE.gCodeReader.setOption({sortLayers: false});
|
||||
|
||||
if(document.getElementById('purgeEmptyLayersCheckbox').checked)GCODE.gCodeReader.setOption({purgeEmptyLayers: true});
|
||||
else GCODE.gCodeReader.setOption({purgeEmptyLayers: false});
|
||||
|
||||
if(document.getElementById('showGCodeCheckbox').checked)showGCode = true;
|
||||
else showGCode = false;
|
||||
|
||||
|
||||
// if(document.getElementById('sortLayersCheckbox').checked) worker.postMessage({"cmd":"setOption", "msg":{sortLayers: true}});
|
||||
// else worker.postMessage({"cmd":"setOption", "msg":{sortLayers: false}});
|
||||
//
|
||||
// if(document.getElementById('purgeEmptyLayersCheckbox').checked)worker.postMessage({"cmd":"setOption", "msg":{purgeEmptyLayers: true}});
|
||||
// else worker.postMessage({"cmd":"setOption", "msg":{purgeEmptyLayers: false}});
|
||||
|
||||
// if(document.getElementById('analyzeModelCheckbox').checked)worker.postMessage({"cmd":"setOption", "msg":{analyzeModel: true}});
|
||||
// else worker.postMessage({"cmd":"setOption", "msg":{analyzeModel: false}});
|
||||
|
||||
|
||||
if(document.getElementById('moveModelCheckbox').checked)GCODE.renderer.setOption({moveModel: true});
|
||||
else GCODE.renderer.setOption({moveModel: false});
|
||||
|
||||
if(document.getElementById('showMovesCheckbox').checked)GCODE.renderer.setOption({showMoves: true});
|
||||
else GCODE.renderer.setOption({showMoves: false});
|
||||
|
||||
if(document.getElementById('showRetractsCheckbox').checked)GCODE.renderer.setOption({showRetracts: true});
|
||||
else GCODE.renderer.setOption({showRetracts: false});
|
||||
|
||||
if(document.getElementById('differentiateColorsCheckbox').checked)GCODE.renderer.setOption({differentiateColors: true});
|
||||
else GCODE.renderer.setOption({differentiateColors: false});
|
||||
|
||||
var widthMod = 2;
|
||||
if(Number($('#widthModifier').attr('value'))) {widthMod = Number($('#widthModifier').attr('value'));}
|
||||
if(document.getElementById('thickExtrusionCheckbox').checked)GCODE.renderer.setOption({extrusionWidth: widthMod});
|
||||
else GCODE.renderer.setOption({extrusionWidth: 1});
|
||||
|
||||
if(document.getElementById('showNextLayer').checked)GCODE.renderer.setOption({showNextLayer: true});
|
||||
else GCODE.renderer.setOption({showNextLayer: false});
|
||||
}
|
||||
}
|
||||
}());
|
||||
|
Before Width: | Height: | Size: 8.8 KiB After Width: | Height: | Size: 8.8 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 8.6 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 197 B After Width: | Height: | Size: 197 B |
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 780 B After Width: | Height: | Size: 780 B |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 721 B After Width: | Height: | Size: 721 B |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 815 B After Width: | Height: | Size: 815 B |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 6.7 KiB After Width: | Height: | Size: 6.7 KiB |