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

proc unstruct_check_vol_orient {which which_bad {display 1}} {
    global batch_mode diag_maps_saved uns_cur
    global tdv_default interrupt_disable
    
    set map [$uns_cur get_map $which]  
	set bad_map [$uns_cur get_map $which_bad]
	if {"" == $bad_map} {
	   ic_uns_create_diagnostic_subset $which_bad
	}
    busy 1
    set interrupt_disable 1
    set nf [$map check_volume_orient 0 $bad_map]
    set interrupt_disable 0
    busy 0
    if {$nf < 0} { mess "Interrupted - not all elements checked\n" red }
    
    return [lindex [$bad_map count] 0]
}

proc unstruct_diag_mesh {what {which ""} {do_fix ""} {fix_fam ""} \
			     {fix_project ""}} {
    global unstruct_diag unstruct_map diag_maps_saved
    global projlib uns_cur batch_mode
    global tdv_default
    
    set color "white"    
    if !$batch_mode { set color [$tdv_default highlight_color] }
    set map [uns_map -mesh $uns_cur -color $color -visible 1 -width 2]
    set edges [uns_edge_list -mesh $uns_cur -color red -visible 1 -width 3]
    if !$batch_mode {
	$tdv_default add_image $map
	$tdv_default add_image $edges
    }
    if {$which == ""} { error "which is blank" }
    switch $which {
	all {
	    set allmap [$uns_cur get_map All]
	    mess "Checking all elements in the mesh\n"
	}
	active {
	    set allmap [$uns_cur get_map Selected]
	    mess "Checking active element types\n"
	}
	subset {
	    set allmap [$uns_cur get_map visible]
	    mess "Checking current visible subset\n"
	}
    }
    
    switch $what {
	bound_edge {
	    set fam [unstruct_select_existing_family]
	    if {$fam != ""} {
		busy 1
		set nch [$map diagnostic_$what $allmap $edges $fam]
		busy 0
	    }
	}
	periodic_problem {
	    if {$projlib == ""} {
		error "Can't do check periodic: no geometry is loaded"
	    }
	    set fams [select_families 0 1 0 "Select only the surface families\nwhich contain the periodic faces."]
	    if { $fams == "" } {
		return
	    }
	    busy 1
	    set probs [eval $allmap check_periodic $fams]
	    foreach line $probs {
		mess $line red
		if [regexp {^triangle ([0-9]*) } $line xx num] {
		    set badn_tri($num) 1
		}
		if [regexp {^quad ([0-9]*) } $line xx num] {
		    set badn_quad($num) 1
		}
	    }
	    set nch 0
	    foreach n [array names badn_tri] {
		$map add_with_number $n 2 TRI_3
	    }
	    foreach n [array names badn_quad] {
		$map add_with_number $n 2 QUAD_4
	    }
	    busy 0
	}
	default {
	    busy 1
	    set nch [$map diagnostic_$what $allmap $edges]
	    busy 0
	}
    }
    
    if {$nch < 0} {
	mess "Interrupted -- only partial results obtained\n" red
	set nch [expr -$nch]
    }
    
    set n [lindex [$map count] 0]
    if $nch {
	mess "$n $what elements found ($nch checked)\n"
    } else {
	mess "$n $what elements found\n"
    }
    
    set ok 0
    set delmap 1
    if $n {
	set ok 2
	switch $what {
	    duplicate {
		if {$do_fix != ""} {
		    switch $do_fix {
			0 { set ch 3 }
			1 { set ch 0 }
			leave { set ch 3; set delmap 0 }
		    }
		} else {
		    set mess "You can delete the duplicate elements,\
 			make them replace the\
			current displayed subset, add them to the\
			current displayed subset, or not do anything."
		    set ch [tk_dialog .mesh_diag "Diagnostics" $mess -0-0 -1 \
				Delete Select "Add select" Dismiss]
		}
		switch $ch {
		    0 {
			ic_newop
			busy 1
			$map delete_contents
			busy 0
			mess "$n elements deleted\n"
			set ok 1
		    }
		    1 - 2 {
			switch_to_subset Diagnostic
			set smap $unstruct_map($uns_cur)
			if {$ch == 1} {
			    $smap copy_from $map 0
			} else {
			    $smap add_from $map
			}
		    }
		    3 { }
		}
	    }
	    multiple {
		if {$do_fix != ""} {
		    switch $do_fix {
			0 { set ch 2 }
			1 { set ch 2 }
			leave { set ch 2; set delmap 0 }
		    }
		} else {
		    set mess "You can make these elements replace the\
			current displayed subset, add them to the\
			current displayed subset, or not do anything."
		    set ch [tk_dialog .mesh_diag "Diagnostics" $mess -0-0 -1 \
				Select "Add select" Dismiss]
		}
		switch $ch {
		    0 - 1 {
			switch_to_subset Diagnostic
			set smap $unstruct_map($uns_cur)
			if {$ch == 0} {
			    $smap copy_from $map 0
			} else {
			    $smap add_from $map
			}
		    }
		    2 { }
		}
	    }
	    triangle_box {
		if {$do_fix != ""} {
		    switch $do_fix {
			0 { set ch 4 }
			1 { set ch 3 }
			leave { set ch 4; set delmap 0 }
		    }
		} else {
		    set mess "You can delete these elements, make them replace the\
			current displayed subset, add them to the\
			current displayed subset, fix the problem by\
			replacing the triangles with a tetra,\
 			or not do anything."
		    set ch [tk_dialog .mesh_diag "Diagnostics" $mess -0-0 -1 \
				Delete Select "Add select" Fix Dismiss]
		}
		switch $ch {
		    0 {
			ic_newop
			busy 1
			$map delete_contents
			busy 0
			mess "$n elements deleted\n"
		    }
		    1 - 2 {
			switch_to_subset Diagnostic
			set smap $unstruct_map($uns_cur)
			if {$ch == 1} {
			    $smap copy_from $map 0
			} else {
			    $smap add_from $map
			}
		    }
		    3 {
			if {$fix_fam != ""} {
			    set fam $fix_fam
			    fam_check_new $fam
			} else {
			    set fam [select_family \
					 " for the newly created tetras"]
			}
			if {$fam != ""} {
			    big_uns_op 0 {
				set nn [$map fix_triangle_box $fam]
			    }
			    mess "$nn triangle boxes replaced with tetras\n"
			}
			set ok 1
		    }
		    4 { }
		}
	    }
	    single_2 - single_multiple - standalone {
		if {$do_fix != ""} {
		    switch $do_fix {
			0 { set ch 3 }
			1 { set ch 0 }
			leave { set ch 3; set delmap 0 }
		    }
		} else {
		    set mess "You can delete these elements, make them replace the\
			current displayed subset, add them to the\
			current displayed subset, or not do anything."
		    set ch [tk_dialog .mesh_diag "Diagnostics" $mess -0-0 -1 \
				Delete Select "Add select" Dismiss]
		}
		switch $ch {
		    0 {
			ic_newop
			busy 1
			$map delete_contents
			busy 0
			mess "$n elements deleted\n"
		    }
		    1 - 2 {
			switch_to_subset Diagnostic
			set smap $unstruct_map($uns_cur)
			if {$ch == 1} {
			    $smap copy_from $map 0
			} else {
			    $smap add_from $map
			}
			set ok 1
		    }
		    3 { }
		}
	    }
	    single {
		if {$do_fix != ""} {
		    switch $do_fix {
			0 { set ch 4 }
			1 { set ch 3 }
			leave { set ch 4; set delmap 0 }
		    }
		} else {
		    set mess "You can delete the single-edge elements,\
			make them replace the\
			current displayed subset, add them to the\
			current displayed subset,\
			delete the elements, or not do anything."
		    set ch [tk_dialog .mesh_diag "Diagnostics" $mess -0-0 -1 \
				Delete Select "Add select" Dismiss] ;# Fix ?
		}
		switch $ch {
		    0 {
			ic_newop
			busy 1
			$map delete_contents
			busy 0
			mess "$n elements deleted\n"
			# Recurse ...
			mess "Checking again for single elements ...\n"
			unstruct_diag_mesh single $which $do_fix
		    }
		    1 - 2 {
			switch_to_subset Diagnostic
			set smap $unstruct_map($uns_cur)
			if {$ch == 1} {
			    $smap copy_from $map 0
			} else {
			    $smap add_from $map
			}
		    }
		    3_not_used {
			big_uns_op 0 {
			    set nn [$edges fix_single_edge_gaps $uns_cur \
				       $projlib]
			    mess "$nn triangles added\n"
			}
			# Recurse ...
			mess "Checking again for single elements ...\n"
			unstruct_diag_mesh single $which $do_fix
			set ok 1
		    }
		    4 { }
		}
	    }
	    delaunay - overlap - 3_surface_node_internal_faces {
		if {$do_fix != ""} {
		    switch $do_fix {
			0 { set ch 2 }
			1 { set ch 2 }
			leave { set ch 2; set delmap 0 }
		    }
		} else {
		    set mess "You can make the elements replace the\
			current displayed subset, add them to the\
			current displayed subset, or not do anything."
		    set ch [tk_dialog .mesh_diag "Diagnostics" $mess -0-0 -1 \
				Select "Add select" Dismiss]
		}
		switch $ch {
		    0 - 1 {
			switch_to_subset Diagnostic
			set smap $unstruct_map($uns_cur)
			if {$ch == 0} {
			    $smap copy_from $map 0
			} else {
			    $smap add_from $map
			}
		    }
		    2 { }
		}
	    }
	    uncovered {
		if {$do_fix != ""} {
		    switch $do_fix {
			0 { set ch 3 }
			1 { set ch 0 }
			leave { set ch 3; set delmap 0 }
		    }
		} else {
		    set mess "You can try to automatically fix the problem,\
			make the elements replace the\
			current displayed subset, add them to the\
			current displayed subset, or not do anything."
		    set ch [tk_dialog .mesh_diag "Diagnostics" $mess -0-0 -1 \
				Fix Select "Add select" Dismiss]
		}
		switch $ch {
		    0 {
			if {$fix_fam != ""} {
			    set fam $fix_fam
			    fam_check_new $fam
			} else {
			    set fam [select_family \
					 " for the newly created triangles"]
			}
			if {$fam != ""} {
			    big_uns_op 0 {
				set nn [$map fix_uncovered $fam 0]
			    }
			    mess "$nn elements added\n"
			    if $nn {
				display_update unstruct
			    }
			}
			set ok 1
		    }
		    1 - 2 {
			switch_to_subset Diagnostic
			set smap $unstruct_map($uns_cur)
			if {$ch == 1} {
			    $smap copy_from $map 0
			} else {
			    $smap add_from $map
			}
		    }
		    3 { }
		}
	    }
	    missing_internal {
		if {$do_fix != ""} {
		    switch $do_fix {
			0 { set ch 3 }
			1 { set ch 2 }
			leave { set ch 3; set delmap 0 }
		    }
		} else {
		    set mess "You can make the elements replace the\
			current displayed subset, add them to the\
			current displayed subset, try to fix them,\
			or not do anything."
		    set ch [tk_dialog .mesh_diag "Diagnostics" $mess -0-0 -1 \
				Select "Add select" Fix Dismiss]
		}
		switch $ch {
		    0 - 1 {
			switch_to_subset Diagnostic
			set smap $unstruct_map($uns_cur)
			if {$ch == 0} {
			    $smap copy_from $map 0
			} else {
			    $smap add_from $map
			}
		    }
		    2 {
			if {$fix_fam != ""} {
			    set fam $fix_fam
			    fam_check_new $fam
			} else {
			    set fam [select_family \
					 " for the newly created triangles"]
			}
			set pl ""
			if {$fix_project != ""} {
			    if $fix_project { set pl $projlib }
			} else {
			    set mess "Project new surface nodes to the\
				nearest surface?"
			    if ![tk_dialog .projn "Project" $mess -0-0 -1 \
				     Yes No] {
					 set pl $projlib
				     }
			}
			big_uns_op 0 {
			    set nn [$map fix_missing_internal_faces $fam $pl]
			    mess "$nn faces added\n"
			    if $nn {
				display_update unstruct
			    }
			}
			set ok 1
		    }
		    3 { }
		}
	    }
	    periodic_problem {
		if {$do_fix != ""} {
		    switch $do_fix {
			0 { set ch 3 }
			1 { set ch 2 }
			leave { set ch 3; set delmap 0 }
		    }
		} else {
		    set mess "You can make the elements replace the\
			current displayed subset, add them to the\
			current displayed subset or not do anything."
		    set ch [tk_dialog .mesh_diag "Diagnostics" $mess -0-0 -1 \
				Select "Add select" Dismiss]
		}
		switch $ch {
		    0 - 1 {
			switch_to_subset Diagnostic
			set smap $unstruct_map($uns_cur)
			if {$ch == 0} {
			    $smap copy_from $map 0
			} else {
			    $smap add_from $map
			}
		    }
		    2 { }
		}
	    }
	    bound_edge {
		if {$do_fix != ""} {
		    switch $do_fix {
			0 { set ch 2 }
			1 { set ch 2 }
			leave { set ch 2; set delmap 0 }
		    }
		} else {
		    set mess "You can make the elements replace the\
			current displayed subset, add them to the\
			current displayed subset, or not do anything."
		    set ch [tk_dialog .mesh_diag "Diagnostics" $mess -0-0 -1 \
				Select "Add select" Dismiss]
		}
		switch $ch {
		    0 - 1 {
			switch_to_subset Diagnostic
			set smap $unstruct_map($uns_cur)
			if {$ch == 0} {
			    $smap copy_from $map 0
			} else {
			    $smap add_from $map
			}
		    }
		    2 { }
		}
	    }
	    nmanvert {
		if {$do_fix != ""} {
		    switch $do_fix {
			0 { set ch 3 }
			1 { set ch 0 }
			leave { set ch 3; set delmap 0 }
		    }
		} else {
		    set mess "You can try to automatically fix the problem,\
 			make the elements replace the\
			current displayed subset, add them to the\
			current displayed subset, or not do anything."
		    set ch [tk_dialog .mesh_diag "Diagnostics" $mess -0-0 -1 \
				Fix Select "Add select" Dismiss]
		}
		switch $ch {
		    0 {
			$map fix_nmanvert $projlib
			set nleft [lindex [$map count] 1]
			if $nleft {
			    mess "$nleft non-manifold vertices\
				could not be fixed\n" red
			} else {
			    mess "All non-manifold vertices were fixed.\n"
			    set ok 1
			}
			update_uns_visible
		    }
		    1 - 2 {
			switch_to_subset Diagnostic
			set smap $unstruct_map($uns_cur)
			if {$ch == 1} {
			    $smap copy_from $map 0
			} else {
			    $smap add_from $map
			}
		    }
		    3 { }
		}
		
	    }
	}
    }
    if $delmap {
	$map delete
	$edges delete
    } else {
	lappend diag_maps_saved $map $edges
    }
    return $ok
}

proc unstruct_clear_diag_display {} {
    global diag_maps_saved
    
    if [info exists diag_maps_saved] {
	foreach i $diag_maps_saved { $i delete }
	unset diag_maps_saved
    }
}

proc unstruct_disconnected_verts {{do_fix ""} {skip 0}} {
    global uns_cur diag_maps_saved batch_mode
    global tdv_default
    
    set color "white"
    if !$batch_mode { set color [$tdv_default highlight_color] }
    
    set map [uns_map -mesh $uns_cur -color $color -visible 1]
    if !$batch_mode { $tdv_default add_image $map }
    
    $map diagnostic_disconnected_verts
    set nn [lindex [$map count] 1]
    
    mess "$nn unconnected vertices were found.\n"
    if !$nn { return 1 }
    
    set delmap 1
    set ch 1
    if {$do_fix != ""} {
        switch $do_fix {
	        0 { set ch 1 }
	        1 { set ch 0 }
	        leave { set ch 1; set delmap 0 }
	    }
    } elseif !$batch_mode {
        if !$skip {
            set mess "Delete the unconnected vertices?"
	        set ch [tk_dialog .mesh_diag "Diagnostics" $mess "" -1 Yes No]
	    } else {
	        set ch 0
	    }
    }
    if !$ch {
        $map delete_vertices
        mess "$nn unconnected vertices deleted\n" blue
        set ok 1
    } else {
        set ok 0
    }
    if $delmap {
        $map delete
    } else {
        lappend diag_maps_saved $map
    }
    return $ok
}
