aboutsummaryrefslogtreecommitdiff
path: root/src/platform/graphics/Geometry.cpp
diff options
context:
space:
mode:
authorYuqian Yang <crupest@crupest.life>2025-09-21 23:40:30 +0800
committerYuqian Yang <crupest@crupest.life>2025-12-18 23:25:06 +0800
commitc3412099485e06109f83b3105ce6c083c2b65dd1 (patch)
tree3ae2ad9026cf1c3279a6cac00d7726ed684de8db /src/platform/graphics/Geometry.cpp
parent6bbadfc6b1eaf14f68a27cb8e378f5e09ab38de6 (diff)
downloadcru-c3412099485e06109f83b3105ce6c083c2b65dd1.tar.gz
cru-c3412099485e06109f83b3105ce6c083c2b65dd1.tar.bz2
cru-c3412099485e06109f83b3105ce6c083c2b65dd1.zip
HALF WORK!geo-arc
Diffstat (limited to 'src/platform/graphics/Geometry.cpp')
-rw-r--r--src/platform/graphics/Geometry.cpp52
1 files changed, 49 insertions, 3 deletions
diff --git a/src/platform/graphics/Geometry.cpp b/src/platform/graphics/Geometry.cpp
index 859a7bd6..e92ea3c9 100644
--- a/src/platform/graphics/Geometry.cpp
+++ b/src/platform/graphics/Geometry.cpp
@@ -1,10 +1,14 @@
#include "cru/platform/graphics/Geometry.h"
-
#include "cru/base/StringUtil.h"
+#include "cru/base/log/Logger.h"
+#include "cru/platform/GraphicsBase.h"
+#include "cru/platform/Matrix.h"
#include "cru/platform/graphics/Factory.h"
#include <cmath>
+#include <numbers>
#include <unordered_set>
+#include <utility>
namespace cru::platform::graphics {
bool IGeometry::StrokeContains(float width, const Point& point) {
@@ -19,6 +23,48 @@ std::unique_ptr<IGeometry> IGeometry::CreateStrokeGeometry(
"not supported on this platform.");
}
+IGeometryBuilder::ArcInfo IGeometryBuilder::CalculateArcInfo(
+ const Point& start_point, const Point& radius, float angle,
+ bool is_large_arc, bool is_clockwise, const Point& end_point) {
+ using std::swap;
+
+ auto matrix =
+ Matrix::Rotation(-angle) * Matrix::Scale(1 / radius.x, 1 / radius.y);
+ auto s1 = matrix.TransformPoint(start_point),
+ s2 = matrix.TransformPoint(end_point);
+
+ if (!is_clockwise) {
+ std::swap(s1, s2);
+ }
+
+ auto mid = (s1 + s2) / 2;
+ auto d = s1.Distance(s2) / 2;
+ if (d > 1) {
+ CruLogWarn(kLogTag, "Invalid Arc.");
+ return {};
+ }
+
+ auto dc = std::sqrt(1 - d * d);
+ auto a = std::atan2(s1.x - s2.x, s2.y - s1.y);
+ Point center(mid.x - dc * std::cos(a), mid.y - dc * std::sin(a));
+
+ if (std::abs(center.x) < 0.000001) {
+ center.x = 0.f;
+ }
+ if (std::abs(center.y) < 0.000001) {
+ center.y = 0.f;
+ }
+
+ auto a1 = std::atan2(s1.y - center.y, s1.x - center.x);
+ auto a2 = std::atan2(s2.y - center.y, s2.x - center.x);
+ auto a3 = a2 > a1 ? a2 - a1 : std::numbers::pi_v<float> * 2 - (a1 - a2);
+ if ((a3 > std::numbers::pi_v<float>) != is_large_arc) {
+ std::swap(a1, a2);
+ }
+
+ return {matrix.Inverted()->TransformPoint(center), a1, a2};
+}
+
void IGeometryBuilder::RelativeMoveTo(const Point& offset) {
MoveTo(GetCurrentPosition() + offset);
}
@@ -233,9 +279,9 @@ void IGeometryBuilder::ParseAndApplySvgPathData(std::string_view path_d) {
++position;
}
-
auto result = cru::string::ParseToNumber<float>(
- path_d.substr(position), cru::string::ParseToNumberFlags::AllowTrailingJunk);
+ path_d.substr(position),
+ cru::string::ParseToNumberFlags::AllowTrailingJunk);
if (!result.valid) throw Exception("Invalid svg path data number.");