# This code creates the user interface for the ICEM/ANSYS HEXA.
#
# Copyright (c) 2004 ICEM CFD Engineering / Ansys Inc
# All rights reserved.
# Author:  Ganesan Harihara P, ganesan@icemcfd.com
#          Jari Spaete jspaete@ansys.com
# This file contains special comments of the form ## html ... which are
# used to automatically generate documentation

## <h2>Blocking commands</h2>
## All ic_hex commands are used as a simple string without argument grouping.
## So if an argument is grouped with curly braces, qoutes, or square brackets, an
## eval should be placed before the command to remove one level of grouping.
## <br>Wherever an index range is needed as an argument, only specify the ranges 
## which are limiting indices, not fully displayed indices.
## <br>Ex. For a box with max indices of 3 in i, j, and k (including VORFN), if only j and
## k are constrained, this argument may look like this: 0:2,3 2:1,3.  The 1 index is not
## specified because it is not limited.
## <br>Use <i>[range_string]</i> to return the current active index range.
## <br>Wherever a list of volume parts is needed as an argument, <i>[volume_activename_string]</i>
## can be substituted for the curent active parts that contain blocks. 
## <br>Ex: The following command returns all visible vertex numbers:
## <br><i>eval ic_hex_select_nodes 1 all [range_string] m [volume_activename_string] node_numbers</i>
## <h3></h3>

## check hexa licensing enabled
proc ic_hex_check_licensing {} {
    return [check_hexa_functions_enabled]
}
set dont_record_command(ic_hex_check_licensing) 1

## check back hexa licensing
proc ic_hex_release_licensing {} {
    return [release_hexa_license]
}
set dont_record_command(ic_hex_release_licensing) 1

## Initialize the hexlib and graphics adapter
## Usage: ic_hex_init
proc ic_hex_init {} {
    global hexlib dladaptobj 
    global tdv_default batch_mode

    if ![info exists hexlib] {
        if [catch {set hexlib [hexlib_interface]}] {
            return 0
        }
    }
    if !$batch_mode {
        if ![info exists dladaptobj] {
            set dladaptobj [dladapt_object]
        }
        $tdv_default add_image $dladaptobj
        $tdv_default just_redraw 1
    }
    return 1
}
set dont_record_command(ic_hex_init) 1

# Only returns status of hexlib variable
# Use ic_hex_blocking_loaded to check if blocking is loaded
proc ic_hex_is_loaded {} {
    global hexlib

    if ![info exists hexlib] { return 0 }
    return [expr {"" != $hexlib}]
}
set dont_record_command(ic_hex_is_loaded) 1

## Returns 1 if the call to the function loads the hex library
## Usage: ic_hex_ensure_is_loaded
proc ic_hex_ensure_is_loaded {} {
    if [ic_hex_is_loaded] { return 0 }
    ic_hex_init
    return 1
}
set dont_record_command(ic_hex_ensure_is_loaded) 1

## Returns 1 if hex graphics adapter is initialized
## Usage: ic_hex_dladaptobj_is_loaded
proc ic_hex_dladaptobj_is_loaded {} {
    global dladaptobj
    if ![info exists dladaptobj] { return 0 }
    return [expr {"" != $dladaptobj}]
}
set dont_record_command(ic_hex_dladaptobj_is_loaded) 1

## Remove hex graphics object if it is initialized
## Usage: ic_hex_remove_dladaptobj
proc ic_hex_remove_dladaptobj {args} {
    global hexlib dladaptobj 
    global tdv_default batch_mode

    if ![info exists hexlib] { return }
    if !$batch_mode {
        if [info exists dladaptobj] {
            $tdv_default remove_image $dladaptobj
        }
    }
}
set dont_record_command(ic_hex_remove_dladaptobj) 1

## Update dladaptobj
proc ic_hex_update_dladaptobj {args} {
    global hexlib dladaptobj 
    global tdv_default batch_mode

    if ![info exists hexlib] { return }
    if !$batch_mode {
        if [info exists dladaptobj] {
            eval $dladaptobj signal_change 1
        }
    }
}
set dont_record_command(ic_hex_update_dladaptobj) 1

## Check to see if blocking has been modified
## optional argument onoff 0/1 sets the blocking as not modified or modified
proc ic_hex_is_modified {{onoff ""}} {
    global blocking_modified
    
    if {$onoff == ""} {
        if [info exists blocking_modified] {
            return $blocking_modified
        } else {
            return 0
        }
    } else {
        set blocking_modified $onoff
    }
}
set dont_record_command(ic_hex_is_modified) 1

## Returns the radius of the curve
## Restrictions: Valid only for periodic models
## Usage: ic_hex_curve_radius curve_name
proc ic_hex_curve_radius {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib curve_radius $args]
    return $res
}

## Returns the arc length of the curve
## Usage: ic_hex_curve_length curve_name
proc ic_hex_curve_length {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib curve_length $args]
    return $res
}

## Returns the distance between the two prescribed points
## Usage: ic_hex_point_distance p1 p2
proc ic_hex_point_distance {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib point_distance $args]
    return $res
}

## Set the display of error messages ON/OFF
## Usage: ic_hex_error_messages on|off|1|0|on_minor|off_minor
proc ic_hex_error_messages {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib error_messages $args]
    return $res
}

## Usage: ic_hex_reference_blocking ref_blocking
proc ic_hex_reference_blocking {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib reference_blocking $args]
    return $res
}

## Usage: ic_hex_set_ref_uns_mesh domain_file
proc ic_hex_set_ref_uns_mesh {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib set_ref_uns_mesh $args]
    return $res
}

## Usage: ic_hex_update_ref_uns_mesh
proc ic_hex_update_ref_uns_mesh {args} {
    global hexlib uns_cur
    
    if {$uns_cur == ""} return
    set res [eval $uns_cur update_hex_ref_mesh $args]
    return $res
}

proc ic_hex_ref_mesh_set {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib ref_mesh_set $args]
    return $res
}
set dont_record_command(ic_hex_ref_mesh_set) 1

## Usage: ic_hex_uns_face_mesh uns_face
proc ic_hex_set_uns_face_mesh {args} {
    global hexlib
    
    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib set_uns_face_mesh $args]
    return $res
}

proc ic_hex_set_face_input_mesh {args} {
    global hexlib
    
    if ![ic_hex_blocking_loaded] return
    return [eval $hexlib set_face_input_mesh $args]
}

## Initializes a 2D block from every surface
## <br>Requires build topology first
## <br>Usage: ic_hex_surface_blocking material block_type -min_edge value
## <p>Argument Descriptions:
## <table border>
## <tr><td><b>material</td><td>The blocks will belong to this part. <b>-inherited</b>
## will put each block into the part of the surface it came from</td></tr>
## <tr><td><b>block_type</td><td>Determines the unstructured and mapped blocks.
## Can be <b>-mapped</b>, <b>-mixed</b>, or <b>-unstruct</b>.</td></tr>
## <tr><td><b>-min_edge</td><td> Merge block if any edge of a block is less than the
## following number.  Only applies if the <b>-respect_non_dormant</b> argument is not added</td></tr>
## <tr><td><b>value</td><td>Value for <b>-min_edge</td></tr>
## </table>
## <br>Additional arguments:
## <table border>
## <tr><td><b>-respect_non_dormant</td><td>Blocks will not be merged if this argumant is appended</td></tr>
## <tr><td><b>-surfaces</td><td>Only initialize the listed surfaces.  This is followed by a list of surface names.</td></tr>
## </table>
proc ic_hex_surface_blocking {args} {
    global hexlib batch_mode

    ic_hex_ensure_is_loaded
    lappend args "-quiet"
    set res [eval $hexlib surface_blocking $args]
    ic_hex_set_mesh_params 
    if !$batch_mode {
        aie_after_blocking_loaded
    }
    return $res
}

## Initializes a 3D blocking
## <br>Requires build topology first
## <br>Geometry must contain a solid (from a imported geometry) or a body
## <br>Usage: ic_hex_multizone_blocking -inherited -block_type -min_edge value1 -uface_type value2 -volfam part
## <br>Usage: ic_hex_multizone_blocking -inherited -block_type -min_edge value1 -automatic_sweep -uface_type value2 -volfam part
## <br> -block_type can be <b>robust</b> or <b>swept</b>
## <br> -min_edge merge blocks if any edge of a block is less than the following number. Only
## <br>  applies if the <b>-respect_non_dormant</b> argument is not added.
## <br> value1 Value for <b>-min_edge</b>
## <br> -uface_type can be one <b>several_tris</b> or <b>all_tris</b> <b>all_quads</b>
## <br> value2 Value for <b>-uface_type</b>
## <br>Additional arguments:
## <table border>
## <tr><td><b>-respect_non_dormant</td><td>Blocks will not be merged if this argument is appended</td></tr>
## <tr><td><b>-automatic_sweep</td><td>In case of block_type <b>swept</b> required</td></tr>
## <tr><td><b>-swept_surfaces</td><td>The surfaces for the swept blocks.  This is followed by a list of surface names.</td></tr>
## </table>

proc ic_hex_multizone_blocking {args} {
    global hexlib batch_mode

    ic_hex_ensure_is_loaded
    lappend args "-quiet"
    set res [eval $hexlib multizone_blocking $args]
    ic_hex_set_mesh_params 
    if !$batch_mode {
        foreach topo [ic_hex_print_topo_tree] {
            set name [lindex $topo 0]
            if {$name == "PS"} {
                eval $hexlib rename_blocking PS root
                break
            }
        }
        aie_after_blocking_loaded
    }
    ic_hex_reset_unstruct_node_locs
    return $res
}

## Creates 2D suface blocking for AutoVT
proc ic_hex_virtual_topo_blocking {args} {
    global hexlib batch_mode

    ic_hex_ensure_is_loaded
    lappend args "-quiet"
    set res [eval $hexlib virtual_topo_blocking $args]
    ic_hex_set_mesh_params 
    if !$batch_mode {
        aie_after_blocking_loaded
    }
    return $res
}

## Fills in 2D suface blocking with volume blocks  
## <br>Usage: ic_hex_twod_to_threed part [-basic]
## <br><b>Part</b> is the part that the new volume blocks will be created in.
## <br> If <b>-basic</b> is appended, the volume blocks will all be unstructured blocks
## if it cannot figure out a simple structured fill.
## If <b>-basic</b> if omitted, it will try to break up the domain in order to get as many structured blocks as possible.
##<br>The basic fill is the most robust and most used.  The 2D blocking must form a closed volume of surface blocks.
proc ic_hex_twod_to_threed {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib twod_to_threed $args]
    return $res
}

## Usage: ic_hex_make_edge_smooth n1 n2
proc ic_hex_make_edge_smooth {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib make_edge_smooth $args]
    return $res
}

## Resets the Ogrid orthogonality between a vertex and the orthogonal vertex along Ogrid direction
## Usage: ic_hex_reset_ogrid_orthogonality n1 n2 [parts] 
proc ic_hex_reset_ogrid_orthogonality {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib reset_ogrid_orthogonality $args]
    return $res
}

## Blanks blocks 
## Usage: ic_hex_blank_blocks [marked] [reverse]
proc ic_hex_blank_blocks {args} {
    global hexlib batch_mode display_flag

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib blank_blocks $args]
    if !$batch_mode { ic_set_global display_flag 1 use_blanking }
    return $res
}

## Blank selected blocks 
## Usage: ic_hex_blank_selected_blocks use_output use_blank blocks
## set use_output to "1" if "Pre-mesh->Output blocks" is set
## set use_blank to "1" if "Pre-mesh->Blanking" is set
## blocks is a list of block numbers

proc ic_hex_blank_selected_blocks {use_output use_blank blocks} {
    global hexlib batch_mode

    if ![ic_hex_blocking_loaded] { return "" }
    if !$batch_mode {  set ta [tdv_active 0]  }
    if {$blocks == ""} { return "" }
    set opts ""
    if $use_output {
        append opts " output_blocks"
    }
    if $use_blank {
        append opts " -not_blanked"
    }   
    ic_hex_mark_blocks unmark
    for {set i 0} {$i < [llength $blocks]} {incr i} {
        eval ic_hex_mark_blocks superblock [lindex $blocks $i] $opts
    }
    set res [ic_hex_blank_blocks marked]
    ic_hex_mark_blocks unmark
    if !$batch_mode { tdv_active $ta }
    return $res
}

## Unblanks blocks 
## Usage: ic_hex_unblank_blocks [marked] [reverse]
proc ic_hex_unblank_blocks {args} {
    global hexlib batch_mode

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib unblank_blocks $args]
    if !$batch_mode { ic_set_global display_flag 0 use_blanking }
    return $res
}

## Usage: ic_hex_check_face_radii n1 n2 n3 n4
proc ic_hex_check_face_radii {args} {
    global hexlib

    set res [eval $hexlib check_face_radii $args]
    return $res
}
set dont_record_command(ic_hex_check_face_radii) 1

## Update the node indices
## Usage: ic_hex_update_node_indices
proc ic_hex_update_node_indices {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib update_node_indices $args]
    return $res
}

## Updates the node locations based on geometry tags and projection of vertices.
## Usage: ic_hex_update_node_locations [parts]
proc ic_hex_update_node_locations {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib update_node_locations $args]
    return $res
}

## Removes unused grid lines from the blocking
## Usage: ic_hex_remove_unused_grid_lines [-only_one] [-version <vers>]
proc ic_hex_remove_unused_grid_lines {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib remove_unused_grid_lines $args]
    return $res
}

## Sets the tangents on an edge
## Usage: ic_hex_set_edge_tangents n1 n2 tan1_info tan2_info 
## Where:
## tan1_info would be one of following:
## tan1 ortho fac1 tangency_factor
## tan1 tangency_point_xyz fac1 tangency_factor
## ""
## and tan2_info would be one of following:
## tan2 ortho fac2 tangency_factor
## tan2 tangency_point_xyz fac2 tangency_factor
## ""
## e.g.
## set n1 22
## set n2 65
## eval ic_hex_set_edge_tangents $n1 $n2 tan1 ortho fac1 0.33 tan2 0 0 1 fac2 0.33
proc ic_hex_set_edge_tangents {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib set_edge_tangents $args]
    return $res
}

## Make the edges coming into a vertex smooth
## Usage: ic_hex_smooth_edges_at_vertex node_num families 
## node_num could be replaced by ijk_range
## e.g.
## set n 26
## eval ic_hex_smooth_edges_at_vertex $n [volume_activename_string]
proc ic_hex_smooth_edges_at_vertex {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib smooth_edges_at_vertex $args]
    return $res
}

## Returns the dimension and index between two vertices
## Usage: ic_hex_edge_node_dim n1 n2
proc ic_hex_edge_node_dim {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib edge_node_dim $args]
    return $res
}
set dont_record_command(ic_hex_edge_node_dim) 1

## Returns the other node of the edge dimension
## Usage: ic_hex_get_edge_node ijk dim
## e.g. 
## ic_hex_get_edge_node " 1 2 1 " 0
proc ic_hex_get_edge_node {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib get_edge_node $args]
    return $res
}
set dont_record_command(ic_hex_get_edge_node) 1

## Returns the location of a prescribed point.
## Usage: ic_hex_point_location name
proc ic_hex_point_location {args} {
    global hexlib
    global _tempx _tempy _tempz
    
    if ![ic_hex_blocking_loaded] return
    set pt [lindex $args 0]
    set res [eval $hexlib point_location $pt]
    set i 0
    set tvars [lrange $args 1 end]
    set varlist ""
    foreach tvar $tvars {
        set $tvar [lindex $res $i]
        lappend varlist $tvar [lindex $res $i]
        incr i
    }
    eval hex_set_return_vars $varlist
    return $res
}

## Returns the family name of a surface
## Usage: ic_hex_get_surface_family surface_name
proc ic_hex_get_surface_family {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] { return "" }
    set res [eval $hexlib get_surface_family $args]
    return $res
}
set dont_record_command(ic_hex_get_surface_family) 1

## Define a family by a name
## Usage: ic_hex_define_family name
proc ic_hex_define_family {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib define_family $args]
    return $res
}

## Split an edge into as many points as it will be meshed
## Usage: ic_hex_auto_split_edge {n1 n2} | {-all [ dim : low , hi ] [fam1 fam2 ... ]}
proc ic_hex_auto_split_edge {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib auto_split_edge $args]
    return $res
}

## Put a major start in the undo log and save model
## Usage: ic_hex_undo_major_start text
proc ic_hex_undo_major_start {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib undo_major_start $args]
    return $res
}

## Put a major end in the undo log 
## Usage: ic_hex_undo_major_end text
proc ic_hex_undo_major_end {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib undo_major_end $args]
    return $res
}

## Add a boundary condition to a family
## Usage: ic_hex_add_boco family [value1 value2 ...]
proc ic_hex_add_boco {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib add_boco $args]
    return $res
}

# I don't think this is used or has help in hexa.
proc ic_hex_display_mat_points {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib display_mat_points $args]
    return $res
}

# I don't think this should be used
proc ic_hex_region_zoom {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib region_zoom $args]
    return $res
}

## Get the family (part) of a block
## Usage: ic_hex_get_block_family block_num
proc ic_hex_get_block_family {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] { return "" }
    set res [eval $hexlib get_block_family $args]
    return $res
}
set dont_record_command(ic_hex_get_block_family) 1

proc ic_hex_get_block_families_and_types {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] { return "" }
    if [catch {eval $hexlib get_block_families_and_types $args} res] {
        set res ""
    }
    return $res
}
set dont_record_command(ic_hex_get_block_families_and_types) 1

proc ic_hex_get_block_type_number {type args} {
    global hexlib

    if ![ic_hex_blocking_loaded] { return 0 }
    if [catch {eval $hexlib get_block_families_and_types $args} res] {
        set res ""
    }
    set n 0
    foreach b $res {
        if {[lindex $b 1] == "ORFN"} continue
        if {[lindex $b 2] == "$type"} {
            incr n
        } elseif {$type == "all"} {
            incr n
        }
    }
    return $n
}
set dont_record_command(ic_hex_get_block_type_number) 1

## Read the node locations from the domains directory
## Usage: ic_hex_read_domains m1 m2 ...
proc ic_hex_read_domains {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib read_domains $args]
    return $res
}

## Reverse the global orientation of a dimension
## Usage: ic_hex_reverse_dimension [dim]
proc ic_hex_reverse_dimension {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib reverse_dimension $args]
    return $res
}

## Write the family boco file
## Usage: ic_hex_write_family_boco [filename]
proc ic_hex_write_family_boco {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib write_family_boco $args]
    return $res
}

## Clear the bocos on some or all families
## Usage: ic_hex_clear_bocos [ fam1 ... ]
proc ic_hex_clear_bocos {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib clear_bocos $args]
    return $res
}

## Align blocks with a given superblock
## Usage: ic_hex_align_superblocks block_num
proc ic_hex_align_superblocks {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib align_superblocks $args]
    return $res
}

## Returns the i j k of a vertex.
## Usage: ic_hex_vertex_ijk vertex_num
proc ic_hex_vertex_ijk {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] { return "" }
    set res [eval $hexlib vertex_ijk $args]
    return [string trimright $res \n]
}
set dont_record_command(ic_hex_vertex_ijk) 1

## Returns the vertex number from the vertex index.
## <br><b>args</b> is a vertex index in format { i j k etc }.
## There must be spaces on both sides of each number.
proc ic_hex_vertex_number {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] { return "" }
    set res [eval $hexlib vertex_number $args]
    return $res
}
set dont_record_command(ic_hex_vertex_number) 1

# doesn't appear to work
proc ic_hex_list_vertex_edges {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] { return "" }
    set res [eval $hexlib list_vertex_edges $args]
    return $res
}
set dont_record_command(ic_hex_list_vertex_edges) 1

## Returns the 8 corner vertices of the block
## <br>Usage: ic_hex_get_block_vertices block_num
proc ic_hex_get_block_vertices {args} {
    global hexlib

    if {![ic_hex_blocking_loaded] || $args == ""} { return "" }
    set res [eval $hexlib get_block_vertices block_number $args]
    return $res
}
set dont_record_command(ic_hex_get_block_vertices) 1

## Returns block numbers of all blocks attached to the vertex
## <br>Usage: ic_hex_get_vertex_blocks vertex_num
proc ic_hex_get_vertex_blocks {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] { return "" }
    set res [eval $hexlib get_block_vertices $args]
    return $res
}
set dont_record_command(ic_hex_get_vertex_blocks) 1

## Returns block numbers of all blocks attached to the edge
## <br>Usage: ic_hex_get_edge_blocks vertex_num1 vertex_num2
## <br>Usage: ic_hex_get_edge_blocks { vertex_num1 vertex_num2 }
## <br> An edge is defned by its end vertex numbers
proc ic_hex_get_edge_blocks {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] { return "" }
    set res [eval $hexlib get_block_vertices $args]
    return $res
}
set dont_record_command(ic_hex_get_edge_blocks) 1

## Returns block numbers of attached blocks that contain the specified face.
## <br>Usage: ic_hex_get_face_blocks vertex_num1 vertex_num2 vertex_num3 vertex_num4
## <br>Usage: ic_hex_get_face_blocks { vertex_num1 vertex_num2 vertex_num3 vertex_num4 }
## <br>A face is defined by its 4 corner vertex numbers
proc ic_hex_get_face_blocks {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] { return "" }
    set res [eval $hexlib get_block_vertices $args]
    return $res
}
set dont_record_command(ic_hex_get_face_blocks) 1

## Returns faces attached to the specified vertex
## <br>Usage: ic_hex_get_vertex_faces vertex_num
## <br>A face is defined by its 4 corner vertex numbers
proc ic_hex_get_vertex_faces {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] { return "" }
    set res [eval $hexlib get_faces_to_entity $args]
    return $res
}
set dont_record_command(ic_hex_get_vertex_faces) 1

## Returns faces attached to the specified edge
## <br>Usage: ic_hex_get_edge_faces vertex_num1 vertex_num2
## <br>A face is defined by its 4 corner vertex numbers
## <br> An edge is defned by its end vertex numbers
proc ic_hex_get_edge_faces {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] { return "" }
    set res [eval $hexlib get_faces_to_entity $args]
    return $res
}
set dont_record_command(ic_hex_get_edge_faces) 1

## Returns edges attached to the specified vertex
## <br>Usage: ic_hex_get_vertex_edges vertex_num
## <br> An edge is defned by its end vertex numbers
proc ic_hex_get_vertex_edges {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] { return "" }
    set res [eval $hexlib get_edges_to_vertex $args]
    return $res
}
set dont_record_command(ic_hex_get_vertex_edges) 1

## Uncollapses an edge of a degenerate block
## <br>Usage: ic_hex_uncollapse_edge vertex_num
proc ic_hex_uncollapse_edge {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib uncollapse_edge $args]
    return $res
}

## Link the shape of one edge to another
## <br>Usage: ic_hex_link_shape tar_vert1 tar_ver2 src_vert1 src_vert2 factor
## <br><b>tar_vert1</b> and <b>tar_vert2</b> are the end vertices of the target edge.
## <b>src_vert1</b> and <b>src_vert2</b> are the end vertices of the source edge.
## <br><b>factor</b> is a mutiple of the curvature. 1 will produce the exact same shape.  A decimal will
## produce less curvature, and a number greater than one will produce more curvature.
proc ic_hex_link_shape {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib link_shape $args]
    return $res
}

proc ic_hex_get_edge_shape_factor {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] { return "" }
    set res [eval $hexlib get_edge_shape_factor $args]
    return $res
}
set dont_record_command(ic_hex_get_edge_shape_factor) 1

## Links the shape of all edges across the specified index dimension
## <br>Usage: ic_hex_link_shape_dimension dim vertex1 vertex2 factor index_range parts
## <p>Argument descriptions:
## <table border>
## <tr><td><b>dim</td><td>Index dimension where i=0, j=1, k=2, O3=3, etc..</td></tr>
## <tr><td><b>vertex1</td><td>vertex number beloning to one of the source edges</td></tr>
## <tr><td><b>vertex2</td><td>vertex number beloning to one of the target edges</td></tr>
## <tr><td><b>factor</td><td>Multiplication factor of the shape curvature. "1" will produce the same curvature.</td></tr>
## <tr><td><b>index_range</td><td>Only operates on this index_range.
## Use [range_string] to return the current active index range.</td></tr>
## <tr><td><b>parts</td><td>The list of parts that contain blocks.
## Only edges belonging to these blocks will be shaped. Use [volume_activename_string]
## to return all the active part names containing blocks.</td></tr>
## </table>
proc ic_hex_link_shape_dimension {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib link_shape_dimension $args]
    return $res
}

## Returns the topological number of a face
## Usage: ic_hex_topo_vertex_number n1
proc ic_hex_topo_vertex_number {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] { return "" }
    set res [eval $hexlib topo_vertex_number $args]
    return $res
}

## Returns the topological number of an edge
## Usage: ic_hex_topo_edge_number [output_blocks] n1 n2
proc ic_hex_topo_edge_number {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] { return "" }
    set res [eval $hexlib topo_edge_number $args]
    return $res
}

## Returns the constraints set on an edge
## Usage: ic_hex_list_edge_constraints n1 n2
proc ic_hex_list_edge_constraints {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] { return "" }
    set res [eval $hexlib list_edge_constraints $args]
    return $res
}
set dont_record_command(ic_hex_list_edge_constraints) 1

## Returns the topological number of a face
## Usage: ic_hex_topo_face_number [output_blocks] n1 n2
proc ic_hex_topo_face_number {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] { return "" }
    set res [eval $hexlib topo_face_number $args]
    return $res
}

## Returns the topological numbers of a list of faces
## Usage: ic_hex_topo_face_number_list [output_blocks] "n1 n2 n1 n2 ..."
proc ic_hex_topo_face_number_list {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] { return "" }
    set res [eval $hexlib topo_face_number_list $args]
    return $res
}

## Returns the topological numbers of all existing faces
## Usage: ic_hex_get_super_faces_topo [output_blocks]
proc ic_hex_get_super_faces_topo {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] { return "" }
    set res [eval $hexlib get_super_faces_topo $args]
    return $res
}

proc ic_hex_get_super_faces_in_plane {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] { return "" }
    set res [eval $hexlib get_super_faces_in_plane $args]
    return $res
}

## Changes mouse buttons for Hexa
## Usage: change_mouse_buttons rotate translate scale scale_dir
proc ic_hex_change_mouse_buttons {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib change_mouse_buttons $args]
    return $res
}

## Runs the global hex smoother on the blocking
## Usage: ic_hex_global_smooth families [fam1 fam2 fam3 ...] 
proc ic_hex_global_smooth {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib global_smooth $args]
    return $res
}

## Usage: ic_hex_edge_ijk topo_num
proc ic_hex_edge_ijk {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] { return "" }
    set res [eval $hexlib edge_ijk $args]
    return $res
}

## Usage: ic_hex_gls_init name
proc ic_hex_gls_init {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib gls_init $args]
    return $res
}


proc ic_hex_gls_display_bucket {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib gls_display_bucket $args]
    return $res
}

## Display faces between different materials
## Usage: ic_hex_display_ijk_region [topo_dom_no dom] [ijk_reg n1 n2 n3 n4 n5 n6] [solid]
proc ic_hex_display_ijk_region {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib display_ijk_region $args]
    return $res
}

## Deletes blocks permanently from the blocking
## Usage: ic_hex_delete_blocks {ijk1 ijk2} | marked | {numbers n1 n2 ...} | {blanked fam1 fam2 ...} [output_blocks]
proc ic_hex_delete_blocks {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    if {[lindex $args 0] == "numbers" && [format %d [ic_hex_mesh_dimension]] == "3"} {
	    set opts ""
        if [string match "*output_blocks*" $args] {
            append opts " output_blocks"
        }
        foreach b [lrange $args 1 end] {
            if [string is integer -strict $b] {
                if {[string trimright [ic_hex_print_block_type_info $b] \n] == "free"} {
                    ic_hex_mark_blocks unmark
                    eval ic_hex_mark_blocks superblock $b $opts
                    ic_hex_change_element_id VORFN
                    ic_hex_mark_blocks unmark
                }
            } else {
                break
            }
        }
    }
    set res [eval $hexlib delete_blocks $args]
    return $res
}

## Gets the dimension of the blocking (2=2D Blocking or 3=3D Blocking)
## Usage: ic_hex_mesh_dimension
proc ic_hex_mesh_dimension {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] { return "" }
    set res [eval $hexlib mesh_dimension $args]
    return $res
}
set dont_record_command(ic_hex_mesh_dimension) 1

## Gets the meshed dimension of the blocking (1,2,2.5 or 3)
## Usage: ic_hex_dim_to_mesh
proc ic_hex_dim_to_mesh {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] { return "" }
    set res [eval $hexlib dim_to_mesh $args]
    return $res
}
set dont_record_command(ic_hex_dim_to_mesh) 1

## Create a new block
## <br>Usage: ic_hex_create_block part_name n1 n2 n3 n4 n5 n6 n7 n8 active_parts
## <br>Usage: ic_hex_create_block part_name n1 n2 n3 n4 active_parts (for a 2D blocking)
## <br>Ex: eval ic_hex_create_block SOLID 134 135 128 129 110 111 104 105 [volume_activename_string]
## <br>For the two opposing rectangular faces of the 3D block, n2 directly opposes n1,
## n4 directly opposes n3, n6 directly opposes n5, and n8 directly opposes n7
## <br>Any of n1 - n8 can be replaced with an { x y z } location
proc ic_hex_create_block {args} {
    global hexlib

    if {![ic_hex_blocking_loaded] || $args == ""} { return "" } 
    set res [eval $hexlib create_block $args] 
    return $res
}

## Create a 2D sheet in 3D Blocking. Usage: same as create_block
proc ic_hex_create_sheet {args} {
    global hexlib

    if {![ic_hex_blocking_loaded] || $args == ""} { return "" }
    set res [eval $hexlib create_sheet $args]
    return $res
}

## Create a 2D unstructured sheet in 3D Blocking. 
proc ic_hex_create_unstruct_sheet {args} {
    global hexlib

    if {![ic_hex_blocking_loaded] || $args == ""} { return "" }
    set res [eval $hexlib create_unstruct_sheet $args]
    return $res
}

## merge sheet inside a free block.
## <br>Usage: ic_hex_merge_sheet_with_unstruct free_block sheet_block
proc ic_hex_merge_sheet_with_unstruct {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib merge_sheet_with_unstruct $args]
    return $res
}

## Create a block primitive
## Usage: ic_hex_create_block_primitive type family c1 c2 [c3] p1 p2 [p3] s1 s2 [s3]
proc ic_hex_create_block_primitive {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib  create_block_primitive $args]
    return $res
}

## Create a new Y-block
## <br>Usage: ic_hex_create_yblock part_name n1 n2 n3 n4 n5 n6 active_parts
## <br>Ex: eval ic_hex_create_yblock SOLID 134 135 110 128 129 104 [volume_activename_string]
## <br>The first 3 vertices belong to the triangular face of one side, and the last 3 vertices
## are for the triangular faces of the opposite side
## <br>Any of n1 - n6 can be replaced with an { x y z } location
proc ic_hex_create_yblock {args} {
    global hexlib

    if {![ic_hex_blocking_loaded] || $args == ""} { return "" }
    set res [eval $hexlib  create_yblock $args]
    return $res
}

## Create a new Degenerate block
## <br>Usage: ic_hex_create_degen_block part_name n1 n2 n3 n4 n5 n6 active_parts
## <br>Ex: eval ic_hex_create_degen_block SOLID 134 135 110 128 129 104 [volume_activename_string]
## <br>The mesh will converge to n1 and n4
## <br>Any of n1 - n6 can be replaced with an { x y z } location
proc ic_hex_create_degen_block {args} {
    global hexlib

    if {![ic_hex_blocking_loaded] || $args == ""} { return "" }
    set res [eval $hexlib  create_degen_block $args]
    return $res
}

proc ic_hex_count_unstruct_blocks {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] { return 0 }
    set res [eval $hexlib count_unstruct_blocks $args]
    return $res
}
set dont_record_command(ic_hex_count_unstruct_blocks) 1

## Create a swept block
## <br>Usage: ic_hex_create_unstruct_block part_name n1 n2 n3 n4 n5 n6 active_parts
## <br>Usage: ic_hex_create_unstruct_block part_name n1 n2 n3 ... nn active_parts (for a 2D blocking)
## <br>Ex: eval ic_hex_create_unstruct_block SOLID 134 135 110 128 129 104 [volume_activename_string]
## <br>For the two opposing triangular faces of the block, n2 directly opposes n1,
## n4 directly opposes n3, and n6 directly opposes n5
## If a block is converted to unstructured, rather than created, it is not limited to a 6-vertex block in shape.
proc ic_hex_create_unstruct_block {args} {
    global hexlib

    if {![ic_hex_blocking_loaded] || $args == ""} { return "" }
    set res [eval $hexlib  create_unstruct_block $args]
    return $res
}

## Split a free block face
## <br>Usage: ic_hex_split_unstruct_block vertex1 vertex2
## <br>vertex1 and vertex2 must be corner vertices of the face to split

proc ic_hex_split_unstruct_block {args} {
    global hexlib

    if {![ic_hex_blocking_loaded] || $args == ""} { return "" }
    set res [eval $hexlib split_unstruct_block $args]
    return $res
}

## Split a 3d unstruct block into different volume regions
## <br>Usage: ic_hex_split_unstruct_block3d ublock_num <b>by_sheets</b> sheet1 sheet2...
## <br>Usage: ic_hex_split_unstruct_block3d ublock_num <b>loop1</b> sheet1
## <br>Usage: ic_hex_split_unstruct_block3d ublock_num <b>loop1</b> sheet1 <b>loop2</b> sheet2
proc ic_hex_split_unstruct_block3d {args} {
    global hexlib

    if {![ic_hex_blocking_loaded] || $args == ""} { return "" }
    set res [eval $hexlib split_unstruct_block3d $args]
    return $res
}

proc ic_hex_transfer_blocks {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib transfer_blocks $args]
    return $res
}

proc ic_hex_compute_spline_distribution {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib compute_spline_distribution $args]
    return $res
}

proc ic_hex_max_superblock_number {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib max_superblock_number $args]
    return $res
}
set dont_record_command(ic_hex_max_superblock_number) 1

proc ic_hex_threed_to_twod {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib threed_to_twod $args]
    return $res
}

## Returns block numbers in the range and parts specified.
## <br>Usage: ic_hex_select_blocks num display method index_range m parts
## <br>Ex: <i>ic_hex_select_blocks 1 no_highlight all [range_string] m [volume_activename_string]</i>
##<p>Argument descriptions:
## <table border>
## <tr><td><b>num</td><td>Usually 1</td></tr>
## <tr><td><b>display</td><td><b>no_highlight</b> to not highlight the block</td></tr>
## <tr><td><b>method</td><td><b>all</b>, or <b>inpoly</b> p1 p2 p3 p4,
## where each p is the xyz of a point</td></tr>
## <tr><td><b>index_range</td><td>Specifies the index range to limit selection.
## Use <i>[range_string]</i> to return the current active index range</td></tr>
## <tr><td><b>m</td><td>"m" indicates the following aguments are part names</td></tr>
## <tr><td><b>parts</td><td>The list of parts that contain blocks. Use
## <i>[volume_activename_string]</i> to return all the active part names containing blocks</td></tr>
## </table>
## <br>The following arguments may be appended:
## <table border>
## <tr><td><b>-not_blanked</td><td>Normally, blanked blocks have no affect on which
## vertices are returned.  This option ensures vertices turned off due to blanked blocks are not returned.</td></tr>
## <tr><td><b>super</td><td></td></tr>
## <tr><td><b>-keep_unstruct3d</td><td></td></tr>
## </table border>
proc ic_hex_select_blocks {args} {
    global hexlib
    
    busy reset   
    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib select_blocks $args]
    return $res
}
set dont_record_command(ic_hex_select_blocks) 1

proc ic_hex_set_edge_length {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib set_edge_length $args]
    return $res
}

proc ic_hex_align_vertices {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib align_vertices $args]
    return $res
}

proc ic_hex_align_vertices2 {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib align_vertices2 $args]
    return $res
}

proc ic_hex_update_association {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib update_association $args]
    return $res
}

proc ic_hex_clear_curve_association {curve} {
    global hexlib

    set res ""
    set comp_curve [ic_hex_find_comp_curve $curve]
    foreach topo [ic_hex_print_topo_tree] {
        if {$comp_curve != "(null)"} {
            set res [eval $hexlib clear_association $topo -on_curve $comp_curve]
        }
    }
    return $res
}

## Sets the default bunching law and ratio
## <br>Usage: ic_hex_default_bunching_law law ratio
## Returns without any argument the current bunching law

proc ic_hex_default_bunching_law {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib default_bunching_law $args]
    return $res
}

## Merge blocking topologies
## <br>Usage: ic_hex_merge_blocking topo1 topo2 parts -remove_unused_grid_lines -eps <tolerance> -separate_classes -version 110
## topo1 topo2: the topologies to merge
## parts: the list of parts that contain blocks. Use <i>[volume_activename_string]</i> 
## to return all the active part names containing blocks
## tolerance: a relative tolerance for merging the topologies

proc ic_hex_merge_blocking {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib merge_blocking $args]
    return $res
}

proc ic_hex_change_origin {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib change_origin $args]
    return $res
}

proc ic_hex_invert_super_block {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib invert_super_block $args]
    return $res
}

proc ic_hex_rotate_super_block {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib rotate_super_block $args]
    return $res
}

proc ic_hex_set_super_block_ijk {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib set_super_block_ijk $args]
    return $res
}

proc ic_hex_auto_merge {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib auto_merge $args]
    return $res
}

proc ic_hex_decimate_blocks {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib decimate_blocks $args]
    return $res
}

proc ic_hex_multi_grid_level {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib multi_grid_level $args]
    return $res
}

proc ic_hex_transfinite_degree {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib transfinite_degree $args]
    return $res
}

proc ic_hex_projection_limit {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib projection_limit $args]
    return $res
}

proc ic_hex_select_surf_uv {args} {
    global hexlib
    busy reset
    set res [eval $hexlib select_surf_uv $args]
    return $res
}

proc ic_hex_isocurve {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib isocurve $args]
    return $res
}

proc ic_hex_scale_mesh_size {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib scale_mesh_size $args]
    return $res
}


proc ic_hex_init_output_blocks {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib init_output_blocks $args]
    return $res
}

proc ic_hex_wing_gri {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib  wing_gri $args]
    return $res
}

proc ic_hex_define_point {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib  define_point $args]
    return $res
}

proc ic_hex_write_tetin_file {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib  write_tetin_file $args]
    return $res
}

proc ic_hex_extrude_faces {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib extrude_faces $args]
    return $res
}

proc ic_hex_extrude_faces_interactive {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib extrude_faces $args]
    return $res
}
set dont_record_command(ic_hex_extrude_faces_interactive) 1

proc ic_hex_extrude_face {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib  extrude_face $args]
    return $res
}

proc ic_hex_split_face {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib  split_face $args]
    return $res
}

proc ic_hex_split_face_auto {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib  split_face_auto $args]
    return $res
}

## Merge faces
## <br>Usage by face corners: ic_hex_merge_face [ijk of vertex_num1] [ijk of vertex_num2]
## <br>Usage by block faces: ic_hex_merge_face -faces face1 face2

proc ic_hex_merge_face {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib  merge_face $args]
    return $res
}

proc ic_hex_invert_blocking {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib invert_blocking $args]
    return $res
}

proc ic_hex_pack_superblocks {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib pack_superblocks $args]
    return $res
}

proc ic_hex_change_superblocks {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib change_superblocks $args]
    return $res
}

proc ic_hex_add_buffer_blocks {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib add_buffer_blocks $args]
    return $res
}

proc ic_hex_query_refinement {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib query_refinement $args]
    return $res
}

proc ic_hex_query_face_proj {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib query_face_proj $args]
    return $res
}
set dont_record_command(ic_hex_query_face_proj) 1

proc ic_hex_set_refinement {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib set_refinement $args]
    return $res
}

proc ic_hex_refine_blocks {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib refine_blocks $args]
    return $res
}

proc ic_hex_insert_blocking {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib insert_blocking $args]
    return $res
}

proc ic_hex_copy_blocking {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib copy_blocking $args]
    return $res
}

## Returns the existing topology names
proc ic_hex_print_topo_tree {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib print_topo_tree $args]
    return $res
}
set dont_record_command(ic_hex_print_topo_tree) 1

proc ic_hex_extract_blocking {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib extract_blocking $args]
    return $res
}

proc ic_hex_delete_blocking {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib delete_blocking $args]
    return $res
}

proc ic_hex_smooth {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib smooth $args]
    return $res
}

proc ic_hex_make_nodes_not_periodic {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib make_nodes_not_periodic $args]
    return $res
}

proc ic_hex_make_nodes_periodic {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib make_nodes_periodic $args]
    return $res
}

proc ic_hex_match_edges {args} {
    global hexlib
    
    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib match_edges $args]
    return $res
}

proc ic_hex_match_edges_auto {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib match_edges_auto $args]
    return $res
}

## Convert a 2D blocking into a 3D blocking by translation or rotation
## <br>Usage: ic_hex_extrude_blocks translate dir
## <br>Usage: ic_hex_extrude_blocks rotate center axis angle
## <br>Ex:  ic_hex_extrude_blocks rotate 0 0.05 0 1 0 0 45 -ncopies 1 -npoints 10 collapse_axis
## -extrude_points -extrude_curves
## <p>Argument descriptions:
## <table border>
## <tr><td><b>dir</td><td>Vector which describes direction and magnitude of translation</td></tr>
## <tr><td><b>center</td><td>xyz location of center of rotation</td></tr>
## <tr><td><b>axis</td><td>Vector which gives the rotation axis direction</td></tr> 
## <tr><td><b>angle</td><td>Angle of rotation in degrees</td></tr>
## </table>
## <br>Additional arguments for the rotation method:
## <table border>
## <tr><td><b>-ncopies</td><td>Each 3D wedge will be incrementally copied around the axis.
## A number must follow this argument. The first extrusion is included in the number. 4 copies of 90 degrees will
## produce a complete 360 degrees.</td></tr>
## <tr><td><b>-npoints</td><td>The number of nodes on extruded edges in the circumferential direction. A number
## must follow this argument.</td></tr> 
## <tr><td><b>collapse_axis</td><td> Merges nodes at the axis.  Choose this if vertices lie on the axis.</td></tr>
## <tr><td><b>-extrude_points</td><td>The points of point-projected vertices (red vertices)
## will be extruded into curves.</td></tr>
## <tr><td><b>-extrude_curves</td><td>The curves of curve-projected edges (green edges)
## will be extruded into surfaces.</td></tr>
## </table>
proc ic_hex_extrude_blocks {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib extrude_blocks $args]
    return $res
}

proc ic_hex_copy_blocking_periodic {args} {
    global hexlib batch_mode

    if ![ic_hex_blocking_loaded] return
    if [catch {eval $hexlib copy_blocking_periodic $args} res] {
        mess "$res\n" red
        return
    }
    if !$batch_mode {
        update_bsp_consistency
        aie_after_blocking_loaded
    }
}

proc ic_hex_make_blocking_periodic {args} {
    global hexlib batch_mode
    
    if ![ic_hex_blocking_loaded] return
    if [catch {eval $hexlib make_blocking_periodic $args} res] {
        mess "$res\n" red
        return
    }
}

proc ic_hex_create_voi {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib create_voi $args]
    return $res
}

# To fix old GUI replay file
proc ic_hex_get_node_location {args} {
    global hexlib 
    global _tempx _tempy _tempz
    
    if ![ic_hex_blocking_loaded] return
    set node [lindex $args  0]
    set res [eval $hexlib get_node_location $node]
    set i 0
    set tvars [lrange $args 1 end]
    set varlist ""
    foreach tvar $tvars {
        set $tvar [lindex $res $i]
        lappend varlist $tvar [lindex $res $i]
        incr i
    }
    eval hex_set_return_vars $varlist
    return $res
}
set dont_record_command(ic_hex_get_node_location) 1

proc ic_hex_set_node_location {args} {
    global hexlib
    global _tempx _tempy _tempz

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib set_node_location [join $args]]    
    return $res
}

proc ic_hex_normalize_grid_lines {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib normalize_grid_lines $args]
    return $res
}

proc ic_hex_floating_grid {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib floating_grid $args]
    return $res
}

proc ic_hex_separate_classes {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib separate_classes $args]
    return $res
}

proc ic_hex_separate_grid_lines {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib separate_grid_lines $args]
    return $res
}

proc ic_hex_place_nodes {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib place_nodes $args]
    return $res
}
set dont_record_command(ic_hex_place_nodes) 1

proc ic_hex_rotate_nodes {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib rotate_nodes $args]
    return $res
}

proc ic_hex_list_surfaces {args} {
    global hexlib

    set res [eval $hexlib list_surfaces $args]
    return $res
}
set dont_record_command(ic_hex_list_surfaces) 1

proc ic_hex_make_nodes_not_periodi {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib make_nodes_not_periodi $args]
    return $res
}

proc ic_hex_set_periodicity {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib set_periodicity $args]
    return $res
}

proc ic_hex_update_periodicity {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib update_periodicity $args]
    return $res
}

proc ic_hex_clear_association {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib clear_association $args]
    return $res
}

proc ic_hex_rename_blocking {args} {
    global hexlib batch_mode

    if ![ic_hex_blocking_loaded] return
    set res ""
    foreach topo [ic_hex_print_topo_tree] {
        set name [lindex $topo 0]
        if {$name == [lindex $args 0]} {
            set res [eval $hexlib rename_blocking $args]
            break
        }
    }
    if !$batch_mode {
        aie_after_rename_blocking [lindex $args 0]
    }
    return $res
}

proc ic_hex_set_linewidth {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib set_linewidth $args]
    return $res
}

proc ic_hex_set_linewidth2 {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib set_linewidth $args]
    return $res
}
set dont_record_command(ic_hex_set_linewidth2) 1

## Switch to another blocking topology
## Usage: ic_hex_switch_blocking <topo_name>

proc ic_hex_switch_blocking {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res ""
    foreach topo [ic_hex_print_topo_tree] {
        set name [lindex $topo 0]
        if {$name == [lindex $args 0]} {
            set res [eval $hexlib switch_blocking $args]
            break
        }
    }
    return $res
}

proc ic_hex_duplicate_blocking {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib duplicate_blocking $args]
    return $res
}

proc ic_hex_transform_blocking {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib transform_blocking $args]
    return $res
}

proc ic_hex_move_node {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib move_node $args]
    return $res
}

proc ic_hex_move_face {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib move_face $args]
    return $res
}

proc ic_hex_read_bocofile {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib read_bocofile $args]
    return $res
}

proc ic_hex_get_indices_should_look_good {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib get_indices_should_look_good $args]
    return $res
}
set dont_record_command(ic_hex_get_indices_should_look_good) 1

proc ic_hex_assemble_topo {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib assemble_topo $args]
    return $res
}

proc ic_hex_write_ppm_file {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib write_ppm_file $args]
    return $res
}

proc ic_hex_graphics_loc_h {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib graphics_loc_h $args]
    return $res
}

proc ic_hex_load_undo_file {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib load_undo_file $args]
    return $res
}

## merge mapped or free blocks
## <br>Usage 2D: ic_hex_merge_blocks block_num ublock_num
## <br>          ic_hex_merge_blocks ublock_num1 ublock_num2
## <br>          ic_hex_merge_blocks block_num1 block_num2 block_num3 ...
## <br>Usage 3D: ic_hex_merge_blocks block_num1 block_num2 block_num3 ...
## <br>          ic_hex_merge_blocks ublock_num1 ublock_num2 ublock_num3 ...
## block_num means mapped block
## ublock_num means free block

proc ic_hex_merge_blocks {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib merge_blocks $args]
    return $res
}

proc ic_hex_set_background {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib set_background $args]
    return $res
}

proc ic_hex_multi_block {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib multi_block $args]
    return $res
}

proc ic_hex_delete_composite {curves} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib delete_composite $curves]
    return $res
}

## Returns the curve names that make up the composite curve.
proc ic_hex_get_proj_curves {compcurve} {
    global hexlib

    if ![ic_hex_blocking_loaded] { return "" }
    set res [eval $hexlib get_proj_curves $compcurve]
    return $res
}
set dont_record_command(ic_hex_get_proj_curves) 1

## Returns the composite curve name given any of the curve names that belong to it.
## <br>Hexa composite curves are given the name of the first curve in the list of curve
## names that make up the composite curve.
proc ic_hex_find_comp_curve {curve} {
    global hexlib

    if ![ic_hex_blocking_loaded] { return "" }
    set res [eval $hexlib find_comp_curve $curve]
    return $res
}

proc ic_hex_collapse_blocks {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib  collapse_blocks $args]
    return $res
}

proc ic_hex_collapse_edge {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib collapse_edge $args]
    return $res
}

## Remove nodes from faces in a free 3d block 
## Removing of node is not allowed for block corners
## <br>Usage: ic_hex_delete_node_on_edge vertex_num 

proc ic_hex_delete_node_on_edge {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib delete_node_on_edge $args]
    return $res
}

proc ic_hex_vertex_to_edge {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib vertex_to_edge $args]
    return $res
}

proc ic_hex_merge_vertices {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib merge_vertices $args]
    return $res
}

proc ic_hex_n_nodes_edge {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib n_nodes_edge $args]
    return $res
}
set dont_record_command(ic_hex_n_nodes_edge) 1

## Sets the mesh params for the pre-mesh
## br>Usage: ic_hex_set_mesh_params parts <fix_counts> <fix_laws> <curve_bunching> -version 110
## parts: the list of parts that contain blocks. Use <i>[volume_activename_string]</i> 
## to return all the active part names containing blocks
## fix_counts: change the geometry law of the edges to the default (BiGeometric) geometry law
## fix_laws: adjusts the number of nodes on each edge based on the global surface or curve mesh size
## curve_bunching; transfers the advanced bunching parameters specified for curves to their associated edges

proc ic_hex_set_mesh_params {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib set_mesh_params $args]
    return $res
}

proc ic_hex_set_curve_params {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib set_curve_params $args]
    return $res
}

proc ic_hex_set_surface_params {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib set_surface_params $args]
    return $res
}

proc ic_hex_create_composite {curves} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib composite_curve $curves]
    return $res
}

## Usage: ic_hex_composite_curve curve1 curve2 curve3 ...
## <br>Creates a composite curve from the list of curves.
## <br>The compcurve name is the name of the first curve in the list.
proc ic_hex_composite_curve {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib composite_curve $args]
    return $res
}

proc ic_hex_compute_mesh_size {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib compute_mesh_size $args]
    return $res
}
set dont_record_command(ic_hex_compute_mesh_size) 1

proc ic_hex_set_node_projection {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib set_node_projection $args]
    return $res
}

proc ic_hex_set_element_materials {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib set_element_materials $args]
    return $res
}

## Marks blocks to be later used in operations on specific blocks.  These include block splitting, O-grids, and tranformation operations.
## <br>Usage: ic_hex_mark_blocks superblock block_number
## <br>Usage: ic_hex_mark_blocks unmark
## <br>Only one <b>block_number</b> is allowed.  Repeat the command for multiple block numbers.
## <br>The <b>unmark</b> version of the command clears all the marked blocks.  This should always be done before marking new blocks.
proc ic_hex_mark_blocks {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib mark_blocks $args]
    return $res
}

proc ic_hex_select_value {args} {
    global hexlib
    
    busy reset
    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib select_value $args]
    return $res
}
set dont_record_command(ic_hex_select_value) 1

proc ic_hex_ray_x_edge_value {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib ray_x_edge_value $args]
    return $res
}
set dont_record_command(ic_hex_ray_x_edge_value) 1

proc ic_hex_set_edge_projection {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib set_edge_projection $args]
    return $res
}

proc ic_hex_auto_associate_geometry {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib auto_associate_geometry $args]
    return $res
}

proc ic_hex_morph_blocking_to_geometry {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib morph_blocking_to_geometry $args]
    return $res
}

proc ic_hex_unproject_face {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib unproject_face $args]
    return $res
}

proc ic_hex_select_curve {args} {
    global hexlib
    
    busy reset
    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib select_curve $args]
    return $res
}

proc ic_hex_select_point {args} {
    global hexlib
    
    busy reset
    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib select_point $args]
    return $res
}
set dont_record_command(ic_hex_select_point) 1

## Returns vertex indices in the index range and block parts specified.
## <br>Usage: ic_hex_select_nodes num method index_range m parts
## <br>Ex: <i>ic_hex_select_nodes 1 all 0:2,3 2:1,3 m [volume_activename_string]</i>

## <p>Argument descriptions:
## <table border>
## <tr><td><b>num</td><td>1</td></tr>
## <tr><td><b>method</td><td><b>all</b>, or <b>inpoly</b> p1 p2 p3 p4,
## where each p is the xyz of a point</td></tr>
## <tr><td><b>index_range</td><td>Specifies the index range to limit selection.
## Use <i>[range_string]</i> to return the current active index range</td></tr>
## <tr><td><b>m</td><td>"m" indicates the following aguments are part names</td></tr>
## <tr><td><b>parts</td><td>The list of parts that contain blocks. Use
## <i>[volume_activename_string]</i> to return all the active part names containing blocks</td></tr>
## </table>
## <br>The following arguments may be appended:
## <table border>
## <tr><td><b>node_numbers</td><td>Return node numbers instead of indices</td></tr>
## <tr><td><b>surface</td><td> Return only external vertices</td></tr>
## <tr><td><b>-not_blanked</td><td>Normally, blanked blocks have no affect on which
## vertices are returned.  This option ensures vertices turned off due to blanked blocks are not returned.</td></tr>
## </table border>
proc ic_hex_select_nodes {args} {
    global hexlib
    
    busy reset
    if ![ic_hex_blocking_loaded] { return "" }
    set res [eval $hexlib select_nodes $args]
    return $res
}
set dont_record_command(ic_hex_select_nodes) 1

proc ic_hex_select_node {args} {
    global hexlib
    
    busy reset
    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib select_node $args]
    return $res
}
set dont_record_command(ic_hex_select_node) 1

proc ic_hex_mesh_params {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib mesh_params $args]
    return $res
}
set dont_record_command(ic_hex_mesh_params) 1

## Returns edge ID's in the range and parts specified
## <br>Usage: ic_hex_select_edge display method index_range max num m parts
## <br>Ex: <i>ic_hex_select_edge no_highlight all [range_string] max 1 m
## [volume_activename_string] new_format edge_segment volume</i>

## <p>Argument descriptions:
## <table border>
## <tr><td><b>display</td><td><b>no_highlight</b> to not highlight the edge</td></tr>
## <tr><td><b>method</td><td><b>all</b>, or <b>inpoly</b> p1 p2 p3 p4,
## where each p is the xyz of a point</td></tr>
## <tr><td><b>index_range</td><td>Specifies the index range to limit selection.
## Use <i>[range_string]</i> to return the current active index range</td></tr>
## <tr><td><b>max</td><td>the text "max" indicates the following number is the maximum amount to select</td></tr>
## <tr><td><b>num</td><td>Usually 1</td></tr>
## <tr><td><b>m</td><td>"m" indicates the following aguments are part names</td></tr>
## <tr><td><b>parts</td><td>The list of parts that contain blocks. Use
## <i>[volume_activename_string]</i> to return all the active part names containing blocks</td></tr>
## </table>
## <br>The following arguments may be appended:
## <table border>
## <tr><td><b>new_format</td><td></td></tr>
## <tr><td><b>edge_segment</td><td></td></tr>
## <tr><td><b>volume</td><td>return internal volume edges also.
## Otherwise just return external edges.</td></tr>
## </table border>
proc ic_hex_select_edge {args} {
    global hexlib
    
    busy reset
    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib select_edge $args]
    return $res
}
set dont_record_command(ic_hex_select_edge) 1

proc ic_hex_erase_edge_mesh {args} {
    global hexlib
    global batch_mode
    
    if $batch_mode { return }
    set res [eval $hexlib erase_edge_mesh $args]
    
    return $res
}
set dont_record_command(ic_hex_erase_edge_mesh) 1


# ####################################### Interactive commands #############################

proc ic_hex_display_bounding_box {args} {
    global hexlib 
    global batch_mode

    if $batch_mode { return }
    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib display_bounding_box $args]
    return $res
}
set dont_record_command(ic_hex_display_bounding_box) 1

proc ic_hex_display_periodic_faces {args} {
    global hexlib batch_mode

    if $batch_mode { return }
    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib display_periodic_faces $args]
    return $res
}
set dont_record_command(ic_hex_display_periodic_faces) 1

proc ic_hex_display_text {args} {
    global hexlib batch_mode

    if $batch_mode { return }
    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib display_text $args]
    return $res
}
set dont_record_command(ic_hex_display_text) 1

proc ic_hex_create_window {args} {
    global hexlib batch_mode

    if $batch_mode { return }
    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib create_window $args]
    return $res
}
set dont_record_command(ic_hex_create_window) 1

## Sets the visible index range for the blocking. 
## <br>Usage: ic_hex_display_edge_mesh index_range m parts volume
## <br>Ex: <i>ic_hex_display_edge_mesh 1:2,3 m [volume_activename_string] volume</i>
## <p>Only specify the ranges which are limiting indices, not fully displayed indices.
## <br>Ex. For a box with max indices of 3 in i, j, and k (including VORFN), if only j and k are
## constrained, this argument may look like this: 0:2,3 2:1,3.  The 1 index is not specified
## because it is not limited.
## <br>To display the full index range, leave the argument empty.
## <br>To return the current index range, use the command <i>range_string</i>.
proc ic_hex_display_edge_mesh {args} {
    global hexlib
    global batch_mode

    if $batch_mode { return }
    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib  display_edge_mesh $args]
    return $res
}
set dont_record_command(ic_hex_display_edge_mesh) 1

proc ic_hex_display_faces {args} {
    global hexlib
    global batch_mode

    if $batch_mode { return }
    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib  display_faces $args]
    
    return $res
}
set dont_record_command(ic_hex_display_faces) 1

proc ic_hex_display_surfaces {args} {
    global hexlib
    global batch_mode

    if $batch_mode { return }
    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib  display_surfaces $args]
    
    return $res
}
set dont_record_command(ic_hex_display_surfaces) 1

## Returns face ID's in the range and parts specified.
## <br>Usage: ic_hex_select_super_faces method max num index_range parts
## <br>Usage: ic_hex_select_super_faces method max num corners v1 v2 index_range parts
## <br>Ex: <i>ic_hex_select_super_faces all max 1 [range_string] [volume_activename_string]</i>
## <p>Argument descriptions:
## <table border>
## <tr><td><b>method</td><td><b>all</b>, or <b>inpoly</b> p1 p2 p3 p4,
## where each p is the xyz of a point</td></tr>
## <tr><td><b>max</td><td>the text "max" indicates the following number is the maximum amount to select</td></tr>
## <tr><td><b>num</td><td>Usually 1</td></tr>
## <tr><td><b>corners</td><td>The text "corners" indicates the faces will be selected by the two corners method</td></tr>
## <tr><td><b>v1, v2</td><td>vertex numbers for the two corners method.  Diagonally opposed vertices.</td></tr>
## <tr><td><b>index_range</td><td>Specifies the index range to limit selection.
## Use <i>[range_string]</i> to return the current active index range</td></tr>
## <tr><td><b>parts</td><td>The list of parts that contain blocks. Use
## <i>[volume_activename_string]</i> to return all the active part names containing blocks</td></tr>
## </table>
proc ic_hex_select_super_faces {args} {
    global hexlib
    global batch_mode
    
    busy reset
    if $batch_mode { return }
    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib select_super_faces $args]
    return $res
}
set dont_record_command(ic_hex_select_super_faces) 1

proc ic_hex_display_curves {args} {
    global hexlib
    global batch_mode

    if $batch_mode { return }
    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib display_comp_curves $args]
    return $res
}
set dont_record_command(ic_hex_display_curves) 1

proc ic_hex_scan_plane {args} {
    global hexlib
    global batch_mode

    if $batch_mode { return }
    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib scan_plane $args]
    return $res
}
set dont_record_command(ic_hex_scan_plane) 1

proc ic_hex_display_elements {args} {
    global hexlib
    global batch_mode

    if $batch_mode { return }
    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib display_elements $args]
    return $res
}
set dont_record_command(ic_hex_display_elements) 1

proc ic_hex_select_surface {args} {
    global hexlib batch_mode
    busy reset
    if $batch_mode { return }
    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib select_surface $args]
    return $res
}
set dont_record_command(ic_hex_select_surface) 1

proc ic_hex_set_depthcue {args} {
    global hexlib
    global batch_mode

    if $batch_mode { return }
    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib set_depthcue $args]
    return $res
}
set dont_record_command(ic_hex_set_depthcue) 1

proc ic_hex_display_axes {args} {
    global hexlib
    global batch_mode

    if $batch_mode { return }
    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib display_axes $args]
    return $res
}
set dont_record_command(ic_hex_display_axes) 1

proc ic_hex_erase_axes {args} {
    global hexlib
    global batch_mode

    if $batch_mode { return }
    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib erase_axes $args]
    return $res
}
set dont_record_command(ic_hex_erase_axes) 1

proc ic_hex_display_nodes {args} {
    global hexlib
    global batch_mode

    if $batch_mode { return }
    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib display_nodes $args]
    return $res
}
set dont_record_command(ic_hex_display_nodes) 1

proc ic_hex_display_points {args} {
    global hexlib
    global batch_mode

    if $batch_mode { return }
    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib display_points $args]
    return $res
}
set dont_record_command(ic_hex_display_points) 1

proc ic_hex_display_super_edges {args} {
    global hexlib
    global batch_mode

    if $batch_mode { return }
    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib display_super_edges $args]
    return $res
}
set dont_record_command(ic_hex_display_super_edges) 1

proc ic_hex_display_super_faces {args} {
    global hexlib
    global batch_mode

    if $batch_mode { return }
    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib display_super_faces $args]
    return $res
}
set dont_record_command(ic_hex_display_super_faces) 1

proc ic_hex_select_super_face {args} {
    global hexlib
    global batch_mode
    
    busy reset
    if $batch_mode { return }
    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib select_super_face $args]
    return $res
}
set dont_record_command(ic_hex_select_super_face) 1

proc ic_hex_display_super_blocks {args} {
    global hexlib
    global batch_mode

    if $batch_mode { return }
    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib display_super_blocks $args]
    return $res
}
set dont_record_command(ic_hex_display_super_blocks) 1

proc ic_hex_dynamic_edge_mesh {args} {
    global hexlib
    global batch_mode

    if $batch_mode { return }
    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib dynamic_edge_mesh $args]
    return $res
}
set dont_record_command(ic_hex_dynamic_edge_mesh) 1

proc ic_hex_orient {args} {
    global hexlib
    global batch_mode

    if $batch_mode { return }
    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib orient $args]
    return $res
}
set dont_record_command(ic_hex_orient) 1

proc ic_hex_multi_grid_level_check {args} {
    global hexlib batch_mode

    if $batch_mode { return }
    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib multi_grid_level_check $args]
    return $res
}

# ##############################################################################################

proc ic_hex_change_element_id {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib change_element_id $args]
    return $res
}

# old GUI compatibility
proc ic_hex_cei {args} {
    global hexlib

    return [eval ic_hex_change_element_id $args]
}

proc ic_hex_dls {args} {
    global hexlib

    return [eval ic_hex_delete_station $args]
}

proc ic_hex_rh {args} {
    global hexlib

    return [eval ic_hex_ratio_histogram $args]
}

proc ic_hex_rr {args} {
    global hexlib

    return [eval ic_hex_ratio_range $args]
}

proc ic_hex_dem {args} {
    global hexlib

    return [eval ic_hex_display_edge_mesh $args]
}

proc ic_hex_dcr {args} {
    global hexlib

    return [eval ic_hex_display_curve $args]
}

proc ic_hex_sp {args} {
    global hexlib

    return [eval ic_hex_scan_plane $args]
}

proc ic_hex_del {args} {
    global hexlib

    return [eval ic_hex_display_elements $args]
}

proc ic_hex_wh {args} {
    global hexlib

    return [eval ic_hex_worst_hex $args]
}

proc ic_hex_ps {args} {
    global hexlib

    return [eval ic_hex_project_to_surface $args]
}

proc ic_hex_rb {args} {
    global hexlib

    return [eval ic_hex_restore_blocking $args]
}

proc ic_hex_oo {args} {
    global hexlib

    return [eval ic_hex_outer_o_grid $args]
}

proc ic_hex_sg {args} {
   global hexlib

    return [eval ic_hex_split_grid $args]
}

proc ic_hex_se {args} {
   global hexlib

    return [eval ic_hex_split_edge $args]
}

proc ic_hex_sm {args} {
   global hexlib

    return [eval ic_hex_set_mesh $args]
}

proc ic_hex_rep {args} {
   global hexlib

    return [eval ic_hex_remove_edge_point $args]
}

proc ic_hex_sd {args} {
   global hexlib

    return [eval ic_hex_superdomain $args]
}


proc ic_hex_worst_hex {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] { return "" }
    if [catch {eval $hexlib worst_hex $args} res] {
        mess "Error: $res\n" red
        return ""
    } else {
        return $res
    }
}
set dont_record_command(ic_hex_worst_hex) 1

## Move the nodes to surfaces curves and points
## Usage: ic_hex_project_to_surface vertices index_range parts <move_ogrid_nodes>
## <br>vertices: vertices to project
## <br>index_range: only operates on this index_range
## Use [range_string] to return the current active index range
## <br>parts: the list of parts that contain blocks
## <br>move_ogrid_nodes: move also the ogrid nodes

proc ic_hex_project_to_surface {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    if {[lindex $args end] == "only_new"} {
        foreach n [lindex $args 0] {
             set arg [lrange $args 1 end-1]
             regsub -all "{" $arg "" arg
             regsub -all "}" $arg "" arg
            set res [eval $hexlib project_to_surface $n $arg]
        }
    } else {
        set res [eval $hexlib project_to_surface $args]
    }
    return $res
}

proc ic_hex_project_to_points {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib project_to_points $args]
    return $res
}

## Create ogrid
## ic_hex_ogrid <offset> parts -version 50 <link_shape>
## offset: specifies the height of the ogrid layer
## link_shape: the internal ogrid block will be created with all internal edges and faces 
## shaped by the nearest, corresponding geometry

proc ic_hex_ogrid {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib ogrid $args]
    return $res
}

proc ic_hex_write_file {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib write_file $args]
    return $res
}

# for backward compatibility with old hexa GUI
proc ic_hex_save {args} {
    return [eval ic_hex_write_file $args]
}

proc ic_hex_print_coordinate_system {args} {
    global hexlib

    set res [eval $hexlib print_coordinate_system $args]
    return $res
}

proc ic_hex_list_coordinate_systems {args} {
    global hexlib

    set res [eval $hexlib list_coordinate_systems $args]
    return $res
}
set dont_record_command(ic_hex_list_coordinate_systems) 1

proc ic_hex_set_coordinate_system {what} {
    global hexlib

    if {$what == "global"} {
        set res [eval $hexlib undefine_variable coordinate_system]
    } else {
        set res [eval $hexlib define_variable coordinate_system $what]
    }
    return $res
}

proc ic_hex_define_coordinate_system {args} {
    global hexlib

    set res [eval $hexlib define_coordinate_system $args]
    return $res
}

proc ic_hex_delete_coordinate_system {args} {
    global hexlib

    set res [eval $hexlib delete_coordinate_system $args]
    return $res
}
proc ic_hex_define_variable {args} {
    global hexlib

    set res [eval $hexlib define_variable $args]
    return $res
}

proc ic_hex_undefine_variable {args} {
    global hexlib

    set res [eval $hexlib undefine_variable $args]
    return $res
}

proc ic_hex_list_families {args} {
    global hexlib

    if ![ic_hex_blocking_loaded]  { return "" }
    set res [eval $hexlib list_families $args]
    return $res
}
set dont_record_command(ic_hex_list_families) 1

## This returns only block parts
proc ic_hex_list_block_families {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] { return "" }
    set res [eval $hexlib list_block_families $args]
    return $res
}
set dont_record_command(ic_hex_list_block_families) 1

## This returns all block parts except part_name
## <br>Usage: ic_hex_list_block_families_without part_name
proc ic_hex_list_block_families_without {{skip VORFN}} {
    global hexlib

    if ![ic_hex_blocking_loaded] { return "" }
    set parts ""
    foreach p [eval $hexlib list_block_families] {
        if {[lsearch $parts $p] >= 0} continue
        if {[lsearch $skip $p] >= 0} continue
        lappend parts $p
    }
    return $parts
}
set dont_record_command(ic_hex_list_block_families_without) 1

## This returns only blocking surface familes
proc ic_hex_list_surface_families {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] { return "" }
    set famdims [eval $hexlib list_families dims]
    set res ""
    foreach {fam dim} $famdims {
    if {$dim != 3} {
        lappend res $fam
    }
    }
    return $res
}
set dont_record_command(ic_hex_list_surface_families) 1

## This returns the list of super block numbers
proc ic_hex_list_block_numbers {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] { return "" }
    set res [eval $hexlib list_block_numbers $args]
    return $res
}
set dont_record_command(ic_hex_list_block_numbers) 1

## This returns all non empty block parts

proc ic_hex_non_empty_families {args} {
    global hexlib
    
    if ![ic_hex_blocking_loaded] { return "" }  
    set blfams [ic_hex_list_block_families]
    return $blfams
}
set dont_record_command(ic_hex_non_empty_families) 1

proc ic_hex_manhattan {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib manhattan $args]
    return $res
}

proc ic_hex_fluent {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib fluent $args]
    return $res
}

proc ic_hex_superdomain {args} {
    global hexlib

    set res [eval $hexlib superdomain $args]
    return $res
}

## Saves the current blocking
## br>Usage: ic_hex_save_blocking file <-sub_topo topo>

proc ic_hex_save_blocking {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    mess "Writing blocking file $args ..."
    set res [eval $hexlib save_blocking $args]
    mess "\nDone saving blocking file.\n"
    return $res
}

proc ic_hex_set_mesh {args} {
    global hexlib env

    set res ""
    if [ic_wb2_input_parameter_mode] {
        if {$args != ""} {
            set args2 [lrange $args 0 1]
            foreach "n v" [lrange $args 2 end] {
                if [ic_wb2_is_input_blocking_param_set $n [lrange $args 0 1]] continue
                if {$v != ""} {
                    lappend args2 $n $v
                } else {
                    lappend args2 $n
                }
                
            }
            if {$args2 == ""} return
            set args $args2
        }
    }
    set res [eval $hexlib set_mesh $args]
    return $res
}

## Split hexa blocks.
## <br>Usage: ic_hex_split_grid vertex1 vertex2 value m parts flags
## <br>Usage: ic_hex_split_grid index dim value m parts flags
## <p>Argument descriptions:
## <table border>
## <tr><td><b>vertex1</td><td>vertex number at end of edge</td></tr>
## <tr><td><b>vertex2</td><td>vertex number at other end of edge</td></tr>
## <tr><td><b>value</td><td>split value
##      <ul>
##      <li> a decimal between 0 and 1
##      <li> <b>abs</b>:distance
##      <li> point name
##      <li> <b>curve</b>:curvename:parameter
##      </ul></td></tr>
## <tr><td><b>m</td><td><b>m</b> indicates the following are part names</td></tr>
## <tr><td><b>parts</td><td>parts to split through</td></tr>
## <tr><td><b>flags</td><td>When set to <b>marked</b>, only the marked blocks are split
## <br>The command ic_hex_mark_blocks will mark blocks</td></tr>
## <tr><td><b>index</td><td>index of vertex on the lower side of <b>dim</b> in format { i j k etc }</td></tr>
## <tr><td><b>dim</td><td>dimension of edge to split where 0=i, 1=j, 2=k, 3=O3, etc...</td></tr>
## </table>

proc ic_hex_split_grid {args} {
    global hexlib projlib

    if {[scan [lindex $args 2] {curve:%[^:]:%f} curve par] == 2} {
        if {$par < 0 || $par > 1} {
            return -code error "Curve parameter must be between 0 and 1"
        }
        set num [$projlib get_number_by_name curve $curve] 
        if [catch {gk_get_crv_nat_par $par $num} res] {
            return -code error $res
        }
        set args [lreplace $args 2 2 "curve:$curve:$res"]
    }
    set res [eval $hexlib split_grid $args]
    return $res
}

proc ic_hex_delete_station {args} {
    global hexlib

    set res [eval $hexlib delete_station $args]
    return $res
}

proc ic_hex_outer_o {args} {
    global hexlib

    set res [eval $hexlib outer_o $args]
    return $res
}

## Loads a blocking file
## <br>Usage: ic_hex_restore_blocking <file>

proc ic_hex_restore_blocking {args} {
    global hexlib batch_mode

    if ![ic_hex_init] { return 0 }
    set res [eval $hexlib restore_blocking $args]
    ic_hex_is_modified 0
    if !$batch_mode { aie_after_blocking_loaded }
    ic_undo_clear
    return $res
}

## Returns whether or not a blocking is loaded.
## <br>Usage: ic_hex_blocking_loaded
proc ic_hex_blocking_loaded {args} {
    global hexlib

    if ![info exists hexlib] { return 0 }
    set res [eval $hexlib blocking_loaded $args] 
    # sanity check
    if !$res {
       ic_hex_remove_dladaptobj
    } else {
        ic_hex_init
    }
    return $res
}
set dont_record_command(ic_hex_blocking_loaded) 1

proc ic_hex_place_node {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib place_node $args]
    return $res
}
set dont_record_command(ic_hex_place_node) 1

proc ic_hex_split_edge {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib split_edge $args]
    return $res
}
set dont_record_command(ic_hex_split_edge) 1

proc ic_hex_remove_edge_points {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib remove_edge_points $args]
    return $res
}

## interactive remove edge split vertices
proc ic_hex_remove_edge_point {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib remove_edge_point $args]
    return $res
}
set dont_record_command(ic_hex_remove_edge_point) 1

proc ic_hex_ijk_max {args} {
    global hexlib

    set res [eval $hexlib ijk_max $args]
    return $res
}
set dont_record_command(ic_hex_ijk_max) 1

proc ic_hex_ijk_material {args} {
    global hexlib

    set res [eval $hexlib ijk_material $args]
    return $res
}
set dont_record_command(ic_hex_ijk_material) 1

## Returns a list with ratio values of the selected quality criterion:
## value 1: the minimum value found
## value 2: the maximum value found
## the number of the next values depends on the number of bars, for each bar (range) it will return 4 values:
## number of elements, the lowest value, the highest value, percent 
## <br>Usage: eval ic_hex_ratio_histogram number_of_bars parts proj <projection_type> minval <min> -type <criterion> maxval <max> new_format
## parts: the list of parts that contain blocks
## number_of_bars: the number of requested bars
## proj: set projection_type to -1 (no projection) or 0 (vertices) or 1 (edges) or 2 (faces)
## minval: set min to the minimum value of the requested ratio range
## maxval: set max to the maximum value of the requested ratio range
## type: set criterion to the requested quality criterion

proc ic_hex_ratio_histogram {args} {
    global hexlib

    set res [eval $hexlib ratio_histogram $args]
    return $res
}
#set dont_record_command(ic_hex_ratio_histogram) 1

proc ic_hex_ratio_range {args} {
    global hexlib

    set res [eval $hexlib ratio_range $args]
    return $res
}
set dont_record_command(ic_hex_ratio_range) 1

proc ic_hex_push_text {args} {
    global hexlib

    set res [eval $hexlib push_text $args]
    return $res
}

## obsolete
proc ic_hex_undo {args} {
    global hexlib

    set res [eval $hexlib undo $args]
    return $res
}
set dont_record_command(ic_hex_undo) 1

## obsolete
proc ic_hex_redo {args} {
    global hexlib

    set res [eval $hexlib redo $args]
    return $res
}
set dont_record_command(ic_hex_redo) 1

proc ic_hex_define_shared_wall {args} {
    global hexlib

    set res [eval $hexlib define_shared_wall $args]
    return $res
}

proc ic_hex_list_shared_walls {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib list_shared_walls $args]
    return $res
}
set dont_record_command(ic_hex_list_shared_walls) 1

proc ic_hex_remove_shared_wall {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib remove_shared_wall $args]
    return $res
}

proc ic_hex_get_curve_params {args} {
    global hexlib

    set res [eval $hexlib get_curve_params $args]
    return $res
}
set dont_record_command(ic_hex_get_curve_params) 1

proc ic_hex_get_surface_params {args} {
    global hexlib

    set res [eval $hexlib get_surface_params $args]
    return $res
}
set dont_record_command(ic_hex_get_surface_params) 1

proc ic_hex_unhighlight_curves {args} {
    global hexlib
    
    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib unhighlight_curves $args]
    return $res
}
set dont_record_command(ic_hex_unhighlight_curves) 1

proc ic_hex_extend_split {args} {
    global hexlib

    set res [eval $hexlib extend_split $args]
    return $res
}

proc ic_hex_index_from_edge {args} {
    global hexlib

    set res [eval $hexlib index_from_edge $args]
    return $res
}
set dont_record_command(ic_hex_index_from_edge) 1

proc ic_hex_straighten {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib straighten $args]
    return $res
}

proc ic_hex_initialize_mesh {args} {
    global hexlib batch_mode

    ic_hex_init
    set res [eval $hexlib initialize_mesh $args]
    ic_hex_set_mesh_params 
    if !$batch_mode {
        aie_after_blocking_loaded
    }
    return $res
}

proc ic_hex_set_family_projection {args} {
    global hexlib

    set res [eval $hexlib set_family_projection $args]
    return $res
}

proc ic_hex_list_family_projection {args} {
    global hexlib

    set res [eval $hexlib list_family_projection $args]
    return $res
}
set dont_record_command(ic_hex_list_family_projection) 1

proc ic_hex_rescale_ogrid {args} {
    global hexlib

    set res [eval $hexlib rescale_ogrid $args]
    return $res
}

proc ic_hex_project_face {args} {
    global hexlib

    set res [eval $hexlib project_face $args]
    return $res
}

proc ic_hex_check_mesh {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib check_mesh $args]
    return $res
}
set dont_record_command(ic_hex_check_mesh) 1

proc ic_hex_create_mesh {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib create_mesh $args]
    return $res
}

proc ic_hex_create_auto_surface_mesh  {args} {
    global hexlib
    
    ic_undo_suspend
    ic_hex_ensure_is_loaded
    set res [eval $hexlib create_auto_surface_mesh $args]
    ic_undo_resume
    return $res
}

proc ic_hex_renew {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib renew $args]
    return $res
}

proc ic_hex_unload_blocking {args} {
    global hexlib dladaptobj 
    global tdv_default batch_mode

    if ![info exists hexlib] { return "" }
    if [ic_hex_blocking_loaded] {
        set res [eval $hexlib unload_blocking $args]
    } else {
        set res ""
    }
    if !$batch_mode {
        if [info exists dladaptobj] {
            $tdv_default remove_image $dladaptobj
            $dladaptobj delete
            unset dladaptobj
        }
    }
    ic_hex_is_modified 0
    ic_hex_release_licensing
    return $res
}

## obsolete; use ic_hex_initialize_blocking
proc ic_hex_new_blocking {ents fam {bbox ""} {trf ""} {version 50}} {
    global hexlib
    
    ic_hex_init
    
    if {$bbox == ""} {
        set surfs ""; set crvs ""; set pts ""
        foreach {type name} $ents {
            switch $type {
                surface { lappend surfs $name }
                curve { lappend crvs $name }
                point { lappend pts $name }
            }
        }
        set bbox [ic_geo_bounding_box [list surface $surfs curve $crvs point $pts]]
    }

    set cmd "ic_hex_initialize_mesh new_numbering new_blocking $fam bbox [join $bbox]"
    if {$trf != ""} {
        append cmd " transform [join $trf]"
    }
    append cmd " -version $version"

    return [eval $cmd]
}

## initialize blocking from key points
proc ic_hex_keypoint_blocking {args} {
    global hexlib batch_mode
    
    ic_hex_init
    set res [eval $hexlib keypoint_blocking $args]
    if !$batch_mode {
        aie_after_blocking_loaded
    }
    return $res
}

## initialize a 3D blocking from ents
## <br>Initializing is required before any other blocking commands can be done.
## <br>Usage: ic_hex_initialize_blocking ents part oriented {version 101}

if { 1 } {
proc ic_hex_initialize_blocking { args } {
    global hexlib  batch_mode

    ic_hex_init

    set res [ eval $hexlib initialize_blocking $args ]
    ic_hex_set_mesh_params 
    if !$batch_mode {
        aie_after_blocking_loaded
    }
    return $res

}
} else {
proc ic_hex_initialize_blocking { ents fam oriented {version 50}} {

# all of this tcl code has been migrated into C++ 
# hex/material.C initialize_blocking()
    
    if {$ents == ""} {
        foreach type {surface curve point} {
            foreach ent [ic_geo_get_objects $type] {
                lappend ents $type $ent
            }
        }
    }

    set surfs ""; set crvs ""; set pts ""
    foreach {type name} $ents {
        switch $type {
            surface { lappend surfs $name }
            curve { lappend crvs $name }
            point { lappend pts $name }
        }
    }
    set obbox [ic_geo_bounding_box [list surface $surfs curve $crvs point $pts]]
    set bmin [lindex $obbox 0]
    set bmax [lindex $obbox 1]

    foreach i {0 1} {
        if {[lindex $bmin $i] == [lindex $bmax $i]} {
            set orient 0
            set obbox [list $bmin $bmax]
            break
        }
    }
    
    set trf ""
    if $oriented {
        set trf [ic_hex_oriented_bbox $ents]
    }
    
    # create only a block if blocking initialized already
    if [ic_hex_blocking_loaded] {
        for {set i 0} {$i < 3} {incr i} {
            set p1($i) [lindex $bmin $i]
            set p2($i) [lindex $bmax $i]
        }
        set corners [list [list $p1(0) $p1(1) $p1(2)] [list $p1(0) $p1(1) $p2(2)]  \
                          [list $p2(0) $p1(1) $p1(2)] [list $p2(0) $p1(1) $p2(2)]  \
                          [list $p1(0) $p2(1) $p1(2)] [list $p1(0) $p2(1) $p2(2)]  \
                          [list $p2(0) $p2(1) $p1(2)] [list $p2(0) $p2(1) $p2(2)]]

        if $oriented {
            foreach pt $corners {
                set tpt [ic_hex_transform_point $trf $pt]
                lappend tcorners [join $tpt]
            }
            set corners $tcorners
        }
        set args [concat $fam $corners $fam]
        return [eval ic_hex_create_block $args]
    }
    
    # initialize blocking by bbox or corners
    return [ic_hex_new_blocking $ents $fam $obbox $trf $version]
}
}

proc ic_hex_transform_point {trf pt} {
    global hexlib

    return [eval $hexlib transform_point [join [concat $pt $trf]]]
}

## Convert a block to structured (mapped)
## <br>Usage for 2D blocking: ic_hex_convert_to_struct block_number
## <br>Usage for 3D blocking: ic_hex_convert_to_struct free_face_number

proc ic_hex_convert_to_struct {args} {
    global hexlib

    set res [eval $hexlib convert_to_struct $args]
    return $res
}

proc ic_hex_convert_sides_to_mapped3d {args} {
    global hexlib

    set res [eval $hexlib convert_sides_to_mapped3d $args]
    return $res
}

proc ic_hex_convert_to_unstruct {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib convert_to_unstruct $args]
    return $res
}

## Convert a block to swept or convert a free block free face to mapped
## <br>Usage for convert a block to swept: ic_hex_convert_to_swept block_face [-merge_parallel]
##  -merge_parallel will merge all adjacent mapped faces at the same index level
## <br>Usage for convert a free block free face to mapped: ic_hex_convert_to_swept free_block_face 
## Note: only for 3D blocking

proc ic_hex_convert_to_swept {args} {
    global hexlib

    set res [eval $hexlib convert_to_swept $args]
    return $res
}

proc ic_hex_convert_unstruct_to_swept {args} {
    global hexlib

    set res [eval $hexlib convert_unstruct_to_swept $args]
    return $res
}

proc ic_hex_imprint_face {args} {
    global hexlib

    set res [eval $hexlib imprint_face $args]
    return $res
}

## Imprint loops of edges from one face onto another free block (2D) or free face (3D)
## <br>Usage for 2D blocking: ic_hex_imprint_loop target_block edge_loops
## <br>Usage for 3D blocking: ic_hex_imprint_loop target_face edge_loops

proc ic_hex_imprint_loop {args} {
    global hexlib

    set res [eval $hexlib imprint_loop $args]
    return $res
}

##  Combines into a single operation the ability to imprint loops from one or more sets of edges onto a free face, 
##  then split the block between the pair(s) of loops
## <br>Usage: ic_hex_imprint_loop_and_split_block3d free_face edge_loops

proc ic_hex_imprint_loop_and_split_block3d {args} {
    global hexlib

    set res [eval $hexlib imprint_loop_and_split_block3d $args]
    return $res
}

## Connect edges from one block onto another free block (2D)
## <br>Usage for 2D blocking: ic_hex_connect_edges target_block edges

proc ic_hex_connect_edges {args} {
    global hexlib

    set res [eval $hexlib connect_edges $args]
    return $res
}

proc ic_hex_get_blk_info {args} {
    global hexlib

    set res [eval $hexlib get_blk_info $args]
    return $res
}

## Create a swept block by merging two faces 
## <br>Usage: ic_hex_create_swept_block face1 face2

proc ic_hex_create_swept_block {args} {
    global hexlib

    set res [eval $hexlib create_swept_block $args]
    return $res
}

## Sets the type of mesh for unstructured 2D blocks
## <br>Usage: ic_hex_unstruct_face_type type
## <br><b>Type</b> can be <b>stl</b>, <b>all_tris</b>, <b>all_quads</b>,
## <b>several_tris</b>, or <b>one_tri</b>
proc ic_hex_unstruct_face_type {args} {
    global hexlib
    
    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib unstruct_face_type $args]
    return $res
}

proc ic_hex_set_sblock_mesh_type {args} {
    global hexlib

    set res [eval $hexlib set_sblock_mesh_type $args]
    return $res
}

proc ic_hex_set_ublock_mesh_type {args} {
    global hexlib

    set res [eval $hexlib set_ublock_mesh_type $args]
    return $res
}


proc ic_hex_set_n_tetra_smoothing_steps {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib set_n_tetra_smoothing_steps $args]
    return $res
}

proc ic_hex_convert_degen_to_yblock {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib convert_degen_to_yblock $args]
    return $res
}

proc ic_hex_update_comp_curves {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib update_comp_curves $args]
    return $res
}

proc ic_hex_write_cart_file {args} {
    global hexlib

    set res [eval $hexlib write_cart_file $args]
    return $res
}

proc ic_hex_print_sblock_info {args} {
    global hexlib

    set res [eval $hexlib print_sblock_info $args]
    return $res
}
set dont_record_command(ic_hex_print_sblock_info) 1

## Returns the block type (free, mapped or swept)
## <br>Usage: ic_hex_print_block_type_info block_num

proc ic_hex_print_block_type_info {args} {
    global hexlib

    set res [eval $hexlib print_block_type_info $args]
    return $res
}
set dont_record_command(ic_hex_print_block_type_info) 1


# ############################ HEXA SUBSET #######################################

proc ic_hex_create_subset {args} {
    global hexlib

    set res [eval $hexlib create_subset $args]
    return $res
}
set dont_record_command(ic_hex_create_subset) 1

## Creates a named selection subset
## <br>Usage: ic_hex_create_named_selection_subset name

proc ic_hex_create_named_selection_subset {args} {
    global hexlib

    set res [eval $hexlib create_subset named_selection $args]
    return $res
}

proc ic_hex_subset_add_items {args} {
    global hexlib

    set res [eval $hexlib subset_add_items $args]
    return $res
}
set dont_record_command(ic_hex_subset_add_items) 1

## Add entities to a named selection subset
## <br>Usage: ic_hex_subset_add_named_selection_items name type number_of_entities entities
## <br>name: the name of the subset
## <br>type: vertex, edge or face
## <br>number_of_entities: the number of entities to add
## <br>entities: 
## <br>in case of type vertex the number of the vertex followed by 0 -1, e.g. 15 0 -1
## <br>in case of type edge the edge number. e.g. 3 15 -1
## <br>in case of type face the face number, e.g. 14 15 19 18 (for a mapped face like { 14 15 19 18 }) or 18 24 -1 -1 (for a free face like { 18 - 24 u })

proc ic_hex_subset_add_named_selection_items {args} {
    global hexlib

    set res [eval $hexlib subset_add_items $args]
    return $res
}

proc ic_hex_subset_remove_items {args} {
    global hexlib

    set res [eval $hexlib subset_remove_items $args]
    return $res
}
set dont_record_command(ic_hex_subset_remove_items) 1

## Remove entities from a named selection subset
## <br>Usage: ic_hex_subset_remove_named_selection_items name type number_of_entities entities
## <br>name: the name of the subset
## <br>type: vertex, edge or face
## <br>number_of_entities: the number of entities to remove
## <br>entities: 
## <br>in case of type vertex the number of the vertex followed by 0 -1, e.g. 15 0 -1
## <br>in case of type edge the edge number. e.g. 3 15 -1
## <br>in case of type face the face number, e.g. 14 15 19 18 (for a mapped face like { 14 15 19 18 }) or 18 24 -1 -1 (for a free face like { 18 - 24 u })

proc ic_hex_subset_remove_named_selection_items {args} {
    global hexlib

    set res [eval $hexlib subset_remove_items $args]
    return $res
}

proc ic_hex_delete_subset {args} {
    global hexlib

    if ![eval ic_hex_subset_exist $args] {
        return
    }
    set res [eval $hexlib delete_subset $args]
    return $res
}
set dont_record_command(ic_hex_delete_subset) 1

## Delete a named selection subset
## <br>Usage: ic_hex_delete_named_selection_subset name

proc ic_hex_delete_named_selection_subset {args} {
    global hexlib

    if ![eval ic_hex_subset_exist $args] {
        return
    }
    set res [eval $hexlib delete_subset $args]
    return $res
}

proc ic_hex_subset_exist {args} {
    global hexlib

    if [catch {set res [eval $hexlib subset_exist $args]} ret] {
        return 0
    } else {
        return $res
    }
}
set dont_record_command(ic_hex_subset_exist) 1

proc ic_hex_display_subset {args} {
    global hexlib

    set res [eval $hexlib display_subset $args]
    return $res
}
set dont_record_command(ic_hex_display_subset) 1

proc ic_hex_subset_unused_name {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib subset_unused_name $args]
    return $res
}
set dont_record_command(ic_hex_subset_unused_name) 1

proc ic_hex_list_subsets {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] { return "" }
    set res [eval $hexlib list_subsets $args]
    return $res
}
set dont_record_command(ic_hex_list_subsets) 1

proc ic_hex_rename_subset {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib rename_subset $args]
    return $res
}
set dont_record_command(ic_hex_rename_subset) 1

## Rename a named selection subset
## <br>Usage: ic_hex_rename_named_selection_subset name new_name

proc ic_hex_rename_named_selection_subset {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib rename_subset $args]
    return $res
}

proc ic_hex_list_subset_entities {subset type} {
    global hexlib

    if ![ic_hex_blocking_loaded] { return "" }
    set ents [eval $hexlib list_subset_entities $subset $type]
    if {$type ==  "vertex" || $type == "block"} {
        set ents [join $ents]
    }
    return $ents
}
set dont_record_command(ic_hex_list_subset_entities) 1

proc ic_hex_get_subset_centroid {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib get_subset_centroid $args]
    return $res
}
set dont_record_command(ic_hex_get_subset_centroid) 1

## Returns 1 in case of a named selection subset (0 otherwise)
## <br>Usage: ic_hex_subset_named_selection name 

proc ic_hex_subset_named_selection {{name ""}} {

    if ![ic_hex_blocking_loaded] { return 0 }
    if {[lsearch "[ic_hex_list_subsets named_selection]" "$name"] >= 0} {
        return 1
    }
    return 0
}
set dont_record_command(ic_hex_subset_named_selection) 1

## Returns a list of all named selection subsets
## <br>Usage: ic_hex_subset_list_named_selections

proc ic_hex_subset_list_named_selections {} {

    if ![ic_hex_blocking_loaded] { return "" }
    return "[ic_hex_list_subsets named_selection]"
}
set dont_record_command(ic_hex_subset_list_named_selections) 1

proc ic_hex_super_determinant {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib super_determinant $args]
    return $res
}

proc ic_hex_oriented_bbox {ents} {
    global hexlib

    ic_hex_ensure_is_loaded
    set surfs ""
    set curves ""
    set points ""
    foreach {type obj} $ents {
        switch $type {
            surface { lappend surfs $obj }
            curve   { lappend curves $obj }
            point   { lappend points $obj }
        }
    }

    set csys [ic_csystem_get_current]
    set obbox [$hexlib oriented_bbox $surfs $curves $points $csys]
    return $obbox
}
set dont_record_command(ic_hex_oriented_bbox) 1

proc ic_hex_list_blocking_parts {} {
    return [ic_hex_list_block_families]
}
set dont_record_command(ic_hex_list_blocking_parts) 1

proc ic_hex_display_loc {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib display_loc $args]
    return $res
}
set dont_record_command(ic_hex_display_loc) 1

proc ic_hex_report_blocking {file} {

    if ![ic_hex_blocking_loaded] return
    if [catch {open $file w} fp] {
        ic_mess "$fp\n" red
        return
    }
#dimension    
    set dim [format %d [ic_hex_mesh_dimension]]
    puts $fp "Blocking dimension: ${dim}D"
    puts $fp "\n"
#topo
    set topos [ic_hex_print_topo_tree]
    puts $fp "Topologies:"
    foreach topo $topos {
        puts $fp "$topo"
    }
    puts $fp "\n"
#index range
    puts $fp "Index Range: [ic_hex_ijk_max]"
    puts $fp "\n"
#families
    puts $fp "Family dims: [ic_hex_list_families dims]"
    puts $fp "\n"
#nblocks and nnodes in each I,J,K,O3,O4...
    set blknodes [ic_hex_n_nodes_edge]
    set ndims [llength $blknodes]
    puts $fp "Number of dimensions: $ndims"
    set dims ""
    for {set i 0} {$i < $ndims} {incr i} {
        switch $i {
            0 { set dim I }
            1 { set dim J }
            2 { set dim K }
            default {set dim "O$i"}
        }
        
        set blocks [lindex $blknodes $i]
        set nblocks [llength $blocks]
        puts $fp "Block Information Along: $dim $nblocks \{$blocks\}"
        lappend dims $dim
    }
    puts $fp "List of Dimensions: $dims\n"
    puts $fp "\n"
#mesh size
    set blk_fams ""
    foreach fam [ic_hex_list_block_families] {
        if {$fam != "VORFN"} {
            lappend blk_fams $fam
        }
    }
    set mesh_info [string trimright [eval ic_hex_compute_mesh_size $blk_fams] \n]
    set nc 0
    set ne 0
    set nf 0
    set nv 0
    set nq 0
    set no 0
    set nh 0
    foreach i {0 1 2 3 4 5 6} {
        set [lindex {nc ne nf nv nq no nh} $i] [lindex $mesh_info $i]
    }
    set n_nodes [expr {$nc + $ne + $nf + $nv}]
    set n_quads [expr {$nq + $no}]
    puts $fp "Mesh size:"
    puts $fp "\tNumber of Nodes = $n_nodes"
    puts $fp "\tNumber of Quads = $n_quads"
    puts $fp "\tNumber of Hexas = $nh"
    puts $fp "\n"
# create mesh first
    ic_hex_create_mesh proj 2
#quality
    set diagnostics "determinant eriksson"
    puts $fp "Quality Diagnostics: $diagnostics"
    foreach diag $diagnostics {
        set ret [eval ic_hex_ratio_histogram 10 $blk_fams proj 2 $diag] 
        puts $fp "Quality - $diag range:"
        puts $fp $ret
    }
    close $fp
}

proc ic_hex_write_grid {file} {
    if ![ic_hex_blocking_loaded] return
    if [catch {open $file w} fp] {
        ic_mess "$fp\n" red
        return
    }
    set blknodes [ic_hex_n_nodes_edge]
    set ndims [llength $blknodes]
    set dims ""
    set nx -1; set ny -1; set nz -1
    for {set i 0} {$i < $ndims} {incr i} {
        set blocks [lindex $blknodes $i]
        set nblocks [expr [llength $blocks] - 2]
        switch $i {
            0 { set nx $nblocks }
            1 { set ny $nblocks }
            2 { set nz $nblocks }
        }
    }
    puts $fp "$nx $ny $nz"
    set vmin [eval ic_hex_vertex_number "{ 1 1 1 }"]
    set bmin [string trimright [ic_hex_get_node_location $vmin] \n]
    set ijkmax [ic_hex_ijk_max]
    set i [expr [lindex $ijkmax 0] - 1]
    set j [expr [lindex $ijkmax 1] - 1]
    set k [expr [lindex $ijkmax 2] - 1]
    set vmax [eval ic_hex_vertex_number "{ $i $j $k }"]
    set bmax [string trimright [ic_hex_get_node_location $vmax] \n]
    puts $fp "$bmin $bmax"
    for {set i 1} {$i <= $nx} {incr i} {
        for {set j 1} {$j <= $ny} {incr j} {
            for {set k 1} {$k <= $nz} {incr k} {
                set vnum1 [eval ic_hex_vertex_number "{ $i $j $k }"]
                set xyz1 [string trimright [ic_hex_get_node_location $vnum1] \n]
                set i2 [expr $i + 1]
                set j2 [expr $j + 1]
                set k2 [expr $k + 1]
                set vnum2 [eval ic_hex_vertex_number "{ $i2 $j2 $k2 }"]
                set xyz2 [ic_hex_get_node_location $vnum2]
                set dx [expr [lindex $xyz2 0] -  [lindex $xyz1 0]]
                set dy [expr [lindex $xyz2 1] -  [lindex $xyz1 1]]
                set dz [expr [lindex $xyz2 2] -  [lindex $xyz1 2]]
                puts $fp "$xyz1 $dx $dy $dz"
            }
        }
    }
    close $fp
}

# ##########################################################################################

proc ic_hex_block_surfaces_base {args} {
    ic_mess "Error: This command is obsolete\n" red
    return
}

proc ic_hex_block_surfaces_status {args} {    
    ic_mess "Error: This command is obsolete\n" red
    return
}

## Use Quad to mesh all of the surfaces with unstruct/free blocks

proc ic_hex_mesh_free_surfaces {args} {
    
    foreach {n v} $args {
        # e.g., -material $material
        set [string range $n 1 end] $v
    }
    # check for required args
    if ![info exists material] {
        ic_mess "Error: cannot mesh free surfaces without specifying a material\n" red
        return ""
    }
    if ![ic_uns_is_loaded] {
        ic_hex_check_mesh $material proj -1 dim_to_mesh 3
        set tmp_mesh "tmp_hex_surface.uns"
        ic_hex_write_file $tmp_mesh $material proj -1
        ic_load_unstruct $tmp_mesh
    }
    # --> Get the surface in question
    # make this function know about material
    set free_blocked_surfs [ic_hex_block_surfaces_status -status unstructured -material $material]
    set undefined_surfs [ic_hex_block_surfaces_status -status undefined -material $material]
    set surfs_meshed  ""
    
    # --> Mesh with Quad from the existing edge-mesh provided by Hexa
    ic_mess "Meshing surfaces with Quad: $free_blocked_surfs\n"
    foreach surf $free_blocked_surfs {
        if [catch {ic_quad_mesh_surface_from_edge_mesh $surf} res] {
            mess "$res\n" red
        } else {
            lappend surfs_meshed $surf
        }
    }
    # ?maybe do something with the undefined_surfaces? ?fixme?
    return $surfs_meshed
}

# ##########################################################################################

proc ic_hex_cut_plane {args} {
    global hexlib

    return [eval $hexlib cut_plane $args]
}
set dont_record_command(ic_hex_cut_plane) 1

proc ic_hex_reverse_swept_direction {args} {
    global hexlib
    
    return [eval $hexlib reverse_swept_direction $args]
}

proc ic_hex_make_edge_curve_type {args} {
    global hexlib
    
    return [eval $hexlib make_edge_curve_type $args]
}

## Returns edge parameter
## <br>Usage: ic_hex_get_edge_param vertex1 vertex2 parameter
## <p>Argument descriptions:
## <table border>
## <tr><td><b>vertex1</td><td>vertex number at end of edge</td></tr>
## <tr><td><b>vertex2</td><td>vertex number at other end of edge</td></tr>
## <tr><td><b>parameter</td><td>parameter value of edge to return
##      <ul>
##      <li> nodes (number of nodes)
##      <li> len (edge length)
##      <li> law (mesh law)
##      <li> max (max space)
##      <li> sp1a or sp2a (actual spacing 1 or 2)
##      <li> sp2r or sp2r (requested spacing 1 or 2)
##      <li> r1a or r2a (actual ratio 1 or 2)
##      <li> r1r or r2r (requested ratio 1 or 2)
##      </ul></td></tr>
## <tr><td></td></tr>
## </table>

proc ic_hex_get_edge_param {n1 n2 param} {

    if ![ic_hex_blocking_loaded] { return "" }
    set mparams [ic_hex_mesh_params $n1 $n2]
    if {[lindex $mparams 0] == "linear" || [lindex $mparams 0] == "spline"} {
        set islinear 1
    } else {
        set islinear 0
    }
    set ret ""
    if {[lindex $mparams 0] == "linked"} {
        set n1 [lindex [lindex $mparams 1] 0]
        set n2 [lindex [lindex $mparams 1] 1]
        set ret [ic_hex_get_edge_param $n1 $n2 $param]
    } else {
        if $islinear {
            switch -- $param {
                law { set ret [lindex $mparams 0] }
                nodes { set ret [lindex $mparams 1] }
                len { set ret [lindex $mparams 9] }
            }
        } else {
            switch -- $param {
                nodes { set ret [lindex $mparams 0] }
                len { set ret [lindex $mparams 5] }
                law { set ret [lindex $mparams 7] }
                max { set ret [lindex $mparams 8] }
                sp1a { set ret [lindex $mparams 9] }
                sp2a { set ret [lindex $mparams 11] }
                sp1r { set ret [lindex $mparams 1] }
                sp2r { set ret [lindex $mparams 3] }
                r1a { set ret [lindex $mparams 10] }
                r2a { set ret [lindex $mparams 12] }
                r1r { set ret [lindex $mparams 2] }
                r2r { set ret [lindex $mparams 4] }
            }
        }
    }
    return $ret
}
set dont_record_command(ic_hex_get_edge_param) 1

## Returns 1 if edge is linked to another edge, and 0 if not
## Usage: ic_hex_is_edge_linked edge_vertex1 edge_vertex2

proc ic_hex_is_edge_linked {n1 n2} {

    if ![ic_hex_blocking_loaded] { return "" }
    set mparams [ic_hex_mesh_params $n1 $n2]
    set ret ""
    if {[lindex $mparams 0] == "linked"} {
        set n1 [lindex [lindex $mparams 1] 0]
        set n2 [lindex [lindex $mparams 1] 1]
        return "$n1 $n2"
    } else {
        if {[lindex [lindex $mparams 1] 0] == "linked"} {
            lappend ret "h1rel [lrange [lindex $mparams 1] 1 2]"
        }
        if {[lindex [lindex $mparams 3] 0] == "linked"} {
            lappend ret "h2rel [lrange [lindex $mparams 3] 1 2]"
        }
    }
    return $ret
}
set dont_record_command(ic_hex_is_edge_linked) 1

## Match and link edges
## Usage: ic_hex_match_and_link_edges from_edge to_edge
##      from_edge : reference edge
##      to_edge : target edge

proc ic_hex_match_and_link_edges {rn1 rn2 n1 n2} {
    global hexlib
    
    if ![ic_hex_blocking_loaded] return
    set res1 [eval $hexlib match_edges $rn1 $rn2 $n1 $n2]
    if {$rn2 == $n1 || $rn1 == $n1} {
        set end 1
    } else {
        set end 0
    }
    if $end {
        set res [eval $hexlib set_mesh $n1 $n2 h1rel linked $rn1 $rn2]
    } else {
        set res [eval $hexlib set_mesh $n1 $n2 h2rel linked $rn1 $rn2]
    }
    return $res
}

## Copy edge params 
## Usage: ic_hex_copy_edge_params from_edge to_edge absolut no_nodes
##      from_edge : reference edge
##      to_edge : an edge or the value "copy_to_parallel" 
##      absolut : the exact spacing will be copied (default 0)
##      no_nodes : the number of nodes will not be copied (default 0)

proc ic_hex_copy_edge_params {from to {absolut 0} {no_nodes 0}} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set n1 [lindex $from 0]
    set n2 [lindex $from 1]
    set mparams [ic_hex_mesh_params $n1 $n2]
    set lw [lindex $mparams 0]
    if {$lw == "linear" || $lw == "spline" || $lw == "userdefined"} {
        set islinear 1
    } else {
        set islinear 0
    }
    if {[lindex $mparams 0] == "linked"} {
        if {[lindex $mparams 2] == "locked"} {
            set locked "locked"
        } else {
            set locked "unlocked"
        }
        set n5 [lindex [lindex $mparams 1] 0]
        set n6 [lindex [lindex $mparams 1] 1]
        if {$to != "copy_to_parallel"} {
            set parallel ""
            set n3 [lindex $to 0]
            set n4 [lindex $to 1]
        } else {
            set parallel copy_to_parallel
            if $absolut {
                append parallel " no_scale"
            }
        }
        set copy "linked $n5 $n6 $parallel $locked"
    } else {
        if $islinear {
            set nodes_locked ""
            set params_locked 0
            set law [lindex $mparams 0]
            set n "n [lindex $mparams 1]"
            set len [lindex $mparams 9]
            #set stuff "n $n [mesh_law_names $eparam_law] $np $eparam_density $key"
            #set copy "$n $law"
            mess "Copy: mesh law $law from reference edge $n1 $n2 not supported\n" red
            return ""
         } else {
            if {[llength $mparams] < 9} {
                    mess "Expecting >= 9 params from reference edge $n1 $n2\n" red
                    return
            }
            set n "n [lindex $mparams 0]"
            set len [lindex $mparams 5]
            set law [lindex $mparams 7]
            set lmax "lmax [lindex $mparams 8]"
            set sp1 [lindex $mparams 9]
            set sp2 [lindex $mparams 11]
            if {$to != "copy_to_parallel"} {
                if {[lindex [lindex $mparams 1] 0] == "linked"} {
                    if $absolut {
                        set h1rel "h1 linked [lrange [lindex $mparams 1] 1 2]"
                    } else {
                        set h1rel "h1rel linked [lrange [lindex $mparams 1] 1 2]"
                    }
                } else {
                    if $absolut {
                        set h1rel "h1 [lindex $mparams 1]"
                    } else {
                        set h1rel "h1rel [lindex $mparams 1]"
                    }
                }
                if {[lindex [lindex $mparams 3] 0] == "linked"} {
                    if $absolut {
                        set h2rel "h2 linked [lrange [lindex $mparams 3] 1 2]"
                    } else {
                        set h2rel "h2rel linked [lrange [lindex $mparams 3] 1 2]"
                    }
                } else {
                    if $absolut {
                        set h2rel "h2 [lindex $mparams 3]"
                    } else {
                        set h2rel "h2rel [lindex $mparams 3]"
                    }
                }
            } else {
                if {[lindex [lindex $mparams 1] 0] == "linked"} {
                    if $absolut {
                        set h1rel "h1 linked [lrange [lindex $mparams 1] 1 2]"
                    } else {
                        set h1rel "h1rel linked [lrange [lindex $mparams 1] 1 2]"
                    }
                } else {
                    if $absolut {
                        set h1rel "h1 [lindex $mparams 1]"
                    } else {
                        set h1rel "h1rel [lindex $mparams 1]"
                    }
                }
                if {[lindex [lindex $mparams 3] 0] == "linked"} {
                    if $absolut {
                        set h2rel "h2 linked [lrange [lindex $mparams 3] 1 2]"
                    } else {
                        set h2rel "h2rel linked [lrange [lindex $mparams 3] 1 2]"
                    }
                } else {
                    if $absolut {
                        set h2rel "h2 [lindex $mparams 3]"
                    } else {
                        set h2rel "h2rel [lindex $mparams 3]"
                    }
                }
            }
            set r1 "r1 [lindex $mparams 10]"
            set r2 "r2 [lindex $mparams 12]"
            set r1r [lindex $mparams 2]
            set r2r [lindex $mparams 4]
            if [lindex $mparams 6] {
                set locked "locked"
            } else {
                set locked "unlocked"
            }
            if {[lindex $mparams 14] == "n_locked"} {
                set nlocked "nlocked"
            } else {
                set nlocked ""
            }
        }
        if !$islinear {
            if {$to != "copy_to_parallel"} {
                set parallel ""
                set n3 [lindex $to 0]
                set n4 [lindex $to 1]
                set emparams [ic_hex_mesh_params $n3 $n4]
                if {[lindex $emparams 14] == "n_locked"} {
                            mess "Error in copy; nodes locked for target edge: $n3 $n4\n" red
                            return ""
                    } elseif {[lindex $emparams 6] == "1"} {
                            mess "Error in copy; mesh params locked for target edge: $n3 $n4\n" red
                            return ""
                    }
            } else {
                set parallel copy_to_parallel
                if $absolut {
                    append parallel " no_scale"
                }
            }
            if $no_nodes {
                set copy "$h1rel $h2rel $r1 $r2 $lmax $law $parallel $locked $nlocked"
            } else {
                set copy "$n $h1rel $h2rel $r1 $r2 $lmax $law $parallel $locked $nlocked"
            }
        }
    }
    if [info exists copy] {
        if {$to != "copy_to_parallel"} {
            set res [eval $hexlib set_mesh $n3 $n4 $copy]
        } else {
            set res [eval $hexlib set_mesh $n1 $n2 $copy]
        }
        return $res
    }
}

proc ic_hex_reset_edge_mesh {params e1 e2 e3 e4} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set nnodes [lindex $params 0]
    if {$nnodes == "linear" || $nnodes == "spline" || $nnodes == "linked"} return
    set nnodes [expr $nnodes + 1]
    set len1 [lindex [string trimright [ic_hex_mesh_params $e1 $e2] \n] 5]
    set len2 [lindex [string trimright [ic_hex_mesh_params $e3 $e4] \n] 5]
    set len [expr $len1 + $len2]
    set n1 [expr round($nnodes / $len * $len1)]
    set n2 [expr round($nnodes / $len * $len2)]
    if {$n1 < 2} { set n1 2; set n2 [expr $nnodes - 2] }
    if {$n2 < 2} { set n2 2; set n1 [expr $nnodes - 2] }
    if {$n1 < 2} { set n1 2 }
    if {$n2 < 2} { set n2 2 }
    set sp1 [lindex $params 1]
    set sp2 [lindex $params 3]
    set r1 [lindex $params 2]
    set r2 [lindex $params 4]
    set law [lindex $params 7]
    set max [lindex $params 8]
    eval $hexlib set_mesh $e1 $e2 n $n1 h1 $sp1 h2 $sp2 r1 $r1 r2 $r2 lmax $max $law
    eval $hexlib set_mesh $e3 $e4 n $n2 h1 $sp1 h2 $sp2 r1 $r1 r2 $r2 lmax $max $law
}
set dont_record_command(ic_hex_reset_edge_mesh) 1

proc ic_hex_cmd_select_edge {{fams ""} {range ""} {bunching 1} {volume 0} {segment 0} {output 0}} {
    global hexlib
    
    if {$fams == ""} {
        foreach f [join [string trimright [ic_hex_list_block_families] \n]] {
            if {$f == "VORFN"} continue
            append fams "$f "
        }
    }
    if $bunching {
        set selected_bunching selected_bunching
    } else {
        set selected_bunching ""
    }
    if $volume {
        set volume volume
    } else {
        set volume ""
    }
    if $segment {
        set segment edge_segment
    } else {
        set segment ""
    }
    set cmd "select_edge no_highlight all $range max 1 m $fams new_format $selected_bunching $volume $segment"   
    if $output { append cmd " output_blocks" }
    return "[string trimright [eval $hexlib $cmd] \n]"
}

## Check minimum quality ratio 
## Usage: ic_hex_ratio_check_minquality "criterion" [parts to check] [index range] [project_type 2]
## Returns the minimum quality (in case of "Volume change" the maximum quality)

proc ic_hex_ratio_check_minquality {which {fams ""} {range ""} {project_type 2} {full 0}} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    if {$fams == ""} {
        foreach f [join [string trimright [ic_hex_list_block_families] \n]] {
            if {$f == "VORFN"} continue
            append fams "$f "
        }
    }
    if {$range == ""} {
        set res [eval $hexlib ratio_histogram 1 "$fams" proj $project_type minval 0 -no_percent -type \"$which\" maxval 1000 new_format]
    } else {
        set res [eval $hexlib ratio_histogram 1 "$fams" $range proj $project_type minval 0 -no_percent -type \"$which\" maxval 1000 new_format]
    }
    if {"$which" == "Volume change"} {
        if $full {
            return "[lindex $res 1] [lindex $res 0]"
        } else {
            return [lindex $res 1]
        }
    } else {
        if $full {
            return "[lindex $res 0] [lindex $res 1]"
        } else {
            return [lindex $res 0]
        }
    }
}

## Scale mesh size and edge spacing1, spacing2, max space
## Selects automatically all visible edges
## <br>Usage: ic_hex_scale_mesh_size_with_spacings_gui scale_factor [parts] [index range] [use_output_blocks 0]
## Note: the function runs only in gui mode, not in batch mode

proc ic_hex_scale_mesh_size_with_spacings_gui {scale {fams ""} {range ""} {use_output_blocks 0}} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    eval $hexlib scale_mesh_size $scale
    set scale2 [expr 1.0 / $scale]
    if {$fams == ""} {
        foreach f [join [string trimright [ic_hex_list_block_families] \n]] {
            if {$f == "VORFN"} continue
            append fams "$f "
        }
    }
    set cmd "select_edge no_highlight all $range max 1 m $fams new_format volume"
    if $use_output_blocks { append cmd " output_blocks" }
    set edges [string trimright [eval $hexlib $cmd] \n]
    foreach e $edges {
        set e1 [lindex $e 0]; set e2 [lindex $e 1]
        set p [string trimright [ic_hex_mesh_params $e1 $e2] \n]
        if {[lindex $p 0] == "linked"} continue
        if {[lindex [lindex $p 1] 0] == "linked" && [lindex [lindex $p 3] 0] == "linked"} continue
        catch { unset sp1; unset sp2; unset max }
        if {[lindex [lindex $p 1] 0] != "linked"} { set sp1 [lindex $p 1] }
        if {[lindex [lindex $p 3] 0] != "linked"} { set sp2 [lindex $p 3] }
        if {![info exists sp1] && ![info exists sp2]} continue
        set max [lindex $p 8]
        if [info exists sp1] { set h1 [expr $sp1 * $scale2] }
        if [info exists sp2] { set h2 [expr $sp2 * $scale2] }
        if [info exists max] { set max [expr $max * $scale2] }
        if {[info exists sp1] && [info exists sp2]} { eval $hexlib set_mesh $e1 $e2 h1 $h1 h2 $h2 lmax $max; continue }
        if [info exists sp1] { eval $hexlib set_mesh $e1 $e2 h1 $h1 lmax $max; continue }
        if [info exists sp2] { eval $hexlib set_mesh $e1 $e2 h2 $h2 lmax $max }
    }
}

## Scale mesh size and edge spacing1, spacing2, max space
## <br>Usage: ic_hex_scale_mesh_size_with_spacings scale_factor edges_to_scale
## Note: the function runs in both modes (gui mode and batch mode)

proc ic_hex_scale_mesh_size_with_spacings {scale edges} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    eval $hexlib scale_mesh_size $scale
    set scale2 [expr 1.0 / $scale]
    foreach e $edges {
        set e1 [lindex $e 0]; set e2 [lindex $e 1]
        set p [string trimright [ic_hex_mesh_params $e1 $e2] \n]
        if {[lindex $p 0] == "linked"} continue
        if {[lindex [lindex $p 1] 0] == "linked" && [lindex [lindex $p 3] 0] == "linked"} continue
        catch { unset sp1; unset sp2; unset max }
        if {[lindex [lindex $p 1] 0] != "linked"} { set sp1 [lindex $p 1] }
        if {[lindex [lindex $p 3] 0] != "linked"} { set sp2 [lindex $p 3] }
        if {![info exists sp1] && ![info exists sp2]} continue
        set max [lindex $p 8]
        if [info exists sp1] { set h1 [expr $sp1 * $scale2] }
        if [info exists sp2] { set h2 [expr $sp2 * $scale2] }
        if [info exists max] { set max [expr $max * $scale2] }
        if {[info exists sp1] && [info exists sp2]} { eval $hexlib set_mesh $e1 $e2 h1 $h1 h2 $h2 lmax $max; continue }
        if [info exists sp1] { eval $hexlib set_mesh $e1 $e2 h1 $h1 lmax $max; continue }
        if [info exists sp2] { eval $hexlib set_mesh $e1 $e2 h2 $h2 lmax $max }
    }
}

## Returns the number of edge segments 
## <br>Usage: ic_hex_get_edge_segment_number edge_vertex1 edge_vertex2

proc ic_hex_get_edge_segment_number {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    if [catch {eval $hexlib get_edge_segment_number $args} res] {
        set res -1
    } else {
        if [string is integer $res] {
            set res [expr $res + 1]
        } else {
            set res -1
        }
    }
    return $res
}
set dont_record_command(ic_hex_get_edge_segment_number) 1

## Returns also the hidden nodes (if any) of an edge
## <br>Usage: ic_hex_get_hidden_nodes edge_vertex1 edge_vertex2

proc ic_hex_get_hidden_nodes {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    if [catch {eval $hexlib get_edge_segment_number $args hidden} res] {
        set res -1
    }
    return $res
}
set dont_record_command(ic_hex_get_hidden_nodes) 1

proc ic_hex_get_edge_curve_type {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    if [catch {eval $hexlib get_edge_curve_type $args} res] {
        set res -1
    }
    return $res
}
set dont_record_command(ic_hex_get_edge_curve_type) 1

## Sets the method of mesh for unstructured 2D blocks
## <br>Usage: ic_hex_unstruct_face_method method
## <br><b>Method</b> can be <b>uniform_quad</b>, <b>gambit_pave</b>, <b>auto</b>

proc ic_hex_set_unstruct_face_method {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib set_unstruct_face_method $args]
    return $res
}

## turn the ogrid_smooth_transition option on or off
## <br>Usage: ic_hex_ogrid_smooth_transition [on/off]
## <br>returns 0 (off) or 1 (on): set state [ic_hex_ogrid_smooth_transition]

proc ic_hex_ogrid_smooth_transition {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib ogrid_smooth_transition $args]
    return $res
}

## turn the project-to_topo option on or off
## <br>Usage: ic_hex_project_to_topo [on/off]
## <br>returns 0 (off) or 1 (on): set state [ic_hex_project_to_topo]
proc ic_hex_project_to_topo {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib project_to_topo $args]
    return $res
}

proc ic_hex_move_lcs_lcs {from to top_current move_how subset} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set nfrom [llength $from]
    set nto [llength $to]
    if {($nfrom != 1 && $nfrom != 3) || ($nto != 1 && $nto != 3)} {
        mess "Error: LCS -> LCS incorrect data\n" red
        return
    }
    
    set was_csys [ic_csystem_get_current]
    ic_csystem_set_current global
    
    if {$nfrom == 1} {
        if {[ic_csystem_get $from] == ""} {
            mess "Error: not defined LCS \"from\"\n" red
            ic_csystem_set_current $was_csys
            return
        }
        set p00 [ic_coords_into_global "0 0 0" $from]
        set p01 [ic_coords_into_global "1 0 0" $from]
        set p02 [ic_coords_into_global "0 1 0" $from]
    } else {
        foreach "p00 p01 p02" $from ""

    }
    if {$nto == 1} {
        if {[ic_csystem_get $to] == ""} {
            mess "Error: not defined LCS \"to\"\n" red
            ic_csystem_set_current $was_csys
            return
        }
        set p10 [ic_coords_into_global "0 0 0" $to]
        set p11 [ic_coords_into_global "1 0 0" $to]
        set p12 [ic_coords_into_global "0 1 0" $to]
    } else {
        foreach "p10 p11 p12" $to ""
    }

    # first move to origin, then rotate, finally move to target
    set translate1 [ic_vcalc diff $p00 {0 0 0}]
    set translate2 $p10
    set p01 [ic_vcalc diff $p00 $p01]
    set p02 [ic_vcalc diff $p00 $p02]
    set p00 "0 0 0"
    set p11 [ic_vcalc diff $p10 $p11]
    set p12 [ic_vcalc diff $p10 $p12]
    set p10 "0 0 0"

    set vecx1 [ic_vcalc dir $p00 $p01]
    set vecx2 [ic_vcalc dir $p10 $p11]
    set vecy1 [ic_vcalc dir $p00 $p02]
    set vecy2 [ic_vcalc dir $p10 $p12]
    set v [ic_vcalc product $vecx1 $vecy1]
    set vv [ic_vcalc product $vecx2 $vecy2]
    if {$v == "" || $vv == ""} {
        ic_mess "Error: data error in ic_hex_move_lcs_lcs\n" red
        ic_csystem_set_current $was_csys
        return
    }
    
    set axs1 [ic_vcalc product $vecx2 $vecx1]
    if {$axs1 == "0 0 0"} {
        set axs1 [ic_vcalc vec_norm $vecx1]
    }
    set ang1 [ic_vcalc angle_normal $axs1 $vecx1 $vecx2]
    set xyz [ic_vcalc sum $p10 $vecy1]
    ic_delete_geometry point names tmp_pnt 0
    ic_geo_cre_pnt TMP tmp_pnt $xyz
    if {$ang1 != 0 && $ang1 != ""} {
        ic_move_geometry point names tmp_pnt rotate $ang1 cent $p10 rotate_axis $axs1
    }
    set xyz [ic_geo_get_point_location tmp_pnt]
    set vecx [ic_vcalc dir $p10 $xyz]
    set ang2 [ic_vcalc angle_normal $vecx2 $vecx $vecy2]
    ic_delete_geometry point names tmp_pnt 0
    switch $move_how {
        copy {
            eval "ic_hex_copy_blocking $top_current __temp__ m $subset"
            eval "ic_hex_transform_blocking __temp__ translate $translate1"
            if {$ang1 != 0 && $ang1 != ""} {
                eval "ic_hex_transform_blocking __temp__ rotate $p10 $axs1 $ang1"
            }
            if {$ang2 != 0 && $ang2 != ""} {
                eval "ic_hex_transform_blocking __temp__ rotate $p10 $vecx2 $ang2"
            }
            eval "ic_hex_transform_blocking __temp__ translate $translate2"
            eval "ic_hex_merge_blocking $top_current __temp__ -remove_unused_grid_lines -separate_classes -version 110"
            eval ic_hex_delete_blocking __temp__
        }
        move {
            eval "ic_hex_transform_blocking $top_current translate $translate1 m $subset"
            if {$ang1 != 0 && $ang1 != ""} {
                eval "ic_hex_transform_blocking $top_current rotate $p10 $axs1 $ang1 m $subset"
            }
            if {$ang2 != 0 && $ang2 != ""} {
                eval "ic_hex_transform_blocking $top_current rotate $p10 $vecx2 $ang2 m $subset"
            }
            eval "ic_hex_transform_blocking $top_current translate $translate2 m $subset"
        }
    }
    ic_csystem_set_current $was_csys
}

## Returns the nearest geometry point to a vertex position
## <br> Usage: ic_hex_get_nearest_existing_point vertex_num

proc ic_hex_get_nearest_existing_point {vertex {part ""}} {
    
    if {![ic_geo_is_loaded] || ![ic_hex_is_loaded]} { return "" }
    return [ic_geo_get_nearest_existing_point [ic_hex_get_node_location $vertex] $part]
}
set dont_record_command(ic_hex_get_nearest_existing_point) 1

proc ic_hex_get_hexlib {} {
    global hexlib

    if {[info exists hexlib] && $hexlib != ""} {
        return $hexlib
    }
    return ""
}
set dont_record_command(ic_hex_get_hexlib) 1

proc ic_hex_sketch_create_blocking_without_geometry {what {tol 0.01} {part SOLID}} {
    global hexlib batch_mode
    
    ic_geo_new_family $part 0
    ic_boco_set_part_color $part
    ic_empty_tetin
    ic_set_global geo_cad 0 toptol_userset
    ic_set_global geo_cad $tol toler
    set res ""
    
    switch $what {
        2DPlanar {
            ic_point {} $part pnt.00 0,1,0.0
            ic_point {} $part pnt.01 1,1,0.0
            ic_point {} $part pnt.02 0,0,0.0
            ic_point {} $part pnt.03 1,0,0.0
            ic_curve point $part crv.00 {pnt.02 pnt.03}
            ic_curve point $part crv.01 {pnt.00 pnt.02}
            ic_curve point $part crv.02 {pnt.01 pnt.03}
            ic_curve point $part crv.03 {pnt.00 pnt.01}
            ic_surface 2-4crvs $part srf.00 {0.001 {crv.00 crv.01 crv.03 crv.02}}
            ic_hex_ensure_is_loaded
            set res [eval $hexlib initialize_mesh 2d new_numbering new_blocking $part]
            ic_hex_sketch_unset_projections
        }
    }
    
    foreach type "point curve surface" {
        ic_delete_geometry $type names [ic_geo_get_objects $type]
    }
    if !$batch_mode {
        aie_after_blocking_loaded
    }
    return $res
}

proc ic_hex_sketch_set_projections {what part} {
    global batch_mode

    ic_hex_undo_major_start set_projections
    set dim [format %d [ic_hex_mesh_dimension]]
    set numbers [eval ic_hex_select_super_faces "all max 1 [join [ic_hex_list_block_families_without]]"]
    foreach "n" $numbers {
        set n1 [lindex $n 0]
        set n2 [lindex $n 1]
        set n3 [lindex $n 2]
        set n4 [lindex $n 3]
        switch $what {
            Part {
                ic_hex_project_face node_numbers " $n1 $n2 $n3 $n4 " $part
            }
       }
   }
   ic_hex_undo_major_end set_projections
   if !$batch_mode { aie_after_blocking_loaded }
}

proc ic_hex_sketch_unset_projections {{what "vertex edge face"}} {
    global batch_mode
    
    ic_hex_undo_major_start sketch_unset_projections
    foreach type $what {
        if {$type == "vertex"} {
            set numbers [eval ic_hex_select_nodes "1 all m [join [ic_hex_list_block_families_without]] node_numbers"]
            foreach n $numbers {
                ic_hex_set_node_projection $n to_none
            }
        } elseif {$type == "edge"} {
            set numbers [eval ic_hex_select_edge "no_highlight all max 1 m [join [ic_hex_list_block_families_without]] new_format selected_bunching volume"]
            foreach "n" $numbers {
                set n1 [lindex $n 0]
                set n2 [lindex $n 1]
                ic_hex_set_edge_projection $n1 $n2 -1 3 0 
            }
        } elseif {$type == "face"} {
            set numbers [eval ic_hex_select_super_faces "all max 1 [join [ic_hex_list_block_families_without]]"]
            foreach "n" $numbers {
                set n1 [lindex $n 0]
                set n2 [lindex $n 1]
                set n3 [lindex $n 2]
                set n4 [lindex $n 3]
                ic_hex_unproject_face node_numbers " $n1 $n2 $n3 $n4 "
            }
        }
    }
    ic_hex_undo_major_end sketch_unset_projections
    if !$batch_mode { aie_after_blocking_loaded }
}

proc ic_mesh2block {} {
    ic_save_unstruct __temp.uns  1 "" "" "" "" 0 1
    ic_run_application_exec . icemcfd mesh2block {-s __temp.uns __temp.blk}
    file delete __temp.uns
    ic_hex_restore_blocking __temp.blk
    file delete __temp.blk
}

## Computes the bunching on the blocking edges according to the TGLib Size Function Background Grid (needs to be accessible)
## <br>Usage: ic_hex_compute_curvature_asf -asf_mesh_file fname -do_proximity -skip_edges_in_sweep_dir -skip_dims d1 d2 d3 ..
## <br>Ex: eval ic_hex_compute_curvature_asf -asf_mesh_file ./asf_mesh.uns -do_proximity -skip_dims 0 4 6
## <p>Argument Descriptions:
## <table border>
## <tr><td><b>-asf_mesh_file</td><td>Full path to a an unstructured mesh file that stores the edge bunching based on size functions.</td></tr>
## </table>
## <br>Optional arguments:
## <table border>
## <tr><td><b>-do_proximity</td><td>Evaluate the also the proximity size functions.</td></tr>
## <tr><td><b>-skip_edges_in_sweep_dir</td><td>Do not compute the size function based bunching in sweep direction.</td></tr>
## <tr><td><b>-skip_dims</td><td>List of integer Hexa blocking dimensions in which direction the size function should not be evaluated.</td></tr>
## </table>
proc ic_hex_compute_curvature_asf {args} {
    global hexlib

    if {$args == ""} { return "" }
    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib compute_curvature_asf $args]
    return $res
}

proc ic_hex_imprint_face3d {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib imprint_face3d $args]
    return $res
}

proc ic_hex_match_swept_levels3d {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib match_swept_levels3d $args]
    return $res
}

proc ic_hex_split_ublock_connect_faces {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib split_ublock_connect_faces $args]
    return $res
}

proc ic_hex_set_default_ublock_mesh_type {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib set_default_ublock_mesh_type $args]
    return $res
}

## Returns the number of blocks 
## <br> Usage: ic_hex_count_blocks block_type <vorfn> <output_blocks>
## <br> <b>block_type</b> can be <b>free</b>, <b>mapped</b>, <b>swept</b>
## <br> set <b>vorfn</b> to 1 to count also blocks in part VORFN

proc ic_hex_count_blocks {type {orfn 0}} {

    if ![ic_hex_blocking_loaded] { return 0 }
    
    set count 0
    set cmd "ic_hex_get_block_families_and_types"
    if !$orfn {
        append cmd " [string trimright [ic_hex_list_block_families_without] \n]"
    } else {
        append cmd " [string trimright [ic_hex_list_block_families_without ""] \n]"
    }
    set blks [eval $cmd]
    set count [llength [lsearch -all $blks "*${type}*"]]
    return $count
}
set dont_record_command(ic_hex_count_blocks) 1

proc ic_hex_select_all_free_faces {} {
    
    if ![ic_hex_blocking_loaded] { return "" }
	set face [eval ic_hex_display_super_faces "[ic_hex_list_block_families_without] ublock_free_faces"]
    return [string trimright $face \n]
}

## Returns the number of free faces (in 3D) and the number of free blocks (in 2D) 
## <br>Usage: ic_hex_number_all_free_faces

proc ic_hex_number_all_free_faces {} {
    
    if ![ic_hex_blocking_loaded] { return "" }
    if {[format %d [ic_hex_mesh_dimension]] == 3} {
	    set len [llength [ic_hex_select_all_free_faces]]
	} else {
	    set len [ic_hex_count_blocks free]
	}
    return $len
}
set dont_record_command(ic_hex_number_all_free_faces) 1

## Split a free block by boundary edges  
## <br>Usage: ic_hex_split_unstruct_block3d_by_edge_loops ublock_num sheet_num

proc ic_hex_split_unstruct_block3d_by_edge_loops {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib split_unstruct_block3d_by_edge_loops $args]
    return $res
}

proc ic_hex_split_block3d_absolute {edge num_splits} {
    global batch_mode
    
    if ![ic_hex_blocking_loaded] return
    set v1 [lindex $edge 0]
    set v2 [lindex $edge 1]
    set mparams [ic_hex_mesh_params $v1 $v2]
    if {[lindex $mparams 0] == "linked"} {
        set n1 [lindex [lindex $mparams 1] 0]
        set n2 [lindex [lindex $mparams 1] 1]
        set mparams [ic_hex_mesh_params $n1 $n2]
        set len [lindex $mparams 5]
    } elseif {[lindex $mparams 0] == "linear" || [lindex $mparams 0] == "spline"} {
        set len [lindex $mparams 7]
    } else {
        set len [lindex $mparams 5]
    }
    set abs [expr $len * 1.0 / [expr $num_splits + 1.0] * 1.0]
    if !$batch_mode { set ta [tdv_active 0] }
    ic_undo_suspend
    set fams [string trimright [ic_hex_list_block_families_without] \n]
    for {set i 0} {$i < $num_splits} {incr i} {
        set ijk1 [string trimright [ic_hex_vertex_ijk $v1] \n]  
        set ve1 [ic_hex_get_vertex_edges $v1]
        eval ic_hex_split_grid $v1 $v2 abs:$abs m $fams
        set ve1a [ic_hex_get_vertex_edges $v1]
        foreach n1 $ve1 {
            set nitem [lsearch $ve1a $n1]
            if {$nitem > -1} {
                set ve1a [lreplace $ve1a $nitem $nitem]
            }
        }
        if {[lindex [lindex $ve1a 0] 0] == $v1} {
            set v1 [lindex [lindex $ve1a 0] 1]
        } elseif {[lindex [lindex $ve1a 0] 1] == $v1} {
            set v1 [lindex [lindex $ve1a 0] 0]
        }
    }
    ic_undo_resume
    if !$batch_mode { tdv_active $ta }
}

## Convert a free block free face to mapped from four corner vertices
## <br>Usage: ic_hex_convert_to_struct_from_nodes -face free_face -v_end "four_corner_vertices"
## Note: use this function if the the selected free face has more than four vertices 

proc ic_hex_convert_to_struct_from_nodes {args} {
    global hexlib

    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib convert_to_struct_from_nodes $args]
    return $res
}

proc ic_hex_read_blocking_mesh {args} {
    global hexlib

    set res [eval $hexlib read_blocking_mesh $args]
    return $res
}

proc ic_hex_write_blocking_mesh {args} {
    global hexlib

    set res [eval $hexlib write_blocking_mesh $args]
    return $res
}

## When working with superblocks (blocks that have been merged) some edges have hidden vertices that are used internally in scripting.
## Returns edge vertices used to define the edge in scripting commands given the visible vertices as input.
## Note, if there are no hidden vertices, the result will be the same as the input
## For example: For an edge with corners 10 and 20, with hidden vertex of 15, "ic_hex_get_edge_to_apply 10 20" would return "10 15"
## If there are no hidden vertices in the case above it would return "10 20"
## <br>Usage: ic_hex_get_edge_to_apply start_edge_vertex end_edge_vertex

proc ic_hex_get_edge_to_apply {n1 n2} {

    set verts "$n1 $n2"
    if {[string trimright [ic_hex_get_hidden_nodes $n1 $n2] \n] == "invalid edge"} {
        foreach e [ic_hex_get_vertex_edges $n1] {
            set hidden [string trimright [ic_hex_get_hidden_nodes [lindex $e 0] [lindex $e 1]] \n]
            if {[lindex $hidden end] == "$n2"} {
                set verts "$n1 [lindex $hidden 1]"
                break
            }
        }
    }
    return $verts
}
set dont_record_command(ic_hex_get_edge_to_apply) 1

proc ic_hex_reset_unstruct_node_locs {args} {
    global hexlib
    
    if ![ic_hex_blocking_loaded] return
    set res [eval $hexlib reset_unstruct_node_locs]
    return $res
}
set dont_record_command(ic_hex_reset_unstruct_node_locs) 1


proc ic_hex_block_transfer {how use_output_blocks blocks} {
    global hexlib
    
    set res [eval $hexlib "mark_blocks unmark" ]
	
    switch $how {
	sel {
	    foreach n $blocks {
		set cmd "mark_blocks superblock $n"
		if $use_output_blocks {
			append cmd " output_blocks"
		}
		set res [eval $hexlib $cmd]
	    }
	}
    }
    set res [eval $hexlib "transfer_blocks" ]
    set res [eval $hexlib "mark_blocks unmark" ]
}

proc ic_hex_set_out_of_date {args} {
    global hexlib
    
    set res [eval $hexlib set_out_of_date $args]
    return $res
}
set dont_record_command(ic_hex_set_out_of_date) 1

proc ic_hex_set_dim_to_project {args} {
    global hexlib
    
    set res [eval $hexlib set_dim_to_project $args]
    return $res
}
set dont_record_command(ic_hex_set_dim_to_project) 1

