Browse Source

impl of helix & TBN for articulation of polylines

master
gjj 4 months ago
parent
commit
551723dc82
  1. 4
      .clang-tidy
  2. 12
      include/common.hpp
  3. 129
      include/line.hpp
  4. 142
      include/solid.hpp
  5. 45
      include/vec.hpp
  6. 54
      require.md

4
.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,

12
include/common.hpp

@ -2,13 +2,19 @@
#include "real.hpp"
#include <limits>
#include <numbers>
#include <cmath>
enum PtBoundaryRelation { Inside = -1, OnBoundary, Outside = 1 };
const real PI = std::numbers::pi;
const real PI2 = 2 * PI;
const real EPS = std::numeric_limits<real>::epsilon() * 1e2;
inline bool isEqual(double a, double b) {
// TODO
return a == b;
const real EPS_NEWTON_ITERATION = std::numeric_limits<real>::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;
}

129
include/line.hpp

@ -1,12 +1,15 @@
#pragma once
#include "common.hpp"
#include "real.hpp"
#include "vec.hpp"
#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstddef>
#include <iostream>
#include <limits.h>
#include <limits>
#include <memory>
#include <numbers>
#include <vector>
@ -31,7 +34,7 @@ struct ClosestDescOnSeg {
ClosestDescOnSeg(real _t, real _dis) : t(_t), dis(_dis) {}
ClosestDescOnSeg() : t(0), dis(std::numeric_limits<real>::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 <typename VecType> // 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<real>(_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<size_t>(std::ceil(_advanceLen / SEG_T));
std::vector<ClosestDescOnSeg> sampledSegs(segCount + 2); // 加上首尾
std::vector<Vec3> 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<real>(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 {

142
include/solid.hpp

@ -2,6 +2,7 @@
#include "common.hpp"
#include "real.hpp"
#include <array>
#include <cassert>
#include <cstddef>
#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) {
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
AxisLineType _axis;
real _rScale;
IExtrudedSolid(std::vector<Polyline> profiles, real rScale)
: _profiles(std::move(profiles)), _rScale(rScale) {}
IExtrudedSolidBase(std::vector<Polyline> 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 <typename AxisLineType>
class ExtrudedSolidPolyline : public IExtrudedSolidBase<Polyline> {
private:
Polyline _axis;
std::vector<Pt2Array> _localProfiles2D;
std::vector<std::vector<CircularArc<Vec2>>> _localArcs2d;
// Pt2Array _localCircleCenter2D;
// Pt2Array _localInCircleDir;
Vec3 _biNormal;
public:
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());
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,52 +96,81 @@ 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<int>(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的过程可以加一点容差
std::array<Vec3, 3> 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;
}
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{};
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<int>(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,
static PtBoundaryRelation pmcLoop2d(const Vec2 &p2D, const Pt2Array &loop2D,
const std::vector<CircularArc<Vec2>> &arcs2d) {
size_t segCount = arcs2d.size();
// 先判断是否在outline上
@ -140,8 +178,8 @@ private:
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,
static ClosestDescOnSeg disLoop2D(const Vec2 &p2D, const Pt2Array &loop2D,
const std::vector<CircularArc<Vec2>> &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;
};

45
include/vec.hpp

@ -1,5 +1,6 @@
#pragma once
#include "common.hpp"
#include "real.hpp"
#include <cmath>
#include <array>
@ -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 <typename... Args>
explicit VecBase(Args... args) : data{static_cast<real>(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<Derived>(*this / norm()); }
Derived reflect(const Derived &n) const { return static_cast<Derived>(*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<Derived>(*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<Vec3, 3> {
@ -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<Vec3>;

54
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<PMSoft::CPMGePoint3DArray, PMSoft::CPMGePoint3DArray&> &jmsPts3d, const CArray<PmGeDoubleArray, PmGeDoubleArray&> &jmsBulges,
const CArray<PMSoft::CPMGeVector3D, PMSoft::CPMGeVector3D&> &normalArr, BOOL bIsFace);
// 多线段蒙皮(线段不含弧)
CPmSolid * createFacesBySkinWithSegs(const CArray<PMSoft::CPMGePoint3DArray, PMSoft::CPMGePoint3DArray&> &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,

Loading…
Cancel
Save