v0.1.0: 初始工程骨架 — 7模块 40头文件 32源文件 17文档 Apache-2.0
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
#pragma once
|
||||
#include "vde/core/point.h"
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
|
||||
namespace vde::core {
|
||||
|
||||
template <typename T>
|
||||
class AABB {
|
||||
public:
|
||||
AABB() : min_(Point3D::Constant(std::numeric_limits<T>::max())),
|
||||
max_(Point3D::Constant(std::numeric_limits<T>::lowest())) {}
|
||||
|
||||
AABB(const Point3D& min, const Point3D& max) : min_(min), max_(max) {}
|
||||
|
||||
void expand(const Point3D& p) {
|
||||
min_ = min_.cwiseMin(p);
|
||||
max_ = max_.cwiseMax(p);
|
||||
}
|
||||
|
||||
void expand(const AABB& other) {
|
||||
min_ = min_.cwiseMin(other.min_);
|
||||
max_ = max_.cwiseMax(other.max_);
|
||||
}
|
||||
|
||||
[[nodiscard]] Point3D center() const { return (min_ + max_) * 0.5; }
|
||||
[[nodiscard]] Vector3D extent() const { return max_ - min_; }
|
||||
[[nodiscard]] T surface_area() const {
|
||||
Vector3D e = extent();
|
||||
return 2.0 * (e.x() * e.y() + e.y() * e.z() + e.z() * e.x());
|
||||
}
|
||||
[[nodiscard]] T volume() const {
|
||||
Vector3D e = extent();
|
||||
return e.x() * e.y() * e.z();
|
||||
}
|
||||
[[nodiscard]] bool contains(const Point3D& p) const {
|
||||
return (p.array() >= min_.array()).all() && (p.array() <= max_.array()).all();
|
||||
}
|
||||
[[nodiscard]] bool intersects(const AABB& other) const {
|
||||
return (min_.array() <= other.max_.array()).all()
|
||||
&& (max_.array() >= other.min_.array()).all();
|
||||
}
|
||||
|
||||
[[nodiscard]] const Point3D& min() const { return min_; }
|
||||
[[nodiscard]] const Point3D& max() const { return max_; }
|
||||
|
||||
private:
|
||||
Point3D min_, max_;
|
||||
};
|
||||
|
||||
using AABB3D = AABB<double>;
|
||||
using AABB3f = AABB<float>;
|
||||
|
||||
} // namespace vde::core
|
||||
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
#include "vde/core/point.h"
|
||||
#include <vector>
|
||||
|
||||
namespace vde::core {
|
||||
|
||||
/// 2D convex hull — Graham scan, O(n log n)
|
||||
std::vector<Point2D> convex_hull_2d(const std::vector<Point2D>& points);
|
||||
|
||||
/// 3D convex hull — QuickHull
|
||||
/// Returns triangles of the hull (counter-clockwise when viewed from outside)
|
||||
std::vector<std::array<Point3D, 3>> convex_hull_3d(const std::vector<Point3D>& points);
|
||||
|
||||
} // namespace vde::core
|
||||
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
#include "vde/core/point.h"
|
||||
#include "vde/core/line.h"
|
||||
#include "vde/core/plane.h"
|
||||
#include "vde/core/triangle.h"
|
||||
|
||||
namespace vde::core {
|
||||
|
||||
double distance(const Point3D& a, const Point3D& b);
|
||||
double distance(const Point3D& p, const Line3D<double>& line);
|
||||
double distance(const Point3D& p, const Segment3D<double>& seg);
|
||||
double distance(const Point3D& p, const Plane<double>& plane);
|
||||
double distance(const Point3D& p, const Triangle<double>& tri);
|
||||
|
||||
Point3D closest_point(const Point3D& p, const Triangle<double>& tri);
|
||||
Point3D closest_point(const Point3D& p, const Segment3D<double>& seg);
|
||||
|
||||
} // namespace vde::core
|
||||
@@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
#include "vde/core/point.h"
|
||||
|
||||
namespace vde::core {
|
||||
|
||||
template <typename T>
|
||||
class Line3D {
|
||||
public:
|
||||
Line3D() = default;
|
||||
Line3D(const Point3D& origin, const Vector3D& direction)
|
||||
: origin_(origin), direction_(direction.normalized()) {}
|
||||
|
||||
[[nodiscard]] const Point3D& origin() const { return origin_; }
|
||||
[[nodiscard]] const Vector3D& direction() const { return direction_; }
|
||||
[[nodiscard]] Point3D point_at(T t) const { return origin_ + direction_ * t; }
|
||||
|
||||
private:
|
||||
Point3D origin_{0,0,0};
|
||||
Vector3D direction_{1,0,0};
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class Segment3D {
|
||||
public:
|
||||
Segment3D() = default;
|
||||
Segment3D(const Point3D& p0, const Point3D& p1) : p0_(p0), p1_(p1) {}
|
||||
|
||||
[[nodiscard]] const Point3D& p0() const { return p0_; }
|
||||
[[nodiscard]] const Point3D& p1() const { return p1_; }
|
||||
[[nodiscard]] Vector3D direction() const { return p1_ - p0_; }
|
||||
[[nodiscard]] T length() const { return direction().norm(); }
|
||||
|
||||
private:
|
||||
Point3D p0_{0,0,0}, p1_{0,0,0};
|
||||
};
|
||||
|
||||
using Line3Dd = Line3D<double>;
|
||||
using Segment3Dd = Segment3D<double>;
|
||||
|
||||
} // namespace vde::core
|
||||
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
#include "vde/core/point.h"
|
||||
|
||||
namespace vde::core {
|
||||
|
||||
template <typename T>
|
||||
class Plane {
|
||||
public:
|
||||
Plane() = default;
|
||||
Plane(const Point3D& point, const Vector3D& normal)
|
||||
: normal_(normal.normalized()), d_(-normal_.dot(point)) {}
|
||||
Plane(const Point3D& a, const Point3D& b, const Point3D& c)
|
||||
: Plane(a, (b - a).cross(c - a)) {}
|
||||
|
||||
[[nodiscard]] const Vector3D& normal() const { return normal_; }
|
||||
[[nodiscard]] T d() const { return d_; }
|
||||
[[nodiscard]] T signed_distance(const Point3D& p) const { return normal_.dot(p) + d_; }
|
||||
[[nodiscard]] T distance(const Point3D& p) const { return std::abs(signed_distance(p)); }
|
||||
[[nodiscard]] Point3D project(const Point3D& p) const {
|
||||
return p - normal_ * signed_distance(p);
|
||||
}
|
||||
|
||||
private:
|
||||
Vector3D normal_{0,0,1};
|
||||
T d_{0};
|
||||
};
|
||||
|
||||
using Plane3D = Plane<double>;
|
||||
|
||||
} // namespace vde::core
|
||||
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
#include "vde/foundation/math_types.h"
|
||||
#include "vde/foundation/tolerance.h"
|
||||
|
||||
namespace vde::core {
|
||||
|
||||
template <typename T, size_t Dim>
|
||||
using Point = foundation::Point<T, Dim>;
|
||||
|
||||
using Point2D = foundation::Point2D;
|
||||
using Point3D = foundation::Point3D;
|
||||
using Point2f = foundation::Point2f;
|
||||
using Point3f = foundation::Point3f;
|
||||
|
||||
template <typename T, size_t Dim>
|
||||
using Vector = foundation::Vector<T, Dim>;
|
||||
|
||||
using Vector2D = foundation::Vector2D;
|
||||
using Vector3D = foundation::Vector3D;
|
||||
|
||||
} // namespace vde::core
|
||||
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
#include "vde/core/point.h"
|
||||
#include <vector>
|
||||
|
||||
namespace vde::core {
|
||||
|
||||
class Polygon2D {
|
||||
public:
|
||||
Polygon2D() = default;
|
||||
explicit Polygon2D(std::vector<Point2D> vertices) : vertices_(std::move(vertices)) {}
|
||||
|
||||
[[nodiscard]] const std::vector<Point2D>& vertices() const { return vertices_; }
|
||||
[[nodiscard]] size_t size() const { return vertices_.size(); }
|
||||
[[nodiscard]] bool empty() const { return vertices_.empty(); }
|
||||
|
||||
/// Signed area (positive = CCW)
|
||||
[[nodiscard]] double signed_area() const;
|
||||
|
||||
/// Absolute area
|
||||
[[nodiscard]] double area() const { return std::abs(signed_area()); }
|
||||
|
||||
/// Point-in-polygon test (ray casting)
|
||||
[[nodiscard]] bool contains(const Point2D& p) const;
|
||||
|
||||
/// Is the polygon counter-clockwise?
|
||||
[[nodiscard]] bool is_ccw() const { return signed_area() > 0; }
|
||||
|
||||
private:
|
||||
std::vector<Point2D> vertices_;
|
||||
};
|
||||
|
||||
} // namespace vde::core
|
||||
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
#include "vde/core/point.h"
|
||||
#include <Eigen/Geometry>
|
||||
|
||||
namespace vde::core {
|
||||
|
||||
using Transform3D = Eigen::Transform<double, 3, Eigen::Affine>;
|
||||
|
||||
inline Transform3D translate(const Vector3D& v) {
|
||||
return Transform3D(Eigen::Translation<double, 3>(v));
|
||||
}
|
||||
inline Transform3D translate(double x, double y, double z) {
|
||||
return translate(Vector3D(x, y, z));
|
||||
}
|
||||
inline Transform3D rotate(const Vector3D& axis, double angle_rad) {
|
||||
return Transform3D(Eigen::AngleAxis<double>(angle_rad, axis.normalized()));
|
||||
}
|
||||
inline Transform3D rotate_x(double rad) { return rotate(Vector3D::UnitX(), rad); }
|
||||
inline Transform3D rotate_y(double rad) { return rotate(Vector3D::UnitY(), rad); }
|
||||
inline Transform3D rotate_z(double rad) { return rotate(Vector3D::UnitZ(), rad); }
|
||||
inline Transform3D scale(double sx, double sy, double sz) {
|
||||
return Transform3D(Eigen::Scaling(sx, sy, sz));
|
||||
}
|
||||
inline Transform3D scale(double s) { return scale(s, s, s); }
|
||||
|
||||
} // namespace vde::core
|
||||
@@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
#include "vde/core/point.h"
|
||||
#include <array>
|
||||
|
||||
namespace vde::core {
|
||||
|
||||
template <typename T>
|
||||
class Triangle {
|
||||
public:
|
||||
Triangle() = default;
|
||||
Triangle(const Point3D& v0, const Point3D& v1, const Point3D& v2)
|
||||
: v_{v0, v1, v2} {}
|
||||
|
||||
[[nodiscard]] const Point3D& v(int i) const { return v_[i]; }
|
||||
[[nodiscard]] const std::array<Point3D, 3>& vertices() const { return v_; }
|
||||
[[nodiscard]] Vector3D normal() const {
|
||||
return (v_[1] - v_[0]).cross(v_[2] - v_[0]).normalized();
|
||||
}
|
||||
[[nodiscard]] T area() const {
|
||||
return (v_[1] - v_[0]).cross(v_[2] - v_[0]).norm() * 0.5;
|
||||
}
|
||||
[[nodiscard]] Point3D centroid() const {
|
||||
return (v_[0] + v_[1] + v_[2]) / 3.0;
|
||||
}
|
||||
[[nodiscard]] bool contains(const Point3D& p) const {
|
||||
Vector3D v0 = v_[2] - v_[0], v1 = v_[1] - v_[0], v2 = p - v_[0];
|
||||
T d00 = v0.dot(v0), d01 = v0.dot(v1), d11 = v1.dot(v1);
|
||||
T d20 = v2.dot(v0), d21 = v2.dot(v1);
|
||||
T denom = d00 * d11 - d01 * d01;
|
||||
T v = (d11 * d20 - d01 * d21) / denom;
|
||||
T w = (d00 * d21 - d01 * d20) / denom;
|
||||
return v >= 0 && w >= 0 && v + w <= 1;
|
||||
}
|
||||
|
||||
private:
|
||||
std::array<Point3D, 3> v_{};
|
||||
};
|
||||
|
||||
using Triangle3D = Triangle<double>;
|
||||
using Triangle3f = Triangle<float>;
|
||||
|
||||
} // namespace vde::core
|
||||
Reference in New Issue
Block a user