1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "core/event/resample_algo.h"
16
17 namespace OHOS::Ace {
GetAvgPoint(const std::vector<PointerEvent> && events,bool isScreen)18 AvgPoint ResampleAlgo::GetAvgPoint(const std::vector<PointerEvent>&& events,
19 bool isScreen)
20 {
21 float avgX = 0.0f;
22 float avgY = 0.0f;
23 uint64_t avgTime = 0;
24 int32_t i = 0;
25 uint64_t lastTime = 0;
26 for (auto iter = events.begin(); iter != events.end(); iter++) {
27 if (lastTime == 0 || static_cast<uint64_t>(iter->time.time_since_epoch().count()) != lastTime) {
28 if (!isScreen) {
29 avgX += iter->x;
30 avgY += iter->y;
31 } else {
32 avgX += iter->screenX;
33 avgY += iter->screenY;
34 }
35 avgTime += static_cast<uint64_t>(iter->time.time_since_epoch().count());
36 i++;
37 lastTime = static_cast<uint64_t>(iter->time.time_since_epoch().count());
38 }
39 }
40 if (i > 0) {
41 avgX /= i;
42 avgY /= i;
43 avgTime /= static_cast<uint64_t>(i);
44 }
45 return {
46 avgX,
47 avgY,
48 avgTime,
49 0.0f,
50 0.0f
51 };
52 }
53
LinearInterpolation(const AvgPoint & history,const AvgPoint & current,uint64_t nanoTimeStamp)54 ResamplePoint ResampleAlgo::LinearInterpolation(const AvgPoint& history, const AvgPoint& current,
55 uint64_t nanoTimeStamp)
56 {
57 if ((nanoTimeStamp == history.time || nanoTimeStamp == current.time) ||
58 (current.time <= history.time) ||
59 (current.time - history.time > INTERPOLATION_THRESHOLD) ||
60 (nanoTimeStamp < history.time)) {
61 return {};
62 }
63 auto inputXDeltaSlope = (current.x - history.x) * ONE_S_IN_NS /
64 (float)(current.time - history.time);
65 auto inputYDeltaSlope = (current.y - history.y) * ONE_S_IN_NS /
66 (float)(current.time - history.time);
67 if (nanoTimeStamp < current.time) {
68 float alpha = (float)(nanoTimeStamp - history.time) /
69 (float)(current.time - history.time);
70 float x = history.x + alpha * (current.x - history.x);
71 float y = history.y + alpha * (current.y - history.y);
72 return {
73 x,
74 y,
75 inputXDeltaSlope,
76 inputYDeltaSlope
77 };
78 } else if (nanoTimeStamp > current.time) {
79 float alpha = (float)(nanoTimeStamp - current.time) /
80 (float)(current.time - history.time);
81 float x = current.x + alpha * (current.x - history.x);
82 float y = current.y + alpha * (current.y - history.y);
83 return {
84 x,
85 y,
86 inputXDeltaSlope,
87 inputYDeltaSlope
88 };
89 }
90 return {};
91 }
92
GetResampleCoord(const std::vector<PointerEvent> && history,const std::vector<PointerEvent> && current,uint64_t nanoTimeStamp,bool isScreen)93 ResamplePoint ResampleAlgo::GetResampleCoord(const std::vector<PointerEvent>&& history,
94 const std::vector<PointerEvent>&& current, uint64_t nanoTimeStamp,
95 bool isScreen)
96 {
97 if (history.empty() || current.empty()) {
98 return {};
99 }
100 uint64_t lastNanoTime = 0;
101 float x = 0.0f;
102 float y = 0.0f;
103 for (const auto& item : current) {
104 uint64_t currentNanoTime = static_cast<uint64_t>(item.time.time_since_epoch().count());
105 if (lastNanoTime < currentNanoTime) {
106 lastNanoTime = currentNanoTime;
107 x = item.x;
108 y = item.y;
109 }
110 }
111 if (nanoTimeStamp > RESAMPLE_COORD_TIME_THRESHOLD + lastNanoTime) {
112 return {
113 x,
114 y,
115 0.0f,
116 0.0f
117 };
118 }
119 auto historyPoint = GetAvgPoint(std::move(history), isScreen);
120 auto currentPoint = GetAvgPoint(std::move(current), isScreen);
121 return LinearInterpolation(historyPoint, currentPoint, nanoTimeStamp);
122 }
123 } // namespace OHOS::Ace