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 <iostream>
#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:
virtual ~ILineParam() = default;
};
struct PolylineParam : ILineParam {
int segIdx;
real tOnSeg;
};
virtual ~ILine() = default;
struct PolynomialLineParam : ILineParam {
real t;
};
virtual Vec3 eval(const double param) const = 0;
class ILine {
public:
virtual ~ILine() = default;
virtual Vec3 tangent(const double param) const = 0;
virtual Vec3 eval(const ILineParam& param) const = 0;
virtual Vec3 tangent(const ILineParam& param) const = 0;
virtual std::unique_ptr<ILineParam> getClosestParam(const Vec3& p) const = 0;
virtual double getClosestParam(const Vec3 &p) const = 0;
};
template<size_t N>
@ -32,42 +36,69 @@ using PtArray = std::vector<Vec<N> >;
using Pt3Array = PtArray<3>;
using Pt2Array = PtArray<2>;
template<size_t N>
class Polyline: public ILine {
class Polyline : public ILine {
public:
Polyline(const PtArray<N> &points, const std::vector<double> &bugles, bool closed = false) : points(points),
bugles(bugles), closed(closed) {
using Point = Vec<3>;
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);
if (closed) {
assert(points.size() == bugles.size());
} 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:
PtArray<N> points;
std::vector<double> bugles;
Pt3Array points;
std::vector<real> bugles;
Vec3 normal;
bool closed;
Pt3Array circleCenters;
std::vector<real> thetas;
std::vector<real> radii;
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 PolylineParam* polyParam = dynamic_cast<const PolylineParam*>(&param); // 进行类型检查
if (!polyParam) {
throw std::invalid_argument("Invalid parameter type for Polyline::eval");
}
// TODO:
const auto &A = points[seg];
// const auto &B = points[(seg + 1) % points.size()];
const auto &center = circleCenters[seg];
Vec3 u = (A-center).normalize();
Vec3 v = normal.cross(u);
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:
}
std::unique_ptr<ILineParam> getClosestParam(const Vec3& p) const override {
auto closestParam = std::make_unique<PolylineParam>();
double getClosestParam(const Vec3 &p) const override {
// TODO:
return closestParam;
}
@ -76,8 +107,6 @@ public:
points.push_back(point);
}
const Point &getPoint(size_t index) const {
return points[index];
}
@ -103,6 +132,6 @@ public:
}
};
class PolynomialLine: public ILine {
class PolynomialLine : public ILine {
public:
};
};

111
include/vec.hpp

@ -2,11 +2,11 @@
#include "real.hpp"
#include <cmath>
#include <array>
#include <assert.h>
template <size_t N>
template<size_t N>
class Vec {
public:
using real = float; // 根据需要定义 real 类型
std::array<real, N> data;
Vec() {
@ -17,24 +17,26 @@ public:
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;
}
Vec<N>& operator=(const Vec<N>& v) {
Vec<N> &operator=(const Vec<N> &v) {
data = v.data;
return *this;
}
real& operator[](size_t index) {
real &operator[](size_t index) {
return data[index];
}
const real& operator[](size_t index) const {
const real &operator[](size_t index) const {
return data[index];
}
Vec<N> operator+(const Vec<N>& v) const {
Vec<N> operator+(const Vec<N> &v) const {
Vec<N> result;
for (size_t i = 0; i < N; ++i) {
result[i] = data[i] + v[i];
@ -42,7 +44,7 @@ public:
return result;
}
Vec<N> operator-(const Vec<N>& v) const {
Vec<N> operator-(const Vec<N> &v) const {
Vec<N> result;
for (size_t i = 0; i < N; ++i) {
result[i] = data[i] - v[i];
@ -58,6 +60,15 @@ public:
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> result;
for (size_t i = 0; i < N; ++i) {
@ -66,7 +77,7 @@ public:
return result;
}
real dot(const Vec<N>& v) const {
real dot(const Vec<N> &v) const {
real sum = 0;
for (size_t i = 0; i < N; ++i) {
sum += data[i] * v[i];
@ -82,12 +93,88 @@ public:
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);
}
};
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 Vec3 = Vec<3>;
@ -141,4 +228,4 @@ using Vec3 = Vec<3>;
// Vec3 reflect(const Vec3& n) const {
// return *this - n * 2 * dot(n);
// }
//};
//};

Loading…
Cancel
Save