From 551723dc8264958df07a65b303362a823596d142 Mon Sep 17 00:00:00 2001 From: gjj Date: Fri, 22 Nov 2024 16:44:01 +0800 Subject: [PATCH] impl of helix & TBN for articulation of polylines --- .clang-tidy | 4 +- include/common.hpp | 12 +++- include/line.hpp | 129 +++++++++++++++++++++++++++++++++++---- include/solid.hpp | 148 +++++++++++++++++++++++++++------------------ include/vec.hpp | 45 +++++++++----- require.md | 54 +++++++++-------- 6 files changed, 279 insertions(+), 113 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index 08c49ec..98d6506 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -5,6 +5,8 @@ Checks: " performance-*, readability-*, -readability-braces-around-statements, + -readability-magic-numbers, + -readability-identifier-length, misc-*, -misc-non-private-member-variables-in-classes, clang-analyzer-*, @@ -15,7 +17,7 @@ Checks: " performance-unnecessary-value-param, modernize-pass-by-value, - -readability-identifier-length, + -modernize-use-trailing-return-type, -cppcoreguidelines-magic-numbers, -cppcoreguidelines-init-variables, diff --git a/include/common.hpp b/include/common.hpp index 0be5879..0da9d21 100644 --- a/include/common.hpp +++ b/include/common.hpp @@ -2,13 +2,19 @@ #include "real.hpp" #include #include +#include enum PtBoundaryRelation { Inside = -1, OnBoundary, Outside = 1 }; const real PI = std::numbers::pi; const real PI2 = 2 * PI; const real EPS = std::numeric_limits::epsilon() * 1e2; -inline bool isEqual(double a, double b) { - // TODO - return a == b; +const real EPS_NEWTON_ITERATION = std::numeric_limits::epsilon() * 1e6; + +const real HALF = 0.5; +const real ONE_FOURTH = 0.25; +const real ONE_EIGHT = 0.125; + +inline bool isEqual(real a, real b) { + return fabs(a - b) < EPS; } \ No newline at end of file diff --git a/include/line.hpp b/include/line.hpp index 4b9b7a6..c30353d 100644 --- a/include/line.hpp +++ b/include/line.hpp @@ -1,12 +1,15 @@ #pragma once #include "common.hpp" +#include "real.hpp" #include "vec.hpp" #include #include #include +#include #include #include +#include #include #include #include @@ -31,7 +34,7 @@ struct ClosestDescOnSeg { ClosestDescOnSeg(real _t, real _dis) : t(_t), dis(_dis) {} ClosestDescOnSeg() : t(0), dis(std::numeric_limits::max()) {} }; - +// vscode C++ override跳转插件 class ILine { public: int aaa; @@ -44,6 +47,8 @@ public: virtual Vec3 der2(real param) = 0; virtual ClosestDescOnSeg getClosestParam(const Vec3 &p) = 0; + + [[nodiscard]] virtual bool isEndParam(real t) const = 0; }; template // Vec2 or Vec3 @@ -111,11 +116,11 @@ public: for (size_t i = 0; i < _bugles.size(); ++i) { const Point &A = _points[i]; const Point &B = _points[(i + 1) % _points.size()]; - Vec3 ABHalf = (B - A) * 0.5; + Vec3 ABHalf = (B - A) * HALF; Vec3 ABNorm = ABHalf.normalize(); real theta = std::atan(_bugles[i]) * 4; - circularArcs[i].inCircleDir = _normal.cross(ABNorm) * (abs(_bugles[i]) > 1 ? -1 : 1); - circularArcs[i].h = ABHalf.norm() * std::tan(theta * 0.5); + circularArcs[i].inCircleDir = _normal.cross(ABNorm) * (fabs(_bugles[i]) > 1 ? -1 : 1); + circularArcs[i].h = ABHalf.norm() * std::tan(theta * HALF); circularArcs[i].center = A + ABHalf + circularArcs[i].inCircleDir * circularArcs[i].h; circularArcs[i].theta = theta; circularArcs[i].radius = (circularArcs[i].center - A).norm(); @@ -290,23 +295,123 @@ public: return {h, (AP - AB * h).norm()}; } - bool isEndParm(real t) { return t < EPS || t > _points.size() - 1 - EPS; } + [[nodiscard]] bool isEndParam(real t) const override { + return t < EPS || t > static_cast(_bugles.size()) - EPS; + } }; class HelixLine : public ILine { public: - Vec3 eval(real param) override { return {}; }; + HelixLine(const Vec3 &axisStart, const Vec3 &axisEnd, real r, real advancePerRound, + const Vec3 &startDir) + : _axisStart(axisStart), _frequency(PI2 / advancePerRound), _u(startDir), _r(r), + _2pir_p(PI2 * _r / advancePerRound), _4pi2r_p2(_2pir_p * PI2 / advancePerRound), + SEG_T(advancePerRound / SEG_PER_ROUND), SEG_T_HALF(SEG_T / 2) { + auto star2nd = axisEnd - _axisStart; + _advanceLen = star2nd.norm(); + _axisDir = star2nd / _advanceLen; + _v = _axisDir.cross(_u); + real _4pi2r = PI2 * PI2 * _r; + // _k = _4pi2r / (advancePerRound * advancePerRound + _4pi2r * _r); + _arcDeltaMaxFactor = _4pi2r / (advancePerRound * advancePerRound + _4pi2r * _r) * ONE_EIGHT; + } + Vec3 eval(real t) override { + real theta = _frequency * t; + return _axisStart + _axisDir * t + (_u * std::cos(theta) + _v * std::sin(theta)) * _r; + }; - Vec3 der1(real param) override { return {}; }; + Vec3 der1(real param) override { + real theta = _frequency * param; + return _axisDir + _2pir_p * (_v * std::cos(theta) - _u * std::sin(theta)); + }; - Vec3 der2(real param) override { return {}; }; + Vec3 der2(real param) override { + real theta = _frequency * param; + return -_4pi2r_p2 * (_u * std::cos(theta) + _v * std::sin(theta)); + }; - ClosestDescOnSeg getClosestParam(const Vec3 &p) override { return {}; }; + ClosestDescOnSeg getClosestParam(const Vec3 &p) override { + // discretization and traversal + real startT = 0; + real endT = SEG_T; + auto segCount = static_cast(std::ceil(_advanceLen / SEG_T)); + std::vector sampledSegs(segCount + 2); // 加上首尾 + std::vector samplePoints(segCount + 2); + + ClosestDescOnSeg 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); + sampledSegs[i].dis = (samplePoints[i] - p).norm(); + sampledSegs[i].t = sampledT; + if (sampledSegs[i].dis < closestSampleDes.dis) { + closestSampleDes = sampledSegs[i]; + } + } + // 特别考虑两端,因为有更多的情形,查询点会离两端更近 + // 好处是可能降低后续迭代次数 + samplePoints[segCount] = eval(0); + samplePoints[segCount + 1] = eval(_advanceLen); + sampledSegs[segCount] = {0, (samplePoints[segCount] - p).norm()}; + sampledSegs[segCount + 1] = {_advanceLen, (samplePoints[segCount + 1] - p).norm()}; + for (size_t i = segCount; i <= segCount + 1; ++i) { + if (sampledSegs[i].dis < closestSampleDes.dis) { + closestSampleDes = sampledSegs[i]; + } + } + + real deltaMaxCommon = (eval(0) - eval(SEG_T)).l2() * _arcDeltaMaxFactor; + for (int i = 0; i < sampledSegs.size(); ++i) { + if (i == segCount - 1) { + // 最后一段 + deltaMaxCommon = + (eval(_advanceLen) - eval(SEG_T * static_cast(segCount - 1))).l2() + * _arcDeltaMaxFactor; + } else if (i == segCount || i == segCount + 1) { + // 首尾点 + deltaMaxCommon = 0; + } + if (sampledSegs[i].dis - deltaMaxCommon < closestSampleDes.dis) { + Vec3 q = samplePoints[i]; + real t = sampledSegs[i].t; + Vec3 qDer1 = der1(t); + Vec3 qDer2 = der2(t); + real lDer1 = (q - p).dot(qDer1); + int iter = 0; + while (fabs(lDer1) > EPS_NEWTON_ITERATION) { + real dif = lDer1 / (qDer1.dot(qDer1) + (q - p).dot(qDer2)); + real tNew = t - dif; + if (tNew < 0 || tNew > _advanceLen) + break; + t = tNew; + q = eval(t); + qDer1 = der1(t); + qDer2 = der2(t); + lDer1 = (q - p).dot(qDer1); + std::cout << "After iter " << iter << ", dL is " << lDer1 << std::endl; + iter++; + } + real dis = (q - p).norm(); + if (dis < closestSampleDes.dis) { + closestSampleDes = {t, dis}; + } + } + } + return closestSampleDes; + }; + + [[nodiscard]] bool isEndParam(real t) const override { + return t < EPS || t > _advanceLen - EPS; + } private: - Vec3 axisStart, axisDir; - real advanceLen, advancePerRound; - real startTheta; // 轴线起始时在螺旋投影(圆)上的参数 + Vec3 _axisStart, _axisDir; + real _advanceLen, _frequency; + real _startTheta; + Vec3 _u, _v; // 螺旋投影圆面上的两个正交单位向量,u X v = axisDir + real _r, _2pir_p, _4pi2r_p2, _arcDeltaMaxFactor; + const int SEG_PER_ROUND = 12; + const real SEG_T, SEG_T_HALF; }; class SingleLine : public ILine { diff --git a/include/solid.hpp b/include/solid.hpp index f870310..23347f7 100644 --- a/include/solid.hpp +++ b/include/solid.hpp @@ -2,6 +2,7 @@ #include "common.hpp" #include "real.hpp" +#include #include #include #include @@ -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) { return Vec2{dir.dot(u), dir.dot(v)}.normalize(); } -class IExtrudedSolid : public ISolid { -public: + +template +class IExtrudedSolidBase : public ISolid { +protected: std::vector _profiles; // TODO: may be replaced by const ref to profile + AxisLineType _axis; real _rScale; - IExtrudedSolid(std::vector profiles, real rScale) - : _profiles(std::move(profiles)), _rScale(rScale) {} + IExtrudedSolidBase(std::vector profiles, AxisLineType axis, real 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); // } -class ExtrudedSolidPolyline : public IExtrudedSolid { +// template +class ExtrudedSolidPolyline : public IExtrudedSolidBase { private: - Polyline _axis; std::vector _localProfiles2D; std::vector>> _localArcs2d; - // Pt2Array _localCircleCenter2D; - // Pt2Array _localInCircleDir; + Vec3 _biNormal; + public: ExtrudedSolidPolyline(std::vector 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()); for (const auto &_profile : _profiles) { 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); + // project profile at st point to 2D + Vec3 tangent = _axis.der1(0).normalize(); + Vec3 normal = _axis.der2(0).normalize(); + _biNormal = tangent.cross(normal); + assert(_biNormal.isParallel(_axis.getNormal())); + Vec3 q = _axis.eval(0); size_t profileCount = _profiles.size(); _localProfiles2D.resize(profileCount); _localArcs2d.resize(profileCount); @@ -71,11 +79,12 @@ public: _localArcs2d[i].resize(segCount); for (int j = 0; j < segCount; ++j) { // 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]; const auto &arc3d = profile.getCircularArcs()[j]; - arc2d.center = get2DRepOf3DPt(arc3d.center - Q, N, B, Q); - arc2d.inCircleDir = get2DRepOf3DDir(arc3d.inCircleDir, N, B); + arc2d.center = get2DRepOf3DPt(arc3d.center - q, normal, _biNormal, q); + arc2d.inCircleDir = get2DRepOf3DDir(arc3d.inCircleDir, normal, _biNormal); arc2d.radius = arc3d.radius; arc2d.theta = arc3d.theta; arc2d.h = arc3d.h; @@ -87,61 +96,90 @@ public: ClosestDescOnSeg closestDescToAxis = _axis.getClosestParam(p); // TNB coordinate system auto t = closestDescToAxis.t; - Vec3 Q = _axis.eval(t); // closest point on axis - Vec3 QP = p - Q; - Vec3 T = _axis.der1(t).normalize(); - if (_axis.isEndParm(t) && fabs(QP.dot(T)) > EPS) { + Vec3 q = _axis.eval(t); // closest point on axis + Vec3 qp = p - q; + auto TBN = getTBN(p, q, closestDescToAxis); + 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 - 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(); - Vec3 B = T.cross(N); + Vec2 p2D = get2DRepOf3DPt(p, normal, biNormal, q); + PtBoundaryRelation ptProfileRelation = pmcProfile2d(p2D); + if (ptProfileRelation == OnBoundary) + return 0; + auto closestDescToProfile = disProfile2D(p2D); + return closestDescToProfile.dis * static_cast(ptProfileRelation); + } - auto p2D = get2DRepOf3DPt(QP, N, B, Q); - // PMC - PtBoundaryRelation ptProfileRelation = Inside; - for (int i = 0; i < _localArcs2d.size(); ++i) { - PtBoundaryRelation relationTmp = - getPtProfileRelation(p2D, _localProfiles2D[i], _localArcs2d[i]); - if (relationTmp == OnBoundary) { - return 0; // TODO: 判断OnBoundary的过程可以加一点容差 - } - if ((relationTmp == Outside && i == 0) || (relationTmp == Inside && i != 0)) { - ptProfileRelation = Outside; - break; + std::array getTBN(const Vec3 &p, const Vec3 &q, const ClosestDescOnSeg &closestDesc) { + real t = closestDesc.t; + if (std::abs(t - std::round(t)) < EPS) { + // 端点处 + // p到圆弧平面的投影 + Vec3 projPt = p - _biNormal.dot(p - q) * _biNormal; + Vec3 normal = (q - projPt).normalize(); + if (normal.dot(_axis.der2(t)) < 0) { + normal = -normal; } + 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{}; for (int i = 0; i < _localArcs2d.size(); ++i) { - ClosestDescOnSeg closestDescTemp = - distance2Profile2D(p2D, _localProfiles2D[i], _localArcs2d[i]); + ClosestDescOnSeg closestDescTemp = disLoop2D(p2D, _localProfiles2D[i], _localArcs2d[i]); if (closestDescTemp.dis < closestDescToProfile.dis) { closestDescToProfile = closestDescTemp; } } - return closestDescToProfile.dis * static_cast(ptProfileRelation); + return closestDescToProfile; } -private: - /** 低于2Dprofile的内外部判定 + inline PtBoundaryRelation pmcProfile2d(const Vec2 &p2D) { + // 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 + out = in * out + in = in * out + out = out */ - static PtBoundaryRelation getPtProfileRelation(const Vec2 &p2D, const Pt2Array &profile2D, - const std::vector> &arcs2d) { + static PtBoundaryRelation pmcLoop2d(const Vec2 &p2D, const Pt2Array &loop2D, + const std::vector> &arcs2d) { size_t segCount = arcs2d.size(); // 先判断是否在outline上 // 顺便判断点-扇的位置关系 bool inFan = false; int onLinesegButHasBugle = -1; for (int i = 0; i < segCount; ++i) { - const Vec2 &a = profile2D[i]; - const Vec2 &b = profile2D[(i + 1) % segCount]; + const Vec2 &a = loop2D[i]; + const Vec2 &b = loop2D[(i + 1) % segCount]; if (arcs2d[i].h <= EPS) { //straight line segment if (isPointOnSegment(p2D, a, b)) { @@ -184,8 +222,8 @@ private: int crossings = 0; for (int i = 0; i < segCount; ++i) { - const Vec2 &a = profile2D[i]; - const Vec2 &b = profile2D[(i + 1) % segCount]; + const Vec2 &a = loop2D[i]; + const Vec2 &b = loop2D[(i + 1) % segCount]; assert(isPointOnSegment(p, a, b)); // if (isPointOnSegment(p2D, a, b)) // { @@ -229,14 +267,13 @@ private: return ptInPolygon(p2D) ^ inFan ? Inside : Outside; } - static ClosestDescOnSeg distance2Profile2D(const Vec2 &p2D, const Pt2Array &profile2D, - const std::vector> &arcs2d) { + static ClosestDescOnSeg disLoop2D(const Vec2 &p2D, const Pt2Array &loop2D, + const std::vector> &arcs2d) { size_t segCount = arcs2d.size(); - assert(profile2D.size() == segCount); + assert(loop2D.size() == segCount); ClosestDescOnSeg res{}; for (int i = 0; i < segCount; ++i) { - auto disDesc = - distance2Arc2D(p2D, profile2D[i], profile2D[(i + 1) % segCount], arcs2d[i]); + auto disDesc = distance2Arc2D(p2D, loop2D[i], loop2D[(i + 1) % segCount], arcs2d[i]); if (res.dis > disDesc.dis) { res.dis = disDesc.dis; 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)); // } }; - -class ExtrudedSolidPolynomialLine : public IExtrudedSolid { -protected: - PolynomialLine _axis; -}; diff --git a/include/vec.hpp b/include/vec.hpp index fdd5980..900b332 100644 --- a/include/vec.hpp +++ b/include/vec.hpp @@ -1,5 +1,6 @@ #pragma once +#include "common.hpp" #include "real.hpp" #include #include @@ -19,13 +20,15 @@ public: std::copy(values.begin(), values.end(), data.begin()); } + VecBase(real v) : data{v} {} + + VecBase(const VecBase &v) : data(v.data) {} + template explicit VecBase(Args... args) : data{static_cast(args)...} { static_assert(sizeof...(args) == N, "Argument count must match vector size."); } - explicit VecBase(const VecBase &v) { data = v.data; } - VecBase &operator=(VecBase v) { *this = std::move(v); return *this; @@ -93,9 +96,21 @@ public: real norm() const { return std::sqrt(dot(*this)); } + real l2() const { return dot(*this); } + Derived normalize() const { return static_cast(*this / norm()); } Derived reflect(const Derived &n) const { return static_cast(*this - n * 2 * dot(n)); } + + bool operator==(const VecBase &v) const { + for (size_t i = 0; i < N; ++i) { + if (!isEqual(data[i], v[i])) + return false; + } + return true; + } + + Derived operator-() const { return static_cast(*this * -1); } }; // Vec<2> 特化 @@ -113,16 +128,16 @@ public: real &x() { return data[0]; } real &y() { return data[1]; } - const real &x() const { return data[0]; } - const real &y() const { return data[1]; } + [[nodiscard]] const real &x() const { return data[0]; } + [[nodiscard]] const real &y() const { return data[1]; } real &u() { return data[0]; } real &v() { return data[1]; } - const real &u() const { return data[0]; } - const real &v() const { return data[1]; } + [[nodiscard]] const real &u() const { return data[0]; } + [[nodiscard]] const real &v() const { return data[1]; } - real cross(const Vec2 &v) const { return x() * v.y() - v.x() * y(); } + [[nodiscard]] real cross(const Vec2 &v) const { return x() * v.y() - v.x() * y(); } }; class Vec3 : public VecBase { @@ -140,21 +155,23 @@ public: real &y() { return data[1]; } real &z() { return data[2]; } - real x() const { return data[0]; } - real y() const { return data[1]; } - real z() const { return data[2]; } + [[nodiscard]] real x() const { return data[0]; } + [[nodiscard]] real y() const { return data[1]; } + [[nodiscard]] real z() const { return data[2]; } real &u() { return data[0]; } real &v() { return data[1]; } real &w() { return data[2]; } - real u() const { return data[0]; } - real v() const { return data[1]; } - real w() const { return data[2]; } + [[nodiscard]] real u() const { return data[0]; } + [[nodiscard]] real v() const { return data[1]; } + [[nodiscard]] real w() const { return data[2]; } - Vec3 cross(const Vec3 &v) const { + [[nodiscard]] Vec3 cross(const Vec3 &v) const { return {y() * v.z() - z() * v.y(), z() * v.x() - x() * v.z(), x() * v.y() - y() * v.x()}; } + + [[nodiscard]] bool isParallel(const Vec3 &v) const { return cross(v) == 0; } }; using Pt3Array = std::vector; diff --git a/require.md b/require.md index d3f6449..9f01477 100644 --- a/require.md +++ b/require.md @@ -82,15 +82,41 @@ virtual CPmSolid * create_face_helix(const PMSoft::CPMGePoint3DArray &pt3d, +## 螺旋路径拉伸 +```C++ +virtual CPmSolid * createHelix(const PMSoft::CPMGePoint3DArray &pt3d, + const PmGeDoubleArray bulges, + const PMSoft::CPMGePoint3D &axis_start, + const PMSoft::CPMGePoint3D &axis_end, + const PMSoft::CPMGeVector3D &start_dir, + BOOL handiness, + double radius, + double pitch); +virtual CPmSolid * createHelix(const PMSoft::CPMGePoint3DArray &pt3d, + const PmGeDoubleArray bulges, + const PMSoft::CPMGeVector3D &FaceNormal, + const PMSoft::CPMGePoint3D &axis_start, + const PMSoft::CPMGePoint3D &axis_end, + const PMSoft::CPMGeVector3D &start_dir, + BOOL handiness, + double radius, + double pitch, + BOOL bIsFace = FALSE); +virtual CPmSolid * create_face_helix(const PMSoft::CPMGePoint3DArray &pt3d, + const PmGeDoubleArray bulges, + const PMSoft::CPMGePoint3D &axis_start, + const PMSoft::CPMGePoint3D &axis_end, + const PMSoft::CPMGeVector3D &start_dir, + BOOL handiness, + double radius, + double pitch); +``` -////////////////////////////////////////////////////////////////////////// - /// 体生成 - ////////////////////////////////////////////////////////////////////////// // 两截面蒙皮(生成台体) virtual CPmSolid * create_by_faces_to_skin(PmDbPolyline * pStartPoly, PmDbPolyline * pEndPoly, PMSoft::CPMGeVector3D normal/*,BOOL bIsFace*/) override; @@ -104,28 +130,6 @@ virtual CPmSolid * create_face_helix(const PMSoft::CPMGePoint3DArray &pt3d, CPmSolid * create_by_faces_to_skin(const CArray &jmsPts3d, const CArray &jmsBulges, const CArray &normalArr, BOOL bIsFace); - // 多线段蒙皮(线段不含弧) - CPmSolid * createFacesBySkinWithSegs(const CArray &segs, BOOL bIsFace); - - virtual CPmSolid * createBox(const PMSoft::CPMGePoint3D& p,double xLen,double yLen,double zLen); - virtual CPmSolid * createTorus(const PMSoft::CPMGePoint3D& p, double majorRadius, double minorRadius); - virtual CPmSolid * createSphere(const PMSoft::CPMGePoint3D& p, double radius); - void CreateCircPoints(int nNum, const PMSoft::CPMGePoint3D& pt, const PMSoft::CPMGePoint3D& ptCent, PMSoft::CPMGePoint3DArray& ptCircArr); - CPmSolid * CreateBall(const PMSoft::CPMGePoint3D& ptCent, double dRadius, PMSoft::PMBoolean3d::Ent3dData& drawData); - CPmSolid * CreateBall(const PMSoft::CPMGePoint3D& ptCent, double dRadius); - CPmSolid * CreateBall(const PMSoft::CPMGePoint3D& ptCent, double dRadius, double dHeight); - CPmSolid * CreateBall(const PMSoft::CPMGePoint3D& ptCent, double dRadius, double dHeight, PMSoft::PMBoolean3d::Ent3dData& drawData); - virtual CPmSolid * CreateBallBoard(const PMSoft::CPMGePoint3D& ptCent, double dHeight, double dRadius, double dBoardHeight); - virtual CPmSolid * createPipe(const PMSoft::CPMGePoint3D& axisStart, PMSoft::CPMGePoint3D& axisEnd, - const PMSoft::CPMGeVector3D& baseNormal, - double dblOuterRadius, double dblInnerRadius); - virtual CPmSolid * createCone(const PMSoft::CPMGePoint3D& axisStart, const PMSoft::CPMGePoint3D& axisEnd, - double radius1, double radius2); - virtual CPmSolid * createEllipsoid(const PMSoft::CPMGePoint3D &basept,double height,double radius1,double radius2,double radius3); - virtual CPmSolid * createPyramid(const PMSoft::CPMGePoint3DArray &Pt3d, const PMSoft::CPMGeVector3D &plgNormal, - const PMSoft::CPMGePoint3D &apex); - virtual CPmSolid * createPyramid(const PMSoft::CPMGePoint3DArray &Pt3d, const PMSoft::CPMGeVector3D &plgNormal, - const PMSoft::CPMGePoint3DArray &apexs); virtual CPmSolid * createHelix(const PMSoft::CPMGePoint3DArray &pt3d, const PmGeDoubleArray bulges, const PMSoft::CPMGePoint3D &axis_start,