proximity_info_state.cpp revision d4828d5053ac30476b884c177235be0cac982c92
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() 18806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi#include <sstream> // for debug prints 193e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka 203e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka#define LOG_TAG "LatinIME: proximity_info_state.cpp" 213e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka 223e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka#include "defines.h" 236cee61deebd0ca2b85054ccc239523d1e5fdfab1Ken Wakasa#include "geometry_utils.h" 243e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka#include "proximity_info.h" 253e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka#include "proximity_info_state.h" 2647cc52415e3affb83eb4369190425b2a17b956c5Satoshi Kataoka#include "proximity_info_state_utils.h" 273e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka 283e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataokanamespace latinime { 29764dd712032d7b8012797b1116b523bef7b907f3Ken Wakasa 30764dd712032d7b8012797b1116b523bef7b907f3Ken Wakasaconst int ProximityInfoState::NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR_LOG_2 = 10; 31764dd712032d7b8012797b1116b523bef7b907f3Ken Wakasaconst int ProximityInfoState::NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR = 32764dd712032d7b8012797b1116b523bef7b907f3Ken Wakasa 1 << NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR_LOG_2; 33764dd712032d7b8012797b1116b523bef7b907f3Ken Wakasaconst float ProximityInfoState::NOT_A_DISTANCE_FLOAT = -1.0f; 34764dd712032d7b8012797b1116b523bef7b907f3Ken Wakasaconst int ProximityInfoState::NOT_A_CODE = -1; 35764dd712032d7b8012797b1116b523bef7b907f3Ken Wakasa 36233aad5e5c7567a97af30f38f50a65365f729dfeSatoshi Kataokavoid ProximityInfoState::initInputParams(const int pointerId, const float maxPointToKeyLength, 371e61493c50082264caaef862df02b1ccc84dc396Ken Wakasa const ProximityInfo *proximityInfo, const int *const inputCodes, const int inputSize, 38687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka const int *const xCoordinates, const int *const yCoordinates, const int *const times, 39687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka const int *const pointerIds, const bool isGeometric) { 40fe4f1ce26ca41ef51b5245d70e93b502f76262a5Satoshi Kataoka mIsContinuationPossible = checkAndReturnIsContinuationPossible( 41fe4f1ce26ca41ef51b5245d70e93b502f76262a5Satoshi Kataoka inputSize, xCoordinates, yCoordinates, times, isGeometric); 42096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi 434a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka mProximityInfo = proximityInfo; 444a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka mHasTouchPositionCorrectionData = proximityInfo->hasTouchPositionCorrectionData(); 454a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka mMostCommonKeyWidthSquare = proximityInfo->getMostCommonKeyWidthSquare(); 464a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka mKeyCount = proximityInfo->getKeyCount(); 474a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka mCellHeight = proximityInfo->getCellHeight(); 484a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka mCellWidth = proximityInfo->getCellWidth(); 494a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka mGridHeight = proximityInfo->getGridWidth(); 504a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka mGridWidth = proximityInfo->getGridHeight(); 513e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka 52bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka memset(mInputProximities, 0, sizeof(mInputProximities)); 533e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka 5408f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka if (!isGeometric && pointerId == 0) { 55bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka mProximityInfo->initializeProximities(inputCodes, xCoordinates, yCoordinates, 56bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka inputSize, mInputProximities); 573e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka } 58687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka 59687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka /////////////////////// 60687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka // Setup touch points 61096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi int pushTouchPointStartIndex = 0; 62096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi int lastSavedInputSize = 0; 6308f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka mMaxPointToKeyLength = maxPointToKeyLength; 64096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi if (mIsContinuationPossible && mInputIndice.size() > 1) { 65096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi // Just update difference. 66096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi // Two points prior is never skipped. Thus, we pop 2 input point data here. 67096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi pushTouchPointStartIndex = mInputIndice[mInputIndice.size() - 2]; 68096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi popInputData(); 69096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi popInputData(); 70feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka lastSavedInputSize = mSampledInputXs.size(); 71096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi } else { 72096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi // Clear all data. 73feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka mSampledInputXs.clear(); 74feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka mSampledInputYs.clear(); 75096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi mTimes.clear(); 76096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi mInputIndice.clear(); 77096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi mLengthCache.clear(); 78a9763f93d76f97b9c6ed7dd1369a4d8cb016f06fSatoshi Kataoka mDistanceCache_G.clear(); 79096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi mNearKeysVector.clear(); 80ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi mSearchKeysVector.clear(); 819af533538ea749d7c930bb3125fa4d3e4feb8478Satoshi Kataoka mSpeedRates.clear(); 826ae8dd4343445d2df4444388b605d2aa930fa2a0Satoshi Kataoka mBeelineSpeedPercentiles.clear(); 83806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi mCharProbabilities.clear(); 841e06a4d8e9e71188ed685282155ea52a48ddc050Keisuke Kuroyanagi mDirections.clear(); 85096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi } 869182daf98c0d1db897e82b77c2196b7f9aad6f01Satoshi Kataoka if (DEBUG_GEO_FULL) { 879182daf98c0d1db897e82b77c2196b7f9aad6f01Satoshi Kataoka AKLOGI("Init ProximityInfoState: reused points = %d, last input size = %d", 889182daf98c0d1db897e82b77c2196b7f9aad6f01Satoshi Kataoka pushTouchPointStartIndex, lastSavedInputSize); 899182daf98c0d1db897e82b77c2196b7f9aad6f01Satoshi Kataoka } 90feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka mSampledInputSize = 0; 91d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi 92687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka if (xCoordinates && yCoordinates) { 9347cc52415e3affb83eb4369190425b2a17b956c5Satoshi Kataoka mSampledInputSize = ProximityInfoStateUtils::updateTouchPoints( 9447cc52415e3affb83eb4369190425b2a17b956c5Satoshi Kataoka mProximityInfo->getMostCommonKeyWidth(), mProximityInfo, mMaxPointToKeyLength, 9547cc52415e3affb83eb4369190425b2a17b956c5Satoshi Kataoka mInputProximities, xCoordinates, yCoordinates, times, pointerIds, inputSize, 9647cc52415e3affb83eb4369190425b2a17b956c5Satoshi Kataoka isGeometric, pointerId, pushTouchPointStartIndex, 9747cc52415e3affb83eb4369190425b2a17b956c5Satoshi Kataoka &mSampledInputXs, &mSampledInputYs, &mTimes, &mLengthCache, &mInputIndice); 983e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka } 99687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka 100feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka if (mSampledInputSize > 0 && isGeometric) { 101ee62b78c9675bddaf2437e0cf521f6115e1d9febSatoshi Kataoka mAverageSpeed = ProximityInfoStateUtils::refreshSpeedRates( 102ee62b78c9675bddaf2437e0cf521f6115e1d9febSatoshi Kataoka inputSize, xCoordinates, yCoordinates, times, lastSavedInputSize, 103ee62b78c9675bddaf2437e0cf521f6115e1d9febSatoshi Kataoka mSampledInputSize, &mSampledInputXs, &mSampledInputYs, &mTimes, &mLengthCache, 104ee62b78c9675bddaf2437e0cf521f6115e1d9febSatoshi Kataoka &mInputIndice, &mSpeedRates, &mDirections); 105ee62b78c9675bddaf2437e0cf521f6115e1d9febSatoshi Kataoka ProximityInfoStateUtils::refreshBeelineSpeedRates( 106ee62b78c9675bddaf2437e0cf521f6115e1d9febSatoshi Kataoka mProximityInfo->getMostCommonKeyWidth(), mAverageSpeed, inputSize, 107ee62b78c9675bddaf2437e0cf521f6115e1d9febSatoshi Kataoka xCoordinates, yCoordinates, times, mSampledInputSize, &mSampledInputXs, 108ee62b78c9675bddaf2437e0cf521f6115e1d9febSatoshi Kataoka &mSampledInputYs, &mInputIndice, &mBeelineSpeedPercentiles); 10928661069591fd1d6a8e25981aaade2e5d8b20b9aKeisuke Kuroyanagi } 11028661069591fd1d6a8e25981aaade2e5d8b20b9aKeisuke Kuroyanagi 111ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi if (DEBUG_GEO_FULL) { 112feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka for (int i = 0; i < mSampledInputSize; ++i) { 113feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka AKLOGI("Sampled(%d): x = %d, y = %d, time = %d", i, mSampledInputXs[i], 114feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka mSampledInputYs[i], mTimes[i]); 115ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi } 116ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi } 117ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi 118feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka if (mSampledInputSize > 0) { 119687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka const int keyCount = mProximityInfo->getKeyCount(); 120feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka mNearKeysVector.resize(mSampledInputSize); 121feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka mSearchKeysVector.resize(mSampledInputSize); 122a9763f93d76f97b9c6ed7dd1369a4d8cb016f06fSatoshi Kataoka mDistanceCache_G.resize(mSampledInputSize * keyCount); 123feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka for (int i = lastSavedInputSize; i < mSampledInputSize; ++i) { 12495a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi mNearKeysVector[i].reset(); 125ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi mSearchKeysVector[i].reset(); 12695a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi static const float NEAR_KEY_NORMALIZED_SQUARED_THRESHOLD = 4.0f; 127687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka for (int k = 0; k < keyCount; ++k) { 128687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka const int index = i * keyCount + k; 129feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka const int x = mSampledInputXs[i]; 130feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka const int y = mSampledInputYs[i]; 13195a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi const float normalizedSquaredDistance = 1320edab9d2fcc30667c79aa9221dbb27f042d8b455Satoshi Kataoka mProximityInfo->getNormalizedSquaredDistanceFromCenterFloatG(k, x, y); 133a9763f93d76f97b9c6ed7dd1369a4d8cb016f06fSatoshi Kataoka mDistanceCache_G[index] = normalizedSquaredDistance; 13495a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi if (normalizedSquaredDistance < NEAR_KEY_NORMALIZED_SQUARED_THRESHOLD) { 135ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi mNearKeysVector[i][k] = true; 13695a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi } 13795a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi } 13895a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi } 139ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi if (isGeometric) { 140ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi // updates probabilities of skipping or mapping each key for all points. 141d4828d5053ac30476b884c177235be0cac982c92Satoshi Kataoka ProximityInfoStateUtils::updateAlignPointProbabilities( 142d4828d5053ac30476b884c177235be0cac982c92Satoshi Kataoka mMaxPointToKeyLength, mProximityInfo->getMostCommonKeyWidth(), 143d4828d5053ac30476b884c177235be0cac982c92Satoshi Kataoka keyCount, lastSavedInputSize, mSampledInputSize, &mSampledInputXs, 144d4828d5053ac30476b884c177235be0cac982c92Satoshi Kataoka &mSampledInputYs, &mSpeedRates, &mLengthCache, &mDistanceCache_G, 145d4828d5053ac30476b884c177235be0cac982c92Satoshi Kataoka &mNearKeysVector, &mCharProbabilities); 146ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi 147ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi static const float READ_FORWORD_LENGTH_SCALE = 0.95f; 148ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi const int readForwordLength = static_cast<int>( 149ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi hypotf(mProximityInfo->getKeyboardWidth(), mProximityInfo->getKeyboardHeight()) 150ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi * READ_FORWORD_LENGTH_SCALE); 151feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka for (int i = 0; i < mSampledInputSize; ++i) { 152ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi if (i >= lastSavedInputSize) { 153ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi mSearchKeysVector[i].reset(); 154ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi } 155feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka for (int j = max(i, lastSavedInputSize); j < mSampledInputSize; ++j) { 156ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi if (mLengthCache[j] - mLengthCache[i] >= readForwordLength) { 157ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi break; 158ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi } 159ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi mSearchKeysVector[i] |= mNearKeysVector[j]; 16095a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi } 161687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka } 162687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka } 163687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka } 16408f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka 165806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi if (DEBUG_SAMPLING_POINTS) { 166806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi std::stringstream originalX, originalY, sampledX, sampledY; 167806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi for (int i = 0; i < inputSize; ++i) { 168806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi originalX << xCoordinates[i]; 169806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi originalY << yCoordinates[i]; 170806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi if (i != inputSize - 1) { 171806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi originalX << ";"; 172806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi originalY << ";"; 173806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi } 174806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi } 1759af533538ea749d7c930bb3125fa4d3e4feb8478Satoshi Kataoka AKLOGI("===== sampled points ====="); 176feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka for (int i = 0; i < mSampledInputSize; ++i) { 1779af533538ea749d7c930bb3125fa4d3e4feb8478Satoshi Kataoka if (isGeometric) { 1786ae8dd4343445d2df4444388b605d2aa930fa2a0Satoshi Kataoka AKLOGI("%d: x = %d, y = %d, time = %d, relative speed = %.4f, beeline speed = %d", 1799af533538ea749d7c930bb3125fa4d3e4feb8478Satoshi Kataoka i, mSampledInputXs[i], mSampledInputYs[i], mTimes[i], mSpeedRates[i], 1806ae8dd4343445d2df4444388b605d2aa930fa2a0Satoshi Kataoka getBeelineSpeedPercentile(i)); 1819af533538ea749d7c930bb3125fa4d3e4feb8478Satoshi Kataoka } 182feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka sampledX << mSampledInputXs[i]; 183feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka sampledY << mSampledInputYs[i]; 184feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka if (i != mSampledInputSize - 1) { 185806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi sampledX << ";"; 186806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi sampledY << ";"; 187806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi } 188806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi } 189f25cc4405e329447425e52c3c5514a8802097fb8Satoshi Kataoka AKLOGI("original points:\n%s, %s,\nsampled points:\n%s, %s,\n", 190f25cc4405e329447425e52c3c5514a8802097fb8Satoshi Kataoka originalX.str().c_str(), originalY.str().c_str(), sampledX.str().c_str(), 191f25cc4405e329447425e52c3c5514a8802097fb8Satoshi Kataoka sampledY.str().c_str()); 192806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi } 193687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka // end 194687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka /////////////////////// 195687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka 19608f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka memset(mNormalizedSquaredDistances, NOT_A_DISTANCE, sizeof(mNormalizedSquaredDistances)); 19708f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka memset(mPrimaryInputWord, 0, sizeof(mPrimaryInputWord)); 198feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka mTouchPositionCorrectionEnabled = mSampledInputSize > 0 && mHasTouchPositionCorrectionData 1990edab9d2fcc30667c79aa9221dbb27f042d8b455Satoshi Kataoka && xCoordinates && yCoordinates; 20008f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka if (!isGeometric && pointerId == 0) { 20108f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka for (int i = 0; i < inputSize; ++i) { 2021e61493c50082264caaef862df02b1ccc84dc396Ken Wakasa mPrimaryInputWord[i] = getPrimaryCodePointAt(i); 2033e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka } 20408f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka 205feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka for (int i = 0; i < mSampledInputSize && mTouchPositionCorrectionEnabled; ++i) { 2061e61493c50082264caaef862df02b1ccc84dc396Ken Wakasa const int *proximityCodePoints = getProximityCodePointsAt(i); 2071e61493c50082264caaef862df02b1ccc84dc396Ken Wakasa const int primaryKey = proximityCodePoints[0]; 20808f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka const int x = xCoordinates[i]; 20908f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka const int y = yCoordinates[i]; 2103e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka if (DEBUG_PROXIMITY_CHARS) { 21108f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka int a = x + y + primaryKey; 21208f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka a += 0; 21308f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka AKLOGI("--- Primary = %c, x = %d, y = %d", primaryKey, x, y); 21408f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka } 2156c22439bf80da08576e86c1282afc5cfa431e235Ken Wakasa for (int j = 0; j < MAX_PROXIMITY_CHARS_SIZE && proximityCodePoints[j] > 0; 2161e61493c50082264caaef862df02b1ccc84dc396Ken Wakasa ++j) { 2171e61493c50082264caaef862df02b1ccc84dc396Ken Wakasa const int currentCodePoint = proximityCodePoints[j]; 21808f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka const float squaredDistance = 21908f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka hasInputCoordinates() ? calculateNormalizedSquaredDistance( 2201e61493c50082264caaef862df02b1ccc84dc396Ken Wakasa mProximityInfo->getKeyIndexOf(currentCodePoint), i) : 22108f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka NOT_A_DISTANCE_FLOAT; 22208f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka if (squaredDistance >= 0.0f) { 2236c22439bf80da08576e86c1282afc5cfa431e235Ken Wakasa mNormalizedSquaredDistances[i * MAX_PROXIMITY_CHARS_SIZE + j] = 22408f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka (int) (squaredDistance * NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR); 22508f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka } else { 2266c22439bf80da08576e86c1282afc5cfa431e235Ken Wakasa mNormalizedSquaredDistances[i * MAX_PROXIMITY_CHARS_SIZE + j] = 22708f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka (j == 0) ? EQUIVALENT_CHAR_WITHOUT_DISTANCE_INFO : 22808f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka PROXIMITY_CHAR_WITHOUT_DISTANCE_INFO; 22908f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka } 23008f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka if (DEBUG_PROXIMITY_CHARS) { 2311e61493c50082264caaef862df02b1ccc84dc396Ken Wakasa AKLOGI("--- Proximity (%d) = %c", j, currentCodePoint); 23208f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka } 2333e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka } 2343e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka } 2353e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka } 236952ec4977d772607140773ae7d8868f86a7e0097Satoshi Kataoka 237952ec4977d772607140773ae7d8868f86a7e0097Satoshi Kataoka if (DEBUG_GEO_FULL) { 238feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka AKLOGI("ProximityState init finished: %d points out of %d", mSampledInputSize, inputSize); 239feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka } 240feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka} 241feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka 242096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagibool ProximityInfoState::checkAndReturnIsContinuationPossible(const int inputSize, 243fe4f1ce26ca41ef51b5245d70e93b502f76262a5Satoshi Kataoka const int *const xCoordinates, const int *const yCoordinates, const int *const times, 244fe4f1ce26ca41ef51b5245d70e93b502f76262a5Satoshi Kataoka const bool isGeometric) const { 245fe4f1ce26ca41ef51b5245d70e93b502f76262a5Satoshi Kataoka if (isGeometric) { 246fe4f1ce26ca41ef51b5245d70e93b502f76262a5Satoshi Kataoka for (int i = 0; i < mSampledInputSize; ++i) { 247fe4f1ce26ca41ef51b5245d70e93b502f76262a5Satoshi Kataoka const int index = mInputIndice[i]; 248fe4f1ce26ca41ef51b5245d70e93b502f76262a5Satoshi Kataoka if (index > inputSize || xCoordinates[index] != mSampledInputXs[i] || 249fe4f1ce26ca41ef51b5245d70e93b502f76262a5Satoshi Kataoka yCoordinates[index] != mSampledInputYs[i] || times[index] != mTimes[i]) { 250fe4f1ce26ca41ef51b5245d70e93b502f76262a5Satoshi Kataoka return false; 251fe4f1ce26ca41ef51b5245d70e93b502f76262a5Satoshi Kataoka } 252fe4f1ce26ca41ef51b5245d70e93b502f76262a5Satoshi Kataoka } 253fe4f1ce26ca41ef51b5245d70e93b502f76262a5Satoshi Kataoka } else { 254fe4f1ce26ca41ef51b5245d70e93b502f76262a5Satoshi Kataoka if (inputSize < mSampledInputSize) { 255fe4f1ce26ca41ef51b5245d70e93b502f76262a5Satoshi Kataoka // Assuming the cache is invalid if the previous input size is larger than the new one. 256096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi return false; 257096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi } 2585db594abbad2d9e8d2cf1aa6e417aa50ffc5dfc1Ken Wakasa for (int i = 0; i < mSampledInputSize && i < MAX_WORD_LENGTH; ++i) { 259fe4f1ce26ca41ef51b5245d70e93b502f76262a5Satoshi Kataoka if (xCoordinates[i] != mSampledInputXs[i] 260fe4f1ce26ca41ef51b5245d70e93b502f76262a5Satoshi Kataoka || yCoordinates[i] != mSampledInputYs[i]) { 261fe4f1ce26ca41ef51b5245d70e93b502f76262a5Satoshi Kataoka return false; 262fe4f1ce26ca41ef51b5245d70e93b502f76262a5Satoshi Kataoka } 263fe4f1ce26ca41ef51b5245d70e93b502f76262a5Satoshi Kataoka } 264096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi } 265096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi return true; 266096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi} 267096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi 2684a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataokafloat ProximityInfoState::calculateNormalizedSquaredDistance( 2694a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka const int keyIndex, const int inputIndex) const { 2704a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka if (keyIndex == NOT_AN_INDEX) { 2714a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka return NOT_A_DISTANCE_FLOAT; 2724a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka } 2734a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka if (!mProximityInfo->hasSweetSpotData(keyIndex)) { 2744a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka return NOT_A_DISTANCE_FLOAT; 2754a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka } 276feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka if (NOT_A_COORDINATE == mSampledInputXs[inputIndex]) { 2774a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka return NOT_A_DISTANCE_FLOAT; 2784a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka } 2794a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka const float squaredDistance = calculateSquaredDistanceFromSweetSpotCenter( 2804a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka keyIndex, inputIndex); 2814a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka const float squaredRadius = square(mProximityInfo->getSweetSpotRadiiAt(keyIndex)); 2824a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka return squaredDistance / squaredRadius; 2834a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka} 2844a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka 285687a244703a02323ebd64433cbaead5def499861Satoshi Kataokaint ProximityInfoState::getDuration(const int index) const { 286feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka if (index >= 0 && index < mSampledInputSize - 1) { 287a811938d40070b96557df0f2a36ba8daa561fdd4Tom Ouyang return mTimes[index + 1] - mTimes[index]; 288687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka } 28937b153e205c9672b299b47e97921fee2462a78bbSatoshi Kataoka return 0; 290687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka} 291687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka 2920519fdd18ac4414b8298d3338db1c8ccce032170Satoshi Kataoka// TODO: Remove the "scale" parameter 2930519fdd18ac4414b8298d3338db1c8ccce032170Satoshi Kataoka// This function basically converts from a length to an edit distance. Accordingly, it's obviously 2940519fdd18ac4414b8298d3338db1c8ccce032170Satoshi Kataoka// wrong to compare with mMaxPointToKeyLength. 2950519fdd18ac4414b8298d3338db1c8ccce032170Satoshi Kataokafloat ProximityInfoState::getPointToKeyLength( 2960519fdd18ac4414b8298d3338db1c8ccce032170Satoshi Kataoka const int inputIndex, const int codePoint, const float scale) const { 297ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi const int keyId = mProximityInfo->getKeyIndexOf(codePoint); 298ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi if (keyId != NOT_AN_INDEX) { 299ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi const int index = inputIndex * mProximityInfo->getKeyCount() + keyId; 300a9763f93d76f97b9c6ed7dd1369a4d8cb016f06fSatoshi Kataoka return min(mDistanceCache_G[index] * scale, mMaxPointToKeyLength); 301ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi } 3021e61493c50082264caaef862df02b1ccc84dc396Ken Wakasa if (isSkippableCodePoint(codePoint)) { 303806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi return 0.0f; 304806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi } 305ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi // If the char is not a key on the keyboard then return the max length. 306ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi return MAX_POINT_TO_KEY_LENGTH; 307806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi} 308806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi 309a9763f93d76f97b9c6ed7dd1369a4d8cb016f06fSatoshi Kataokafloat ProximityInfoState::getPointToKeyLength_G(const int inputIndex, const int codePoint) const { 3100519fdd18ac4414b8298d3338db1c8ccce032170Satoshi Kataoka return getPointToKeyLength(inputIndex, codePoint, 1.0f); 3110519fdd18ac4414b8298d3338db1c8ccce032170Satoshi Kataoka} 3120519fdd18ac4414b8298d3338db1c8ccce032170Satoshi Kataoka 3130519fdd18ac4414b8298d3338db1c8ccce032170Satoshi Kataoka// TODO: Remove the "scale" parameter 3140519fdd18ac4414b8298d3338db1c8ccce032170Satoshi Kataokafloat ProximityInfoState::getPointToKeyByIdLength( 3150519fdd18ac4414b8298d3338db1c8ccce032170Satoshi Kataoka const int inputIndex, const int keyId, const float scale) const { 316d4828d5053ac30476b884c177235be0cac982c92Satoshi Kataoka return ProximityInfoStateUtils::getPointToKeyByIdLength(mMaxPointToKeyLength, 317d4828d5053ac30476b884c177235be0cac982c92Satoshi Kataoka &mDistanceCache_G, mProximityInfo->getKeyCount(), inputIndex, keyId, scale); 318687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka} 319687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka 3200519fdd18ac4414b8298d3338db1c8ccce032170Satoshi Kataokafloat ProximityInfoState::getPointToKeyByIdLength(const int inputIndex, const int keyId) const { 3210519fdd18ac4414b8298d3338db1c8ccce032170Satoshi Kataoka return getPointToKeyByIdLength(inputIndex, keyId, 1.0f); 3220519fdd18ac4414b8298d3338db1c8ccce032170Satoshi Kataoka} 3230519fdd18ac4414b8298d3338db1c8ccce032170Satoshi Kataoka 3242c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa// In the following function, c is the current character of the dictionary word currently examined. 3252c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa// currentChars is an array containing the keys close to the character the user actually typed at 3262c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa// the same position. We want to see if c is in it: if so, then the word contains at that position 3272c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa// a character close to what the user typed. 3282c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa// What the user typed is actually the first character of the array. 3292c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa// proximityIndex is a pointer to the variable where getMatchedProximityId returns the index of c 3302c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa// in the proximity chars of the input index. 3312c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa// Notice : accented characters do not have a proximity list, so they are alone in their list. The 3322c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa// non-accented version of the character should be considered "close", but not the other keys close 3332c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa// to the non-accented version. 3342c2f3a90d8115777adbe9ffd597f344aede84276Ken WakasaProximityType ProximityInfoState::getMatchedProximityId(const int index, const int c, 3352c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa const bool checkProximityChars, int *proximityIndex) const { 3362c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa const int *currentCodePoints = getProximityCodePointsAt(index); 3372c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa const int firstCodePoint = currentCodePoints[0]; 3382c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa const int baseLowerC = toBaseLowerCase(c); 3392c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa 3402c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa // The first char in the array is what user typed. If it matches right away, that means the 3412c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa // user typed that same char for this pos. 3422c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa if (firstCodePoint == baseLowerC || firstCodePoint == c) { 3432c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa return EQUIVALENT_CHAR; 3442c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa } 3452c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa 3462c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa if (!checkProximityChars) return UNRELATED_CHAR; 3472c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa 3482c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa // If the non-accented, lowercased version of that first character matches c, then we have a 3492c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa // non-accented version of the accented character the user typed. Treat it as a close char. 3502c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa if (toBaseLowerCase(firstCodePoint) == baseLowerC) { 3512c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa return NEAR_PROXIMITY_CHAR; 3522c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa } 3532c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa 3542c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa // Not an exact nor an accent-alike match: search the list of close keys 3552c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa int j = 1; 3566c22439bf80da08576e86c1282afc5cfa431e235Ken Wakasa while (j < MAX_PROXIMITY_CHARS_SIZE 3572c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa && currentCodePoints[j] > ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) { 3582c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa const bool matched = (currentCodePoints[j] == baseLowerC || currentCodePoints[j] == c); 3592c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa if (matched) { 3602c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa if (proximityIndex) { 3612c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa *proximityIndex = j; 3622c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa } 3632c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa return NEAR_PROXIMITY_CHAR; 3642c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa } 3652c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa ++j; 3662c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa } 3676c22439bf80da08576e86c1282afc5cfa431e235Ken Wakasa if (j < MAX_PROXIMITY_CHARS_SIZE 3682c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa && currentCodePoints[j] == ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) { 3692c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa ++j; 3706c22439bf80da08576e86c1282afc5cfa431e235Ken Wakasa while (j < MAX_PROXIMITY_CHARS_SIZE 3712c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa && currentCodePoints[j] > ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) { 3722c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa const bool matched = (currentCodePoints[j] == baseLowerC || currentCodePoints[j] == c); 3732c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa if (matched) { 3742c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa if (proximityIndex) { 3752c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa *proximityIndex = j; 3762c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa } 3772c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa return ADDITIONAL_PROXIMITY_CHAR; 3782c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa } 3792c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa ++j; 3802c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa } 3812c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa } 3822c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa // Was not included, signal this as an unrelated character. 3832c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa return UNRELATED_CHAR; 3842c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa} 3852c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa 3863811a28ddc07201930e0bbd2e1d01045b59af308Keisuke Kuroyanagiint ProximityInfoState::getSpaceY() const { 387b02ee3d67a1884b6ff59cc16c29a476845c0694fKen Wakasa const int keyId = mProximityInfo->getKeyIndexOf(KEYCODE_SPACE); 388f2789819bd005b5b0581e8439601b5501306327dKen Wakasa return mProximityInfo->getKeyCenterYOfKeyIdG(keyId); 389687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka} 390687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka 3914a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataokafloat ProximityInfoState::calculateSquaredDistanceFromSweetSpotCenter( 3924a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka const int keyIndex, const int inputIndex) const { 3934a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka const float sweetSpotCenterX = mProximityInfo->getSweetSpotCenterXAt(keyIndex); 3944a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka const float sweetSpotCenterY = mProximityInfo->getSweetSpotCenterYAt(keyIndex); 395feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka const float inputX = static_cast<float>(mSampledInputXs[inputIndex]); 396feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka const float inputY = static_cast<float>(mSampledInputYs[inputIndex]); 3974a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka return square(inputX - sweetSpotCenterX) + square(inputY - sweetSpotCenterY); 3984a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka} 39995a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi 40095a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi// Puts possible characters into filter and returns new filter size. 401082507e1da56c6cefe575ec3d6a334e9b717e3faKen Wakasaint ProximityInfoState::getAllPossibleChars( 402082507e1da56c6cefe575ec3d6a334e9b717e3faKen Wakasa const size_t index, int *const filter, const int filterSize) const { 403feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka if (index >= mSampledInputXs.size()) { 40495a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi return filterSize; 40595a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi } 40641f12ee27b269033fe818f7d52e81ba948a046c3Keisuke Kuroyanagi int newFilterSize = filterSize; 407ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi const int keyCount = mProximityInfo->getKeyCount(); 408ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi for (int j = 0; j < keyCount; ++j) { 409ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi if (mSearchKeysVector[index].test(j)) { 410082507e1da56c6cefe575ec3d6a334e9b717e3faKen Wakasa const int keyCodePoint = mProximityInfo->getCodePointOf(j); 41195a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi bool insert = true; 41295a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi // TODO: Avoid linear search 41395a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi for (int k = 0; k < filterSize; ++k) { 41495a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi if (filter[k] == keyCodePoint) { 41595a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi insert = false; 41695a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi break; 41795a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi } 41895a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi } 41995a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi if (insert) { 42041f12ee27b269033fe818f7d52e81ba948a046c3Keisuke Kuroyanagi filter[newFilterSize++] = keyCodePoint; 42195a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi } 42295a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi } 42395a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi } 42441f12ee27b269033fe818f7d52e81ba948a046c3Keisuke Kuroyanagi return newFilterSize; 42595a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi} 4263811a28ddc07201930e0bbd2e1d01045b59af308Keisuke Kuroyanagi 427ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagibool ProximityInfoState::isKeyInSerchKeysAfterIndex(const int index, const int keyId) const { 428ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi ASSERT(keyId >= 0); 429feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka ASSERT(index >= 0 && index < mSampledInputSize); 430ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi return mSearchKeysVector[index].test(keyId); 431ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi} 432ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi 433096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagivoid ProximityInfoState::popInputData() { 43447cc52415e3affb83eb4369190425b2a17b956c5Satoshi Kataoka ProximityInfoStateUtils::popInputData(&mSampledInputXs, &mSampledInputYs, &mTimes, 43547cc52415e3affb83eb4369190425b2a17b956c5Satoshi Kataoka &mLengthCache, &mInputIndice); 436096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi} 437096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi 438ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagifloat ProximityInfoState::getDirection(const int index0, const int index1) const { 439ee62b78c9675bddaf2437e0cf521f6115e1d9febSatoshi Kataoka return ProximityInfoStateUtils::getDirection( 440ee62b78c9675bddaf2437e0cf521f6115e1d9febSatoshi Kataoka &mSampledInputXs, &mSampledInputYs, index0, index1); 441ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi} 442ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi 443ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagifloat ProximityInfoState::getLineToKeyDistance( 444ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi const int from, const int to, const int keyId, const bool extend) const { 445feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka if (from < 0 || from > mSampledInputSize - 1) { 446ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi return 0.0f; 447ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi } 448feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka if (to < 0 || to > mSampledInputSize - 1) { 449ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi return 0.0f; 450ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi } 451feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka const int x0 = mSampledInputXs[from]; 452feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka const int y0 = mSampledInputYs[from]; 453feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka const int x1 = mSampledInputXs[to]; 454feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka const int y1 = mSampledInputYs[to]; 455ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi 456ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi const int keyX = mProximityInfo->getKeyCenterXOfKeyIdG(keyId); 457ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi const int keyY = mProximityInfo->getKeyCenterYOfKeyIdG(keyId); 458ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi 4590c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa return ProximityInfoUtils::pointToLineSegSquaredDistanceFloat( 4600c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa keyX, keyY, x0, y0, x1, y1, extend); 461806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi} 462806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi 463e0349619acdba79223390c9925d81f7e88c7f8adSatoshi Kataoka// Get a word that is detected by tracing the most probable string into codePointBuf and 4641e61493c50082264caaef862df02b1ccc84dc396Ken Wakasa// returns probability of generating the word. 465e0349619acdba79223390c9925d81f7e88c7f8adSatoshi Kataokafloat ProximityInfoState::getMostProbableString(int *const codePointBuf) const { 466350309aeb81ad1924af4d2e6d0bceaa6f98e4821Keisuke Kuroyanagi static const float DEMOTION_LOG_PROBABILITY = 0.3f; 467ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi int index = 0; 468ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi float sumLogProbability = 0.0f; 469806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi // TODO: Current implementation is greedy algorithm. DP would be efficient for many cases. 4705db594abbad2d9e8d2cf1aa6e417aa50ffc5dfc1Ken Wakasa for (int i = 0; i < mSampledInputSize && index < MAX_WORD_LENGTH - 1; ++i) { 471ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi float minLogProbability = static_cast<float>(MAX_POINT_TO_KEY_LENGTH); 472ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi int character = NOT_AN_INDEX; 473806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi for (hash_map_compat<int, float>::const_iterator it = mCharProbabilities[i].begin(); 474806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi it != mCharProbabilities[i].end(); ++it) { 475ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi const float logProbability = (it->first != NOT_AN_INDEX) 476350309aeb81ad1924af4d2e6d0bceaa6f98e4821Keisuke Kuroyanagi ? it->second + DEMOTION_LOG_PROBABILITY : it->second; 477ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi if (logProbability < minLogProbability) { 478ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi minLogProbability = logProbability; 479ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi character = it->first; 480806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi } 481806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi } 482ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi if (character != NOT_AN_INDEX) { 4831e61493c50082264caaef862df02b1ccc84dc396Ken Wakasa codePointBuf[index] = mProximityInfo->getCodePointOf(character); 484806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi index++; 485806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi } 486ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi sumLogProbability += minLogProbability; 487806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi } 4881e61493c50082264caaef862df02b1ccc84dc396Ken Wakasa codePointBuf[index] = '\0'; 489ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi return sumLogProbability; 490ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi} 491ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi 492f32869c6b6296a8bf594abdf0b18281d9312e54fSatoshi Kataokabool ProximityInfoState::hasSpaceProximity(const int index) const { 493f32869c6b6296a8bf594abdf0b18281d9312e54fSatoshi Kataoka ASSERT(0 <= index && index < mSampledInputSize); 494f32869c6b6296a8bf594abdf0b18281d9312e54fSatoshi Kataoka return mProximityInfo->hasSpaceProximity(getInputX(index), getInputY(index)); 495f32869c6b6296a8bf594abdf0b18281d9312e54fSatoshi Kataoka} 496f32869c6b6296a8bf594abdf0b18281d9312e54fSatoshi Kataoka 497ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi// Returns a probability of mapping index to keyIndex. 498ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagifloat ProximityInfoState::getProbability(const int index, const int keyIndex) const { 499feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka ASSERT(0 <= index && index < mSampledInputSize); 500ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi hash_map_compat<int, float>::const_iterator it = mCharProbabilities[index].find(keyIndex); 501ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi if (it != mCharProbabilities[index].end()) { 502ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi return it->second; 503ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi } 504ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi return static_cast<float>(MAX_POINT_TO_KEY_LENGTH); 505806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi} 5063e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka} // namespace latinime 507