You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

138 lines
3.4 KiB

7 months ago
#pragma once
#include "vec.hpp"
#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;
// };
7 months ago
class ILine {
7 months ago
public:
virtual ~ILine() = default;
7 months ago
virtual Vec3 eval(const double param) const = 0;
7 months ago
virtual Vec3 tangent(const double param) const = 0;
7 months ago
virtual double getClosestParam(const Vec3 &p) const = 0;
7 months ago
};
template<size_t N>
using PtArray = std::vector<Vec<N> >;
using Pt3Array = PtArray<3>;
using Pt2Array = PtArray<2>;
class Polyline : public ILine {
7 months ago
public:
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()) {
7 months ago
assert(points.size() >= 2);
if (closed) {
assert(points.size() == bugles.size());
} else {
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();
7 months ago
}
}
private:
Pt3Array points;
std::vector<real> bugles;
Vec3 normal;
7 months ago
bool closed;
Pt3Array circleCenters;
std::vector<real> thetas;
std::vector<real> radii;
7 months ago
public:
Vec3 eval(const real param) const override {
assert(param >= 0 && param <= bugles.size());
int seg = static_cast<int>(param);
real tOnSeg = param - seg;
7 months ago
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));
7 months ago
}
Vec3 tangent(const double param) const override {
7 months ago
// TODO:
}
double getClosestParam(const Vec3 &p) const override {
7 months ago
// TODO:
return closestParam;
}
void addPoint(const Point &point) {
points.push_back(point);
}
const Point &getPoint(size_t index) const {
return points[index];
}
size_t size() const {
return points.size();
}
void clear() {
points.clear();
}
void print() const {
for (const auto &point: points) {
std::cout << "(";
for (size_t i = 0; i < N; ++i) {
std::cout << point[i];
if (i < N - 1) std::cout << ", ";
}
std::cout << ") ";
}
std::cout << std::endl;
}
};
class PolynomialLine : public ILine {
7 months ago
public:
};