Revision: 71151 http://sourceforge.net/p/brlcad/code/71151 Author: sharannyn Date: 2018-07-11 09:10:13 +0000 (Wed, 11 Jul 2018) Log Message: ----------- Introduce better object selection with an interactive tree view of the database; Ability to add/remove selected objects with help of wildcards; Cleaned up the OverlapFileTool.tcl
Modified Paths: -------------- brlcad/trunk/src/tclscripts/checker/OverlapFileTool.tcl Modified: brlcad/trunk/src/tclscripts/checker/OverlapFileTool.tcl =================================================================== --- brlcad/trunk/src/tclscripts/checker/OverlapFileTool.tcl 2018-07-11 08:53:56 UTC (rev 71150) +++ brlcad/trunk/src/tclscripts/checker/OverlapFileTool.tcl 2018-07-11 09:10:13 UTC (rev 71151) @@ -28,6 +28,7 @@ package require Tk package require Itcl package require Itk +package require Iwidgets # go ahead and blow away the class if we are reloading # catch {delete class OverlapFileTool} error @@ -45,9 +46,13 @@ variable runCheckCallback method runTools {} {} + method getNodeChildren { { node "" }} {} + method selectNode { node } {} + method manualObjs { option } {} } private { variable _objs + variable _entryObjs variable _statusText variable _progressValue @@ -58,31 +63,69 @@ method rmDupPairs {} {} method addToList { new_list } {} + method UpdateObjsList { } {} + + method removeParentMark { node } {} + method removeChildrenMark { node } {} + + method markNode { node } {} + method unmarkNode { { node "" } } {} } } ::itcl::body OverlapFileTool::constructor { args } { set firstFlag false - set _objs [who] set _statusText "Ready" set _progressValue 0 + set _entryObjs "" itk_component add ovFrame { ttk::frame $itk_interior.ovFrame -padding 4 } {} itk_component add objectsLabel { - ttk::label $itk_component(ovFrame).objectsLabel -text "Object(s)" + ttk::label $itk_component(ovFrame).objectsLabel -text "Manually Enter The Object(s):" } {} itk_component add objectsEntry { - tk::entry $itk_component(ovFrame).objectsEntry -width 40 -textvariable [scope _objs] + tk::entry $itk_component(ovFrame).objectsEntry -width 40 -textvariable [scope _entryObjs] } {} + itk_component add buttonAdd { + ttk::button $itk_component(ovFrame).buttonAdd \ + -text "Add" -padding 5 -command [code $this manualObjs add ] + } {} + itk_component add buttonRemove { + ttk::button $itk_component(ovFrame).buttonRemove \ + -text "Remove" -padding 5 -command [code $this manualObjs remove ] + } {} + itk_component add objFrame { + ttk::frame $itk_interior.objFrame -padding 10 + } {} + itk_component add object_tree { + Hierarchy $itk_component(objFrame).object_tree \ + -labeltext "Double click to select/deselect objects" \ + -querycommand [ code $this getNodeChildren %n ] \ + -dblclickcommand [ code $this selectNode %n ] \ + -markforeground black \ + -markbackground yellow \ + -visibleitems 40x20 \ + -alwaysquery 1 + } {} + itk_component add objslist { + scrolledlistbox $itk_component(objFrame).objslist \ + -labelpos n \ + -dblclickcommand [code $this unmarkNode ] \ + -visibleitems 40x18 \ + -selectbackground yellow \ + -selectforeground black \ + -labeltext "Selected Items:" \ + } {} + itk_component add progressFrame { ttk::frame $itk_interior.progressFrame -padding 4 } {} itk_component add statusLabel { ttk::label $itk_component(progressFrame).statusLabel \ - -textvariable [scope _statusText] + -textvariable [scope _statusText] -justify center -wraplength 500 } {} itk_component add progressBar { ttk::progressbar $itk_component(progressFrame).progressBar -variable [scope _progressValue] @@ -101,9 +144,13 @@ pack $itk_component(ovFrame) -side top -fill x -padx 8 pack $itk_component(objectsLabel) -side top -expand true -anchor nw pack $itk_component(objectsEntry) -side left -expand true -fill x - focus $itk_component(objectsEntry) - bind $itk_component(objectsEntry) <Return> [code $itk_component(buttonGo) invoke] + pack $itk_component(buttonAdd) -side left -padx 8 + pack $itk_component(buttonRemove) -side right + pack $itk_component(objFrame) -side top + pack $itk_component(object_tree) -side left -padx {0 8} + pack $itk_component(objslist) -side right -padx {8 0} + pack $itk_component(ovButtonFrame) -side top -fill both pack $itk_component(buttonGo) -side left -expand true @@ -110,9 +157,309 @@ pack $itk_component(progressFrame) -side top -expand true -fill both pack $itk_component(statusLabel) pack $itk_component(progressBar) -side left -expand true -fill x -anchor nw -pady 8 -padx 8 +} + +########### +# begin public methods +########### + +# runTools +# +# main driver that calls the commands and +# creates the overlaps file +# +body OverlapFileTool::runTools { } { + # get _objs from list + set _objs "" + foreach obj [$itk_component(objslist) get 0 end] { + append _objs " " $obj + } + # check if user passed the objects list + if { [llength $_objs] == 0 } { + tk_messageBox -icon info -type ok -title "No Objects Specified" -message "Please input objects names in the objects field" + return + } + # check if the specified objects exist in the database + set bad_objs "" + foreach obj $_objs { + set ret "" + catch {set ret [paths $obj]} + if { $ret eq "" } { + lappend bad_objs $obj + } + } + + if { [llength $bad_objs] > 0 } { + tk_messageBox -icon error -type ok -title "Bad Object Names" -message "Unrecognized object names:\n$bad_objs" + return + } + + # disable the go button and entry before proceeding to prevent any re-runs + $itk_component(buttonGo) configure -state disabled + $itk_component(objectsEntry) configure -state disabled + $this configure -cursor watch + update + + # run checkoverlaps and gqa for all the specified objects + if { [string length $_objs] > 0 } { + $this runCheckOverlaps $_objs + $this runGqa $_objs + } + # check for the count of overlaps detected + set ov_count [llength $pairsList] + if { $ov_count == 0 } { + tk_messageBox -type ok -title "No Overlaps Found" -message "No Overlaps Found" + $itk_component(buttonGo) configure -state normal + $itk_component(objectsEntry) configure -state normal + $this configure -cursor "" + set _progressValue 0 + set _statusText "Ready" + update + return + } + + puts "\nCount of overlaps: $ov_count\n" + + # process the overlap pairs + $this sortPairs + $this rmDupPairs + + # delete any previous overlaps files in the db directory + set db_path [eval opendb] + set dir [file dirname $db_path] + set name [file tail $db_path] + set ol_dir [file join $dir "${name}.ck"] + set filename [file join $dir "${name}.ck" "ck.${name}.overlaps"] + file delete -force -- $ol_dir + + # create new folder + file mkdir $ol_dir + # write the overlaps file + set fp [open $filename w+] + foreach pair [lsort -decreasing -real -index 2 $overlapsList] { + puts $pair + puts $fp $pair + } + close $fp + puts "\nOverlaps file saved: $filename" + + # run checker tool + eval $runCheckCallback } +# getNodeChildren is the -querycommand +# +# returns the geometry at any node in the object tree. +body OverlapFileTool::getNodeChildren { { node "" } } { + # get a list of children for the current node. the result in childList + # should be a list of adorned children nodes. + set childList "" + if {$node == ""} { + # process top geometry + set topsCommand "tops -n" + + if [ catch $topsCommand roots ] { + puts $roots + return + } + + # the children are all of the top geometry + set childList "" + foreach topItem $roots { + # XXX handle the case where tops returns decorated paths + if { [ llength [ split $topItem / ] ] >= 2 } { + set topItem [ lindex [ split $topItem / ] 0 ] + } + lappend childList "/$topItem" + } + + } else { + # process some combination or region or primitive + + set lsNodeName [ls [ lindex [ split $node / ] end ]] + # if region don't expand + if { [ string compare "R" [ string index $lsNodeName end-1 ] ] == 0 } { + if { [ string compare "/" [ string index $lsNodeName end-2 ] ] == 0 } { + return + } + } + set parentName [ lindex [ split $node / ] end ] + + set childrenPairs "" + if [ catch { lt $parentName } childrenPairs ] { + set childrenPairs "" + } + + foreach child $childrenPairs { + lappend childList "$node/[ lindex $child 1 ]" + } + } + + # generate the final child list including determining whether the object is a + # primitive or a combinatorial (branch or leaf node). + set children "" + foreach child $childList { + + set childName [ lindex [ split $child / ] end ] + + # we do not call getObjectType for performance reasons (big directories + # can choke. Sides, we do not need to know the type, just whether the + # node is a branch or not. + if { [ catch { ls $childName } lsName ] } { + puts "$lsName" + continue + } + set nodeType leaf + if { [ string compare "/" [ string index $lsName end-1 ] ] == 0 } { + set nodeType branch + } + + lappend children [ list "$node/$childName" "$childName" $nodeType ] + } + # done iterating over children + + return $children +} + +# selectNode - dblclickcommand +# +# to select/deselect the nodes in the object tree on double click +# +body OverlapFileTool::selectNode { node } { + set nodeName [ lindex $node 1 ] + set markedobjs [ $itk_component(object_tree) mark get ] + + if {[lsearch $markedobjs $nodeName] >= 0} { + $this unmarkNode $nodeName + } else { + $this markNode $nodeName + } + return +} + +# manualObjs +# +# function to run the search command on the manually entered objects +# and add them to the objects list and mark them in the tree. +# +body OverlapFileTool::manualObjs { option } { + set entrylist {} + set badentry {} + set searchcmd "search / -type c -path" + foreach object $_entryObjs { + if { [string index $object 0] ne "/" } { + lappend entrylist "/$object" + } else { + lappend entrylist $object + } + } + foreach object $entrylist { + set objlist [eval $searchcmd $object] + if { $objlist == "" } { + lappend badentry $object + } + if { [llength $objlist] > 1 } { + set answer [tk_messageBox -title "Warning" \ + -message "Do you want to $option these [llength $objlist] objects:" \ + -detail "[lrange [split $objlist \n] 0 end-1]" -type okcancel -icon question] + if { $answer == "cancel" } { continue } + } + foreach searchobj $objlist { + if { $option eq "add" } { + $this markNode $searchobj + } else { + $this unmarkNode $searchobj + } + } + } + if { [llength $badentry] > 0 } { + tk_messageBox -icon error -type ok -title "Bad Object Names" -message "Unrecognized object names:\n$badentry" + } +} + +########### +# end public methods +########### + + +########### +# begin private methods +########### + +# UpdateObjsList +# +# Updates the object list for any marking/unmarking of the nodes +# in the object tree. +# +body OverlapFileTool::UpdateObjsList { } { + set markedobjs [ $itk_component(object_tree) mark get ] + $itk_component(objslist) clear + foreach obj [ lsort $markedobjs ] { + $itk_component(objslist) insert end $obj + } +} + +# removeParentMark +# +# Removes mark for any parent nodes recursively if a child node is marked +# +body OverlapFileTool::removeParentMark { node } { + set full "" + regexp {(.*)/} $node full parent + if { $full ne "" } { + $itk_component(object_tree) mark remove $parent + $this removeParentMark $parent + } else { + return + } +} + +# removeChildrenMark +# +# Removes mark for any child nodes recursively if a parent node is marked +# +body OverlapFileTool::removeChildrenMark { node } { + set full "" + regexp {(.*)/(.*)} $node full parent child + if { $full ne "" } { + foreach cnodes [$this getNodeChildren $child] { + set subchild [ lindex $cnodes 0 ] + $itk_component(object_tree) mark remove $parent/$subchild + $this removeChildrenMark "$parent/$subchild" + } + } else { + return + } +} + +# markNode +# +# marks the node in the object tree +# +body OverlapFileTool::markNode { node } { + # if we are selecting a parent node then disable the mark of children nodes. + $this removeChildrenMark $node + # we also have to disable the mark of parent nodes as well + $this removeParentMark $node + + $itk_component(object_tree) mark add $node + $this UpdateObjsList +} + +# unmarkNode +# +# unmarks the nodes in the object tree +# +body OverlapFileTool::unmarkNode { { node "" } } { + # if called from the scrolledlistbox get the current selection + if {$node == ""} { + set node [$itk_component(objslist) getcurselection] + } + $itk_component(object_tree) mark remove $node + $this UpdateObjsList +} + # addToList # # averages the size values for common pairs and @@ -185,7 +532,9 @@ set cmd "gqa -Ao -q -g1mm,1mm $obj" set _statusText "Running $cmd" update - catch {set gqa_list [eval $cmd]} + if [ catch {set gqa_list [eval $cmd]} ] { + set gqa_list {} + } set lines [split $gqa_list \n] foreach line $lines { regexp {(.*) (.*) count:([0-9]*) dist:(.*)mm} $line full left right count depth @@ -193,7 +542,7 @@ continue } set size [expr $count * $depth] - # swaps the region names by comparing lexicographically + # swaps the region names by comparing lexicographically if { [string compare $left $right] > 0 } { lappend pairsList [list $right $left $size] } else { @@ -218,7 +567,9 @@ set _statusText "Running $cmd" incr _progressValue 4 update - catch {set chk_list [eval $cmd]} + if [catch {set chk_list [eval $cmd]}] { + set chk_list {} + } set lines [split $chk_list \n] foreach line $lines { regexp {<(.*),.(.*)>: ([0-9]*).* (.*)mm} $line full left right count depth @@ -226,7 +577,7 @@ continue } set size [expr $count * $depth] - # swaps the region names by comparing lexicographically + # swaps the region names by comparing lexicographically if { [string compare $left $right] > 0 } { lappend pairsList [list $right $left $size] } else { @@ -238,88 +589,10 @@ } } } +########### +# end private methods +########### -# runTools -# -# main driver that calls the commands and -# creates the overlaps file -# -body OverlapFileTool::runTools { } { - # check if user passed the objects list - if { [llength $_objs] == 0 } { - tk_messageBox -icon info -type ok -title "No Objects Specified" -message "Please input objects names in the objects field" - return - } - # check if the specified objects exist in the database - set bad_objs "" - foreach obj $_objs { - catch {set ret [t $obj]} - if { [string first $obj $ret] != 0 } { - lappend bad_objs $obj - } - } - - if { [llength $bad_objs] > 0 } { - tk_messageBox -icon error -type ok -title "Bad Object Names" -message "Unrecognized object names:\n$bad_objs" - return - } - - # disable the go button and entry before proceeding to prevent any re-runs - $itk_component(buttonGo) configure -state disabled - $itk_component(objectsEntry) configure -state disabled - $this configure -cursor watch - update - - # run checkoverlaps and gqa for all the specified objects - if { [string length $_objs] > 0 } { - foreach obj $_objs { - set _progressValue 0 - update - $this runCheckOverlaps $obj - $this runGqa $obj - } - } - # check for the count of overlaps detected - set ov_count [llength $pairsList] - if { $ov_count == 0 } { - tk_messageBox -type ok -title "No Overlaps Found" -message "No Overlaps Found" - $itk_component(buttonGo) configure -state normal - $itk_component(objectsEntry) configure -state normal - $this configure -cursor "" - set _progressValue 0 - update - return - } - - puts "\nCount of overlaps: $ov_count\n" - - # process the overlap pairs - $this sortPairs - $this rmDupPairs - - # delete any previous overlaps files in the db directory - set db_path [eval opendb] - set dir [file dirname $db_path] - set name [file tail $db_path] - set ol_dir [file join $dir "${name}.ck"] - set filename [file join $dir "${name}.ck" "ck.${name}.overlaps"] - file delete -force -- $ol_dir - - # create new folder - file mkdir $ol_dir - # write the overlaps file - set fp [open $filename w+] - foreach pair [lsort -decreasing -real -index 2 $overlapsList] { - puts $pair - puts $fp $pair - } - close $fp - puts "\nOverlaps file saved: $filename" - - # run checker tool - eval $runCheckCallback -} - # Local Variables: # mode: Tcl # tab-width: 8 This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot _______________________________________________ BRL-CAD Source Commits mailing list brlcad-commits@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/brlcad-commits