proximity_info_state.cpp revision d9c10b19793b011f862e3dd31883f746044431d7
13e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka/* 23e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka * Copyright (C) 2012 The Android Open Source Project 33e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka * 43e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka * Licensed under the Apache License, Version 2.0 (the "License"); 53e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka * you may not use this file except in compliance with the License. 63e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka * You may obtain a copy of the License at 73e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka * 83e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka * http://www.apache.org/licenses/LICENSE-2.0 93e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka * 103e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka * Unless required by applicable law or agreed to in writing, software 113e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka * distributed under the License is distributed on an "AS IS" BASIS, 123e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka * See the License for the specific language governing permissions and 143e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka * limitations under the License. 153e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka */ 163e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka 1777e8e81ad95cfc1eb8f8407fc872674b8d08bbe9Ken Wakasa#include <cstring> // for memset() 183e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka#include <stdint.h> 193e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka 203e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka#define LOG_TAG "LatinIME: proximity_info_state.cpp" 213e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka 223e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka#include "defines.h" 23687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka#include "geometry_utils.h" 243e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka#include "proximity_info.h" 253e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka#include "proximity_info_state.h" 263e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka 273e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataokanamespace latinime { 28233aad5e5c7567a97af30f38f50a65365f729dfeSatoshi Kataokavoid ProximityInfoState::initInputParams(const int pointerId, const float maxPointToKeyLength, 2908f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka const ProximityInfo *proximityInfo, const int32_t *const inputCodes, const int inputSize, 30687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka const int *const xCoordinates, const int *const yCoordinates, const int *const times, 31687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka const int *const pointerIds, const bool isGeometric) { 324a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka mProximityInfo = proximityInfo; 334a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka mHasTouchPositionCorrectionData = proximityInfo->hasTouchPositionCorrectionData(); 344a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka mMostCommonKeyWidthSquare = proximityInfo->getMostCommonKeyWidthSquare(); 354a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka mLocaleStr = proximityInfo->getLocaleStr(); 364a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka mKeyCount = proximityInfo->getKeyCount(); 374a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka mCellHeight = proximityInfo->getCellHeight(); 384a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka mCellWidth = proximityInfo->getCellWidth(); 394a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka mGridHeight = proximityInfo->getGridWidth(); 404a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka mGridWidth = proximityInfo->getGridHeight(); 413e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka 4208f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka memset(mInputCodes, 0, sizeof(mInputCodes)); 433e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka 4408f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka if (!isGeometric && pointerId == 0) { 4508f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka // Initialize 4608f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka // - mInputCodes 4708f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka // - mNormalizedSquaredDistances 4808f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka // TODO: Merge 49687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka for (int i = 0; i < inputSize; ++i) { 5008f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka const int32_t primaryKey = inputCodes[i]; 5108f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka const int x = xCoordinates[i]; 5208f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka const int y = yCoordinates[i]; 5308f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka int *proximities = &mInputCodes[i * MAX_PROXIMITY_CHARS_SIZE_INTERNAL]; 5408f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka mProximityInfo->calculateNearbyKeyCodes(x, y, primaryKey, proximities); 5508f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka } 5608f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka 5708f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka if (DEBUG_PROXIMITY_CHARS) { 5808f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka for (int i = 0; i < inputSize; ++i) { 5908f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka AKLOGI("---"); 6008f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka for (int j = 0; j < MAX_PROXIMITY_CHARS_SIZE_INTERNAL; ++j) { 6108f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka int icc = mInputCodes[i * MAX_PROXIMITY_CHARS_SIZE_INTERNAL + j]; 6208f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka int icfjc = inputCodes[i * MAX_PROXIMITY_CHARS_SIZE_INTERNAL + j]; 6308f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka icc += 0; 6408f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka icfjc += 0; 6508f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka AKLOGI("--- (%d)%c,%c", i, icc, icfjc); AKLOGI("--- A<%d>,B<%d>", icc, icfjc); 6608f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka } 673e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka } 683e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka } 693e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka } 70687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka 71687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka /////////////////////// 72687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka // Setup touch points 7308f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka mMaxPointToKeyLength = maxPointToKeyLength; 74687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka mInputXs.clear(); 75687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka mInputYs.clear(); 76687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka mTimes.clear(); 77687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka mLengthCache.clear(); 78687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka mDistanceCache.clear(); 79687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka mInputSize = 0; 80d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi 81687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka if (xCoordinates && yCoordinates) { 82687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka const bool proximityOnly = !isGeometric && (xCoordinates[0] < 0 || yCoordinates[0] < 0); 83d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi int lastInputIndex = 0; 84d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi for (int i = 0; i < inputSize; ++i) { 85d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi const int pid = pointerIds ? pointerIds[i] : 0; 86d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi if (pointerId == pid) { 87d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi lastInputIndex = i; 88d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi } 89d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi } 90d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi // Working space to save near keys distances for current, prev and prevprev input point. 91d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi NearKeysDistanceMap nearKeysDistances[3]; 92d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi // These pointers are swapped for each inputs points. 93d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi NearKeysDistanceMap *currentNearKeysDistances = &nearKeysDistances[0]; 94d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi NearKeysDistanceMap *prevNearKeysDistances = &nearKeysDistances[1]; 95d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi NearKeysDistanceMap *prevPrevNearKeysDistances = &nearKeysDistances[2]; 96d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi 97687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka for (int i = 0; i < inputSize; ++i) { 98687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka // Assuming pointerId == 0 if pointerIds is null. 99687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka const int pid = pointerIds ? pointerIds[i] : 0; 100687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka if (pointerId == pid) { 101687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka const int c = isGeometric ? NOT_A_COORDINATE : getPrimaryCharAt(i); 102687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka const int x = proximityOnly ? NOT_A_COORDINATE : xCoordinates[i]; 103687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka const int y = proximityOnly ? NOT_A_COORDINATE : yCoordinates[i]; 104687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka const int time = times ? times[i] : -1; 105d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi if (pushTouchPoint(c, x, y, time, isGeometric, i == lastInputIndex, 106d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi currentNearKeysDistances, prevNearKeysDistances, 107d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi prevPrevNearKeysDistances)) { 108d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi // Previous point information was popped. 109d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi NearKeysDistanceMap *tmp = prevNearKeysDistances; 110d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi prevNearKeysDistances = currentNearKeysDistances; 111d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi currentNearKeysDistances = tmp; 112d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi } else { 113d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi NearKeysDistanceMap *tmp = prevPrevNearKeysDistances; 114d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi prevPrevNearKeysDistances = prevNearKeysDistances; 115d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi prevNearKeysDistances = currentNearKeysDistances; 116d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi currentNearKeysDistances = tmp; 11737b153e205c9672b299b47e97921fee2462a78bbSatoshi Kataoka } 118687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka } 119687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka } 120d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi mInputSize = mInputXs.size(); 1213e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka } 122687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka 123687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka if (mInputSize > 0) { 124687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka const int keyCount = mProximityInfo->getKeyCount(); 125687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka mDistanceCache.resize(mInputSize * keyCount); 126687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka for (int i = 0; i < mInputSize; ++i) { 127687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka for (int k = 0; k < keyCount; ++k) { 128687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka const int index = i * keyCount + k; 129687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka const int x = mInputXs[i]; 130687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka const int y = mInputYs[i]; 131687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka mDistanceCache[index] = 132687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka mProximityInfo->getNormalizedSquaredDistanceFromCenterFloat(k, x, y); 133687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka } 134687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka } 135687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka } 13608f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka 137687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka // end 138687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka /////////////////////// 139687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka 14008f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka memset(mNormalizedSquaredDistances, NOT_A_DISTANCE, sizeof(mNormalizedSquaredDistances)); 14108f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka memset(mPrimaryInputWord, 0, sizeof(mPrimaryInputWord)); 142233aad5e5c7567a97af30f38f50a65365f729dfeSatoshi Kataoka mTouchPositionCorrectionEnabled = mInputSize > 0 && mHasTouchPositionCorrectionData 143233aad5e5c7567a97af30f38f50a65365f729dfeSatoshi Kataoka && xCoordinates && yCoordinates && !isGeometric; 14408f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka if (!isGeometric && pointerId == 0) { 14508f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka for (int i = 0; i < inputSize; ++i) { 14608f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka mPrimaryInputWord[i] = getPrimaryCharAt(i); 1473e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka } 14808f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka 14908f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka for (int i = 0; i < mInputSize && mTouchPositionCorrectionEnabled; ++i) { 15008f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka const int *proximityChars = getProximityCharsAt(i); 15108f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka const int primaryKey = proximityChars[0]; 15208f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka const int x = xCoordinates[i]; 15308f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka const int y = yCoordinates[i]; 1543e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka if (DEBUG_PROXIMITY_CHARS) { 15508f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka int a = x + y + primaryKey; 15608f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka a += 0; 15708f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka AKLOGI("--- Primary = %c, x = %d, y = %d", primaryKey, x, y); 15808f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka } 15908f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka for (int j = 0; j < MAX_PROXIMITY_CHARS_SIZE_INTERNAL && proximityChars[j] > 0; ++j) { 16008f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka const int currentChar = proximityChars[j]; 16108f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka const float squaredDistance = 16208f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka hasInputCoordinates() ? calculateNormalizedSquaredDistance( 16308f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka mProximityInfo->getKeyIndex(currentChar), i) : 16408f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka NOT_A_DISTANCE_FLOAT; 16508f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka if (squaredDistance >= 0.0f) { 16608f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka mNormalizedSquaredDistances[i * MAX_PROXIMITY_CHARS_SIZE_INTERNAL + j] = 16708f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka (int) (squaredDistance * NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR); 16808f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka } else { 16908f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka mNormalizedSquaredDistances[i * MAX_PROXIMITY_CHARS_SIZE_INTERNAL + j] = 17008f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka (j == 0) ? EQUIVALENT_CHAR_WITHOUT_DISTANCE_INFO : 17108f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka PROXIMITY_CHAR_WITHOUT_DISTANCE_INFO; 17208f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka } 17308f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka if (DEBUG_PROXIMITY_CHARS) { 17408f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka AKLOGI("--- Proximity (%d) = %c", j, currentChar); 17508f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka } 1763e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka } 1773e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka } 1783e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka } 1793e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka} 1804a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka 181d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi// Calculating point to key distance for all near keys and returning the distance between 182d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi// the given point and the nearest key position. 183d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagifloat ProximityInfoState::updateNearKeysDistances(const int x, const int y, 184d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi NearKeysDistanceMap *const currentNearKeysDistances) { 185d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi static const float NEAR_KEY_THRESHOLD = 10.0f; 186d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi 187d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi currentNearKeysDistances->clear(); 188d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi const int keyCount = mProximityInfo->getKeyCount(); 189d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi float nearestKeyDistance = mMaxPointToKeyLength; 190d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi for (int k = 0; k < keyCount; ++k) { 191d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi const float dist = mProximityInfo->getNormalizedSquaredDistanceFromCenterFloat(k, x, y); 192d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi if (dist < NEAR_KEY_THRESHOLD) { 193d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi currentNearKeysDistances->insert(std::pair<int, float>(k, dist)); 194687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka } 195d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi if (nearestKeyDistance > dist) { 196d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi nearestKeyDistance = dist; 197d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi } 198d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi } 199d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi return nearestKeyDistance; 200d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi} 201d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi 202d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi// Check if previous point is at local minimum position to near keys. 203d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagibool ProximityInfoState::isPrevLocalMin(const NearKeysDistanceMap *const currentNearKeysDistances, 204d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi const NearKeysDistanceMap *const prevNearKeysDistances, 205d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi const NearKeysDistanceMap *const prevPrevNearKeysDistances) const { 206d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi static const float MARGIN = 0.5f; 207d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi 208d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi for (NearKeysDistanceMap::const_iterator it = prevNearKeysDistances->begin(); 209d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi it != prevNearKeysDistances->end(); ++it) { 210d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi NearKeysDistanceMap::const_iterator itPP = prevPrevNearKeysDistances->find(it->first); 211d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi NearKeysDistanceMap::const_iterator itC = currentNearKeysDistances->find(it->first); 212d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi if ((itPP == prevPrevNearKeysDistances->end() || itPP->second > it->second + MARGIN) 213d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi && (itC == currentNearKeysDistances->end() || itC->second > it->second + MARGIN)) { 214d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi return true; 215d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi } 216d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi } 217d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi return false; 218d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi} 219d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi 220d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi// Calculating a point score that indicates usefulness of the point. 221d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagifloat ProximityInfoState::getPointScore( 222d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi const int x, const int y, const int time, const bool lastPoint, const float nearest, 223d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi const NearKeysDistanceMap *const currentNearKeysDistances, 224d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi const NearKeysDistanceMap *const prevNearKeysDistances, 225d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi const NearKeysDistanceMap *const prevPrevNearKeysDistances) const { 226d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi static const float BASE_SAMPLE_RATE_SCALE = 0.1f; 227d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi static const float SAVE_DISTANCE_SCALE = 12.0f; 228d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi static const float SAVE_DISTANCE_SCORE = 2.0f; 229d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi static const float SKIP_DISTANCE_SCALE = 1.5f; 230d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi static const float SKIP_DISTANCE_SCORE = -1.0f; 231d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi static const float CHECK_LOCALMIN_DISTANCE_THRESHOLD_SCALE = 2.5f; 232d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi static const float CHECK_LOCALMIN_DISTANCE_SCORE = -1.0f; 233d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi static const float STRAIGHT_ANGLE_THRESHOLD = M_PI_F / 32.0f; 234d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi static const float STRAIGHT_SKIP_DISTANCE_THRESHOLD_SCALE = 4.0f; 235d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi static const float STRAIGHT_SKIP_NEAREST_DISTANCE_THRESHOLD = 0.5f; 236d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi static const float STRAIGHT_SKIP_SCORE = -1.0f; 237d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi 238d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi const std::size_t size = mInputXs.size(); 239d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi if (size <= 1) { 240d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi return 0; 241687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka } 242d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi const float baseSampleRate = mProximityInfo->getMostCommonKeyWidth() * BASE_SAMPLE_RATE_SCALE; 243d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi const float distNext = getDistanceFloat(x, y, mInputXs.back(), mInputYs.back()); 244d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi const float distPrev = getDistanceFloat(mInputXs.back(), mInputYs.back(), 245d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi mInputXs[size - 2], mInputYs[size - 2]); 246d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi float score = 0.0f; 247d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi 248d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi // Sum of distances 249d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi if (distPrev + distNext > baseSampleRate * SAVE_DISTANCE_SCALE) { 250d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi score += SAVE_DISTANCE_SCORE; 251d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi } 252d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi // Distance 253d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi if (distPrev < baseSampleRate * SKIP_DISTANCE_SCALE) { 254d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi score += SKIP_DISTANCE_SCORE; 255d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi } 256d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi // Location 257d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi if (!isPrevLocalMin(currentNearKeysDistances, currentNearKeysDistances, 258d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi prevPrevNearKeysDistances)) { 259d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi if (distPrev < baseSampleRate * CHECK_LOCALMIN_DISTANCE_THRESHOLD_SCALE) { 260d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi score += CHECK_LOCALMIN_DISTANCE_SCORE; 261d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi } 262d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi } 263d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi // Angle 264d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi const float angle1 = getAngle(x, y, mInputXs.back(), mInputYs.back()); 265d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi const float angle2 = getAngle(mInputXs.back(), mInputYs.back(), 266d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi mInputXs[size - 2], mInputYs[size - 2]); 267d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi if (getAngleDiff(angle1, angle2) < STRAIGHT_ANGLE_THRESHOLD) { 268d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi if (nearest > STRAIGHT_SKIP_NEAREST_DISTANCE_THRESHOLD 269d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi && distPrev < baseSampleRate * STRAIGHT_SKIP_DISTANCE_THRESHOLD_SCALE) { 270d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi score += STRAIGHT_SKIP_SCORE; 271d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi } 272d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi } 273d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi return score; 274d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi} 275d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi 276d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi// Sampling touch point and pushing information to vectors. 277d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi// Returning if previous point is popped or not. 278d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagibool ProximityInfoState::pushTouchPoint(const int nodeChar, int x, int y, const int time, 279d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi const bool sample, const bool isLastPoint, 280d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi NearKeysDistanceMap *const currentNearKeysDistances, 281d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi const NearKeysDistanceMap *const prevNearKeysDistances, 282d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi const NearKeysDistanceMap *const prevPrevNearKeysDistances) { 283d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi static const float LAST_POINT_SKIP_DISTANCE_SCALE = 0.25f; 284d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi 285d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi uint32_t size = mInputXs.size(); 286d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi bool popped = false; 287d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi if (nodeChar < 0 && sample) { 288d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi const float nearest = updateNearKeysDistances(x, y, currentNearKeysDistances); 289d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi const float score = getPointScore(x, y, time, isLastPoint, nearest, 290d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi currentNearKeysDistances, prevNearKeysDistances, prevPrevNearKeysDistances); 291d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi if (score < 0) { 292d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi // Pop previous point because it would be useless. 293d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi mInputXs.pop_back(); 294d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi mInputYs.pop_back(); 295d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi mTimes.pop_back(); 296d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi mLengthCache.pop_back(); 297d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi size = mInputXs.size(); 298d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi popped = true; 299d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi } else { 300d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi popped = false; 301d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi } 302d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi // Check if the last point should be skipped. 303d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi if (isLastPoint) { 304d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi if (size > 0 && getDistanceFloat(x, y, mInputXs.back(), mInputYs.back()) 305d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi < mProximityInfo->getMostCommonKeyWidth() * LAST_POINT_SKIP_DISTANCE_SCALE) { 306d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi return popped; 307d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi } else if (size > 1) { 308d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi int minChar = 0; 309d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi float minDist = mMaxPointToKeyLength; 310d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi for (NearKeysDistanceMap::const_iterator it = currentNearKeysDistances->begin(); 311d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi it != currentNearKeysDistances->end(); ++it) { 312d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi if(minDist > it->second){ 313d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi minChar = it->first; 314d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi minDist = it->second; 315d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi } 316d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi } 317d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi NearKeysDistanceMap::const_iterator itPP = 318d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi prevNearKeysDistances->find(minChar); 319d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi if (itPP != prevNearKeysDistances->end() && minDist > itPP->second) { 320d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi return popped; 321d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi } 322d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi } 323d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi } 324d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi } 325d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi 326687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka if (nodeChar >= 0 && (x < 0 || y < 0)) { 327687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka const int keyId = mProximityInfo->getKeyIndex(nodeChar); 328687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka if (keyId >= 0) { 329687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka x = mProximityInfo->getKeyCenterXOfIdG(keyId); 330687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka y = mProximityInfo->getKeyCenterYOfIdG(keyId); 331687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka } 332687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka } 333d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi 334d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi // Pushing point information. 335d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi if (size > 0) { 336d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi mLengthCache.push_back( 337d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi mLengthCache.back() + getDistanceInt(x, y, mInputXs.back(), mInputYs.back())); 338d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi } else { 339d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi mLengthCache.push_back(0); 340d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi } 341687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka mInputXs.push_back(x); 342687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka mInputYs.push_back(y); 343687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka mTimes.push_back(time); 344d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi return popped; 345687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka} 346687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka 3474a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataokafloat ProximityInfoState::calculateNormalizedSquaredDistance( 3484a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka const int keyIndex, const int inputIndex) const { 3494a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka if (keyIndex == NOT_AN_INDEX) { 3504a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka return NOT_A_DISTANCE_FLOAT; 3514a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka } 3524a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka if (!mProximityInfo->hasSweetSpotData(keyIndex)) { 3534a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka return NOT_A_DISTANCE_FLOAT; 3544a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka } 355687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka if (NOT_A_COORDINATE == mInputXs[inputIndex]) { 3564a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka return NOT_A_DISTANCE_FLOAT; 3574a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka } 3584a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka const float squaredDistance = calculateSquaredDistanceFromSweetSpotCenter( 3594a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka keyIndex, inputIndex); 3604a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka const float squaredRadius = square(mProximityInfo->getSweetSpotRadiiAt(keyIndex)); 3614a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka return squaredDistance / squaredRadius; 3624a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka} 3634a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka 364687a244703a02323ebd64433cbaead5def499861Satoshi Kataokaint ProximityInfoState::getDuration(const int index) const { 36537b153e205c9672b299b47e97921fee2462a78bbSatoshi Kataoka if (mInputSize > 0 && index > 0 && index < static_cast<int>(mInputSize) - 1) { 36637b153e205c9672b299b47e97921fee2462a78bbSatoshi Kataoka return mTimes[index + 1] - mTimes[index - 1]; 367687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka } 36837b153e205c9672b299b47e97921fee2462a78bbSatoshi Kataoka return 0; 369687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka} 370687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka 371687a244703a02323ebd64433cbaead5def499861Satoshi Kataokafloat ProximityInfoState::getPointToKeyLength(int inputIndex, int charCode, float scale) { 372687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka const int keyId = mProximityInfo->getKeyIndex(charCode); 373687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka if (keyId >= 0) { 374687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka const int index = inputIndex * mProximityInfo->getKeyCount() + keyId; 375687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka return min(mDistanceCache[index] * scale, mMaxPointToKeyLength); 376687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka } 377687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka return 0; 378687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka} 379687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka 380687a244703a02323ebd64433cbaead5def499861Satoshi Kataokaint ProximityInfoState::getKeyKeyDistance(int key0, int key1) { 381687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka return mProximityInfo->getKeyKeyDistanceG(key0, key1); 382687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka} 383687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka 384687a244703a02323ebd64433cbaead5def499861Satoshi Kataokaint ProximityInfoState::getSpaceY() { 385687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka const int keyId = mProximityInfo->getKeyIndex(' '); 386687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka return mProximityInfo->getKeyCenterYOfIdG(keyId); 387687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka} 388687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka 3894a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataokafloat ProximityInfoState::calculateSquaredDistanceFromSweetSpotCenter( 3904a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka const int keyIndex, const int inputIndex) const { 3914a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka const float sweetSpotCenterX = mProximityInfo->getSweetSpotCenterXAt(keyIndex); 3924a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka const float sweetSpotCenterY = mProximityInfo->getSweetSpotCenterYAt(keyIndex); 393687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka const float inputX = static_cast<float>(mInputXs[inputIndex]); 394687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka const float inputY = static_cast<float>(mInputYs[inputIndex]); 3954a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka return square(inputX - sweetSpotCenterX) + square(inputY - sweetSpotCenterY); 3964a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka} 3973e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka} // namespace latinime 398