1245 lines
45 KiB
Plaintext
1245 lines
45 KiB
Plaintext
/**
|
|
Copyright (C) 2012-2016 by Autodesk, Inc.
|
|
All rights reserved.
|
|
|
|
JSON setup sheet.
|
|
|
|
$Revision: 42020 a20cdb5530b7a5b3e441ecf55e3eebdd06fd6cd5 $
|
|
$Date: 2018-06-18 18:34:01 $
|
|
|
|
FORKID {4E9DFE89-DA1C-4531-98C9-7FECF672BD47}
|
|
*/
|
|
|
|
// Disable a few lint rules that don't seem compatible with the post's underlying JS engine
|
|
/* eslint-disable prefer-reflect */
|
|
/* eslint-disable prefer-arrow-callback */
|
|
|
|
description = "Setup sheet (JSON)";
|
|
vendor = "Autodesk";
|
|
vendorUrl = "http://www.autodesk.com";
|
|
legal = "Copyright (C) 2012-2016 by Autodesk, Inc.";
|
|
certificationLevel = 2;
|
|
longDescription = "Setup sheet data export in JSON (JavaScript Object Notation) format.";
|
|
capabilities = CAPABILITY_SETUP_SHEET;
|
|
extension = "json";
|
|
keywords = "MODEL_IMAGE PREVIEW_IMAGE"
|
|
setCodePage("utf-8");
|
|
|
|
// Allows use of different machines across setups
|
|
allowMachineChangeOnSection = true;
|
|
|
|
// A running container object that will eventually be exported as JSON
|
|
let setupSheetObj = {};
|
|
|
|
// An object to cache all parameters for the current section (operation)
|
|
let cachedParams = {};
|
|
|
|
// A container for miscellaneous items that need to be gathered
|
|
// along the way and processed at the end (in onClose)
|
|
let runningValues = {};
|
|
|
|
// map image extensions to mime types
|
|
const supportedImageTypes = {
|
|
bmp: "image/bmp",
|
|
gif: "image/gif",
|
|
jpg: "image/jpeg",
|
|
jpeg: "image/jpeg",
|
|
png: "image/png",
|
|
tif: "image/tiff",
|
|
tiff: "image/tiff"
|
|
};
|
|
|
|
// Called first, before any data is processed
|
|
// Initialize a few things
|
|
function onOpen() {
|
|
setupSheetObj = getInitialSetupObject();
|
|
runningValues = getRunningValuesObject();
|
|
}
|
|
|
|
// Called as each parameter is passed into the post
|
|
// Cache them all in an object for later use (mostly, in onSection and friends)
|
|
function onParameter(name, value) {
|
|
cachedParams[name] = value;
|
|
}
|
|
|
|
// Called for each CAM operation
|
|
// Most processing is handled here
|
|
function onSection() {
|
|
// Add the sections for this operation to the container object
|
|
addSummaryObject();
|
|
addToolObject(tool);
|
|
addSetupObject();
|
|
addOperationObject(tool);
|
|
|
|
// No need to process anything else in this section.
|
|
// This will stop processing the section and go directly on onSectionEnd.
|
|
skipRemainingSection();
|
|
}
|
|
|
|
// Process "no-tool" operations
|
|
function onSectionSpecialCycle() {
|
|
// Get an empty operation properties object (all props with null values)
|
|
// and then update a few select properties useful for "no-tool" operations
|
|
var operationProps = getEmptyOperationProperties();
|
|
operationProps.description = getParamValueOrNull("operation-comment")
|
|
operationProps.strategy = cachedParams["operation-strategy"] ? getStrategyDescription(cachedParams["operation-strategy"]) : null;
|
|
operationProps.wcs = currentSection.workOffset;
|
|
operationProps.tolerance = getParamValueOrNull("operation:tolerance");
|
|
|
|
const operation = {
|
|
id: cachedParams["autodeskcam:operation-id"],
|
|
images: [],
|
|
properties: operationProps
|
|
};
|
|
|
|
// add the operation to the container
|
|
setupSheetObj.operations.push(operation);
|
|
}
|
|
|
|
// Process "Manual NC" operations
|
|
function onManualNC(command, value) {
|
|
var cmdName = getManualNCCommandName(command);
|
|
var description = value ? (cmdName + " = " + String(value)) : cmdName;
|
|
var operation = createManualNCOperation();
|
|
operation.properties.description = description;
|
|
|
|
// add the operation to the container
|
|
setupSheetObj.operations.push(operation);
|
|
}
|
|
|
|
// Called at the end of each CAM operation
|
|
function onSectionEnd() {
|
|
// Clear out the cached params in preparation for the next operation
|
|
cachedParams = {};
|
|
}
|
|
|
|
// Called after all processing finishes
|
|
// Tidy up a few things and store our JSON payload file
|
|
function onClose() {
|
|
// Update the properties that had to wait until all data was processed
|
|
updateCalculatedPropertyValues();
|
|
|
|
// Write the final container object as JSON
|
|
writeln(JSON.stringify(setupSheetObj, null, 0));
|
|
}
|
|
|
|
// Calculate values in the container object based on other data
|
|
function updateCalculatedPropertyValues() {
|
|
setupSheetObj.summary.properties.maxZ = Math.max.apply(null, runningValues.zVals);
|
|
setupSheetObj.summary.properties.minZ = Math.min.apply(null, runningValues.zVals);
|
|
setupSheetObj.summary.properties.maxFeedrate = Math.max.apply(null, runningValues.feedrates);
|
|
setupSheetObj.summary.properties.maxSpindleSpeed = Math.max.apply(null, runningValues.spindleSpeeds);
|
|
setupSheetObj.summary.properties.numSetups = setupSheetObj.setups.length;
|
|
setupSheetObj.summary.properties.numOperations = setupSheetObj.operations.length;
|
|
setupSheetObj.summary.properties.numTools = Object.keys(runningValues.tools).length;
|
|
setupSheetObj.summary.properties.tools = getToolList();
|
|
setupSheetObj.summary.properties.cuttingDistance = runningValues.cuttingDistance;
|
|
setupSheetObj.summary.properties.rapidDistance = runningValues.rapidDistance;
|
|
setupSheetObj.summary.properties.cycleTime = runningValues.cycleTime; // missing rapid time
|
|
|
|
// Update the "operationList" property of each setup with an array
|
|
// containing the id's of its child operations. Note, once done, we
|
|
// no longer need (or want) the setup's id property, so remove it.
|
|
setupSheetObj.setups.forEach(function (setup) {
|
|
setup.operationList = runningValues.operationGroups[setup.id];
|
|
delete setup.id;
|
|
});
|
|
|
|
// Insert some aggregated tool properties
|
|
insertAggregateToolProperties();
|
|
|
|
// Reorder the tool objects in ascending order by tool number
|
|
setupSheetObj.tools.sort(function(t1, t2) {
|
|
return t1.properties.number - t2.properties.number;
|
|
});
|
|
}
|
|
|
|
// Add a summary object to the container, but only if
|
|
// this is the first operation of the entire process
|
|
function addSummaryObject() {
|
|
if (isFirstSection()) {
|
|
const image = getImageFromTempFolder(modelImagePath);
|
|
const imageArray = image ? [image] : [];
|
|
setupSheetObj.summary.images = imageArray;
|
|
setupSheetObj.summary.properties = getSummaryProperties();
|
|
}
|
|
}
|
|
|
|
// Get a cached parameter value or null if the parameter is undefined
|
|
function getParamValueOrNull(param) {
|
|
return (cachedParams[param] !== undefined) ? cachedParams[param] : null;
|
|
}
|
|
|
|
// Get a set of operation properties as a JSON object
|
|
function getOperationProperties(tool) {
|
|
const isJet = currentSection.getType() === TYPE_JET;
|
|
const isMill = currentSection.getType() === TYPE_MILLING;
|
|
const isTurn = currentSection.getType() === TYPE_TURNING;
|
|
const useCoolant = tool.coolant !== COOLANT_OFF;
|
|
const isProbeOp = isProbeOperation();
|
|
|
|
// grab some operation-oriented data from various post methods
|
|
const maxZ = currentSection.getGlobalZRange().getMaximum();
|
|
const minZ = currentSection.getGlobalZRange().getMinimum();
|
|
const feed = currentSection.getMaximumFeedrate();
|
|
let spindleSpeed = currentSection.getMaximumSpindleSpeed();
|
|
const cuttingDistance = currentSection.getCuttingDistance();
|
|
const rapidDistance = currentSection.getRapidDistance();
|
|
const cycleTime = currentSection.getCycleTime();
|
|
|
|
let surfaceSpeed = null;
|
|
if (currentSection.getType() === TYPE_TURNING) {
|
|
if (currentSection.getTool().getSpindleMode() === SPINDLE_CONSTANT_SURFACE_SPEED) {
|
|
surfaceSpeed = currentSection.getTool().surfaceSpeed;
|
|
spindleSpeed = null;
|
|
}
|
|
}
|
|
|
|
let jetCutType = null;
|
|
let quality = null;
|
|
if (isJet) {
|
|
quality = currentSection.quality;
|
|
switch (currentSection.jetMode) {
|
|
case JET_MODE_THROUGH:
|
|
jetCutType = localize("Through cutting");
|
|
break;
|
|
case JET_MODE_ETCHING:
|
|
jetCutType = localize("Etching");
|
|
break;
|
|
case JET_MODE_VAPORIZE:
|
|
jetCutType = localize("Vaporize");
|
|
break;
|
|
}
|
|
}
|
|
|
|
// store these values for future aggregation / processing
|
|
runningValues.zVals.push(maxZ);
|
|
runningValues.zVals.push(minZ);
|
|
runningValues.feedrates.push(feed);
|
|
runningValues.spindleSpeeds.push(spindleSpeed);
|
|
runningValues.cuttingDistance += cuttingDistance;
|
|
runningValues.rapidDistance += rapidDistance;
|
|
runningValues.cycleTime += cycleTime;
|
|
|
|
let maxStepDown = null;
|
|
if (cachedParams["operation:maximumStepdown"] !== undefined && cachedParams["operation:maximumStepdown"] > 0) {
|
|
maxStepDown = cachedParams["operation:maximumStepdown"];
|
|
}
|
|
|
|
let maxStepOver = null;
|
|
if (cachedParams["operation:maximumStepover"] !== undefined) {
|
|
maxStepOver = cachedParams["operation:maximumStepover"];
|
|
} else if (cachedParams["operation:stepover"] !== undefined) {
|
|
maxStepOver = cachedParams["operation:stepover"];
|
|
}
|
|
|
|
//Stock to leave for milling operations
|
|
let radialStockToLeave = cachedParams["operation:stockToLeave"];
|
|
let axialStockToLeave = cachedParams["operation:verticalStockToLeave"];
|
|
let stockToLeave = null;
|
|
|
|
if (radialStockToLeave !== undefined && axialStockToLeave !== undefined) {
|
|
if (radialStockToLeave === axialStockToLeave) {
|
|
stockToLeave = radialStockToLeave;
|
|
radialStockToLeave = null;
|
|
axialStockToLeave = null;
|
|
}
|
|
} else if (radialStockToLeave !== undefined) {
|
|
axialStockToLeave = null;
|
|
} else if (axialStockToLeave !== undefined) {
|
|
radialStockToLeave = null;
|
|
} else {
|
|
radialStockToLeave = null;
|
|
axialStockToLeave = null;
|
|
}
|
|
|
|
//Finish allowance for turning operations
|
|
let xStockToLeave = cachedParams["operation:xStockToLeave"];
|
|
let zStockToLeave = cachedParams["operation:zStockToLeave"];
|
|
let finishAllowance = null;
|
|
|
|
if (xStockToLeave !== undefined && zStockToLeave !== undefined) {
|
|
if (xStockToLeave === zStockToLeave) {
|
|
finishAllowance = xStockToLeave;
|
|
xStockToLeave = null;
|
|
zStockToLeave = null;
|
|
}
|
|
} else if (xStockToLeave !== undefined) {
|
|
zStockToLeave = null;
|
|
} else if (zStockToLeave !== undefined) {
|
|
xStockToLeave = null;
|
|
} else {
|
|
xStockToLeave = null;
|
|
zStockToLeave = null;
|
|
}
|
|
|
|
// Note, the properties in this returned object need to be kept in
|
|
// sync with the object returned by getEmptyOperationProperties()
|
|
return {
|
|
coolant: !isProbeOp && (!isJet || useCoolant) ? getCoolantDescription(tool.coolant) : null,
|
|
compensation: null,
|
|
cuttingDistance: isProbeOp ? null : cuttingDistance,
|
|
cuttingType: jetCutType,
|
|
cycleTime: isProbeOp ? null : cycleTime,
|
|
description: getParamValueOrNull("operation-comment"),
|
|
feedratePerRevolution: isProbeOp || currentSection.feedMode != FEED_PER_REVOLUTION ? null : getParamValueOrNull("operation:tool_feedCuttingRel"),
|
|
loadDeviation: getParamValueOrNull("operation:loadDeviation"),
|
|
maxFeedrate: isProbeOp ? null : feed,
|
|
maxSpindleSpeed: (!isTurn && !isMill) || isProbeOp ? null : spindleSpeed,
|
|
maxStepdown: maxStepDown,
|
|
maxStepover: maxStepOver,
|
|
maxZ: is3D() ? maxZ : null,
|
|
minZ: is3D() ? minZ : null,
|
|
notes: getParamValueOrNull("notes"),
|
|
optimalLoad: getParamValueOrNull("operation:optimalLoad"),
|
|
patternGroup: getPatternGroupName(currentSection),
|
|
quality: quality,
|
|
rapidDistance: isProbeOp ? null : rapidDistance,
|
|
safeToolDiameter: null,
|
|
stockToLeave: stockToLeave !== undefined ? stockToLeave : null,
|
|
radialStockToLeave: radialStockToLeave !== undefined ? radialStockToLeave : null,
|
|
axialStockToLeave: axialStockToLeave !== undefined ? axialStockToLeave : null,
|
|
finishAllowance: finishAllowance !== undefined ? finishAllowance : null,
|
|
xStockToLeave: xStockToLeave !== undefined ? xStockToLeave : null,
|
|
zStockToLeave: zStockToLeave !== undefined ? zStockToLeave : null,
|
|
strategy: cachedParams["operation-strategy"] ? getStrategyDescription(cachedParams["operation-strategy"]) : null,
|
|
surfaceSpeed: isProbeOp ? null : surfaceSpeed,
|
|
tolerance: getParamValueOrNull("operation:tolerance"),
|
|
wcs: currentSection.workOffset
|
|
}
|
|
}
|
|
|
|
// Get a set of setup properties as a JSON object
|
|
function getSetupProperties() {
|
|
return {
|
|
description: getParamValueOrNull("job-description"),
|
|
notes: getParamValueOrNull("job-notes"),
|
|
part: {
|
|
x: cachedParams["part-upper-x"] - cachedParams["part-lower-x"],
|
|
y: cachedParams["part-upper-y"] - cachedParams["part-lower-y"],
|
|
z: cachedParams["part-upper-z"] - cachedParams["part-lower-z"]
|
|
},
|
|
stock: {
|
|
x: cachedParams["stock-upper-x"] - cachedParams["stock-lower-x"],
|
|
y: cachedParams["stock-upper-y"] - cachedParams["stock-lower-y"],
|
|
z: cachedParams["stock-upper-z"] - cachedParams["stock-lower-z"]
|
|
},
|
|
stockLower: {
|
|
x: cachedParams["stock-lower-x"],
|
|
y: cachedParams["stock-lower-y"],
|
|
z: cachedParams["stock-lower-z"]
|
|
},
|
|
stockUpper: {
|
|
x: cachedParams["stock-upper-x"],
|
|
y: cachedParams["stock-upper-y"],
|
|
z: cachedParams["stock-upper-z"]
|
|
},
|
|
wcs: currentSection.workOffset
|
|
}
|
|
}
|
|
|
|
// Get a set of summary properties as a JSON object
|
|
function getSummaryProperties() {
|
|
var now = new Date();
|
|
return {
|
|
creationDate: now.toLocaleDateString() + " " + now.toLocaleTimeString(),
|
|
cuttingDistance: getParamValueOrNull("cuttingDistance"),
|
|
cycleTime: getParamValueOrNull("cycleTime"),
|
|
designDocument: getParamValueOrNull("document-path"),
|
|
maxFeedrate: getParamValueOrNull("maxFeedrate"),
|
|
maxSpindleSpeed: getParamValueOrNull("maxSpindleSpeed"),
|
|
maxZ: getParamValueOrNull("maxZ"),
|
|
minZ: getParamValueOrNull("minZ"),
|
|
numOperations: getParamValueOrNull("numOperations"),
|
|
numSetups: getParamValueOrNull("numSetups"),
|
|
numTools: getParamValueOrNull("numTools"),
|
|
productVersion: getParamValueOrNull("generated-by"),
|
|
programComment: programComment,
|
|
rapidDistance: getParamValueOrNull("rapidDistance"),
|
|
tools: null // this is updated later in updateCalculatedPropertyValues()
|
|
}
|
|
}
|
|
|
|
// Get a set of tool properties as a JSON object
|
|
function getToolProperties(tool) {
|
|
const isTurning = tool.isTurningTool();
|
|
const isJet = !isTurning && tool.isJetTool();
|
|
const isDrill = !isTurning && tool.isDrill();
|
|
|
|
const isTurningGrooving = tool.type === TOOL_TURNING_GROOVING;
|
|
const isTurningGeneral = tool.type === TOOL_TURNING_GENERAL;
|
|
const isTurningBoring = tool.type === TOOL_TURNING_BORING;
|
|
const isTurningThreading = tool.type === TOOL_TURNING_THREADING;
|
|
|
|
let edgeLength = null;
|
|
let inscribedCircle = null;
|
|
|
|
// If we have values for both edgeLength and inscribedCircleDiameter, use only one
|
|
// or the other based on the current unit system. While this might seem odd, it's
|
|
// apparently the industry standard way of defining the size of a turning insert.
|
|
if ((isTurningGeneral || isTurningBoring) && tool.inscribedCircleDiameter !== undefined
|
|
&& tool.edgeLength !== undefined) {
|
|
if (unit === MM && tool.edgeLength > 0) {
|
|
edgeLength = tool.edgeLength;
|
|
} else {
|
|
inscribedCircle = tool.inscribedCircleDiameter;
|
|
}
|
|
}
|
|
|
|
return {
|
|
comment: tool.comment ? tool.comment : null,
|
|
compensation: getCompensationDescription(tool),
|
|
cornerRadius: !isTurning && tool.cornerRadius ? tool.cornerRadius : null,
|
|
crossSection: (isTurningGeneral || isTurningBoring) && tool.crossSection ? tool.crossSection : null,
|
|
diameter: isTurning || isJet ? null : tool.diameter,
|
|
diameterOffset: isJet ? null : isTurning ? tool.compensationOffset : tool.diameterOffset,
|
|
edgeLength: edgeLength,
|
|
flutes: !isTurning && !isJet && tool.numberOfFlutes > 0 ? tool.numberOfFlutes : null,
|
|
holderDescription: tool.holderDescription ? tool.holderDescription : null,
|
|
holderProduct: {
|
|
id: tool.holderProductId ? tool.holderProductId : "",
|
|
link: cachedParams["operation:holder_productLink"] ? cachedParams["operation:holder_productLink"] : ""
|
|
},
|
|
holderType: getHolderTypeName(tool),
|
|
holderVendor: tool.holderVendor ? tool.holderVendor : null,
|
|
inscribedCircle : inscribedCircle,
|
|
insertType: getInsertTypeName(tool),
|
|
jetDiameter: isJet ? tool.jetDiameter : null,
|
|
kerfDiameter: !isJet ? null : tool.jetDiameter,
|
|
length: !isTurning && !isJet ? tool.bodyLength : null,
|
|
lengthOffset: !isJet && !isTurning ? tool.lengthOffset : null,
|
|
manualToolChange: tool.manualToolChange,
|
|
material: tool.material ? getMaterialName(tool.material) : null, // getMaterialName is an api method
|
|
noseRadius: (isTurningGeneral || isTurningGrooving || isTurningBoring) && tool.noseRadius !== undefined && tool.noseRadius > 0 ? tool.noseRadius : null,
|
|
number: tool.getNumber(),
|
|
pitch: isTurningThreading && tool.pitch && tool.pitch > 0 ? tool.pitch : null,
|
|
relief: getReliefAngleDescription(tool),
|
|
taperAngle: !isTurning && !isDrill && tool.taperAngle > 0 && tool.taperAngle < Math.PI ? radToDeg(tool.taperAngle) : null,
|
|
tipAngle: isDrill && tool.taperAngle > 0 && tool.taperAngle < Math.PI ? radToDeg(tool.taperAngle) : null,
|
|
tolerance: (isTurningGeneral || isTurningBoring) && tool.tolerance ? tool.tolerance : null,
|
|
toolDescription: tool.description ? tool.description : null,
|
|
toolProduct: {
|
|
id: tool.productId ? tool.productId : "",
|
|
link: cachedParams["operation:tool_productLink"] ? cachedParams["operation:tool_productLink"] : ""
|
|
},
|
|
toolType: getToolTypeNameLocal(tool),
|
|
toolVendor: tool.vendor ? tool.vendor : null,
|
|
width: isTurningGrooving && tool.grooveWidth ? tool.grooveWidth : null,
|
|
}
|
|
}
|
|
|
|
// Convert radians to degrees
|
|
function radToDeg(radians)
|
|
{
|
|
return radians * (180 / Math.PI);
|
|
}
|
|
|
|
// Checks if the tool is a duplicate in the array runningValues.tools
|
|
function isDuplicateTool(tool) {
|
|
for (var i in runningValues.tools) {
|
|
if (runningValues.tools[i].toolId === tool.toolId) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// Add a tool object to the container if it's a new tool.
|
|
function addToolObject(tool) {
|
|
// Add this tool only if it's not already in the cache
|
|
const toolId = parseInt(tool.toolId);
|
|
if (!isDuplicateTool(tool)) {
|
|
// Add the new tool to the cache
|
|
runningValues.tools[toolId] = tool;
|
|
|
|
// Create the initial tool object
|
|
const toolObj = {
|
|
id: toolId,
|
|
images: [getToolAsSVGObject(tool)],
|
|
properties: getToolProperties(tool)
|
|
};
|
|
|
|
setupSheetObj.tools.push(toolObj);
|
|
}
|
|
}
|
|
|
|
// Add a setup object to the container, but only if the current set of
|
|
// cached params has a "job-description" item, which is only available
|
|
// with the first operation of each setup.
|
|
function addSetupObject() {
|
|
if (cachedParams["job-description"]) {
|
|
|
|
// Cache a new object key of this setup's id. The value will be
|
|
// a running array of operation id's that belong to it.
|
|
runningValues.operationGroups[currentSection.getJobId()] = [];
|
|
|
|
// Add the id of each setup the current operation belongs to to the global setupIds array
|
|
var operationSetupIds = setupSheetObj.setups.map(function (el) { return el.id; });
|
|
runningValues.setupIds = [].concat(runningValues.setupIds, operationSetupIds);
|
|
|
|
// Add this setup to the container if it has not been added before to the global setups array
|
|
if (runningValues.setupIds.indexOf(currentSection.getJobId()) === -1) {
|
|
const image = getImageFromTempFolder(cachedParams["job-image"]);
|
|
const imageArray = image ? [image] : [];
|
|
setupSheetObj.setups.push({
|
|
id: currentSection.getJobId(), // temporary (removed before JSON creation)
|
|
images: imageArray,
|
|
properties: getSetupProperties()
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
// Add an operation object to the container.
|
|
// Note that we get it's id from the runningValues, as it will
|
|
// have been added by addToolObject.
|
|
function addOperationObject(tool) {
|
|
if (currentSection.getForceToolChange && currentSection.getForceToolChange()) {
|
|
addForceToolChange();
|
|
}
|
|
|
|
// Add this operation's id to the running collection of id's belonging to the same setup
|
|
runningValues.operationGroups[currentSection.getJobId()].
|
|
push(cachedParams["autodeskcam:operation-id"]);
|
|
|
|
const image = getImageFromTempFolder(cachedParams["operation:associatedView"]);
|
|
const imageArray = image ? [image] : [];
|
|
|
|
const operation = {
|
|
id: cachedParams["autodeskcam:operation-id"],
|
|
images: imageArray,
|
|
tool: {id: parseInt(tool.toolId)},
|
|
properties: getOperationProperties(tool)
|
|
};
|
|
|
|
// update compensation and safe tool diameter parameters if required
|
|
updateOperationCompensationParams(operation, tool);
|
|
|
|
// add the operation to the container
|
|
setupSheetObj.operations.push(operation);
|
|
}
|
|
|
|
// Create a Manual NC operation.
|
|
// Note: operation id is not exported for Manual NC, hard coded as 0.
|
|
function createManualNCOperation() {
|
|
// Get an empty operation properties object (all props with null values)
|
|
// and then update the strategy name
|
|
var operationProps = getEmptyOperationProperties();
|
|
operationProps.strategy = localize("Manual NC");
|
|
const operation = {
|
|
id: 0,
|
|
images: [],
|
|
properties: operationProps
|
|
};
|
|
|
|
return operation;
|
|
}
|
|
|
|
// Process Manual NC operation - "Force tool change"
|
|
// Special case that does not have function callback, invoked with following section.
|
|
function addForceToolChange() {
|
|
var operation = createManualNCOperation();
|
|
operation.properties.description = localize("Force tool change");
|
|
|
|
// add the operation to the container
|
|
setupSheetObj.operations.push(operation);
|
|
}
|
|
|
|
// Update compensation and safe tool diameter parameters if required
|
|
function updateOperationCompensationParams(operation, tool) {
|
|
const compTypeParam = "operation:compensationType";
|
|
const compRadiusParam = "operation:compensationDeltaRadius";
|
|
const compParam = "operation:compensation";
|
|
|
|
const compensationType = cachedParams[compTypeParam] ? cachedParams[compTypeParam] : "computer";
|
|
if (compensationType != "computer") {
|
|
const COMPENSATIONS = { left: localize("left"), right: localize("right"), center: localize("center") };
|
|
const DESCRIPTIONS = { computer: localize("computer"), control: localize("control"), wear: localize("wear"), inverseWear: localize("inverse wear") };
|
|
const compensationDeltaRadius = cachedParams[compRadiusParam] ? cachedParams[compRadiusParam] : 0;
|
|
const compensation = cachedParams[compParam] ? cachedParams[compParam] : localize("center");
|
|
const compensationText = COMPENSATIONS[compensation] ? COMPENSATIONS[compensation] : localize("unspecified");
|
|
const description = DESCRIPTIONS[compensationType] ? DESCRIPTIONS[compensationType] : localize("unspecified");
|
|
operation.properties.compensation = description + " (" + compensationText + ")";
|
|
if (!tool.isTurningTool()) {
|
|
operation.properties.safeToolDiameter = tool.diameter + (2 * compensationDeltaRadius);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Return the unit system used for the values in the JSON output
|
|
function getUnitSystem() {
|
|
return unit === MM ? "mm" : "inch";
|
|
}
|
|
|
|
// Return the title
|
|
function getTitle() {
|
|
let title = localize("Setup Sheet");
|
|
if (programName) {
|
|
title = localize("Setup Sheet for Program") + " " + programName;
|
|
}
|
|
return title;
|
|
}
|
|
|
|
// Build a sorted tool list string ("T2 T4 T49") from the cached tools
|
|
function getToolList() {
|
|
const tNumArray = [];
|
|
Object.keys(runningValues.tools).forEach(function(key) {
|
|
tNumArray.push(runningValues.tools[key].number);
|
|
});
|
|
|
|
return tNumArray.
|
|
sort(function(a, b) {
|
|
return a - b;
|
|
}).
|
|
map(function(t) {return "T" + t;}).
|
|
join(" ");
|
|
}
|
|
|
|
// Return the extension (with no leading dot) of the specified file name
|
|
// or an empty string if no extension exists.
|
|
function getFileExtension(filename) {
|
|
const a = filename.split(".");
|
|
if (a.length === 1) {return "";} // normal file, no extension
|
|
if (a[0] === "" && a.length === 2) {return "";} // hidden file, no extension
|
|
return a.pop().toLowerCase();
|
|
}
|
|
|
|
// Return a formatted image object for the specified PNG image file
|
|
// The image is stored in base64 format.
|
|
function getImageAsBase64PngObject(imageFile) {
|
|
const pngMimeType = "image/png";
|
|
|
|
let imgObj;
|
|
if (FileSystem.isFile(imageFile)) {
|
|
if (typeof BinaryFile == "function" && typeof Base64 == "function") {
|
|
const extension = getFileExtension(imageFile);
|
|
if (supportedImageTypes[extension] == pngMimeType) {
|
|
imgObj = {
|
|
mimetype: pngMimeType,
|
|
content: {
|
|
data: "data:" + pngMimeType + ";base64," +
|
|
Base64.btoa(BinaryFile.loadBinary(imageFile))
|
|
}
|
|
};
|
|
}
|
|
}
|
|
}
|
|
|
|
return imgObj;
|
|
}
|
|
|
|
// Generate an SVG polygon element from a set of points
|
|
function getSvgPolygonFromPoints(pointsArray, className) {
|
|
let p = [];
|
|
for (let i = 0; i < pointsArray.length; ++i) {
|
|
p.push(pointsArray[i].x + " " + pointsArray[i].y);
|
|
}
|
|
|
|
return {
|
|
polygon: {
|
|
className: className,
|
|
points: p.join(',')
|
|
}
|
|
};
|
|
}
|
|
|
|
// Generate an SVG rect element from a set of 4 points
|
|
// Note, p0 is lower left corner, moving CCW
|
|
function getSvgRectangleFromPoints(pointsArray, className) {
|
|
const x = pointsArray[0].x;
|
|
const y = pointsArray[0].y;
|
|
const width = pointsArray[1].x - pointsArray[0].x;
|
|
const height = pointsArray[2].y - pointsArray[1].y;
|
|
|
|
return {
|
|
rect: {
|
|
className: className,
|
|
x: x,
|
|
y: y,
|
|
width: width,
|
|
height: height
|
|
}
|
|
};
|
|
}
|
|
|
|
// Generate tool holder geometry from a number of SVG "rect" and "polygon" elements
|
|
function getSvgHolderGeometry(holder) {
|
|
const toler = 0.001;
|
|
let svgElemsAsJson = [];
|
|
let yOffset = 0;
|
|
|
|
if (holder && holder.hasSections()) {
|
|
const numSects = holder.getNumberOfSections();
|
|
let radPrev;
|
|
let rad;
|
|
let points = [];
|
|
|
|
// Calculate the 4 corner points for the current section from the available
|
|
// length and diameter info. The result could be a rectangle or an isosceles
|
|
// trapezoid (with the top or bottom being the larger dimension)
|
|
//
|
|
// p4 ------------- p3 p4 --------------- p3
|
|
// | | \ /
|
|
// | | or \ /
|
|
// p1 ------+------ p2 p1 ----+---- p2
|
|
// x0 x0
|
|
//
|
|
for (let i = 0; i < numSects; ++i) {
|
|
if (i === 0) {
|
|
// For the first section, add the points that form the lower edge
|
|
rad = radPrev = holder.getDiameter(i) / 2;
|
|
points.push({x: -rad, y: 0});
|
|
points.push({x: rad, y: 0});
|
|
} else {
|
|
// Add the next 2 points to form the upper edge of the section
|
|
// (should always be points 3 and 4 in the array)
|
|
yOffset += holder.getLength(i - 1); // track section "stack height" in space
|
|
rad = holder.getDiameter(i) / 2;
|
|
let height = holder.getLength(i) + yOffset;
|
|
|
|
points.push({x: rad, y: height});
|
|
points.push({x: -rad, y: height});
|
|
|
|
// See if the current section has any height
|
|
let sectionHasHeight = holder.getLength(i) > toler;
|
|
|
|
// If the current section has height...
|
|
// Create either an SVG rect or polygon depending on the shape.
|
|
// They're shaded differently, so they need different CSS class names
|
|
if (sectionHasHeight) {
|
|
if (Math.abs(radPrev - rad) < toler ) {
|
|
svgElemsAsJson.push(getSvgRectangleFromPoints(points, "holderRect"));
|
|
} else {
|
|
// If this is the *last* element, shade it like the rects
|
|
let className = i === numSects - 1 ? "holderRect" : "holderTrap";
|
|
svgElemsAsJson.push(getSvgPolygonFromPoints(points, className));
|
|
}
|
|
}
|
|
|
|
// Copy point 4 to point 1 and point 3 to point 2 as the lower edge of the next section.
|
|
// (See above line drawings for details...)
|
|
// Truncate the array to the first 2 points. We'll add the last 2 in the next iteration.
|
|
points[0] = points[3];
|
|
points[1] = points[2];
|
|
points.length = 2;
|
|
|
|
radPrev = rad;
|
|
}
|
|
}
|
|
}
|
|
|
|
return svgElemsAsJson;
|
|
}
|
|
|
|
// Return an object containing the data required to render a tool
|
|
// and its holder as SVG
|
|
function getToolAsSVGObject(tool) {
|
|
let svgElemsAsJson = [];
|
|
let bounds = {};
|
|
let transform;
|
|
|
|
if (!tool.isTurningTool()) {
|
|
holder = tool.holder;
|
|
|
|
// Build a transform that (during rendering) will place the center of
|
|
// this tool's bounding box at 0,0 and will flip the data in Y to draw
|
|
// the tool "right side up"
|
|
transform = 'scale(1,-1) translate(0,' + -((tool.holderLength - tool.bodyLength) / 2) + ')';
|
|
|
|
// Get the holder geometry as SVG data
|
|
svgElemsAsJson = getSvgHolderGeometry(holder);
|
|
|
|
// Add the tool profile as an SVG path
|
|
let toolPath = tool.getCutterProfileAsSVGPath();
|
|
svgElemsAsJson.push({
|
|
path: {
|
|
className: "tool",
|
|
transform: 'translate(0,' + -tool.bodyLength + ')',
|
|
d: toolPath
|
|
}
|
|
});
|
|
|
|
let bbox = tool.getExtent(true);
|
|
let width = bbox.upper.x - bbox.lower.x;
|
|
let height = bbox.upper.y - bbox.lower.y;
|
|
bounds = {
|
|
minX: bbox.lower.x,
|
|
minY: -(height/2),
|
|
width: width,
|
|
height: height
|
|
}
|
|
} else {
|
|
let bbox = tool.getExtent(true);
|
|
let width = bbox.upper.x - bbox.lower.x;
|
|
let height = bbox.upper.y - bbox.lower.y;
|
|
bounds = {
|
|
minX: -width/2,
|
|
minY: -height/2,
|
|
width: width,
|
|
height: height
|
|
}
|
|
let xTrans = -((width / 2) + bbox.lower.x);
|
|
let yTrans = -((height / 2) + bbox.lower.y);
|
|
transform = 'translate(' + xTrans + ' ' + yTrans + ')';
|
|
svgElemsAsJson.push({
|
|
path: {
|
|
className: "holderRect",
|
|
d: tool.getHolderProfileAsSVGPath()
|
|
}
|
|
});
|
|
svgElemsAsJson.push({
|
|
path: {
|
|
className: "tool",
|
|
d: tool.getCutterProfileAsSVGPath()
|
|
}
|
|
});
|
|
}
|
|
|
|
return {
|
|
// the mime type of SVG data
|
|
mimetype: "image/svg+xml",
|
|
// content specific to the SVG image type
|
|
content: {
|
|
// bounds of all SVG path data (useful in SVG viewbox object)
|
|
bounds: bounds,
|
|
transform: transform,
|
|
// all SVG path data associated with this tool
|
|
geometry: svgElemsAsJson
|
|
}
|
|
};
|
|
}
|
|
|
|
// Return an object used for tracking intermediate values
|
|
function getRunningValuesObject() {
|
|
return {
|
|
tools: {},
|
|
operationGroups: {},
|
|
patternGroups: {},
|
|
zVals: [],
|
|
feedrates: [],
|
|
spindleSpeeds: [],
|
|
cuttingDistance: 0,
|
|
rapidDistance: 0,
|
|
cycleTime: 0,
|
|
};
|
|
}
|
|
|
|
// Convert a specified integer value to a base26 number-string containing only
|
|
// the chars A-Z
|
|
// (0 = A, 25 = Z, 26 = AA, 52 = BA, ... )
|
|
function getBase26String(n) {
|
|
const base = 26;
|
|
if (n < base) {
|
|
return String.fromCharCode(65 + n); // 65 is the ASCII code for 'A'
|
|
} else {
|
|
return getBase26String((n / base) - 1) + String.fromCharCode(65 + (n % base));
|
|
}
|
|
}
|
|
|
|
// Return a string rep of a turning tool's (numeric) compensation mode.
|
|
// Returns null if the tool is not a turning tool.
|
|
function getCompensationDescription(tool) {
|
|
var desc = null;
|
|
if (tool.isTurningTool()) {
|
|
switch (tool.getCompensationMode()) {
|
|
case TOOL_COMPENSATION_INSERT_CENTER:
|
|
desc = localize("Insert center");
|
|
break;
|
|
case TOOL_COMPENSATION_TIP:
|
|
desc = localize("Tip");
|
|
break;
|
|
case TOOL_COMPENSATION_TIP_CENTER:
|
|
desc = localize("Tip center");
|
|
break;
|
|
case TOOL_COMPENSATION_TIP_TANGENT:
|
|
desc = localize("Tip tangent");
|
|
break;
|
|
}
|
|
}
|
|
return desc;
|
|
}
|
|
|
|
// Return a string rep of a turning tool's (numeric) "relief angle" property.
|
|
// Returns "Custom <ang>deg" if the angle is non-standard and null if the tool
|
|
// is not a turning tool.
|
|
function getReliefAngleDescription(tool) {
|
|
let desc = null;
|
|
if (tool.isTurningTool() && tool.reliefAngle !== undefined) {
|
|
|
|
var turningReliefAngles = [
|
|
{id:"N", value:0},
|
|
{id:"A", value:3},
|
|
{id:"B", value:5},
|
|
{id:"C", value:7},
|
|
{id:"P", value:11},
|
|
{id:"D", value:15},
|
|
{id:"E", value:20},
|
|
{id:"F", value:25},
|
|
{id:"G", value:30}
|
|
];
|
|
|
|
let id = localize("Custom");
|
|
let value = tool.reliefAngle;
|
|
|
|
// const does not work here, but we'll get a linter complaint unless we disable the rule
|
|
// eslint-disable-next-line prefer-const
|
|
for (let item in turningReliefAngles) {
|
|
const thisItem = turningReliefAngles[item];
|
|
if (Math.abs(thisItem.value - value) < 1e-3) {
|
|
id = thisItem.id;
|
|
value = thisItem.value;
|
|
break;
|
|
}
|
|
}
|
|
desc = id + " " + value + "deg";
|
|
}
|
|
return desc;
|
|
}
|
|
|
|
// Return a Manual NC command display name for a specified Manual NC command or the
|
|
// command name itself if a display name is not available.
|
|
function getManualNCCommandName(command) {
|
|
var cmdStringId = getCommandStringId(command);
|
|
const manaulNCCmdNames = {
|
|
"COMMAND_COMMENT": localize("Comment"),
|
|
"COMMAND_STOP": localize("Stop"),
|
|
"COMMAND_OPTIONAL_STOP": localize("Optional Stop"),
|
|
"COMMAND_DWELL": localize("Dwell"),
|
|
"COMMAND_BREAK_CONTROL": localize("Tool break control"),
|
|
"COMMAND_TOOL_MEASURE": localize("Measure tool"),
|
|
"COMMAND_START_CHIP_TRANSPORT": localize("Start chip transport"),
|
|
"COMMAND_STOP_CHIP_TRANSPORT": localize("Stop chip transport"),
|
|
"COMMAND_OPEN_DOOR": localize("Open door"),
|
|
"COMMAND_CLOSE_DOOR": localize("Close door"),
|
|
"COMMAND_CALIBRATE": localize("Calibrate"),
|
|
"COMMAND_VERIFY": localize("Verify"),
|
|
"COMMAND_CLEAN": localize("Clean"),
|
|
"COMMAND_ACTION": localize("Action"),
|
|
"COMMAND_PRINT_MESSAGE": localize("Print message"),
|
|
"COMMAND_DISPLAY_MESSAGE": localize("Display message"),
|
|
"COMMAND_ALARM": localize("Alarm"),
|
|
"COMMAND_ALERT": localize("Alert"),
|
|
"COMMAND_PASS_THROUGH": localize("Pass through"),
|
|
"COMMAND_CALL_PROGRAM": localize("Call program")
|
|
};
|
|
|
|
return manaulNCCmdNames[cmdStringId] ? manaulNCCmdNames[cmdStringId] : cmdStringId;
|
|
}
|
|
|
|
// Return a strategy description for a specified strategy name or the
|
|
// strategy name itself if a description is not available.
|
|
function getStrategyDescription(strategyName) {
|
|
var strategies = {
|
|
"drill": localize("Drilling"),
|
|
"probe": localize("Probe WCS"),
|
|
"probe_geometry": localize("Probe Geometry"),
|
|
"inspectSurface": localize("Inspect"),
|
|
"rotary_finishing": localize("Rotary"),
|
|
"steep_and_shallow": localize("Steep and Shallow"),
|
|
"face": localize("Facing"),
|
|
"path3d": localize("3D Path"),
|
|
"pocket2d": localize("Pocket 2D"),
|
|
"contour2d": localize("Contour 2D"),
|
|
"adaptive2d": localize("Adaptive 2D"),
|
|
"slot": localize("Slot"),
|
|
"circular": localize("Circular"),
|
|
"bore": localize("Bore"),
|
|
"thread": localize("Thread"),
|
|
"jet2d": localize("Profile 2D"),
|
|
"contour_new": localize("Contour"),
|
|
"contour": localize("Contour"),
|
|
"parallel_new": localize("Parallel"),
|
|
"parallel": localize("Parallel"),
|
|
"pocket_new": localize("Pocket"),
|
|
"pocket": localize("Pocket"),
|
|
"adaptive": localize("Adaptive"),
|
|
"horizontal_new": localize("Horizontal"),
|
|
"horizontal": localize("Horizontal"),
|
|
"blend": localize("Blend"),
|
|
"flow": localize("Flow"),
|
|
"morph": localize("Morph"),
|
|
"pencil_new": localize("Pencil"),
|
|
"pencil": localize("Pencil"),
|
|
"project": localize("Project"),
|
|
"ramp": localize("Ramp"),
|
|
"radial_new": localize("Radial"),
|
|
"radial": localize("Radial"),
|
|
"scallop_new": localize("Scallop"),
|
|
"scallop": localize("Scallop"),
|
|
"morphed_spiral": localize("Morphed Spiral"),
|
|
"spiral_new": localize("Spiral"),
|
|
"spiral": localize("Spiral"),
|
|
"swarf5d": localize("Multi-Axis Swarf"),
|
|
"multiAxisContour": localize("Multi-Axis Contour"),
|
|
"multiAxisBlend": localize("Multi-Axis Blend"),
|
|
"turningRoughing": localize("Turning Roughing"),
|
|
"turningProfileRoughing": localize("Turning Profile Roughing"),
|
|
"turningProfileFinishing": localize("Turning Profile Finishing"),
|
|
"turningProfileGroove": localize("Turning Profile Groove"),
|
|
"turningPart": localize("Turning Part"),
|
|
"turningFace": localize("Turning Face"),
|
|
"turningGroove": localize("Turning Single Groove"),
|
|
"turningChamfer": localize("Turning Chamfer"),
|
|
"turningThread": localize("Turning Thread"),
|
|
"turningStockTransfer": localize("Turning Stock Transfer"),
|
|
"turningSecondarySpindleGrab": localize("Subspindle Grab"),
|
|
"turningSecondarySpindlePull": localize("Bar Pull"),
|
|
"turningSecondarySpindleReturn": localize("Subspindle Return")
|
|
};
|
|
|
|
return strategies[strategyName] ? strategies[strategyName] : strategyName;
|
|
}
|
|
|
|
// If the specified operation is a pattern, return a string representing its
|
|
// pattern group name. The first pattern group is named "A" and the value
|
|
// increments as a base26 string (A, B, ..., Z, AA, AB, ... ZZ, AAA, AAB,
|
|
// ..., ZZZ, ...) for each new patterned operation. Patterened operations
|
|
// with the same operationID will have matching pattern group names.
|
|
// Return null for operations that are not patterns.
|
|
function getPatternGroupName(section) {
|
|
let name = null;
|
|
if (section.isPatterned()) {
|
|
const id = section.getPatternId();
|
|
if (!runningValues.patternGroups[id]) {
|
|
runningValues.patternGroups[id] =
|
|
getBase26String(Object.keys(runningValues.patternGroups).length);
|
|
}
|
|
name = runningValues.patternGroups[id];
|
|
}
|
|
return name;
|
|
}
|
|
|
|
// Return the basic shell of the setup object we're building.
|
|
// This ensures the object contains the necessary sections by default.
|
|
function getInitialSetupObject() {
|
|
return {
|
|
version: 1,
|
|
unitSystem: getUnitSystem(),
|
|
title: getTitle(),
|
|
summary: {
|
|
images: [],
|
|
properties: {}
|
|
},
|
|
tools: [],
|
|
setups: [],
|
|
operations: []
|
|
};
|
|
}
|
|
|
|
// Return a string rep of a turning tool's (numeric) "holder type" property.
|
|
// Returns null if the type isn't found or the tool is not a turning tool.
|
|
function getHolderTypeName(tool) {
|
|
let desc = null;
|
|
if (tool.isTurningTool()) {
|
|
var holderDesc = [
|
|
localize("No holder"), localize("ISO A"), localize("ISO B"),
|
|
localize("ISO C"), localize("ISO D"), localize("ISO E"),
|
|
localize("ISO F"), localize("ISO G"), localize("ISO H"),
|
|
localize("ISO J"), localize("ISO K"), localize("ISO L"),
|
|
localize("ISO M"), localize("ISO N"), localize("ISO P"),
|
|
localize("ISO Q"), localize("ISO R"), localize("ISO S"),
|
|
localize("ISO T"), localize("ISO U"), localize("ISO V"),
|
|
localize("ISO W"), localize("ISO Y"), localize("Offset"),
|
|
localize("Straight"), localize("External"), localize("Internal"),
|
|
localize("Face"), localize("Straight"), localize("Offset"),
|
|
localize("Face"), localize("Boring bar ISO F"), localize("Boring bar ISO G"),
|
|
localize("Boring bar ISO J"), localize("Boring bar ISO K"),
|
|
localize("Boring bar ISO L"), localize("Boring bar ISO P"),
|
|
localize("Boring bar ISO Q"), localize("Boring bar ISO S"),
|
|
localize("Boring bar ISO U"), localize("Boring bar ISO W"),
|
|
localize("Boring bar ISO Y"), localize("Boring bar ISO X")
|
|
];
|
|
|
|
const holderIndex = tool.getHolderType();
|
|
if (holderIndex < holderDesc.length) {
|
|
desc = holderDesc[holderIndex];
|
|
|
|
let hand = "";
|
|
switch (tool.hand) {
|
|
case "L":
|
|
hand = localize("Left");
|
|
break;
|
|
case "R":
|
|
hand = localize("Right");
|
|
break;
|
|
case "N":
|
|
hand = localize("Neutral");
|
|
break;
|
|
}
|
|
|
|
if (hand !== "") {desc += " " + hand;}
|
|
}
|
|
}
|
|
|
|
return desc;
|
|
}
|
|
|
|
// Return a string rep of a turning tool's (numeric) "insert type" property.
|
|
// Returns null if the type isn't found or the tool is not a turning tool.
|
|
function getInsertTypeName(tool) {
|
|
let desc = null;
|
|
if (tool.isTurningTool()) {
|
|
var insertDesc = [
|
|
localize("User defined"), localize("ISO A 85deg"), localize("ISO B 82deg"),
|
|
localize("ISO C 80deg"), localize("ISO D 55deg"), localize("ISO E 75deg"),
|
|
localize("ISO H 120deg"), localize("ISO K 55deg"), localize("ISO L 90deg"),
|
|
localize("ISO M 86deg"), localize("ISO O 135deg"), localize("ISO P 108deg"),
|
|
localize("ISO R round"), localize("ISO S square"), localize("ISO T triangle"),
|
|
localize("ISO V 35deg"), localize("ISO W 80deg"), localize("Round"),
|
|
localize("Radius"), localize("Square"), localize("Chamfer"), localize("40deg"),
|
|
localize("ISO double"), localize("ISO triple"), localize("UTS double"),
|
|
localize("UTS triple"), localize("ISO double V"), localize("ISO triple V"),
|
|
localize("UTS double V"), localize("UTS triple V")
|
|
];
|
|
|
|
const insertIndex = tool.getInsertType();
|
|
if (insertIndex < insertDesc.length) {
|
|
desc = insertDesc[insertIndex];
|
|
}
|
|
}
|
|
|
|
return desc;
|
|
}
|
|
|
|
// Returns the tool type name for a specified tool. The returned value may also
|
|
// contain an additional "LIVE" or "STATIC" suffix string, added based on logic
|
|
// from the original HTML setup post.
|
|
function getToolTypeNameLocal(tool) {
|
|
let toolType = getToolTypeName(tool.type); // Note, this is a post-engine method
|
|
if (tool.isLiveTool && !tool.isTurningTool() && (machineConfiguration.getTurning() || isTurning())) {
|
|
toolType += " " + (tool.isLiveTool() ? localize("LIVE") : localize("STATIC"));
|
|
}
|
|
return toolType;
|
|
}
|
|
|
|
// Returns a base64 image object from the specified PNG file.
|
|
// The file is assumed to be in folder where the post places temporary images.
|
|
// If the file isn't found, or is not a PNG, an empty object is returned.
|
|
function getImageFromTempFolder(file) {
|
|
let imageObj;
|
|
if (file) {
|
|
const path = FileSystem.getCombinedPath(FileSystem.getFolderPath(getOutputPath()), file);
|
|
imageObj = getImageAsBase64PngObject(path);
|
|
}
|
|
return imageObj;
|
|
}
|
|
|
|
function isProbeOperation() {
|
|
return cachedParams["operation-strategy"] && cachedParams["operation-strategy"] === "probe";
|
|
}
|
|
|
|
/**
|
|
Returns the specified coolant as a string.
|
|
*/
|
|
function getCoolantDescription(coolant) {
|
|
switch (coolant) {
|
|
case COOLANT_OFF:
|
|
return localize("Off");
|
|
case COOLANT_FLOOD:
|
|
return localize("Flood");
|
|
case COOLANT_MIST:
|
|
return localize("Mist");
|
|
case COOLANT_THROUGH_TOOL:
|
|
return localize("Through tool");
|
|
case COOLANT_AIR:
|
|
return localize("Air");
|
|
case COOLANT_AIR_THROUGH_TOOL:
|
|
return localize("Air through tool");
|
|
case COOLANT_SUCTION:
|
|
return localize("Suction");
|
|
case COOLANT_FLOOD_MIST:
|
|
return localize("Flood and mist");
|
|
case COOLANT_FLOOD_THROUGH_TOOL:
|
|
return localize("Flood and through tool");
|
|
default:
|
|
return localize("Unknown");
|
|
}
|
|
}
|
|
|
|
// Get an *empty* operation properties object (*all* properties, but *null* values)
|
|
// Note, this property set needs to be kept in sync wtih the property set that's
|
|
// being returned from getOperationProperties
|
|
function getEmptyOperationProperties() {
|
|
return {
|
|
coolant: null,
|
|
compensation: null,
|
|
cuttingDistance: null,
|
|
cuttingType: null,
|
|
cycleTime: null,
|
|
description: null,
|
|
feedratePerRevolution: null,
|
|
loadDeviation: null,
|
|
maxFeedrate: null,
|
|
maxSpindleSpeed: null,
|
|
maxStepdown: null,
|
|
maxStepover: null,
|
|
maxZ: null,
|
|
minZ: null,
|
|
notes: null,
|
|
optimalLoad: null,
|
|
patternGroup: null,
|
|
quality: null,
|
|
rapidDistance: null,
|
|
safeToolDiameter: null,
|
|
stockToLeave: null,
|
|
radialStockToLeave: null,
|
|
axialStockToLeave: null,
|
|
finishAllowance: null,
|
|
xStockToLeave: null,
|
|
zStockToLeave: null,
|
|
strategy: null,
|
|
surfaceSpeed: null,
|
|
tolerance: null,
|
|
wcs: null
|
|
}
|
|
}
|
|
|
|
// Utility function to write all cached parameters and their values
|
|
// to the output file.
|
|
function dumpCachedParams() {
|
|
// const does not work here, but we'll get a linter complaint unless we disable the rule
|
|
// eslint-disable-next-line prefer-const
|
|
for (let prop in cachedParams) {
|
|
writeln(prop + ": " + cachedParams[prop]);
|
|
}
|
|
writeln("------------");
|
|
}
|
|
|
|
function insertAggregateToolProperties() {
|
|
// Iterate through each tool in our JSON object
|
|
setupSheetObj.tools.forEach(function (tool) {
|
|
|
|
// Build an array of all operations (from the JSON object) that use the current tool
|
|
// (matched by the tool's id)
|
|
const matchingOperations = setupSheetObj.operations.filter(function(operation) {
|
|
return operation.tool && operation.tool.id === parseInt(tool.id);
|
|
});
|
|
|
|
// Create some initial values for the properties we want to insert
|
|
let cuttingDistance = 0;
|
|
let rapidDistance = 0;
|
|
let cycleTime = 0;
|
|
let maxFeedrate = Number.NEGATIVE_INFINITY;
|
|
let maxSpindleSpeed = Number.NEGATIVE_INFINITY;
|
|
let minZ = Number.POSITIVE_INFINITY;
|
|
|
|
// Spin through the matching operations and aggregate the values accordingly
|
|
matchingOperations.forEach(function (operation) {
|
|
cuttingDistance += operation.properties.cuttingDistance;
|
|
rapidDistance += operation.properties.rapidDistance;
|
|
cycleTime += operation.properties.cycleTime;
|
|
maxFeedrate = Math.max(maxFeedrate, operation.properties.maxFeedrate);
|
|
maxSpindleSpeed = Math.max(maxSpindleSpeed, operation.properties.maxSpindleSpeed);
|
|
minZ = Math.min(minZ, operation.properties.minZ);
|
|
});
|
|
|
|
// Finally, insert the target properties for this tool
|
|
tool.properties.cuttingDistance = cuttingDistance;
|
|
tool.properties.rapidDistance = rapidDistance;
|
|
tool.properties.cycleTime = cycleTime;
|
|
tool.properties.maxFeedrate = maxFeedrate;
|
|
tool.properties.maxSpindleSpeed = maxSpindleSpeed;
|
|
tool.properties.minZ = minZ;
|
|
});
|
|
}
|