Recalculating all blocks
The Hull Clone utility can run child processes through the system command, as well as CADMATIC Hull executables. Hence a JavaScript can be written to recalculate all construction in a project and/or reference surfaces.
Below is an example of a script that recalculates all the blocks in a COS (distributed) project, including the reference surfaces.
Introduction
The example script makes use of the Hull COS Client Command Line Interface (HCC CLI) to query the COS state of the blocks in the project, and to execute the relevant COS commands. These commands need to know the Hullcentre path and the project path. Both paths can be passed either through an environment variable or as a command line parameter. In this example both techniques are displayed.
-
The project path is passed as command line parameter in the script.
In a COS project the Hull data is in the Hull subfolder of the Outfitting project <ProjectName>.pms. If the <ProjectName>.pms folder is passed to Hull Clone without the Hull subfolder, the tool will automatically add it.
-
The Hullcentre path is set in the environment by wrapping the execution of the script in a small batch file.
Hullcentre is typically on a network location. The path may be given using a mapped drive letter or as a fully qualified UNC path. Also the path to the distributed Hull project can either be a mapped folder, or a fully qualified UNC path.
The same batch file is used to set the %DM_NLC_HOST% environment variable that tells the Hull Clone program where the license server can be found.

This batch runs the Hull Clone script with the correct environment settings.
echo on
setlocal
set DM_NLC_HOST=<License server Host>
REM only needed in version <2023T2:
set HULLCENTRE=<Path\To\Hullcentre>
C:\<CADMATIC Hull installation bin path>\hullclone <'Hull' project sub folder or .pms folder> <Path to example script>\recalc2.js
pause
Example script
This example script recalculates the inner structure in the checked-out blocks. It showcases how we can interact with the Hull COS Agent (HCA) using the system()
command, and then recalculate all inner structure in the blocks that are checked out at our site. Also note how the script defines functions which can already be used before they are defined in the script file.
Th script performs the following steps:
-
Collect blocks that have 3D data and that are not virtual.
- Check the COS status of each selected block.
Select blocks that are checked out for recalculation.
Skip blocks that are checked out at a different site.
Try to check out blocks that are not checked out anywhere (free blocks). If successful, select the blocks for recalculation.
-
Recalculate selected blocks.
-
Save construction of blocks that were already checked out to our site.
-
Check in blocks we implicitly checked out in preceding steps.
Notes on the script:
-
The different
hcc
commands only start the COS operation. Thehcc progress
special command can be used to wait for queued and unfinished commands. -
Take special note of the
leaveActiveBlock()
call. The Hull Clone process appears as a normal Hull user to the system, and therefore the HCA is not allowed to execute COS actions in a block if a Hull Clone process is active in that block. Therefore we need to (temporarily) leave the last recalculated block to ensure that the subsequent save or check in action succeeds.

// A hullclone example script to recalculate block data (construction or reference surfaces)
// that showcases some of the capabilities.
//
send_msg("project folder: " + projectFolder());
send_msg("project name: " + currentProject());
send_msg("number of blocks: " + blocks.length);
function send_msg(message)
{
print("recalc.js >>> " + message);
}
function send_pref_msg(pref, message, output)
{
send_msg(pref + ": " + message);
var lines = output.split("\n");
var idx;
for (idx = 0; idx < lines.length; ++idx)
{
send_msg(pref + ": " + lines[idx]);
}
}
function send_err(message, output)
{
send_pref_msg("ERROR", message, output);
}
function send_warn(message, output)
{
send_pref_msg("WARNING", message, output);
}
function recalculate_block(target_blocks, avail_blocks, ref_surface)
{
var blockIdx;
for (blockIdx = 0; blockIdx < target_blocks.length; ++blockIdx)
{
if (avail_blocks.indexOf(target_blocks[blockIdx]) == -1)
{
// block not (locally) available, so skip it
continue;
}
send_msg("Switching to block " + target_blocks[blockIdx]);
if (!switchBlock(target_blocks[blockIdx]))
{
send_err("Failed to switch to the block");
continue;
}
send_msg("Recalculating ...");
// Execute the hull command(s) that will do all the recalculations,
// then wait for the hull server to finish
system("construct recalcons 1 innerconstr");
if (ref_surface)
{
system("syncrs");
system("sic /p %iges_endpoint% reload");
}
waitForHullServer();
}
}
// Blocks for which we will recalculate reference surfaces / construction
var operations = { reference : [], construction : [] };
// Blocks that are already checked out to us
var save_blocks = [];
// Blocks we implicitly checked out
var checked_out_blocks = [];
// We start by collecting some information on blocks we need to process:
var idx;
for (idx = 0; idx < blocks.length; ++idx)
{
// Skip virtual and 2D blocks:
if (isVirtualBlock(blocks[idx]))
{
continue;
}
if (!is3Dblock(blocks[idx]))
{
continue;
}
send_msg("Collecting information on block " + blocks[idx]);
// Check if the block is checked out. If free, we will try to check it out
var check = system("hcc", "hull block is-checked-out " + blocks[idx]);
if (!check.cmdOke)
{
send_err("Failed determining COS status", check.output);
continue;
}
if (check.output == "yes")
{
send_msg("Block is checked out");
save_blocks.push(blocks[idx]);
}
else
{
// Collect blocks that are free; we will try to check them out later:
var ownerCmd = system("hcc", "hull block site " + blocks[idx]);
if (!ownerCmd.cmdOke)
{
send_err("Failed determining site where block is checked out", ownerCmd.output);
continue;
}
if (ownerCmd.output == "None")
{
send_msg("Block will be checked out");
checked_out_blocks.push(blocks[idx]);
}
else
{
send_msg("Block is checked out at site " + ownerCmd.output);
continue;
}
}
if (isRefSurfBlock(blocks[idx]))
{
send_msg("Adding block to the list of reference surface blocks");
operations.reference.push(blocks[idx]);
}
else
{
send_msg("Adding block to the list of 3D construction blocks");
operations.construction.push(blocks[idx]);
}
}
// Try to check out free blocks we collected above:
if (checked_out_blocks.length > 0)
{
var checkOutCmd = system("hcc","hull block check-out " + checked_out_blocks.join(" "));
if (!checkOutCmd.cmdOke)
{
send_err("Failed starting check out process");
}
// wait for the check-out(s) to finish:
var waitFinish = system("hcc", "progress");
if (!waitFinish.cmdOke)
{
// Collect errors reported by 'progress':
var errorRegExp = /ERROR.+[bB]lock (\S+)\> failed: (.*)/g;
var error;
while ((error = errorRegExp.exec(waitFinish.output)) !== null)
{
send_err("Failed to check out block " + error[1], error[2]);
checked_out_blocks = checked_out_blocks.filter(function(value){ return value != error[1];});
}
}
}
// Start the recalculations:
var available_blocks = save_blocks.concat(checked_out_blocks);
if (operations.reference.length > 0)
{
send_msg("** RECALCULATING REFERENCE SURFACES **");
recalculate_block(operations.reference, available_blocks, 1);
}
else
{
send_msg("No reference surface blocks selected for recalculation");
}
if (operations.construction.length > 0)
{
send_msg("** RECALCULATING BLOCK CONSTRUCTION **");
recalculate_block(operations.construction, available_blocks, 0);
}
else
{
send_msg("No construction blocks selected for recalculation");
}
// Ensure we exit the last block we entered, otherwise COS operations will fail in that block
leaveActiveBlock();
// Check in blocks we implicitly checked out; save construction in blocks that were already checked out
var waitForAny = 0;
if (checked_out_blocks.length > 0)
{
send_msg("Checking in blocks " + checked_out_blocks.join());
var checkInCmd = system("hcc","hull block check-in " + checked_out_blocks.join(" "));
if (checkInCmd.cmdOke)
{
waitForAny = 1;
}
else
{
send_warn("Failed to check in blocks " + checked_out_blocks.join(), checkInCmd.output);
}
}
if (save_blocks.length > 0)
{
send_msg("Saving construction in blocks " + save_blocks.join());
var saveCmd = system("hcc", "hull construction save " + save_blocks.join(" "));
if (saveCmd.cmdOke)
{
waitForAny = 1;
}
else
{
send_warn("Failed to save construction in blocks " + save_blocks.join(), saveCmd.output);
}
}
if (waitForAny)
{
send_msg("Waiting for COS commands to finish");
var waitFinish = system("hcc", "progress");
if (!waitFinish.cmdOke)
{
send_warn("Errors were encountered while saving and checking in data - please check the log", waitFinish.output);
}
}