From 8ca407c367337b05e66acd0c6ec2ce46ce4c83f4 Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Fri, 7 Jul 2023 18:23:50 -0400 Subject: Implement `region move` (at least for AA regions) start on `region clip` and some other utilities too --- virtual-programs/regions.folk | 58 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 53 insertions(+), 5 deletions(-) (limited to 'virtual-programs') diff --git a/virtual-programs/regions.folk b/virtual-programs/regions.folk index 8f320b42..343ffe03 100644 --- a/virtual-programs/regions.folk +++ b/virtual-programs/regions.folk @@ -34,12 +34,16 @@ namespace eval ::vec2 { } namespace eval ::region { - proc new {vertices edges angle space} { - list region $vertices $edges $angle $space - } - proc vertices {r} { lindex $r 0 } proc edges {r} { lindex $r 1 } + # Angle the region is rotated above the horizontal, in radians: + proc angle {r} { + expr {[llength $r] >= 3 ? [lindex $r 2] : 0} + } + + proc mapVertices {varname r body} { + lreplace $r 0 0 [uplevel [list lmap $varname [vertices $r] $body]] + } proc edgeToLineSegment {r e} { list [lindex [vertices $r] [lindex $e 0]] [lindex [vertices $r] [lindex $e 1]] @@ -68,6 +72,9 @@ namespace eval ::region { expr {0 <= $dot_abap && $dot_abap <= [vec2 dot $ab $ab] && \ 0 <= $dot_bcbp && $dot_bcbp <= [vec2 dot $bc $bc]} } + proc intersects {r1 r2} { + # FIXME: implement + } proc centroid {r1} { # This only works for rectangular regions @@ -78,7 +85,48 @@ namespace eval ::region { vec2 scale 0.25 $vecsum } - namespace export distance contains centroid + # Utilities that transform regions while preserving center + proc clip {r args} { + foreach {property value} $args { + if {$property eq "width"} { + + } elseif {$property eq "height"} { + + } else { + error "region clip: Invalid property $property" + } + } + } + proc move {r args} { + set angle [angle $r] + # FIXME: This one should work on any region -- just map over vertices. + foreach {direction distance} $args { + if {![regexp {([0-9]+)px} $distance -> distance]} { + error "region move: Invalid distance $distance" + } + set dx [if {$direction eq "left"} {- $distance} \ + elseif {$direction eq "right"} {+ $distance} \ + else {+ 0}] + set dy [if {$direction eq "up"} {- $distance} \ + elseif {$direction eq "down"} {+ $distance} \ + else {+ 0}] + if {$dx == 0 && $dy == 0} { + error "region move: Invalid direction $direction" + } + + # Translate dx and dy into polar coordinates. + set theta [atan2 $dy $dx] + set mag [hypot $dy $dx] + + # Rotate dx and dy into the global coordinate space. + set dv [list [expr {$mag*cos($theta)}] [expr {$mag*sin($theta)}]] + + set r [mapVertices v $r {vec2 add $v $dv}] + } + set r + } + + namespace export * namespace ensemble create } -- cgit v1.2.3 From 96b7384bb36c87e13b0fc8b528d0f94fd9feed22 Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Sat, 8 Jul 2023 23:47:41 -0400 Subject: region move: Implement % move --- virtual-programs/regions.folk | 44 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) (limited to 'virtual-programs') diff --git a/virtual-programs/regions.folk b/virtual-programs/regions.folk index 343ffe03..7f16196c 100644 --- a/virtual-programs/regions.folk +++ b/virtual-programs/regions.folk @@ -41,6 +41,31 @@ namespace eval ::region { expr {[llength $r] >= 3 ? [lindex $r 2] : 0} } + proc width {r} { + set minXp 100000 + set maxXp -100000 + set theta [angle $r] + foreach v [vertices $r] { + lassign $v x y + set xp [expr {$x*cos($theta) + $y*sin($theta)}] + if {$xp < $minXp} { set minXp $xp } + if {$xp > $maxXp} { set maxXp $xp } + } + expr { $maxXp - $minXp } + } + proc height {r} { + set minYp 100000 + set maxYp -100000 + set theta [angle $r] + foreach v [vertices $r] { + lassign $v x y + set yp [expr {-$x*sin($theta) + $y*cos($theta)}] + if {$yp < $minYp} { set minYp $yp } + if {$yp > $maxYp} { set maxYp $yp } + } + expr { $maxYp - $minYp } + } + proc mapVertices {varname r body} { lreplace $r 0 0 [uplevel [list lmap $varname [vertices $r] $body]] } @@ -85,8 +110,7 @@ namespace eval ::region { vec2 scale 0.25 $vecsum } - # Utilities that transform regions while preserving center - proc clip {r args} { + proc scale {r args} { foreach {property value} $args { if {$property eq "width"} { @@ -95,15 +119,27 @@ namespace eval ::region { } else { error "region clip: Invalid property $property" } + + # TODO: Support % + # TODO: Support scale-all + set r [mapVertices v $r {vec2 add $v $dv}] } } proc move {r args} { set angle [angle $r] - # FIXME: This one should work on any region -- just map over vertices. + # This one should work on any region -- just map over vertices. foreach {direction distance} $args { - if {![regexp {([0-9]+)px} $distance -> distance]} { + if {![regexp {([0-9]+)(px|%)} $distance -> distance unit]} { error "region move: Invalid distance $distance" } + if {$unit eq "%"} { + # Convert to pixels + if {$direction eq "left" || $direction eq "right"} { + set distance [expr {[width $r] * $distance * 0.01}] + } elseif {$direction eq "up" || $direction eq "down"} { + set distance [expr {[height $r] * $distance * 0.01}] + } + } set dx [if {$direction eq "left"} {- $distance} \ elseif {$direction eq "right"} {+ $distance} \ else {+ 0}] -- cgit v1.2.3 From c32138b1e24e0a578d3c9ed3f5c80f93838fa529 Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Sun, 9 Jul 2023 12:53:51 -0400 Subject: Start on `region scale` --- virtual-programs/regions.folk | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) (limited to 'virtual-programs') diff --git a/virtual-programs/regions.folk b/virtual-programs/regions.folk index 7f16196c..67d9bf47 100644 --- a/virtual-programs/regions.folk +++ b/virtual-programs/regions.folk @@ -111,20 +111,36 @@ namespace eval ::region { } proc scale {r args} { - foreach {property value} $args { - if {$property eq "width"} { - - } elseif {$property eq "height"} { - + set theta [angle $r] + foreach {dim value} $args { + if {![regexp {([0-9]+)(px|%)} $value -> value unit]} { + error "region scale: Invalid scale value $value" + } + + set sxp 1; set syp 1 + if {$dim eq "width"} { + if {$unit eq "px"} { + set sxp [/ $value [width $r]] + } elseif {$unit eq "%"} { + set sxp [* $value 0.01] + } + } elseif {$dim eq "height"} { + if {$unit eq "px"} { + set syp [/ $value [height $r]] + } elseif {$unit eq "%"} { + set syp [* $value 0.01] + } } else { - error "region clip: Invalid property $property" + error "region scale: Invalid dimension $dim" } - # TODO: Support % - # TODO: Support scale-all - set r [mapVertices v $r {vec2 add $v $dv}] + set sx [expr {$sxp*cos(-$theta) + $syp*sin(-$theta)}] + set sy [expr {-$sxp*sin(-$theta) + $syp*cos(-$theta)}] + set r [mapVertices v $r {list [* $sx [lindex $v 0]] [* $sy [lindex $v 1]]}] } + set r } + proc move {r args} { set angle [angle $r] # This one should work on any region -- just map over vertices. -- cgit v1.2.3 From b753eb633d9b78c2c730eabf0083c56114ee0568 Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Sun, 9 Jul 2023 13:21:58 -0400 Subject: region scale: Finish --- virtual-programs/regions.folk | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'virtual-programs') diff --git a/virtual-programs/regions.folk b/virtual-programs/regions.folk index 67d9bf47..7220ee25 100644 --- a/virtual-programs/regions.folk +++ b/virtual-programs/regions.folk @@ -112,6 +112,10 @@ namespace eval ::region { proc scale {r args} { set theta [angle $r] + lassign [centroid $r] cx cy + if {[llength $args] == 1} { + set args [list width [lindex $args 0] height [lindex $args 0]] + } foreach {dim value} $args { if {![regexp {([0-9]+)(px|%)} $value -> value unit]} { error "region scale: Invalid scale value $value" @@ -136,7 +140,13 @@ namespace eval ::region { set sx [expr {$sxp*cos(-$theta) + $syp*sin(-$theta)}] set sy [expr {-$sxp*sin(-$theta) + $syp*cos(-$theta)}] - set r [mapVertices v $r {list [* $sx [lindex $v 0]] [* $sy [lindex $v 1]]}] + set r [mapVertices v $r { + lassign $v x y + set x [- $x $cx]; set y [- $y $cy] + set x [* $x $sx]; set y [* $y $sy] + set x [+ $x $cx]; set y [+ $y $cy] + list $x $y + }] } set r } -- cgit v1.2.3 From 30cc6de1c30764145778119cb098c32b30a56e4e Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Sun, 9 Jul 2023 13:57:51 -0400 Subject: Implement whisker using region stuff; document region stuff --- virtual-programs/points-at.folk | 50 ++++++++++++----------------------------- virtual-programs/regions.folk | 14 ++++++++++-- 2 files changed, 26 insertions(+), 38 deletions(-) (limited to 'virtual-programs') diff --git a/virtual-programs/points-at.folk b/virtual-programs/points-at.folk index 5c79cf1e..b0937495 100644 --- a/virtual-programs/points-at.folk +++ b/virtual-programs/points-at.folk @@ -1,50 +1,28 @@ -set pi 3.1415926535897931 - When when /rect/ points /direction/ at /someone/ /lambda/ with environment /e/ { Wish $rect points $direction } When /someone/ wishes /rect/ points /direction/ & /rect/ has region /region/ { - lassign $region vertices edges - lassign $vertices a b c d - - set cx [expr {([lindex $a 0] + [lindex $c 0])/2}] - set cy [expr {([lindex $a 1] + [lindex $c 1])/2}] - - set width [vec2 distance $a $b] - set height [vec2 distance $a $d] - - set radians [lindex $region 2] - if {$radians eq ""} {set radians 0} - - set whisker_radians $radians - set fac -1.0 - set whisker_size [expr {$width * $fac}] - set color green - if {$direction eq "up"} { - set whisker_radians [expr {$radians + $pi / 2}] - set whisker_size [expr {$height * $fac}] + set whiskerRegion [region move [region scale $region width 0.01px] up 50%] set color blue - } - if {$direction eq "left"} { - set whisker_radians [expr {$radians + $pi}] + } elseif {$direction eq "left"} { + set whiskerRegion [region move [region scale $region height 0.01px] left 50%] set color red - } - if {$direction eq "down"} { - set whisker_radians [expr {$radians + $pi * 1.5}] - set whisker_size [expr {$height * $fac}] + } elseif {$direction eq "right"} { + set whiskerRegion [region move [region scale $region height 0.01px] right 50%] + set color green + } elseif {$direction eq "down"} { + set whiskerRegion [region move [region scale $region width 0.01px] down 50%] set color white - } - - set wx [expr {$cx + $whisker_size * [::tcl::mathfunc::cos [expr {-1 * $whisker_radians}]] }] - set wy [expr {$cy + $whisker_size * [::tcl::mathfunc::sin [expr {-1 * $whisker_radians}]] }] - - Display::stroke [list [list $cx $cy] [list $wx $wy] ] 4 $color + } + set whisker [list $rect whisker $direction] + Claim $whisker has region $whiskerRegion + Wish $whisker is outlined $color When /target/ has region /r2/ { - if {$target != $rect && \ - [region contains $r2 [list $wx $wy]]} { + if {$target != $rect && $target != $whisker && \ + [region intersects $whiskerRegion $r2]} { Claim $rect points $direction at $target } } diff --git a/virtual-programs/regions.folk b/virtual-programs/regions.folk index 7220ee25..f0a7347d 100644 --- a/virtual-programs/regions.folk +++ b/virtual-programs/regions.folk @@ -98,7 +98,14 @@ namespace eval ::region { 0 <= $dot_bcbp && $dot_bcbp <= [vec2 dot $bc $bc]} } proc intersects {r1 r2} { - # FIXME: implement + # Either r1 should contain a vertex of r2 or r2 should contain a vertex of r1 + foreach v1 [vertices $r1] { + if {[contains $r2 $v1]} { return true } + } + foreach v2 [vertices $r2] { + if {[contains $r1 $v2]} { return true } + } + expr false } proc centroid {r1} { @@ -110,6 +117,8 @@ namespace eval ::region { vec2 scale 0.25 $vecsum } + # Scales about the center of the region, along the x and y axes of + # the space of the region (not the global x and y). proc scale {r args} { set theta [angle $r] lassign [centroid $r] cx cy @@ -151,9 +160,10 @@ namespace eval ::region { set r } + # Moves the region left/right/up/down along the x and y axes of + # the space of the region (not the global x and y). proc move {r args} { set angle [angle $r] - # This one should work on any region -- just map over vertices. foreach {direction distance} $args { if {![regexp {([0-9]+)(px|%)} $distance -> distance unit]} { error "region move: Invalid distance $distance" -- cgit v1.2.3 From daf74752ca1aee57b56dfc71412ad24b2e7603ad Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Sun, 9 Jul 2023 15:54:37 -0400 Subject: Fix `region scale` for rotated regions Flip arg order for `vec2 scale`, add support for individual x/y scale --- virtual-programs/regions.folk | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) (limited to 'virtual-programs') diff --git a/virtual-programs/regions.folk b/virtual-programs/regions.folk index f0a7347d..10684a59 100644 --- a/virtual-programs/regions.folk +++ b/virtual-programs/regions.folk @@ -5,8 +5,18 @@ namespace eval ::vec2 { proc sub {a b} { list [- [lindex $a 0] [lindex $b 0]] [- [lindex $a 1] [lindex $b 1]] } - proc scale {s a} { - list [* $s [lindex $a 0]] [* $s [lindex $a 1]] + proc scale {a args} { + if {[llength $args] == 1} { + set sx [lindex $args 0]; set sy [lindex $args 0] + } else { + lassign $args sx sy + } + list [* [lindex $a 0] $sx] [* [lindex $a 1] $sy] + } + proc rotate {a theta} { + lassign $a x y + list [expr {$x*cos($theta) - $y*sin($theta)}] \ + [expr {$x*sin($theta) + $y*cos($theta)}] } proc distance {a b} { lassign $a ax ay @@ -114,14 +124,14 @@ namespace eval ::region { lassign $vertices a b c d set vecsum [vec2 add [vec2 add [vec2 add $a $b] $c] $d] - vec2 scale 0.25 $vecsum + vec2 scale $vecsum 0.25 } # Scales about the center of the region, along the x and y axes of # the space of the region (not the global x and y). proc scale {r args} { set theta [angle $r] - lassign [centroid $r] cx cy + set c [centroid $r] if {[llength $args] == 1} { set args [list width [lindex $args 0] height [lindex $args 0]] } @@ -147,14 +157,13 @@ namespace eval ::region { error "region scale: Invalid dimension $dim" } - set sx [expr {$sxp*cos(-$theta) + $syp*sin(-$theta)}] - set sy [expr {-$sxp*sin(-$theta) + $syp*cos(-$theta)}] set r [mapVertices v $r { - lassign $v x y - set x [- $x $cx]; set y [- $y $cy] - set x [* $x $sx]; set y [* $y $sy] - set x [+ $x $cx]; set y [+ $y $cy] - list $x $y + set v [vec2 sub $v $c] + set v [vec2 rotate $v [* -1 $theta]] + set v [vec2 scale $v $sxp $syp] + set v [vec2 rotate $v $theta] + set v [vec2 add $v $c] + set v }] } set r -- cgit v1.2.3 From ba97d2928ec3d15f2baacd41e3e8455b81b5932f Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Sun, 9 Jul 2023 16:26:28 -0400 Subject: Implement `region rotate` helper --- virtual-programs/regions.folk | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'virtual-programs') diff --git a/virtual-programs/regions.folk b/virtual-programs/regions.folk index 10684a59..b1cf45a0 100644 --- a/virtual-programs/regions.folk +++ b/virtual-programs/regions.folk @@ -127,6 +127,17 @@ namespace eval ::region { vec2 scale $vecsum 0.25 } + proc rotate {r angle} { + set theta [angle $r] + set c [centroid $r] + mapVertices v $r { + set v [vec2 sub $v $c] + set v [vec2 rotate $v $angle] + set v [vec2 add $v $c] + set v + } + } + # Scales about the center of the region, along the x and y axes of # the space of the region (not the global x and y). proc scale {r args} { -- cgit v1.2.3 From 26266ab14c2c24632aeedc7b1b129b1bee0f32db Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Sun, 9 Jul 2023 18:27:08 -0400 Subject: Fix region and vec2 rotate --- virtual-programs/regions.folk | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'virtual-programs') diff --git a/virtual-programs/regions.folk b/virtual-programs/regions.folk index b1cf45a0..0e261b34 100644 --- a/virtual-programs/regions.folk +++ b/virtual-programs/regions.folk @@ -15,8 +15,8 @@ namespace eval ::vec2 { } proc rotate {a theta} { lassign $a x y - list [expr {$x*cos($theta) - $y*sin($theta)}] \ - [expr {$x*sin($theta) + $y*cos($theta)}] + list [expr {$x*cos($theta) + $y*sin($theta)}] \ + [expr {-$x*sin($theta) + $y*cos($theta)}] } proc distance {a b} { lassign $a ax ay @@ -130,12 +130,14 @@ namespace eval ::region { proc rotate {r angle} { set theta [angle $r] set c [centroid $r] - mapVertices v $r { + set r' [mapVertices v $r { set v [vec2 sub $v $c] set v [vec2 rotate $v $angle] set v [vec2 add $v $c] set v - } + }] + lset r' 2 [+ $theta $angle] + set r' } # Scales about the center of the region, along the x and y axes of -- cgit v1.2.3 From e65ed488a28438434adab878d1fcf8f0eb71aaff Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Sun, 9 Jul 2023 19:28:25 -0400 Subject: Fix `region move/scale/width/height` for rotated regions --- virtual-programs/regions.folk | 39 +++++++++++++++------------------------ 1 file changed, 15 insertions(+), 24 deletions(-) (limited to 'virtual-programs') diff --git a/virtual-programs/regions.folk b/virtual-programs/regions.folk index 0e261b34..9cec956d 100644 --- a/virtual-programs/regions.folk +++ b/virtual-programs/regions.folk @@ -54,10 +54,8 @@ namespace eval ::region { proc width {r} { set minXp 100000 set maxXp -100000 - set theta [angle $r] - foreach v [vertices $r] { - lassign $v x y - set xp [expr {$x*cos($theta) + $y*sin($theta)}] + foreach v [vertices [rotate $r [* -1 [angle $r]]]] { + lassign $v xp yp if {$xp < $minXp} { set minXp $xp } if {$xp > $maxXp} { set maxXp $xp } } @@ -66,10 +64,8 @@ namespace eval ::region { proc height {r} { set minYp 100000 set maxYp -100000 - set theta [angle $r] - foreach v [vertices $r] { - lassign $v x y - set yp [expr {-$x*sin($theta) + $y*cos($theta)}] + foreach v [vertices [rotate $r [* -1 [angle $r]]]] { + lassign $v xp yp if {$yp < $minYp} { set minYp $yp } if {$yp > $maxYp} { set maxYp $yp } } @@ -170,6 +166,7 @@ namespace eval ::region { error "region scale: Invalid dimension $dim" } + # TODO: Optimize set r [mapVertices v $r { set v [vec2 sub $v $c] set v [vec2 rotate $v [* -1 $theta]] @@ -185,7 +182,8 @@ namespace eval ::region { # Moves the region left/right/up/down along the x and y axes of # the space of the region (not the global x and y). proc move {r args} { - set angle [angle $r] + set theta [angle $r] + set c [centroid $r] foreach {direction distance} $args { if {![regexp {([0-9]+)(px|%)} $distance -> distance unit]} { error "region move: Invalid distance $distance" @@ -198,23 +196,16 @@ namespace eval ::region { set distance [expr {[height $r] * $distance * 0.01}] } } - set dx [if {$direction eq "left"} {- $distance} \ - elseif {$direction eq "right"} {+ $distance} \ - else {+ 0}] - set dy [if {$direction eq "up"} {- $distance} \ - elseif {$direction eq "down"} {+ $distance} \ - else {+ 0}] - if {$dx == 0 && $dy == 0} { + set dxp [if {$direction eq "left"} {- $distance} \ + elseif {$direction eq "right"} {+ $distance} \ + else {+ 0}] + set dyp [if {$direction eq "up"} {- $distance} \ + elseif {$direction eq "down"} {+ $distance} \ + else {+ 0}] + if {$dxp == 0 && $dyp == 0} { error "region move: Invalid direction $direction" } - - # Translate dx and dy into polar coordinates. - set theta [atan2 $dy $dx] - set mag [hypot $dy $dx] - - # Rotate dx and dy into the global coordinate space. - set dv [list [expr {$mag*cos($theta)}] [expr {$mag*sin($theta)}]] - + set dv [vec2 rotate [list $dxp $dyp] $theta] set r [mapVertices v $r {vec2 add $v $dv}] } set r -- cgit v1.2.3 From 0836a03dd737ed40dfc72db218662161875103c6 Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Mon, 10 Jul 2023 02:30:04 -0400 Subject: Fix tag region angles, get rid of rectangle claim --- virtual-programs/tags-and-calibration.folk | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'virtual-programs') diff --git a/virtual-programs/tags-and-calibration.folk b/virtual-programs/tags-and-calibration.folk index cf252de6..f6f78b67 100644 --- a/virtual-programs/tags-and-calibration.folk +++ b/virtual-programs/tags-and-calibration.folk @@ -76,9 +76,6 @@ proc ::projectorToCamera {projectorPoint} { When (non-capturing) tag /tag/ has center /c/ size /size/ { Claim tag $tag is a tag - - lassign [::cameraToProjector $c] px py - Claim $tag is a rectangle with x [expr $px-20] y [expr $py-10] width [expr $size*2] height [expr $size*2] } When (non-capturing) tag /tag/ is a tag { @@ -116,7 +113,8 @@ When (non-capturing) tag /tag/ has corners /corners/ { } lappend edges [list [expr {[llength $corners] - 1}] 0] - set region [list $corners $edges [::tcl::mathfunc::atan2 {*}$vecRight]] + set angle [atan2 [lindex $vecBottom 1] [lindex $vecBottom 0]] + set region [list $corners $edges $angle] Claim $tag has region $region } -- cgit v1.2.3 From 7b67ece913f8e852856260818428cbb9ac1bacad Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Mon, 10 Jul 2023 03:04:59 -0400 Subject: Fix uspidedown with new angles --- virtual-programs/label.folk | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'virtual-programs') diff --git a/virtual-programs/label.folk b/virtual-programs/label.folk index d18bdd02..eeaaf143 100644 --- a/virtual-programs/label.folk +++ b/virtual-programs/label.folk @@ -5,16 +5,8 @@ When /thing/ has region /region/ { set height [boxHeight $bbox] - set radians [lindex $region 2] - if {$radians eq ""} {set radians 0} - - set upsidedown [expr {abs($radians) < 1.57}] - if ($upsidedown) { - set x [expr {$x + $width * 0.4}] - set y [expr {$y - $height * 0.2}] - } else { - set x [expr {$x - $width * 0.4}] - } + set radians [region angle $region] + set upsidedown [expr {$radians > 1.57 || $radians < -1.57}] if {$::isLaptop} {set upsidedown false} When the collected matches for [list /someone/ wishes $thing is labelled /text/] are /matches/ { -- cgit v1.2.3 From a4bf38f97bf727ed0defc07080df9ab656703139 Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Mon, 10 Jul 2023 03:34:15 -0400 Subject: Move dep stuff to math.tcl, fix angle impl --- virtual-programs/regions.folk | 217 ----------------------------- virtual-programs/tags-and-calibration.folk | 2 +- 2 files changed, 1 insertion(+), 218 deletions(-) (limited to 'virtual-programs') diff --git a/virtual-programs/regions.folk b/virtual-programs/regions.folk index 9cec956d..5de19b98 100644 --- a/virtual-programs/regions.folk +++ b/virtual-programs/regions.folk @@ -1,220 +1,3 @@ -namespace eval ::vec2 { - proc add {a b} { - list [+ [lindex $a 0] [lindex $b 0]] [+ [lindex $a 1] [lindex $b 1]] - } - proc sub {a b} { - list [- [lindex $a 0] [lindex $b 0]] [- [lindex $a 1] [lindex $b 1]] - } - proc scale {a args} { - if {[llength $args] == 1} { - set sx [lindex $args 0]; set sy [lindex $args 0] - } else { - lassign $args sx sy - } - list [* [lindex $a 0] $sx] [* [lindex $a 1] $sy] - } - proc rotate {a theta} { - lassign $a x y - list [expr {$x*cos($theta) + $y*sin($theta)}] \ - [expr {-$x*sin($theta) + $y*cos($theta)}] - } - proc distance {a b} { - lassign $a ax ay - lassign $b bx by - expr {sqrt(pow($ax-$bx, 2) + pow($ay-$by, 2))} - } - proc normalize {a} { - set l2 [vec2 distance $a [list 0 0]] - vec2 scale [/ 1 $l2] $a - } - proc dot {a b} { - expr {[lindex $a 0]*[lindex $b 0] + [lindex $a 1]*[lindex $b 1]} - } - proc distanceToLineSegment {a v w} { - set l2 [vec2 distance $v $w] - if {$l2 == 0.0} { - return [distance $a $v] - } - set t [max 0 [min 1 [/ [dot [sub $a $v] [sub $w $v]] $l2]]] - set proj [add $v [scale $t [sub $w $v]]] - vec2 distance $a $proj - } - namespace export * - namespace ensemble create -} - -namespace eval ::region { - proc vertices {r} { lindex $r 0 } - proc edges {r} { lindex $r 1 } - # Angle the region is rotated above the horizontal, in radians: - proc angle {r} { - expr {[llength $r] >= 3 ? [lindex $r 2] : 0} - } - - proc width {r} { - set minXp 100000 - set maxXp -100000 - foreach v [vertices [rotate $r [* -1 [angle $r]]]] { - lassign $v xp yp - if {$xp < $minXp} { set minXp $xp } - if {$xp > $maxXp} { set maxXp $xp } - } - expr { $maxXp - $minXp } - } - proc height {r} { - set minYp 100000 - set maxYp -100000 - foreach v [vertices [rotate $r [* -1 [angle $r]]]] { - lassign $v xp yp - if {$yp < $minYp} { set minYp $yp } - if {$yp > $maxYp} { set maxYp $yp } - } - expr { $maxYp - $minYp } - } - - proc mapVertices {varname r body} { - lreplace $r 0 0 [uplevel [list lmap $varname [vertices $r] $body]] - } - - proc edgeToLineSegment {r e} { - list [lindex [vertices $r] [lindex $e 0]] [lindex [vertices $r] [lindex $e 1]] - } - proc distance {r1 r2} { - puts $r2 - set minDist 1e9 - foreach v1 [vertices $r1] e2 [edges $r2] { - set dist [vec2 distanceToLineSegment $v1 {*}[edgeToLineSegment $r2 $e2]] - if {$dist < $minDist} { set minDist $dist } - } - set minDist - } - - proc contains {r1 p} { - lassign $r1 vertices edges - lassign $vertices a b c d - - set ab [vec2 sub $b $a] - set ap [vec2 sub $p $a] - set bc [vec2 sub $c $b] - set bp [vec2 sub $p $b] - set dot_abap [vec2 dot $ab $ap] - set dot_bcbp [vec2 dot $bc $bp] - - expr {0 <= $dot_abap && $dot_abap <= [vec2 dot $ab $ab] && \ - 0 <= $dot_bcbp && $dot_bcbp <= [vec2 dot $bc $bc]} - } - proc intersects {r1 r2} { - # Either r1 should contain a vertex of r2 or r2 should contain a vertex of r1 - foreach v1 [vertices $r1] { - if {[contains $r2 $v1]} { return true } - } - foreach v2 [vertices $r2] { - if {[contains $r1 $v2]} { return true } - } - expr false - } - - proc centroid {r1} { - # This only works for rectangular regions - lassign $r1 vertices edges - lassign $vertices a b c d - - set vecsum [vec2 add [vec2 add [vec2 add $a $b] $c] $d] - vec2 scale $vecsum 0.25 - } - - proc rotate {r angle} { - set theta [angle $r] - set c [centroid $r] - set r' [mapVertices v $r { - set v [vec2 sub $v $c] - set v [vec2 rotate $v $angle] - set v [vec2 add $v $c] - set v - }] - lset r' 2 [+ $theta $angle] - set r' - } - - # Scales about the center of the region, along the x and y axes of - # the space of the region (not the global x and y). - proc scale {r args} { - set theta [angle $r] - set c [centroid $r] - if {[llength $args] == 1} { - set args [list width [lindex $args 0] height [lindex $args 0]] - } - foreach {dim value} $args { - if {![regexp {([0-9]+)(px|%)} $value -> value unit]} { - error "region scale: Invalid scale value $value" - } - - set sxp 1; set syp 1 - if {$dim eq "width"} { - if {$unit eq "px"} { - set sxp [/ $value [width $r]] - } elseif {$unit eq "%"} { - set sxp [* $value 0.01] - } - } elseif {$dim eq "height"} { - if {$unit eq "px"} { - set syp [/ $value [height $r]] - } elseif {$unit eq "%"} { - set syp [* $value 0.01] - } - } else { - error "region scale: Invalid dimension $dim" - } - - # TODO: Optimize - set r [mapVertices v $r { - set v [vec2 sub $v $c] - set v [vec2 rotate $v [* -1 $theta]] - set v [vec2 scale $v $sxp $syp] - set v [vec2 rotate $v $theta] - set v [vec2 add $v $c] - set v - }] - } - set r - } - - # Moves the region left/right/up/down along the x and y axes of - # the space of the region (not the global x and y). - proc move {r args} { - set theta [angle $r] - set c [centroid $r] - foreach {direction distance} $args { - if {![regexp {([0-9]+)(px|%)} $distance -> distance unit]} { - error "region move: Invalid distance $distance" - } - if {$unit eq "%"} { - # Convert to pixels - if {$direction eq "left" || $direction eq "right"} { - set distance [expr {[width $r] * $distance * 0.01}] - } elseif {$direction eq "up" || $direction eq "down"} { - set distance [expr {[height $r] * $distance * 0.01}] - } - } - set dxp [if {$direction eq "left"} {- $distance} \ - elseif {$direction eq "right"} {+ $distance} \ - else {+ 0}] - set dyp [if {$direction eq "up"} {- $distance} \ - elseif {$direction eq "down"} {+ $distance} \ - else {+ 0}] - if {$dxp == 0 && $dyp == 0} { - error "region move: Invalid direction $direction" - } - set dv [vec2 rotate [list $dxp $dyp] $theta] - set r [mapVertices v $r {vec2 add $v $dv}] - } - set r - } - - namespace export * - namespace ensemble create -} - When when the distance between /p1/ and /p2/ is /distanceVar/ /body/ with environment /e/ & /p1/ has region /r1/ & /p2/ has region /r2/ { Claim the distance between $p1 and $p2 is [region distance $r1 $r2] } diff --git a/virtual-programs/tags-and-calibration.folk b/virtual-programs/tags-and-calibration.folk index f6f78b67..2ad6cb59 100644 --- a/virtual-programs/tags-and-calibration.folk +++ b/virtual-programs/tags-and-calibration.folk @@ -113,7 +113,7 @@ When (non-capturing) tag /tag/ has corners /corners/ { } lappend edges [list [expr {[llength $corners] - 1}] 0] - set angle [atan2 [lindex $vecBottom 1] [lindex $vecBottom 0]] + set angle [expr {atan2(-[lindex $vecBottom 1], [lindex $vecBottom 0])}] set region [list $corners $edges $angle] Claim $tag has region $region -- cgit v1.2.3 From dcfc86c3ec495ea92e59fb5422b4b019c50a6384 Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Mon, 10 Jul 2023 03:35:47 -0400 Subject: Fix error reporting --- virtual-programs/new-program-web-editor.folk | 2 +- virtual-programs/web-editor.folk | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'virtual-programs') diff --git a/virtual-programs/new-program-web-editor.folk b/virtual-programs/new-program-web-editor.folk index 5797365b..305dde8f 100644 --- a/virtual-programs/new-program-web-editor.folk +++ b/virtual-programs/new-program-web-editor.folk @@ -155,7 +155,7 @@ Wish the web server handles route "/new" with handler { setTimeout(() => { send(` set errors [Statements::findMatches [list {${program}} has error /err/ with info /errorInfo/]] -join [list "Error:" {*}[lmap e $errors {dict get $e errorInfo}]] "\n" +::websocket::send $chan text [join [list "Error:" {*}[lmap e $errors {dict get $e errorInfo}]] "\n"] `); }, 500); } diff --git a/virtual-programs/web-editor.folk b/virtual-programs/web-editor.folk index ae14f9b4..245b6043 100644 --- a/virtual-programs/web-editor.folk +++ b/virtual-programs/web-editor.folk @@ -100,7 +100,7 @@ Wish the web server handles route {/page/(.*)$} with handler { setTimeout(() => { send(` set errors [Statements::findMatches [list program_id has error /err/ with info /errorInfo/]] -join [list "Error:" {*}[lmap e $errors {dict get $e errorInfo}]] "\n" +::websocket::send $chan text [join [list "Error:" {*}[lmap e $errors {dict get $e errorInfo}]] "\n"] `); }, 500); } -- cgit v1.2.3 From 7de278406eb1488f5bee5e12337de6443cf4c371 Mon Sep 17 00:00:00 2001 From: Omar Rizwan Date: Mon, 10 Jul 2023 13:10:34 -0400 Subject: Hack to prevent multiple whiskers intersecting --- virtual-programs/points-at.folk | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'virtual-programs') diff --git a/virtual-programs/points-at.folk b/virtual-programs/points-at.folk index b0937495..773d42b3 100644 --- a/virtual-programs/points-at.folk +++ b/virtual-programs/points-at.folk @@ -4,16 +4,16 @@ When when /rect/ points /direction/ at /someone/ /lambda/ with environment /e/ { When /someone/ wishes /rect/ points /direction/ & /rect/ has region /region/ { if {$direction eq "up"} { - set whiskerRegion [region move [region scale $region width 0.01px] up 50%] + set whiskerRegion [region move [region scale $region width 0.01px] up 51%] set color blue } elseif {$direction eq "left"} { - set whiskerRegion [region move [region scale $region height 0.01px] left 50%] + set whiskerRegion [region move [region scale $region height 0.01px] left 51%] set color red } elseif {$direction eq "right"} { - set whiskerRegion [region move [region scale $region height 0.01px] right 50%] + set whiskerRegion [region move [region scale $region height 0.01px] right 51%] set color green } elseif {$direction eq "down"} { - set whiskerRegion [region move [region scale $region width 0.01px] down 50%] + set whiskerRegion [region move [region scale $region width 0.01px] down 51%] set color white } set whisker [list $rect whisker $direction] -- cgit v1.2.3