bool OverlapTester::doLineAndRectangleOverlap(Line &l, Rectangle &r) { if (doLinesIntersect(l.getOrigin().getX(), l.getOrigin().getY(), l.getEnd().getX(), l.getEnd().getY(), r.getLowerLeft().getX(), r.getLowerLeft().getY() + r.getHeight() / 2, r.getLowerLeft().getX() + r.getWidth(), r.getLowerLeft().getY() + r.getHeight() / 2)) { return true; } if (doLinesIntersect(l.getOrigin().getX(), l.getOrigin().getY(), l.getEnd().getX(), l.getEnd().getY(), r.getLowerLeft().getX() + r.getWidth() / 2, r.getLowerLeft().getY(), r.getLowerLeft().getX() + r.getWidth() / 2, r.getLowerLeft().getY() + r.getHeight())) { return true; } return false; }
// called by Tcl Event loop to check for new data void TclTimerProc(ClientData clientData) { if (!isPenLoaderStarted()) { printLog("Timer stopped\n"); return; } // get the next stroke to analyze Stroke stroke = getNextAvailableStroke(); Tcl_CreateTimerHandler(TCL_TIMER_MS, &TclTimerProc, NULL); if (stroke.nSamples == 0) { return; } if (gameFinished) { printLog(" This game is already finished, skipping stroke\n"); return; } // if already have the board, determine and make the move if (numBoardLines == 4) { Line testLine = newLine(boardCenterX, boardCenterY, stroke.bounds.centerX, stroke.bounds.centerY); int crossing = (doLinesIntersect(&testLine, boardLeft)) ? CROSS_LEFT : CROSS_NONE; crossing |= (doLinesIntersect(&testLine, boardRight)) ? CROSS_RIGHT : CROSS_NONE; crossing |= (doLinesIntersect(&testLine, boardTop)) ? CROSS_TOP : CROSS_NONE; crossing |= (doLinesIntersect(&testLine, boardBottom)) ? CROSS_BOTTOM : CROSS_NONE; int move = CrossToMove[crossing]; if (move == -1) { printLog(" Invalid crossing value detected: %d, skipping\n", crossing); return; } else if (movesDone[move] != 0) { printLog(" Skipping duplicate move: %d\n", move); return; } movesDone[move] = currentPlayer; currentPlayer = (currentPlayer % 2) + 1; printLog(" Making move %d\n", move); char moveCommand[30]; sprintf(moveCommand, "ReturnFromHumanMove %d", move); Tcl_Eval(tclInterpreter, moveCommand); if (checkForFinishCondition()) { gameFinished = TRUE; printLog(" Game finished\n"); } return; } // otherwise, add the stroke to the board if (stroke.type != STROKE_LINE) { printLog(" Board isn't finished, skipping non-LINE stroke\n"); return; } boardLines[numBoardLines] = stroke.line; numBoardLines++; if (numBoardLines < 4) { return; } // determine board lines (two pairs of non-intersecting lines) int idx, match1b, match2a, match2b; match1b = 0; for (idx = 1; idx < 4; idx++) { if (!doLinesIntersect(&boardLines[0], &boardLines[idx])) { if (match1b != 0) { // matched twice, so something is wrong match1b = 0; break; } match1b = idx; match2a = (idx == 1) ? 2 : 1; match2b = (idx == 3) ? 2 : 3; } } // verify that matched lines intersect properly if ((match1b == 0) || (!doLinesIntersect(&boardLines[match1b], &boardLines[match2a])) || (!doLinesIntersect(&boardLines[match1b], &boardLines[match2b])) || (doLinesIntersect(&boardLines[match2a], &boardLines[match2b]))) { printLog(" Could not match board lines, trying again without first line\n"); boardLines[0] = boardLines[1]; boardLines[1] = boardLines[2]; boardLines[2] = boardLines[3]; numBoardLines = 3; return; } // assign proper sides (within 90 degree range away from pure vertical or horizontal) double angle = fabs(boardLines[0].angleDegrees); BOOL isLeft, isTop; int leftIdx, rightIdx, topIdx, bottomIdx; if (angle >= 45 && angle < 135) { // match 1 is vertical, match 2 is horizontal isLeft = (boardLines[0].centerX < boardLines[match1b].centerX); isTop = (boardLines[match2a].centerY < boardLines[match2b].centerY); leftIdx = isLeft ? 0 : match1b; rightIdx = isLeft ? match1b : 0; topIdx = isTop ? match2a : match2b; bottomIdx = isTop ? match2b : match2a; } else { // match 2 is vertical, match 1 is horizontal isLeft = (boardLines[match2a].centerX < boardLines[match2b].centerX); isTop = (boardLines[0].centerY < boardLines[match1b].centerY); leftIdx = isLeft ? match2a : match2b; rightIdx = isLeft ? match2b : match2a; topIdx = isTop ? 0 : match1b; bottomIdx = isTop ? match1b : 0; } boardLeft = &boardLines[leftIdx]; boardRight = &boardLines[rightIdx]; boardTop = &boardLines[topIdx]; boardBottom = &boardLines[bottomIdx]; // calculate center of the board (average of the 4 intersection points) double iLeftTop = intersectionPoint(boardLeft, boardTop); double iLeftBottom = intersectionPoint(boardLeft, boardBottom); double iRightTop = intersectionPoint(boardRight, boardTop); double iRightBottom = intersectionPoint(boardRight, boardBottom); boardCenterX = projectedX(boardLeft, iLeftTop, TRUE); boardCenterX += projectedX(boardLeft, iLeftBottom, TRUE); boardCenterX += projectedX(boardRight, iRightTop, TRUE); boardCenterX += projectedX(boardRight, iRightBottom, TRUE); boardCenterY = projectedY(boardLeft, iLeftTop, TRUE); boardCenterY += projectedY(boardLeft, iLeftBottom, TRUE); boardCenterY += projectedY(boardRight, iRightTop, TRUE); boardCenterY += projectedY(boardRight, iRightBottom, TRUE); boardCenterX /= 4; boardCenterY /= 4; printLog(" Detected board strokes: Left %d, Right %d, Top %d, Bottom %d, with center (%.3f, %.3f)\n", \ leftIdx, rightIdx, topIdx, bottomIdx, boardCenterX, boardCenterY); }