Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9357ceba authored by Satoshi Kataoka's avatar Satoshi Kataoka Committed by Android (Google) Code Review
Browse files

Merge "Smart sampling for geometric inputs." into jb-mr1-dev

parents ab5f9532 d9c10b19
Loading
Loading
Loading
Loading
+180 −16
Original line number Diff line number Diff line
@@ -76,10 +76,24 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi
    mTimes.clear();
    mLengthCache.clear();
    mDistanceCache.clear();

    mInputSize = 0;

    if (xCoordinates && yCoordinates) {
        const bool proximityOnly = !isGeometric && (xCoordinates[0] < 0 || yCoordinates[0] < 0);
        int lastInputIndex = 0;
        for (int i = 0; i < inputSize; ++i) {
            const int pid = pointerIds ? pointerIds[i] : 0;
            if (pointerId == pid) {
                lastInputIndex = i;
            }
        }
        // Working space to save near keys distances for current, prev and prevprev input point.
        NearKeysDistanceMap nearKeysDistances[3];
        // These pointers are swapped for each inputs points.
        NearKeysDistanceMap *currentNearKeysDistances = &nearKeysDistances[0];
        NearKeysDistanceMap *prevNearKeysDistances = &nearKeysDistances[1];
        NearKeysDistanceMap *prevPrevNearKeysDistances = &nearKeysDistances[2];

        for (int i = 0; i < inputSize; ++i) {
            // Assuming pointerId == 0 if pointerIds is null.
            const int pid = pointerIds ? pointerIds[i] : 0;
@@ -88,11 +102,22 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi
                const int x = proximityOnly ? NOT_A_COORDINATE : xCoordinates[i];
                const int y = proximityOnly ? NOT_A_COORDINATE : yCoordinates[i];
                const int time = times ? times[i] : -1;
                if (pushTouchPoint(c, x, y, time, isGeometric)) {
                    ++mInputSize;
                if (pushTouchPoint(c, x, y, time, isGeometric, i == lastInputIndex,
                        currentNearKeysDistances, prevNearKeysDistances,
                        prevPrevNearKeysDistances)) {
                    // Previous point information was popped.
                    NearKeysDistanceMap *tmp = prevNearKeysDistances;
                    prevNearKeysDistances = currentNearKeysDistances;
                    currentNearKeysDistances = tmp;
                } else {
                    NearKeysDistanceMap *tmp = prevPrevNearKeysDistances;
                    prevPrevNearKeysDistances = prevNearKeysDistances;
                    prevNearKeysDistances = currentNearKeysDistances;
                    currentNearKeysDistances = tmp;
                }
            }
        }
        mInputSize = mInputXs.size();
    }

    if (mInputSize > 0) {
@@ -153,20 +178,151 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi
    }
}

bool ProximityInfoState::pushTouchPoint(const int nodeChar, int x, int y,
        const int time, const bool sample) {
    const uint32_t size = mInputXs.size();
    // TODO: Should have a const variable for 10
    const int sampleRate = mProximityInfo->getMostCommonKeyWidth() / 10;
    if (size > 0) {
        const int dist = getDistanceInt(x, y, mInputXs[size - 1], mInputYs[size - 1]);
        if (sample && dist < sampleRate) {
// Calculating point to key distance for all near keys and returning the distance between
// the given point and the nearest key position.
float ProximityInfoState::updateNearKeysDistances(const int x, const int y,
        NearKeysDistanceMap *const currentNearKeysDistances) {
    static const float NEAR_KEY_THRESHOLD = 10.0f;

    currentNearKeysDistances->clear();
    const int keyCount = mProximityInfo->getKeyCount();
    float nearestKeyDistance = mMaxPointToKeyLength;
    for (int k = 0; k < keyCount; ++k) {
        const float dist = mProximityInfo->getNormalizedSquaredDistanceFromCenterFloat(k, x, y);
        if (dist < NEAR_KEY_THRESHOLD) {
            currentNearKeysDistances->insert(std::pair<int, float>(k, dist));
        }
        if (nearestKeyDistance > dist) {
            nearestKeyDistance = dist;
        }
    }
    return nearestKeyDistance;
}

// Check if previous point is at local minimum position to near keys.
bool ProximityInfoState::isPrevLocalMin(const NearKeysDistanceMap *const currentNearKeysDistances,
        const NearKeysDistanceMap *const prevNearKeysDistances,
        const NearKeysDistanceMap *const prevPrevNearKeysDistances) const {
    static const float MARGIN = 0.5f;

    for (NearKeysDistanceMap::const_iterator it = prevNearKeysDistances->begin();
        it != prevNearKeysDistances->end(); ++it) {
        NearKeysDistanceMap::const_iterator itPP = prevPrevNearKeysDistances->find(it->first);
        NearKeysDistanceMap::const_iterator itC = currentNearKeysDistances->find(it->first);
        if ((itPP == prevPrevNearKeysDistances->end() || itPP->second > it->second + MARGIN)
                && (itC == currentNearKeysDistances->end() || itC->second > it->second + MARGIN)) {
            return true;
        }
    }
    return false;
}
        mLengthCache.push_back(mLengthCache[size - 1] + dist);

// Calculating a point score that indicates usefulness of the point.
float ProximityInfoState::getPointScore(
        const int x, const int y, const int time, const bool lastPoint, const float nearest,
        const NearKeysDistanceMap *const currentNearKeysDistances,
        const NearKeysDistanceMap *const prevNearKeysDistances,
        const NearKeysDistanceMap *const prevPrevNearKeysDistances) const {
    static const float BASE_SAMPLE_RATE_SCALE = 0.1f;
    static const float SAVE_DISTANCE_SCALE = 12.0f;
    static const float SAVE_DISTANCE_SCORE = 2.0f;
    static const float SKIP_DISTANCE_SCALE = 1.5f;
    static const float SKIP_DISTANCE_SCORE = -1.0f;
    static const float CHECK_LOCALMIN_DISTANCE_THRESHOLD_SCALE = 2.5f;
    static const float CHECK_LOCALMIN_DISTANCE_SCORE = -1.0f;
    static const float STRAIGHT_ANGLE_THRESHOLD = M_PI_F / 32.0f;
    static const float STRAIGHT_SKIP_DISTANCE_THRESHOLD_SCALE = 4.0f;
    static const float STRAIGHT_SKIP_NEAREST_DISTANCE_THRESHOLD = 0.5f;
    static const float STRAIGHT_SKIP_SCORE = -1.0f;

    const std::size_t size = mInputXs.size();
    if (size <= 1) {
        return 0;
    }
    const float baseSampleRate = mProximityInfo->getMostCommonKeyWidth() * BASE_SAMPLE_RATE_SCALE;
    const float distNext = getDistanceFloat(x, y, mInputXs.back(), mInputYs.back());
    const float distPrev = getDistanceFloat(mInputXs.back(), mInputYs.back(),
            mInputXs[size - 2], mInputYs[size - 2]);
    float score = 0.0f;

    // Sum of distances
    if (distPrev + distNext > baseSampleRate * SAVE_DISTANCE_SCALE) {
        score +=  SAVE_DISTANCE_SCORE;
    }
    // Distance
    if (distPrev < baseSampleRate * SKIP_DISTANCE_SCALE) {
        score += SKIP_DISTANCE_SCORE;
    }
    // Location
    if (!isPrevLocalMin(currentNearKeysDistances, currentNearKeysDistances,
            prevPrevNearKeysDistances)) {
        if (distPrev < baseSampleRate * CHECK_LOCALMIN_DISTANCE_THRESHOLD_SCALE) {
            score += CHECK_LOCALMIN_DISTANCE_SCORE;
        }
    }
    // Angle
    const float angle1 = getAngle(x, y, mInputXs.back(), mInputYs.back());
    const float angle2 = getAngle(mInputXs.back(), mInputYs.back(),
            mInputXs[size - 2], mInputYs[size - 2]);
    if (getAngleDiff(angle1, angle2) < STRAIGHT_ANGLE_THRESHOLD) {
        if (nearest > STRAIGHT_SKIP_NEAREST_DISTANCE_THRESHOLD
                && distPrev < baseSampleRate * STRAIGHT_SKIP_DISTANCE_THRESHOLD_SCALE) {
            score += STRAIGHT_SKIP_SCORE;
        }
    }
    return score;
}

// Sampling touch point and pushing information to vectors.
// Returning if previous point is popped or not.
bool ProximityInfoState::pushTouchPoint(const int nodeChar, int x, int y, const int time,
        const bool sample, const bool isLastPoint,
        NearKeysDistanceMap *const currentNearKeysDistances,
        const NearKeysDistanceMap *const prevNearKeysDistances,
        const NearKeysDistanceMap *const prevPrevNearKeysDistances) {
    static const float LAST_POINT_SKIP_DISTANCE_SCALE = 0.25f;

    uint32_t size = mInputXs.size();
    bool popped = false;
    if (nodeChar < 0 && sample) {
        const float nearest = updateNearKeysDistances(x, y, currentNearKeysDistances);
        const float score = getPointScore(x, y, time, isLastPoint, nearest,
                currentNearKeysDistances, prevNearKeysDistances, prevPrevNearKeysDistances);
        if (score < 0) {
            // Pop previous point because it would be useless.
            mInputXs.pop_back();
            mInputYs.pop_back();
            mTimes.pop_back();
            mLengthCache.pop_back();
            size = mInputXs.size();
            popped = true;
        } else {
        mLengthCache.push_back(0);
            popped = false;
        }
        // Check if the last point should be skipped.
        if (isLastPoint) {
            if (size > 0 && getDistanceFloat(x, y, mInputXs.back(), mInputYs.back())
                    < mProximityInfo->getMostCommonKeyWidth() * LAST_POINT_SKIP_DISTANCE_SCALE) {
                return popped;
            } else if (size > 1) {
                int minChar = 0;
                float minDist = mMaxPointToKeyLength;
                for (NearKeysDistanceMap::const_iterator it = currentNearKeysDistances->begin();
                        it != currentNearKeysDistances->end(); ++it) {
                    if(minDist > it->second){
                        minChar = it->first;
                        minDist = it->second;
                    }
                }
                NearKeysDistanceMap::const_iterator itPP =
                        prevNearKeysDistances->find(minChar);
                if (itPP != prevNearKeysDistances->end() && minDist > itPP->second) {
                    return popped;
                }
            }
        }
    }

    if (nodeChar >= 0 && (x < 0 || y < 0)) {
        const int keyId = mProximityInfo->getKeyIndex(nodeChar);
        if (keyId >= 0) {
@@ -174,10 +330,18 @@ bool ProximityInfoState::pushTouchPoint(const int nodeChar, int x, int y,
            y = mProximityInfo->getKeyCenterYOfIdG(keyId);
        }
    }

    // Pushing point information.
    if (size > 0) {
        mLengthCache.push_back(
                mLengthCache.back() + getDistanceInt(x, y, mInputXs.back(), mInputYs.back()));
    } else {
        mLengthCache.push_back(0);
    }
    mInputXs.push_back(x);
    mInputYs.push_back(y);
    mTimes.push_back(time);
    return true;
    return popped;
}

float ProximityInfoState::calculateNormalizedSquaredDistance(
+18 −1
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@

#include "char_utils.h"
#include "defines.h"
#include "hash_map_compat.h"

namespace latinime {

@@ -216,6 +217,7 @@ class ProximityInfoState {

 private:
    DISALLOW_COPY_AND_ASSIGN(ProximityInfoState);
    typedef hash_map_compat<int, float> NearKeysDistanceMap;
    /////////////////////////////////////////
    // Defined in proximity_info_state.cpp //
    /////////////////////////////////////////
@@ -224,7 +226,11 @@ class ProximityInfoState {
    float calculateSquaredDistanceFromSweetSpotCenter(
            const int keyIndex, const int inputIndex) const;

    bool pushTouchPoint(const int nodeChar, int x, int y, const int time, const bool sample);
    bool pushTouchPoint(const int nodeChar, int x, int y, const int time,
            const bool sample, const bool isLastPoint,
            NearKeysDistanceMap *const currentNearKeysDistances,
            const NearKeysDistanceMap *const prevNearKeysDistances,
            const NearKeysDistanceMap *const prevPrevNearKeysDistances);
    /////////////////////////////////////////
    // Defined here                        //
    /////////////////////////////////////////
@@ -238,6 +244,17 @@ class ProximityInfoState {
        return mInputCodes + (index * MAX_PROXIMITY_CHARS_SIZE_INTERNAL);
    }

    float updateNearKeysDistances(const int x, const int y,
            NearKeysDistanceMap *const currentNearKeysDistances);
    bool isPrevLocalMin(const NearKeysDistanceMap *const currentNearKeysDistances,
            const NearKeysDistanceMap *const prevNearKeysDistances,
            const NearKeysDistanceMap *const prevPrevNearKeysDistances) const;
    float getPointScore(
            const int x, const int y, const int time, const bool last, const float nearest,
            const NearKeysDistanceMap *const currentNearKeysDistances,
            const NearKeysDistanceMap *const prevNearKeysDistances,
            const NearKeysDistanceMap *const prevPrevNearKeysDistances) const;

    // const
    const ProximityInfo *mProximityInfo;
    float mMaxPointToKeyLength;