From 41e2851b25bbd12964307821becbf1bb3c923b48 Mon Sep 17 00:00:00 2001
From: Yuriy Maksymets <iurii.maksymets@gmail.com>
Date: Sun, 10 Nov 2019 17:40:09 +0000
Subject: [PATCH] Recognizing lines with angles (test)

---
 __tests__/shape.test.js | 151 +++++++++++++++++++++++++++++++++++++++-
 src/shapes.js           |  23 ++++--
 2 files changed, 167 insertions(+), 7 deletions(-)

diff --git a/__tests__/shape.test.js b/__tests__/shape.test.js
index 201a159..db3d23f 100644
--- a/__tests__/shape.test.js
+++ b/__tests__/shape.test.js
@@ -1,4 +1,4 @@
-import recognizeFromPoints, { Shapes } from "../src/shapes"
+import recognizeFromPoints, { Shapes, LineDirections } from "../src/shapes"
 
 describe("shape recognition", () => {
   describe("general", () => {
@@ -14,22 +14,171 @@ describe("shape recognition", () => {
       const points = [[0, 0], [100, 0]]
       const result = recognizeFromPoints(points)
       expect(result.shape).toBe(Shapes.line)
+      expect(result.direction).toBe(LineDirections.h)
     })
+
     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.direction).toBe(LineDirections.v)
     })
+
     test("should recognize a slightly curve horizontal line", () => {
       const points = [[0, 0], [30, 5], [100, 2]]
       const result = recognizeFromPoints(points)
       expect(result.shape).toBe(Shapes.line)
+      expect(result.direction).toBe(LineDirections.h)
     })
+
     test("should not recognize a really curved horizontal line", () => {
       const points = [[0, 0], [30, 30], [100, -4]]
       const result = recognizeFromPoints(points)
       expect(result.shape).not.toBe(Shapes.line)
     })
+
+    test("should recognize a long horizontal line", () => {
+      const points = [
+        [48.675496688741724, 197.8062913907285],
+        [50.66225165562914, 197.8062913907285],
+        [53.64238410596026, 197.8062913907285],
+        [57.6158940397351, 197.8062913907285],
+        [61.58940397350993, 197.8062913907285],
+        [66.55629139072848, 197.8062913907285],
+        [71.52317880794702, 197.8062913907285],
+        [76.49006622516558, 197.8062913907285],
+        [77.48344370860927, 197.8062913907285],
+        [82.45033112582782, 197.8062913907285],
+        [84.43708609271523, 197.8062913907285],
+        [87.41721854304636, 197.8062913907285],
+        [88.41059602649007, 197.8062913907285],
+        [88.41059602649007, 197.8062913907285],
+        [89.40397350993378, 197.8062913907285],
+      ]
+      const result = recognizeFromPoints(points)
+      expect(result.shape).toBe(Shapes.line)
+      expect(result.direction).toBe(LineDirections.h)
+    })
+
+    test("should recognize a long vertical line", () => {
+      const points = [
+        [218.54304635761588, 84.56125827814569],
+        [218.54304635761588, 86.54801324503312],
+        [218.54304635761588, 87.54139072847681],
+        [218.54304635761588, 88.53476821192052],
+        [218.54304635761588, 90.52152317880794],
+        [218.54304635761588, 91.51490066225165],
+        [218.54304635761588, 92.50827814569537],
+        [218.54304635761588, 93.50165562913908],
+        [218.54304635761588, 94.49503311258277],
+        [218.54304635761588, 94.49503311258277],
+        [218.54304635761588, 95.4884105960265],
+        [218.54304635761588, 96.4817880794702],
+        [218.54304635761588, 97.4751655629139],
+        [218.54304635761588, 98.46854304635761],
+        [218.54304635761588, 100.45529801324503],
+        [218.54304635761588, 101.44867549668874],
+        [218.54304635761588, 103.43543046357617],
+        [218.54304635761588, 105.42218543046357],
+        [218.54304635761588, 108.4023178807947],
+        [218.54304635761588, 110.38907284768212],
+        [218.54304635761588, 112.37582781456953],
+        [218.54304635761588, 114.36258278145695],
+        [218.54304635761588, 116.34933774834438],
+        [218.54304635761588, 118.33609271523179],
+        [218.54304635761588, 119.32947019867551],
+        [218.54304635761588, 120.3228476821192],
+        [218.54304635761588, 122.30960264900662],
+        [218.54304635761588, 123.30298013245033],
+        [218.54304635761588, 124.29635761589404],
+        [218.54304635761588, 125.28973509933775],
+        [218.54304635761588, 125.28973509933775],
+        [218.54304635761588, 125.28973509933775],
+        [218.54304635761588, 126.28311258278147],
+        [218.54304635761588, 126.28311258278147],
+        [218.54304635761588, 127.27649006622516],
+      ]
+      const result = recognizeFromPoints(points)
+      expect(result.shape).toBe(Shapes.line)
+      expect(result.direction).toBe(LineDirections.v)
+    })
+
+    test("should recognize a line at 20 degrees", () => {
+      const points = [
+        [34.7682119205298, 268.3360927152318],
+        [34.7682119205298, 268.3360927152318],
+        [36.75496688741722, 268.3360927152318],
+        [37.74834437086093, 268.3360927152318],
+        [38.741721854304636, 268.3360927152318],
+        [39.735099337748345, 268.3360927152318],
+        [40.728476821192054, 268.3360927152318],
+        [41.721854304635755, 268.3360927152318],
+        [42.71523178807947, 268.3360927152318],
+        [43.70860927152318, 268.3360927152318],
+        [43.70860927152318, 268.3360927152318],
+        [44.70198675496689, 268.3360927152318],
+        [44.70198675496689, 268.3360927152318],
+        [45.6953642384106, 267.3427152317881],
+        [45.6953642384106, 267.3427152317881],
+        [46.6887417218543, 267.3427152317881],
+        [47.682119205298015, 267.3427152317881],
+        [48.675496688741724, 266.34933774834434],
+        [48.675496688741724, 266.34933774834434],
+        [49.66887417218543, 266.34933774834434],
+        [50.66225165562914, 266.34933774834434],
+        [51.65562913907284, 265.35596026490066],
+        [52.64900662251656, 265.35596026490066],
+        [52.64900662251656, 265.35596026490066],
+        [53.64238410596026, 265.35596026490066],
+        [54.63576158940397, 264.362582781457],
+        [54.63576158940397, 264.362582781457],
+        [55.629139072847686, 264.362582781457],
+        [55.629139072847686, 264.362582781457],
+        [57.6158940397351, 263.36920529801324],
+        [57.6158940397351, 263.36920529801324],
+        [58.609271523178805, 263.36920529801324],
+        [58.609271523178805, 263.36920529801324],
+        [59.602649006622514, 262.37582781456956],
+        [60.59602649006623, 262.37582781456956],
+        [61.58940397350993, 262.37582781456956],
+        [62.58278145695365, 261.3824503311258],
+        [63.57615894039735, 261.3824503311258],
+        [64.56953642384106, 260.3890728476821],
+        [66.55629139072848, 259.3956953642384],
+        [67.54966887417218, 259.3956953642384],
+        [68.54304635761589, 259.3956953642384],
+        [69.5364238410596, 258.4023178807947],
+        [69.5364238410596, 258.4023178807947],
+        [70.52980132450331, 258.4023178807947],
+        [71.52317880794702, 258.4023178807947],
+        [71.52317880794702, 257.408940397351],
+        [71.52317880794702, 257.408940397351],
+        [72.51655629139073, 257.408940397351],
+        [72.51655629139073, 257.408940397351],
+        [72.51655629139073, 257.408940397351],
+        [73.50993377483444, 257.408940397351],
+        [73.50993377483444, 257.408940397351],
+        [73.50993377483444, 257.408940397351],
+        [74.50331125827815, 257.408940397351],
+        [76.49006622516558, 257.408940397351],
+        [77.48344370860927, 257.408940397351],
+        [79.47019867549669, 256.4155629139073],
+        [80.4635761589404, 256.4155629139073],
+        [82.45033112582782, 255.42218543046357],
+        [83.44370860927151, 255.42218543046357],
+        [84.43708609271523, 255.42218543046357],
+        [85.43046357615894, 255.42218543046357],
+        [85.43046357615894, 254.42880794701986],
+        [86.42384105960264, 254.42880794701986],
+        [86.42384105960264, 254.42880794701986],
+        [87.41721854304636, 254.42880794701986],
+        [87.41721854304636, 254.42880794701986],
+      ]
+
+      const result = recognizeFromPoints(points)
+      expect(result.shape).toBe(Shapes.line)
+      expect(result.direction).toBe(LineDirections.d20)
+    })
   })
 
   describe("rectangles", () => {
diff --git a/src/shapes.js b/src/shapes.js
index 72f8e71..4611b73 100644
--- a/src/shapes.js
+++ b/src/shapes.js
@@ -9,7 +9,7 @@ function sin(a) {
 }
 
 const rhoStep = 5
-const angleStep = 90
+const angleStep = 10
 const numAngleCells = 180 / angleStep
 const rhoMax = 1000
 
@@ -32,11 +32,7 @@ function findMaxInHough(accum, threshold) {
   bestTheta *= angleStep
 
   if (max > threshold) {
-    if (bestTheta === 90) {
-      return 90
-    } else {
-      return 0
-    }
+    return bestTheta
   }
   return undefined
 }
@@ -67,6 +63,7 @@ function recognizeFromPoints(points) {
   if (angle !== undefined) {
     return {
       shape: Shapes.line,
+      direction: getDirection(angle),
       points,
     }
   }
@@ -74,6 +71,20 @@ function recognizeFromPoints(points) {
   return {}
 }
 
+const dirMap = { 0: "v", 90: "h", 70: "d20" }
+
+function getDirection(angle) {
+  const map = dirMap[angle]
+  if (map == undefined) return angle
+  return LineDirections[map]
+}
+
+export const LineDirections = {
+  v: "v",
+  h: "h",
+  d20: "20",
+}
+
 export const Shapes = {
   rectangle: "rect",
   line: "line",
-- 
GitLab