From 7f186ff963ff149a947d91bb0a5088f4153875a7 Mon Sep 17 00:00:00 2001 From: Edouard DUPIN Date: Sat, 20 Aug 2016 11:01:58 +0200 Subject: [PATCH] [DEV] first stable version --- .gitignore | 4 + README.md | 51 ++++++- data/figure/arrow_1.json | 15 ++ data/figure/circle_1.json | 73 ++++++++++ data/figure/circle_1.svg | 57 ++++++++ data/figure/diamond_1.json | 16 +++ data/figure/rectangle_1.json | 16 +++ data/figure/tick_1.json | 12 ++ data/figure/triangle_1.json | 14 ++ data/test/Arrow.json | 17 +++ data/test/P.json | 12 ++ data/text/A_1.json | 17 +++ data/text/B_1.json | 63 ++++++++ data/text/B_1.svg | 67 +++++++++ data/text/C_1.json | 42 ++++++ data/text/C_1.svg | 56 ++++++++ data/text/D_1.json | 46 ++++++ data/text/D_1.svg | 61 ++++++++ data/text/E_1.json | 16 +++ data/text/F_1.json | 14 ++ data/text/G_1.json | 50 +++++++ data/text/G_1.svg | 66 +++++++++ data/text/H_1.json | 14 ++ data/text/I_1.json | 14 ++ data/text/J_1.json | 35 +++++ data/text/J_1.svg | 61 ++++++++ data/text/K_1.json | 14 ++ data/text/L_1.json | 12 ++ data/text/M_1.json | 16 +++ data/text/N_1.json | 14 ++ data/text/O_1.json | 73 ++++++++++ data/text/O_1.svg | 57 ++++++++ data/text/P_1.json | 37 +++++ data/text/P_1.svg | 61 ++++++++ data/text/Q_1.json | 77 ++++++++++ data/text/Q_1.svg | 62 ++++++++ data/text/R_1.json | 41 ++++++ data/text/R_1.svg | 67 +++++++++ data/text/S_1.json | 56 ++++++++ data/text/S_1.svg | 56 ++++++++ data/text/T_1.json | 12 ++ data/text/U_1.json | 38 +++++ data/text/U_1.svg | 61 ++++++++ data/text/V_1.json | 14 ++ data/text/W_1.json | 16 +++ data/text/X_1.json | 12 ++ data/text/Y_1.json | 14 ++ data/text/Z_1.json | 14 ++ data/text/brace-left_1.json | 57 ++++++++ data/text/brace-left_1.svg | 56 ++++++++ data/text/brace-right_1.json | 57 ++++++++ data/text/brace-right_1.svg | 56 ++++++++ data/text/bracket-left_1.json | 14 ++ data/text/bracket-right_1.json | 14 ++ data/text/question-mark_1.json | 38 +++++ data/text/question-mark_1.svg | 56 ++++++++ data/text/slash-back_1.json | 11 ++ data/text/slash_1.json | 11 ++ data/text/star_1.json | 16 +++ dollar/Engine.cpp | 256 +++++++++++++++++++++++++++++++++ dollar/Engine.h | 42 ++++++ dollar/Gesture.cpp | 169 ++++++++++++++++++++++ dollar/Gesture.h | 57 ++++++++ dollar/Rectangle.cpp | 47 ++++++ dollar/Rectangle.h | 53 +++++++ dollar/Results.cpp | 47 ++++++ dollar/Results.h | 28 ++++ dollar/debug.cpp | 13 ++ dollar/debug.h | 45 ++++++ dollar/tools.cpp | 209 +++++++++++++++++++++++++++ dollar/tools.h | 106 ++++++++++++++ lutin_dollar-converter.py | 37 +++++ lutin_dollar-data.py | 30 ++++ lutin_dollar-test.py | 39 +++++ lutin_dollar.py | 57 ++++++++ test/main.cpp | 92 ++++++++++++ tool/converter/main.cpp | 79 ++++++++++ 77 files changed, 3523 insertions(+), 2 deletions(-) create mode 100644 data/figure/arrow_1.json create mode 100644 data/figure/circle_1.json create mode 100644 data/figure/circle_1.svg create mode 100644 data/figure/diamond_1.json create mode 100644 data/figure/rectangle_1.json create mode 100644 data/figure/tick_1.json create mode 100644 data/figure/triangle_1.json create mode 100644 data/test/Arrow.json create mode 100644 data/test/P.json create mode 100644 data/text/A_1.json create mode 100644 data/text/B_1.json create mode 100644 data/text/B_1.svg create mode 100644 data/text/C_1.json create mode 100644 data/text/C_1.svg create mode 100644 data/text/D_1.json create mode 100644 data/text/D_1.svg create mode 100644 data/text/E_1.json create mode 100644 data/text/F_1.json create mode 100644 data/text/G_1.json create mode 100644 data/text/G_1.svg create mode 100644 data/text/H_1.json create mode 100644 data/text/I_1.json create mode 100644 data/text/J_1.json create mode 100644 data/text/J_1.svg create mode 100644 data/text/K_1.json create mode 100644 data/text/L_1.json create mode 100644 data/text/M_1.json create mode 100644 data/text/N_1.json create mode 100644 data/text/O_1.json create mode 100644 data/text/O_1.svg create mode 100644 data/text/P_1.json create mode 100644 data/text/P_1.svg create mode 100644 data/text/Q_1.json create mode 100644 data/text/Q_1.svg create mode 100644 data/text/R_1.json create mode 100644 data/text/R_1.svg create mode 100644 data/text/S_1.json create mode 100644 data/text/S_1.svg create mode 100644 data/text/T_1.json create mode 100644 data/text/U_1.json create mode 100644 data/text/U_1.svg create mode 100644 data/text/V_1.json create mode 100644 data/text/W_1.json create mode 100644 data/text/X_1.json create mode 100644 data/text/Y_1.json create mode 100644 data/text/Z_1.json create mode 100644 data/text/brace-left_1.json create mode 100644 data/text/brace-left_1.svg create mode 100644 data/text/brace-right_1.json create mode 100644 data/text/brace-right_1.svg create mode 100644 data/text/bracket-left_1.json create mode 100644 data/text/bracket-right_1.json create mode 100644 data/text/question-mark_1.json create mode 100644 data/text/question-mark_1.svg create mode 100644 data/text/slash-back_1.json create mode 100644 data/text/slash_1.json create mode 100644 data/text/star_1.json create mode 100644 dollar/Engine.cpp create mode 100644 dollar/Engine.h create mode 100644 dollar/Gesture.cpp create mode 100644 dollar/Gesture.h create mode 100644 dollar/Rectangle.cpp create mode 100644 dollar/Rectangle.h create mode 100644 dollar/Results.cpp create mode 100644 dollar/Results.h create mode 100644 dollar/debug.cpp create mode 100644 dollar/debug.h create mode 100644 dollar/tools.cpp create mode 100644 dollar/tools.h create mode 100644 lutin_dollar-converter.py create mode 100644 lutin_dollar-data.py create mode 100644 lutin_dollar-test.py create mode 100644 lutin_dollar.py create mode 100644 test/main.cpp create mode 100644 tool/converter/main.cpp diff --git a/.gitignore b/.gitignore index 4581ef2..baacc5e 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,7 @@ *.exe *.out *.app + +#python temporary files +__pycache__ +*.pyc diff --git a/README.md b/README.md index 3861db9..57d5e88 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,49 @@ -# dollar -[APACHE-2] $1 and $N recognition (ready for prod...) +dollar +====== + +`dollar` is a $1 and $N gesture recognition + + +Instructions +============ + +download Build system: +---------------------- + + sudo pip install lutin + sudo pip install pillow + +download the software: +---------------------- + + mkdir WORKING_DIRECTORY + cd WORKING_DIRECTORY + git clone https://github.com/atria-soft/etk.git + git clone https://github.com/atria-soft/ejson.git + git clone https://github.com/generic-library/gtest-lutin.git --recursive + git clone https://github.com/generic-library/z-lutin.git --recursive + +Compile software: +----------------- + + cd WORKING_DIRECTORY + lutin dollar-test?build?run + + +License (APACHE v2.0) +===================== +Copyright dollar Edouard DUPIN + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + + diff --git a/data/figure/arrow_1.json b/data/figure/arrow_1.json new file mode 100644 index 0000000..07f4d28 --- /dev/null +++ b/data/figure/arrow_1.json @@ -0,0 +1,15 @@ +{ + "type":"REFERENCE", + "value":"arrow", + "sub-id":1, + "data":[ + [ + [0.00,0.50], + [1.00,0.50] + ],[ + [0.75,0.60], + [1.00,0.50], + [0.75,0.40] + ] + ] +} \ No newline at end of file diff --git a/data/figure/circle_1.json b/data/figure/circle_1.json new file mode 100644 index 0000000..a019c32 --- /dev/null +++ b/data/figure/circle_1.json @@ -0,0 +1,73 @@ +{ + "type": "REFERENCE", + "value": "circle", + "sub-id": 1, + "data": [ + [ + [ 1, 0.500000 ], + [ 0.997419, 0.551122 ], + [ 0.989842, 0.600767 ], + [ 0.977521, 0.648685 ], + [ 0.960707, 0.694623 ], + [ 0.939653, 0.738330 ], + [ 0.914608, 0.779555 ], + [ 0.885824, 0.818046 ], + [ 0.853553, 0.853553 ], + [ 0.818046, 0.885824 ], + [ 0.779555, 0.914608 ], + [ 0.738330, 0.939653 ], + [ 0.694623, 0.960707 ], + [ 0.648685, 0.977521 ], + [ 0.600767, 0.989842 ], + [ 0.551122, 0.997418 ], + [ 0.500000, 1.000000 ], + [ 0.448878, 0.997418 ], + [ 0.399233, 0.989842 ], + [ 0.351315, 0.977521 ], + [ 0.305377, 0.960707 ], + [ 0.261670, 0.939653 ], + [ 0.220445, 0.914608 ], + [ 0.181954, 0.885824 ], + [ 0.146447, 0.853553 ], + [ 0.114176, 0.818046 ], + [ 0.085392, 0.779555 ], + [ 0.060347, 0.738330 ], + [ 0.039292, 0.694623 ], + [ 0.022479, 0.648685 ], + [ 0.010158, 0.600767 ], + [ 0.002581, 0.551122 ], + [ 0, 0.500000 ], + [ 0.002581, 0.448878 ], + [ 0.010158, 0.399233 ], + [ 0.022479, 0.351315 ], + [ 0.039292, 0.305377 ], + [ 0.060347, 0.261670 ], + [ 0.085392, 0.220445 ], + [ 0.114176, 0.181954 ], + [ 0.146447, 0.146447 ], + [ 0.181954, 0.114176 ], + [ 0.220445, 0.085392 ], + [ 0.261670, 0.060347 ], + [ 0.305377, 0.039292 ], + [ 0.351315, 0.022479 ], + [ 0.399233, 0.010158 ], + [ 0.448878, 0.002581 ], + [ 0.500000, 0 ], + [ 0.551122, 0.002581 ], + [ 0.600767, 0.010158 ], + [ 0.648685, 0.022479 ], + [ 0.694623, 0.039292 ], + [ 0.738330, 0.060347 ], + [ 0.779555, 0.085392 ], + [ 0.818046, 0.114176 ], + [ 0.853553, 0.146447 ], + [ 0.885824, 0.181954 ], + [ 0.914608, 0.220445 ], + [ 0.939653, 0.261670 ], + [ 0.960707, 0.305377 ], + [ 0.977521, 0.351315 ], + [ 0.989842, 0.399233 ], + [ 0.997419, 0.448878 ] + ] + ] +} diff --git a/data/figure/circle_1.svg b/data/figure/circle_1.svg new file mode 100644 index 0000000..75f7539 --- /dev/null +++ b/data/figure/circle_1.svg @@ -0,0 +1,57 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/data/figure/diamond_1.json b/data/figure/diamond_1.json new file mode 100644 index 0000000..6b9181d --- /dev/null +++ b/data/figure/diamond_1.json @@ -0,0 +1,16 @@ +{ + "type":"REFERENCE", + "value":"diamond", + "sub-id":1, + "data":[ + [ + [0.5,0.0],[1.0,0.5] + ],[ + [1.0,0.5],[0.5,1.0] + ],[ + [0.5,1.0],[0.0,0.5] + ],[ + [0.0,0.5],[0.5,0.0] + ] + ] +} \ No newline at end of file diff --git a/data/figure/rectangle_1.json b/data/figure/rectangle_1.json new file mode 100644 index 0000000..4226913 --- /dev/null +++ b/data/figure/rectangle_1.json @@ -0,0 +1,16 @@ +{ + "type":"REFERENCE", + "value":"rectangle", + "sub-id":1, + "data":[ + [ + [0.0,0.0],[1.0,0.0] + ],[ + [1.0,0.0],[1.0,1.0] + ],[ + [1.0,1.0],[0.0,1.0] + ],[ + [0.0,1.0],[0.0,0.0] + ] + ] +} \ No newline at end of file diff --git a/data/figure/tick_1.json b/data/figure/tick_1.json new file mode 100644 index 0000000..442c344 --- /dev/null +++ b/data/figure/tick_1.json @@ -0,0 +1,12 @@ +{ + "type":"REFERENCE", + "value":"tick", + "sub-id":1, + "data":[ + [ + [0.0,0.5], + [0.5,0.0], + [1.0,1.0] + ] + ] +} \ No newline at end of file diff --git a/data/figure/triangle_1.json b/data/figure/triangle_1.json new file mode 100644 index 0000000..10f570e --- /dev/null +++ b/data/figure/triangle_1.json @@ -0,0 +1,14 @@ +{ + "type":"REFERENCE", + "value":"triangle", + "sub-id":1, + "data":[ + [ + [0.0,0.0],[1.0,0.0] + ],[ + [1.0,0.0],[0.5,1.0] + ],[ + [0.0,0.0],[0.5,1.0] + ] + ] +} \ No newline at end of file diff --git a/data/test/Arrow.json b/data/test/Arrow.json new file mode 100644 index 0000000..0b246da --- /dev/null +++ b/data/test/Arrow.json @@ -0,0 +1,17 @@ +{ + "data":[ + [ + [68,222],[70,220],[73,218],[75,217],[77,215],[80,213], + [82,212],[84,210],[87,209],[89,208],[92,206],[95,204], + [101,201],[106,198],[112,194],[118,191],[124,187],[127,186], + [132,183],[138,181],[141,180],[146,178],[154,173],[159,171], + [161,170],[166,167],[168,167],[171,166],[174,164],[177,162], + [180,160],[182,158],[183,156],[181,154],[178,153],[171,153], + [164,153],[160,153],[150,154],[147,155],[141,157],[137,158], + [135,158],[137,158],[140,157],[143,156],[151,154],[160,152], + [170,149],[179,147],[185,145],[192,144],[196,144],[198,144], + [200,144],[201,147],[199,149],[194,157],[191,160],[186,167], + [180,176],[177,179],[171,187],[169,189],[165,194],[164,196], + ] + ] +} \ No newline at end of file diff --git a/data/test/P.json b/data/test/P.json new file mode 100644 index 0000000..e54de8a --- /dev/null +++ b/data/test/P.json @@ -0,0 +1,12 @@ +{ + "data":[ + [ + [507,8],[507,87] + ], [ + [510,7],[528,7],[530,8], + [544,10],[550,12],[550,15],[558,20],[560,22],[561,27], + [562,33],[561,37],[559,42],[556,45],[550,48],[544,51], + [538,53],[532,54],[525,55],[519,55],[513,55],[510,55] + ] + ] +} \ No newline at end of file diff --git a/data/text/A_1.json b/data/text/A_1.json new file mode 100644 index 0000000..073b628 --- /dev/null +++ b/data/text/A_1.json @@ -0,0 +1,17 @@ +{ + "type":"REFERENCE", + "value":"A", + "sub-id":1, + "data":[ + [ + [0.00,0.00], + [0.50,1.00] + ],[ + [0.50,1.00], + [1.00,0.00] + ],[ + [0.25,0.50], + [0.75,0.50] + ] + ] +} \ No newline at end of file diff --git a/data/text/B_1.json b/data/text/B_1.json new file mode 100644 index 0000000..f9d9314 --- /dev/null +++ b/data/text/B_1.json @@ -0,0 +1,63 @@ +{ + "type": "REFERENCE", + "value": "B", + "sub-id": 1, + "data": [ + [ + [ 0, 0 ], + [ 0, 1 ] + ], + [ + [ 0, 0.003491 ], + [ 0.232282, 0.009006 ], + [ 0.434124, 0.024593 ], + [ 0.605421, 0.048818 ], + [ 0.746066, 0.080245 ], + [ 0.855952, 0.117437 ], + [ 0.899328, 0.137747 ], + [ 0.934975, 0.158959 ], + [ 0.962878, 0.180896 ], + [ 0.983026, 0.203376 ], + [ 0.995404, 0.226222 ], + [ 1.000000, 0.249252 ], + [ 0.996800, 0.272289 ], + [ 0.985791, 0.295152 ], + [ 0.966959, 0.317662 ], + [ 0.940291, 0.339639 ], + [ 0.905775, 0.360904 ], + [ 0.863396, 0.381278 ], + [ 0.813142, 0.400581 ], + [ 0.754998, 0.418634 ], + [ 0.614992, 0.450271 ], + [ 0.443271, 0.474752 ], + [ 0.239728, 0.490644 ], + [ 0.004257, 0.496509 ] + ], + [ + [ 0, 0.503491 ], + [ 0.232282, 0.509006 ], + [ 0.434124, 0.524593 ], + [ 0.605421, 0.548818 ], + [ 0.746066, 0.580245 ], + [ 0.855952, 0.617437 ], + [ 0.899328, 0.637747 ], + [ 0.934975, 0.658959 ], + [ 0.962878, 0.680896 ], + [ 0.983026, 0.703376 ], + [ 0.995404, 0.726222 ], + [ 1.000000, 0.749252 ], + [ 0.996800, 0.772289 ], + [ 0.985791, 0.795152 ], + [ 0.966959, 0.817662 ], + [ 0.940291, 0.839639 ], + [ 0.905775, 0.860904 ], + [ 0.863396, 0.881278 ], + [ 0.813142, 0.900581 ], + [ 0.754998, 0.918634 ], + [ 0.614992, 0.950271 ], + [ 0.443271, 0.974752 ], + [ 0.239728, 0.990644 ], + [ 0.004257, 0.996509 ] + ] + ] +} diff --git a/data/text/B_1.svg b/data/text/B_1.svg new file mode 100644 index 0000000..32adc55 --- /dev/null +++ b/data/text/B_1.svg @@ -0,0 +1,67 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/data/text/C_1.json b/data/text/C_1.json new file mode 100644 index 0000000..71b953f --- /dev/null +++ b/data/text/C_1.json @@ -0,0 +1,42 @@ +{ + "type": "REFERENCE", + "value": "C", + "sub-id": 1, + "data": [ + [ + [ 1, 0.147941 ], + [ 0.880008, 0.089209 ], + [ 0.767615, 0.046089 ], + [ 0.662835, 0.017541 ], + [ 0.565684, 0.002524 ], + [ 0.476174, 0 ], + [ 0.394320, 0.008928 ], + [ 0.320137, 0.028268 ], + [ 0.253638, 0.056979 ], + [ 0.194838, 0.094023 ], + [ 0.143752, 0.138359 ], + [ 0.100392, 0.188947 ], + [ 0.064774, 0.244747 ], + [ 0.036911, 0.304719 ], + [ 0.016819, 0.367824 ], + [ 0.004510, 0.433020 ], + [ 0, 0.499268 ], + [ 0.003302, 0.565529 ], + [ 0.014431, 0.630761 ], + [ 0.033401, 0.693926 ], + [ 0.060226, 0.753983 ], + [ 0.094920, 0.809892 ], + [ 0.137498, 0.860613 ], + [ 0.187974, 0.905106 ], + [ 0.246362, 0.942331 ], + [ 0.312676, 0.971249 ], + [ 0.386930, 0.990818 ], + [ 0.469139, 1 ], + [ 0.559317, 0.997754 ], + [ 0.657477, 0.983040 ], + [ 0.763635, 0.954818 ], + [ 0.877805, 0.912049 ], + [ 1, 0.853691 ] + ] + ] +} diff --git a/data/text/C_1.svg b/data/text/C_1.svg new file mode 100644 index 0000000..32ca8eb --- /dev/null +++ b/data/text/C_1.svg @@ -0,0 +1,56 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/data/text/D_1.json b/data/text/D_1.json new file mode 100644 index 0000000..075ff29 --- /dev/null +++ b/data/text/D_1.json @@ -0,0 +1,46 @@ +{ + "type": "REFERENCE", + "value": "D", + "sub-id": 1, + "data": [ + [ + [ 0, 0 ], + [ 0, 256 ] + ], + [ + [ 0, -1.084746 ], + [ 30.558805, -0.344010 ], + [ 59.182121, 1.815285 ], + [ 85.866562, 5.298776 ], + [ 110.608734, 10.012094 ], + [ 133.405258, 15.860873 ], + [ 154.252762, 22.750751 ], + [ 173.147842, 30.587358 ], + [ 190.087112, 39.276329 ], + [ 205.067184, 48.723301 ], + [ 218.084686, 58.833897 ], + [ 229.136200, 69.513771 ], + [ 238.218399, 80.668533 ], + [ 245.327850, 92.203842 ], + [ 250.461166, 104.025307 ], + [ 253.614990, 116.038582 ], + [ 254.785934, 128.149292 ], + [ 253.970581, 140.263077 ], + [ 251.165573, 152.285568 ], + [ 246.367538, 164.122406 ], + [ 239.573044, 175.679199 ], + [ 230.778732, 186.861603 ], + [ 219.981201, 197.575256 ], + [ 207.177109, 207.725769 ], + [ 192.362991, 217.218811 ], + [ 175.535507, 225.959976 ], + [ 156.691330, 233.854935 ], + [ 135.826981, 240.809296 ], + [ 112.939117, 246.728699 ], + [ 88.024353, 251.518784 ], + [ 61.079292, 255.085190 ], + [ 32.100552, 257.333557 ], + [ 1.084746, 258.169495 ] + ] + ] +} diff --git a/data/text/D_1.svg b/data/text/D_1.svg new file mode 100644 index 0000000..58d2c18 --- /dev/null +++ b/data/text/D_1.svg @@ -0,0 +1,61 @@ + + + + + + image/svg+xml + + + + + + + + + + diff --git a/data/text/E_1.json b/data/text/E_1.json new file mode 100644 index 0000000..cef8f98 --- /dev/null +++ b/data/text/E_1.json @@ -0,0 +1,16 @@ +{ + "type":"REFERENCE", + "value":"E", + "sub-id":1, + "data":[ + [ + [0.0,0.0],[0.0,1.0] + ],[ + [0.0,0.0],[1.0,0.0] + ],[ + [0.0,0.5],[1.0,0.5] + ],[ + [0.0,1.0],[1.0,1.0] + ] + ] +} \ No newline at end of file diff --git a/data/text/F_1.json b/data/text/F_1.json new file mode 100644 index 0000000..e92767f --- /dev/null +++ b/data/text/F_1.json @@ -0,0 +1,14 @@ +{ + "type":"REFERENCE", + "value":"F", + "sub-id":1, + "data":[ + [ + [0.0,0.0],[0.0,1.0] + ],[ + [0.0,0.5],[1.0,0.5] + ],[ + [0.0,1.0],[1.0,1.0] + ] + ] +} \ No newline at end of file diff --git a/data/text/G_1.json b/data/text/G_1.json new file mode 100644 index 0000000..2370cd1 --- /dev/null +++ b/data/text/G_1.json @@ -0,0 +1,50 @@ +{ + "type": "REFERENCE", + "value": "G", + "sub-id": 1, + "data": [ + [ + [ 1, 0.140482 ], + [ 0.852131, 0.079876 ], + [ 0.717526, 0.037124 ], + [ 0.595810, 0.010931 ], + [ 0.486605, 0 ], + [ 0.389537, 0.003035 ], + [ 0.304228, 0.018739 ], + [ 0.230304, 0.045815 ], + [ 0.167387, 0.082968 ], + [ 0.115103, 0.128901 ], + [ 0.073075, 0.182317 ], + [ 0.040926, 0.241921 ], + [ 0.018282, 0.306415 ], + [ 0.004765, 0.374503 ], + [ 0, 0.444889 ], + [ 0.003611, 0.516276 ], + [ 0.015222, 0.587368 ], + [ 0.034456, 0.656868 ], + [ 0.060939, 0.723480 ], + [ 0.094293, 0.785908 ], + [ 0.134143, 0.842855 ], + [ 0.180113, 0.893024 ], + [ 0.231826, 0.935120 ], + [ 0.288907, 0.967845 ], + [ 0.350979, 0.989904 ], + [ 0.417667, 1.000000 ], + [ 0.488595, 0.996836 ], + [ 0.563387, 0.979116 ], + [ 0.641665, 0.945544 ], + [ 0.723056, 0.894823 ], + [ 0.807182, 0.825656 ], + [ 0.893667, 0.736748 ], + [ 0.982136, 0.626801 ] + ], + [ + [ 0.511234, 0.615937 ], + [ 0.993572, 0.615937 ] + ], + [ + [ 0.993572, 0.979437 ], + [ 0.993572, 0.611660 ] + ] + ] +} diff --git a/data/text/G_1.svg b/data/text/G_1.svg new file mode 100644 index 0000000..fdea3b8 --- /dev/null +++ b/data/text/G_1.svg @@ -0,0 +1,66 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/data/text/H_1.json b/data/text/H_1.json new file mode 100644 index 0000000..e7aa8c8 --- /dev/null +++ b/data/text/H_1.json @@ -0,0 +1,14 @@ +{ + "type":"REFERENCE", + "value":"H", + "sub-id":1, + "data":[ + [ + [0.0,0.0],[0.0,1.0] + ],[ + [0.0,0.5],[0.0,0.5] + ],[ + [1.0,0.0],[1.0,1.0] + ] + ] +} \ No newline at end of file diff --git a/data/text/I_1.json b/data/text/I_1.json new file mode 100644 index 0000000..4cce55a --- /dev/null +++ b/data/text/I_1.json @@ -0,0 +1,14 @@ +{ + "type":"REFERENCE", + "value":"I", + "sub-id":1, + "data":[ + [ + [0.25,0.0],[0.75,0.0] + ],[ + [0.5,0.0],[0.5,1.0] + ],[ + [0.25,1.0],[0.75,1.0] + ] + ] +} \ No newline at end of file diff --git a/data/text/J_1.json b/data/text/J_1.json new file mode 100644 index 0000000..0a12ae9 --- /dev/null +++ b/data/text/J_1.json @@ -0,0 +1,35 @@ +{ + "type": "REFERENCE", + "value": "J", + "sub-id": 1, + "data": [ + [ + [ 0.500000, 0 ], + [ 0.503189, 0.252934 ], + [ 0.494712, 0.462548 ], + [ 0.476102, 0.632184 ], + [ 0.448895, 0.765185 ], + [ 0.432547, 0.818994 ], + [ 0.414624, 0.864897 ], + [ 0.395320, 0.903314 ], + [ 0.374825, 0.934662 ], + [ 0.353332, 0.959359 ], + [ 0.331032, 0.977824 ], + [ 0.308117, 0.990473 ], + [ 0.284779, 0.997726 ], + [ 0.261209, 1.000000 ], + [ 0.237600, 0.997713 ], + [ 0.191031, 0.981127 ], + [ 0.146605, 0.951313 ], + [ 0.105857, 0.911614 ], + [ 0.070322, 0.865373 ], + [ 0.041534, 0.815934 ], + [ 0.021027, 0.766642 ], + [ 0.010336, 0.720839 ] + ], + [ + [ 1, 0.005057 ], + [ 0, 0.005057 ] + ] + ] +} diff --git a/data/text/J_1.svg b/data/text/J_1.svg new file mode 100644 index 0000000..b5c8bc9 --- /dev/null +++ b/data/text/J_1.svg @@ -0,0 +1,61 @@ + + + + + + image/svg+xml + + + + + + + + + + diff --git a/data/text/K_1.json b/data/text/K_1.json new file mode 100644 index 0000000..af60081 --- /dev/null +++ b/data/text/K_1.json @@ -0,0 +1,14 @@ +{ + "type":"REFERENCE", + "value":"K", + "sub-id":1, + "data":[ + [ + [0.0,0.0],[0.0,1.0] + ],[ + [0.0,0.5],[1.0,0.0] + ],[ + [0.0,0.5],[1.0,1.0] + ] + ] +} \ No newline at end of file diff --git a/data/text/L_1.json b/data/text/L_1.json new file mode 100644 index 0000000..1390e35 --- /dev/null +++ b/data/text/L_1.json @@ -0,0 +1,12 @@ +{ + "type":"REFERENCE", + "value":"L", + "sub-id":1, + "data":[ + [ + [0.0,0.0],[0.0,1.0] + ],[ + [0.0,0.0],[1.0,0.0] + ] + ] +} \ No newline at end of file diff --git a/data/text/M_1.json b/data/text/M_1.json new file mode 100644 index 0000000..f4d49aa --- /dev/null +++ b/data/text/M_1.json @@ -0,0 +1,16 @@ +{ + "type":"REFERENCE", + "value":"M", + "sub-id":1, + "data":[ + [ + [0.0,0.0],[0.0,1.0] + ],[ + [0.0,1.0],[0.5,0.5] + ],[ + [0.5,0.5],[1.0,1.0] + ],[ + [1.0,0.0],[1.0,1.0] + ] + ] +} \ No newline at end of file diff --git a/data/text/N_1.json b/data/text/N_1.json new file mode 100644 index 0000000..24295f5 --- /dev/null +++ b/data/text/N_1.json @@ -0,0 +1,14 @@ +{ + "type":"REFERENCE", + "value":"N", + "sub-id":1, + "data":[ + [ + [0.0,0.0],[0.0,1.0] + ],[ + [0.0,1.0],[1.0,0.0] + ],[ + [1.0,0.0],[1.0,1.0] + ] + ] +} \ No newline at end of file diff --git a/data/text/O_1.json b/data/text/O_1.json new file mode 100644 index 0000000..d9fae09 --- /dev/null +++ b/data/text/O_1.json @@ -0,0 +1,73 @@ +{ + "type": "REFERENCE", + "value": "O", + "sub-id": 1, + "data": [ + [ + [ 1, 0.500000 ], + [ 0.997419, 0.551122 ], + [ 0.989842, 0.600767 ], + [ 0.977521, 0.648685 ], + [ 0.960707, 0.694623 ], + [ 0.939653, 0.738330 ], + [ 0.914608, 0.779555 ], + [ 0.885824, 0.818046 ], + [ 0.853553, 0.853553 ], + [ 0.818046, 0.885824 ], + [ 0.779555, 0.914608 ], + [ 0.738330, 0.939653 ], + [ 0.694623, 0.960707 ], + [ 0.648685, 0.977521 ], + [ 0.600767, 0.989842 ], + [ 0.551122, 0.997418 ], + [ 0.500000, 1.000000 ], + [ 0.448878, 0.997418 ], + [ 0.399233, 0.989842 ], + [ 0.351315, 0.977521 ], + [ 0.305377, 0.960707 ], + [ 0.261670, 0.939653 ], + [ 0.220445, 0.914608 ], + [ 0.181954, 0.885824 ], + [ 0.146447, 0.853553 ], + [ 0.114176, 0.818046 ], + [ 0.085392, 0.779555 ], + [ 0.060347, 0.738330 ], + [ 0.039292, 0.694623 ], + [ 0.022479, 0.648685 ], + [ 0.010158, 0.600767 ], + [ 0.002581, 0.551122 ], + [ 0, 0.500000 ], + [ 0.002581, 0.448878 ], + [ 0.010158, 0.399233 ], + [ 0.022479, 0.351315 ], + [ 0.039292, 0.305377 ], + [ 0.060347, 0.261670 ], + [ 0.085392, 0.220445 ], + [ 0.114176, 0.181954 ], + [ 0.146447, 0.146447 ], + [ 0.181954, 0.114176 ], + [ 0.220445, 0.085392 ], + [ 0.261670, 0.060347 ], + [ 0.305377, 0.039292 ], + [ 0.351315, 0.022479 ], + [ 0.399233, 0.010158 ], + [ 0.448878, 0.002581 ], + [ 0.500000, 0 ], + [ 0.551122, 0.002581 ], + [ 0.600767, 0.010158 ], + [ 0.648685, 0.022479 ], + [ 0.694623, 0.039292 ], + [ 0.738330, 0.060347 ], + [ 0.779555, 0.085392 ], + [ 0.818046, 0.114176 ], + [ 0.853553, 0.146447 ], + [ 0.885824, 0.181954 ], + [ 0.914608, 0.220445 ], + [ 0.939653, 0.261670 ], + [ 0.960707, 0.305377 ], + [ 0.977521, 0.351315 ], + [ 0.989842, 0.399233 ], + [ 0.997419, 0.448878 ] + ] + ] +} diff --git a/data/text/O_1.svg b/data/text/O_1.svg new file mode 100644 index 0000000..75f7539 --- /dev/null +++ b/data/text/O_1.svg @@ -0,0 +1,57 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/data/text/P_1.json b/data/text/P_1.json new file mode 100644 index 0000000..358baf0 --- /dev/null +++ b/data/text/P_1.json @@ -0,0 +1,37 @@ +{ + "type": "REFERENCE", + "value": "P", + "sub-id": 1, + "data": [ + [ + [ 0, 0 ], + [ 0, 1 ] + ], + [ + [ 0, 0.003491 ], + [ 0.232282, 0.009006 ], + [ 0.434124, 0.024593 ], + [ 0.605421, 0.048818 ], + [ 0.746066, 0.080245 ], + [ 0.855952, 0.117437 ], + [ 0.899328, 0.137747 ], + [ 0.934975, 0.158959 ], + [ 0.962878, 0.180896 ], + [ 0.983026, 0.203376 ], + [ 0.995404, 0.226222 ], + [ 1.000000, 0.249252 ], + [ 0.996800, 0.272289 ], + [ 0.985791, 0.295152 ], + [ 0.966959, 0.317662 ], + [ 0.940291, 0.339639 ], + [ 0.905775, 0.360904 ], + [ 0.863396, 0.381278 ], + [ 0.813142, 0.400581 ], + [ 0.754998, 0.418634 ], + [ 0.614992, 0.450271 ], + [ 0.443271, 0.474752 ], + [ 0.239728, 0.490644 ], + [ 0.004257, 0.496509 ] + ] + ] +} diff --git a/data/text/P_1.svg b/data/text/P_1.svg new file mode 100644 index 0000000..1cdb6f1 --- /dev/null +++ b/data/text/P_1.svg @@ -0,0 +1,61 @@ + + + + + + image/svg+xml + + + + + + + + + + diff --git a/data/text/Q_1.json b/data/text/Q_1.json new file mode 100644 index 0000000..59704e3 --- /dev/null +++ b/data/text/Q_1.json @@ -0,0 +1,77 @@ +{ + "type": "REFERENCE", + "value": "Q", + "sub-id": 1, + "data": [ + [ + [ 0.990345, 0.495173 ], + [ 0.987789, 0.545801 ], + [ 0.980285, 0.594967 ], + [ 0.968083, 0.642422 ], + [ 0.951432, 0.687916 ], + [ 0.930580, 0.731201 ], + [ 0.905777, 0.772028 ], + [ 0.877272, 0.810148 ], + [ 0.845312, 0.845312 ], + [ 0.810148, 0.877272 ], + [ 0.772028, 0.905778 ], + [ 0.731201, 0.930581 ], + [ 0.687916, 0.951432 ], + [ 0.642422, 0.968083 ], + [ 0.594967, 0.980285 ], + [ 0.545801, 0.987789 ], + [ 0.495173, 0.990345 ], + [ 0.444544, 0.987789 ], + [ 0.395378, 0.980285 ], + [ 0.347923, 0.968083 ], + [ 0.302429, 0.951432 ], + [ 0.259144, 0.930581 ], + [ 0.218317, 0.905778 ], + [ 0.180197, 0.877272 ], + [ 0.145033, 0.845312 ], + [ 0.113073, 0.810148 ], + [ 0.084568, 0.772028 ], + [ 0.059765, 0.731201 ], + [ 0.038913, 0.687916 ], + [ 0.022262, 0.642422 ], + [ 0.010060, 0.594967 ], + [ 0.002557, 0.545801 ], + [ 0, 0.495173 ], + [ 0.002557, 0.444544 ], + [ 0.010060, 0.395378 ], + [ 0.022262, 0.347923 ], + [ 0.038913, 0.302429 ], + [ 0.059765, 0.259144 ], + [ 0.084568, 0.218317 ], + [ 0.113073, 0.180197 ], + [ 0.145033, 0.145033 ], + [ 0.180197, 0.113073 ], + [ 0.218317, 0.084568 ], + [ 0.259144, 0.059765 ], + [ 0.302429, 0.038913 ], + [ 0.347923, 0.022262 ], + [ 0.395378, 0.010060 ], + [ 0.444544, 0.002557 ], + [ 0.495173, 0 ], + [ 0.545801, 0.002557 ], + [ 0.594967, 0.010060 ], + [ 0.642422, 0.022262 ], + [ 0.687916, 0.038913 ], + [ 0.731201, 0.059765 ], + [ 0.772028, 0.084568 ], + [ 0.810148, 0.113073 ], + [ 0.845312, 0.145033 ], + [ 0.877272, 0.180197 ], + [ 0.905777, 0.218317 ], + [ 0.930580, 0.259144 ], + [ 0.951432, 0.302429 ], + [ 0.968083, 0.347923 ], + [ 0.980285, 0.395378 ], + [ 0.987789, 0.444544 ] + ], + [ + [ 0.673347, 0.732738 ], + [ 1, 1 ] + ] + ] +} diff --git a/data/text/Q_1.svg b/data/text/Q_1.svg new file mode 100644 index 0000000..045b3eb --- /dev/null +++ b/data/text/Q_1.svg @@ -0,0 +1,62 @@ + + + + + + image/svg+xml + + + + + + + + + + diff --git a/data/text/R_1.json b/data/text/R_1.json new file mode 100644 index 0000000..f0f2d9c --- /dev/null +++ b/data/text/R_1.json @@ -0,0 +1,41 @@ +{ + "type": "REFERENCE", + "value": "R", + "sub-id": 1, + "data": [ + [ + [ 0, 0 ], + [ 0, 1 ] + ], + [ + [ 0, 0.003491 ], + [ 0.231464, 0.009006 ], + [ 0.432595, 0.024593 ], + [ 0.603289, 0.048818 ], + [ 0.743438, 0.080245 ], + [ 0.852938, 0.117437 ], + [ 0.896161, 0.137747 ], + [ 0.931682, 0.158959 ], + [ 0.959487, 0.180896 ], + [ 0.979564, 0.203376 ], + [ 0.991898, 0.226222 ], + [ 0.996478, 0.249252 ], + [ 0.993289, 0.272289 ], + [ 0.982319, 0.295152 ], + [ 0.963553, 0.317662 ], + [ 0.936980, 0.339639 ], + [ 0.902585, 0.360904 ], + [ 0.860355, 0.381278 ], + [ 0.810278, 0.400581 ], + [ 0.752339, 0.418634 ], + [ 0.612826, 0.450271 ], + [ 0.441709, 0.474752 ], + [ 0.238884, 0.490644 ], + [ 0.004242, 0.496509 ] + ], + [ + [ 0, 0.500000 ], + [ 1, 1 ] + ] + ] +} diff --git a/data/text/R_1.svg b/data/text/R_1.svg new file mode 100644 index 0000000..0d83466 --- /dev/null +++ b/data/text/R_1.svg @@ -0,0 +1,67 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/data/text/S_1.json b/data/text/S_1.json new file mode 100644 index 0000000..656073b --- /dev/null +++ b/data/text/S_1.json @@ -0,0 +1,56 @@ +{ + "type": "REFERENCE", + "value": "S", + "sub-id": 1, + "data": [ + [ + [ 1, 0 ], + [ 0.790439, 0.001118 ], + [ 0.606683, 0.013011 ], + [ 0.448298, 0.034223 ], + [ 0.314847, 0.063295 ], + [ 0.205897, 0.098774 ], + [ 0.121011, 0.139200 ], + [ 0.087457, 0.160814 ], + [ 0.059755, 0.183119 ], + [ 0.037852, 0.205933 ], + [ 0.021694, 0.229074 ], + [ 0.011225, 0.252359 ], + [ 0.006392, 0.275607 ], + [ 0.007140, 0.298636 ], + [ 0.013415, 0.321264 ], + [ 0.025162, 0.343308 ], + [ 0.042327, 0.364586 ], + [ 0.064856, 0.384917 ], + [ 0.092693, 0.404118 ], + [ 0.164079, 0.438404 ], + [ 0.256049, 0.465985 ], + [ 0.368167, 0.485408 ], + [ 0.500000, 0.495213 ], + [ 0.631746, 0.505541 ], + [ 0.743626, 0.526395 ], + [ 0.835242, 0.556114 ], + [ 0.873326, 0.573779 ], + [ 0.906193, 0.593038 ], + [ 0.933793, 0.613684 ], + [ 0.956077, 0.635508 ], + [ 0.972995, 0.658304 ], + [ 0.984497, 0.681863 ], + [ 0.990531, 0.705979 ], + [ 0.991049, 0.730444 ], + [ 0.986001, 0.755050 ], + [ 0.975336, 0.779590 ], + [ 0.959004, 0.803856 ], + [ 0.936955, 0.827642 ], + [ 0.909140, 0.850738 ], + [ 0.875508, 0.872938 ], + [ 0.836009, 0.894035 ], + [ 0.790593, 0.913820 ], + [ 0.681811, 0.948627 ], + [ 0.548761, 0.975700 ], + [ 0.391042, 0.993377 ], + [ 0.208256, 1 ], + [ 0, 0.993908 ] + ] + ] +} diff --git a/data/text/S_1.svg b/data/text/S_1.svg new file mode 100644 index 0000000..a65b820 --- /dev/null +++ b/data/text/S_1.svg @@ -0,0 +1,56 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/data/text/T_1.json b/data/text/T_1.json new file mode 100644 index 0000000..c859f3f --- /dev/null +++ b/data/text/T_1.json @@ -0,0 +1,12 @@ +{ + "type":"REFERENCE", + "value":"T", + "sub-id":1, + "data":[ + [ + [0.5,0.0],[0.5,1.0] + ],[ + [0.25,1.0],[0.75,1.0] + ] + ] +} \ No newline at end of file diff --git a/data/text/U_1.json b/data/text/U_1.json new file mode 100644 index 0000000..c38d098 --- /dev/null +++ b/data/text/U_1.json @@ -0,0 +1,38 @@ +{ + "type": "REFERENCE", + "value": "U", + "sub-id": 1, + "data": [ + [ + [ 0.991609, 0 ], + [ 0.992411, 0.755487 ], + [ 0.989280, 0.788232 ], + [ 0.980773, 0.818411 ], + [ 0.967246, 0.846070 ], + [ 0.949060, 0.871256 ], + [ 0.926571, 0.894016 ], + [ 0.900139, 0.914396 ], + [ 0.836874, 0.948202 ], + [ 0.762132, 0.973047 ], + [ 0.678776, 0.989304 ], + [ 0.589672, 0.997345 ], + [ 0.497686, 0.997543 ], + [ 0.405681, 0.990270 ], + [ 0.316525, 0.975899 ], + [ 0.233080, 0.954802 ], + [ 0.158214, 0.927352 ], + [ 0.094790, 0.893922 ], + [ 0.045675, 0.854883 ], + [ 0.027378, 0.833377 ], + [ 0.013733, 0.810609 ], + [ 0.005097, 0.786625 ], + [ 0.001829, 0.761472 ], + [ 0, 0.403139 ], + [ 0.001520, 0 ] + ], + [ + [ 1.000000, 1 ], + [ 0.995805, 0 ] + ] + ] +} diff --git a/data/text/U_1.svg b/data/text/U_1.svg new file mode 100644 index 0000000..60c6392 --- /dev/null +++ b/data/text/U_1.svg @@ -0,0 +1,61 @@ + + + + + + image/svg+xml + + + + + + + + + + diff --git a/data/text/V_1.json b/data/text/V_1.json new file mode 100644 index 0000000..10607e9 --- /dev/null +++ b/data/text/V_1.json @@ -0,0 +1,14 @@ +{ + "type":"REFERENCE", + "value":"V", + "sub-id":1, + "data":[ + [ + [0.0, 1.0], + [0.5, 0.0] + ],[ + [0.5, 0.0], + [1.0, 1.0] + ], + ] +} \ No newline at end of file diff --git a/data/text/W_1.json b/data/text/W_1.json new file mode 100644 index 0000000..79632fe --- /dev/null +++ b/data/text/W_1.json @@ -0,0 +1,16 @@ +{ + "type":"REFERENCE", + "value":"W", + "sub-id":1, + "data":[ + [ + [0.0,1.0],[0.25,0.0] + ],[ + [0.25,0.0],[0.5,0.5] + ],[ + [0.5,0.5],[0.75,0.0] + ],[ + [0.75,0.0],[1.0,1.0] + ], + ] +} \ No newline at end of file diff --git a/data/text/X_1.json b/data/text/X_1.json new file mode 100644 index 0000000..01d10cb --- /dev/null +++ b/data/text/X_1.json @@ -0,0 +1,12 @@ +{ + "type":"REFERENCE", + "value":"X", + "sub-id":1, + "data":[ + [ + [0.0,0.0],[1.0,1.0] + ],[ + [0.0,1.0],[1.0,0.0] + ] + ] +} \ No newline at end of file diff --git a/data/text/Y_1.json b/data/text/Y_1.json new file mode 100644 index 0000000..2423495 --- /dev/null +++ b/data/text/Y_1.json @@ -0,0 +1,14 @@ +{ + "type":"REFERENCE", + "value":"Y", + "sub-id":1, + "data":[ + [ + [0.5,0.5],[1.0,1.0] + ],[ + [0.5,0.5],[1.0,0.0] + ],[ + [0.5,0.5],[0.5,0.0] + ] + ] +} \ No newline at end of file diff --git a/data/text/Z_1.json b/data/text/Z_1.json new file mode 100644 index 0000000..32f1486 --- /dev/null +++ b/data/text/Z_1.json @@ -0,0 +1,14 @@ +{ + "type":"REFERENCE", + "value":"Z", + "sub-id":1, + "data":[ + [ + [0.0,1.0],[1.0,1.0] + ],[ + [1.0,1.0],[0.0,0.0] + ],[ + [0.0,0.0],[1.0,0.0] + ], + ] +} \ No newline at end of file diff --git a/data/text/brace-left_1.json b/data/text/brace-left_1.json new file mode 100644 index 0000000..496b5cb --- /dev/null +++ b/data/text/brace-left_1.json @@ -0,0 +1,57 @@ +{ + "type": "REFERENCE", + "value": "{", + "sub-id": 1, + "data": [ + [ + [ 0.991543, 0 ], + [ 0.890026, 0.002108 ], + [ 0.802061, 0.008146 ], + [ 0.726682, 0.017683 ], + [ 0.662923, 0.030288 ], + [ 0.609817, 0.045532 ], + [ 0.566398, 0.062984 ], + [ 0.531700, 0.082213 ], + [ 0.504757, 0.102791 ], + [ 0.484602, 0.124285 ], + [ 0.470270, 0.146265 ], + [ 0.455206, 0.189965 ], + [ 0.452431, 0.264271 ], + [ 0.447350, 0.311527 ], + [ 0.432991, 0.352143 ], + [ 0.410679, 0.386614 ], + [ 0.381739, 0.415437 ], + [ 0.347497, 0.439105 ], + [ 0.309279, 0.458116 ], + [ 0.268410, 0.472965 ], + [ 0.226216, 0.484147 ], + [ 0.143152, 0.497491 ], + [ 0.070692, 0.502115 ], + [ 0, 0.501057 ], + [ 0.070992, 0.499438 ], + [ 0.143715, 0.502729 ], + [ 0.227016, 0.513478 ], + [ 0.310217, 0.535226 ], + [ 0.348443, 0.551333 ], + [ 0.382639, 0.571518 ], + [ 0.411471, 0.596225 ], + [ 0.433603, 0.625896 ], + [ 0.447702, 0.660974 ], + [ 0.452431, 0.701903 ], + [ 0.454730, 0.750956 ], + [ 0.465852, 0.801398 ], + [ 0.476296, 0.826397 ], + [ 0.490834, 0.850850 ], + [ 0.510098, 0.874461 ], + [ 0.534716, 0.896932 ], + [ 0.565318, 0.917967 ], + [ 0.602534, 0.937267 ], + [ 0.646995, 0.954536 ], + [ 0.699329, 0.969476 ], + [ 0.760167, 0.981790 ], + [ 0.830138, 0.991180 ], + [ 0.909873, 0.997349 ], + [ 1, 1 ] + ] + ] +} diff --git a/data/text/brace-left_1.svg b/data/text/brace-left_1.svg new file mode 100644 index 0000000..51f4c44 --- /dev/null +++ b/data/text/brace-left_1.svg @@ -0,0 +1,56 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/data/text/brace-right_1.json b/data/text/brace-right_1.json new file mode 100644 index 0000000..35d4aa2 --- /dev/null +++ b/data/text/brace-right_1.json @@ -0,0 +1,57 @@ +{ + "type": "REFERENCE", + "value": "}", + "sub-id": 1, + "data": [ + [ + [ 0.008457, 0 ], + [ 0.109974, 0.002108 ], + [ 0.197939, 0.008146 ], + [ 0.273318, 0.017683 ], + [ 0.337077, 0.030288 ], + [ 0.390183, 0.045532 ], + [ 0.433602, 0.062984 ], + [ 0.468300, 0.082213 ], + [ 0.495243, 0.102791 ], + [ 0.515398, 0.124285 ], + [ 0.529730, 0.146265 ], + [ 0.544794, 0.189965 ], + [ 0.547569, 0.264271 ], + [ 0.552650, 0.311527 ], + [ 0.567009, 0.352143 ], + [ 0.589321, 0.386614 ], + [ 0.618261, 0.415437 ], + [ 0.652503, 0.439105 ], + [ 0.690721, 0.458116 ], + [ 0.731590, 0.472965 ], + [ 0.773784, 0.484147 ], + [ 0.856848, 0.497491 ], + [ 0.929308, 0.502115 ], + [ 1, 0.501057 ], + [ 0.929008, 0.499438 ], + [ 0.856285, 0.502729 ], + [ 0.772984, 0.513478 ], + [ 0.689783, 0.535226 ], + [ 0.651558, 0.551333 ], + [ 0.617361, 0.571518 ], + [ 0.588529, 0.596225 ], + [ 0.566397, 0.625896 ], + [ 0.552298, 0.660974 ], + [ 0.547569, 0.701903 ], + [ 0.545270, 0.750956 ], + [ 0.534148, 0.801398 ], + [ 0.523704, 0.826397 ], + [ 0.509166, 0.850850 ], + [ 0.489902, 0.874461 ], + [ 0.465284, 0.896932 ], + [ 0.434682, 0.917967 ], + [ 0.397466, 0.937267 ], + [ 0.353005, 0.954536 ], + [ 0.300671, 0.969476 ], + [ 0.239833, 0.981790 ], + [ 0.169862, 0.991180 ], + [ 0.090127, 0.997349 ], + [ 0, 1 ] + ] + ] +} diff --git a/data/text/brace-right_1.svg b/data/text/brace-right_1.svg new file mode 100644 index 0000000..621ca88 --- /dev/null +++ b/data/text/brace-right_1.svg @@ -0,0 +1,56 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/data/text/bracket-left_1.json b/data/text/bracket-left_1.json new file mode 100644 index 0000000..01ed814 --- /dev/null +++ b/data/text/bracket-left_1.json @@ -0,0 +1,14 @@ +{ + "type":"REFERENCE", + "value":"[", + "sub-id":1, + "data":[ + [ + [0.0,0.0],[1.0,0.0] + ],[ + [0.0,0.0],[0.0,1.0] + ],[ + [0.0,1.0],[1.0,1.0] + ] + ] +} \ No newline at end of file diff --git a/data/text/bracket-right_1.json b/data/text/bracket-right_1.json new file mode 100644 index 0000000..098efec --- /dev/null +++ b/data/text/bracket-right_1.json @@ -0,0 +1,14 @@ +{ + "type":"REFERENCE", + "value":"]", + "sub-id":1, + "data":[ + [ + [0.0,0.0],[1.0,0.0] + ],[ + [1.0,0.0],[1.0,1.0] + ],[ + [0.0,1.0],[1.0,1.0] + ] + ] +} \ No newline at end of file diff --git a/data/text/question-mark_1.json b/data/text/question-mark_1.json new file mode 100644 index 0000000..4ca79ce --- /dev/null +++ b/data/text/question-mark_1.json @@ -0,0 +1,38 @@ +{ + "type": "REFERENCE", + "value": "?", + "sub-id": 1, + "data": [ + [ + [ 0, 0.307167 ], + [ 0.013307, 0.212637 ], + [ 0.050746, 0.139665 ], + [ 0.108336, 0.085491 ], + [ 0.182096, 0.047355 ], + [ 0.268044, 0.022498 ], + [ 0.362200, 0.008159 ], + [ 0.460582, 0.001580 ], + [ 0.559210, 0 ], + [ 0.652741, 0.005593 ], + [ 0.737685, 0.021704 ], + [ 0.812847, 0.047335 ], + [ 0.877029, 0.081485 ], + [ 0.929032, 0.123154 ], + [ 0.967660, 0.171342 ], + [ 0.991716, 0.225049 ], + [ 1, 0.283276 ], + [ 0.985056, 0.340744 ], + [ 0.944593, 0.393611 ], + [ 0.885164, 0.443039 ], + [ 0.813322, 0.490188 ], + [ 0.658614, 0.582285 ], + [ 0.588854, 0.629553 ], + [ 0.532895, 0.679181 ], + [ 0.492779, 0.727962 ], + [ 0.464844, 0.772504 ], + [ 0.437500, 0.852389 ], + [ 0.434827, 0.925875 ], + [ 0.440790, 1.000000 ] + ] + ] +} diff --git a/data/text/question-mark_1.svg b/data/text/question-mark_1.svg new file mode 100644 index 0000000..5ddd505 --- /dev/null +++ b/data/text/question-mark_1.svg @@ -0,0 +1,56 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/data/text/slash-back_1.json b/data/text/slash-back_1.json new file mode 100644 index 0000000..bb37293 --- /dev/null +++ b/data/text/slash-back_1.json @@ -0,0 +1,11 @@ +{ + "type":"REFERENCE", + "value":"\\", + "sub-id":1, + "data":[ + [ + [1.0,0.0], + [0.0,1.0] + ] + ] +} \ No newline at end of file diff --git a/data/text/slash_1.json b/data/text/slash_1.json new file mode 100644 index 0000000..25501f9 --- /dev/null +++ b/data/text/slash_1.json @@ -0,0 +1,11 @@ +{ + "type":"REFERENCE", + "value":"/", + "sub-id":1, + "data":[ + [ + [0.0,0.0], + [1.0,1.0] + ] + ] +} \ No newline at end of file diff --git a/data/text/star_1.json b/data/text/star_1.json new file mode 100644 index 0000000..accded1 --- /dev/null +++ b/data/text/star_1.json @@ -0,0 +1,16 @@ +{ + "type":"REFERENCE", + "value":"*", + "sub-id":1, + "data":[ + [ + [0.0,0.5],[1.0,0.5] + ],[ + [0.5,0.0],[0.5,1.0] + ],[ + [0.0,0.0],[1.0,1.0] + ],[ + [0.0,1.0],[1.0,0.0] + ] + ] +} \ No newline at end of file diff --git a/dollar/Engine.cpp b/dollar/Engine.cpp new file mode 100644 index 0000000..8e5cd48 --- /dev/null +++ b/dollar/Engine.cpp @@ -0,0 +1,256 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2016, Edouard DUPIN, all right reserved + * @license APACHE v2.0 (see license file) + */ + +#include +#include +#include +#include +#include +#include +#include +#define MAX_FLOAT std::numeric_limits::max() +// simple decree to radian convertion +#define DEG_2_RAD(ddd) (ddd*M_PI/180.0) + +// Test is done on the square of 1.0f * 1.0f ==> the result depend on the diagonal size +#define DIAGONAL (1.414213562) +#define HALF_DIAGONAL (0.707106781) +// an other magic number ratio of starting vetor pos... ==> must be reworked ==> nbElementInVector/RATIO_START_VECTOR +#define RATIO_START_VECTOR (8) +// angle precision of the detecting the way of rotation +#define ANGLE_ROTATION (2.0f) +// Angle to start processing of a start vector comparaison +#define ANGLE_THRESHOLD_START_PROCESSING DEG_2_RAD(30.0) + +// A magic number: 0.5 * (-1.0 + sqrt(5.0)) +#define MAGIC_RATIO (0.618033989) + + + +static float angleBetweenUnitVectors(const vec2& _vect1, const vec2& _vect2) { + float n = _vect1.dot(_vect2); + // TODO : No needs + if (n < -1.0 || n > +1.0){ + n = round(n*100000.0f)/100000.0f; + } + return std::acos(n); // arc cosine of the vector dot product +} + +static float pathDistance(const std::vector& _path1, const std::vector& _path2) { + // assumes pts1.size == pts2.size + float distance = 0.0; + if (_path1.size() != _path2.size()) { + DOLLAR_ERROR("Path have not the same size: " << _path1.size() << " != " << _path2.size()); + return MAX_FLOAT; + } + for (size_t iii=0; iii<_path1.size(); ++iii) { + distance += (_path2[iii]-_path1[iii]).length(); + } + DOLLAR_VERBOSE("distance: " << distance << " size= " << _path1.size()); + return (distance / _path1.size()); +} + +dollar::Engine::Engine() { + m_numPointsInGesture = 128; + DOLLAR_ASSERT(m_numPointsInGesture>16, "NB element in a path must be > 16 ..."); + setRotationInvariance(false); +} + + +void dollar::Engine::setNumberPointInGesture(size_t _value) { + if (_value == m_numPointsInGesture) { + return; + } + m_numPointsInGesture = _value; + DOLLAR_ASSERT(m_numPointsInGesture>16, "NB element in a path must be > 16 ..."); + for (auto &it: m_gestures) { + it.configure(m_numPointsInGesture/RATIO_START_VECTOR, m_numPointsInGesture, m_paramterIgnoreRotation); + } +} + +size_t dollar::Engine::getNumberPointInGesture() { + return m_numPointsInGesture; +} + +float dollar::Engine::distanceAtBestAngle(const std::vector& _points, const std::vector& _reference) { + float startRange = -m_angleRange; + float endRange = m_angleRange; + float x1 = MAGIC_RATIO * startRange + (1.0 - MAGIC_RATIO) * endRange; + float f1 = pathDistance(dollar::rotateBy(_points, x1), _reference); + float x2 = (1.0 - MAGIC_RATIO) * startRange + MAGIC_RATIO * endRange; + float f2 = pathDistance(dollar::rotateBy(_points, x2), _reference); + DOLLAR_VERBOSE("init: startRange=" << startRange << " endRange=" << endRange << " MAGIC_RATIO=" << MAGIC_RATIO << " x1=" << x1 << " f1=" << f1 << " x2=" << x2 << " f2=" << f2); + while (fabs(endRange - startRange) > ANGLE_ROTATION) { + if (f1 < f2) { + endRange = x2; + x2 = x1; + f2 = f1; + x1 = MAGIC_RATIO * startRange + (1.0f - MAGIC_RATIO) * endRange; + f1 = pathDistance(dollar::rotateBy(_points, x1), _reference); + } else { + startRange = x1; + x1 = x2; + f1 = f2; + x2 = (1.0f - MAGIC_RATIO) * startRange + MAGIC_RATIO * endRange; + f2 = pathDistance(dollar::rotateBy(_points, x2), _reference); + } + } + return std::min(f1, f2); +} + +float dollar::Engine::optimalCosineDistance(const std::vector& _vect1, const std::vector& _vect2) { + if (_vect1.size() != _vect2.size()) { + DOLLAR_ERROR("Vector have not the same size: " << _vect1.size() << " != " << _vect2.size()); + return M_PI; + } + double somDot = 0; + double somCross = 0; + for (size_t iii=0; iii<_vect1.size(); ++iii) { + somDot += _vect1[iii].dot(_vect2[iii]); + somCross += _vect1[iii].cross(_vect2[iii]); + } + if (somDot == 0.0f) { + DOLLAR_ERROR("devide by 0"); + return M_PI; + } + float angle = std::atan(somCross / somDot); + return std::acos(somDot * std::cos(angle) + somCross * std::sin(angle)); +} + + + +void dollar::Engine::setRotationInvariance(bool _ignoreRotation) { + m_paramterIgnoreRotation = _ignoreRotation; + if (m_paramterIgnoreRotation == true) { + m_angleRange = 45.0; + } else { + m_angleRange = 15.0; + } +} + +bool dollar::Engine::loadPath(const std::string& _path) { + DOLLAR_INFO("Load Path: " << _path); + etk::FSNode path(_path); + std::vector files = path.folderGetSub(false, true, "*.json"); + for (auto &it : files) { + loadGesture(it); + } + return true; +} + +bool dollar::Engine::loadGesture(const std::string& _filename) { + dollar::Gesture ref; + DOLLAR_INFO("Load Gesture: " << _filename); + if (ref.load(_filename) == true) { + addGesture(std::move(ref)); + return true; + } + return false; +} + +void dollar::Engine::addGesture(Gesture _gesture) { + _gesture.configure(m_numPointsInGesture/RATIO_START_VECTOR, m_numPointsInGesture, m_paramterIgnoreRotation); + m_gestures.push_back(std::move(_gesture)); +} + +dollar::Results dollar::Engine::recognize(const std::vector& _points, const std::string& _method) { + std::vector> tmp; + tmp.push_back(_points); + return recognize(tmp, _method); +} +#define MAX_RESULT_NUMBER (5) + +dollar::Results dollar::Engine::recognize(const std::vector>& _strokes, const std::string& _method) { + std::vector points = dollar::combineStrokes(_strokes); + // Make sure we have some templates to compare this to + // or else recognition will be impossible + if (m_gestures.empty()) { + DOLLAR_WARNING("No templates loaded so no symbols to match."); + return Results(); + } + points = dollar::normalizePath(points, m_numPointsInGesture, m_paramterIgnoreRotation); + vec2 startv = dollar::getStartVector(points, m_numPointsInGesture/RATIO_START_VECTOR); + std::vector vector = normalyse(points); + // Keep maximum 5 results ... + float bestDistance[MAX_RESULT_NUMBER]; + int32_t indexOfBestMatch[MAX_RESULT_NUMBER]; + for (size_t iii=0; iii ANGLE_THRESHOLD_START_PROCESSING) { + continue; + } + float distance = MAX_FLOAT; + // for Protractor + if (_method=="protractor") { + distance = Engine::optimalCosineDistance(vector, gesture.getEngineVector(jjj)); + } else { + // Golden Section Search (original $N) + distance = Engine::distanceAtBestAngle(points, gesture.getEnginePath(jjj)); + } + for (size_t kkk=0; kkkint32_t(kkk); --rrr) { + bestDistance[rrr] = bestDistance[rrr-1]; + indexOfBestMatch[rrr] = indexOfBestMatch[rrr-1]; + } + indexOfBestMatch[kkk] = iii; + } + bestDistance[kkk] = distance; + break; + } else { + if (kkk == 0) { + DOLLAR_VERBOSE("[" << iii << "," << jjj << "] d=" << distance << " < bd=" << bestDistance << " "); + } + } + } + } + } + // Make sure we actually found a good match + // Sometimes we don't, like when the user doesn't draw enough points + if (-1 == indexOfBestMatch[0]) { + DOLLAR_WARNING("Couldn't find a good match."); + return Results(); + } + Results res; + // Turn the distance into a percentage by dividing it by half the maximum possible distance (across the diagonal of the square we scaled everything too) + // Distance = hwo different they are subtract that from 1 (100%) to get the similarity + if (_method == "protractor") { + for (size_t iii=0; iii +#include +#include +#include +#include +#include + +namespace dollar { + class Engine { + protected: + float m_angleRange; + bool m_paramterIgnoreRotation; //!< Ignore the start rotation of the gesture + public: + void setRotationInvariance(bool _ignoreRotation); + protected: + size_t m_numPointsInGesture; //!< Number of point in a gesture to recognise patern ... + public: + void setNumberPointInGesture(size_t _value); + size_t getNumberPointInGesture(); + protected: + std::vector m_gestures; //!< List of all loaded gesture in the engine + public: + Engine(); + float distanceAtBestAngle(const std::vector& _points, const std::vector& _reference); + Results recognize(const std::vector>& _paths, const std::string& _method="normal"); + Results recognize(const std::vector& _points, const std::string& _method="normal"); + float optimalCosineDistance(const std::vector& _vect1, const std::vector& _vect2); + bool loadPath(const std::string& _path); + bool loadGesture(const std::string& _filename); + void addGesture(Gesture _gesture); + }; +} + + diff --git a/dollar/Gesture.cpp b/dollar/Gesture.cpp new file mode 100644 index 0000000..67c61c5 --- /dev/null +++ b/dollar/Gesture.cpp @@ -0,0 +1,169 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2016, Edouard DUPIN, all right reserved + * @license APACHE v2.0 (see license file) + */ + +#include +#include +#include +#include +#include +#include +#include + + +static std::vector> loadPointsJson(const ejson::Document& _doc) { + // extract lines: + std::vector> out; + const ejson::Array listOfLines = _doc["data"].toArray(); + if (listOfLines.exist() == false) { + DOLLAR_WARNING("Reference element has no element named 'data' " << _doc["data"]); + return out; + } + for (auto itLines : listOfLines) { + ejson::Array listOfpoint = itLines.toArray(); + std::vector line; + for (auto itPoints : listOfpoint) { + ejson::Array pointsArray = itPoints.toArray(); + line.push_back(vec2(pointsArray[0].toNumber().get(), pointsArray[1].toNumber().get())); + } + if (line.size() > 1) { + out.push_back(std::move(line)); + } + } + return out; +} + +std::vector> dollar::loadPoints(const std::string& _fileName) { + ejson::Document doc; + doc.load(_fileName); + return loadPointsJson(doc); +} + + +dollar::Gesture::Gesture(): + m_name(""), + m_subId(0), + m_path(){ + +} + +bool dollar::Gesture::load(const std::string& _fileName) { + std::string tmpName = etk::tolower(_fileName); + if (etk::end_with(tmpName, ".json") == true) { + return loadJSON(_fileName); + } else if (etk::end_with(tmpName, ".svg") == true) { + return loadSVG(_fileName); + } + DOLLAR_ERROR("Un-sopported LOAD extention : " << _fileName); + DOLLAR_ERROR(" supported: [svg,json]"); + return false; +} + +bool dollar::Gesture::loadJSON(const std::string& _fileName) { + ejson::Document doc; + doc.load(_fileName); + if (doc["type"].toString().get() != "REFERENCE") { + DOLLAR_WARNING("can not LOAD file that is not a reference"); + } + m_name = doc["value"].toString().get(); + m_subId = doc["sub-id"].toNumber().getU64(), + m_path = loadPointsJson(doc); + m_path = dollar::scaleToOne(m_path); + DOLLAR_DEBUG("Load gesture : " << m_name << " id=" << m_subId << " nb_elem=" << m_path.size()); + return true; +} + +bool dollar::Gesture::loadSVG(const std::string& _fileName) { + esvg::Document doc; + doc.load(_fileName); + std::vector plop = etk::split(_fileName, '.'); + plop = etk::split(plop[plop.size() -2], '/'); + plop = etk::split(plop[plop.size() -1], '_'); + m_name = plop[0]; + m_subId = etk::string_to_int32_t(plop[1]); + m_path = doc.getLines(); + m_path = dollar::scaleToOne(m_path); + DOLLAR_DEBUG("Load gesture : " << m_name << " id=" << m_subId << " nb_elem=" << m_path.size()); + return true; +} + + +bool dollar::Gesture::store(const std::string& _fileName) { + std::string tmpName = etk::tolower(_fileName); + if (etk::end_with(tmpName, ".json") == true) { + storeJSON(_fileName); + return true; + } else if (etk::end_with(tmpName, ".svg") == true) { + storeSVG(_fileName); + return true; + } + DOLLAR_ERROR("Un-sopported STORE extention : " << _fileName); + DOLLAR_ERROR(" supported: [svg,json]"); + return false; +} + +void dollar::Gesture::storeJSON(const std::string& _fileName) { + ejson::Document doc; + doc.add("type", ejson::String("REFERENCE")); + doc.add("value", ejson::String(m_name)); + doc.add("sub-id", ejson::Number(m_subId)); + ejson::Array data; + doc.add("data", data); + for (auto &it : m_path) { + ejson::Array path; + for (auto &pathIt : it) { + ejson::Array value; + value.add(ejson::Number(pathIt.x())); + value.add(ejson::Number(pathIt.y())); + path.add(value); + } + data.add(path); + } + doc.store(_fileName); +} + +void dollar::Gesture::storeSVG(const std::string& _fileName) { + std::vector> strokes = dollar::scaleToOne(m_path); + std::string data("\n"); + data += "\n"; + for (auto &itLines : strokes) { + data += " > uniPath = dollar::makeReferenceStrokes(m_path); + // normalize paths + for (auto &it : uniPath) { + std::vector val = dollar::normalizePath(it, _nbSample, _ignoreRotation); + m_enginePath.push_back(val); + // calculate start vector: + vec2 startv = dollar::getStartVector(val, _startAngleIndex); + m_engineStartV.push_back(startv); + m_engineVector.push_back(dollar::normalyse(val)); + } +} \ No newline at end of file diff --git a/dollar/Gesture.h b/dollar/Gesture.h new file mode 100644 index 0000000..02f7b21 --- /dev/null +++ b/dollar/Gesture.h @@ -0,0 +1,57 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2016, Edouard DUPIN, all right reserved + * @license APACHE v2.0 (see license file) + */ + +#pragma once +#include +#include + +namespace dollar { + class Gesture { + protected: + std::string m_name; + uint32_t m_subId; + std::vector> m_path; + public: + Gesture(); + bool load(const std::string& _filename); + bool store(const std::string& _filename); + protected: + bool loadJSON(const std::string& _filename); + bool loadSVG(const std::string& _filename); + void storeJSON(const std::string& _filename); + void storeSVG(const std::string& _filename); + public: + const std::string& getName() { + return m_name; + } + const std::vector>& getPath() const { + return m_path; + } + std::vector>& getPath() { + return m_path; + } + protected: + std::vector> m_enginePath; // Singulized path with every conbinaison + std::vector> m_engineVector; + std::vector m_engineStartV; + public: + // Configure the reference gesture for recognition... + void configure(float _startAngleIndex, size_t _nbSample, bool _ignoreRotation); + size_t getEngineSize() const { + return m_enginePath.size(); + } + const std::vector& getEnginePath(size_t _id) const { + return m_enginePath[_id]; + } + const std::vector& getEngineVector(size_t _id) const { + return m_engineVector[_id]; + } + const vec2& getEngineStartVector(size_t _id) const { + return m_engineStartV[_id]; + } + }; + std::vector> loadPoints(const std::string& _fileName); +} diff --git a/dollar/Rectangle.cpp b/dollar/Rectangle.cpp new file mode 100644 index 0000000..113f652 --- /dev/null +++ b/dollar/Rectangle.cpp @@ -0,0 +1,47 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2016, Edouard DUPIN, all right reserved + * @license APACHE v2.0 (see license file) + */ +#include +#include + +#define MAX_FLOAT std::numeric_limits::max() + +dollar::Rectangle::Rectangle(const vec2& _pos, const vec2& _size): + m_pos(_pos), + m_size(_size) { + +} +dollar::Rectangle::Rectangle(const std::vector& _points) { + vec2 minPos(MAX_FLOAT,MAX_FLOAT); + vec2 maxPos(-MAX_FLOAT,-MAX_FLOAT); + for (auto &it : _points) { + minPos.setMin(it); + maxPos.setMax(it); + } + m_pos = minPos; + m_size = maxPos-minPos; +} +dollar::Rectangle::Rectangle(const std::vector>& _points) { + vec2 minPos(MAX_FLOAT,MAX_FLOAT); + vec2 maxPos(-MAX_FLOAT,-MAX_FLOAT); + for (auto &it : _points) { + for (auto &itPoint : it) { + minPos.setMin(itPoint); + maxPos.setMax(itPoint); + } + } + m_pos = minPos; + m_size = maxPos-minPos; +} + +const vec2& dollar::Rectangle::getPos() const { + return m_pos; +} + +const vec2& dollar::Rectangle::getSize() const { + return m_size; +} + + diff --git a/dollar/Rectangle.h b/dollar/Rectangle.h new file mode 100644 index 0000000..1539d21 --- /dev/null +++ b/dollar/Rectangle.h @@ -0,0 +1,53 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2016, Edouard DUPIN, all right reserved + * @license APACHE v2.0 (see license file) + */ +#pragma once + +#include +#include +#include +#include +#include + +namespace dollar { + /** + * @brief Simple rectangle area (AABB mode) + */ + class Rectangle { + protected: + vec2 m_pos; //!< Position of the start of the rectangle (min position) + vec2 m_size; //!< Size of the rectangle + public: + /** + * @brief Create a rectangle as a bounding box + * @param[in] _points List of point that is contained in this area + */ + Rectangle(const std::vector& _points); + /** + * @brief Create a rectangle as a bounding box + * @param[in] _points List of point that is contained in this area + */ + Rectangle(const std::vector>& _points); + /** + * @brief Create a rectangle with values + * @param[in] _pos Start position + * @param[in] _size Size of the rectangle + */ + Rectangle(const vec2& _pos, const vec2& _size); + public: + /** + * @brief Get start position of the rectangle + * @return Start position. + */ + const vec2& getPos() const; + /** + * @brief Get the size of the rectangle + * @return Size of the rectangle + */ + const vec2& getSize() const; + }; +} + + diff --git a/dollar/Results.cpp b/dollar/Results.cpp new file mode 100644 index 0000000..7de7662 --- /dev/null +++ b/dollar/Results.cpp @@ -0,0 +1,47 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2016, Edouard DUPIN, all right reserved + * @license APACHE v2.0 (see license file) + */ + +#include +#include + + +dollar::Results::Results() { + // nothing to do ... +} + +bool dollar::Results::haveMath() const { + return m_values.size() != 0; +} + +size_t dollar::Results::getSize() const { + return m_values.size(); +} + +std::string dollar::Results::getName(size_t _id) const { + if (_id >= m_values.size()) { + DOLLAR_ERROR("request acces error result out of range (name)"); + return ""; + } + return m_values[_id].first; +} + +float dollar::Results::getConfidence(size_t _id) const { + if (_id >= m_values.size()) { + DOLLAR_ERROR("request acces error result out of range (value)"); + return 0; + } + return m_values[_id].second; +} + +void dollar::Results::addValue(const std::string& _name, float _confidence) { + m_values.push_back(std::make_pair(_name, _confidence)); +} + + +void dollar::Results::clear() { + m_values.clear(); +} + diff --git a/dollar/Results.h b/dollar/Results.h new file mode 100644 index 0000000..ec45003 --- /dev/null +++ b/dollar/Results.h @@ -0,0 +1,28 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2016, Edouard DUPIN, all right reserved + * @license APACHE v2.0 (see license file) + */ +#pragma once + +#include +#include +#include +#include + +namespace dollar { + class Results { + protected: + std::vector> m_values; + public: + Results(); + bool haveMath() const; + size_t getSize() const; + std::string getName(size_t _id=0) const; + float getConfidence(size_t _id=0) const; + void addValue(const std::string& _name, float _confidence); + void clear(); + }; +} + + diff --git a/dollar/debug.cpp b/dollar/debug.cpp new file mode 100644 index 0000000..e242d8c --- /dev/null +++ b/dollar/debug.cpp @@ -0,0 +1,13 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2016, Edouard DUPIN, all right reserved + * @license APACHE v2.0 (see license file) + */ + +#include + +int32_t dollar::getLogId() { + static int32_t g_val = elog::registerInstance("dollar"); + return g_val; +} + diff --git a/dollar/debug.h b/dollar/debug.h new file mode 100644 index 0000000..a64f380 --- /dev/null +++ b/dollar/debug.h @@ -0,0 +1,45 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2016, Edouard DUPIN, all right reserved + * @license APACHE v2.0 (see license file) + */ + +#include + +#pragma once + +#include + +namespace dollar { + int32_t getLogId(); +}; + +#define DOLLAR_BASE(info,data) ELOG_BASE(dollar::getLogId(),info,data) + +#define DOLLAR_PRINT(data) DOLLAR_BASE(-1, data) +#define DOLLAR_CRITICAL(data) DOLLAR_BASE(1, data) +#define DOLLAR_ERROR(data) DOLLAR_BASE(2, data) +#define DOLLAR_WARNING(data) DOLLAR_BASE(3, data) +#ifdef DEBUG + #define DOLLAR_INFO(data) DOLLAR_BASE(4, data) + #define DOLLAR_DEBUG(data) DOLLAR_BASE(5, data) + #define DOLLAR_VERBOSE(data) DOLLAR_BASE(6, data) + #define DOLLAR_TODO(data) DOLLAR_BASE(4, "TODO : " << data) +#else + #define DOLLAR_INFO(data) do { } while(false) + #define DOLLAR_DEBUG(data) do { } while(false) + #define DOLLAR_VERBOSE(data) do { } while(false) + #define DOLLAR_TODO(data) do { } while(false) +#endif + +#define DOLLAR_HIDDEN(data) do { } while(false) + +#define DOLLAR_ASSERT(cond,data) \ + do { \ + if (!(cond)) { \ + DOLLAR_CRITICAL(data); \ + assert(!#cond); \ + } \ + } while (0) + + diff --git a/dollar/tools.cpp b/dollar/tools.cpp new file mode 100644 index 0000000..f88fccb --- /dev/null +++ b/dollar/tools.cpp @@ -0,0 +1,209 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2016, Edouard DUPIN, all right reserved + * @license APACHE v2.0 (see license file) + */ + +#include +#include +#include +#include + + +float dollar::pathLength(std::vector _points) { + float distance = 0; + for (size_t iii = 1; iii < _points.size(); ++iii) { + distance += (_points[iii] - _points[iii-1]).length(); + } + return distance; +} + +vec2 dollar::getBaryCenter(const std::vector& _points) { + vec2 center(0,0); + for (auto &it : _points) { + center += it; + } + center /= float(_points.size()); + return center; +} + +// TODO: Change this with the use of a generic matrix 2D... +std::vector dollar::rotateBy(const std::vector& _points, float _rotation) { + std::vector out; + vec2 center = getBaryCenter(_points); + float cosine = std::cos(_rotation); + float sine = std::sin(_rotation); + for (auto &it : _points) { + float qx = (it.x() - center.x()) * cosine - (it.y() - center.y()) * sine + center.x(); + float qy = (it.x() - center.x()) * sine + (it.y() - center.y()) * cosine + center.y(); + out.push_back(vec2(qx, qy)); + } + return out; +} + +std::vector dollar::rotateToZero(const std::vector& _points) { + vec2 center = getBaryCenter(_points); + float rotation = std::atan2(center.y() - _points[0].y(), center.x() - _points[0].x()); + return rotateBy(_points, -rotation); +} + +// TODO : Rework this to have a correct scale with keeping aspect ration ... or not ... +std::vector dollar::scaleToOne(const std::vector& _points, bool _keepAspectRation) { + dollar::Rectangle box(_points); + std::vector out; + vec2 scale(1.0f/box.getSize().x(), 1.0f/box.getSize().y()); + if (_keepAspectRation == true) { + float val = 1; + if (box.getSize().x() > 0) { + val = 1.0f/box.getSize().x(); + } else { + val = 1.0f/box.getSize().y(); + } + scale = vec2(val,val); + } + for (auto &it : _points) { + vec2 tmp = it - box.getPos(); + tmp *= scale; + out.push_back(tmp); + } + return out; +} + +std::vector> dollar::scaleToOne(const std::vector>& _points, bool _keepAspectRation) { + dollar::Rectangle box(_points); + std::vector> out; + vec2 scale(1.0f/box.getSize().x(), 1.0f/box.getSize().y()); + if (_keepAspectRation == true) { + float val = 1; + if (box.getSize().x() > 0) { + val = 1.0f/box.getSize().x(); + } else { + val = 1.0f/box.getSize().y(); + } + scale = vec2(val,val); + } + for (auto &it : _points) { + std::vector stroke; + for (auto &itPoint : it) { + vec2 tmp = itPoint - box.getPos(); + tmp *= scale; + stroke.push_back(tmp); + } + out.push_back(stroke); + } + return out; +} + +std::vector dollar::translateBariCenterToZero(std::vector _points) { + std::vector out; + vec2 center = getBaryCenter(_points); + for (auto &it :_points) { + out.push_back(it - center); + } + return out; +} + + +std::vector dollar::resample(std::vector _points, int32_t _nbPoints) { + std::vector out; + // calculate the interval between every points ... + float interval = pathLength(_points) / (_nbPoints - 1); + float distance = 0.0; + // same first point ==> no change + out.push_back(_points.front()); + // For all other point we have to resample elements + for (size_t iii=1; iii<_points.size(); ++iii) { + vec2 currentPoint = _points[iii]; + vec2 previousPoint = _points[iii-1]; + float tmpDist = (currentPoint-previousPoint).length(); + if ((distance + tmpDist) >= interval) { + vec2 point = previousPoint + (currentPoint - previousPoint) * ((interval - distance) / tmpDist); + out.push_back(point); + _points.insert(_points.begin() + iii, point); + distance = 0.0; + } else { + distance += tmpDist; + } + } + // somtimes we fall a rounding-error short of adding the last point, so add it if so + if (int64_t(out.size()) == (_nbPoints - 1)) { + out.push_back(_points.back()); + } + return out; +} + +std::vector> dollar::makeReferenceStrokes(const std::vector>& _strokes) { + std::vector> out; + // create the ordr of all possibilities of writing the strokes ... (ABC, ACB, BAC, BCA ...) + std::vector order; + for(size_t iii=0; iii<_strokes.size(); ++iii) { + order.push_back(iii); + } + // For all orders (every permutation of the path): + do { + // now we have an other problem: the user can write in multiple way the path + size_t nbPermutation = std::pow(2, order.size()); + // we use the bit like a flag to know the order of the draw + for (size_t permut=0; permut stroke; + for (size_t iii=0; iii pts = _strokes[order[iii]]; + // check to permut the value order + if (((permut>>iii) & 0x01) == 1) { + reverse(pts.begin(),pts.end()); + } + // Add point in next of the path... + for (auto &it : pts) { + stroke.push_back(it); + } + } + // Add new generated stroke + out.push_back(stroke); + } + } while (next_permutation(order.begin(), order.end())); + return out; +} + +std::vector dollar::combineStrokes(const std::vector>& _strokes) { + std::vector out; + for (auto &it : _strokes) { + for (auto &pointIt : it) { + out.push_back(pointIt); + } + } + return out; +} + +vec2 dollar::getStartVector(const std::vector& _points, float _index) { + DOLLAR_ASSERT(_index > 0, "index must be != of 0"); + vec2 vect = _points[_index] - _points[0]; + float len = vect.length(); + return vect / len; +} + +std::vector dollar::normalyse(const std::vector& _points) { + float sum = 0.0; + std::vector out = _points; + for (auto &it : _points) { + sum += it.length2(); + } + float magnitude = sqrt(sum); + if (magnitude == 0.0f) { + DOLLAR_ERROR("Magnetude is == 0"); + return out; + } + for (auto &it : out) { + it /= magnitude; + } + return out; +} + + +std::vector dollar::normalizePath(std::vector _points, size_t _nbSample, bool _ignoreRotation) { + _points = dollar::resample(_points, _nbSample); + if (_ignoreRotation == true) { + _points = rotateToZero(_points); + } + _points = scaleToOne(_points); + return translateBariCenterToZero(_points);; +} diff --git a/dollar/tools.h b/dollar/tools.h new file mode 100644 index 0000000..8cc8ccb --- /dev/null +++ b/dollar/tools.h @@ -0,0 +1,106 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2016, Edouard DUPIN, all right reserved + * @license APACHE v2.0 (see license file) + */ +#pragma once +#include +#include +#include + +namespace dollar { + /** + * @brief Get the size of a path (not the number of element but the distance of the path + * @param[in] _points List of point of the path + * @return the size of the path + */ + float pathLength(std::vector _points); + /** + * @brief Get the center position of the Path (baricenter)... + * @param[in] _points List of points. + * @return The center position of all the points. + */ + vec2 getBaryCenter(const std::vector& _points); + /** + * @brief Rotate a list of point from the center to the precise angle. + * @param[in] _points List of point in the path. + * @param[in] _rotation Angle to apply. + * @return new path with the rotated points. + */ + // TODO: Change this with the use of a generic matrix 2D... + std::vector rotateBy(const std::vector& _points, float _rotation); + /** + * @brief Rotate a path to a specific angle (0rad) + * @param[in] _points Path to rotate + * @return the Path aligned with 0; + */ + std::vector rotateToZero(const std::vector& _points); + /** + * @brief Get the Bounding box associated at a path + * @param[in] _points List of point at the path + * @return the rectangle with the bounding box associated + */ + dollar::Rectangle boundingBox(const std::vector& _points); + /** + * @brief Scale the list of point in a 1.0*1.0 box started at 0.0*0.0 + * @param[in] _points input path + * @param[in] _keepAspectRation Keep the aspect ratio of the scaling + * @return modify points + */ + std::vector scaleToOne(const std::vector& _points, bool _keepAspectRation=false); + /** + * @brief Scale the list of point in a 1.0*1.0 box started at 0.0*0.0 + * @param[in] _points input path + * @param[in] _keepAspectRation Keep the aspect ratio of the scaling + * @return modify points + */ + std::vector> scaleToOne(const std::vector>& _points, bool _keepAspectRation=false); + /** + * @brief Get center of the path and move the path to be center at (0,0) + * @param[in] _points List of point in the path + * @return centered path. + */ + std::vector translateBariCenterToZero(std::vector _points); + /** + * @brief Resample a path With a specific number of elements + * @param[in] _points Path to change number of elements + * @param[in] _nbPoints Number of point desired in the output path + * @return Resample path. + */ + std::vector resample(std::vector _points, int32_t _nbPoints); + /** + * @brief Make a list of all single stroke possible for a specific stroke (take in case the user can write the second stroke befor the first and he can do the stroke in the oposite way + * @param[in] _strokes List of all strokes + * @return List of a list of single stroke of multiple stroke + */ + std::vector> makeReferenceStrokes(const std::vector>& _strokes); + /** + * @brief combine some stroke in a single one. + * @param[in] _strokes value to merge + * @return Merged vector + */ + std::vector combineStrokes(const std::vector>& _strokes); + /** + * @brief Normalise the Path with the full magnetude of the data + * @param[in] _points Input path + * @return Normalized path + */ + std::vector normalyse(const std::vector& _points); + /** + * @brief Calculate a starting vector of the path + * @param[in] _points List of point of the path + * @param[in] _index position index to get the vector (ratio to 0) + * @return the start vector. + */ + vec2 getStartVector(const std::vector& _points, float _index = 1); + /** + * @brief Transform the path to be comparable, resample the path with a specific number of sample, and limit size at 1.0 square center around 0 + * @param[in] _points List of points in the path + * @param[in] _nbSample Number of element to resample + * @param[in] _ignoreRotation Ignore start rotation of the algorithm + * @return new list of points + */ + std::vector normalizePath(std::vector _points, size_t _nbSample, bool _ignoreRotation); +} + + diff --git a/lutin_dollar-converter.py b/lutin_dollar-converter.py new file mode 100644 index 0000000..7c77d1e --- /dev/null +++ b/lutin_dollar-converter.py @@ -0,0 +1,37 @@ +#!/usr/bin/python +import lutin.module as module +import lutin.tools as tools + + +def get_type(): + return "BINARY" + +def get_sub_type(): + return "TOOL" + +def get_desc(): + return "Dollar converter svg to json and json to SVG" + +def get_licence(): + return "APACHE-2" + +def get_compagny_type(): + return "com" + +def get_compagny_name(): + return "atria-soft" + +def get_maintainer(): + return ["Mr DUPIN Edouard "] + +def create(target, module_name): + my_module = module.Module(__file__, module_name, get_type()) + my_module.add_src_file([ + 'tool/converter/main.cpp' + ]) + my_module.add_module_depend([ + 'dollar', + 'test-debug', + ]) + return my_module + diff --git a/lutin_dollar-data.py b/lutin_dollar-data.py new file mode 100644 index 0000000..16b78ef --- /dev/null +++ b/lutin_dollar-data.py @@ -0,0 +1,30 @@ +#!/usr/bin/python +import lutin.module as module +import lutin.tools as tools + + +def get_type(): + return "DATA" + +def get_desc(): + return "dallar test-unit" + +def get_licence(): + return "APACHE-2" + +def get_compagny_type(): + return "com" + +def get_compagny_name(): + return "atria-soft" + +def get_maintainer(): + return ["Mr DUPIN Edouard "] + +def create(target, module_name): + my_module = module.Module(__file__, module_name, get_type()) + my_module.copy_path('data/text/*.json', 'text') + my_module.copy_path('data/figure/*.json', 'figure') + my_module.copy_path('data/test/*.json', 'test') + return my_module + diff --git a/lutin_dollar-test.py b/lutin_dollar-test.py new file mode 100644 index 0000000..d9d4c66 --- /dev/null +++ b/lutin_dollar-test.py @@ -0,0 +1,39 @@ +#!/usr/bin/python +import lutin.module as module +import lutin.tools as tools + + +def get_type(): + return "BINARY" + +def get_sub_type(): + return "TEST" + +def get_desc(): + return "dollar test-unit" + +def get_licence(): + return "APACHE-2" + +def get_compagny_type(): + return "com" + +def get_compagny_name(): + return "atria-soft" + +def get_maintainer(): + return ["Mr DUPIN Edouard "] + +def create(target, module_name): + my_module = module.Module(__file__, module_name, get_type()) + my_module.add_src_file([ + 'test/main.cpp' + ]) + my_module.add_module_depend([ + 'dollar', + 'dollar-data', + 'test-debug', + 'gtest', + ]) + return my_module + diff --git a/lutin_dollar.py b/lutin_dollar.py new file mode 100644 index 0000000..9a0a321 --- /dev/null +++ b/lutin_dollar.py @@ -0,0 +1,57 @@ +#!/usr/bin/python +import lutin.module as module +import lutin.tools as tools + + +def get_type(): + return "LIBRARY" + +def get_desc(): + return "$N gesture recognition" + +def get_licence(): + return "BSD-3" + +def get_compagny_type(): + return "com" + +def get_compagny_name(): + return "atria-soft" + +def get_maintainer(): + return ["Mr DUPIN Edouard "] + +def get_version(): + return [0,1,"dev"] + +def create(target, module_name): + my_module = module.Module(__file__, module_name, get_type()) + my_module.add_extra_compile_flags() + # add the file to compile: + my_module.add_src_file([ + 'dollar/debug.cpp', + 'dollar/Engine.cpp', + 'dollar/Gesture.cpp', + 'dollar/Results.cpp', + 'dollar/tools.cpp', + 'dollar/Rectangle.cpp' + ]) + + my_module.add_header_file([ + 'dollar/*.h', + ], + destination_path="dollar") + + # build in C++ mode + my_module.compile_version("c++", 2011) + # add dependency of the generic C++ library: + my_module.add_module_depend([ + 'cxx', + 'elog', + 'etk', + 'ejson', + 'esvg', + ]) + return my_module + + diff --git a/test/main.cpp b/test/main.cpp new file mode 100644 index 0000000..19eb54a --- /dev/null +++ b/test/main.cpp @@ -0,0 +1,92 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2016, Edouard DUPIN, all right reserved + * @license APACHE v2.0 (see license file) + */ + +#include +#include + +#include +#include +#include + +int main(int _argc, const char *_argv[]) { + // init Google test : + ::testing::InitGoogleTest(&_argc, const_cast(_argv)); + // init etk log system and file interface: + etk::init(_argc, _argv); + // Run all test with gtest + return RUN_ALL_TESTS(); +} + +/* + * single-stroke gesture recognition + */ +TEST(TestAll, singleStroke_normal) { + dollar::Engine reco; + reco.loadPath("DATA:figure"); + dollar::Results res = reco.recognize(dollar::loadPoints("DATA:test/Arrow.json"), "normal"); + EXPECT_EQ(res.haveMath(), true); + if (res.haveMath() == false) { + TEST_INFO(" Recognise noting ..."); + return; + } + EXPECT_EQ(res.getName(), "arrow"); + TEST_INFO("Results"); + for (size_t iii=0; iii