• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 
16 #include "core/animation/spring_model.h"
17 
18 #include "base/log/log.h"
19 #include "base/utils/utils.h"
20 
21 namespace OHOS::Ace {
22 namespace {
23 
24 constexpr double HIGH_RATIO = 4.0;
25 constexpr double LOW_RATIO = 2.0;
26 
27 } // namespace
28 
IsValid() const29 bool SpringProperty::IsValid() const
30 {
31     if (LessOrEqual(mass_, 0.0) || LessOrEqual(stiffness_, 0.0) || LessOrEqual(damping_, 0.0)) {
32         return false;
33     }
34     return true;
35 }
36 
SetMass(double mass)37 void SpringProperty::SetMass(double mass)
38 {
39     if (mass > 0.0) {
40         mass_ = mass;
41     }
42 }
43 
Mass() const44 double SpringProperty::Mass() const
45 {
46     return mass_;
47 }
48 
SetStiffness(double stiffness)49 void SpringProperty::SetStiffness(double stiffness)
50 {
51     if (stiffness > 0.0) {
52         stiffness_ = stiffness;
53     }
54 }
55 
Stiffness() const56 double SpringProperty::Stiffness() const
57 {
58     return stiffness_;
59 }
60 
SetDamping(double damping)61 void SpringProperty::SetDamping(double damping)
62 {
63     if (damping > 0.0) {
64         damping_ = damping;
65     }
66 }
67 
Damping() const68 double SpringProperty::Damping() const
69 {
70     return damping_;
71 }
72 
Build(double distance,double velocity,const RefPtr<SpringProperty> & spring)73 RefPtr<SpringModel> SpringModel::Build(double distance, double velocity, const RefPtr<SpringProperty>& spring)
74 {
75     if (!spring || !spring->IsValid()) {
76         LOGE("SpringProperty can not be nullptr.");
77         return nullptr;
78     } else {
79         double cmk = spring->Damping() * spring->Damping() - HIGH_RATIO * spring->Mass() * spring->Stiffness();
80         if (NearZero(cmk)) {
81             if (NearZero(distance)) {
82                 LOGE("create CriticalDamped failed, distance can not be zero.");
83                 return nullptr;
84             }
85             return AceType::MakeRefPtr<CriticalDampedModel>(distance, velocity, spring);
86         } else if (cmk > 0.0) {
87             return AceType::MakeRefPtr<OverdampedModel>(distance, velocity, spring);
88         } else {
89             return AceType::MakeRefPtr<UnderdampedModel>(distance, velocity, spring);
90         }
91     }
92 }
93 
94 // Overdamping calculation model.
CriticalDampedModel(double distance,double velocity,const RefPtr<SpringProperty> & spring)95 CriticalDampedModel::CriticalDampedModel(double distance, double velocity, const RefPtr<SpringProperty>& spring)
96 {
97     if (spring && spring->IsValid() && !NearZero(distance)) {
98         r_ = -spring->Damping() / (LOW_RATIO * spring->Mass());
99         c1_ = distance;
100         c2_ = velocity / (r_ * distance);
101     }
102 }
103 
Position(double time) const104 double CriticalDampedModel::Position(double time) const
105 {
106     return (c1_ + c2_ * time) * exp(r_ * time);
107 }
108 
Velocity(double time) const109 double CriticalDampedModel::Velocity(double time) const
110 {
111     const double power = exp(r_ * time);
112     return r_ * (c1_ + c2_ * time) * power + c2_ * power;
113 }
114 
GetType() const115 SpringModelType CriticalDampedModel::GetType() const
116 {
117     return SpringModelType::CRITICAL_DAMPED;
118 }
119 
120 // Overdamping calculation model.
OverdampedModel(double distance,double velocity,const RefPtr<SpringProperty> & spring)121 OverdampedModel::OverdampedModel(double distance, double velocity, const RefPtr<SpringProperty>& spring)
122 {
123     if (spring && spring->IsValid()) {
124         double cmk = spring->Damping() * spring->Damping() - HIGH_RATIO * spring->Mass() * spring->Stiffness();
125         r1_ = (-spring->Damping() - sqrt(cmk)) / (LOW_RATIO * spring->Mass());
126         r2_ = (-spring->Damping() + sqrt(cmk)) / (LOW_RATIO * spring->Mass());
127         if (!NearEqual(r2_, r1_)) {
128             c2_ = (velocity - r1_ * distance) / (r2_ - r1_);
129             c1_ = distance - c2_;
130         }
131     }
132 }
133 
Position(double time) const134 double OverdampedModel::Position(double time) const
135 {
136     return c1_ * exp(r1_ * time) + c2_ * exp(r2_ * time);
137 }
138 
Velocity(double time) const139 double OverdampedModel::Velocity(double time) const
140 {
141     return c1_ * r1_ * exp(r1_ * time) + c2_ * r2_ * exp(r2_ * time);
142 }
143 
GetType() const144 SpringModelType OverdampedModel::GetType() const
145 {
146     return SpringModelType::OVER_DAMPED;
147 }
148 
149 // Underdamped calculation model
UnderdampedModel(double distance,double velocity,const RefPtr<SpringProperty> & spring)150 UnderdampedModel::UnderdampedModel(double distance, double velocity, const RefPtr<SpringProperty>& spring)
151 {
152     if (spring && spring->IsValid()) {
153         w_ = sqrt(HIGH_RATIO * spring->Mass() * spring->Stiffness() - spring->Damping() * spring->Damping()) /
154              (LOW_RATIO * spring->Mass());
155         r_ = -(spring->Damping() / LOW_RATIO * spring->Mass());
156         c1_ = distance;
157         if (!NearEqual(w_, 0.0)) {
158             c2_ = (velocity - r_ * distance) / w_;
159         }
160     }
161 }
162 
Position(double time) const163 double UnderdampedModel::Position(double time) const
164 {
165     return exp(r_ * time) * (c1_ * cos(w_ * time) + c2_ * sin(w_ * time));
166 }
167 
Velocity(double time) const168 double UnderdampedModel::Velocity(double time) const
169 {
170     double power = exp(r_ * time);
171     double cosine = cos(w_ * time);
172     double sine = sin(w_ * time);
173     return power * (c2_ * w_ * cosine - c1_ * w_ * sine) + r_ * power * (c2_ * sine + c1_ * cosine);
174 }
175 
GetType() const176 SpringModelType UnderdampedModel::GetType() const
177 {
178     return SpringModelType::UNDER_DAMPED;
179 }
180 
181 } // namespace OHOS::Ace