mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
380 lines
9.3 KiB
C++
380 lines
9.3 KiB
C++
#ifndef Vectors_hpp
|
|
#define Vectors_hpp
|
|
|
|
#ifdef __cplusplus
|
|
|
|
#include <stdlib.h>
|
|
#include <math.h>
|
|
|
|
#include <LottieCpp/lottiejson11.hpp>
|
|
|
|
namespace lottie {
|
|
|
|
struct Vector1D {
|
|
enum class InternalRepresentationType {
|
|
SingleNumber,
|
|
Array
|
|
};
|
|
|
|
explicit Vector1D(float value_) :
|
|
value(value_) {
|
|
}
|
|
|
|
explicit Vector1D(lottiejson11::Json const &json) noexcept(false);
|
|
lottiejson11::Json toJson() const;
|
|
|
|
float value;
|
|
|
|
float distanceTo(Vector1D const &to) const {
|
|
return abs(to.value - value);
|
|
}
|
|
};
|
|
|
|
float interpolate(float value, float to, float amount);
|
|
|
|
Vector1D interpolate(
|
|
Vector1D const &from,
|
|
Vector1D const &to,
|
|
float amount
|
|
);
|
|
|
|
struct __attribute__((packed)) Vector2D {
|
|
static Vector2D Zero() {
|
|
return Vector2D(0.0, 0.0);
|
|
}
|
|
|
|
Vector2D() :
|
|
x(0.0),
|
|
y(0.0) {
|
|
}
|
|
|
|
explicit Vector2D(float x_, float y_) :
|
|
x(x_),
|
|
y(y_) {
|
|
}
|
|
|
|
explicit Vector2D(lottiejson11::Json const &json) noexcept(false);
|
|
lottiejson11::Json toJson() const;
|
|
|
|
float x;
|
|
float y;
|
|
|
|
Vector2D operator+(Vector2D const &rhs) const {
|
|
return Vector2D(x + rhs.x, y + rhs.y);
|
|
}
|
|
|
|
Vector2D operator-(Vector2D const &rhs) const {
|
|
return Vector2D(x - rhs.x, y - rhs.y);
|
|
}
|
|
|
|
Vector2D operator*(float scalar) const {
|
|
return Vector2D(x * scalar, y * scalar);
|
|
}
|
|
|
|
bool operator==(Vector2D const &rhs) const {
|
|
return x == rhs.x && y == rhs.y;
|
|
}
|
|
|
|
bool operator!=(Vector2D const &rhs) const {
|
|
return !(*this == rhs);
|
|
}
|
|
|
|
bool isZero() const {
|
|
return x == 0.0 && y == 0.0;
|
|
}
|
|
|
|
float distanceTo(Vector2D const &to) const {
|
|
auto deltaX = to.x - x;
|
|
auto deltaY = to.y - y;
|
|
return sqrt(deltaX * deltaX + deltaY * deltaY);
|
|
}
|
|
|
|
bool colinear(Vector2D const &a, Vector2D const &b) const {
|
|
float area = x * (a.y - b.y) + a.x * (b.y - y) + b.x * (y - a.y);
|
|
float accuracy = 0.05;
|
|
if (area < accuracy && area > -accuracy) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
Vector2D pointOnPath(Vector2D const &to, Vector2D const &outTangent, Vector2D const &inTangent, float amount) const;
|
|
|
|
Vector2D interpolate(Vector2D const &to, float amount) const;
|
|
|
|
Vector2D interpolate(
|
|
Vector2D const &to,
|
|
Vector2D const &outTangent,
|
|
Vector2D const &inTangent,
|
|
float amount,
|
|
int maxIterations = 3,
|
|
int samples = 20,
|
|
float accuracy = 1.0
|
|
) const;
|
|
};
|
|
|
|
Vector2D interpolate(
|
|
Vector2D const &from,
|
|
Vector2D const &to,
|
|
float amount
|
|
);
|
|
|
|
struct Vector3D {
|
|
explicit Vector3D(float x_, float y_, float z_) :
|
|
x(x_),
|
|
y(y_),
|
|
z(z_) {
|
|
}
|
|
|
|
explicit Vector3D(lottiejson11::Json const &json) noexcept(false);
|
|
lottiejson11::Json toJson() const;
|
|
|
|
float x = 0.0;
|
|
float y = 0.0;
|
|
float z = 0.0;
|
|
};
|
|
|
|
Vector3D interpolate(
|
|
Vector3D const &from,
|
|
Vector3D const &to,
|
|
float amount
|
|
);
|
|
|
|
inline float degreesToRadians(float value) {
|
|
return value * M_PI / 180.0f;
|
|
}
|
|
|
|
inline float radiansToDegrees(float value) {
|
|
return value * 180.0f / M_PI;
|
|
}
|
|
|
|
struct Transform3D {
|
|
float m11, m12, m13, m14;
|
|
float m21, m22, m23, m24;
|
|
float m31, m32, m33, m34;
|
|
float m41, m42, m43, m44;
|
|
|
|
Transform3D(
|
|
float m11_, float m12_, float m13_, float m14_,
|
|
float m21_, float m22_, float m23_, float m24_,
|
|
float m31_, float m32_, float m33_, float m34_,
|
|
float m41_, float m42_, float m43_, float m44_
|
|
) :
|
|
m11(m11_), m12(m12_), m13(m13_), m14(m14_),
|
|
m21(m21_), m22(m22_), m23(m23_), m24(m24_),
|
|
m31(m31_), m32(m32_), m33(m33_), m34(m34_),
|
|
m41(m41_), m42(m42_), m43(m43_), m44(m44_) {
|
|
}
|
|
|
|
bool operator==(Transform3D const &rhs) const {
|
|
return m11 == rhs.m11 && m12 == rhs.m12 && m13 == rhs.m13 && m14 == rhs.m14 &&
|
|
m21 == rhs.m21 && m22 == rhs.m22 && m23 == rhs.m23 && m24 == rhs.m24 &&
|
|
m31 == rhs.m31 && m32 == rhs.m32 && m33 == rhs.m33 && m34 == rhs.m34 &&
|
|
m41 == rhs.m41 && m42 == rhs.m42 && m43 == rhs.m43 && m44 == rhs.m44;
|
|
}
|
|
|
|
bool operator!=(Transform3D const &rhs) const {
|
|
return !(*this == rhs);
|
|
}
|
|
|
|
inline bool isIdentity() const {
|
|
return m11 == 1.0 && m12 == 0.0 && m13 == 0.0 && m14 == 0.0 &&
|
|
m21 == 0.0 && m22 == 1.0 && m23 == 0.0 && m24 == 0.0 &&
|
|
m31 == 0.0 && m32 == 0.0 && m33 == 1.0 && m34 == 0.0 &&
|
|
m41 == 0.0 && m42 == 0.0 && m43 == 0.0 && m44 == 1.0;
|
|
}
|
|
|
|
static Transform3D makeTranslation(float tx, float ty, float tz) {
|
|
return Transform3D(
|
|
1, 0, 0, 0,
|
|
0, 1, 0, 0,
|
|
0, 0, 1, 0,
|
|
tx, ty, tz, 1
|
|
);
|
|
}
|
|
|
|
static Transform3D makeScale(float sx, float sy, float sz) {
|
|
return Transform3D(
|
|
sx, 0, 0, 0,
|
|
0, sy, 0, 0,
|
|
0, 0, sz, 0,
|
|
0, 0, 0, 1
|
|
);
|
|
}
|
|
|
|
static Transform3D makeRotation(float radians, float x, float y, float z);
|
|
|
|
static Transform3D makeSkew(float skew, float skewAxis) {
|
|
float mCos = cos(degreesToRadians(skewAxis));
|
|
float mSin = sin(degreesToRadians(skewAxis));
|
|
float aTan = tan(degreesToRadians(skew));
|
|
|
|
Transform3D transform1(
|
|
mCos,
|
|
mSin,
|
|
0.0,
|
|
0.0,
|
|
-mSin,
|
|
mCos,
|
|
0.0,
|
|
0.0,
|
|
0.0,
|
|
0.0,
|
|
1.0,
|
|
0.0,
|
|
0.0,
|
|
0.0,
|
|
0.0,
|
|
1.0
|
|
);
|
|
|
|
Transform3D transform2(
|
|
1.0,
|
|
0.0,
|
|
0.0,
|
|
0.0,
|
|
aTan,
|
|
1.0,
|
|
0.0,
|
|
0.0,
|
|
0.0,
|
|
0.0,
|
|
1.0,
|
|
0.0,
|
|
0.0,
|
|
0.0,
|
|
0.0,
|
|
1.0
|
|
);
|
|
|
|
Transform3D transform3(
|
|
mCos,
|
|
-mSin,
|
|
0.0,
|
|
0.0,
|
|
mSin,
|
|
mCos,
|
|
0.0,
|
|
0.0,
|
|
0.0,
|
|
0.0,
|
|
1.0,
|
|
0.0,
|
|
0.0,
|
|
0.0,
|
|
0.0,
|
|
1.0
|
|
);
|
|
|
|
return transform3 * transform2 * transform1;
|
|
}
|
|
|
|
static Transform3D makeTransform(
|
|
Vector2D const &anchor,
|
|
Vector2D const &position,
|
|
Vector2D const &scale,
|
|
float rotation,
|
|
std::optional<float> skew,
|
|
std::optional<float> skewAxis
|
|
) {
|
|
Transform3D result = Transform3D::identity();
|
|
if (skew.has_value() && skewAxis.has_value()) {
|
|
result = Transform3D::identity().translated(position).rotated(rotation).skewed(-skew.value(), skewAxis.value()).scaled(Vector2D(scale.x * 0.01, scale.y * 0.01)).translated(Vector2D(-anchor.x, -anchor.y));
|
|
} else {
|
|
result = Transform3D::identity().translated(position).rotated(rotation).scaled(Vector2D(scale.x * 0.01, scale.y * 0.01)).translated(Vector2D(-anchor.x, -anchor.y));
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
Transform3D rotated(float degrees) const;
|
|
|
|
Transform3D translated(Vector2D const &translation) const;
|
|
|
|
Transform3D scaled(Vector2D const &scale) const;
|
|
|
|
Transform3D skewed(float skew, float skewAxis) const {
|
|
return Transform3D::makeSkew(skew, skewAxis) * (*this);
|
|
}
|
|
|
|
static Transform3D const &identity() {
|
|
return _identity;
|
|
}
|
|
|
|
Transform3D operator*(Transform3D const &b) const;
|
|
|
|
bool isInvertible() const;
|
|
|
|
Transform3D inverted() const;
|
|
|
|
private:
|
|
static Transform3D _identity;
|
|
};
|
|
|
|
struct CGRect {
|
|
explicit CGRect(float x_, float y_, float width_, float height_) :
|
|
x(x_), y(y_), width(width_), height(height_) {
|
|
}
|
|
|
|
float x = 0.0f;
|
|
float y = 0.0f;
|
|
float width = 0.0f;
|
|
float height = 0.0f;
|
|
|
|
static CGRect veryLarge() {
|
|
return CGRect(
|
|
-100000000.0f,
|
|
-100000000.0f,
|
|
200000000.0f,
|
|
200000000.0f
|
|
);
|
|
}
|
|
|
|
bool operator==(CGRect const &rhs) const {
|
|
return x == rhs.x && y == rhs.y && width == rhs.width && height == rhs.height;
|
|
}
|
|
|
|
bool operator!=(CGRect const &rhs) const {
|
|
return !(*this == rhs);
|
|
}
|
|
|
|
bool empty() const {
|
|
return width <= 0.0 || height <= 0.0;
|
|
}
|
|
|
|
CGRect insetBy(float dx, float dy) const {
|
|
CGRect result = *this;
|
|
|
|
result.x += dx;
|
|
result.y += dy;
|
|
result.width -= dx * 2.0f;
|
|
result.height -= dy * 2.0f;
|
|
|
|
return result;
|
|
}
|
|
|
|
bool intersects(CGRect const &other) const;
|
|
bool contains(CGRect const &other) const;
|
|
|
|
CGRect intersection(CGRect const &other) const;
|
|
CGRect unionWith(CGRect const &other) const;
|
|
|
|
CGRect applyingTransform(Transform3D const &transform) const;
|
|
};
|
|
|
|
inline bool isInRangeOrEqual(float value, float from, float to) {
|
|
return from <= value && value <= to;
|
|
}
|
|
|
|
inline bool isInRange(float value, float from, float to) {
|
|
return from < value && value < to;
|
|
}
|
|
|
|
float cubicBezierInterpolate(float value, Vector2D const &P0, Vector2D const &P1, Vector2D const &P2, Vector2D const &P3);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif /* Vectors_hpp */
|