Loading native/jni/src/geometry_utils.h 0 → 100644 +101 −0 Original line number Diff line number Diff line /* * Copyright (C) 2012 The Android Open Source Project * * 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. */ #ifndef LATINIME_INCREMENTAL_GEOMETRY_UTILS_H #define LATINIME_INCREMENTAL_GEOMETRY_UTILS_H #include <cmath> #define MAX_DISTANCE 10000000 #define KEY_NUM 27 #define SPACE_KEY 26 #define MAX_PATHS 2 #define DEBUG_DECODER false namespace latinime { static inline float sqr(float x) { return x * x; } static inline float getNormalizedSqrDistance(int x1, int y1, int x2, int y2, int scale) { return sqr((x1 - x2) * 1.0 / scale) + sqr((y1 - y2) * 1.0 / scale); } static inline int getDistance(int x1, int y1, int x2, int y2) { return (int) sqrt(sqr(x2 - x1) + sqr(y2 - y1)); } static inline float getDistanceSq(float x1, float y1, float x2, float y2) { return sqr(x2 - x1) + sqr(y2 - y1); } static inline float getAngle(int x1, int y1, int x2, int y2) { float dx = x1 - x2; float dy = y1 - y2; if (dx == 0 && dy == 0) return 0; return atan2(dy, dx); } static inline float angleDiff(float a1, float a2) { float diff = a1 - a2; if (diff < 0) { diff = -diff; } if (diff > M_PI) { return 2 * M_PI - diff; } return diff; } //static float pointToLineDistanceSq(float x, float y, float x1, float y1, float x2, float y2) { // float A = x - x1; // float B = y - y1; // float C = x2 - x1; // float D = y2 - y1; // return abs(A * D - C * B) / sqrt(C * C + D * D); //} static inline float pointToLineSegDistanceSq( float x, float y, float x1, float y1, float x2, float y2) { float ray1x = x - x1; float ray1y = y - y1; float ray2x = x2 - x1; float ray2y = y2 - y1; float dotProduct = ray1x * ray2x + ray1y * ray2y; float lineLengthSq = ray2x * ray2x + ray2y * ray2y; float projectionLengthSq = dotProduct / lineLengthSq; float projectionX, projectionY; if (projectionLengthSq < 0) { projectionX = x1; projectionY = y1; } else if (projectionLengthSq > 1) { projectionX = x2; projectionY = y2; } else { projectionX = x1 + projectionLengthSq * ray2x; projectionY = y1 + projectionLengthSq * ray2y; } float dist = getDistanceSq(x, y, projectionX, projectionY); return dist; } } // namespace latinime #endif // LATINIME_INCREMENTAL_GEOMETRY_UTILS_H native/jni/src/proximity_info.cpp +64 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ #include "additional_proximity_chars.h" #include "char_utils.h" #include "defines.h" #include "geometry_utils.h" #include "jni.h" #include "proximity_info.h" Loading Loading @@ -55,6 +56,7 @@ ProximityInfo::ProximityInfo(JNIEnv *env, const jstring localeJStr, const int ma const jfloatArray sweetSpotRadii) : MAX_PROXIMITY_CHARS_SIZE(maxProximityCharsSize), KEYBOARD_WIDTH(keyboardWidth), KEYBOARD_HEIGHT(keyboardHeight), GRID_WIDTH(gridWidth), GRID_HEIGHT(gridHeight), MOST_COMMON_KEY_WIDTH(mostCommonKeyWidth), MOST_COMMON_KEY_WIDTH_SQUARE(mostCommonKeyWidth * mostCommonKeyWidth), CELL_WIDTH((keyboardWidth + gridWidth - 1) / gridWidth), CELL_HEIGHT((keyboardHeight + gridHeight - 1) / gridHeight), Loading Loading @@ -84,6 +86,7 @@ ProximityInfo::ProximityInfo(JNIEnv *env, const jstring localeJStr, const int ma safeGetOrFillZeroFloatArrayRegion(env, sweetSpotCenterYs, KEY_COUNT, mSweetSpotCenterYs); safeGetOrFillZeroFloatArrayRegion(env, sweetSpotRadii, KEY_COUNT, mSweetSpotRadii); initializeCodeToKeyIndex(); initializeG(); } // Build the reversed look up table from the char code to the index in mKeyXCoordinates, Loading Loading @@ -222,6 +225,67 @@ int ProximityInfo::getKeyIndex(const int c) const { return mCodeToKeyIndex[baseLowerC]; } int ProximityInfo::getKeyCode(const int keyIndex) const { if (keyIndex < 0 || keyIndex >= KEY_COUNT) { return NOT_AN_INDEX; } return mKeyToCodeIndexG[keyIndex]; } void ProximityInfo::initializeG() { for (int i = 0; i < KEY_COUNT; ++i) { const int code = mKeyCharCodes[i]; const int lowerCode = toBaseLowerCase(code); mCenterXsG[i] = mKeyXCoordinates[i] + mKeyWidths[i] / 2; mCenterYsG[i] = mKeyYCoordinates[i] + mKeyHeights[i] / 2; if (code != lowerCode && lowerCode >= 0 && lowerCode <= MAX_CHAR_CODE) { mCodeToKeyIndex[lowerCode] = i; mKeyToCodeIndexG[i] = lowerCode; } else { mKeyToCodeIndexG[i] = code; } } for (int i = 0; i < KEY_COUNT; i++) { mKeyKeyDistancesG[i][i] = 0; for (int j = i + 1; j < KEY_COUNT; j++) { mKeyKeyDistancesG[i][j] = getDistance( mCenterXsG[i], mCenterYsG[i], mCenterXsG[j], mCenterYsG[j]); mKeyKeyDistancesG[j][i] = mKeyKeyDistancesG[i][j]; } } } float ProximityInfo::getKeyCenterXOfCharG(int charCode) const { return getKeyCenterXOfIdG(getKeyIndex(charCode)); } float ProximityInfo::getKeyCenterYOfCharG(int charCode) const { return getKeyCenterYOfIdG(getKeyIndex(charCode)); } float ProximityInfo::getKeyCenterXOfIdG(int keyId) const { if (keyId >= 0) { return mCenterXsG[keyId]; } return 0; } float ProximityInfo::getKeyCenterYOfIdG(int keyId) const { if (keyId >= 0) { return mCenterYsG[keyId]; } return 0; } int ProximityInfo::getKeyKeyDistanceG(int key0, int key1) const { const int keyId0 = getKeyIndex(key0); const int keyId1 = getKeyIndex(key1); if (keyId0 >= 0 && keyId1 >= 0) { return mKeyKeyDistancesG[keyId0][keyId1]; } return 0; } // TODO: [Staging] Optimize void ProximityInfo::getCenters(int *centerXs, int *centerYs, int *codeToKeyIndex, int *keyToCodeIndex, int *keyCount, int *keyWidth) const { Loading native/jni/src/proximity_info.h +18 −0 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ class ProximityInfo { return left < right && top < bottom && x >= left && x < right && y >= top && y < bottom; } int getKeyIndex(const int c) const; int getKeyCode(const int keyIndex) const; bool hasSweetSpotData(const int keyIndex) const { // When there are no calibration data for a key, // the radius of the key is assigned to zero. Loading @@ -70,6 +71,10 @@ class ProximityInfo { return HAS_TOUCH_POSITION_CORRECTION_DATA; } int getMostCommonKeyWidth() const { return MOST_COMMON_KEY_WIDTH; } int getMostCommonKeyWidthSquare() const { return MOST_COMMON_KEY_WIDTH_SQUARE; } Loading Loading @@ -98,6 +103,12 @@ class ProximityInfo { return GRID_HEIGHT; } float getKeyCenterXOfCharG(int charCode) const; float getKeyCenterYOfCharG(int charCode) const; float getKeyCenterXOfIdG(int keyId) const; float getKeyCenterYOfIdG(int keyId) const; int getKeyKeyDistanceG(int key0, int key1) const; // Returns the keyboard key-center information. void getCenters(int *centersX, int *centersY, int *codeToKeyIndex, int *keyToCodeIndex, int *keyCount, int *keyWidth) const; Loading @@ -113,6 +124,7 @@ class ProximityInfo { int getStartIndexFromCoordinates(const int x, const int y) const; void initializeCodeToKeyIndex(); void initializeG(); float calculateNormalizedSquaredDistance(const int keyIndex, const int inputIndex) const; float calculateSquaredDistanceFromSweetSpotCenter( const int keyIndex, const int inputIndex) const; Loading @@ -123,6 +135,7 @@ class ProximityInfo { const int KEYBOARD_HEIGHT; const int GRID_WIDTH; const int GRID_HEIGHT; const int MOST_COMMON_KEY_WIDTH; const int MOST_COMMON_KEY_WIDTH_SQUARE; const int CELL_WIDTH; const int CELL_HEIGHT; Loading @@ -139,6 +152,11 @@ class ProximityInfo { float mSweetSpotCenterYs[MAX_KEY_COUNT_IN_A_KEYBOARD]; float mSweetSpotRadii[MAX_KEY_COUNT_IN_A_KEYBOARD]; int mCodeToKeyIndex[MAX_CHAR_CODE + 1]; int mKeyToCodeIndexG[MAX_KEY_COUNT_IN_A_KEYBOARD]; int mCenterXsG[MAX_KEY_COUNT_IN_A_KEYBOARD]; int mCenterYsG[MAX_KEY_COUNT_IN_A_KEYBOARD]; int mKeyKeyDistancesG[MAX_KEY_COUNT_IN_A_KEYBOARD][MAX_KEY_COUNT_IN_A_KEYBOARD]; // TODO: move to correction.h }; } // namespace latinime Loading Loading
native/jni/src/geometry_utils.h 0 → 100644 +101 −0 Original line number Diff line number Diff line /* * Copyright (C) 2012 The Android Open Source Project * * 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. */ #ifndef LATINIME_INCREMENTAL_GEOMETRY_UTILS_H #define LATINIME_INCREMENTAL_GEOMETRY_UTILS_H #include <cmath> #define MAX_DISTANCE 10000000 #define KEY_NUM 27 #define SPACE_KEY 26 #define MAX_PATHS 2 #define DEBUG_DECODER false namespace latinime { static inline float sqr(float x) { return x * x; } static inline float getNormalizedSqrDistance(int x1, int y1, int x2, int y2, int scale) { return sqr((x1 - x2) * 1.0 / scale) + sqr((y1 - y2) * 1.0 / scale); } static inline int getDistance(int x1, int y1, int x2, int y2) { return (int) sqrt(sqr(x2 - x1) + sqr(y2 - y1)); } static inline float getDistanceSq(float x1, float y1, float x2, float y2) { return sqr(x2 - x1) + sqr(y2 - y1); } static inline float getAngle(int x1, int y1, int x2, int y2) { float dx = x1 - x2; float dy = y1 - y2; if (dx == 0 && dy == 0) return 0; return atan2(dy, dx); } static inline float angleDiff(float a1, float a2) { float diff = a1 - a2; if (diff < 0) { diff = -diff; } if (diff > M_PI) { return 2 * M_PI - diff; } return diff; } //static float pointToLineDistanceSq(float x, float y, float x1, float y1, float x2, float y2) { // float A = x - x1; // float B = y - y1; // float C = x2 - x1; // float D = y2 - y1; // return abs(A * D - C * B) / sqrt(C * C + D * D); //} static inline float pointToLineSegDistanceSq( float x, float y, float x1, float y1, float x2, float y2) { float ray1x = x - x1; float ray1y = y - y1; float ray2x = x2 - x1; float ray2y = y2 - y1; float dotProduct = ray1x * ray2x + ray1y * ray2y; float lineLengthSq = ray2x * ray2x + ray2y * ray2y; float projectionLengthSq = dotProduct / lineLengthSq; float projectionX, projectionY; if (projectionLengthSq < 0) { projectionX = x1; projectionY = y1; } else if (projectionLengthSq > 1) { projectionX = x2; projectionY = y2; } else { projectionX = x1 + projectionLengthSq * ray2x; projectionY = y1 + projectionLengthSq * ray2y; } float dist = getDistanceSq(x, y, projectionX, projectionY); return dist; } } // namespace latinime #endif // LATINIME_INCREMENTAL_GEOMETRY_UTILS_H
native/jni/src/proximity_info.cpp +64 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ #include "additional_proximity_chars.h" #include "char_utils.h" #include "defines.h" #include "geometry_utils.h" #include "jni.h" #include "proximity_info.h" Loading Loading @@ -55,6 +56,7 @@ ProximityInfo::ProximityInfo(JNIEnv *env, const jstring localeJStr, const int ma const jfloatArray sweetSpotRadii) : MAX_PROXIMITY_CHARS_SIZE(maxProximityCharsSize), KEYBOARD_WIDTH(keyboardWidth), KEYBOARD_HEIGHT(keyboardHeight), GRID_WIDTH(gridWidth), GRID_HEIGHT(gridHeight), MOST_COMMON_KEY_WIDTH(mostCommonKeyWidth), MOST_COMMON_KEY_WIDTH_SQUARE(mostCommonKeyWidth * mostCommonKeyWidth), CELL_WIDTH((keyboardWidth + gridWidth - 1) / gridWidth), CELL_HEIGHT((keyboardHeight + gridHeight - 1) / gridHeight), Loading Loading @@ -84,6 +86,7 @@ ProximityInfo::ProximityInfo(JNIEnv *env, const jstring localeJStr, const int ma safeGetOrFillZeroFloatArrayRegion(env, sweetSpotCenterYs, KEY_COUNT, mSweetSpotCenterYs); safeGetOrFillZeroFloatArrayRegion(env, sweetSpotRadii, KEY_COUNT, mSweetSpotRadii); initializeCodeToKeyIndex(); initializeG(); } // Build the reversed look up table from the char code to the index in mKeyXCoordinates, Loading Loading @@ -222,6 +225,67 @@ int ProximityInfo::getKeyIndex(const int c) const { return mCodeToKeyIndex[baseLowerC]; } int ProximityInfo::getKeyCode(const int keyIndex) const { if (keyIndex < 0 || keyIndex >= KEY_COUNT) { return NOT_AN_INDEX; } return mKeyToCodeIndexG[keyIndex]; } void ProximityInfo::initializeG() { for (int i = 0; i < KEY_COUNT; ++i) { const int code = mKeyCharCodes[i]; const int lowerCode = toBaseLowerCase(code); mCenterXsG[i] = mKeyXCoordinates[i] + mKeyWidths[i] / 2; mCenterYsG[i] = mKeyYCoordinates[i] + mKeyHeights[i] / 2; if (code != lowerCode && lowerCode >= 0 && lowerCode <= MAX_CHAR_CODE) { mCodeToKeyIndex[lowerCode] = i; mKeyToCodeIndexG[i] = lowerCode; } else { mKeyToCodeIndexG[i] = code; } } for (int i = 0; i < KEY_COUNT; i++) { mKeyKeyDistancesG[i][i] = 0; for (int j = i + 1; j < KEY_COUNT; j++) { mKeyKeyDistancesG[i][j] = getDistance( mCenterXsG[i], mCenterYsG[i], mCenterXsG[j], mCenterYsG[j]); mKeyKeyDistancesG[j][i] = mKeyKeyDistancesG[i][j]; } } } float ProximityInfo::getKeyCenterXOfCharG(int charCode) const { return getKeyCenterXOfIdG(getKeyIndex(charCode)); } float ProximityInfo::getKeyCenterYOfCharG(int charCode) const { return getKeyCenterYOfIdG(getKeyIndex(charCode)); } float ProximityInfo::getKeyCenterXOfIdG(int keyId) const { if (keyId >= 0) { return mCenterXsG[keyId]; } return 0; } float ProximityInfo::getKeyCenterYOfIdG(int keyId) const { if (keyId >= 0) { return mCenterYsG[keyId]; } return 0; } int ProximityInfo::getKeyKeyDistanceG(int key0, int key1) const { const int keyId0 = getKeyIndex(key0); const int keyId1 = getKeyIndex(key1); if (keyId0 >= 0 && keyId1 >= 0) { return mKeyKeyDistancesG[keyId0][keyId1]; } return 0; } // TODO: [Staging] Optimize void ProximityInfo::getCenters(int *centerXs, int *centerYs, int *codeToKeyIndex, int *keyToCodeIndex, int *keyCount, int *keyWidth) const { Loading
native/jni/src/proximity_info.h +18 −0 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ class ProximityInfo { return left < right && top < bottom && x >= left && x < right && y >= top && y < bottom; } int getKeyIndex(const int c) const; int getKeyCode(const int keyIndex) const; bool hasSweetSpotData(const int keyIndex) const { // When there are no calibration data for a key, // the radius of the key is assigned to zero. Loading @@ -70,6 +71,10 @@ class ProximityInfo { return HAS_TOUCH_POSITION_CORRECTION_DATA; } int getMostCommonKeyWidth() const { return MOST_COMMON_KEY_WIDTH; } int getMostCommonKeyWidthSquare() const { return MOST_COMMON_KEY_WIDTH_SQUARE; } Loading Loading @@ -98,6 +103,12 @@ class ProximityInfo { return GRID_HEIGHT; } float getKeyCenterXOfCharG(int charCode) const; float getKeyCenterYOfCharG(int charCode) const; float getKeyCenterXOfIdG(int keyId) const; float getKeyCenterYOfIdG(int keyId) const; int getKeyKeyDistanceG(int key0, int key1) const; // Returns the keyboard key-center information. void getCenters(int *centersX, int *centersY, int *codeToKeyIndex, int *keyToCodeIndex, int *keyCount, int *keyWidth) const; Loading @@ -113,6 +124,7 @@ class ProximityInfo { int getStartIndexFromCoordinates(const int x, const int y) const; void initializeCodeToKeyIndex(); void initializeG(); float calculateNormalizedSquaredDistance(const int keyIndex, const int inputIndex) const; float calculateSquaredDistanceFromSweetSpotCenter( const int keyIndex, const int inputIndex) const; Loading @@ -123,6 +135,7 @@ class ProximityInfo { const int KEYBOARD_HEIGHT; const int GRID_WIDTH; const int GRID_HEIGHT; const int MOST_COMMON_KEY_WIDTH; const int MOST_COMMON_KEY_WIDTH_SQUARE; const int CELL_WIDTH; const int CELL_HEIGHT; Loading @@ -139,6 +152,11 @@ class ProximityInfo { float mSweetSpotCenterYs[MAX_KEY_COUNT_IN_A_KEYBOARD]; float mSweetSpotRadii[MAX_KEY_COUNT_IN_A_KEYBOARD]; int mCodeToKeyIndex[MAX_CHAR_CODE + 1]; int mKeyToCodeIndexG[MAX_KEY_COUNT_IN_A_KEYBOARD]; int mCenterXsG[MAX_KEY_COUNT_IN_A_KEYBOARD]; int mCenterYsG[MAX_KEY_COUNT_IN_A_KEYBOARD]; int mKeyKeyDistancesG[MAX_KEY_COUNT_IN_A_KEYBOARD][MAX_KEY_COUNT_IN_A_KEYBOARD]; // TODO: move to correction.h }; } // namespace latinime Loading