[Keith Vetter] 2007-10-12 : I'd thought I'd share some new techniques I've created while adding a new feature to my KLIMB bike mapping program which lets you plan bike routes interactively on topo maps [http://www.klimb.org/klimb.html]. The new feature is another way of printing out bike routes by collecting multiple, smaller map segments and laying them out on a page. The key problem, however, is that the smaller map segments, in order to better cover the bike route, can be at any angle. I'm still working on this new feature, and would like feedback on it, especially on the user interaction in specifying the map segment--it's tricky because the user can move, rotate and resize the selection. A selection box is drawn on the map. The user can grab and move it anywhere. Grabbing the SE corner or by using the 3rd button, the user can rotate the box. Grabbing either of two resize controls lets you change the size. The second aspect of this problem is laying out the results, and I haven't really done much with that yet. The third aspect is printing the result--that's going to be real fun to solve. I included demo code, including a sample map image (compressed to death jpeg so it doesn't look great). ---- Some technical details. The hardest/funnest part was extracting an angled rectangle area off a canvas. Initially I used [TclMagick] to do it, but because of poor documentation (I ended up using the php doc) and a few programming snags, I realized that that was overkill. Instead I used '''xphoto''' from [Enhanced photo image copy command]. I use [Img] to grab the whole window, then crop that image to the bounding box of the selection. Next, I use '''xphoto''' to rotate the image. Then, after some simple trig, I use Img again to crop down to the selected area. ---- ##+########################################################################## # # Clipbox -- grabs rectangular region of an image at any angle or size # by Keith Vetter, Sep, 2007 # package require Tk package require Img set hasXPhoto 1 if {[catch {load xphoto.dll}]} { wm withdraw . set msg "ERROR: missing xphoto.dll\n\n" append msg "This program requires the xphoto extension, which\n" append msg "can be downloaded from http://wiki.tcl.tk/11924\n\n" append msg "You can still run the program and interact with\n" append msg "the map but you cannot take snapshots." tk_messageBox -icon error -message $msg set hasXPhoto 0 wm deiconify . } namespace eval ::ClipBox { variable P ;# Box position variable M ;# Mousing info unset -nocomplain P set P(clr,1) cyan set P(clr,0) red array set M { xy {} minWidth 200 minHeight 200 mousing 0 resizeSize 8 cornerSize 15 cursor,corner exchange cursor,strip hand2 cursor,width fleur cursor,height fleur } } ##+########################################################################## # # Go -- creates the initial instance of our clipping box # proc ::ClipBox::Go {W p0 angle width height} { variable P set P(0) $p0 set P(a,deg) $angle set P(w) $width set P(h) $height $W delete BOX $W create poly -tag {BOX clip} -fill cyan -stipple gray50 -width 2 \ -outline black -dash - $W create poly -tag {BOX corner} -outline black -fill {} -width 2 $W create poly -tag {BOX width} -fill black $W create poly -tag {BOX height} -fill black $W create text -100 -100 -text "N" -font {Helvetica 20 bold} -fill red \ -anchor s -tag {BOX north northText} $W create line -100 -100 -200 -200 -width 5 -tag {BOX north northLine} \ -fill red -arrow first -arrowshape {25 25 6} foreach tag {clip corner width height} { $W bind $tag <1> [list ::ClipBox::MouseDown %W $tag %x %y] $W bind $tag [list ::ClipBox::MouseMove %W $tag %x %y] $W bind $tag [list ::ClipBox::MouseUp %W] $W bind $tag [list ::ClipBox::MouseEnter %W $tag] $W bind $tag [list ::ClipBox::MouseLeave %W $tag] $W bind $tag <3> [list ::ClipBox::MouseDown %W corner %x %y] $W bind $tag [list ::ClipBox::MouseMove %W corner %x %y] $W bind $tag [list ::ClipBox::MouseUp %W] } ::ClipBox::DrawClipBox $W } ##+########################################################################## # # DrawClipBox -- repositions all elements of our clipbox # proc ::ClipBox::DrawClipBox {W} { set xy [::ClipBox::GetBoxCoords] foreach {bxy wxy hxy} [::ClipBox::GetSmallBoxCoords] break foreach {top bot} [::ClipBox::NorthArrow] break $W coords clip $xy $W coords corner $bxy $W coords width $wxy $W coords height $hxy $W coords northText $top $W coords northLine [concat $top $bot] } ##+########################################################################## # # GetBoxCoords -- given topleft corner, width, height and angle # returns coordinates of the box # proc ::ClipBox::GetBoxCoords {} { variable P set w $P(w) set h $P(h) set a $P(a,deg) set a [expr {$a * acos(-1) / 180}] ;# Radians foreach {x0 y0} $P(0) break set x1 [expr {$x0 + $w*cos($a)}] set y1 [expr {$y0 + $w*sin($a)}] set P(1) [list $x1 $y1] set top [::Data::VSub $P(1) $P(0)] set left [::Data::VNormalTo $top $h] set P(3) [::Data::VAdd $P(0) $left] set P(2) [::Data::VAdd $P(3) $top] set xy [concat $P(0) $P(1) $P(2) $P(3)] return $xy } ##+########################################################################## # # GetSmallBoxCoords -- returns coords for rotate box and two sizing boxes # proc ::ClipBox::GetSmallBoxCoords {} { variable P variable M # Assumes P(0-3) are correct set top [::Data::VSub $P(1) $P(0)] set left [::Data::VSub $P(3) $P(0)] set nTop [::Data::VReScale $top 1] set nLeft [::Data::VReScale $left 1] set c2 $P(2) set c1 [::Data::VAdd $c2 $nLeft -$M(cornerSize)] set c0 [::Data::VAdd $c1 $nTop -$M(cornerSize)] set c3 [::Data::VAdd $c0 $nLeft $M(cornerSize)] set cxy [concat $c0 $c1 $c2 $c3] # Width adjust box set w [::Data::VAdd $P(1) $left .5] set rSize2 [expr {$M(resizeSize)/2.0}] set w1 [::Data::VAdd $w $nLeft -$rSize2] set w0 [::Data::VAdd $w1 $nTop -$M(resizeSize)] set w3 [::Data::VAdd $w0 $nLeft $M(resizeSize)] set w2 [::Data::VAdd $w3 $nTop $M(resizeSize)] set wxy [concat $w0 $w1 $w2 $w3] # Height adjust box set h [::Data::VAdd $P(3) $top .5] set h2 [::Data::VAdd $h $nTop $rSize2] set h1 [::Data::VAdd $h2 $nLeft -$M(resizeSize)] set h0 [::Data::VAdd $h1 $nTop -$M(resizeSize)] set h3 [::Data::VAdd $h0 $nLeft $M(resizeSize)] set hxy [concat $h0 $h1 $h2 $h3] return [list $cxy $wxy $hxy] } ##+########################################################################## # # NorthArrow -- computes where north compass arrow should be positioned # proc ::ClipBox::NorthArrow {} { variable P set cornerOffset 35 set fudgeFactor {0 15} set arrowLength {0 150} set dir [expr {$P(a,deg) >= 0 ? 1 : -1}] if {($P(a,deg) >= 0 && $P(a,deg) <= 90) || $P(a,deg) < -90} { set bisect [::Data::VBisect $P(1) $P(0) $P(3)] set pt $P(0) } else { set bisect [::Data::VBisect $P(2) $P(3) $P(0)] set pt $P(3) } set pt1 [::Data::VAdd $pt $bisect $cornerOffset] set top [::Data::VAdd $pt1 $fudgeFactor] set bot [::Data::VAdd $top $arrowLength $dir] if {$dir == -1} {foreach {top bot} [list $bot $top] break} return [list $top $bot] } proc ::ClipBox::MouseEnter {W who} { variable M if {[info exists M(cursor,$who)]} { $W config -cursor $M(cursor,$who) } } proc ::ClipBox::MouseLeave {W who} { variable M if {$M(mousing)} return ;# Mouse down, don't change $W config -cursor {} } proc ::ClipBox::MouseDown {W who x y} { variable M variable P set M(xy) [list [$W canvasx $x] [$W canvasy $y]] set M(mousing) 1 if {$who eq "corner"} { $W config -cursor $M(cursor,corner) ::ClipBox::FourCorners $W # Create pivot foreach {X Y} $P(0) break set xy [list [expr {$X-10}] [expr {$Y-10}] [expr {$X+10}] [expr {$Y+10}]] $W create oval $xy -tag {BOX pivot} -fill black ::ClipBox::MouseMove $W $who $x $y } } proc ::ClipBox::MouseUp {W} { variable M set M(mousing) 0 $W delete pivot $W config -cursor {} } proc ::ClipBox::MouseMove {W who x y} { variable M set x [$W canvasx $x] set y [$W canvasy $y] if {$who eq "corner"} { ::ClipBox::MouseSpin $W $who $x $y } elseif {$who eq "width" || $who eq "height"} { ::ClipBox::MouseResize $W $who $x $y } else { foreach {bx by} $M(xy) break set M(xy) [list $x $y] set dx [expr {$x - $bx}] set dy [expr {$y - $by}] $W move BOX $dx $dy ::ClipBox::Onscreen $W } } ##+########################################################################## # # MouseSpin -- rotates clipbox to keep mouse point on the main diagonal # proc ::ClipBox::MouseSpin {W who x y} { variable P set v [::Data::VReScale [::Data::VSub [list $x $y] $P(0)] 1] set n [::Data::VDot [list 1 0] $v] set a1 [expr {acos($n)}] if {[lindex $v 1] < 0} { set a1 [expr {-$a1}] } ;# Quadrant check set a2 [expr {atan2($P(h), $P(w))}] set a3 [expr {$a1 - $a2}] set P(a,deg) [expr {$a3 * 180 / acos(-1)}] ::ClipBox::DrawClipBox $W ::ClipBox::Onscreen $W } ##+########################################################################## # # MouseResize -- resizes clipbox vertically or horizontally # proc ::ClipBox::MouseResize {W who x y} { variable P variable M ::ClipBox::FourCorners $W set top [::Data::VSub $P(1) $P(0)] set left [::Data::VSub $P(3) $P(0)] set nTop [::Data::VReScale $top 1] set nLeft [::Data::VReScale $left 1] if {$who eq "width"} { set p0 [::Data::VAdd $P(0) $left .5] set v [::Data::VSub [list $x $y] $p0] set w [::Data::VDot $nTop $v] if {$w < $M(minWidth)} return set P(w) $w } else { set p0 [::Data::VAdd $P(0) $top .5] set v [::Data::VSub [list $x $y] $p0] set h [::Data::VDot $nLeft $v] if {$h < $M(minHeight)} return set P(h) $h } ::ClipBox::DrawClipBox $W ::ClipBox::Onscreen $W } ##+########################################################################## # # Onscreen -- figures out if clipbox is off the screen at all # proc ::ClipBox::Onscreen {W} { variable P foreach {x0 y0 x1 y1 x2 y2 x3 y3} [$W coords clip] break set l [expr {round([::Data::Min $x0 $x1 $x2 $x3])}] set r [expr {round([::Data::Max $x0 $x1 $x2 $x3])}] set t [expr {round([::Data::Min $y0 $y1 $y2 $y3])}] set b [expr {round([::Data::Max $y0 $y1 $y2 $y3])}] set cx0 [$W canvasx 0] set cy0 [$W canvasy 0] set cx1 [expr {$cx0 + [winfo width $W]}] set cy1 [expr {$cy0 + [winfo height $W]}] set onscreen 1 if {$l < $cx0 || $t < $cy0 || $r > $cx1 || $b > $cy1} { set onscreen 0 } $W itemconfig clip -fill $P(clr,$onscreen) return $onscreen } proc ::ClipBox::PointOnscreen {W pt} { foreach {x y} $pt break set cx0 [$W canvasx 0] set cy0 [$W canvasy 0] set cx1 [expr {$cx0 + [winfo width $W]}] set cy1 [expr {$cy0 + [winfo height $W]}] return [expr {$x >= $cx0 && $x <= $cx1 && $y >= $cy0 && $y <= $cy1}] } ##+########################################################################## # # FourCorners -- fills in our data structures with clipbox's corners # proc ::ClipBox::FourCorners {W} { variable P foreach idx {0 1 2 3} {x y} [$W coords clip] { set P($idx) [list $x $y] } } ##+########################################################################## # # GetClipBoxSizes -- computes parameters needed to crop, rotate # and crop again the image # proc ::ClipBox::GetClipBoxSizes {W} { variable P ::ClipBox::FourCorners $W foreach {x0 y0} $P(0) {x1 y1} $P(1) {x2 y2} $P(2) {x3 y3} $P(3) break set l [expr {round([::Data::Min $x0 $x1 $x2 $x3])}] set r [expr {round([::Data::Max $x0 $x1 $x2 $x3])}] set t [expr {round([::Data::Min $y0 $y1 $y2 $y3])}] set b [expr {round([::Data::Max $y0 $y1 $y2 $y3])}] #set P(bbox) [list $l $t $r $b] set P(bbox) [::ClipBox::World2Canvas $W $l $t $r $b] set dy [expr {$y1 - $y0}] set dx [expr {$x1 - $x0}] set dx2 [expr {$x3 - $x0}] set dy2 [expr {$y3 - $y0}] # Question: use values from p or recompute from coordinates??? set P(a,rad) [expr {atan2($dy,$dx)}] set P(a,deg) [expr {$P(a,rad)*180/acos(-1)}] set P(w) [expr {round(hypot($dx,$dy))}] set P(h) [expr {round(hypot($dx2,$dy2))}] # R0 is topleft corner in the rotated image # R1 is bottomright corner in the rotated image set P(rx0) [expr {abs(round($dy2 * sin($P(a,rad))))}] set P(ry0) [expr {abs(round($dx * sin($P(a,rad))))}] set P(rx1) [expr {$P(rx0) + $P(w)}] set P(ry1) [expr {$P(ry0) + $P(h)}] } ##+########################################################################## # # World2Canvas -- translates world coordinates into canvas ones # proc ::ClipBox::World2Canvas {W args} { set x0 [$W canvasx 0] set y0 [$W canvasy 0] set result {} foreach {x y} $args { set x [expr {round($x - $x0)}] set y [expr {round($y - $y0)}] lappend result $x $y } return $result } ##+########################################################################## # # Snapshot -- extracts content of the clipbox, with the proper # cropping and rotating. # proc ::ClipBox::Snapshot {W} { variable P # Hide everything except compass north raise [winfo toplevel $W] $W lower BOX ; $W raise north update idletasks ::ClipBox::GetClipBoxSizes $W set snap [image create photo -data $W] set rot [image create photo] set chop [image create photo] $W raise BOX ; $W raise north set crop [eval ::ClipBox::SafeCrop $snap $P(bbox)] $rot copy $crop -rotate $P(a,deg) $chop copy $rot -from $P(rx0) $P(ry0) $P(rx1) $P(ry1) image delete $snap image delete $crop image delete $rot if {[::ClipBox::PointOnscreen $W $P(1)]} { ;# Move clipbox forward set P(0) $P(1) ::ClipBox::DrawClipBox $W } return $chop } ##+########################################################################## # # SafeCrop -- crops image handling off image coordinates # proc ::ClipBox::SafeCrop {cimg left top right bottom} { set w [image width $cimg] set h [image height $cimg] set pad(l) [expr {$left < 0 ? -$left : 0}] set left [::Data::Max $left 0] set pad(t) [expr {$top < 0 ? -$top : 0}] set top [::Data::Max $top 0] set pad(r) [expr {$right > $w ? $right-$w : 0}] set right [::Data::Min $right $w] set pad(b) [expr {$bottom > $h ? $bottom-$h : 0}] set bottom [::Data::Min $bottom $h] set crop [image create photo] $crop copy $cimg -from $left $top $right $bottom set pimg [::ClipBox::PadImage $crop $pad(l) $pad(t) $pad(r) $pad(b)] return $pimg } ##+########################################################################## # # PadImage -- adds requested borders to the image # proc ::ClipBox::PadImage {img left top right bottom} { if {$left == 0 && $top == 0 && $right == 0 && $bottom == 0} {return $img} set w [expr {[image width $img] + $left + $right}] set h [expr {[image height $img] + $top + $bottom}] set tmp [image create photo -width $w -height $h] $tmp put yellow -to 0 0 $w $h $tmp copy $img -to $left $top image delete $img return $tmp } namespace eval ::ShowPics { variable S unset -nocomplain S image create bitmap ::bmp::up -data { #define up_width 11 #define up_height 11 static char up_bits = { 0x00, 0x00, 0x20, 0x00, 0x70, 0x00, 0xf8, 0x00, 0xfc, 0x01, 0xfe, 0x03, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00 } } image create bitmap ::bmp::down -data { #define down_width 11 #define down_height 11 static char down_bits = { 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0xfe, 0x03, 0xfc, 0x01, 0xf8, 0x00, 0x70, 0x00, 0x20, 0x00, 0x00, 0x00 } } image create bitmap ::bmp::x -foreground white -data { #define X_width 11 #define X_height 11 static char X_bits = { 0x04, 0x01, 0x8e, 0x03, 0xdf, 0x07, 0xfe, 0x03, 0xfc, 0x01, 0xf8, 0x00, 0xfc, 0x01, 0xfe, 0x03, 0xdf, 0x07, 0x8e, 0x03, 0x04, 0x01 } } } proc ::ShowPics::ShowImg {W} { variable S global I set img [::ClipBox::Snapshot $W] if {! [winfo exists .show]} { toplevel .show wm protocol .show WM_DELETE_WINDOW ::ShowPics::Cleanup wm title .show "Snap Shot Gallery" RightWindow .show $W #wm transient .show [winfo toplevel $W] unset -nocomplain S } set id [expr {1 + [llength [grid slaves .show]]}] set w .show.$id frame $w grid $w -sticky w if {$id > 1} { grid config $w -pady {10 0}} button $w.up -image ::bmp::up -takefocus 0 \ -command [list ::ShowPics::Swap up $id] button $w.x -image ::bmp::x -bg red -takefocus 0 \ -command [list ::ShowPics::DeleteRow $id] button $w.down -image ::bmp::down -takefocus 0 \ -command [list ::ShowPics::Swap down $id] frame $w.right -bd 2 -relief solid ::ShowPics::OneImage $w.right $img $id set S($id,img) $img set S($id,txt) "" ::ShowPics::DoButtons grid $w.up $w.right -sticky s grid $w.x ^ -pady 5 grid $w.down ^ -sticky n -pady [list 0 [winfo reqheight $w.right.txt]] grid rowconfigure $w {0 2} -weight 1 grid columnconfigure $w 0 -pad 10 raise .show } proc ::ShowPics::Cleanup {} { variable S destroy .show foreach arr [array names S *,img] { image delete $S($arr) } unset -nocomplain S } proc ::ShowPics::OneImage {w img id} { variable S set S($id,w) $w.img label $w.img -image $img -bd 0 label $w.id -text "MAP $id" -font {Helvetica 12 bold} -anchor e entry $w.txt -font {Helvetica 12 bold} -justify c -bd 0 \ -textvariable ::ShowPics::S($id,txt) pack $w.img -side top -fill both -expand 1 pack $w.id -side right pack $w.txt -side left -fill both -expand 1 } proc ::ShowPics::SwapRows {row1 row2} { variable S set txt $S($row1,txt) set S($row1,txt) $S($row2,txt) set S($row2,txt) $txt set img $S($row1,img) set S($row1,img) $S($row2,img) set S($row2,img) $img $S($row1,w) config -image $S($row1,img) $S($row2,w) config -image $S($row2,img) } proc ::ShowPics::Swap {dir which} { set other [expr {$dir eq "up" ? $which-1 : $which+1}] ::ShowPics::SwapRows $which $other } proc ::ShowPics::DeleteRow {which} { variable S set len [llength [array names S *,img]] for {set row $which} {$row < $len} {incr row} { ::ShowPics::SwapRows $row [expr {$row+1}] } destroy .show.$len image delete $S($len,img) array unset S $len,* ::ShowPics::DoButtons if {$len == 1} ::ShowPics::Cleanup } proc ::ShowPics::DoButtons {} { variable S set len [llength [array names S *,img]] if {$len == 0} return for {set i 1} {$i <= $len} {incr i} { .show.$i.up config -state normal .show.$i.down config -state normal } .show.1.up config -state disabled .show.$len.down config -state disabled } ################################################################ # # Utility routines # namespace eval ::Data {} proc ::Data::Max {a args} { foreach arg $args {if {$arg > $a} { set a $arg}} return $a } proc ::Data::Min {a args} { foreach arg $args {if {$arg < $a} { set a $arg}} return $a } proc ::Data::VAdd {v1 v2 {scaling 1}} { foreach {x1 y1} $v1 {x2 y2} $v2 break return [list [expr {$x1 + $scaling*$x2}] [expr {$y1 + $scaling*$y2}]] } proc ::Data::VSub {v1 v2} { return [::Data::VAdd $v1 $v2 -1] } proc ::Data::VReScale {v scaling} { foreach {x y} $v break set len [expr {hypot($x,$y)}] return [list [expr {$x * $scaling / $len}] [expr {$y * $scaling / $len}]] } proc ::Data::VNormalTo {vv length} { foreach {x y} $vv break set len [expr {hypot($x,$y)}] set xx [expr {-$y * $length / $len}] set yy [expr {$x * $length / $len}] return [list $xx $yy] } proc ::Data::VBisect {p1 p2 p3} { set v1 [::Data::VReScale [::Data::VSub $p1 $p2] 1] set v2 [::Data::VReScale [::Data::VSub $p3 $p2] 1] set v [::Data::VReScale [::Data::VAdd $v1 $v2] 1] return $v } proc ::Data::VDot {v1 v2} { foreach {x1 y1} $v1 {x2 y2} $v2 break return [expr {$x1*$x2 + $y1*$y2}] } proc RightWindow {w {W .}} { update idletasks set W [winfo toplevel $W] set y [expr {3 + [winfo y $W]}] ;# Top of main window set x [expr {15 + [winfo x $W] + [winfo width $W]}] ;# Right side wm geom $w +$x+$y } ################################################################ # # DEMO CODE BELOW # image create photo ::img::img -data { /9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAP////////////////////////////////////////// ////////////////////////////////////////////2wBDAf////////////////////////// ////////////////////////////////////////////////////////////wAARCALrBEADASIA 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 dgaAAAlZyjUoAka1KAAAAH//2Q== } proc About {} { set msg "Route Map Selection\nby Keith Vetter\n\n" append msg "This demonstrates a package that lets\n" append msg "select arbitrary rectangular areas of\n" append msg "canvas and to extract exactly that area.\n\n" append msg "You can move the selection by dragging it,\n" append msg "you can resize the selection by dragging\n" append msg "a resize button, and you can rotate the\n" append msg "selection by dragging the resize control\n" append msg "or by dragging with the 3rd mouse button.\n" tk_messageBox -icon info -message $msg } ################################################################ # # Demo code proc DoDisplay {} { bind all {console show} wm title . "Clip Box Demo" canvas .c -highlightthickness 0 -bd 0 \ -width [image width ::img::img] -height [image height ::img::img] .c create image 0 0 -image ::img::img -anchor nw .c config -scrollregion [.c bbox all] button .chop -text "Take Snap Shot" -command [list ::ShowPics::ShowImg .c] if {! $::hasXPhoto} { .chop config -state disabled } button .about -text About -command About pack .c -side top #pack .chop .about -side left -pady 10 -expand 1 -padx 10 pack .about -side right -padx 10 -pady 10 pack .chop -side bottom -pady 10 bind .c <2> [bind Text <2>] ;# Enable dragging w/ <2> bind .c [bind Text ] } DoDisplay wm geom . +1+1 ::ClipBox::Go .c {35 135} -7 700 200 set W .c return <>GUI|Graphics