| 
						
						
							
								
							
						
						
					 | 
					@ -2,6 +2,7 @@ | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					#include "common.hpp" | 
					 | 
					 | 
					#include "common.hpp" | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					#include "real.hpp" | 
					 | 
					 | 
					#include "real.hpp" | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					#include <array> | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					#include <cassert> | 
					 | 
					 | 
					#include <cassert> | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					#include <cstddef> | 
					 | 
					 | 
					#include <cstddef> | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					#include <utility> | 
					 | 
					 | 
					#include <utility> | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					@ -22,12 +23,18 @@ inline Vec2 get2DRepOf3DPt(const Vec3 &pt3D, const Vec3 &u, const Vec3 &v, const | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					inline Vec2 get2DRepOf3DDir(const Vec3 &dir, const Vec3 &u, const Vec3 &v) { | 
					 | 
					 | 
					inline Vec2 get2DRepOf3DDir(const Vec3 &dir, const Vec3 &u, const Vec3 &v) { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    return Vec2{dir.dot(u), dir.dot(v)}.normalize(); | 
					 | 
					 | 
					    return Vec2{dir.dot(u), dir.dot(v)}.normalize(); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					} | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					class IExtrudedSolid : public ISolid { | 
					 | 
					 | 
					
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					public: | 
					 | 
					 | 
					template <typename AxisLineType> | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					class IExtrudedSolidBase : public ISolid { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					protected: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    std::vector<Polyline> _profiles; // TODO: may be replaced by const ref to profile
 | 
					 | 
					 | 
					    std::vector<Polyline> _profiles; // TODO: may be replaced by const ref to profile
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    AxisLineType _axis; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    real _rScale; | 
					 | 
					 | 
					    real _rScale; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					    IExtrudedSolid(std::vector<Polyline> profiles, real rScale) | 
					 | 
					 | 
					    IExtrudedSolidBase(std::vector<Polyline> profiles, AxisLineType axis, real rScale) | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					        : _profiles(std::move(profiles)), _rScale(rScale) {} | 
					 | 
					 | 
					        : _profiles(std::move(profiles)), _axis(std::move(axis)), _rScale(rScale) {} | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					public: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    virtual real sdf(const Vec3 &p) = 0; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					}; | 
					 | 
					 | 
					}; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					/**
 | 
					 | 
					 | 
					/**
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					@ -42,25 +49,26 @@ public: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					//            / (std::numbers::pi * 2);
 | 
					 | 
					 | 
					//            / (std::numbers::pi * 2);
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					// }
 | 
					 | 
					 | 
					// }
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					class ExtrudedSolidPolyline : public IExtrudedSolid { | 
					 | 
					 | 
					// template <typename AxisLineType>
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					class ExtrudedSolidPolyline : public IExtrudedSolidBase<Polyline> { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					private: | 
					 | 
					 | 
					private: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    Polyline _axis; | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    std::vector<Pt2Array> _localProfiles2D; | 
					 | 
					 | 
					    std::vector<Pt2Array> _localProfiles2D; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    std::vector<std::vector<CircularArc<Vec2>>> _localArcs2d; | 
					 | 
					 | 
					    std::vector<std::vector<CircularArc<Vec2>>> _localArcs2d; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					    // Pt2Array _localCircleCenter2D;
 | 
					 | 
					 | 
					    Vec3 _biNormal; | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					    // Pt2Array _localInCircleDir;
 | 
					 | 
					 | 
					
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					public: | 
					 | 
					 | 
					public: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    ExtrudedSolidPolyline(std::vector<Polyline> profiles, Polyline axis, real rScale) | 
					 | 
					 | 
					    ExtrudedSolidPolyline(std::vector<Polyline> profiles, Polyline axis, real rScale) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					        : IExtrudedSolid(std::move(profiles), rScale), _axis(std::move(axis)) { | 
					 | 
					 | 
					        : IExtrudedSolidBase(std::move(profiles), std::move(axis), rScale) { | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					        assert(!_profiles.empty()); | 
					 | 
					 | 
					        assert(!_profiles.empty()); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        for (const auto &_profile : _profiles) { | 
					 | 
					 | 
					        for (const auto &_profile : _profiles) { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            assert(_profile.isClosed()); | 
					 | 
					 | 
					            assert(_profile.isClosed()); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        } | 
					 | 
					 | 
					        } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					        // TODO: project profile at st point to 2D
 | 
					 | 
					 | 
					        // project profile at st point to 2D
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					        Vec3 T = _axis.der1(0).normalize(); | 
					 | 
					 | 
					        Vec3 tangent = _axis.der1(0).normalize(); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					        Vec3 N = _axis.der2(0).normalize(); | 
					 | 
					 | 
					        Vec3 normal = _axis.der2(0).normalize(); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					        Vec3 B = T.cross(N); | 
					 | 
					 | 
					        _biNormal = tangent.cross(normal); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					        Vec3 Q = _axis.eval(0); | 
					 | 
					 | 
					        assert(_biNormal.isParallel(_axis.getNormal())); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        Vec3 q = _axis.eval(0); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        size_t profileCount = _profiles.size(); | 
					 | 
					 | 
					        size_t profileCount = _profiles.size(); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        _localProfiles2D.resize(profileCount); | 
					 | 
					 | 
					        _localProfiles2D.resize(profileCount); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        _localArcs2d.resize(profileCount); | 
					 | 
					 | 
					        _localArcs2d.resize(profileCount); | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					@ -71,11 +79,12 @@ public: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            _localArcs2d[i].resize(segCount); | 
					 | 
					 | 
					            _localArcs2d[i].resize(segCount); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            for (int j = 0; j < segCount; ++j) { | 
					 | 
					 | 
					            for (int j = 0; j < segCount; ++j) { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                // TODO:
 | 
					 | 
					 | 
					                // TODO:
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					                _localProfiles2D[i][j] = get2DRepOf3DPt(profile.getPoints()[j] - Q, N, B, Q); | 
					 | 
					 | 
					                _localProfiles2D[i][j] = | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                    get2DRepOf3DPt(profile.getPoints()[j] - q, normal, _biNormal, q); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                auto &arc2d = _localArcs2d[i][j]; | 
					 | 
					 | 
					                auto &arc2d = _localArcs2d[i][j]; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                const auto &arc3d = profile.getCircularArcs()[j]; | 
					 | 
					 | 
					                const auto &arc3d = profile.getCircularArcs()[j]; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					                arc2d.center = get2DRepOf3DPt(arc3d.center - Q, N, B, Q); | 
					 | 
					 | 
					                arc2d.center = get2DRepOf3DPt(arc3d.center - q, normal, _biNormal, q); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					                arc2d.inCircleDir = get2DRepOf3DDir(arc3d.inCircleDir, N, B); | 
					 | 
					 | 
					                arc2d.inCircleDir = get2DRepOf3DDir(arc3d.inCircleDir, normal, _biNormal); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					                arc2d.radius = arc3d.radius; | 
					 | 
					 | 
					                arc2d.radius = arc3d.radius; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                arc2d.theta = arc3d.theta; | 
					 | 
					 | 
					                arc2d.theta = arc3d.theta; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                arc2d.h = arc3d.h; | 
					 | 
					 | 
					                arc2d.h = arc3d.h; | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					@ -87,61 +96,90 @@ public: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        ClosestDescOnSeg closestDescToAxis = _axis.getClosestParam(p); | 
					 | 
					 | 
					        ClosestDescOnSeg closestDescToAxis = _axis.getClosestParam(p); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        // TNB coordinate system
 | 
					 | 
					 | 
					        // TNB coordinate system
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        auto t = closestDescToAxis.t; | 
					 | 
					 | 
					        auto t = closestDescToAxis.t; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					        Vec3 Q = _axis.eval(t); // closest point on axis
 | 
					 | 
					 | 
					        Vec3 q = _axis.eval(t); // closest point on axis
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					        Vec3 QP = p - Q; | 
					 | 
					 | 
					        Vec3 qp = p - q; | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					        Vec3 T = _axis.der1(t).normalize(); | 
					 | 
					 | 
					        auto TBN = getTBN(p, q, closestDescToAxis); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					        if (_axis.isEndParm(t) && fabs(QP.dot(T)) > EPS) { | 
					 | 
					 | 
					        const Vec3 &tangent = TBN[0]; | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        const Vec3 &normal = TBN[1]; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        const Vec3 &biNormal = TBN[2]; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        if (_axis.isEndParam(t) && fabs(qp.dot(tangent)) > EPS) { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            // project p to the plane passing through Q and perpendicular to T
 | 
					 | 
					 | 
					            // project p to the plane passing through Q and perpendicular to T
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					            Vec3 projP = p + T * (-QP.dot(T)); | 
					 | 
					 | 
					            real pqDotT = -qp.dot(tangent); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					            Vec3 projP = p + tangent * pqDotT; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					            Vec2 p2D = get2DRepOf3DPt(projP, normal, biNormal, q); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					            PtBoundaryRelation ptProfileRelation = pmcProfile2d(p2D); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					            real projectedDis = 0; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					            if (ptProfileRelation == Outside) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                projectedDis = disProfile2D(p2D).dis; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					            // must be positive (outside)
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					            return sqrt(projectedDis * projectedDis + pqDotT * pqDotT); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        } | 
					 | 
					 | 
					        } | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					        Vec3 N = _axis.der2(t).normalize(); | 
					 | 
					 | 
					        Vec2 p2D = get2DRepOf3DPt(p, normal, biNormal, q); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					        Vec3 B = T.cross(N); | 
					 | 
					 | 
					        PtBoundaryRelation ptProfileRelation = pmcProfile2d(p2D); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        if (ptProfileRelation == OnBoundary) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					            return 0; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        auto closestDescToProfile = disProfile2D(p2D); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        return closestDescToProfile.dis * static_cast<int>(ptProfileRelation); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					        auto p2D = get2DRepOf3DPt(QP, N, B, Q); | 
					 | 
					 | 
					    std::array<Vec3, 3> getTBN(const Vec3 &p, const Vec3 &q, const ClosestDescOnSeg &closestDesc) { | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					        // PMC
 | 
					 | 
					 | 
					        real t = closestDesc.t; | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					        PtBoundaryRelation ptProfileRelation = Inside; | 
					 | 
					 | 
					        if (std::abs(t - std::round(t)) < EPS) { | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					        for (int i = 0; i < _localArcs2d.size(); ++i) { | 
					 | 
					 | 
					            // 端点处
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					            PtBoundaryRelation relationTmp = | 
					 | 
					 | 
					            // p到圆弧平面的投影
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					                getPtProfileRelation(p2D, _localProfiles2D[i], _localArcs2d[i]); | 
					 | 
					 | 
					            Vec3 projPt = p - _biNormal.dot(p - q) * _biNormal; | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					            if (relationTmp == OnBoundary) { | 
					 | 
					 | 
					            Vec3 normal = (q - projPt).normalize(); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					                return 0; // TODO: 判断OnBoundary的过程可以加一点容差
 | 
					 | 
					 | 
					            if (normal.dot(_axis.der2(t)) < 0) { | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					            } | 
					 | 
					 | 
					                normal = -normal; | 
				
			
			
				
				
			
		
	
		
		
			
				
					 | 
					 | 
					            if ((relationTmp == Outside && i == 0) || (relationTmp == Inside && i != 0)) { | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                ptProfileRelation = Outside; | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                break; | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					            } | 
					 | 
					 | 
					            } | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					            return {normal.cross(_biNormal), normal, _biNormal}; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        } | 
					 | 
					 | 
					        } | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        return {_axis.der1(t).normalize(), _axis.der1(t).normalize(), _biNormal}; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					        // distance
 | 
					 | 
					 | 
					private: | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    inline ClosestDescOnSeg disProfile2D(const Vec2 &p2D) { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        ClosestDescOnSeg closestDescToProfile{}; | 
					 | 
					 | 
					        ClosestDescOnSeg closestDescToProfile{}; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        for (int i = 0; i < _localArcs2d.size(); ++i) { | 
					 | 
					 | 
					        for (int i = 0; i < _localArcs2d.size(); ++i) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					            ClosestDescOnSeg closestDescTemp = | 
					 | 
					 | 
					            ClosestDescOnSeg closestDescTemp = disLoop2D(p2D, _localProfiles2D[i], _localArcs2d[i]); | 
				
			
			
				
				
			
		
	
		
		
			
				
					 | 
					 | 
					                distance2Profile2D(p2D, _localProfiles2D[i], _localArcs2d[i]); | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					            if (closestDescTemp.dis < closestDescToProfile.dis) { | 
					 | 
					 | 
					            if (closestDescTemp.dis < closestDescToProfile.dis) { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                closestDescToProfile = closestDescTemp; | 
					 | 
					 | 
					                closestDescToProfile = closestDescTemp; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            } | 
					 | 
					 | 
					            } | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        } | 
					 | 
					 | 
					        } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					        return closestDescToProfile.dis * static_cast<int>(ptProfileRelation); | 
					 | 
					 | 
					        return closestDescToProfile; | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					    } | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					private: | 
					 | 
					 | 
					    inline PtBoundaryRelation pmcProfile2d(const Vec2 &p2D) { | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					    /** 低于2Dprofile的内外部判定
 | 
					 | 
					 | 
					        // PMC
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        for (int i = 0; i < _localArcs2d.size(); ++i) { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					            PtBoundaryRelation relationTmp = pmcLoop2d(p2D, _localProfiles2D[i], _localArcs2d[i]); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					            if (relationTmp == OnBoundary) { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                return OnBoundary; // TODO: 判断OnBoundary的过程可以加一点容差
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					            } | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					            if ((relationTmp == Outside && i == 0) || (relationTmp == Inside && i != 0)) { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                return Outside; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					            } | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        } | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        return Inside; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    /** 2D Loop的内外部判定
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					     * in + in = out | 
					 | 
					 | 
					     * in + in = out | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					     * in + out = in | 
					 | 
					 | 
					     * in + out = in | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					     * out + in = in | 
					 | 
					 | 
					     * out + in = in | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					     * out + out = out | 
					 | 
					 | 
					     * out + out = out | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					     */ | 
					 | 
					 | 
					     */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					    static PtBoundaryRelation getPtProfileRelation(const Vec2 &p2D, const Pt2Array &profile2D, | 
					 | 
					 | 
					    static PtBoundaryRelation pmcLoop2d(const Vec2 &p2D, const Pt2Array &loop2D, | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					                                                   const std::vector<CircularArc<Vec2>> &arcs2d) { | 
					 | 
					 | 
					                                        const std::vector<CircularArc<Vec2>> &arcs2d) { | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					        size_t segCount = arcs2d.size(); | 
					 | 
					 | 
					        size_t segCount = arcs2d.size(); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        // 先判断是否在outline上
 | 
					 | 
					 | 
					        // 先判断是否在outline上
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        // 顺便判断点-扇的位置关系
 | 
					 | 
					 | 
					        // 顺便判断点-扇的位置关系
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        bool inFan = false; | 
					 | 
					 | 
					        bool inFan = false; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        int onLinesegButHasBugle = -1; | 
					 | 
					 | 
					        int onLinesegButHasBugle = -1; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        for (int i = 0; i < segCount; ++i) { | 
					 | 
					 | 
					        for (int i = 0; i < segCount; ++i) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					            const Vec2 &a = profile2D[i]; | 
					 | 
					 | 
					            const Vec2 &a = loop2D[i]; | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					            const Vec2 &b = profile2D[(i + 1) % segCount]; | 
					 | 
					 | 
					            const Vec2 &b = loop2D[(i + 1) % segCount]; | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					            if (arcs2d[i].h <= EPS) { | 
					 | 
					 | 
					            if (arcs2d[i].h <= EPS) { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                //straight line segment
 | 
					 | 
					 | 
					                //straight line segment
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                if (isPointOnSegment(p2D, a, b)) { | 
					 | 
					 | 
					                if (isPointOnSegment(p2D, a, b)) { | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					@ -184,8 +222,8 @@ private: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                int crossings = 0; | 
					 | 
					 | 
					                int crossings = 0; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                for (int i = 0; i < segCount; ++i) { | 
					 | 
					 | 
					                for (int i = 0; i < segCount; ++i) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					                    const Vec2 &a = profile2D[i]; | 
					 | 
					 | 
					                    const Vec2 &a = loop2D[i]; | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					                    const Vec2 &b = profile2D[(i + 1) % segCount]; | 
					 | 
					 | 
					                    const Vec2 &b = loop2D[(i + 1) % segCount]; | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					                    assert(isPointOnSegment(p, a, b)); | 
					 | 
					 | 
					                    assert(isPointOnSegment(p, a, b)); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                    // if (isPointOnSegment(p2D, a, b))
 | 
					 | 
					 | 
					                    // if (isPointOnSegment(p2D, a, b))
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                    // {
 | 
					 | 
					 | 
					                    // {
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					@ -229,14 +267,13 @@ private: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        return ptInPolygon(p2D) ^ inFan ? Inside : Outside; | 
					 | 
					 | 
					        return ptInPolygon(p2D) ^ inFan ? Inside : Outside; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    } | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					    static ClosestDescOnSeg distance2Profile2D(const Vec2 &p2D, const Pt2Array &profile2D, | 
					 | 
					 | 
					    static ClosestDescOnSeg disLoop2D(const Vec2 &p2D, const Pt2Array &loop2D, | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					                                               const std::vector<CircularArc<Vec2>> &arcs2d) { | 
					 | 
					 | 
					                                      const std::vector<CircularArc<Vec2>> &arcs2d) { | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					        size_t segCount = arcs2d.size(); | 
					 | 
					 | 
					        size_t segCount = arcs2d.size(); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					        assert(profile2D.size() == segCount); | 
					 | 
					 | 
					        assert(loop2D.size() == segCount); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					        ClosestDescOnSeg res{}; | 
					 | 
					 | 
					        ClosestDescOnSeg res{}; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        for (int i = 0; i < segCount; ++i) { | 
					 | 
					 | 
					        for (int i = 0; i < segCount; ++i) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					            auto disDesc = | 
					 | 
					 | 
					            auto disDesc = distance2Arc2D(p2D, loop2D[i], loop2D[(i + 1) % segCount], arcs2d[i]); | 
				
			
			
				
				
			
		
	
		
		
			
				
					 | 
					 | 
					                distance2Arc2D(p2D, profile2D[i], profile2D[(i + 1) % segCount], arcs2d[i]); | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					            if (res.dis > disDesc.dis) { | 
					 | 
					 | 
					            if (res.dis > disDesc.dis) { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                res.dis = disDesc.dis; | 
					 | 
					 | 
					                res.dis = disDesc.dis; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                res.t = i + disDesc.t; | 
					 | 
					 | 
					                res.t = i + disDesc.t; | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					@ -330,8 +367,3 @@ private: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    //     return arc.center + arc.radius * (arc.u * std::cos(phi) + arc.v * std::sin(phi));
 | 
					 | 
					 | 
					    //     return arc.center + arc.radius * (arc.u * std::cos(phi) + arc.v * std::sin(phi));
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    // }
 | 
					 | 
					 | 
					    // }
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					}; | 
					 | 
					 | 
					}; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					class ExtrudedSolidPolynomialLine : public IExtrudedSolid { | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					protected: | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    PolynomialLine _axis; | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					}; | 
					 | 
					 | 
					 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
					
  |