From 7e5f6b57947471c0cffb54fa53679c45e40aed1c Mon Sep 17 00:00:00 2001 From: Yuriy Maksymets <iurii.maksymets@gmail.com> Date: Sat, 23 Nov 2019 12:32:36 +0000 Subject: [PATCH] Fixed tests to match new interfaces, minor refactor --- __tests__/shape.test.js | 45 ++++++++++++++--------------------------- src/app.js | 33 ++++++++++++++++-------------- src/shapes.js | 45 ++++++++++++++++++++++------------------- 3 files changed, 57 insertions(+), 66 deletions(-) diff --git a/__tests__/shape.test.js b/__tests__/shape.test.js index d7f4f36..bca2693 100644 --- a/__tests__/shape.test.js +++ b/__tests__/shape.test.js @@ -1,7 +1,4 @@ -import recognizeFromPoints, { - Shapes, - computeMatrixCoefficients, -} from "../src/shapes" +import recognizeFromPoints, { Shapes } from "../src/shapes" describe("shape recognition", () => { describe("general", () => { @@ -12,41 +9,30 @@ describe("shape recognition", () => { }) }) - describe("matrix coefficients", () => { - test("should compute coefficients correctly", () => { - const points = [[0, 0], [0, 5], [0, 10], [10, 5]] - const coefficients = computeMatrixCoefficients(points) - expect(coefficients).toStrictEqual([ - [1 / 4, 1 / 4, 1 / 4], - [0, 0, 0], - [0, 1 / 4, 0], - ]) - }) - }) - describe("lines", () => { test("should recognize a simple horizontal line", () => { const points = [[0, 0], [100, 0]] const result = recognizeFromPoints(points) expect(result.shape).toBe(Shapes.line) - expect(result.angle).toBe(0) + expect(result.firstPoint).toStrictEqual([0, 0]) + expect(result.lastPoint).toStrictEqual([100, 0]) }) test("should recognize a simple vertical line", () => { const points = [[0, 50], [0, -100]] const result = recognizeFromPoints(points) expect(result.shape).toBe(Shapes.line) - expect(result.angle).toBe(90) + expect(result.firstPoint).toStrictEqual([0, 50]) + expect(result.lastPoint).toStrictEqual([0, -100]) }) test("should recognize a slightly curve horizontal line", () => { const points = [[0, 0], [30, 5], [100, 0]] const result = recognizeFromPoints(points) expect(result.shape).toBe(Shapes.line) - expect(result.angle).toBe(0) }) - test("should not recognize a really curved horizontal line", () => { + test("should not recognize a heavily curved horizontal line", () => { const points = [[0, 0], [30, 30], [100, -4]] const result = recognizeFromPoints(points) expect(result.shape).not.toBe(Shapes.line) @@ -72,7 +58,6 @@ describe("shape recognition", () => { ] const result = recognizeFromPoints(points) expect(result.shape).toBe(Shapes.line) - expect(result.angle).toBe(0) }) test("should recognize a long vertical line", () => { @@ -115,7 +100,6 @@ describe("shape recognition", () => { ] const result = recognizeFromPoints(points) expect(result.shape).toBe(Shapes.line) - expect(result.angle).toBe(90) }) test("should recognize a line at 20 degrees", () => { @@ -192,7 +176,6 @@ describe("shape recognition", () => { const result = recognizeFromPoints(points) expect(result.shape).toBe(Shapes.line) - expect(result.angle).toBeGreaterThan(12) }) test("should recognize line 1", () => { @@ -328,12 +311,6 @@ describe("shape recognition", () => { describe("rectangles", () => { test("should recognize simple rectangle", () => { - const points = [[-10, -10], [10, -10], [10, 10], [-10, 10]] - const result = recognizeFromPoints(points) - expect(result.shape).toBe(Shapes.rectangle) - }) - - test("should recognize rectangle with many points", () => { const points = [ [0, 0], [5, 0], @@ -374,7 +351,15 @@ describe("shape recognition", () => { }) test("should recognize almost-closed rectangle", () => { - const points = [[-10, -10], [10, -10], [10, 10], [-9, 9]] + const points = [ + [0, 0], + [5, 0], + [10, 0], + [10, 5], + [10, 10], + [5, 10], + [0, 8], + ] const result = recognizeFromPoints(points) expect(result.shape).toBe(Shapes.rectangle) }) diff --git a/src/app.js b/src/app.js index 552aebd..876ed05 100644 --- a/src/app.js +++ b/src/app.js @@ -33,6 +33,21 @@ const getPressureFactor = (pressure) => { return a * pressure ** 2 + b * pressure + c } +const PREDICTED_POINT_COLOR = "#00000055" + +function faintPoint(x, y) { + return [x, y, 1, PREDICTED_POINT_COLOR] +} + +function attributedPoint(x, y, pressure = 0) { + return [ + x, + y, + toolSelection.getStrokeRadius() * getPressureFactor(pressure), + toolSelection.getStrokeColour(), + ] +} + let room = null const humanHasher = new humanhash() @@ -148,26 +163,13 @@ const onRoomConnect = (room_) => { ) } -function faintPoint(x, y) { - return [x, y, 1, "#00000033"] -} - -function attributedPoint(x, y, pressure = 0) { - return [ - x, - y, - toolSelection.getStrokeRadius() * getPressureFactor(pressure), - toolSelection.getStrokeColour(), - ] -} - function getRecognizedShapePoints(points) { const recognizedShape = recognizeFromPoints(points) if (!recognizedShape.shape) return undefined + switch (recognizedShape.shape) { case Shapes.line: { - const [x, y] = points[0] - const p1 = [x, y] + const p1 = recognizedShape.firstPoint const p2 = recognizedShape.lastPoint return [p1, p2] } @@ -175,6 +177,7 @@ function getRecognizedShapePoints(points) { return recognizedShape.boundingPoints } } + return undefined } diff --git a/src/shapes.js b/src/shapes.js index 1495ed8..e3fc050 100644 --- a/src/shapes.js +++ b/src/shapes.js @@ -7,7 +7,12 @@ const RECT_MATRIX_CENTER_RATIO = 0.65 const RECT_THRESHOLD_CENTER = 0 const RECT_THRESHOLD_SIDE_VARIANCE = 0.25 -function getDistance([x0, y0], [x1, y1]) { +const MIN_RECT_POINTS = 4 +const MIN_LINE_POINTS = 2 + +function getDistance(p1, p2) { + if (!(p1 && p2)) return 0 + const [[x0, y0], [x1, y1]] = [p1, p2] return Math.hypot(x1 - x0, y1 - y0) } @@ -85,12 +90,13 @@ export function computeMatrixCoefficients(points, boundingRect) { const xBounds = matrixBoundsArray(minX, maxX) const yBounds = matrixBoundsArray(minY, maxY) const clusters = computeClusters(points, xBounds, yBounds) + console.log(clusters) const coefficients = clusterCoefficients(clusters, points) return coefficients } function couldBeRect(points) { - if (points.length < 4) return false + if (points.length < MIN_RECT_POINTS) return false const boundingRect = boundingCoords(points) const matrixCoefficients = computeMatrixCoefficients(points, boundingRect) @@ -115,22 +121,23 @@ function couldBeRect(points) { } function couldBeLine(points) { - if (points.length < 2) return false + if (points.length < MIN_LINE_POINTS) return false + const vectorThreshold = Math.floor( points.length * VECTOR_LEN_THRESHOLD_FRACTION, ) const pivot = points[0] let cumulativeThreshold = 0 - for (let i = 2; i < points.length; i++) { - const p1 = points[i - 1] - const p2 = points[i] - const d1 = diffVector(pivot, p1) - const d2 = diffVector(p1, p2) - - const d2Len = vectorLength(d2) + for (let i = 2; i < points.length; i++) { + const prev = points[i - 1] + const curr = points[i] + const d1 = diffVector(pivot, prev) + const d2 = diffVector(prev, curr) const angle = angleBetweenVectors(d1, d2) + if (Math.abs(angle) > LINE_ANGLE_THRESHOLD) { + const d2Len = vectorLength(d2) if (cumulativeThreshold < vectorThreshold && d2Len < vectorThreshold) { cumulativeThreshold += d2Len continue @@ -141,10 +148,9 @@ function couldBeLine(points) { return true } -function recognizeRect(points, rectDetectionData) { +function recognizedRect(_, rectDetectionData) { const { minX, minY, maxX, maxY } = rectDetectionData.boundingRect return { - boundingRect: rectDetectionData.boundingRect, boundingPoints: [ [minX, minY], [minX, maxY], @@ -153,29 +159,26 @@ function recognizeRect(points, rectDetectionData) { [minX, minY], ], shape: Shapes.rectangle, - points, } } -function recognizeLine(points) { +function recognizedLine(points) { const [p1, p2] = [points[0], points[points.length - 1]] - const angle = - (angleBetweenVectors(diffVector(p2, p1), [1, 0]) / Math.PI) * 180 return { shape: Shapes.line, - angle, - points, - length: getDistance(p1, p2), + + // Take only [x, y] from the whole point tuple lastPoint: p2.slice(0, 2), + firstPoint: p1.slice(0, 2), } } function recognizeFromPoints(points) { const rectDetectData = couldBeRect(points) if (rectDetectData) { - return recognizeRect(points, rectDetectData) + return recognizedRect(points, rectDetectData) } else if (couldBeLine(points)) { - return recognizeLine(points) + return recognizedLine(points) } return {} -- GitLab