
# This code creates the user interface for the hexa mesher.
#
# Copyright (c) 1993 - 1995 Pacific Marketing and Consulting, Inc,
#       and ICEM Systems, GmbH.  All rights reserved.
# Author:  Wayne A. Christopher, wayne@icemcfd.com

proc select_node {mess {num 1} {opts ""}} {
    global last_line display_flag
    
    focus .v
    banner $mess
    
    if { $num == "unlimited" } {
	set rnum 100
    } else {
        if { [scan $num "%d" temp ] != 1 } {
	    mess "num is not a number\n"
	    return ""
        }
	set rnum $num
    }
    set cmd \
	"select_nodes $rnum [range_string] m [volume_activename_string] $opts"
    
    if !$display_flag(edge_vol) { append cmd " surface" }

    
    if ![command $cmd 1 1] {
	set last_line ""
    }
    banner ""
    
    return $last_line
}

proc select_node_text {mess num text} {
    global last_line display_flag
    
    focus .v
    banner $mess
    
    set cmd "select_nodes $num [range_string] m [volume_activename_string]"
    if !$display_flag(edge_vol) { append cmd " surface" }
    append cmd " text $text"
    
    if ![command $cmd 1 1] {
	set last_line ""
    }
    banner ""
    
    return $last_line
}

proc select_curve_parameter {mess} {
    global last_line display_flag
    
    focus .v
    banner $mess
    
    if ![command "select_curve parameter 1" 1 1] {
	set last_line ""
    }
    
# reset
    
    banner ""
    
    return $last_line
}
proc select_point {mess} {
    global last_line display_flag
    
    focus .v
    banner $mess
    
    set pp $display_flag(point)
    set display_flag(point) 1
    if ![command "select_point [point_activename_string]" 1 1] {
	set last_line ""
    }
    
    # reset
    
    set display_flag(point) $pp
    banner ""
    
    return $last_line
}

proc select_edge {mess {max_sel 1} {opts ""}} {
    global last_line display_flag use_output_blocks

    if $display_flag(edge_vol)     { append opts " volume" }
    if $use_output_blocks          { append opts " output_blocks" }
    if $display_flag(edge_proj)    { append opts " proj" }
    if $display_flag(edge_counts)  { append opts " counts" }
    if $display_flag(edge_bunch)   { append opts " bunching" }
    if $display_flag(edge_nodes)   { append opts " nodes" }
    if $display_flag(edge_proj)    { append opts " proj" }
    if $display_flag(edge_mset)    { append opts " highlight_set" }
    if $display_flag(use_blanking) { append opts " -not_blanked" }
    if $display_flag(attached_faces) { append opts " -faces" }
    
    focus .v
    banner $mess
    set cmd "select_edge [range_string] max $max_sel m \
	     [volume_activename_string] $opts"
    if ![command $cmd 1 1] {
	set last_line ""
    }
    banner ""
    
    if {$last_line == ""} { return "" }
    
    if {$max_sel == 1} {
	set edge [lindex $last_line 0]
	
	set vert [lindex $edge 0]
	set dim [lindex $edge 1]
	
	if {$dim < 3} {
	    set ind [lindex $vert $dim]
	} else {
	    set ind 0
	    foreach i $vert {
		if {[scan $i "%d:%d" ndim nind] == 2} {
		    if {$ndim == $dim} {
			set ind $nind
			break
		    }
		}
	    }
	}
	return [list $vert $dim $ind]
    } else {
	return $last_line
    }
}

proc select_surface {mess} {
    global last_line display_flag
    
    if !$display_flag(surf) { set display_flag(surf) 1; update_display surf }

    focus .v
    banner $mess
    if ![command "select_surface" 1 1] {
	set last_line ""
    }
    banner ""
    
    return $last_line
}

proc select_curve {mess} {
    global last_line display_flag
    
    if !$display_flag(curve) {
	set display_flag(curve) 1; update_display curve
    }
    
    focus .v
    banner $mess
    if ![command "select_curve 1" 1 1] {
	set last_line ""
    }
    banner ""
    
    return $last_line
}

# -------------------

proc block_mark_families {vol_var { face_var "" }  { del_opts "" } } {
    global $vol_var family_name
    
    command "mark_blocks unmark" 0
# process volume families
    set ff ""
    if { 0 }  {
	set ff $family_name([set $vol_var])
    } else {
	set ff ""
	foreach f [array names $vol_var] {
	    if [set ${vol_var}($f)] { lappend ff $family_name($f) }
	}
    }
    if {$ff != ""} {
	command "mark_blocks $ff" 0
    }
# process surface families
    if { $face_var != "" } {
	global $face_var 
        foreach f [ array names $face_var ] {
	    if [ set ${face_var}($f) ] { 
		command "mark_blocks on_family $family_name($f)"
	    }
        }
    }
    command "del -solid marked $del_opts" 0
}

proc surface_mark_families {var {one 0}} {
    global $var family_name
    
    set ff ""
    if $one {
	set val [ set $var ]
	if { $val != "" } {
		set ff $family_name($val)
	}
    } else {
	set ff ""
	foreach f [array names $var] {
	    if [set ${var}($f)] { lappend ff $family_name($f) }
	}
    }
    if {$ff != ""} {
	command "display_surfaces simpler -solid $ff" 0
    } else {
	command "erase_surfaces" 0
    }
}

# -----------------------

proc block_unmark {} {
    command "mark_blocks unmark" 0
    update_display edge face block
}

proc block_mark {on face {del_opts ""}} {
    global enable_exec last_line
    global button_instructions
    
    if !$enable_exec {
	mess "Please complete the operation on the screen first.\n" red
	return 0
    }
    
    if { $face == 4 } {
	command "select_super_face node_numbers [volume_activename_string]" 0
	if { $last_line == "" } { return 0 }
	foreach f $last_line {
	    if { [ lindex $f 3 ] == "u" } {
# unstructured interface.
		set bnums "[ lindex $f 0 ] [ lindex $f 2 ]"
		foreach i $bnums {
			set cmd "mark_blocks superblock $i"
			if !$on  { append cmd " unmark" }
			command $cmd 0
		}
	    } else {
		set first [ lindex $f 0 ]
		set second [ lindex $f 3 ]
		set cmd "mark_blocks numbers $first $second face_neighbors"
		if !$on  { append cmd " unmark" }
		command $cmd 0
	    }
	}
    } else {
        set first ""
        set second ""
        if {$face == 3} {
	    set first [select_node "Please select the vertex \
			    $button_instructions" 2 node_numbers ]
	    if {$first == ""} { return 0 }
	    set second $first
        } else {
	    set nns [select_node "Please select the two vertices  \
		    $button_instructions" 3 node_numbers ]
	    set first [lindex $nns 0]
	    set second [lindex $nns 1]
	    if {($first == "") || ($second == "")} { return 0 }
        }
        set cmd "mark_blocks numbers $first $second"
        if !$on  { append cmd " unmark" }
        switch $face {
	    1 { append cmd " face_neighbors" }
	    2 { append cmd " edge_neighbors" }
	    3 { append cmd " vertex_neighbors" }
        }
        
        command $cmd 0
    }
    command "del marked -solid $del_opts" 0
    return 1
}

proc block_mark_fams {on face {del_opts ""}} {
    set ff [select_some_volume_families]
    if {$ff == ""} return
    
    set cmd "mark_blocks $ff [range_string]"
    if !$on  { append cmd " unmark" }
    switch $face {
	1 { append cmd " face_neighbors" }
	2 { append cmd " edge_neighbors" }
	3 { append cmd " vertex_neighbors" }
    }
    
    command $cmd 0
    command "del marked -solid $del_opts" 0 
}

proc block_mark_all { on mess {del_opts {}} } {
	set cmd "mark_blocks  [volume_activename_string] [range_string]"
	if { $on == 0 } {
		lappend cmd "unmark"
	}
	command $cmd
	command "del marked -solid $del_opts" 0
}
proc block_mark_super {on isedge mess del_opts} {
    global last_line use_output_blocks display_flag
    global enable_exec
    global button_instructions
    
    if !$enable_exec {
	mess "Please complete the operation on the screen first.\n" red
	return 0
    }
    
    set mess [string tolower $mess]
    banner "Please select the blocks $mess $button_instructions"
    
    set cmd "select_blocks 1000 [range_string] m [volume_activename_string]"
    if $use_output_blocks           { append cmd " output_blocks" }
    if {$isedge && $display_flag(edge_mset)} { append cmd " highlight_set" }
    
    command $cmd
    set blocks $last_line
    
    banner ""
    
    foreach n $blocks {
	if $on {
		set cmd "mark_blocks superblock $n"
	} else {
		set cmd "mark_blocks unmark superblock $n"
	}
	if $use_output_blocks {
		append cmd " output_blocks"
	}
	command $cmd 0
    }
    command "del marked -solid $del_opts" 0
    return [llength $blocks]
}

proc block_mark_numbers {on mess {del_opts {}}} {
    global select_block_numbers display_flag
    
#    set bnums_save $display_flag(block_numbers)
#    if { $bnums_save == 0 } {
## turn on block_numbers
#	set display_flag(block_numbers) 1
#	update_display block
#    }
    set nb [get_hexa_nsuperblocks]
    for {set i 1} {$i <= $nb} {incr i} {
	set select_block_numbers($i) 0
    }
#
# highlight selected blocks so far -- need command to add to del
# of form 
# command "del marked ... "
#
    set r [form_block_numbers select_block_numbers 0 $mess]
    
    if $r {
	for {set i 1} {$i <= $nb} {incr i} {
	    if $select_block_numbers($i) {
		if $on {
		    command "mark_blocks superblock $i" 0
		} else {
		    command "mark_blocks unmark superblock $i" 0
		}
	    }
	}
    }
    command "del marked -solid $del_opts" 0
#    if { $bnums_save == 0 } {
## turn block numbers back off
#	set $display_flag(block_numbers) 0
#	update_display block
#    }
	
     return $r
}

proc select_material {mess} {
    global families family_name family_dims last_line family_active
    
    set appvols [volume_name_string]
    set vols ""
    foreach f $appvols {
	lappend vols $f
    }
    
    set mat [choose_one $mess $vols "" upright]
    if {$mat == ""} { return "" }
    
    if { [ string index $mat 0 ] == "$" } {
	return $mat
    }
    foreach f $families {
	if {($family_dims($f) == 3) && ($mat == $family_name($f))} {
	    return $mat
	}
    }
    define_family $mat
    return $mat
}
proc define_family { mat } {
# create a new volume family
    global last_line family_name  family_dims family_active

    command "define_family $mat"
    if { [ scan $last_line "%d" f ] != 1 } {
        tk_dialog .err "Error" "Error defining family \"$mat\"" "" 0 Ok
    }
    lappend families $f
    mess "new families: $families\n"
    set family_name($f) $mat
    set family_dims($f) 3
    set family_active($f) 1
    add_families
}

# --------------------------

# Not really selection-oriented things....

proc get_families {} {
    global all_lines families family_dims family_active family_name
    
    command "list_families dims"
    catch {unset family_dims}
    catch {unset family_active}
    set families "-1 0"
    set family_name(-1) VORFN
    set family_dims(-1) 3
    set family_active(-1) 0
    set family_name(0) ORFN
    set family_dims(0) 2
    set family_active(0) 1
    set i 1
    foreach line $all_lines {
	if {$line == ""} continue
	set f [lindex $line 0]
	set d [lindex $line 1]
	if {$f != "__PARAMS__"} {
	    lappend families $i
	}
	set family_dims($i) $d
	set family_name($i) $f
	set family_active($i) 1
	incr i
    }
}

proc reset_families {} {
    global families family_active
    
    foreach f $families {
	set family_active($f) 1
    }
    set family_active(0) 0
    set family_active(-1) 0
}

# reset 0 don't change index_min or index_max
# reset 1 set index_min to 0  and index_max to index_max_limit
# reset 2 obsolete
# reset 3 increment changed indices only
proc get_indices {reset} {
    global last_line index_min index_max index_min_limit index_max_limit

    
    if [info exists index_max_limit] {
	foreach i [array names index_max_limit] {
	    set old_limits($i) $index_max_limit($i)
	}
    }
    catch {unset index_min_limit}
    catch {unset index_max_limit}
    
    set should_update 0
    
    command "ijk_max"
    set i 0
    set nnew 0
    if { $reset == 3 } {
	set reset 0
	set reset_changed 1
    } elseif { $reset } {
	set reset_changed 1
    } else {
	set reset_changed 0
    }
	
    foreach m $last_line {
	if {[scan $m %d:%d dim val] != 2} {
	    set dim $i
	    set val $m
	}
	if {($dim > 2) && ![info exists index_min($dim)]} { incr nnew }
	
	if {$reset || ![info exists index_min($dim)] || \
		($index_min($dim) == "")} {
	    set index_min($dim) 0
	}
	set index_min_limit($dim) 0
	if {$reset || ![info exists index_max($dim)] || \
		($index_max($dim) == "")} {
	    set index_max($dim) $val
	} 
	if { $reset_changed && [info exists old_limits($dim)] && \
		($old_limits($dim) < $val)} {
# in this dimension the range has increased.
	    set index_max($dim) $val
	    set should_update 1
	}
	set index_max_limit($dim) $val
	set index_min_limit($dim) 0
	
	if {$index_max($dim) > $index_max_limit($dim)} {
	    set index_max($dim)  $index_max_limit($dim)
	}
	if {$index_min($dim) > $index_max_limit($dim)} {
	    set index_min($dim) $index_max_limit($dim)
	}
	
	if {$reset == 2} {
	    incr index_min($dim)
	    incr index_max($dim) -1
	}
	incr i
    }
    if {$nnew == 1} {
	mess "1 new O-grid index defined\n"
    } elseif {$nnew > 1} {
	mess "$nnew new O-grid indices defined\n"
    }
    
    foreach i [array names index_min] {
	if ![info exists index_min_limit($i)] { unset index_min($i) }
    }
    foreach i [array names index_max] {
	if ![info exists index_max_limit($i)] { unset index_max($i) }
    }
    
    # Maybe not always needed but can't hurt too much.
    setup_index_box
    if $should_update {
	update_display edge face block vert
	scan_reset
    }
    readjust_edit_geometry
}

proc select_some_volume_families {} {
    global select_some_families
    global family_active family_dims families family_name
    
    set fams ""
    foreach f $families {
	if {$family_dims($f) == 3} {
	    lappend fams "$f -text $family_name($f)"
	    set select_some_families($f) $family_active($f)
	}
    }
    if {$fams == ""} { 
	tk_dialog .err "Error" "No volume families are visible" "" 0 Ok
    }
    
    form_kill .mark_fams
    set d [form_init .mark_fams "Volume families" "" "done cancel"]
    form_frame $d.fams flat 0 {0 0}
    check_box $d.fams $fams 6 select_some_families
    form_finish +300+300
    if ![form_wait .mark_fams] { return "" }
    
    set fams ""
    foreach i [array names select_some_families] {
	if $select_some_families($i) { lappend fams $i }
    }
    return $fams
}

proc select_one_family {mess} {
    global families family_dims family_name
    
    set appfam [family_name_string]
    set fams ""
    foreach f $appfam {
	lappend fams $f
    }
    return [choose_one $mess $fams "" +300+300]
}
