Browse Source

refactor line geometry def; solve circle & eval for polylines with bugles

master
Dtouch 4 months ago
parent
commit
c89448b3ed
  1. 107
      include/line.hpp
  2. 111
      include/vec.hpp

107
include/line.hpp

@ -3,28 +3,32 @@
#include <vector> #include <vector>
#include <iostream> #include <iostream>
#include <memory> #include <memory>
#include <cassert>
#include <cmath>
// class ILineParam {
// public:
// virtual ~ILineParam() = default;
// };
//
// class PolylineParam : ILineParam {
// int segIdx;
// real tOnSeg;
// };
//
// class PolynomialLineParam : ILineParam {
// real t;
// };
class ILineParam { class ILine {
public: public:
virtual ~ILineParam() = default; virtual ~ILine() = default;
};
struct PolylineParam : ILineParam {
int segIdx;
real tOnSeg;
};
struct PolynomialLineParam : ILineParam { virtual Vec3 eval(const double param) const = 0;
real t;
};
class ILine { virtual Vec3 tangent(const double param) const = 0;
public:
virtual ~ILine() = default;
virtual Vec3 eval(const ILineParam& param) const = 0; virtual double getClosestParam(const Vec3 &p) const = 0;
virtual Vec3 tangent(const ILineParam& param) const = 0;
virtual std::unique_ptr<ILineParam> getClosestParam(const Vec3& p) const = 0;
}; };
template<size_t N> template<size_t N>
@ -32,42 +36,69 @@ using PtArray = std::vector<Vec<N> >;
using Pt3Array = PtArray<3>; using Pt3Array = PtArray<3>;
using Pt2Array = PtArray<2>; using Pt2Array = PtArray<2>;
template<size_t N>
class Polyline: public ILine { class Polyline : public ILine {
public: public:
Polyline(const PtArray<N> &points, const std::vector<double> &bugles, bool closed = false) : points(points), using Point = Vec<3>;
bugles(bugles), closed(closed) {
Polyline(const Pt3Array &points, const std::vector<double> &bugles, const Vec3 &normal, bool closed = false)
: points(points), bugles(bugles), closed(closed), normal(normal.normalize()) {
assert(points.size() >= 2); assert(points.size() >= 2);
if (closed) { if (closed) {
assert(points.size() == bugles.size()); assert(points.size() == bugles.size());
} else { } else {
assert(points.size() - 1 == bugles.size() || points.size() == bugles.size()); assert(points.size() - 1 == bugles.size());
}
circleCenters.resize(bugles.size());
thetas.resize(bugles.size());
radii.resize(bugles.size());
for (size_t i = 0; i < bugles.size(); ++i) {
const Point &A = points[i];
const Point &B = points[(i + 1) % points.size()];
Vec3 AB = B - A;
Vec3 ABNorm = AB.normalize();
Vec3 QO = normal.cross(ABNorm) * (abs(bugles[i]) > 1 ? -1 : 1);
float theta = std::atan(bugles[i]) * 4;
float h = AB.length() * 0.5 * std::tan(theta * 0.5);
circleCenters[i] = A + AB * 0.5 + QO * h;
thetas[i] = theta;
radii[i] = (circleCenters[i] - A).length();
} }
} }
using Point = Vec<N>;
private: private:
PtArray<N> points; Pt3Array points;
std::vector<double> bugles; std::vector<real> bugles;
Vec3 normal;
bool closed; bool closed;
Pt3Array circleCenters;
std::vector<real> thetas;
std::vector<real> radii;
public: public:
Vec3 eval(const real param) const override {
assert(param >= 0 && param <= bugles.size());
int seg = static_cast<int>(param);
real tOnSeg = param - seg;
Vec3 eval(const ILineParam& param) const override { const auto &A = points[seg];
const PolylineParam* polyParam = dynamic_cast<const PolylineParam*>(&param); // 进行类型检查 // const auto &B = points[(seg + 1) % points.size()];
if (!polyParam) { const auto &center = circleCenters[seg];
throw std::invalid_argument("Invalid parameter type for Polyline::eval"); Vec3 u = (A-center).normalize();
} Vec3 v = normal.cross(u);
// TODO:
real phi = tOnSeg * thetas[seg];
const auto &r = radii[seg];
return center + r * (u * std::cos(phi) + v * std::sin(phi));
} }
Vec3 tangent(const ILineParam& param) const override { Vec3 tangent(const double param) const override {
// TODO: // TODO:
} }
std::unique_ptr<ILineParam> getClosestParam(const Vec3& p) const override { double getClosestParam(const Vec3 &p) const override {
auto closestParam = std::make_unique<PolylineParam>();
// TODO: // TODO:
return closestParam; return closestParam;
} }
@ -76,8 +107,6 @@ public:
points.push_back(point); points.push_back(point);
} }
const Point &getPoint(size_t index) const { const Point &getPoint(size_t index) const {
return points[index]; return points[index];
} }
@ -103,6 +132,6 @@ public:
} }
}; };
class PolynomialLine: public ILine { class PolynomialLine : public ILine {
public: public:
}; };

111
include/vec.hpp

@ -2,11 +2,11 @@
#include "real.hpp" #include "real.hpp"
#include <cmath> #include <cmath>
#include <array> #include <array>
#include <assert.h>
template <size_t N> template<size_t N>
class Vec { class Vec {
public: public:
using real = float; // 根据需要定义 real 类型
std::array<real, N> data; std::array<real, N> data;
Vec() { Vec() {
@ -17,24 +17,26 @@ public:
std::copy(values.begin(), values.end(), data.begin()); std::copy(values.begin(), values.end(), data.begin());
} }
Vec(const Vec<N>& v) { Vec(real... args) : data{static_cast<real>(args)...} {}
Vec(const Vec<N> &v) {
data = v.data; data = v.data;
} }
Vec<N>& operator=(const Vec<N>& v) { Vec<N> &operator=(const Vec<N> &v) {
data = v.data; data = v.data;
return *this; return *this;
} }
real& operator[](size_t index) { real &operator[](size_t index) {
return data[index]; return data[index];
} }
const real& operator[](size_t index) const { const real &operator[](size_t index) const {
return data[index]; return data[index];
} }
Vec<N> operator+(const Vec<N>& v) const { Vec<N> operator+(const Vec<N> &v) const {
Vec<N> result; Vec<N> result;
for (size_t i = 0; i < N; ++i) { for (size_t i = 0; i < N; ++i) {
result[i] = data[i] + v[i]; result[i] = data[i] + v[i];
@ -42,7 +44,7 @@ public:
return result; return result;
} }
Vec<N> operator-(const Vec<N>& v) const { Vec<N> operator-(const Vec<N> &v) const {
Vec<N> result; Vec<N> result;
for (size_t i = 0; i < N; ++i) { for (size_t i = 0; i < N; ++i) {
result[i] = data[i] - v[i]; result[i] = data[i] - v[i];
@ -58,6 +60,15 @@ public:
return result; return result;
} }
friend Vec<N> operator*(real s, const Vec<N> &v) {
Vec<N> result;
for (size_t i = 0; i < N; ++i) {
result[i] = s * v[i];
}
return result;
}
Vec<N> operator/(real s) const { Vec<N> operator/(real s) const {
Vec<N> result; Vec<N> result;
for (size_t i = 0; i < N; ++i) { for (size_t i = 0; i < N; ++i) {
@ -66,7 +77,7 @@ public:
return result; return result;
} }
real dot(const Vec<N>& v) const { real dot(const Vec<N> &v) const {
real sum = 0; real sum = 0;
for (size_t i = 0; i < N; ++i) { for (size_t i = 0; i < N; ++i) {
sum += data[i] * v[i]; sum += data[i] * v[i];
@ -82,12 +93,88 @@ public:
return *this / norm(); return *this / norm();
} }
Vec<N> reflect(const Vec<N>& n) const { Vec<N> reflect(const Vec<N> &n) const {
return *this - n * 2 * dot(n); return *this - n * 2 * dot(n);
} }
}; };
template <size_t N>
// specialize template class Vec<3>;
template<>
class Vec<3> {
public:
union {
std::array<real, 3> data;
struct {
real x, y, z;
};
struct {
real u, v, w;
};
};
Vec() : data{0, 0, 0} {}
Vec(real x, real y, real z) : data{x, y, z} {}
Vec(const Vec &v) : data{v.data[0], v.data[1], v.data[2]} {}
Vec &operator=(const Vec &v) {
data[0] = v.data[0];
data[1] = v.data[1];
data[2] = v.data[2];
return *this;
}
real operator[](size_t index) const {
return data[index];
}
real &operator[](size_t index) {
return data[index];
}
Vec operator+(const Vec &v) const {
return {x + v.x, y + v.y, z + v.z};
}
Vec operator-(const Vec &v) const {
return {x - v.x, y - v.y, z - v.z};
}
Vec operator*(real s) const {
return {x * s, y * s, z * s};
}
friend Vec operator*(real s, const Vec &v) {
return {s * v.x, s * v.y, s * v.z};
}
Vec operator/(real s) const {
assert(s != 0);
real inv = 1 / s;
return *this * inv;
}
real dot(const Vec &v) const {
return x * v.x + y * v.y + z * v.z;
}
real length() const {
return std::sqrt(dot(*this));
}
Vec normalize() const {
return *this / length();
}
Vec cross(const Vec &v) const {
return {y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x};
}
};
using Vec2 = Vec<2>; using Vec2 = Vec<2>;
using Vec3 = Vec<3>; using Vec3 = Vec<3>;
@ -141,4 +228,4 @@ using Vec3 = Vec<3>;
// Vec3 reflect(const Vec3& n) const { // Vec3 reflect(const Vec3& n) const {
// return *this - n * 2 * dot(n); // return *this - n * 2 * dot(n);
// } // }
//}; //};

Loading…
Cancel
Save