UITouch определение скорости движения - PullRequest
11 голосов
/ 21 марта 2009

Я пытаюсь определить скорость движения прикосновения и не всегда получаю ожидаемые результаты. (добавлено: скорость слишком резко увеличивается) Может кто-нибудь заметить, если я делаю что-то напуганное, или предложить лучший способ сделать это?


- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    self.previousTimestamp = event.timestamp;
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
    UITouch *touch = [touches anyObject];
    CGPoint location = [touch locationInView:self.view];
    CGPoint prevLocation = [touch previousLocationInView:self.view];
    CGFloat distanceFromPrevious = distanceBetweenPoints(location,prevLocation);
    NSTimeInterval timeSincePrevious = event.timestamp - self.previousTimestamp;
    CGFloat speed = distanceFromPrevious/timeSincePrevious;
    self.previousTimestamp = event.timestamp;
    NSLog(@"dist %f | time %f | speed %f",distanceFromPrevious, timeSincePrevious, speed);

}

Ответы [ 3 ]

11 голосов
/ 21 марта 2009

Вы можете попробовать (обнулить расстояниеSinceStart и timeSinceStart в касаниях Beg):

distanceSinceStart = distanceSinceStart + distanceFromPrevious;
timeSinceStart = timeSincestart + timeSincePrevious;
speed = distanceSinceStart/timeSinceStart;

, которая даст вам среднюю скорость с момента начала касания (общее расстояние / общее время).

Или вы можете сделать скользящее среднее по скорости, возможно, экспоненциальное скользящее среднее:

const float lambda = 0.8f; // the closer to 1 the higher weight to the next touch

newSpeed = (1.0 - lambda) * oldSpeed + lambda* (distanceFromPrevious/timeSincePrevious);
oldSpeed = newSpeed;

Вы можете настроить лямбду на значения, близкие к 1, если хотите придать больший вес последним значениям.

3 голосов
/ 31 июля 2012

Основная проблема в том, что вычисление скорости будет очень неточным , когда timeSincePrevious очень мало (несколько миллисекунд). Чтобы увидеть это, скажем, что timeSincePrevious равно 1 мс. Тогда вычисленная скорость будет 0, если distanceFromPrevious равно 0, и 1000, если distanceFromZero равно 1.

По этой причине я предлагаю следующее значение лямбды:

const float labmda = (timeSincePrevious>0.2? 1: timeSincePrevious/0.2);

То есть мы используем крошечную лямбду, когда timeSincePrevious мало.

1 голос
/ 26 ноября 2012

Предложение фильтра может быть в порядке, но это не решает проблему: пик будет сглажен, но останется.

Если вы отключили события касания, эти пики будут выглядеть как касание с очень небольшим интервалом времени по сравнению с предыдущим (0,001215 мс), которому предшествует касание с большим интервалом времени.

distance = 17.269917, timeDelta = 0.016132, speed = 1070.504639 
distance = 15.206906, timeDelta = 0.017494, speed = 869.251709 
distance = 15.882380, timeDelta = 0.017583, speed = 903.297546 
distance = 14.983324, timeDelta = 0.030101, speed = 497.771088      //low peak
distance = 15.435349, timeDelta = 0.001215, speed = 12703.991211    //high peak!
distance = 15.882380, timeDelta = 0.017343, speed = 915.795898 
distance = 15.890248, timeDelta = 0.016302, speed = 974.742249 
distance = 16.560495, timeDelta = 0.016468, speed = 1005.606445 
distance = 16.101242, timeDelta = 0.017291, speed = 931.201050 

Что я делаю, так это вычисляю среднюю дельту времени между недавними событиями касания, и если происходит касание с ненормальной дельтой времени (± 30%), я игнорирую его скорость (сохраняя скорость предыдущего события)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...