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