|
|
@ -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*>(¶m); // 进行类型检查
|
|
|
|
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 ¢er = 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: |
|
|
|
}; |
|
|
|
}; |
|
|
|