// module: TRUE
/** Model ID for workflow model
* @type {number} */
let model_id = Workflow.ModelIdFromIndex(0);
let unit_system = Workflow.ModelUnitSystemFromIndex(0);
/** Model information for workflow model */
let info = GetModelInfo(model_id);
/** Window ID for workflow model
* @type {number} */
let win_id = -1;
/** Previous state
* @type {number} */
let prev_st;
/** Current state
* @type {number} */
let curr_state;
/** Previous part
* @type {number} */
let prev_pt;
/** List of yielding parts
* @type {number[]} */
let list_yielding = [];
/** List of non-yielding parts
* @type {number[]} */
let list_non_yielding = [];
/** Object with yielding & non_yielding lists */
let test_yielding;
/** D3PLOT plot component
* @type {number} */
let plot_comp = 1;
/** D3PLOT plot type
* @type {number} */
let plot_typ = 1;
/** No user defined contour levels
* @type {boolean} */
let auto_contour = true;
/** Calculate maximum contour values
* @type {boolean} */
let calc_max = true;
/** Workflow initialisation
* @type {boolean} */
let initialised = false;
/** Properties filename
* @type {string} */
let props_filename = null;
/** Exit script without changing properties
* @type {boolean} */
let exit_without_props = false;
import { SavePropFile, LoadPropFile, DelPropFile } from "../../modules/d3plot_properties.js";
import * as guiWdw from "post_strength_check_gui_raw.js";
guiWdw.wdwStrengthCheck.Show(false); /* Show the first window */
/**
* Main callback function to update the yielding parts displayed
*/
export function update_plot()
{
SetCurrentModel(model_id);
win_id = calc_window_id();
auto_contour = !(guiWdw.userDefCB.pushed);
if (auto_contour) /* if automatic contour is used, maximum value calculation is irrelevant */
{
guiWdw.maxValCB.active = false;
guiWdw.maxValLabel.active = false;
calc_max = false;
}
else /* ungrey maximum value label & tickbox */
{
guiWdw.maxValCB.active = true;
guiWdw.maxValLabel.active = true;
calc_max = guiWdw.maxValCB.pushed;
}
/* Do nothing if there's no ZTF file */
if (info.ztf_name == "Not defined")
{
ErrorMessage("There is no ZTF file in the model directory!");
let answer = Window.Error("Strength Check Workflow Error", "There is no ZTF file in the model directory. Yielding parts cannot be evaluated. \nExiting workflow...");
if (answer == Window.OK) exit_strength_check();
}
/* Update total number of states in model */
guiWdw.stateTotal.text = `/ ${info.num_states}`;
/** yielding parts display mode
* @type {number} */
let mode = 1;
switch (guiWdw.displayMode.selectedItem.text.substring(0, 1))
{
case "1": mode = 1; break;
case "2": mode = 2; break;
case "3": mode = 3; break;
default: mode = 1;
}
switch (guiWdw.plotComp.selectedItem.text.substring(0, 4))
{
case "YUTF": plot_comp = 1; break;
case "YUTP": plot_comp = 2; break;
default: plot_comp = 1;
}
switch (guiWdw.plotTyp.selectedItem.text.substring(0, 2))
{
case "SI": plot_typ = 1; break;
case "CT": plot_typ = 2; break;
default: plot_typ = 1;
}
if (isNaN(parseInt(guiWdw.stateTB.text)))
{
WarningMessage(`${guiWdw.stateTB.text} is not a number. Reverted to previous state.`);
guiWdw.stateTB.text = `${prev_st}`;
return;
}
if (prev_st != parseInt(guiWdw.stateTB.text)) //Need to detect changes to state from main animation control buttons. Issue raised. Already logged?
{
curr_state = parseInt(guiWdw.stateTB.text);
guiWdw.stateTB.text = `${curr_state}`;
if (curr_state < 1 || curr_state > info.num_states)
{
WarningMessage(`State ${curr_state} is not a valid state between 1 to ${info.num_states}. Reverted to previous state.`);
guiWdw.stateTB.text = `${prev_st}`;
return;
}
prev_st = curr_state;
/* Go to concerned state */
SetCurrentState(curr_state);
DialogueInputNoEcho(`/CM ${model_id}`);
DialogueInputNoEcho(`/STATE ${curr_state}`);
/* Update yielding and non-yielding part lists */
check_parts_yielding(); /* Uses the GetConditionParts() JS API function */
/* Set to last yielding part (or 0 if no yielding parts) if previous partTB.text exceeds current list_yielding.length */
if (parseInt(guiWdw.partTB.text) > list_yielding.length)
guiWdw.partTB.text = `${list_yielding.length}`;
/* If previous state has no yielding parts but current state has yielding parts, default to part 1 */
if (parseInt(guiWdw.partTB.text) == 0 && list_yielding.length != 0)
guiWdw.partTB.text = "1";
/* Update total number of yielding parts in state */
guiWdw.partTotal.text = `/ ${list_yielding.length}`;
}
DialogueInputNoEcho("/PROPERTIES DISPLAY_MODE DEFAULT"); /* Reset display mode to default */
/* Give warning message & plot accordingly when there are no yielding parts for state concerned */
if (list_yielding.length == 0)
{
/* Update GUI: Grey looping through yielding parts */
loop_buttons(false);
WarningMessage(`There are no yielding parts in state ${curr_state}`);
if (mode == 3)
{
Unblank(MODEL, "ALL", win_id);
plot_component(true);
}
else if (mode == 1)
{
DialogueInputNoEcho("/PROPERTIES DISPLAY_MODE PART ALL", "SH");
DialogueInputNoEcho("/PROPERTIES COLOUR ALL", "GREY");
DialogueInputNoEcho("/PROPERTIES TRANSPARENCY ALL", "50");
Unblank(MODEL, "ALL", win_id);
plot_component(true);
}
else if (mode == 2)
{
Blank(MODEL, "ALL", win_id);
plot_component(true);
}
return;
}
/* Reset colours to default */
DialogueInputNoEcho("/PROPERTIES COLOUR ALL", "DEFAULT");
/* Reset transparency to default */
DialogueInputNoEcho("/PROPERTIES TRANSPARENCY DEFAULT");
/* Unblank everything */
Unblank(MODEL, "ALL", win_id);
/* If partTB.text is not a number, revert to previous part */
if (isNaN(parseInt(guiWdw.partTB.text)))
{
WarningMessage(`${guiWdw.partTB.text} is not a number. Reverted to previous part index.`);
guiWdw.partTB.text = `${prev_pt}`;
return;
}
/** Yielding index of part to draw (for mode 2)
* @type {number} */
let index = parseInt(guiWdw.partTB.text);
/* If index is not a valid index, revert to previous part */
if (index < 1 || index > list_yielding.length)
{
WarningMessage(`${index} is not a valid part index between 1 to ${list_yielding.length}. Reverted to previous part index.`);
guiWdw.partTB.text = `${prev_pt}`;
return;
}
guiWdw.partTB.text = `${index}`;
prev_pt = index;
if (mode == 3) /* Do a normal plot of component plot_comp */
{
/* Update GUI: Grey looping through yielding parts */
loop_buttons(false);
/* Do CT/SI plot accordingly */
plot_component(auto_contour);
}
else if (mode == 1) /* Draw model with non-yielding parts transparent-grey. */
{
/* Update GUI: Grey looping through yielding parts */
loop_buttons(false);
/* Set non-yielding parts to transparent-grey */
parts_grey_transparent();
/* Do CT/SI plot accordingly */
plot_component(auto_contour);
}
else if (mode == 2) /* Do a plot of component plot_comp for each yielding part in state */
{
/* Blank everything */
Blank(MODEL, "ALL", win_id);
/* Update GUI: Ungrey looping through yielding parts */
loop_buttons(true);
/* Unblank the part concerned */
Unblank(PART, list_yielding[index - 1], win_id);
/* Do CT/SI plot accordingly */
plot_component(auto_contour);
}
DialogueInputNoEcho("Quit");
if (list_yielding.length == 1)
Message(`${list_yielding.length} yielding parts in state ${curr_state}`);
else
Message(`${list_yielding.length} yielding parts in state ${curr_state}`);
if (mode == 2) /* If cycling through yielding parts */
Message(`Plotting yielding part ${index} of ${list_yielding.length}: PART ${GetLabel(PART, list_yielding[index - 1])}`);
}
/**
* Callback function to update yielding & non-yielding part lists
*/
function check_parts_yielding()
{
/** Number of parts in model
* @type {number} */
let n = 0;
n = GetNumberOf(PART);
if (n == 0)
{
Message("No PARTs in model.");
return;
}
/* Reset arrays */
list_yielding = [];
list_non_yielding = [];
test_yielding = GetConditionParts(YUTF, 1.0, GTEQ);
list_yielding = test_yielding.pass_list;
list_non_yielding = test_yielding.fail_list;
n = test_yielding.passed + test_yielding.failed;
Message(`Checked ${n} PARTs for yielding status: ${list_yielding.length} yielding & ${list_non_yielding.length} non-yielding`);
}
/**
* Callback function to update GUI: Ungrey buttons forlooping through yielding parts
* @param {boolean} option Switch looping buttons on/off
*/
function loop_buttons(option)
{
guiWdw.yptLabel.active = option;
guiWdw.firstPart.active = option;
guiWdw.prevPart.active = option;
guiWdw.partTB.active = option;
guiWdw.partTotal.active = option;
guiWdw.nextPart.active = option;
guiWdw.lastPart.active = option;
}
/**
* Callback function to do plot of plot_comp in plot_typ
* @param {boolean} plot_without If true, plot without user defined contour levels
*/
function plot_component(plot_without)
{
/** Maximum contour plot value
* @type {number} */
let max = 0;
/** Number contour plot levels
* @type {number} */
let level = 13;
if (plot_comp == 1)
DialogueInputNoEcho("/COMPONENT", "YIELD_UTILISATION_FACTOR");
else if (plot_comp == 2)
DialogueInputNoEcho("/COMPONENT", "YIELD_UTILISATION_PERCENTAGE");
/* Change integration point to MAX_ALL!!! */
DialogueInputNoEcho("/STRESS_CONTROL SURFACE MAX");
/* Set current window for plotting */
DialogueInputNoEcho(`/CW ${win_id}`);
if (plot_without) /* plot_without means using automatic contour levels */
{
/* Just do an automatic contour plot */
DialogueInputNoEcho("/CONTOUR AUTOMATIC_ALL");
Message("Plotting without user defined contour levels.");
if (plot_typ == 1)
DialogueInputNoEcho("/SI GO");
else if (plot_typ == 2)
DialogueInputNoEcho("/CT");
return;
}
else if (!calc_max) /* when user-defined contour levels are used with max contour level set to 1.3 or 130 */
{
Message("Plotting with user defined contour levels but maximum contour value is not calculated.");
level = 13;
DialogueInputNoEcho(`/CONTOUR NUMBER_OF_LEVELS ${level}`);
if (plot_comp == 1)
DialogueInputNoEcho("/CONTOUR USER_DEFINED", "0.0", "0.1", "0.2", "0.3", "0.4", "0.5", "0.6", "0.7", "0.8", "0.9", "1.0", "1.1", "1.2", "1.3");
else if (plot_comp == 2)
DialogueInputNoEcho("/CONTOUR USER_DEFINED", "0.0", "10", "20", "30", "40", "50", "60", "70", "80", "90", "100", "110", "120", "130");
}
else /* when user-defined contour levels are used and maximum contour level is calculated */
{
/* Do an automatic contour plot first */
DialogueInputNoEcho("/CONTOUR AUTOMATIC_ALL");
if (plot_typ == 1)
DialogueInputNoEcho("/SI GO");
else if (plot_typ == 2)
DialogueInputNoEcho("/CT");
//- GetContourLimit() doesn't work properly (for mode 1) without SI/CT plot update above
//I see flickering (probably due to "/CT" call in parts_grey_transparent & here) but it might be unavoidable?
/* Get maximum scalar contour value. Note: If null for maximum of both scalar 1 & scalar 2 components, max remains 0 */
if (GetContourLimit(MAX, "SCALAR_1") != null)
max = GetContourLimit(MAX, "SCALAR_1"); /* Get max for scalar 1 component */
else if (GetContourLimit(MAX, "SCALAR_2") != null)
max = GetContourLimit(MAX, "SCALAR_2"); /* Get max for scalar 2 component */
if (max < 0.1) /* Any number less than this will be out-of-range for setting contour levels */
{
/* No need to modify contour bar levels & colours */
return;
}
/* Set contour levels & limits. Note: max will always be >1.0 */
if ((plot_comp == 1 && max <= 1.1) || (plot_comp == 2 && max <= 110))
{
level = 11;
DialogueInputNoEcho(`/CONTOUR NUMBER_OF_LEVELS ${level}`);
if (plot_comp == 1)
DialogueInputNoEcho("/CONTOUR USER_DEFINED", "0.0", "0.1", "0.2", "0.3", "0.4", "0.5", "0.6", "0.7", "0.8", "0.9", "1.0", `${max}`);
else if (plot_comp == 2)
DialogueInputNoEcho("/CONTOUR USER_DEFINED", "0.0", "10", "20", "30", "40", "50", "60", "70", "80", "90", "100", `${max}`);
}
else if ((plot_comp == 1 && max <= 1.2) || (plot_comp == 2 && max <= 120))
{
level = 12;
DialogueInputNoEcho(`/CONTOUR NUMBER_OF_LEVELS ${level}`);
if (plot_comp == 1)
DialogueInputNoEcho("/CONTOUR USER_DEFINED", "0.0", "0.1", "0.2", "0.3", "0.4", "0.5", "0.6", "0.7", "0.8", "0.9", "1.0", "1.1", `${max}`);
else if (plot_comp == 2)
DialogueInputNoEcho("/CONTOUR USER_DEFINED", "0.0", "10", "20", "30", "40", "50", "60", "70", "80", "90", "100", "110", `${max}`);
}
else
{
level = 13;
DialogueInputNoEcho(`/CONTOUR NUMBER_OF_LEVELS ${level}`);
if (plot_comp == 1)
DialogueInputNoEcho("/CONTOUR USER_DEFINED", "0.0", "0.1", "0.2", "0.3", "0.4", "0.5", "0.6", "0.7", "0.8", "0.9", "1.0", "1.1", "1.2", `${max}`);
else if (plot_comp == 2)
DialogueInputNoEcho("/CONTOUR USER_DEFINED", "0.0", "10", "20", "30", "40", "50", "60", "70", "80", "90", "100", "110", "120", `${max}`);
}
}
/* Set contour bar colours. Note: level will always be >=11 */
DialogueInputNoEcho("/CONTOUR COLOURS", "1", "BLUE");
DialogueInputNoEcho("/CONTOUR COLOURS", "2", "CYAN/BLUE");
DialogueInputNoEcho("/CONTOUR COLOURS", "3", "LIGHT_BLUE");
DialogueInputNoEcho("/CONTOUR COLOURS", "4", "CYAN");
DialogueInputNoEcho("/CONTOUR COLOURS", "5", "GREEN/CYAN");
DialogueInputNoEcho("/CONTOUR COLOURS", "6", "GREEN");
DialogueInputNoEcho("/CONTOUR COLOURS", "7", "YELLOW/GREEN");
DialogueInputNoEcho("/CONTOUR COLOURS", "8", "YELLOW");
DialogueInputNoEcho("/CONTOUR COLOURS", "9", "RED/ORANGE");
DialogueInputNoEcho("/CONTOUR COLOURS", "10", "DARK_ORANGE");
DialogueInputNoEcho("/CONTOUR COLOURS", "11", "RED");
if (level >= 12) DialogueInputNoEcho("/CONTOUR COLOURS", "12", "RED/MAGENTA");
if (level == 13) DialogueInputNoEcho("/CONTOUR COLOURS", "13", "MAGENTA");
/* Refresh contour plot */
DialogueInputNoEcho("/REDRAW");
}
/**
* Callback function to change non-yielding PARTs to grey_transparent (uses internal indices)
*/
function parts_grey_transparent()
{
/* Blank yielding parts */
Blank(PART, list_yielding, win_id);
/* Refresh graphics */
DialogueInputNoEcho("/REDRAW");
/* Set display mode to SH */
DialogueInputNoEcho("/PROPERTIES DISPLAY_MODE PART AV", "SH");
/* Set colour to grey */
DialogueInputNoEcho("/PROPERTIES COLOUR PART AV", "GREY");
/* Set transparency to 50 */
DialogueInputNoEcho("/PROPERTIES TRANSPARENCY PART AV", "50");
/* Unblank yielding parts */
Unblank(PART, list_yielding, win_id);
}
/**
* Callback function to calculate the window_id for model_id
* @returns {number} Window ID
*/
function calc_window_id()
{
/** Number of windows in D3PLOT
* @type {number} */
let n = GetNumberOf(WINDOW);
/** Window ID corresponding to model_id
* @type {number} */
let window_id = -1;
/** Number of models in window_id
* @type {number[]} */
let nm = [1, 1];
for (let i = 1; i <= n; i++)
{
/** Model numbers in window i */
let wm = GetWindowModels(i);
for (let j = 0; j < wm.nm; j++)
{
if (wm.list[j] == model_id)
{
window_id = i;
nm[0] = wm.nm;
nm[1] = j + 1;
break;
}
}
}
if (nm[0] > 1)
{
WarningMessage(`Model ${model_id} is model ${nm[1]}/${nm[0]} in window ${window_id}. This workflow does not work properly for windows with more than 1 model.`);
exit_without_props = true;
exit_strength_check();
}
if (window_id == -1) /* Aka. if the window containing the model has been deleted, but not the model [Window -> Close Window -> Leave Model] */
{
WarningMessage("Unable to find model window");
exit_without_props = true;
exit_strength_check();
}
return window_id;
}
/**
* Callback function corresponding to the firstState button
*/
export function first_state()
{
/** Update stateTB with this state
* @type {number} */
let state = 1;
guiWdw.stateTB.text = `${state}`;
update_plot();
}
/**
* Callback function corresponding to the prevState button
*/
export function prev_state()
{
/** Update stateTB with this state
* @type {number} */
let state = parseInt(guiWdw.stateTB.text);
if (state - 1 >= 1)
state -= 1;
else
{
WarningMessage("This is already the first state.");
return;
}
guiWdw.stateTB.text = `${state}`;
update_plot();
}
/**
* Callback function corresponding to the nextState button
*/
export function next_state()
{
/** Update stateTB with this state
* @type {number} */
let state = parseInt(guiWdw.stateTB.text);
if (state + 1 <= info.num_states)
state += 1;
else
{
WarningMessage("This is already the last state.");
return;
}
guiWdw.stateTB.text = `${state}`;
update_plot();
}
/**
* Callback function corresponding to the finalState button
*/
export function last_state()
{
/** Update stateTB with this state
* @type {number} */
let state = info.num_states;
guiWdw.stateTB.text = `${state}`;
/* Save properties for restoration later */
if (!initialised)
{
props_filename = SavePropFile(model_id);
initialised = true;
}
update_plot();
}
/**
* Callback function corresponding to the firstPart button
*/
export function first_part()
{
/** Update partTB with this yielding part
* @type {number} */
let part = 1;
guiWdw.partTB.text = `${part}`;
update_plot();
}
/**
* Callback function corresponding to the prevPart button
*/
export function prev_part()
{
/** Update partTB with this yielding part
* @type {number} */
let part = parseInt(guiWdw.partTB.text);
if (part - 1 >= 1)
part -= 1;
else
{
WarningMessage("This is already the first part.");
return;
}
guiWdw.partTB.text = `${part}`;
update_plot();
}
/**
* Callback function corresponding to the nextPart button
*/
export function next_part()
{
/** Update partTB with this yielding part
* @type {number} */
let part = parseInt(guiWdw.partTB.text);
if (part + 1 <= list_yielding.length)
part += 1;
else
{
WarningMessage("This is already the last part.");
return;
}
guiWdw.partTB.text = `${part}`;
update_plot();
}
/**
* Callback function corresponding to the finalPart button
*/
export function last_part()
{
/** Update partTB with this yielding part
* @type {number} */
let part = list_yielding.length;
guiWdw.partTB.text = `${part}`;
update_plot();
}
/**
* Callback function to open workflow manual
*/
export function workflow_manual()
{
OpenManual("d3plot", "strength-check.html");
}
/**
* Callback function to give message on exit of workflow
*/
export function exit_strength_check()
{
if (info.ztf_name == "Not defined" || exit_without_props)
DelPropFile(props_filename); /* Delete temporary properties file */
else
LoadPropFile(model_id, props_filename);
Message("Exited post_strength_check.js");
Exit();
}