[DEV] first stable version

This commit is contained in:
Edouard DUPIN 2016-08-20 11:01:58 +02:00
parent b7d07981e6
commit 7f186ff963
77 changed files with 3523 additions and 2 deletions

4
.gitignore vendored
View File

@ -27,3 +27,7 @@
*.exe
*.out
*.app
#python temporary files
__pycache__
*.pyc

View File

@ -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.

15
data/figure/arrow_1.json Normal file
View File

@ -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]
]
]
}

73
data/figure/circle_1.json Normal file
View File

@ -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 ]
]
]
}

57
data/figure/circle_1.svg Normal file
View File

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="100"
width="100"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="circle_1.svg">
<metadata
id="metadata14">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs12" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1022"
id="namedview10"
showgrid="false"
inkscape:zoom="2.36"
inkscape:cx="-2.8813361e-09"
inkscape:cy="49.152542"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg2" />
<ellipse
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:1.08125556;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path3334"
cx="50"
cy="50.000004"
rx="49.45937"
ry="49.459373" />
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -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]
]
]
}

View File

@ -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]
]
]
}

12
data/figure/tick_1.json Normal file
View File

@ -0,0 +1,12 @@
{
"type":"REFERENCE",
"value":"tick",
"sub-id":1,
"data":[
[
[0.0,0.5],
[0.5,0.0],
[1.0,1.0]
]
]
}

View File

@ -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]
]
]
}

17
data/test/Arrow.json Normal file
View File

@ -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],
]
]
}

12
data/test/P.json Normal file
View File

@ -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]
]
]
}

17
data/text/A_1.json Normal file
View File

@ -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]
]
]
}

63
data/text/B_1.json Normal file
View File

@ -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 ]
]
]
}

67
data/text/B_1.svg Normal file
View File

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="100"
width="100"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="B_1.svg">
<metadata
id="metadata14">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs12" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1032"
inkscape:window-height="801"
id="namedview10"
showgrid="false"
inkscape:zoom="2.36"
inkscape:cx="50.113774"
inkscape:cy="49.978966"
inkscape:window-x="800"
inkscape:window-y="28"
inkscape:window-maximized="0"
inkscape:current-layer="svg2" />
<polyline
points="50.000000,0.000000 50.000000,100.000000"
id="polyline6"
transform="translate(-50,0)"
style="fill:none;stroke:#000000;stroke-width:2;stroke-opacity:1" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.69815958px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 0,0.34908033 c 131.51698,3e-7 134.06904,49.10250767 0.42424835,49.30184067"
id="path4144"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.69815958px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 0,50.349081 c 131.51698,1e-6 134.06904,49.102507 0.424248,49.30184"
id="path4144-3"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

42
data/text/C_1.json Normal file
View File

@ -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 ]
]
]
}

56
data/text/C_1.svg Normal file
View File

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="100"
width="100"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="C_1.svg">
<metadata
id="metadata14">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs12" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1022"
id="namedview10"
showgrid="false"
inkscape:zoom="2.36"
inkscape:cx="-2.8813361e-09"
inkscape:cy="49.152542"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg2" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.00227606px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 99.762443,15.178408 c -131.061261,-70.556909 -133.629318,139.945072 0,69.796417"
id="path4144"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

46
data/text/D_1.json Normal file
View File

@ -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 ]
]
]
}

61
data/text/D_1.svg Normal file
View File

@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="100"
width="100"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="D_1.svg">
<metadata
id="metadata14">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs12" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1600"
inkscape:window-height="801"
id="namedview10"
showgrid="false"
inkscape:zoom="2.36"
inkscape:cx="-0.84745763"
inkscape:cy="50"
inkscape:window-x="0"
inkscape:window-y="28"
inkscape:window-maximized="1"
inkscape:current-layer="svg2" />
<polyline
points="50.000000,0.000000 50.000000,100.000000"
id="polyline6"
transform="translate(-50,0)"
style="fill:none;stroke:#000000;stroke-width:2;stroke-opacity:1" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 0,-0.42372881 c 131.35593,5e-7 133.90485,100.86173881 0.42372881,101.27118881"
id="path4144"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

16
data/text/E_1.json Normal file
View File

@ -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]
]
]
}

14
data/text/F_1.json Normal file
View File

@ -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]
]
]
}

50
data/text/G_1.json Normal file
View File

@ -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 ]
]
]
}

66
data/text/G_1.svg Normal file
View File

@ -0,0 +1,66 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="100"
width="100"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="G_1.svg">
<metadata
id="metadata14">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs12" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1022"
id="namedview10"
showgrid="false"
inkscape:zoom="2.36"
inkscape:cx="0.84745762"
inkscape:cy="49.152542"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg2" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.00227606px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 95.525155,14.754679 C -60.959835,-59.19206 3.4212606,190.7167 93.83024,62.940927"
id="path4144"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 49.152542,61.864407 45.762712,0"
id="path3333"
inkscape:connector-curvature="0" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 94.915254,97.881356 0,-36.440678"
id="path3335"
inkscape:connector-curvature="0" />
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

14
data/text/H_1.json Normal file
View File

@ -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]
]
]
}

14
data/text/I_1.json Normal file
View File

@ -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]
]
]
}

35
data/text/J_1.json Normal file
View File

@ -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 ]
]
]
}

61
data/text/J_1.svg Normal file
View File

@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="100"
width="100"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="J_1.svg">
<metadata
id="metadata14">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs12" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1022"
id="namedview10"
showgrid="false"
inkscape:zoom="2.36"
inkscape:cx="1.6949152"
inkscape:cy="48.305084"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg2" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.00227606px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 50,0 C 55.084746,145.68167 3.844989,94.106534 1.0336298,71.415503"
id="path4144"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.99788809px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 100,0.50105596 -100,0"
id="path3335"
inkscape:connector-curvature="0" />
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

14
data/text/K_1.json Normal file
View File

@ -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]
]
]
}

12
data/text/L_1.json Normal file
View File

@ -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]
]
]
}

16
data/text/M_1.json Normal file
View File

@ -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]
]
]
}

14
data/text/N_1.json Normal file
View File

@ -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]
]
]
}

73
data/text/O_1.json Normal file
View File

@ -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 ]
]
]
}

57
data/text/O_1.svg Normal file
View File

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="100"
width="100"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="circle_1.svg">
<metadata
id="metadata14">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs12" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1022"
id="namedview10"
showgrid="false"
inkscape:zoom="2.36"
inkscape:cx="-2.8813361e-09"
inkscape:cy="49.152542"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg2" />
<ellipse
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:1.08125556;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path3334"
cx="50"
cy="50.000004"
rx="49.45937"
ry="49.459373" />
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

37
data/text/P_1.json Normal file
View File

@ -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 ]
]
]
}

61
data/text/P_1.svg Normal file
View File

@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="100"
width="100"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="P_1.svg">
<metadata
id="metadata14">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs12" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="800"
inkscape:window-height="801"
id="namedview10"
showgrid="false"
inkscape:zoom="2.36"
inkscape:cx="50.113774"
inkscape:cy="49.978966"
inkscape:window-x="800"
inkscape:window-y="28"
inkscape:window-maximized="0"
inkscape:current-layer="svg2" />
<polyline
points="50.000000,0.000000 50.000000,100.000000"
id="polyline6"
transform="translate(-50,0)"
style="fill:none;stroke:#000000;stroke-width:2;stroke-opacity:1" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.69815958px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 0,0.34908033 c 131.51698,3e-7 134.06904,49.10250767 0.42424835,49.30184067"
id="path4144"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

77
data/text/Q_1.json Normal file
View File

@ -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 ]
]
]
}

62
data/text/Q_1.svg Normal file
View File

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="100"
width="100"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="Q_1.svg">
<metadata
id="metadata14">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs12" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1022"
id="namedview10"
showgrid="false"
inkscape:zoom="2.36"
inkscape:cx="0.84745762"
inkscape:cy="49.152542"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg2" />
<ellipse
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:1.08125556;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path3334"
cx="50"
cy="50.000004"
rx="49.45937"
ry="49.459373" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 67.79661,73.728814 32.62712,26.694916"
id="path3333"
inkscape:connector-curvature="0" />
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

41
data/text/R_1.json Normal file
View File

@ -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 ]
]
]
}

67
data/text/R_1.svg Normal file
View File

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="100"
width="100"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="R_1.svg">
<metadata
id="metadata14">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs12" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="800"
inkscape:window-height="801"
id="namedview10"
showgrid="false"
inkscape:zoom="2.36"
inkscape:cx="50.113774"
inkscape:cy="49.978966"
inkscape:window-x="800"
inkscape:window-y="28"
inkscape:window-maximized="0"
inkscape:current-layer="svg2" />
<polyline
points="50.000000,0.000000 50.000000,100.000000"
id="polyline6"
transform="translate(-50,0)"
style="fill:none;stroke:#000000;stroke-width:2;stroke-opacity:1" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.69815958px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 0,0.34908033 c 131.51698,3e-7 134.06904,49.10250767 0.42424835,49.30184067"
id="path4144"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 0,50 100,50"
id="path3334"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

56
data/text/S_1.json Normal file
View File

@ -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 ]
]
]
}

56
data/text/S_1.svg Normal file
View File

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="100"
width="100"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="S_1.svg">
<metadata
id="metadata14">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs12" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="800"
inkscape:window-height="801"
id="namedview10"
showgrid="false"
inkscape:zoom="2.36"
inkscape:cx="90.544855"
inkscape:cy="76.673254"
inkscape:window-x="800"
inkscape:window-y="28"
inkscape:window-maximized="0"
inkscape:current-layer="svg2" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.69815958px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 100,0.34908033 C -18.72459,-2.1932923 -25.490396,47.587345 50,50 c 75.4904,2.412654 67.93244,56.95303 -50,50"
id="path4144"
inkscape:connector-curvature="0"
sodipodi:nodetypes="czc" />
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

12
data/text/T_1.json Normal file
View File

@ -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]
]
]
}

38
data/text/U_1.json Normal file
View File

@ -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 ]
]
]
}

61
data/text/U_1.svg Normal file
View File

@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="100"
width="100"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="U_1.svg">
<metadata
id="metadata14">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs12" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="800"
inkscape:window-height="801"
id="namedview10"
showgrid="false"
inkscape:zoom="2.36"
inkscape:cx="33.210862"
inkscape:cy="50.020299"
inkscape:window-x="800"
inkscape:window-y="28"
inkscape:window-maximized="0"
inkscape:current-layer="svg2" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.69815958px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 100,0 c 0,32.879245 0.4295,39.235481 0.081,75.548711 C 99.732491,111.86194 0.53196835,103.58429 0.0311269,76.147158 -0.46971456,48.710031 0.04983325,33.411198 0,0"
id="path4144"
inkscape:connector-curvature="0"
sodipodi:nodetypes="czzc" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 100.84746,100 100.42373,0"
id="path3337"
inkscape:connector-curvature="0" />
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

14
data/text/V_1.json Normal file
View File

@ -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]
],
]
}

16
data/text/W_1.json Normal file
View File

@ -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]
],
]
}

12
data/text/X_1.json Normal file
View File

@ -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]
]
]
}

14
data/text/Y_1.json Normal file
View File

@ -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]
]
]
}

14
data/text/Z_1.json Normal file
View File

@ -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]
],
]
}

View File

@ -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 ]
]
]
}

View File

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="100"
width="100"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="brace-left_1.svg">
<metadata
id="metadata14">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs12" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1600"
inkscape:window-height="801"
id="namedview10"
showgrid="false"
inkscape:zoom="3.337544"
inkscape:cx="95.364467"
inkscape:cy="55.575628"
inkscape:window-x="0"
inkscape:window-y="28"
inkscape:window-maximized="1"
inkscape:current-layer="svg2" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 99.576271,0.21186435 c -58.050847,0 -54.025424,18.64120465 -54.025424,26.48305165 0,27.119406 -45.33898259,23.728812 -45.33898259,23.728812 0,0 45.55277359,-3.389812 45.33898259,20.127119 C 45.43529,83.262186 49.364407,100 100.42373,100.42373"
id="path4209"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cscsc" />
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -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 ]
]
]
}

View File

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="100"
width="100"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="brace-right_1.svg">
<metadata
id="metadata14">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs12" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1022"
id="namedview10"
showgrid="false"
inkscape:zoom="3.337544"
inkscape:cx="95.96371"
inkscape:cy="54.976385"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg2" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 1.0261852,0.21186435 c 58.0508468,0 54.0254238,18.64120465 54.0254238,26.48305165 0,27.119406 45.338981,23.728812 45.338981,23.728812 0,0 -45.552772,-3.389812 -45.338981,20.127119 C 55.167166,83.262186 51.238049,100 0.17872618,100.42373"
id="path4209"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cscsc" />
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -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]
]
]
}

View File

@ -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]
]
]
}

View File

@ -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 ]
]
]
}

View File

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="100"
width="100"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="question-mark_1.svg">
<metadata
id="metadata14">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs12" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="800"
inkscape:window-height="801"
id="namedview10"
showgrid="false"
inkscape:zoom="3.337544"
inkscape:cx="36.014704"
inkscape:cy="56.990605"
inkscape:window-x="800"
inkscape:window-y="28"
inkscape:window-maximized="0"
inkscape:current-layer="svg2" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 31.75988,27.491593 C 31.749416,2.6230068 45.395948,0.52565618 57.22771,0.52565618 c 11.831762,0 20.074641,10.78637482 20.074641,24.86858582 0,14.082212 -15.580318,22.771235 -21.273127,34.756096 -5.692809,11.984861 -4.494323,19.175777 -4.194701,28.164423"
id="path4230"
inkscape:connector-curvature="0"
sodipodi:nodetypes="czzsc" />
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -0,0 +1,11 @@
{
"type":"REFERENCE",
"value":"\\",
"sub-id":1,
"data":[
[
[1.0,0.0],
[0.0,1.0]
]
]
}

11
data/text/slash_1.json Normal file
View File

@ -0,0 +1,11 @@
{
"type":"REFERENCE",
"value":"/",
"sub-id":1,
"data":[
[
[0.0,0.0],
[1.0,1.0]
]
]
}

16
data/text/star_1.json Normal file
View File

@ -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]
]
]
}

256
dollar/Engine.cpp Normal file
View File

@ -0,0 +1,256 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include <dollar/Engine.h>
#include <dollar/debug.h>
#include <dollar/Rectangle.h>
#include <dollar/tools.h>
#include <etk/os/FSNode.h>
#include <math.h>
#include <algorithm>
#define MAX_FLOAT std::numeric_limits<float>::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<vec2>& _path1, const std::vector<vec2>& _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<vec2>& _points, const std::vector<vec2>& _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<vec2>& _vect1, const std::vector<vec2>& _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<std::string> 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<vec2>& _points, const std::string& _method) {
std::vector<std::vector<vec2>> tmp;
tmp.push_back(_points);
return recognize(tmp, _method);
}
#define MAX_RESULT_NUMBER (5)
dollar::Results dollar::Engine::recognize(const std::vector<std::vector<vec2>>& _strokes, const std::string& _method) {
std::vector<vec2> 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<vec2> vector = normalyse(points);
// Keep maximum 5 results ...
float bestDistance[MAX_RESULT_NUMBER];
int32_t indexOfBestMatch[MAX_RESULT_NUMBER];
for (size_t iii=0; iii<MAX_RESULT_NUMBER; ++iii) {
bestDistance[iii] = MAX_FLOAT;
indexOfBestMatch[iii] = -1;
}
// for each multistroke
for (size_t iii=0; iii<m_gestures.size(); ++iii) {
DOLLAR_DEBUG("[" << iii << "] '" << m_gestures[iii].getName() << "'");
Gesture gesture = m_gestures[iii];
for (size_t jjj=0; jjj<gesture.getEngineSize(); ++jjj) {
if (gesture.getEnginePath(jjj).size() == 0) {
DOLLAR_ERROR("Reference path with no Value");
continue;
}
// strokes start in the same direction
if(angleBetweenUnitVectors(startv, gesture.getEngineStartVector(jjj)) > 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; kkk<MAX_RESULT_NUMBER; ++kkk) {
if (distance < bestDistance[kkk]) {
if (kkk == 0) {
DOLLAR_DEBUG("[" << iii << "," << jjj << "] d=" << distance << " < bd=" << bestDistance << " ");
}
if (indexOfBestMatch[kkk] != int64_t(iii)) {
for (int32_t rrr=MAX_RESULT_NUMBER-1; rrr>int32_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<MAX_RESULT_NUMBER; ++iii) {
if (-1 != indexOfBestMatch[0]) {
float score = MAX_FLOAT;;
if (bestDistance[iii] != 0.0) {
score = 1.0f / bestDistance[iii];
}
res.addValue(m_gestures[indexOfBestMatch[iii]].getName(), score);
}
}
} else {
for (size_t iii=0; iii<MAX_RESULT_NUMBER; ++iii) {
if (-1 != indexOfBestMatch[0]) {
float score = 1.0 - (bestDistance[iii] / HALF_DIAGONAL);
res.addValue(m_gestures[indexOfBestMatch[iii]].getName(), score);
}
}
}
return res;
}

42
dollar/Engine.h Normal file
View File

@ -0,0 +1,42 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#pragma once
#include <etk/math/Vector2D.h>
#include <limits>
#include <iostream>
#include <dollar/Results.h>
#include <string>
#include <dollar/Gesture.h>
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<Gesture> m_gestures; //!< List of all loaded gesture in the engine
public:
Engine();
float distanceAtBestAngle(const std::vector<vec2>& _points, const std::vector<vec2>& _reference);
Results recognize(const std::vector<std::vector<vec2>>& _paths, const std::string& _method="normal");
Results recognize(const std::vector<vec2>& _points, const std::string& _method="normal");
float optimalCosineDistance(const std::vector<vec2>& _vect1, const std::vector<vec2>& _vect2);
bool loadPath(const std::string& _path);
bool loadGesture(const std::string& _filename);
void addGesture(Gesture _gesture);
};
}

169
dollar/Gesture.cpp Normal file
View File

@ -0,0 +1,169 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include <dollar/debug.h>
#include <dollar/Gesture.h>
#include <dollar/tools.h>
#include <etk/os/FSNode.h>
#include <ejson/ejson.h>
#include <esvg/esvg.h>
#include <etk/stdTools.h>
static std::vector<std::vector<vec2>> loadPointsJson(const ejson::Document& _doc) {
// extract lines:
std::vector<std::vector<vec2>> 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<vec2> 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<std::vector<vec2>> 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<std::string> 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<std::vector<vec2>> strokes = dollar::scaleToOne(m_path);
std::string data("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n");
data += "<svg height=\"100\" width=\"100\">\n";
for (auto &itLines : strokes) {
data += " <polyline\n";
data += " fill=\"none\"\n";
data += " stroke=\"black\"\n";
data += " stroke-opacity=\"1\"\n";
data += " stroke-width=\"2\"\n";
data += " points=\"";
bool first = true;
for (auto& itPoints : itLines) {
if (first == false) {
data += " ";
}
first = false;
data += etk::to_string(itPoints.x()*100.0f) + "," + etk::to_string(itPoints.y()*100.0f);
}
data += "\"\n";
data += " />\n";
}
data += "</svg>\n";
etk::FSNodeWriteAllData(_fileName, data);
}
void dollar::Gesture::configure(float _startAngleIndex, size_t _nbSample, bool _ignoreRotation) {
m_enginePath.clear();
m_engineVector.clear();
m_engineStartV.clear();
// Simplyfy paths
std::vector<std::vector<vec2>> uniPath = dollar::makeReferenceStrokes(m_path);
// normalize paths
for (auto &it : uniPath) {
std::vector<vec2> 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));
}
}

57
dollar/Gesture.h Normal file
View File

@ -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 <string>
#include <etk/math/Vector2D.h>
namespace dollar {
class Gesture {
protected:
std::string m_name;
uint32_t m_subId;
std::vector<std::vector<vec2>> 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<std::vector<vec2>>& getPath() const {
return m_path;
}
std::vector<std::vector<vec2>>& getPath() {
return m_path;
}
protected:
std::vector<std::vector<vec2>> m_enginePath; // Singulized path with every conbinaison
std::vector<std::vector<vec2>> m_engineVector;
std::vector<vec2> 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<vec2>& getEnginePath(size_t _id) const {
return m_enginePath[_id];
}
const std::vector<vec2>& getEngineVector(size_t _id) const {
return m_engineVector[_id];
}
const vec2& getEngineStartVector(size_t _id) const {
return m_engineStartV[_id];
}
};
std::vector<std::vector<vec2>> loadPoints(const std::string& _fileName);
}

47
dollar/Rectangle.cpp Normal file
View File

@ -0,0 +1,47 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include <dollar/Rectangle.h>
#include <dollar/debug.h>
#define MAX_FLOAT std::numeric_limits<float>::max()
dollar::Rectangle::Rectangle(const vec2& _pos, const vec2& _size):
m_pos(_pos),
m_size(_size) {
}
dollar::Rectangle::Rectangle(const std::vector<vec2>& _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<std::vector<vec2>>& _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;
}

53
dollar/Rectangle.h Normal file
View File

@ -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 <math.h>
#include <string>
#include <list>
#include <vector>
#include <etk/math/Vector2D.h>
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<vec2>& _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<std::vector<vec2>>& _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;
};
}

47
dollar/Results.cpp Normal file
View File

@ -0,0 +1,47 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include <dollar/debug.h>
#include <dollar/Results.h>
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();
}

28
dollar/Results.h Normal file
View File

@ -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 <math.h>
#include <string>
#include <list>
#include <vector>
namespace dollar {
class Results {
protected:
std::vector<std::pair<std::string,float>> 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();
};
}

13
dollar/debug.cpp Normal file
View File

@ -0,0 +1,13 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include <dollar/debug.h>
int32_t dollar::getLogId() {
static int32_t g_val = elog::registerInstance("dollar");
return g_val;
}

45
dollar/debug.h Normal file
View File

@ -0,0 +1,45 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include <etk/types.h>
#pragma once
#include <elog/log.h>
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)

209
dollar/tools.cpp Normal file
View File

@ -0,0 +1,209 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include <dollar/tools.h>
#include <dollar/debug.h>
#include <math.h>
#include <algorithm>
float dollar::pathLength(std::vector<vec2> _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<vec2>& _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<vec2> dollar::rotateBy(const std::vector<vec2>& _points, float _rotation) {
std::vector<vec2> 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<vec2> dollar::rotateToZero(const std::vector<vec2>& _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<vec2> dollar::scaleToOne(const std::vector<vec2>& _points, bool _keepAspectRation) {
dollar::Rectangle box(_points);
std::vector<vec2> 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<std::vector<vec2>> dollar::scaleToOne(const std::vector<std::vector<vec2>>& _points, bool _keepAspectRation) {
dollar::Rectangle box(_points);
std::vector<std::vector<vec2>> 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<vec2> stroke;
for (auto &itPoint : it) {
vec2 tmp = itPoint - box.getPos();
tmp *= scale;
stroke.push_back(tmp);
}
out.push_back(stroke);
}
return out;
}
std::vector<vec2> dollar::translateBariCenterToZero(std::vector<vec2> _points) {
std::vector<vec2> out;
vec2 center = getBaryCenter(_points);
for (auto &it :_points) {
out.push_back(it - center);
}
return out;
}
std::vector<vec2> dollar::resample(std::vector<vec2> _points, int32_t _nbPoints) {
std::vector<vec2> 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<std::vector<vec2>> dollar::makeReferenceStrokes(const std::vector<std::vector<vec2>>& _strokes) {
std::vector<std::vector<vec2>> out;
// create the ordr of all possibilities of writing the strokes ... (ABC, ACB, BAC, BCA ...)
std::vector<size_t> 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<nbPermutation; ++permut) {
std::vector<vec2> stroke;
for (size_t iii=0; iii<order.size(); ++iii) {
std::vector<vec2> 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<vec2> dollar::combineStrokes(const std::vector<std::vector<vec2>>& _strokes) {
std::vector<vec2> out;
for (auto &it : _strokes) {
for (auto &pointIt : it) {
out.push_back(pointIt);
}
}
return out;
}
vec2 dollar::getStartVector(const std::vector<vec2>& _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<vec2> dollar::normalyse(const std::vector<vec2>& _points) {
float sum = 0.0;
std::vector<vec2> 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<vec2> dollar::normalizePath(std::vector<vec2> _points, size_t _nbSample, bool _ignoreRotation) {
_points = dollar::resample(_points, _nbSample);
if (_ignoreRotation == true) {
_points = rotateToZero(_points);
}
_points = scaleToOne(_points);
return translateBariCenterToZero(_points);;
}

106
dollar/tools.h Normal file
View File

@ -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 <etk/types.h>
#include <etk/math/Vector2D.h>
#include <dollar/Rectangle.h>
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<vec2> _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<vec2>& _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<vec2> rotateBy(const std::vector<vec2>& _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<vec2> rotateToZero(const std::vector<vec2>& _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<vec2>& _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<vec2> scaleToOne(const std::vector<vec2>& _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<std::vector<vec2>> scaleToOne(const std::vector<std::vector<vec2>>& _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<vec2> translateBariCenterToZero(std::vector<vec2> _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<vec2> resample(std::vector<vec2> _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<std::vector<vec2>> makeReferenceStrokes(const std::vector<std::vector<vec2>>& _strokes);
/**
* @brief combine some stroke in a single one.
* @param[in] _strokes value to merge
* @return Merged vector
*/
std::vector<vec2> combineStrokes(const std::vector<std::vector<vec2>>& _strokes);
/**
* @brief Normalise the Path with the full magnetude of the data
* @param[in] _points Input path
* @return Normalized path
*/
std::vector<vec2> normalyse(const std::vector<vec2>& _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<vec2>& _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<vec2> normalizePath(std::vector<vec2> _points, size_t _nbSample, bool _ignoreRotation);
}

37
lutin_dollar-converter.py Normal file
View File

@ -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 <yui.heero@gmail.com>"]
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

30
lutin_dollar-data.py Normal file
View File

@ -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 <yui.heero@gmail.com>"]
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

39
lutin_dollar-test.py Normal file
View File

@ -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 <yui.heero@gmail.com>"]
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

57
lutin_dollar.py Normal file
View File

@ -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 <yui.heero@gmail.com>"]
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

92
test/main.cpp Normal file
View File

@ -0,0 +1,92 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include <iostream>
#include <dollar/Engine.h>
#include <etk/etk.h>
#include <test-debug/debug.h>
#include <gtest/gtest.h>
int main(int _argc, const char *_argv[]) {
// init Google test :
::testing::InitGoogleTest(&_argc, const_cast<char **>(_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<res.getSize(); ++iii) {
TEST_INFO(" - " << res.getName(iii) << " score=" << res.getConfidence(iii));
}
}
TEST(TestAll, singleStroke_protractor) {
dollar::Engine reco;
reco.loadPath("DATA:figure");
dollar::Results res = reco.recognize(dollar::loadPoints("DATA:test/Arrow.json"), "protractor");
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<res.getSize(); ++iii) {
TEST_INFO(" - " << res.getName(iii) << " score=" << res.getConfidence(iii));
}
}
/*
* multi-stroke gesture recognition
*/
TEST(TestAll, multiStroke_normal) {
dollar::Engine reco;
reco.loadPath("DATA:text");
dollar::Results res = reco.recognize(dollar::loadPoints("DATA:test/P.json"), "normal");
EXPECT_EQ(res.haveMath(), true);
if (res.haveMath() == false) {
TEST_INFO(" Recognise noting ...");
return;
}
EXPECT_EQ(res.getName(), "P");
TEST_INFO("Results");
for (size_t iii=0; iii<res.getSize(); ++iii) {
TEST_INFO(" - " << res.getName(iii) << " score=" << res.getConfidence(iii));
}
}
TEST(TestAll, multiStroke_protractor) {
dollar::Engine reco;
reco.loadPath("DATA:text");
dollar::Results res = reco.recognize(dollar::loadPoints("DATA:test/P.json"), "protractor");
EXPECT_EQ(res.haveMath(), true);
if (res.haveMath() == false) {
TEST_INFO(" Recognise noting ...");
return;
}
EXPECT_EQ(res.getName(), "P");
TEST_INFO("Results");
for (size_t iii=0; iii<res.getSize(); ++iii) {
TEST_INFO(" - " << res.getName(iii) << " score=" << res.getConfidence(iii));
}
}

79
tool/converter/main.cpp Normal file
View File

@ -0,0 +1,79 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include <iostream>
#include <dollar/Engine.h>
#include <etk/etk.h>
#include <test-debug/debug.h>
void usage(const std::string& _progName) {
TEST_PRINT("usage:");
TEST_PRINT(" " << _progName << " [option] source destination");
TEST_PRINT(" [option]");
TEST_PRINT(" -h --help Display this help");
TEST_PRINT(" parameters (must be here)");
TEST_PRINT(" source file .json or .svg");
TEST_PRINT(" destination file .json or .svg");
}
int main(int _argc, const char *_argv[]) {
// init etk log system and file interface:
etk::init(_argc, _argv);
std::string src;
std::string dst;
for (int32_t iii=1; iii<_argc; ++iii) {
std::string arg = _argv[iii];
if ( arg == "-h"
|| arg == "--help") {
usage(_argv[0]);
return 0;
}
if (src == "") {
src = arg;
continue;
}
if (dst == "") {
dst = arg;
continue;
}
if( arg[0] == '-'
&& arg[1] == '-') {
// subLibrary usage ...
continue;
}
usage(_argv[0]);
return -1;
}
if ( src == ""
|| dst == "") {
TEST_ERROR("Missing input or output");
usage(_argv[0]);
return -1;
}
// declare a Gesture (internal API)
dollar::Gesture ref;
TEST_PRINT("---------------------------------------------------------------------------");
TEST_PRINT("-- Load gesture: " << src);
TEST_PRINT("---------------------------------------------------------------------------");
// Load gesture with his extention type:
std::string tmpName = etk::tolower(src);
if (ref.load(src) == false) {
TEST_ERROR("Error when loading the gesture");
return -1;
}
TEST_PRINT("---------------------------------------------------------------------------");
TEST_PRINT("-- Store gesture: " << dst);
TEST_PRINT("---------------------------------------------------------------------------");
// Store gesture with his extention type:
if (ref.store(dst) == false) {
TEST_ERROR("UNKNOW 'destination' extention type");
usage(_argv[0]);
return -1;
}
// All is done corectly
return 0;
}