/** Copyright 2014-2017 Stewart Allen -- All Rights Reserved */ "use strict"; var gs_kiri_widget = exports; (function() { if (!self.kiri) self.kiri = {}; if (self.kiri.Widget) return; var KIRI = self.kiri, DRIVERS = KIRI.driver, CAM = DRIVERS.CAM, FDM = DRIVERS.FDM, LASER = DRIVERS.LASER, CPRO = CAM.process, BASE = self.base, CONF = BASE.config, DBUG = BASE.debug, UTIL = BASE.util, POLY = BASE.polygons, MATH = Math, ABS = MATH.abs, MIN = MATH.min, MAX = MATH.max, SQRT = MATH.sqrt, CEIL = MATH.ceil, FLOOR = MATH.floor, ROUND = MATH.round, SLICER = KIRI.slicer, newLine = BASE.newLine, newPoint = BASE.newPoint, newSlice = KIRI.newSlice, newPolygon = BASE.newPolygon, newOrderedLine = BASE.newOrderedLine, time = UTIL.time, PRO = Widget.prototype, solid_opacity = 1.0, nextId = 0; KIRI.Widget = Widget; KIRI.newWidget = newWidget; function newWidget(id) { return new Widget(id) } /** ****************************************************************** * Constructor ******************************************************************* */ /** * @params {String} [id] * @constructor */ function Widget(id) { this.id = id || new Date().getTime().toString(36)+(nextId++); this.mesh = null; this.points = null; // todo resolve use of this vs. mesh.bounds this.bounds = null; this.wire = null; this.topo = null; this.slices = null; this.settings = null; this.modified = true; this.orient = { scale: { x: 1.0, y: 1.0, z: 1.0 }, rot: { x: 0, y: 0, z: 0 }, pos: { x: 0, y: 0, z: 0 }, mirror: false }, this.stats = { slice_time: 0, load_time: 0, progress: 0 }; this.saved = false; // cancel slice/print ops this.cancel = false; } /** ****************************************************************** * Widget Class Functions ******************************************************************* */ Widget.loadFromCatalog = function(filename, ondone) { KIRI.catalog.getFile(filename, function(data) { ondone(newWidget().loadVertices(data)); }); }; Widget.loadFromState = function(id, ondone, move) { var widget = newWidget(); widget.id = id; widget.saved = time(); KIRI.odb.get('ws-save-'+id, function(data) { if (data) { var vertices = data.geo || data, orient = data.orient || null; ondone(widget.loadVertices(vertices)); // restore widget position if specified if (move && orient && orient.pos) { widget.orient = orient; widget.move(orient.pos.x, orient.pos.y, orient.pos.z, true); } } else { ondone(null); } }); }; Widget.deleteFromState = function(id,ondone) { KIRI.odb.remove('ws-save-'+id, ondone); }; /** * converts a geometry point array into a kiri point array * with auto-decimation * * @param {Float32Array} array * @param {boolean} [decimate] * @returns {Array} */ Widget.verticesToPoints = function(array,decimate) { var parr = new Array(array.length / 3), i = 0, j = 0, t = time(), hash = {}, unique = 0, passes = 0, points, oldpoints = parr.length, newpoints; // replace point objects with their equivalents while (i < array.length) { var p = newPoint(array[i++], array[i++], array[i++]), k = p.key, m = hash[k]; if (!m) { m = p; hash[k] = p; unique++; } parr[j++] = m; } // decimate until all point spacing > precision_decimate while (parr.length > BASE.config.decimate_threshold && decimate && BASE.config.precision_decimate > 0.0) { var lines = [], line, dec = 0; for (i=0; i= BASE.config.precision_decimate) break; if (line.p1.op || line.p2.op) continue; // todo skip dropping lines where either point is a "sharp" on 3 vectors line.p1.op = line.p2.op = line.p1.midPointTo3D(line.p2); dec++; } // exit if nothing to decimate if (dec === 0) break; passes++; // create new facets points = new Array(oldpoints); newpoints = 0; for (i=0; i