Skip to content

Instantly share code, notes, and snippets.

@selvypen
Last active May 25, 2020 04:47
Show Gist options
  • Save selvypen/d7435e8c3a81244cbb1ddc1bb4995e5c to your computer and use it in GitHub Desktop.
Save selvypen/d7435e8c3a81244cbb1ddc1bb4995e5c to your computer and use it in GitHub Desktop.
Simple example source of math recognition for Windows using C++
/*!
* @brief simple example source of math recognition
* @date 2020/01/16
* @file math_simple_example.cpp
* @author SELVAS AI
*
* Copyright 2020. SELVAS AI Inc. All Rights Reserved.
*/
#include <stdio.h>
#include <locale.h>
#include "dhwr.h"
#define log(...) printf(__VA_ARGS__)
// points of '\frac{2x+4}{5y-2}'
// -1, 0 : end of stroke
// -1, -1 : end of ink
// (x0, y0), (x1, y1), ... (-1, 0) ... (xn, yn) .... (-1, 0), (-1, -1)
const int ink_fraction[] = {383, 614, 325, 755, 338, 759, 373, 759, 392, 772, 353, 808, 318,
825, 320, 805, -1, 0, 348, 691, 351, 688, 358, 676, 397, 668, 427, 667, 433, 663, -1, 0,
528, 642, 533, 647, 524, 654, 506, 696, 503, 729, 515, 726, 528, 711, 561, 671, 586,
648, 585, 657, 572, 701, 563, 736, 545, 810, 518, 860, 498, 865, 478, 849, 480, 822,
515, 783, 535, 769, 587, 744, 620, 735, 631, 732, 642, 732, 644, 733, -1, 0, 714, 691,
712, 685, 750, 684, 771, 679, 778, 678, -1, 0, 880, 665, 891, 660, 926, 655, 938, 659,
958, 680, 940, 706, 923, 719, 883, 743, 876, 750, 892, 752, 933, 749, 979, 744, 999,
743, 1023, 743, 1003, 744, -1, 0, 193, 531, 206, 526, 258, 529, 316, 528, 384, 524, 418,
522, 500, 520, 575, 519, 604, 518, 661, 517, 715, 516, 752, 515, 798, 512, 852, 508,
873, 508, 915, 505, 961, 502, 979, 501, 1023, 500, 1055, 500, 1070, 499, 1100, 497,
1135, 495, 1146, 493, 1163, 492, 1152, 490, 1131, 487, -1, 0, 302, 341, 340, 342, 365,
355, 369, 379, 327, 416, 313, 427, 304, 436, 337, 430, 362, 424, 414, 410, 430, 406,
423, 406, -1, 0, 444, 337, 450, 337, 479, 319, 509, 325, 511, 347, 492, 386, 481, 405,
465, 428, 472, 414, -1, 0, 537, 292, 534, 292, 512, 303, 498, 337, 500, 378, 520, 419,
529, 429, 548, 445, 555, 452, 558, 453, -1, 0, 607, 374, 613, 369, 660, 371, 728, 364,
761, 356, 760, 349, -1, 0, 688, 316, 686, 318, 681, 331, 690, 388, 693, 407, 696, 426,
697, 423, -1, 0, 842, 292, 851, 296, 849, 311, 830, 354, 821, 376, 827, 391, 861, 398,
926, 402, 985, 401, 995, 400, 989, 398, -1, 0, 959, 281, 941, 293, 916, 337, 890, 401,
869, 458, 864, 479, 866, 488, -1, 0, -1, -1};
// points of '\sqrt{144}+\sqrt{1728}'
const int ink_square_root[] = {376, 665, 375, 659, 383, 680, 394, 704, 405, 717, 410, 691, 411,
666, 408, 566, 404, 495, 410, 450, 413, 437, 419, 429, 449, 427, 498, 436, 602, 440,
759, 428, 824, 421, 859, 418, 857, 428, -1, 0, 516, 571, 509, 580, 513, 625, 519, 648,
526, 644, -1, 0, 624, 545, 627, 545, 627, 553, 594, 582, 562, 604, 567, 609, 606, 605,
657, 596, 670, 588, -1, 0, 613, 555, 612, 553, 620, 569, 624, 616, 630, 634, 635, 632,
-1, 0, 728, 547, 729, 548, 695, 580, 671, 597, 672, 601, 716, 601, 775, 594, 786, 590,
-1, 0, 739, 541, 728, 562, 729, 606, 733, 642, 743, 654, -1, 0, 1063, 519, 1054, 536,
1058, 577, 1060, 597, -1, 0, 1023, 563, 1032, 558, 1087, 553, 1117, 552, -1, 0, 1315,
620, 1319, 620, 1343, 652, 1360, 672, 1361, 650, 1359, 570, 1363, 484, 1365, 424, 1370,
413, 1391, 412, 1454, 415, 1519, 413, 1685, 397, 1816, 382, 1910, 377, 1980, 386, 1963,
394, -1, 0, 1506, 512, 1493, 512, 1499, 556, 1504, 592, 1509, 608, 1513, 602, -1, 0,
1586, 505, 1586, 511, 1573, 560, 1560, 549, 1564, 534, 1586, 506, 1614, 497, 1635, 525,
1637, 554, 1624, 617, 1618, 639, 1617, 641, 1623, 632, -1, 0, 1714, 542, 1731, 516,
1778, 519, 1792, 561, 1778, 578, 1735, 595, 1713, 593, 1733, 587, 1753, 584, 1811, 579,
1838, 578, -1, 0, 1925, 527, 1925, 520, 1906, 470, 1886, 476, 1877, 525, 1885, 576,
1873, 615, 1852, 617, 1862, 561, 1907, 535, 1942, 531, 1959, 542, -1, 0, -1, -1};
const int DHWR_MAX_CANDIDATES = 10;
DHWRInkObject ink_obj = NULL;
DHWRResultObject result_obj = NULL;
DHWRSettingObject setting_obj = NULL;
void make_input_event(DHWRInkObject ink, const int* inputs) {
DHWRInkClear(ink);
int i = 0;
while (true) {
if (inputs[i + 0] == -1 && inputs[i + 1] == -1) {
break;
} else if (inputs[i + 0] == -1 && inputs[i + 1] == 0) {
DHWREndStroke(ink);
} else {
DHWRAddPoint(ink, inputs[i + 0], inputs[i + 1]);
}
i += 2;
}
}
void print_wchar(const wchar_t* result, int size) {
int i;
for (i = 0; i < size; i++) {
log("%C", result[i]);
}
}
void print_candidate(DHWRResultObject result) {
bool exit = false;
unsigned int length;
int size_line = DHWRGetLineSize(result);
if (size_line == 0) {
log("result empty\n");
return;
}
for (unsigned int i = 0; i < DHWR_MAX_CANDIDATES; i++) {
for (int j = 0; j < size_line; j++) {
DHWRResultLine line = DHWRGetLine(result, j);
int size_block = DHWRGetBlockSize(line);
for (int k = 0; k < size_block; k++) {
DHWRResultBlock block = DHWRGetBlock(line, k);
if (DHWRGetCandidateSize(block) <= i) {
exit = true;
break;
}
log("[%02d] ", i + 1);
const wchar_t* current_cand = (const wchar_t*)(DHWRGetCandidate(block, i, &length));
print_wchar(current_cand, length);
if (k + 1 < size_block) {
log(", ");
}
}
if (exit) {
break;
}
if (j + 1 < size_line) {
log("\n");
}
}
if (exit) {
break;
}
log("\n");
}
}
void print_result(const char *title, int status) {
log("\n%s ", title);
if (status == ERR_SUCCESS) {
log("...Success\n");
print_candidate(result_obj);
} else {
log("...Failed (%d)\n", status);
}
}
int initEngine() {
char *version;
DHWRGetRevision(&version);
unsigned long status = ERR_SUCCESS;
status = DHWRCreate("./license_key/license.key");
if (ink_obj == NULL) {
ink_obj = DHWRCreateInkObject();
}
if (result_obj == NULL) {
result_obj = DHWRCreateResultObject();
}
if (setting_obj == NULL) {
setting_obj = DHWRCreateSettingObject();
}
DHWRSetExternalResourcePath("./hdb/");
DHWRSetRecognitionMode(setting_obj, MULTICHAR);
DHWRSetCandidateSize(setting_obj, DHWR_MAX_CANDIDATES);
log("\nSDK Version: %s", version);
log("\nInitialize Engine ...%s (%ld)\n", status == ERR_SUCCESS ? "Success" : "Failed", status);
return status;
}
int destroyEngine() {
unsigned long status = ERR_SUCCESS;
status = DHWRClose();
if (ink_obj != NULL) {
DHWRDestroyInkObject(ink_obj);
}
if (result_obj != NULL) {
DHWRDestroyResultObject(result_obj);
}
if (setting_obj != NULL) {
DHWRDestroySettingObject(setting_obj);
}
log("\nDestroy Engine ...%s (%ld)\n", status == ERR_SUCCESS ? "Success" : "Failed", status);
return status;
}
int testFraction() {
unsigned long status = ERR_SUCCESS;
DHWRClearLanguage(setting_obj);
DHWRAddLanguage(setting_obj, DLANG_MATH_MIDDLE_EXPANSION, DTYPE_MATH_EX);
status = DHWRSetAttribute(setting_obj);
make_input_event(ink_obj, ink_fraction);
status = DHWRecognize(ink_obj, result_obj);
print_result("Fraction Test", status);
return status;
}
int testSquareRoot() {
unsigned long status = ERR_SUCCESS;
DHWRClearLanguage(setting_obj);
DHWRAddLanguage(setting_obj, DLANG_MATH_MIDDLE_EXPANSION, DTYPE_MATH_EX);
DHWRSetAttribute(setting_obj);
make_input_event(ink_obj, ink_square_root);
status = DHWRecognize(ink_obj, result_obj);
print_result("Square root Test", status);
return status;
}
int main() {
setlocale(LC_ALL, "");
initEngine();
testFraction();
testSquareRoot();
destroyEngine();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment