| 
						
						
							
								
							
						
						
					 | 
				
				 | 
				
					@ -11,6 +11,7 @@ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					#include <limits.h> | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					#include <limits> | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					#include <vector> | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					#include "aabb.hpp" | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					// class ILineParam {
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					// public:
 | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -26,12 +27,19 @@ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					//     real t;
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					// };
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					struct ClosestDescOnSeg { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					struct ClosestDescOnLine { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    real t; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    real dis; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    ClosestDescOnSeg(real _t, real _dis) : t(_t), dis(_dis) {} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    ClosestDescOnSeg() : t(0), dis(std::numeric_limits<real>::max()) {} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    ClosestDescOnLine(real _t, real _dis) : t(_t), dis(_dis) {} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    ClosestDescOnLine() : t(0), dis(std::numeric_limits<real>::max()) {} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					}; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					struct ClosestDescOnProfile : public ClosestDescOnLine { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    int i; // line idx
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    ClosestDescOnProfile(real _t, real _dis, int _i) : ClosestDescOnLine(_t, _dis), i(_i) {} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    ClosestDescOnProfile() : i(-1) {} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					}; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					// vscode C++ override跳转插件
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					class ILine { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					public: | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -43,29 +51,34 @@ public: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    ILine(ILine &&) = default; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    ILine &operator=(ILine &&) = default; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    virtual Vec3 eval(real t) const = 0; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    [[nodiscard]] virtual Vec3 eval(real t) const = 0; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    virtual Vec3 der1(real t) const = 0; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    [[nodiscard]] virtual Vec3 der1(real t) const = 0; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    virtual Vec3 der2(real t) const = 0; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    [[nodiscard]] virtual Vec3 der2(real t) const = 0; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    virtual Vec3 tangent(real t) const = 0; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    [[nodiscard]] virtual Vec3 tangent(real t) const = 0; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    virtual Vec3 normal(real t, const Vec3 &tan = -1.) const = 0; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    [[nodiscard]] virtual Vec3 normal(real t, const Vec3 &tan = -1.) const = 0; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    virtual ClosestDescOnSeg getClosestParam(const Vec3 &p) const = 0; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    [[nodiscard]] virtual ClosestDescOnLine getClosestParam(const Vec3 &p) const = 0; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    [[nodiscard]] virtual bool isEndParam(real t) const = 0; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    [[nodiscard]] virtual real startT() const = 0; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    [[nodiscard]] virtual real endT() const = 0; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    [[nodiscard]] virtual AABB getAABB() const = 0; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					}; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					inline static ClosestDescOnSeg segPtDist(const Vec3 &p, const Vec3 &A, const Vec3 &B) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					inline static ClosestDescOnLine segPtDist(const Vec3 &p, const Vec3 &A, const Vec3 &B) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    Vec3 AB = B - A; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    Vec3 AP = p - A; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    real h = std::clamp(AP.dot(AB) / AB.dot(AB), 0., 1.); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    return {h, (AP - AB * h).norm()}; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					inline static ClosestDescOnSeg segPtDist(const Vec2 &p, const Vec2 &A, const Vec2 &B) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					inline static ClosestDescOnLine segPtDist(const Vec2 &p, const Vec2 &A, const Vec2 &B) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    Vec2 AB = B - A; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    Vec2 AP = p - A; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    real h = std::clamp(AP.dot(AB) / AB.dot(AB), 0., 1.); | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				
					@ -109,6 +122,12 @@ public: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        circularArcs.resize(_bugles.size()); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        initSegInfo(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        for (size_t i = 0; i < _bugles.size(); ++i) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            AABB tmp{_points[i], _points[i]}; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            tmp.extend(AABB{_points[(i + 1) % _points.size()], _points[(i + 1) % _points.size()]}); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            tmp.expand(circularArcs[i].radius - circularArcs[i].h); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            aabb.extend(tmp); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    [[nodiscard]] const Pt3Array &getPoints() const { return _points; } | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -123,6 +142,9 @@ public: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        return circularArcs; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    [[nodiscard]] real startT() const override { return 0; }; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    [[nodiscard]] real endT() const override { return static_cast<real>(_bugles.size()); }; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					protected: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    Pt3Array _points; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    std::vector<real> _bugles; | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -130,6 +152,8 @@ protected: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    bool _closed; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    std::vector<CircularArc<Vec3>> circularArcs; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    AABB aabb; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					public: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    void initSegInfo() { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        for (size_t i = 0; i < _bugles.size(); ++i) { | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -138,7 +162,7 @@ public: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    Vec3 eval(real t) const override { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    [[nodiscard]] Vec3 eval(real t) const override { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        // if (circularArcs.empty())
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        //     initSegInfo();
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        int seg = static_cast<int>(t); | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -151,7 +175,7 @@ public: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        return arc.center + arc.radius * (arc.u * std::cos(phi) + arc.v * std::sin(phi)); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    Vec3 der1(real t) const override { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    [[nodiscard]] Vec3 der1(real t) const override { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        int seg = static_cast<int>(t); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        if (isEqual(_bugles[seg], 0)) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            return _points[(seg + 1) % _points.size()] - _points[seg]; | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -162,7 +186,7 @@ public: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        return arc.radius * (arc.u * -std::sin(phi) + arc.v * std::cos(phi)); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    Vec3 der2(real t) const override { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    [[nodiscard]] Vec3 der2(real t) const override { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        int seg = static_cast<int>(t); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        if (isEqual(_bugles[seg], 0)) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            int aaa = 1; | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				
					@ -245,14 +269,14 @@ public: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    //     return {closestParam, closestDis};
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    // }
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    ClosestDescOnSeg getClosestParam(const Vec3 &p) const override { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        ClosestDescOnSeg closestDes{}; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    [[nodiscard]] ClosestDescOnLine getClosestParam(const Vec3 &p) const override { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        ClosestDescOnLine closestDes{}; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        for (int i = 0; i < _bugles.size(); ++i) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            const Vec3 &a = _points[i]; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            const Vec3 &b = _points[(i + 1) % _points.size()]; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if (isEqual(_bugles[i], 0)) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                // 点到线段最近距离
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                ClosestDescOnSeg segPtDistRes = segPtDist(p, a, b); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                ClosestDescOnLine segPtDistRes = segPtDist(p, a, b); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                if (segPtDistRes.dis < closestDes.dis) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    closestDes = segPtDistRes; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    closestDes.t = i + segPtDistRes.t; | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				
					@ -320,6 +344,8 @@ public: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        return t < EPS_END_PARAM || t > static_cast<real>(_bugles.size()) - EPS_END_PARAM; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    [[nodiscard]] AABB getAABB() const override { return aabb; } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					private: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    void initCircularArcInfo(const Vec3 &a, const Vec3 &b, real bugle, const Vec3 &refNormal, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                             CircularArc<Vec3> &res) { | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				
					@ -365,25 +391,30 @@ public: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        real _4pi2r = PI2 * PI2 * _r; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        // _k = _4pi2r / (advancePerRound * advancePerRound + _4pi2r * _r);
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        _arcDeltaMaxFactor = _4pi2r / (advancePerRound * advancePerRound + _4pi2r * _r) * ONE_EIGHT; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        // init aabb
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        aabb.extend(_axisStart); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        aabb.extend(axisEnd); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        aabb.extend(r); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    Vec3 eval(real t) const override { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    [[nodiscard]] Vec3 eval(real t) const override { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        real theta = _frequency * t; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        return _axisStart + _axisDir * t + (_u * std::cos(theta) + _v * std::sin(theta)) * _r; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    }; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    Vec3 der1(real param) const override { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    [[nodiscard]] Vec3 der1(real param) const override { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        real theta = _frequency * param; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        return _axisDir + _2pir_p * (_v * std::cos(theta) - _u * std::sin(theta)); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    }; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    Vec3 der2(real param) const override { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    [[nodiscard]] Vec3 der2(real param) const override { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        real theta = _frequency * param; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        return -_4pi2r_p2 * (_u * std::cos(theta) + _v * std::sin(theta)); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    }; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    Vec3 tangent(real t) const override { return der1(t).normalize(); } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    [[nodiscard]] Vec3 tangent(real t) const override { return der1(t).normalize(); } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    Vec3 normal(real t, const Vec3 &tan = -1.) const override { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    [[nodiscard]] Vec3 normal(real t, const Vec3 &tan = -1.) const override { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        Vec3 der2Vec = this->der2(t); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        if (tan == -1.) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            Vec3 realTan = tangent(t); | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -392,15 +423,20 @@ public: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        return (der2Vec - der2Vec.dot(tan) * tan).normalize(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    ClosestDescOnSeg getClosestParam(const Vec3 &p) const override { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    [[nodiscard]] real startT() const override { return 0; } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    [[nodiscard]] real endT() const override { return 1; } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    [[nodiscard]] AABB getAABB() const override { return aabb; } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    ClosestDescOnLine getClosestParam(const Vec3 &p) const override { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        // discretization and traversal
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        real startT = 0; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        real endT = SEG_T; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        auto segCount = static_cast<size_t>(std::ceil(_advanceLen / SEG_T)); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        std::vector<ClosestDescOnSeg> sampledSegs(segCount + 2); // 加上首尾
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        std::vector<ClosestDescOnLine> sampledSegs(segCount + 2); // 加上首尾
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        std::vector<Vec3> samplePoints(segCount + 2); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        ClosestDescOnSeg closestSampleDes; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        ClosestDescOnLine closestSampleDes; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        for (size_t i = 0; i < segCount; ++i, startT = endT, endT += SEG_T) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            real sampledT = fmin(startT + SEG_T_HALF, _advanceLen); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            samplePoints[i] = eval(sampledT); | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				
					@ -474,6 +510,7 @@ private: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    real _r, _2pir_p, _4pi2r_p2, _arcDeltaMaxFactor; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    const int SEG_PER_ROUND = 12; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    const real SEG_T, SEG_T_HALF; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    AABB aabb; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					}; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					class SingleLine : public ILine { | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				
					@ -507,5 +544,5 @@ public: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    Vec3 normal(real t, const Vec3 &tan = -1.) const override { return {}; } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    ClosestDescOnSeg getClosestParam(const Vec3 &p) const override { return {}; }; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    ClosestDescOnLine getClosestParam(const Vec3 &p) const override { return {}; }; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					}; | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
					 | 
				
				 | 
				
					
  |