From 547fc34fc22b1467e8b9214689af342d6c59e532 Mon Sep 17 00:00:00 2001 From: Mason Jones <20848827+smj-edison@users.noreply.github.com> Date: Fri, 28 Aug 2026 15:31:40 -0600 Subject: [PATCH 1/5] Add tagged points --- builtin-programs/quad-lib.folk | 88 +++++++++++++++++++++++++++++----- 1 file changed, 77 insertions(+), 11 deletions(-) diff --git a/builtin-programs/quad-lib.folk b/builtin-programs/quad-lib.folk index 60c3e829..e361e2de 100644 --- a/builtin-programs/quad-lib.folk +++ b/builtin-programs/quad-lib.folk @@ -10,16 +10,65 @@ set quadLib [library create quadLib {} { ::math::linearalgebra::scale rename scale scaleVector + ## Points + + proc surfacePointInner {id x y} { + return [list surface-point $id $x $y] + } + + proc surfacePoint {x y} { + upvar this this + return [surfacePointInner $this $x $y] + } + + proc surfacePointCheckType {surfacePoint} { + set type [lindex $surfacePoint 0] + if {$type ne "surface-point"} { error "expected type "surface-point", but got \"$type\""} + } + + proc surfacePointVector {surfacePoint} { + surfacePointCheckType $surfacePoint + return [lrange $surfacePoint 2 end] + } + + proc surfacePointId {surfacePoint} { + surfacePointCheckType $surfacePoint + return [lindex $surfacePoint 1] + } + + proc 3dPoint {space x y z} { + return [list 3d-point $space $x $y $z] + } + + proc 3dPointCheckType {3dPoint} { + set type [lindex $3dPoint 0] + if {$type ne "3d-point"} { error "expected type "3d-point", but got \"$type\""} + } + + proc 3dPointVector {3dPoint} { + 3dPointCheckType $3dPoint + return [lrange $3dPoint 2 end] + } + + proc 3dPointSpace {3dPoint} { + 3dPointCheckType $3dPoint + return [lindex $3dPoint 1] + } + + ## Quads + proc create {space vertices} { list $space $vertices } proc space {q} { lindex $q 0 } proc vertices {q} { lindex $q 1 } - # Returns an {x y z} point in the space of the quad. + # Returns an 3d point in the space of the quad. proc centroid {q} { + set quadSpace [space $q] lassign [vertices $q] topLeft topRight bottomRight bottomLeft - return [::math::linearalgebra::scale 0.25 \ + # Average the four points. + return [3dPoint $quadSpace [scaleVector 0.25 \ [add [add $topLeft $bottomRight] \ - [add $topRight $bottomLeft]]] + [add $topRight $bottomLeft]]]] } # Scales about the centroid of the quad, along the width and height @@ -65,7 +114,7 @@ set quadLib [library create quadLib {} { } } - set c [centroid $q] + set c [3dPointVector [centroid $q]] # Calculate width and height vectors from the quad's actual orientation # Width goes from left to right (topLeft -> topRight, bottomLeft -> bottomRight) @@ -230,11 +279,29 @@ set quadLib [library create quadLib {} { return [create [space $q] [list $topLeft $topRight $bottomRight $bottomLeft]] } + proc surfacePointTo3dPoint {surfacePoint quad} { + lassign [surfacePointVector $surfacePoint] x y + lassign [vertices $quad] topLeft topRight bottomRight bottomLeft + set width [norm [sub $topRight $topLeft]] + set height [norm [sub $bottomLeft $topLeft]] + + set xAxis [unitLengthVector [sub $topRight $topLeft]] + set yAxis [unitLengthVector [sub $bottomLeft $topLeft]] + set pointRelativeToTopLeft [add [scale $xAxis x] \ + [scale $yAxis y]] + return [3dPoint [space $quad] {*}[add $pointRelativeToTopLeft $topLeft]] + } + # Take a {x y z} point in the same space as the quad and project # it down onto a {top left} point on the quad (that can be used in # the drawing APIs, etc). - proc pointToXY {q xyz {checkBounds true}} { - lassign [vertices $q] topLeft topRight bottomRight bottomLeft + proc 3dPointToSurfacePoint {3dPoint targetId targetQuad {checkBounds true}} { + set pointSpace [3dPointSpace $3dPoint] + set quadSpace [space $targetQuad] + if {$pointSpace ne $quadSpace} { error "spaces $pointSpace and $quadSpace disagree" } + set xyz [3dPointVector $3dPoint] + + lassign [vertices $targetQuad] topLeft topRight bottomRight bottomLeft set width [norm [sub $topRight $topLeft]] set height [norm [sub $bottomLeft $topLeft]] set xAxis [unitLengthVector [sub $topRight $topLeft]] @@ -244,14 +311,13 @@ set quadLib [library create quadLib {} { set y [dotproduct $delta $yAxis] set eps 0.000001 - if {$x < -$eps || $x > $width + $eps || + if {$checkBounds && + $x < -$eps || $x > $width + $eps || $y < -$eps || $y > $height + $eps} { - if {$checkBounds} { - error "quad pointToXY: point $xyz projects outside quad bounds as {$x $y}; bounds are {0 0} {$width $height}" - } + error "quad pointToXY: point $xyz projects outside quad bounds as {$x $y}; bounds are {0 0} {$width $height}" } - return [list $x $y] + return [surfacePointInner $targetId $x $y] } }] Claim the quad library is $quadLib From 90cab8bf416857c9ba269d6e02209abbec6f3369 Mon Sep 17 00:00:00 2001 From: Mason Jones <20848827+smj-edison@users.noreply.github.com> Date: Fri, 28 Aug 2026 21:23:18 -0600 Subject: [PATCH 2/5] Undo quad-lib changes for now, I think it'll be better in a separate points-lib that contains its own behavior --- builtin-programs/quad-lib.folk | 88 +++++----------------------------- 1 file changed, 11 insertions(+), 77 deletions(-) diff --git a/builtin-programs/quad-lib.folk b/builtin-programs/quad-lib.folk index e361e2de..60c3e829 100644 --- a/builtin-programs/quad-lib.folk +++ b/builtin-programs/quad-lib.folk @@ -10,65 +10,16 @@ set quadLib [library create quadLib {} { ::math::linearalgebra::scale rename scale scaleVector - ## Points - - proc surfacePointInner {id x y} { - return [list surface-point $id $x $y] - } - - proc surfacePoint {x y} { - upvar this this - return [surfacePointInner $this $x $y] - } - - proc surfacePointCheckType {surfacePoint} { - set type [lindex $surfacePoint 0] - if {$type ne "surface-point"} { error "expected type "surface-point", but got \"$type\""} - } - - proc surfacePointVector {surfacePoint} { - surfacePointCheckType $surfacePoint - return [lrange $surfacePoint 2 end] - } - - proc surfacePointId {surfacePoint} { - surfacePointCheckType $surfacePoint - return [lindex $surfacePoint 1] - } - - proc 3dPoint {space x y z} { - return [list 3d-point $space $x $y $z] - } - - proc 3dPointCheckType {3dPoint} { - set type [lindex $3dPoint 0] - if {$type ne "3d-point"} { error "expected type "3d-point", but got \"$type\""} - } - - proc 3dPointVector {3dPoint} { - 3dPointCheckType $3dPoint - return [lrange $3dPoint 2 end] - } - - proc 3dPointSpace {3dPoint} { - 3dPointCheckType $3dPoint - return [lindex $3dPoint 1] - } - - ## Quads - proc create {space vertices} { list $space $vertices } proc space {q} { lindex $q 0 } proc vertices {q} { lindex $q 1 } - # Returns an 3d point in the space of the quad. + # Returns an {x y z} point in the space of the quad. proc centroid {q} { - set quadSpace [space $q] lassign [vertices $q] topLeft topRight bottomRight bottomLeft - # Average the four points. - return [3dPoint $quadSpace [scaleVector 0.25 \ + return [::math::linearalgebra::scale 0.25 \ [add [add $topLeft $bottomRight] \ - [add $topRight $bottomLeft]]]] + [add $topRight $bottomLeft]]] } # Scales about the centroid of the quad, along the width and height @@ -114,7 +65,7 @@ set quadLib [library create quadLib {} { } } - set c [3dPointVector [centroid $q]] + set c [centroid $q] # Calculate width and height vectors from the quad's actual orientation # Width goes from left to right (topLeft -> topRight, bottomLeft -> bottomRight) @@ -279,29 +230,11 @@ set quadLib [library create quadLib {} { return [create [space $q] [list $topLeft $topRight $bottomRight $bottomLeft]] } - proc surfacePointTo3dPoint {surfacePoint quad} { - lassign [surfacePointVector $surfacePoint] x y - lassign [vertices $quad] topLeft topRight bottomRight bottomLeft - set width [norm [sub $topRight $topLeft]] - set height [norm [sub $bottomLeft $topLeft]] - - set xAxis [unitLengthVector [sub $topRight $topLeft]] - set yAxis [unitLengthVector [sub $bottomLeft $topLeft]] - set pointRelativeToTopLeft [add [scale $xAxis x] \ - [scale $yAxis y]] - return [3dPoint [space $quad] {*}[add $pointRelativeToTopLeft $topLeft]] - } - # Take a {x y z} point in the same space as the quad and project # it down onto a {top left} point on the quad (that can be used in # the drawing APIs, etc). - proc 3dPointToSurfacePoint {3dPoint targetId targetQuad {checkBounds true}} { - set pointSpace [3dPointSpace $3dPoint] - set quadSpace [space $targetQuad] - if {$pointSpace ne $quadSpace} { error "spaces $pointSpace and $quadSpace disagree" } - set xyz [3dPointVector $3dPoint] - - lassign [vertices $targetQuad] topLeft topRight bottomRight bottomLeft + proc pointToXY {q xyz {checkBounds true}} { + lassign [vertices $q] topLeft topRight bottomRight bottomLeft set width [norm [sub $topRight $topLeft]] set height [norm [sub $bottomLeft $topLeft]] set xAxis [unitLengthVector [sub $topRight $topLeft]] @@ -311,13 +244,14 @@ set quadLib [library create quadLib {} { set y [dotproduct $delta $yAxis] set eps 0.000001 - if {$checkBounds && - $x < -$eps || $x > $width + $eps || + if {$x < -$eps || $x > $width + $eps || $y < -$eps || $y > $height + $eps} { - error "quad pointToXY: point $xyz projects outside quad bounds as {$x $y}; bounds are {0 0} {$width $height}" + if {$checkBounds} { + error "quad pointToXY: point $xyz projects outside quad bounds as {$x $y}; bounds are {0 0} {$width $height}" + } } - return [surfacePointInner $targetId $x $y] + return [list $x $y] } }] Claim the quad library is $quadLib From 61d34d82787999c422eca860adc9ab184ab7562a Mon Sep 17 00:00:00 2001 From: Mason Jones <20848827+smj-edison@users.noreply.github.com> Date: Fri, 28 Aug 2026 21:23:35 -0600 Subject: [PATCH 3/5] Get the table a quad --- builtin-programs/geometric/points-at.folk | 2 +- builtin-programs/table.folk | 32 ++++++++++++++++++ builtin-programs/tags-to-quads.folk | 40 +++++++++++++++++++++++ 3 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 builtin-programs/table.folk diff --git a/builtin-programs/geometric/points-at.folk b/builtin-programs/geometric/points-at.folk index 5de70d0d..afdb22a6 100644 --- a/builtin-programs/geometric/points-at.folk +++ b/builtin-programs/geometric/points-at.folk @@ -82,7 +82,7 @@ When $rect has quad /quad/ { $to] When /target/ has quad /q2/ { - if {$target eq $rect} { return } + if {$target eq $rect || $target eq "table"} { return } set displayVertices [lmap v [$quadLib vertices [quadChange $q2 "display $disp"]] { $poseLib project $displayIntrinsics \ diff --git a/builtin-programs/table.folk b/builtin-programs/table.folk new file mode 100644 index 00000000..c80c6cde --- /dev/null +++ b/builtin-programs/table.folk @@ -0,0 +1,32 @@ +When the quad library is /quadLib/ &\ + the pose library is /poseLib/ &\ + a calibration from camera /camera/ to display /display/ is /calibration/ { + package require linalg + namespace import ::math::linearalgebra::dotproduct \ + ::math::linearalgebra::scale \ + ::math::linearalgebra::getcol + + local proc unprojectWithReferencePlane {intrinsics planeOrigin planeNormal x y} { + upvar poseLib poseLib + set width $intrinsics(width) + set height $intrinsics(height) + set ray [$poseLib unproject $intrinsics $width $height $x $y] + # Ray-plane intersection to figure out where the ray lands on the reference plane. + set z [/ [dotproduct $planeNormal $planeOrigin] [dotproduct $planeNormal $ray]] + return [scale $z $ray] + } + + set intrinsics [dict get $calibration projector intrinsics] + set width $intrinsics(width) + set height $intrinsics(height) + set extrinsics [lindex [dict get $calibration projector extrinsics] 0] + set tablePlaneOrigin [dict get $extrinsics t] + set tablePlaneNormal [getcol [dict get $extrinsics R] 2] + + set topLeft [unprojectWithReferencePlane $intrinsics $tablePlaneOrigin $tablePlaneNormal 0 0] + set topRight [unprojectWithReferencePlane $intrinsics $tablePlaneOrigin $tablePlaneNormal $width 0] + set bottomRight [unprojectWithReferencePlane $intrinsics $tablePlaneOrigin $tablePlaneNormal $width $height] + set bottomLeft [unprojectWithReferencePlane $intrinsics $tablePlaneOrigin $tablePlaneNormal 0 $height] + + Claim table has quad [$quadLib create "display $display" [list $topLeft $topRight $bottomRight $bottomLeft]] +} \ No newline at end of file diff --git a/builtin-programs/tags-to-quads.folk b/builtin-programs/tags-to-quads.folk index b9475f10..86fdb83b 100644 --- a/builtin-programs/tags-to-quads.folk +++ b/builtin-programs/tags-to-quads.folk @@ -42,6 +42,22 @@ $cc proc distort {double fx double fy double cx double cy out[0] = (x * (1.0 + radial) + dx)*fx + cx; out[1] = (y * (1.0 + radial) + dy)*fy + cy; } +$cc proc undistort {double fx double fy double cx double cy + double k1 double k2 double p1 double p2 + double xy[2] double out[2]} void { + double x0 = (xy[0] - cx)/fx; + double y0 = (xy[1] - cy)/fy; + double x = x0, y = y0; + for (int i = 0; i < 5; i++) { + double r2 = x*x + y*y; + double radial = 1.0 + k1 * r2 + k2 * r2*r2; + double dx = 2*p1*x*y + p2*(r2 + 2*x*x); + double dy = p1*(r2 + 2*y*y) + 2*p2*x*y; + x = (x0 - dx) / radial; + y = (y0 - dy) / radial; + } + out[0] = x*fx + cx; out[1] = y*fy + cy; +} $cc proc project {Intrinsics intr double width double height double[3] v} Jim_Obj* { double out[3] = { @@ -61,6 +77,30 @@ $cc proc project {Intrinsics intr double width double height }; return Jim_NewListObj(interp, retObjs, 2); } +# Returns a homogenous point. +$cc proc unproject {Intrinsics intr double width double height + double u double v} Jim_Obj* { + // Normalize the provided `u` and `v` to our width and height. + double pixel[2] = { + u * intr.width / width, + v * intr.height / height + }; + + undistort(intr.fx, intr.fy, intr.cx, intr.cy, + intr.k1, intr.k2, intr.p1, intr.p2, + pixel, pixel); + + // Apply inverse intrinsic matrix. + double y = (pixel[1] - intr.cy) / intr.fy; + double x = (pixel[0] - intr.cx - intr.s * y) / intr.fx; + + Jim_Obj* retObjs[3] = { + Jim_NewDoubleObj(interp, x), + Jim_NewDoubleObj(interp, y), + Jim_NewDoubleObj(interp, 1) + }; + return Jim_NewListObj(interp, retObjs, 3); +} $cc proc rescaleAndUndistort {Intrinsics intr double cameraWidth double cameraHeight double* in From 441b4134a3b264e68ef0b8000c32626ca935e4c2 Mon Sep 17 00:00:00 2001 From: Mason Jones <20848827+smj-edison@users.noreply.github.com> Date: Sat, 29 Aug 2026 20:47:29 -0600 Subject: [PATCH 4/5] Add points changing --- builtin-programs/points.folk | 83 ++++++++++++++++++++++++++++++++++ builtin-programs/quad-lib.folk | 45 ++++++++++++++---- 2 files changed, 120 insertions(+), 8 deletions(-) create mode 100644 builtin-programs/points.folk diff --git a/builtin-programs/points.folk b/builtin-programs/points.folk new file mode 100644 index 00000000..fda09a83 --- /dev/null +++ b/builtin-programs/points.folk @@ -0,0 +1,83 @@ +set pointsLib [library create pointsLib {} { + proc surfacePoint {surface xy} { + upvar this this + return [list surface-point $surface $xy] + } + + proc surfacePointCheckType {surfacePoint} { + set type [lindex $surfacePoint 0] + if {$type ne "surface-point"} { error "expected type "surface-point", but got \"$type\""} + } + + proc surfacePointVector {surfacePoint} { + surfacePointCheckType $surfacePoint + return [lindex $surfacePoint 2] + } + + proc surfacePointId {surfacePoint} { + surfacePointCheckType $surfacePoint + return [lindex $surfacePoint 1] + } + + proc spacePoint {space xyz} { + return [list space-point $space $xyz] + } + + proc spacePointCheckType {spacePoint} { + set type [lindex $spacePoint 0] + if {$type ne "space-point"} { error "expected type "space-point", but got \"$type\""} + } + + proc spacePointVector {spacePoint} { + spacePointCheckType $spacePoint + return [lindex $spacePoint 2] + } + + proc spacePointSpace {spacePoint} { + spacePointCheckType $spacePoint + return [lindex $spacePoint 1] + } + + # User API + proc point {x y} { + upvar this this + return [surfacePoint $this [list $x $y]] + } +}] +Claim the points library is $pointsLib + +When when point /point/ has point /anything/ on /targetSurface/ /lambda/ with environment /anything/ { + Wish point $point is projected to surface $targetSurface +} + +When the quad library is /quadLib/ &\ + the quad changer is /quadChange/ &\ + /someone/ wishes point /point/ is projected to surface /targetSurface/ { + set pointSurface [$pointsLib surfacePointId $point] + When $pointSurface has quad /pointQuad/ &\ + $targetSurface has quad /targetQuad/ { + # "Now in 3D!" + set pointInSpace [$quadLib XYToPoint $pointQuad [$pointsLib surfacePointVector $point]] + + # HACK currently the `quadChange` changes quads, not points. We + # construct an artifical quad that has zeros for the last three + # coordinates so we can still use quadLib for conversion. + set targetSpace [$quadLib space $targetQuad] + set pointInQuad [$quadLib create $targetSpace [list $pointInSpace {0.0 0.0 0.0} \ + {0.0 0.0 0.0} {0.0 0.0 0.0}]] + + fn quadChange + # Note this will throw an error if the point can't be converted between these + # two spaces. + set pointQuadInTargetSpace [quadChange $pointInQuad $targetSpace] + set pointInTargetSpace [lindex [$quadLib vertices $pointQuadInTargetSpace] 0] + + set projectedOntoTarget [$quadLib projectAlongSourceNormal $pointQuad $targetQuad $pointInTargetSpace] + set targetXY [$quadLib pointToXY $targetQuad $projectedOntoTarget] + + # Flatland has entered the chat. + set pointOnTargetSurface [$pointsLib surfacePoint $targetSurface $targetXY] + + Claim point $point has point $pointOnTargetSurface on $targetSurface + } +} \ No newline at end of file diff --git a/builtin-programs/quad-lib.folk b/builtin-programs/quad-lib.folk index 60c3e829..79c21449 100644 --- a/builtin-programs/quad-lib.folk +++ b/builtin-programs/quad-lib.folk @@ -6,6 +6,7 @@ set quadLib [library create quadLib {} { ::math::linearalgebra::sub \ ::math::linearalgebra::norm \ ::math::linearalgebra::dotproduct \ + ::math::linearalgebra::crossproduct \ ::math::linearalgebra::unitLengthVector \ ::math::linearalgebra::scale rename scale scaleVector @@ -230,10 +231,22 @@ set quadLib [library create quadLib {} { return [create [space $q] [list $topLeft $topRight $bottomRight $bottomLeft]] } + proc XYToPoint {quad xy} { + lassign $xy x y + lassign [vertices $quad] topLeft topRight bottomRight bottomLeft + set width [norm [sub $topRight $topLeft]] + set height [norm [sub $bottomLeft $topLeft]] + set xAxis [unitLengthVector [sub $topRight $topLeft]] + set yAxis [unitLengthVector [sub $bottomLeft $topLeft]] + set pointRelativeToTopLeft [add [scaleVector $x $xAxis] \ + [scaleVector $y $yAxis]] + return [add $pointRelativeToTopLeft $topLeft] + } + # Take a {x y z} point in the same space as the quad and project # it down onto a {top left} point on the quad (that can be used in # the drawing APIs, etc). - proc pointToXY {q xyz {checkBounds true}} { + proc pointToXY {q xyz} { lassign [vertices $q] topLeft topRight bottomRight bottomLeft set width [norm [sub $topRight $topLeft]] set height [norm [sub $bottomLeft $topLeft]] @@ -243,15 +256,31 @@ set quadLib [library create quadLib {} { set x [dotproduct $delta $xAxis] set y [dotproduct $delta $yAxis] - set eps 0.000001 - if {$x < -$eps || $x > $width + $eps || - $y < -$eps || $y > $height + $eps} { - if {$checkBounds} { - error "quad pointToXY: point $xyz projects outside quad bounds as {$x $y}; bounds are {0 0} {$width $height}" - } + return [list $x $y] + } + + proc projectAlongSourceNormal {sourceQuad targetQuad xyz} { + lassign [vertices $sourceQuad] sourceTopLeft sourceTopRight sourceBottomRight sourceBottomLeft + # We project a ray out from the source quad onto the target quad. + set rayDirection [unitLengthVector [crossproduct \ + [sub $sourceTopRight $sourceTopLeft] \ + [sub $sourceBottomLeft $sourceTopLeft]]] + + lassign [vertices $targetQuad] targetTopLeft targetTopRight targetBottomRight targetBottomLeft + set targetNormal [unitLengthVector [crossproduct \ + [sub $targetTopRight $targetTopLeft] \ + [sub $targetBottomLeft $targetTopLeft]]] + + set cosineToTarget [dotproduct $targetNormal $rayDirection] + if {abs($cosineToTarget) < 1e-6} { + error "projectAlongSourceNormal: source plane is perpendicular to target plane" } - return [list $x $y] + set distanceToTarget [expr { + [dotproduct $targetNormal [sub $targetTopLeft $xyz]] / $cosineToTarget + }] + + return [add $xyz [scaleVector $distanceToTarget $rayDirection]] } }] Claim the quad library is $quadLib From 5961f8d9b2c13aad4063cc2a078dcaf79e1e1e45 Mon Sep 17 00:00:00 2001 From: Mason Jones <20848827+smj-edison@users.noreply.github.com> Date: Sat, 29 Aug 2026 21:15:44 -0600 Subject: [PATCH 5/5] Remove table quad for now (should be a separate PR) --- builtin-programs/geometric/points-at.folk | 2 +- builtin-programs/table.folk | 32 ----------------------- 2 files changed, 1 insertion(+), 33 deletions(-) delete mode 100644 builtin-programs/table.folk diff --git a/builtin-programs/geometric/points-at.folk b/builtin-programs/geometric/points-at.folk index afdb22a6..5de70d0d 100644 --- a/builtin-programs/geometric/points-at.folk +++ b/builtin-programs/geometric/points-at.folk @@ -82,7 +82,7 @@ When $rect has quad /quad/ { $to] When /target/ has quad /q2/ { - if {$target eq $rect || $target eq "table"} { return } + if {$target eq $rect} { return } set displayVertices [lmap v [$quadLib vertices [quadChange $q2 "display $disp"]] { $poseLib project $displayIntrinsics \ diff --git a/builtin-programs/table.folk b/builtin-programs/table.folk deleted file mode 100644 index c80c6cde..00000000 --- a/builtin-programs/table.folk +++ /dev/null @@ -1,32 +0,0 @@ -When the quad library is /quadLib/ &\ - the pose library is /poseLib/ &\ - a calibration from camera /camera/ to display /display/ is /calibration/ { - package require linalg - namespace import ::math::linearalgebra::dotproduct \ - ::math::linearalgebra::scale \ - ::math::linearalgebra::getcol - - local proc unprojectWithReferencePlane {intrinsics planeOrigin planeNormal x y} { - upvar poseLib poseLib - set width $intrinsics(width) - set height $intrinsics(height) - set ray [$poseLib unproject $intrinsics $width $height $x $y] - # Ray-plane intersection to figure out where the ray lands on the reference plane. - set z [/ [dotproduct $planeNormal $planeOrigin] [dotproduct $planeNormal $ray]] - return [scale $z $ray] - } - - set intrinsics [dict get $calibration projector intrinsics] - set width $intrinsics(width) - set height $intrinsics(height) - set extrinsics [lindex [dict get $calibration projector extrinsics] 0] - set tablePlaneOrigin [dict get $extrinsics t] - set tablePlaneNormal [getcol [dict get $extrinsics R] 2] - - set topLeft [unprojectWithReferencePlane $intrinsics $tablePlaneOrigin $tablePlaneNormal 0 0] - set topRight [unprojectWithReferencePlane $intrinsics $tablePlaneOrigin $tablePlaneNormal $width 0] - set bottomRight [unprojectWithReferencePlane $intrinsics $tablePlaneOrigin $tablePlaneNormal $width $height] - set bottomLeft [unprojectWithReferencePlane $intrinsics $tablePlaneOrigin $tablePlaneNormal 0 $height] - - Claim table has quad [$quadLib create "display $display" [list $topLeft $topRight $bottomRight $bottomLeft]] -} \ No newline at end of file