modules/post/d3plot/d3plot.mjs

export { D3PlotHelper };

/**
 * Helper class to carry out tasks in D3PLOT
 */
class D3PlotHelper {
    /**
     * Maximum number of windows
     * @type {number} */
    static get MAX_WINDOWS() {
        return 32;
    }

    /**
     * Return the window id of the first window with the given model id.
     * Returns null if it's not in any windows.
     * @param {number} model_id Model Id to search for
     * @return {?number} Window Id of the first window with the given model id
     * @example
     * let model_id = 1;
     * let window_id = D3PlotHelper.FirstWindowWithModel(model_id);
     */
    static FirstWindowWithModel(model_id) {
        for (let window_id = 1; window_id <= D3PlotHelper.MAX_WINDOWS; window_id++) {
            let models = GetWindowModels(window_id);

            if (models.nm == 0) continue;

            for (let id of models.list) {
                if (id === model_id) {
                    return window_id;
                }
            }
        }

        return null;
    }

    /**
     * Opens a model, returning the model number or null if it failed
     * @param {string} filename Filename of model to open
     * @return {?number}
     */
    static OpenModel(filename) {
        if (!File.Exists(filename)) {
            WarningMessage(`File ${filename} does not exist`);
            return null;
        }

        /* Read in the model */

        DialogueInput("/NEW_MODEL ", filename);

        /* The model should have been read into the next available slot, so
         * return the current number of models in D3PLOT as that should be
         * the model number */

        return GetNumberOf(MODEL);
    }

    /**
     * Puts models into a window, returning true if successful, false otherwise
     * @param {number} window_id Window Id to put models in
     * @param {number[]} model_ids Modle Ids to put in window
     * @return {boolean}
     */
    static PutModelsInWindow(window_id, model_ids) {
        /* Check the window id is valid */

        let num_windows = GetNumberOf(WINDOW);

        if (window_id < 1 || window_id > num_windows) {
            ErrorMessage(`Invalid window id ${window_id} in <D3PlotHelper.PutModelsInWindow>`);
            return false;
        }

        /* Check the model ids are valid */

        let num_models = GetNumberOf(MODEL);

        for (let model_id of model_ids) {
            if (model_id < 1 || model_id > num_models) {
                ErrorMessage(`Invalid model id ${model_id} in <D3PlotHelper.PutModelsInWindow>`);
                return false;
            }
        }

        /* Write a template file to put the models in the window */

        let template_filename = File.Mktemp();

        let template_file = new File(template_filename, File.WRITE);

        for (let model_id of model_ids) {
            template_file.Writeln(`WINDOW=${window_id} MODEL=${model_id}`);
        }

        template_file.Close();

        /* Read in the template file */

        DialogueInput("/TEMPLATE READ", template_filename);

        /* Make sure to delete the file */

        File.Delete(template_filename);

        return true;
    }

    /**
     * Set the shift deformed nodes
     * @param {number} model_id Model nodes are in
     * @param {number} node1 First shift deformed node
     * @param {number} node2 Second shift deformed node
     * @param {number} node3 Third shift deformed node
     */
    static SetShiftDeformed(model_id, node1, node2, node3) {
        DialogueInput(
            `/CM ${model_id}`,
            "/DEFORM SHIFT_DEFORMED DEFINE",
            node1.toString(),
            node2.toString(),
            node3.toString()
        );
    }
}