int main(){ float x,y; //calculates polar coordinates given x and y //ask for x and y values printf("This program converts cartesian coordinates into polar coordinates.\nPlease enter values for x and y."); printf("\nX: "); scanf("%f", &x); printf("Y: "); scanf("%f", &y); float radius=findRadius(x,y); float angle=findAngle(x,y); int quadrant=findQuadrant(radius,angle); printf("\nThe radius is %.2f and the angle is %.2f degrees counterclockwise from the positive x axis.\n", radius, angle); switch(quadrant){ case 0: printf("The point is on the origin."); break; case 1: printf("The point is in the first quadrant."); break; case 2: printf("The point is in the second quadrant."); break; case 3: printf("The point is in the third quadrant."); break; case 4: printf("The point is in the fourth quadrant."); break; case 5: printf("The point is on the positive x axis."); break; case 6: printf("The point is on the negative x axis."); break; case 7: printf("The point is on the positive y axis."); break; case 8: printf("The point is on the negative y axis."); break; } printf("\n"); }
/** * @brief View-volume culling * * View-volume culling: axis-aligned bounding box against view volume, * given as Model/View/Projection matrix. * Inputs: * MVP: Matrix from object to NDC space * (model/view/projection) * Inputs/Outputs: * cullBits: Keeps track of which planes we need to test against. * Has three bits, for X, Y and Z. If cullBits is 0, * then the bounding box is completely inside the view * and no further cull tests need be done for things * inside the bounding box. Zero bits in cullBits mean * the bounding box is completely between the * left/right, top/bottom, or near/far clipping planes. * Outputs: * bool: TRUE if bbox is completely outside view volume * defined by MVP. * * * * How: * * An axis-aligned bounding box is the set of all points P, * Pmin < P < Pmax. We're interested in finding out whether or not * any of those points P are clipped after being transformed through * MVP (transformed into clip space). * * A transformed point P'[x,y,z,w] is inside the view if [x,y,z] are * all between -w and w. Otherwise the point is outside the view. * * Instead of testing individual points, we want to treat the range of * points P. We want to know if: All points P are clipped (in which * case the cull test succeeds), all points P are NOT clipped (in * which case they are completely inside the view volume and no more * cull tests need be done for objects inside P), or some points are * clipped and some aren't. * * P transformed into clip space is a 4-dimensional solid, P'. To * speed things up, this algorithm finds the 4-dimensional, * axis-aligned bounding box of that solid and figures out whether or * not that bounding box intersects any of the sides of the view * volume. In the 4D space with axes x,y,z,w, the view volume planes * are the planes x=w, x=-w, y=w, y=-w, z=w, z=-w. * * This is all easier to think about if we think about each of the X, * Y, Z axes in clip space independently; worrying only about the X * axis for a moment: * * The idea is to find the minimum and maximum possible X,W * coordinates of P'. If all of the points in the * [(Xmin,Xmax),(Wmin,Wmax)] range satisfy -|W| < X < |W| (|W| is * absolute value of W), then the original bounding box P is * completely inside the X-axis (left/right) clipping planes of the * view volume. In (x,w) space, a point (x,w) is clipped depending on * which quadrant it is in: * * x=-w x=w * \ Q0 / * \ IN / * \ / * \ / * Q1 \/ Q2 * CLIPPED /\ CLIPPED * / \ * / \ * / Q3 \ * / CLIPPED\ * * If the axis-aligned box [(Xmin,Xmax),(Wmin,Wmax)] lies entirely in * Q0, then it is entirely inside the X-axis clipping planes (IN * case). If it is not in Q0 at all, then it is clipped (OUT). If it * straddles Q0 and some other quadrant, the bounding box intersects * the clipping planes (STRADDLE). The 4 corners of the bounding box * are tested first using bitwise tests on their quadrant numbers; if * they determine the case is STRADDLE then a more refined test is * done on the 8 points of the original bounding box. * The test isn't perfect-- a bounding box that straddles both Q1 and * Q2 may be incorrectly classified as STRADDLE; however, those cases * are rare and the cases that are incorrectly classified will likely * be culled when testing against the other clipping planes (these * cases are cases where the bounding box is near the eye). * * Finding [(Xmin,Xmax),(Wmin,Wmax)] is easy. Consider Xmin. It is * the smallest X coordinate when all of the points in the range * Pmin,Pmax are transformed by MVP; written out: * X = P[0]*M[0][0] + P[1]*M[1][0] + P[2]*M[2][0] + M[3][0] * X will be minimized when each of the terms is minimized. If the * matrix entry for the term is positive, then the term is minimized * by choosing Pmin; if the matrix entry is negative, the term is * minimized by choosing Pmax. Three 'if' test will let us calculate * the transformed Xmin. Xmax can be calculated similarly. * * Testing for IN/OUT/STRADDLE for the Y and Z coordinates is done * exactly the same way. */ bool Box3f::outside(const MatrixR& MVP, int32& cullBits) const { float Wmax = minExtreme(m_max, m_min, MVP, 3); if (Wmax < 0) return true; float Wmin = minExtreme(m_min, m_max, MVP, 3); // Do each coordinate: for (int32 i = 0; i < 3; i++) { if (cullBits & (1<<i)) { // STRADDLES: float Cmin = minExtreme(m_min, m_max, MVP, i); // The and_bits and or_bits are used to keep track of // which quadrants point lie in. The cases are: // // All in Q0: IN // (or_bits == 0) --> and_bits MUST also be 0 // Some/all in Q1, some/all in Q3: CULLED // Some/all in Q2, some/none in Q3: CULLED // (and_bits != 0, or_bits != 0) // Some in Q1, some in Q2, some/none in Q3: STRADDLE // (and_bits == 0, or_bits !=0) // int32 and_bits; int32 or_bits; and_bits = or_bits = quadrant(Cmin, Wmin); int32 q0 = quadrant(Cmin, Wmax); and_bits &= q0; or_bits |= q0; // Hit the STRADDLE case as soon as and_bits == 0 and // or_bits != 0: if (!(and_bits == 0 && or_bits != 0)) { float Cmax = minExtreme(m_max, m_min, MVP, i); q0 = quadrant(Cmax, Wmin); and_bits &= q0; or_bits |= q0; if (!(and_bits == 0 && or_bits != 0)) { q0 = quadrant(Cmax, Wmax); and_bits &= q0; or_bits |= q0; // Either completely IN or completely OUT: if (or_bits == 0) { // IN cullBits &= ~(1<<i); // Clear bit continue; // Continue for loop } else if (and_bits != 0) { return true; // CULLED } } } // Before we give up and just claim it straddles, do a // more refined test-- check the 8 corners of the // bounding box: // Test to see if all 8 corner points of the bounding box // are in the same quadrant. If so, the object is either // completely in or out of the view. Otherwise, it straddles // at least one of the view boundaries. and_bits = or_bits = findQuadrant(m_min[0], m_min[1], m_min[2], i, MVP); if (and_bits == 0 && or_bits != 0) continue; q0 = findQuadrant(m_max[0], m_max[1], m_max[2], i, MVP); and_bits &= q0; or_bits |= q0; if (and_bits == 0 && or_bits != 0) continue; q0 = findQuadrant(m_max[0], m_min[1], m_min[2], i, MVP); and_bits &= q0; or_bits |= q0; if (and_bits == 0 && or_bits != 0) continue; q0 = findQuadrant(m_min[0], m_max[1], m_max[2], i, MVP); and_bits &= q0; or_bits |= q0; if (and_bits == 0 && or_bits != 0) continue; q0 = findQuadrant(m_min[0], m_max[1], m_min[2], i, MVP); and_bits &= q0; or_bits |= q0; if (and_bits == 0 && or_bits != 0) continue; q0 = findQuadrant(m_max[0], m_min[1], m_max[2], i, MVP); and_bits &= q0; or_bits |= q0; if (and_bits == 0 && or_bits != 0) continue; q0 = findQuadrant(m_max[0], m_max[1], m_min[2], i, MVP); and_bits &= q0; or_bits |= q0; if (and_bits == 0 && or_bits != 0) continue; q0 = findQuadrant(m_min[0], m_min[1], m_max[2], i, MVP); and_bits &= q0; or_bits |= q0; // Either completely IN or completely OUT: if (or_bits == 0) { // IN cullBits &= ~(1<<i); // Clear bit continue; // Continue for loop } else if (and_bits != 0) { return true; // CULLED } } } return false;// Not culled }
void GestureDetector::detect(NUI_SKELETON_FRAME &SkeletonFrame, NUI_SKELETON_FRAME &prevFrame) { NUI_SKELETON_DATA SkeletonData = SkeletonFrame.SkeletonData[id]; NUI_SKELETON_DATA prevSkeletonData = prevFrame.SkeletonData[id]; /*** The compiler does not like initializing variables within case statements ***/ // Temporary variables for actual body part points Vector4 headPoint; Vector4 rightHandPoint; Vector4 leftHandPoint; Vector4 handPoint; Vector4 spinePoint; // Vector4 rightShoulderPoint; // Vector4 leftShoulderPoint; // These are derived points used for magnification and movement Vector4 upPoint; Vector4 downPoint; Vector4 leftPoint; Vector4 rightPoint; Vector4 centerPoint; FLOAT displacement_x = 0; FLOAT displacement_y = 0; long long curTime = 0; Quadrant curQuadrant; // Do as much as we can before entering the state machine, because long states are confusing // If they make the "stop" gesture, turn off gesture recognition and magnification period // // In this case the "stop" gesture is hands _crossed_ and touching the shoulders // rightHandPoint = SkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_HAND_RIGHT]; // leftHandPoint = SkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_HAND_LEFT]; // rightShoulderPoint = SkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_SHOULDER_RIGHT]; // leftShoulderPoint = SkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_SHOULDER_LEFT]; // if (areClose(leftShoulderPoint, rightHandPoint, detectRange) && areClose(rightShoulderPoint, leftHandPoint, detectRange)) // Stop gesture is hands on head rightHandPoint = SkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_HAND_RIGHT]; leftHandPoint = SkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_HAND_LEFT]; headPoint = SkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_HEAD]; if (id == activeSkeleton) // Only if we're the active skeleton - nobody else should be able to kill it { if ( areClose3D(headPoint, rightHandPoint, detectRange) && areClose3D(headPoint, leftHandPoint, detectRange) ) { moveAmount_y = 0; moveAmount_x = 0; // Stop us from immediately re-enabling after disabling (cycling) if (! hideWindowOn) { hideWindowOn = TRUE; // Reset magnification value magnificationFloor = 0; HideMagnifier(); clearAndHideOverlay(); state->set(OFF); } } else { hideWindowOn = FALSE; } } // If the magnifier is off now, don't bother detecting gestures, just stop. if (id == activeSkeleton && (! IsWindowVisible(hwndMag))) { return; } // Most states are only applicable if we're the active skeleton if (id != activeSkeleton) { // Setting an already OFF state to OFF won't cause issues. if (state->state != SALUTE1) { // Adding a 'return' here will prevent anyone from stealing focus while a gesture is happening state->set(OFF); } } // Timeout any state other than OFF curTime = getTimeIn100NSIntervals(); if ( (curTime - startTime) > timeout ) { if (id == activeSkeleton) { moveAmount_y = 0; moveAmount_x = 0; clearAndHideOverlay(); state->set(OFF); } state->set(OFF); } // Same thing if they make the "cancel" gesture // The cancel gesture is to start the salute again static BOOL cancelling = FALSE; if (cancelling || (id == activeSkeleton && state->state != SALUTE1 && state->state != OFF && state->state != SALUTE2)) { // Headpoint already initialized above for the stop gesture // headPoint = SkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_HEAD]; if (hand == RIGHT) { handPoint = SkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_HAND_RIGHT]; } else { handPoint = SkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_HAND_LEFT]; } if (areClose3D(headPoint, handPoint, detectRange)) { if (! cancelling) { cancelling = TRUE; moveAmount_y = 0; moveAmount_x = 0; clearAndHideOverlay(); state->set(OFF); } return; } else { cancelling = FALSE; } } // If they make the "cancel" gesture, stop recognizing gestures // Cancel gesture here is both hands touching. // static BOOL cancelling = FALSE; // if (id == activeSkeleton // && areClose3D(leftHandPoint, rightHandPoint, handsTogether)) // { // if ( ! cancelling) // { // cancelling = TRUE; // killGesturesStartTime = getTimeIn100NSIntervals(); // } // else // { // if ( (curTime - killGesturesStartTime) > killGesturesTime) // { // moveAmount_y = 0; // moveAmount_x = 0; // clearAndHideOverlay(); // state->set(OFF); // } // } // } // else // { // cancelling = FALSE; // } // Click gesture spinePoint = SkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_SPINE]; static BOOL amClicking = FALSE; if (id == activeSkeleton && state->state == MOVECENTER && ( ((spinePoint.z - rightHandPoint.z) > clickDistance) || ((spinePoint.z - leftHandPoint.z) > clickDistance) ) ) { if (showOverlays) { int ulx_small; int ulx_ss; int uly_small = (yRes/2) - (boxSmall/2); int uly_ss = (yRes/2) - (boxSuperSmall/2); if (hand == RIGHT) { ulx_small = (xRes*3/4) - (boxSmall/2); ulx_ss = (xRes*3/4) - (boxSuperSmall/2); } else { ulx_small = (xRes/4) - (boxSmall/2); ulx_ss = (xRes/4) - (boxSuperSmall/2); } // Make the center swirls go red drawRectangle(ulx_small, uly_small, boxSmall, boxSmall, 0); drawRectangle(ulx_ss, uly_ss, boxSuperSmall, boxSuperSmall, 0); } if (! amClicking) { // It'd be nice if the screen could flash at this // point or something, but that doesn't seem entirely // trivial with our current concept of overlays mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); amClicking = TRUE; } } else { amClicking = FALSE; } switch (state->state) { case OFF: if (id == activeSkeleton) { moveAmount_y = 0; moveAmount_x = 0; } // Check if a hand is close to the head headPoint = SkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_HEAD]; rightHandPoint = SkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_HAND_RIGHT]; leftHandPoint = SkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_HAND_LEFT]; if (areClose(headPoint, rightHandPoint, detectRange)) { state->set(SALUTE1); startTime = getTimeIn100NSIntervals(); hand = RIGHT; return; } if (areClose(headPoint, leftHandPoint, detectRange)) { state->set(SALUTE1); startTime = getTimeIn100NSIntervals(); hand = LEFT; return; } break; case SALUTE1: // Check for saluting action (box up and away) headPoint = SkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_HEAD]; headPoint.y += saluteUp; if (hand == RIGHT) { handPoint = SkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_HAND_RIGHT]; headPoint.x += saluteOver; } else { handPoint = SkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_HAND_LEFT]; headPoint.x -= saluteOver; } if (areClose(headPoint, handPoint, detectRange)) { if (showOverlays) { if (allowMagnifyGestures) { if (hand == RIGHT) { drawRectangle ((xRes*3/4) - (boxLarge/2), (yRes/2) - (boxLarge/2), boxLarge, boxLarge, 0); } else { drawRectangle ((xRes/4) - (boxLarge/2), (yRes/2) - (boxLarge/2), boxLarge, boxLarge, 0); } drawRectangle ((xRes/2) - (boxLarge/2), (yRes/2) - (boxLarge/2), boxLarge, boxLarge, 0); } else { if (hand == RIGHT) { drawRectangle ((xRes*3/4) - (boxLarge/2), (yRes/2) - (boxLarge/2), boxLarge, boxLarge, 0); } else { drawRectangle ((xRes/4) - (boxLarge/2), (yRes/2) - (boxLarge/2), boxLarge, boxLarge, 0); } } } state->set(SALUTE2); // Right now, an alert to let me know gesture tracking is working //MessageBox(NULL, "Salute detected", "Gesture Detection", NULL); // Change the active user // This is a race condition, but what it's doing is also inherently one if (activeSkeleton != id) { activeSkeleton = id; clearOverlay(); moveAmount_x = 0; moveAmount_y = 0; } startTime = getTimeIn100NSIntervals(); return; } // Otherwise, keep looking (until the timeout) break; case SALUTE2: spinePoint = SkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_SPINE]; centerPoint = spinePoint; if (hand == RIGHT) { handPoint = SkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_HAND_RIGHT]; centerPoint.x += centerRightOver; } else { handPoint = SkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_HAND_LEFT]; centerPoint.x -= centerLeftOver; } // Only allow user magnification if it's turned on if (allowMagnifyGestures) { if (areClose(spinePoint, handPoint, detectRange)) { // Lock-on if (! lockingOn_magnify) { lockingOn_magnify = TRUE; lockonStartTime = getTimeIn100NSIntervals(); if (showOverlays) { clearOverlay(); drawLockOn(xRes/2, yRes/2); drawText ((xRes/3), (yRes/10), L"Locking on to Magnification Mode", 56); } } else // We're locking on already { curTime = getTimeIn100NSIntervals(); if ((curTime - lockonStartTime) > lockonTime) { state->set(MAGNIFYLEFT); startTime = getTimeIn100NSIntervals(); if (showOverlays) { clearOverlay(); drawRectangle ((xRes/2) - (boxLarge/2), (yRes/2) - (boxLarge/2), boxLarge, boxLarge, 1); drawText ((xRes/3), (yRes/10), L"Magnification Gesture Mode", 56); } } } return; } else if (areClose(centerPoint, handPoint, detectRange)) { // Don't do anything during the dead time if (! lockingOn_move) { lockingOn_move = TRUE; lockonStartTime = getTimeIn100NSIntervals(); if (showOverlays) { clearOverlay(); if (hand == RIGHT) { drawLockOn(xRes*3/4, yRes/2); } else { drawLockOn(xRes/4, yRes/2); } drawText ((xRes/3), (yRes/10), L"Locking on to Movement Mode", 56); } } else { curTime = getTimeIn100NSIntervals(); if ((curTime - lockonStartTime) > lockonTime) { state->set(MOVECENTER); startTime = getTimeIn100NSIntervals(); if (showOverlays) { clearOverlay(); int ulx; int ulx_small; int ulx_ss; int uly = (yRes/2) - (boxLarge/2); int uly_small = (yRes/2) - (boxSmall/2); int uly_ss = (yRes/2) - (boxSuperSmall/2); if (hand == RIGHT) { ulx = (xRes*3/4) - (boxLarge/2); ulx_small = (xRes*3/4) - (boxSmall/2); ulx_ss = (xRes*3/4) - (boxSuperSmall/2); } else { ulx = (xRes/4) - (boxLarge/2); ulx_small = (xRes/4) - (boxSmall/2); ulx_ss = (xRes/4) - (boxSuperSmall/2); } drawTrapezoid(ulx, uly, Q_TOP, 0); drawTrapezoid(ulx, uly, Q_BOTTOM, 0); // drawTrapezoid(ulx, uly, Q_RIGHT, 0); // drawTrapezoid(ulx, uly, Q_LEFT, 0); drawRectangle(ulx, uly, boxLarge, boxLarge, 1); drawRectangle(ulx_small, uly_small, boxSmall, boxSmall, 1); drawRectangle(ulx_ss, uly_ss, boxSuperSmall, boxSuperSmall, 1); drawText ((xRes/3), (yRes/10), L"Movement Gesture Mode", 56); } } } return; } // Nothing hit, so we're not locking on lockingOn_move = FALSE; lockingOn_magnify = FALSE; if (showOverlays) { clearOverlay(); if (hand == RIGHT) { drawRectangle ((xRes*3/4) - (boxLarge/2), (yRes/2) - (boxLarge/2), boxLarge, boxLarge, 0); } else { drawRectangle ((xRes/4) - (boxLarge/2), (yRes/2) - (boxLarge/2), boxLarge, boxLarge, 0); } drawRectangle ((xRes/2) - (boxLarge/2), (yRes/2) - (boxLarge/2), boxLarge, boxLarge, 0); } } else // Only movement gestures { if (areClose(centerPoint, handPoint, detectRange)) { if (! lockingOn_move) { lockingOn_move = TRUE; lockonStartTime = getTimeIn100NSIntervals(); if (showOverlays) { clearOverlay(); if (hand == RIGHT) { drawLockOn(xRes*3/4, yRes/2); } else { drawLockOn(xRes/4, yRes/2); } drawText ((xRes/3), (yRes/10), L"Locking on to Movement Mode", 56); } } else { // We're locking on curTime = getTimeIn100NSIntervals(); if ((curTime - lockonStartTime) > lockonTime) { state->set(MOVECENTER); startTime = getTimeIn100NSIntervals(); if (showOverlays) { clearOverlay(); int ulx; int ulx_small; int ulx_ss; int uly = (yRes/2) - (boxLarge/2); int uly_small = (yRes/2) - (boxSmall/2); int uly_ss = (yRes/2) - (boxSuperSmall/2); if (hand == RIGHT) { ulx = (xRes*3/4) - (boxLarge/2); ulx_small = (xRes*3/4) - (boxSmall/2); ulx_ss = (xRes*3/4) - (boxSuperSmall/2); } else { ulx = (xRes/4) - (boxLarge/2); ulx_small = (xRes/4) - (boxSmall/2); ulx_ss = (xRes/4) - (boxSuperSmall/2); } drawTrapezoid(ulx, uly, Q_TOP, 0); drawTrapezoid(ulx, uly, Q_BOTTOM, 0); // drawTrapezoid(ulx, uly, Q_RIGHT, 0); // drawTrapezoid(ulx, uly, Q_LEFT, 0); drawRectangle(ulx, uly, boxLarge, boxLarge, 1); drawRectangle(ulx_small, uly_small, boxSmall, boxSmall, 1); drawRectangle(ulx_ss, uly_ss, boxSuperSmall, boxSuperSmall, 1); drawText ((xRes/3), (yRes/10), L"Movement Gesture Mode", 56); } } } return; } // We're not close to anything, so turn off the lockon lockingOn_move = FALSE; if (showOverlays) { clearOverlay(); if (hand == RIGHT) { drawRectangle ((xRes*3/4) - (boxLarge/2), (yRes/2) - (boxLarge/2), boxLarge, boxLarge, 0); } else { drawRectangle ((xRes/4) - (boxLarge/2), (yRes/2) - (boxLarge/2), boxLarge, boxLarge, 0); } } } break; // case BODYCENTER: // spinePoint = SkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_SPINE]; // centerPoint = spinePoint; // if (hand == RIGHT) // { // handPoint = SkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_HAND_RIGHT]; // centerPoint.x += centerRightOver; // } // else // { // handPoint = SkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_HAND_LEFT]; // centerPoint.x -= centerLeftOver; // } // if (areClose(centerPoint, handPoint, detectRange)) // { // if (hand == RIGHT) // { // // Center // drawRectangle ((xRes*3/4) - (boxSmall/2), (yRes/2) - (boxSmall/2), boxSmall, boxSmall, 1); // // Vert // drawRectangle ((xRes*3/4) - (boxSmall/2), (yRes/2) - (boxSmall/2) - overlayCircleRadius, boxSmall, boxSmall, 0); // drawRectangle ((xRes*3/4) - (boxSmall/2), (yRes/2) - (boxSmall/2) + overlayCircleRadius, boxSmall, boxSmall, 0); // // Horiz // drawRectangle ((xRes*3/4) - (boxSmall/2) - overlayCircleRadius, (yRes/2) - (boxSmall/2), boxSmall, boxSmall, 0); // drawRectangle ((xRes*3/4) - (boxSmall/2) + overlayCircleRadius, (yRes/2) - (boxSmall/2), boxSmall, boxSmall, 0); // } // else // { // // Center // drawRectangle ((xRes/4) - (boxSmall/2), (yRes/2) - (boxSmall/2), boxSmall, boxSmall, 1); // // Vert // drawRectangle ((xRes/4) - (boxSmall/2), (yRes/2) - (boxSmall/2) - overlayCircleRadius, boxSmall, boxSmall, 0); // drawRectangle ((xRes/4) - (boxSmall/2), (yRes/2) - (boxSmall/2) + overlayCircleRadius, boxSmall, boxSmall, 0); // // Horiz // drawRectangle ((xRes/4) - (boxSmall/2) - overlayCircleRadius, (yRes/2) - (boxSmall/2), boxSmall, boxSmall, 0); // drawRectangle ((xRes/4) - (boxSmall/2) + overlayCircleRadius, (yRes/2) - (boxSmall/2), boxSmall, boxSmall, 0); // } // state->set(MOVECENTER); // startTime = getTimeIn100NSIntervals(); // return; // } // // Otherwise, keep looking (until the timeout) // break; case MOVECENTER: case MOVEUP: case MOVEDOWN: case MOVERIGHT: case MOVELEFT: spinePoint = SkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_SPINE]; centerPoint = spinePoint; if (hand == RIGHT) { handPoint = SkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_HAND_RIGHT]; centerPoint.x += centerRightOver; // Add velocity getDifference(handPoint, prevSkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_HAND_RIGHT], displacement_x, displacement_y); } else { handPoint = SkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_HAND_LEFT]; centerPoint.x -= centerLeftOver; // Add velocity getDifference(handPoint, prevSkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_HAND_LEFT], displacement_x, displacement_y); } // Specific direction curQuadrant = findQuadrant(centerPoint, handPoint); // Place the direction arrows if (curQuadrant == Q_TOP) { if (showOverlays) { int ulx; int ulx_small; int ulx_ss; int uly = (yRes/2) - (boxLarge/2); int uly_small = (yRes/2) - (boxSmall/2); int uly_ss = (yRes/2) - (boxSuperSmall/2); if (hand == RIGHT) { ulx = (xRes*3/4) - (boxLarge/2); ulx_small = (xRes*3/4) - (boxSmall/2); ulx_ss = (xRes*3/4) - (boxSuperSmall/2); } else { ulx = (xRes/4) - (boxLarge/2); ulx_small = (xRes/4) - (boxSmall/2); ulx_ss = (xRes/4) - (boxSuperSmall/2); } // Overwrite old center stuff drawRectangle(ulx_small, uly_small, boxSmall, boxSmall, 2); drawRectangle(ulx_ss, uly_ss, boxSuperSmall, boxSuperSmall, 2); drawRectangle(ulx, uly, boxLarge, boxLarge, 0); drawTrapezoid(ulx, uly, Q_BOTTOM, 0); /*drawTrapezoid(ulx, uly, Q_RIGHT, 0); drawTrapezoid(ulx, uly, Q_LEFT, 0);*/ drawTrapezoid(ulx, uly, Q_TOP, 1); drawText ((xRes/3), (yRes/10), L"Movement Gesture Mode", 56); } state->set(MOVEUP); if (MOVEMENT_STYLE == Velocity_Style) { if (displacement_y < 0) { moveAmount_y += 500*displacement_y; } } else if (MOVEMENT_STYLE == Constant_Style) { moveAmount_x = 0; moveAmount_y = -constantMovement; } startTime = getTimeIn100NSIntervals(); return; } else if (curQuadrant == Q_BOTTOM) { if (showOverlays) { int ulx; int ulx_small; int ulx_ss; int uly = (yRes/2) - (boxLarge/2); int uly_small = (yRes/2) - (boxSmall/2); int uly_ss = (yRes/2) - (boxSuperSmall/2); if (hand == RIGHT) { ulx = (xRes*3/4) - (boxLarge/2); ulx_small = (xRes*3/4) - (boxSmall/2); ulx_ss = (xRes*3/4) - (boxSuperSmall/2); } else { ulx = (xRes/4) - (boxLarge/2); ulx_small = (xRes/4) - (boxSmall/2); ulx_ss = (xRes/4) - (boxSuperSmall/2); } // Overwrite old center stuff drawRectangle(ulx_small, uly_small, boxSmall, boxSmall, 2); drawRectangle(ulx_ss, uly_ss, boxSuperSmall, boxSuperSmall, 2); drawRectangle(ulx, uly, boxLarge, boxLarge, 0); drawTrapezoid(ulx, uly, Q_TOP, 0); /*drawTrapezoid(ulx, uly, Q_RIGHT, 0); drawTrapezoid(ulx, uly, Q_LEFT, 0);*/ drawTrapezoid(ulx, uly, Q_BOTTOM, 1); drawText ((xRes/3), (yRes/10), L"Movement Gesture Mode", 56); } state->set(MOVEDOWN); if (MOVEMENT_STYLE == Velocity_Style) { if (displacement_y > 0) { moveAmount_y += 500*displacement_y; } } else if (MOVEMENT_STYLE == Constant_Style) { moveAmount_x = 0; moveAmount_y = constantMovement; } startTime = getTimeIn100NSIntervals(); return; } else if (curQuadrant == Q_RIGHT) { if (showOverlays) { int ulx; int ulx_small; int ulx_ss; int uly = (yRes/2) - (boxLarge/2); int uly_small = (yRes/2) - (boxSmall/2); int uly_ss = (yRes/2) - (boxSuperSmall/2); if (hand == RIGHT) { ulx = (xRes*3/4) - (boxLarge/2); ulx_small = (xRes*3/4) - (boxSmall/2); ulx_ss = (xRes*3/4) - (boxSuperSmall/2); } else { ulx = (xRes/4) - (boxLarge/2); ulx_small = (xRes/4) - (boxSmall/2); ulx_ss = (xRes/4) - (boxSuperSmall/2); } // Overwrite old center stuff drawRectangle(ulx_small, uly_small, boxSmall, boxSmall, 2); drawRectangle(ulx_ss, uly_ss, boxSuperSmall, boxSuperSmall, 2); drawRectangle(ulx, uly, boxLarge, boxLarge, 0); /*drawTrapezoid(ulx, uly, Q_TOP, 0); drawTrapezoid(ulx, uly, Q_BOTTOM, 0);*/ drawTrapezoid(ulx, uly, Q_LEFT, 0); drawTrapezoid(ulx, uly, Q_RIGHT, 1); drawText ((xRes/3), (yRes/10), L"Movement Gesture Mode", 56); } state->set(MOVERIGHT); if (MOVEMENT_STYLE == Velocity_Style) { if (displacement_x > 0) { moveAmount_x += 500*displacement_x; } } else if (MOVEMENT_STYLE == Constant_Style) { moveAmount_y = 0; moveAmount_x = constantMovement; } startTime = getTimeIn100NSIntervals(); return; } else if (curQuadrant == Q_LEFT) { if (showOverlays) { int ulx; int ulx_small; int ulx_ss; int uly = (yRes/2) - (boxLarge/2); int uly_small = (yRes/2) - (boxSmall/2); int uly_ss = (yRes/2) - (boxSuperSmall/2); if (hand == RIGHT) { ulx = (xRes*3/4) - (boxLarge/2); ulx_small = (xRes*3/4) - (boxSmall/2); ulx_ss = (xRes*3/4) - (boxSuperSmall/2); } else { ulx = (xRes/4) - (boxLarge/2); ulx_small = (xRes/4) - (boxSmall/2); ulx_ss = (xRes/4) - (boxSuperSmall/2); } // Overwrite old center stuff drawRectangle(ulx_small, uly_small, boxSmall, boxSmall, 2); drawRectangle(ulx_ss, uly_ss, boxSuperSmall, boxSuperSmall, 2); drawRectangle(ulx, uly, boxLarge, boxLarge, 0); /*drawTrapezoid(ulx, uly, Q_TOP, 0); drawTrapezoid(ulx, uly, Q_BOTTOM, 0);*/ drawTrapezoid(ulx, uly, Q_RIGHT, 0); drawTrapezoid(ulx, uly, Q_LEFT, 1); drawText ((xRes/3), (yRes/10), L"Movement Gesture Mode", 56); } state->set(MOVELEFT); if (MOVEMENT_STYLE == Velocity_Style) { if (displacement_x < 0) { moveAmount_x += 500*displacement_x; } } else if (MOVEMENT_STYLE == Constant_Style) { moveAmount_y = 0; moveAmount_x = -constantMovement; } startTime = getTimeIn100NSIntervals(); return; } // Back to MOVECENTER else if (curQuadrant == Q_CENTER) { if (MOVEMENT_STYLE == Constant_Style) { moveAmount_y = 0; moveAmount_x = 0; } if (showOverlays) { int ulx; int ulx_small; int ulx_ss; int uly = (yRes/2) - (boxLarge/2); int uly_small = (yRes/2) - (boxSmall/2); int uly_ss = (yRes/2) - (boxSuperSmall/2); if (hand == RIGHT) { ulx = (xRes*3/4) - (boxLarge/2); ulx_small = (xRes*3/4) - (boxSmall/2); ulx_ss = (xRes*3/4) - (boxSuperSmall/2); } else { ulx = (xRes/4) - (boxLarge/2); ulx_small = (xRes/4) - (boxSmall/2); ulx_ss = (xRes/4) - (boxSuperSmall/2); } if (! amClicking) { drawRectangle(ulx_small, uly_small, boxSmall, boxSmall, 1); drawRectangle(ulx_ss, uly_ss, boxSuperSmall, boxSuperSmall, 1); } drawTrapezoid(ulx, uly, Q_TOP, 0); drawTrapezoid(ulx, uly, Q_BOTTOM, 0); /*drawTrapezoid(ulx, uly, Q_RIGHT, 0); drawTrapezoid(ulx, uly, Q_LEFT, 0);*/ drawRectangle(ulx, uly, boxLarge, boxLarge, 1); drawText ((xRes/3), (yRes/10), L"Movement Gesture Mode", 56); } state->set(MOVECENTER); startTime = getTimeIn100NSIntervals(); return; } // Otherwise, keep looking (until the timeout) break; // case MOVE: // spinePoint = SkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_SPINE]; // centerPoint = spinePoint; // if (hand == RIGHT) // { // handPoint = SkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_HAND_RIGHT]; // centerPoint.x += centerRightOver; // } // else // { // handPoint = SkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_HAND_LEFT]; // centerPoint.x -= centerLeftOver; // } // // Back to MOVECENTER // if (areClose(centerPoint, handPoint, detectRange)) // { // state->set(MOVECENTER); // startTime = getTimeIn100NSIntervals(); // return; // } // // Otherwise, keep looking (until the timeout) // break; // case MAGNIFYCENTER: // spinePoint = SkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_SPINE]; // centerPoint = spinePoint; // if (hand == RIGHT) // { // handPoint = SkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_HAND_RIGHT]; // centerPoint.x += centerRightOver; // } // else // { // handPoint = SkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_HAND_LEFT]; // centerPoint.x -= centerLeftOver; // } // // Place the direction arrows // upPoint = centerPoint; // upPoint.y += directionRadius; // if (areClose(upPoint, handPoint, detectRange)) // { // state->set(MAGNIFYUP); // return; // } // downPoint = centerPoint; // downPoint.y -= directionRadius; // if (areClose(downPoint, handPoint, detectRange)) // { // state->set(MAGNIFYDOWN); // startTime = getTimeIn100NSIntervals(); // return; // } // rightPoint = centerPoint; // rightPoint.x += directionRadius; // if (areClose(rightPoint, handPoint, detectRange)) // { // state->set(MAGNIFYRIGHT); // startTime = getTimeIn100NSIntervals(); // return; // } // leftPoint = centerPoint; // leftPoint.x -= directionRadius; // if (areClose(leftPoint, handPoint, detectRange)) // { // state->set(MAGNIFYLEFT); // startTime = getTimeIn100NSIntervals(); // return; // } // if (showOverlays) // { // clearOverlay(); // drawText ((xRes/3), (yRes/10), L"Rotate clockwise to decrease magnification and vice-versa to increase", 56); // // Center // drawRectangle ((xRes*3/4) - (boxSmall/2), (yRes/2) - (boxSmall/2), boxSmall, boxSmall, 0); // // Vert // drawRectangle ((xRes*3/4) - (boxSmall/2), (yRes/2) - (boxSmall/2) - overlayCircleRadius, boxSmall, boxSmall, 0); // drawRectangle ((xRes*3/4) - (boxSmall/2), (yRes/2) - (boxSmall/2) + overlayCircleRadius, boxSmall, boxSmall, 0); // // Horiz // drawRectangle ((xRes*3/4) - (boxSmall/2) - overlayCircleRadius, (yRes/2) - (boxSmall/2), boxSmall, boxSmall, 0); // drawRectangle ((xRes*3/4) - (boxSmall/2) + overlayCircleRadius, (yRes/2) - (boxSmall/2), boxSmall, boxSmall, 0); // } // // Otherwise, keep looking (until the timeout) // break; case MAGNIFYUP: spinePoint = SkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_SPINE]; centerPoint = spinePoint; if (hand == RIGHT) { handPoint = SkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_HAND_RIGHT]; centerPoint.x += centerRightOver; // Add velocity getDifference(handPoint, prevSkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_HAND_RIGHT], displacement_x, displacement_y); } else { handPoint = SkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_HAND_LEFT]; centerPoint.x -= centerLeftOver; // Add velocity getDifference(handPoint, prevSkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_HAND_LEFT], displacement_x, displacement_y); } // Place the direction arrows // upPoint = centerPoint; // upPoint.y += directionRadius; // if (areClose(upPoint, handPoint, detectRange)) // { // state->set(MAGNIFYUP); // return; // } // downPoint = centerPoint; // downPoint.y -= directionRadius; // if (areClose(downPoint, handPoint, detectRange)) // { // state->set(MAGNIFYDOWN); // startTime = getTimeIn100NSIntervals(); // return; // } rightPoint = centerPoint; rightPoint.x += directionRadius; if (areClose(rightPoint, handPoint, detectRange)) { state->set(MAGNIFYRIGHT); // Clockwise is increase magnification magnifyAmount += abs(displacement_x + displacement_y); startTime = getTimeIn100NSIntervals(); return; } leftPoint = centerPoint; leftPoint.x -= directionRadius; if (areClose(leftPoint, handPoint, detectRange)) { state->set(MAGNIFYLEFT); // Counterclockwise is decrease magnification magnifyAmount -= abs(displacement_x + displacement_y); startTime = getTimeIn100NSIntervals(); return; } if (showOverlays) { clearOverlay(); drawText ((xRes/3), (yRes/10), L"Clockwise = zoom in", 56); drawText ((xRes/3), (yRes*9/10), L"Counter-Clockwise = zoom out", 56); int ulx; int uly = (yRes/2) - (boxSmall/2); if (hand == RIGHT) { ulx = (xRes*3/4) - (boxSmall/2); } else { ulx = (xRes/4) - (boxSmall/2); } // Vert drawRectangle (ulx, uly - overlayCircleRadius, boxSmall, boxSmall, 1); drawRectangle (ulx, uly + overlayCircleRadius, boxSmall, boxSmall, 0); // Horiz drawRectangle (ulx - overlayCircleRadius, uly, boxSmall, boxSmall, 0); drawRectangle (ulx + overlayCircleRadius, uly, boxSmall, boxSmall, 0); } // Otherwise, keep looking (until the timeout) break; case MAGNIFYDOWN: spinePoint = SkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_SPINE]; centerPoint = spinePoint; if (hand == RIGHT) { handPoint = SkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_HAND_RIGHT]; centerPoint.x += centerRightOver; // Add velocity getDifference(handPoint, prevSkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_HAND_RIGHT], displacement_x, displacement_y); } else { handPoint = SkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_HAND_LEFT]; centerPoint.x -= centerLeftOver; // Add velocity getDifference(handPoint, prevSkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_HAND_LEFT], displacement_x, displacement_y); } // Place the direction arrows // upPoint = centerPoint; // upPoint.y += directionRadius; // if (areClose(upPoint, handPoint, detectRange)) // { // state->set(MAGNIFYUP); // return; // } // downPoint = centerPoint; // downPoint.y -= directionRadius; // if (areClose(downPoint, handPoint, detectRange)) // { // state->set(MAGNIFYDOWN); // startTime = getTimeIn100NSIntervals(); // return; // } rightPoint = centerPoint; rightPoint.x += directionRadius; if (areClose(rightPoint, handPoint, detectRange)) { state->set(MAGNIFYRIGHT); // Counterclockwise is increase magnification magnifyAmount -= abs(displacement_x + displacement_y); startTime = getTimeIn100NSIntervals(); return; } leftPoint = centerPoint; leftPoint.x -= directionRadius; if (areClose(leftPoint, handPoint, detectRange)) { state->set(MAGNIFYLEFT); // Clockwise is decrease magnification magnifyAmount += abs(displacement_x + displacement_y); startTime = getTimeIn100NSIntervals(); return; } if (showOverlays) { clearOverlay(); drawText ((xRes/3), (yRes/10), L"Clockwise = zoom in", 56); drawText ((xRes/3), (yRes*9/10), L"Counter-Clockwise = zoom out", 56); int ulx; int uly = (yRes/2) - (boxSmall/2); if (hand == RIGHT) { ulx = (xRes*3/4) - (boxSmall/2); } else { ulx = (xRes/4) - (boxSmall/2); } // Vert drawRectangle (ulx, uly - overlayCircleRadius, boxSmall, boxSmall, 0); drawRectangle (ulx, uly + overlayCircleRadius, boxSmall, boxSmall, 1); // Horiz drawRectangle (ulx - overlayCircleRadius, uly, boxSmall, boxSmall, 0); drawRectangle (ulx + overlayCircleRadius, uly, boxSmall, boxSmall, 0); } // Otherwise, keep looking (until the timeout) break; case MAGNIFYLEFT: spinePoint = SkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_SPINE]; centerPoint = spinePoint; if (hand == RIGHT) { handPoint = SkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_HAND_RIGHT]; centerPoint.x += centerRightOver; // Add velocity getDifference(handPoint, prevSkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_HAND_RIGHT], displacement_x, displacement_y); } else { handPoint = SkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_HAND_LEFT]; centerPoint.x -= centerLeftOver; // Add velocity getDifference(handPoint, prevSkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_HAND_LEFT], displacement_x, displacement_y); } // Place the direction arrows upPoint = centerPoint; upPoint.y += directionRadius; if (areClose(upPoint, handPoint, detectRange)) { state->set(MAGNIFYUP); // Clockwise is increase magnification magnifyAmount += abs(displacement_x + displacement_y); return; } downPoint = centerPoint; downPoint.y -= directionRadius; if (areClose(downPoint, handPoint, detectRange)) { state->set(MAGNIFYDOWN); // Counterclockwise is decrease magnification magnifyAmount -= abs(displacement_x + displacement_y); startTime = getTimeIn100NSIntervals(); return; } // rightPoint = centerPoint; // rightPoint.x += directionRadius; // if (areClose(rightPoint, handPoint, detectRange)) // { // state->set(MAGNIFYRIGHT); // // Clockwise is increase magnification // magnifyAmount += abs(displacement_x + displacement_y); // startTime = getTimeIn100NSIntervals(); // return; // } // leftPoint = centerPoint; // leftPoint.x -= directionRadius; // if (areClose(leftPoint, handPoint, detectRange)) // { // state->set(MAGNIFYLEFT); // // Counterclockwise is decrease magnification // magnifyAmount -= abs(displacement_x + displacement_y); // startTime = getTimeIn100NSIntervals(); // return; // } if (showOverlays) { clearOverlay(); drawText ((xRes/3), (yRes/10), L"Clockwise = zoom in", 56); drawText ((xRes/3), (yRes*9/10), L"Counter-Clockwise = zoom out", 56); int ulx; int uly = (yRes/2) - (boxSmall/2); if (hand == RIGHT) { ulx = (xRes*3/4) - (boxSmall/2); } else { ulx = (xRes/4) - (boxSmall/2); } // Vert drawRectangle (ulx, uly - overlayCircleRadius, boxSmall, boxSmall, 0); drawRectangle (ulx, uly + overlayCircleRadius, boxSmall, boxSmall, 0); // Horiz drawRectangle (ulx - overlayCircleRadius, uly, boxSmall, boxSmall, 1); drawRectangle (ulx + overlayCircleRadius, uly, boxSmall, boxSmall, 0); } // Otherwise, keep looking (until the timeout) break; case MAGNIFYRIGHT: spinePoint = SkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_SPINE]; centerPoint = spinePoint; if (hand == RIGHT) { handPoint = SkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_HAND_RIGHT]; centerPoint.x += centerRightOver; // Add velocity getDifference(handPoint, prevSkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_HAND_RIGHT], displacement_x, displacement_y); } else { handPoint = SkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_HAND_LEFT]; centerPoint.x -= centerLeftOver; // Add velocity getDifference(handPoint, prevSkeletonData.SkeletonPositions[NUI_SKELETON_POSITION_HAND_LEFT], displacement_x, displacement_y); } // Place the direction arrows upPoint = centerPoint; upPoint.y += directionRadius; if (areClose(upPoint, handPoint, detectRange)) { // Counterclockwise is decrease magnification magnifyAmount -= abs(displacement_x + displacement_y); state->set(MAGNIFYUP); return; } downPoint = centerPoint; downPoint.y -= directionRadius; if (areClose(downPoint, handPoint, detectRange)) { state->set(MAGNIFYDOWN); // Clockwise is increase magnification magnifyAmount += abs(displacement_x + displacement_y); startTime = getTimeIn100NSIntervals(); return; } // rightPoint = centerPoint; // rightPoint.x += directionRadius; // if (areClose(rightPoint, handPoint, detectRange)) // { // state->set(MAGNIFYRIGHT); // // Clockwise is increase magnification // magnifyAmount += abs(displacement_x + displacement_y); // startTime = getTimeIn100NSIntervals(); // return; // } // leftPoint = centerPoint; // leftPoint.x -= directionRadius; // if (areClose(leftPoint, handPoint, detectRange)) // { // state->set(MAGNIFYLEFT); // // Counterclockwise is decrease magnification // magnifyAmount -= abs(displacement_x + displacement_y); // startTime = getTimeIn100NSIntervals(); // return; // } if (showOverlays) { clearOverlay(); drawText ((xRes/3), (yRes/10), L"Clockwise = zoom in", 56); drawText ((xRes/3), (yRes*9/10), L"Counter-Clockwise = zoom out", 56); int ulx; int uly = (yRes/2) - (boxSmall/2); if (hand == RIGHT) { ulx = (xRes*3/4) - (boxSmall/2); } else { ulx = (xRes/4) - (boxSmall/2); } // Vert drawRectangle (ulx, uly - overlayCircleRadius, boxSmall, boxSmall, 0); drawRectangle (ulx, uly + overlayCircleRadius, boxSmall, boxSmall, 0); // Horiz drawRectangle (ulx - overlayCircleRadius, uly, boxSmall, boxSmall, 0); drawRectangle (ulx + overlayCircleRadius, uly, boxSmall, boxSmall, 1); } // Otherwise, keep looking (until the timeout) break; } }