first commit

This commit is contained in:
2025-10-20 00:32:01 +08:00
parent edac742f6a
commit 6ad03fc44f
106 changed files with 52165 additions and 0 deletions

View File

@@ -0,0 +1,54 @@
#include "round-angle.hh"
#include <eigen3/Eigen/Dense>
using namespace creeper;
using Eigen::Vector2d, std::numbers::pi;
static inline auto impl_round_angle_solution(
RoundAngleSolution& solution, Vector2d e0, Vector2d e1, Vector2d e2, double radius) -> void {
// solve the arc origin
const auto v1 = Vector2d { e1 - e0 };
const auto v2 = Vector2d { e2 - e0 };
const auto dot = v1.x() * v2.x() + v1.y() * v2.y();
const auto det = v1.x() * v2.y() - v1.y() * v2.x();
const auto angle = std::abs(std::atan2(det, dot));
const auto width = radius / std::tan(angle / 2);
const auto point_begin = Vector2d { e0 + width * v1.normalized() };
const auto point_end = Vector2d { e0 + width * v2.normalized() };
const auto origin = Vector2d { point_begin + radius * v1.unitOrthogonal() };
solution.start = QPointF { point_begin.x(), point_begin.y() };
solution.end = QPointF { point_end.x(), point_end.y() };
// solve the rect corners
const auto v3 = Vector2d { e0 - origin }.normalized();
const auto v4 = Vector2d { v3.unitOrthogonal() };
const Vector2d corner0 = origin + Vector2d::UnitX() * radius + Vector2d::UnitY() * radius;
const Vector2d corner1 = origin - Vector2d::UnitX() * radius - Vector2d::UnitY() * radius;
solution.rect = QRectF { QPointF(corner1.x(), corner1.y()), QPointF(corner0.x(), corner0.y()) };
// solve the arc angle
// 角度计算时注意Qt的系Y的正方向向下但角度又是从X正方向逆时针开始计算,可谓混乱
const auto angle_begin_vector = Vector2d { point_begin - origin };
const auto angle_end_vector = Vector2d { point_end - origin };
const auto angle_end = std::atan2(-angle_end_vector.y(), angle_end_vector.x());
solution.angle_begin = std::atan2(-angle_begin_vector.y(), angle_begin_vector.x());
solution.angle_length = angle_end - solution.angle_begin;
if (solution.angle_length < -pi) solution.angle_length = 2 * pi + solution.angle_length;
solution.angle_begin = solution.angle_begin * 180 / pi;
solution.angle_length = solution.angle_length * 180 / pi;
}
RoundAngleSolution::RoundAngleSolution(QPointF e0, QPointF e1, QPointF e2, double radius) noexcept {
impl_round_angle_solution(
*this, Eigen::Vector2d { e0.x(), e0.y() }, { e1.x(), e1.y() }, { e2.x(), e2.y() }, radius);
}

View File

@@ -0,0 +1,25 @@
#pragma once
#include <qpoint.h>
#include <qrect.h>
namespace creeper {
struct RoundAngleSolution {
/// @brief 给定原点和端点,按逆时针方向计算圆弧
/// @note 圆弧注意按照逆时针算
/// @param e0 两切线交点
/// @param e1 圆弧起始点切线
/// @param e2 圆弧终点切线
/// @param radius 半径
RoundAngleSolution(QPointF e0, QPointF e1, QPointF e2, double radius) noexcept;
QRectF rect;
QPointF start;
QPointF end;
double angle_begin;
double angle_length;
};
}