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.
 
 

101 lines
3.0 KiB

#pragma once
#include <real.hpp>
#include <utility>
#include <vec.hpp>
#include <line.hpp>
class ISolid {
public:
virtual ~ISolid() = default;
virtual real sdf(const Vec3 &p) = 0;
};
Vec2 get2DRepOf3DPt(const Vec3 &pt3D, const Vec3 &u, const Vec3 &v, const Vec3 &localO) {
Vec3 OP = pt3D - localO;
return {OP.dot(u), OP.dot(v)};
}
class IExtrudedSolid : public ISolid {
public:
Polyline _profile;
real _rScale;
public:
IExtrudedSolid(Polyline profile, real rScale) : _profile(std::move(profile)), _rScale(rScale) {
}
};
/**
* calculate winding number of a point w.r.t. a segment ab
*/
real wnSegment(const Vec3 &p, const Vec3 &a, const Vec3 &b, const Vec3 &refNormal) {
Vec3 pa = a - p;
Vec3 pb = b - p;
real wn = std::acos(std::clamp(pa.dot(pb) / (pa.norm() * pb.norm()), static_cast<real>(-1.),
static_cast<real>(1.)));
return wn * (refNormal.dot(pa.cross(pb)) > 0 ? 1 : -1);
}
class ExtrudedSolidPolyline : public IExtrudedSolid {
private:
Polyline _axis;
Pt2Array _localProfile2D;
public:
ExtrudedSolidPolyline(Polyline profile, Polyline axis, real rScale) : IExtrudedSolid(std::move(profile), rScale),
_axis(std::move(axis)) {
assert(_profile.isClosed());
// TODO: project profile at st point to 2D
Vec3 T = _axis.der1(0).normalize();
Vec3 N = _axis.der2(0).normalize();
Vec3 B = T.cross(N);
Vec3 Q = _axis.eval(0);
for (const auto &P: _profile.getPoints()) {
Vec3 QP = P - Q;
auto uv = get2DRepOf3DPt(QP, N, B, Q);
// test it
{
}
_localProfile2D.emplace_back(uv.u(), uv.v());
}
}
real sdf(const Vec3 &p) override {
ClosestDescOnSeg closestDesc = _axis.getClosestParam(p);
// TNB coordinate system
auto t = closestDesc.t;
Vec3 T = _axis.der1(t).normalize();
Vec3 N = _axis.der2(t).normalize();
Vec3 B = T.cross(N);
Vec3 Q = _axis.eval(t);
Vec3 QP = p - Q;
auto uv = get2DRepOf3DPt(QP, N, B, Q);
//test it
{
}
// TODO: to test if uv is in _localProfile2D
for (auto i = 0; i < _localProfile2D.size(); ++i) {
}
return 0;
}
private:
real wnCircularArc(const Vec3& p, const Vec3& a, const Vec3& b, const Vec3& refNormal, const Polyline::CircularArc& arc) {
Vec3 pa = a - p;
Vec3 pb = b - p;
real wn = std::acos(std::clamp(pa.dot(pb) / (pa.norm() * pb.norm()), static_cast<real>(-1.),
static_cast<real>(1.)));
real dir = refNormal.dot(pb.cross(pa)) > 0 ? 1 : -1; // 注意这里是pb x pa, 不是pa x pb
auto inOutCircle = arc.inCircleCheck(p);
if (inOutCircle == OnBoundary) {
// TODO
}
return (inOutCircle - wn) * dir;
}
};
class ExtrudedSolidPolynomialLine : public IExtrudedSolid {
protected:
PolynomialLine _axis;
};