From 17c931ec95bc979cb687dd96284cd2476589b317 Mon Sep 17 00:00:00 2001 From: Dtouch <1472779700@qq.com> Date: Thu, 14 Nov 2024 13:00:17 +0800 Subject: [PATCH] winding number of arc --- include/common.hpp | 6 ++++++ include/line.hpp | 24 +++++++++++++---------- include/solid.hpp | 48 +++++++++++++++++++++++++++++++++++++--------- 3 files changed, 59 insertions(+), 19 deletions(-) diff --git a/include/common.hpp b/include/common.hpp index 6f70f09..354fd66 100644 --- a/include/common.hpp +++ b/include/common.hpp @@ -1 +1,7 @@ #pragma once + +enum PtBoundaryRelation { + Inside = 1, + OnBoundary, + Outside = -1 +}; \ No newline at end of file diff --git a/include/line.hpp b/include/line.hpp index 357b51a..5a0b974 100644 --- a/include/line.hpp +++ b/include/line.hpp @@ -8,6 +8,7 @@ #include #include #include +#include "common.hpp" // class ILineParam { // public: @@ -53,6 +54,7 @@ public: } else { assert(_points.size() - 1 == _points.size()); } + circularArcs.resize(_bugles.size()); } [[nodiscard]] const Pt3Array &getPoints() const { return _points; } @@ -63,12 +65,6 @@ public: [[nodiscard]] bool isClosed() const { return _closed; } -private: - Pt3Array _points; - std::vector _bugles; - Vec3 _normal; - bool _closed; - struct CircularArc { Vec3 center; real radius; @@ -76,13 +72,23 @@ private: real h; Vec3 u; // dir of OA Vec3 v; // u X v = normal + + PtBoundaryRelation inCircleCheck(const Vec3 &pt) const { + real d = (pt - center).norm(); + return d < radius ? Inside : d > radius ? Outside : OnBoundary; + } }; +private: + Pt3Array _points; + std::vector _bugles; + Vec3 _normal; + bool _closed; + std::vector circularArcs; public: void initSegInfo() { - circularArcs.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()]; @@ -102,7 +108,6 @@ public: } Vec3 eval(real param) override { - assert(param >= 0 && param <= _bugles.size()); if (circularArcs.empty()) initSegInfo(); int seg = static_cast(param); real tOnSeg = param - seg; @@ -112,7 +117,6 @@ public: } Vec3 der1(real param) override { - assert(param >= 0 && param <= _bugles.size()); if (circularArcs.empty()) initSegInfo(); int seg = static_cast(param); real tOnSeg = param - seg; @@ -122,7 +126,6 @@ public: } Vec3 der2(real param) override { - assert(param >= 0 && param <= _bugles.size()); if (circularArcs.empty()) initSegInfo(); int seg = static_cast(param); real tOnSeg = param - seg; @@ -188,6 +191,7 @@ public: return {closestParam, closestDis}; } + const std::vector &getCircularArcs() const { return circularArcs; } void print() const { if (_closed) printf("Closed Polyline: \n"); diff --git a/include/solid.hpp b/include/solid.hpp index 460f03a..48de046 100644 --- a/include/solid.hpp +++ b/include/solid.hpp @@ -8,6 +8,7 @@ class ISolid { public: virtual ~ISolid() = default; + virtual real sdf(const Vec3 &p) = 0; }; @@ -20,31 +21,44 @@ 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(-1.), + static_cast(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)) { + 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); - const Pt3Array& profilePts = _profile.getPoints(); - for (int i = 0; i < profilePts.size(); ++i) { - const Vec3& P = profilePts[i]; + for (const auto &P: _profile.getPoints()) { Vec3 QP = P - Q; auto uv = get2DRepOf3DPt(QP, N, B, Q); // test it - {} - _localProfile2D.emplace_back(uv.x(), uv.y()); + { + } + _localProfile2D.emplace_back(uv.u(), uv.v()); } } @@ -58,14 +72,30 @@ public: Vec3 Q = _axis.eval(t); Vec3 QP = p - Q; auto uv = get2DRepOf3DPt(QP, N, B, Q); - // test it + //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(-1.), + static_cast(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; - };