Browse Source

analytical 3D closest arc & multi polylines for one profile

master
gjj 4 months ago
parent
commit
f721b9a95b
  1. 4
      .clang-tidy
  2. 8
      include/common.hpp
  3. 183
      include/line.hpp
  4. 187
      include/solid.hpp
  5. 220
      require.md

4
.clang-tidy

@ -1,9 +1,12 @@
Checks: "
-*,
bugprone-*,
-bugprone-easily-swappable-parameters,
performance-*,
readability-*,
-readability-braces-around-statements,
misc-*,
-misc-non-private-member-variables-in-classes,
clang-analyzer-*,
clang-diagnostic-*,
cppcoreguidelines-*,
@ -16,6 +19,7 @@ Checks: "
-modernize-use-trailing-return-type,
-cppcoreguidelines-magic-numbers,
-cppcoreguidelines-init-variables,
-cppcoreguidelines-pro-type-member-init,
"
WarningsAsErrors: ''

8
include/common.hpp

@ -1,8 +1,14 @@
#pragma once
#include "real.hpp"
#include <limits>
#include <numbers>
enum PtBoundaryRelation { Inside = -1, OnBoundary, Outside = 1 };
bool isEqual(double a, double b) {
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;
}

183
include/line.hpp

@ -34,6 +34,7 @@ struct ClosestDescOnSeg {
class ILine {
public:
int aaa;
virtual ~ILine() = default;
virtual Vec3 eval(real param) = 0;
@ -50,7 +51,7 @@ struct CircularArc {
VecType center;
real radius;
real theta;
real h;
real h = -1; // straight line for h <= 0.
VecType u;
VecType v;
VecType inCircleDir;
@ -61,6 +62,12 @@ struct CircularArc {
};
;
struct AA {
int a;
int b;
void print() const { std::cout << a << " " << b << std::endl; }
};
const real DISC_ARC_ANGLE = std::numbers::pi * 0.125;
class Polyline : public ILine {
@ -87,6 +94,10 @@ public:
[[nodiscard]] bool isClosed() const { return _closed; }
[[nodiscard]] const std::vector<CircularArc<Vec3>> &getCircularArcs() const {
return circularArcs;
}
private:
Pt3Array _points;
std::vector<real> _bugles;
@ -143,90 +154,128 @@ public:
return -arc.radius * (arc.u * std::cos(phi) + arc.v * std::cos(phi));
}
// ClosestDescOnSeg getClosestParam(const Vec3 &p) override {
// real closestDis = std::numeric_limits<real>::max();
// real closestParam;
// for (int i = 0; i < _bugles.size(); ++i) {
// const Vec3 &A = _points[i];
// const Vec3 &B = _points[(i + 1) % _points.size()];
// const auto &arc = circularArcs[i];
// real dis2Seg = segPtDist(p, A, B).dis;
// if (dis2Seg - arc.h > closestDis)
// continue;
// if ((A - p).norm() < closestDis) {
// closestDis = (A - p).norm();
// closestParam = i;
// }
// if ((B - p).norm() < closestDis) {
// closestDis = (B - p).norm();
// closestParam = i + 1;
// }
// int segInsertedCnt = arc.theta / DISC_ARC_ANGLE;
// for (int j = 0; j < segInsertedCnt; ++j) {
// real insertParam = i + j * DISC_ARC_ANGLE / arc.theta;
// const Vec3 insertPt = eval(insertParam);
// real dis2InsertPt = (p - insertPt).norm();
// if (dis2InsertPt < closestDis) {
// closestDis = dis2InsertPt;
// closestParam = insertParam;
// }
// }
// }
// // TODO: 为了鲁棒和精度,应该在每个可能最近的seg上做newton iteration
// int seg = static_cast<int>(closestParam);
// // Q = arc.center + arc.radius * (arc.u * std::cos(phi) + arc.v *
// // std::sin(phi)) d2 = (Q - p)^2
// Vec3 q = eval(closestParam);
// Vec3 qDer1 = der1(closestParam);
// Vec3 qDer2 = der2(closestParam);
// real lDer1 = (q - p).dot(qDer1);
// int iter = 0;
// while (fabs(lDer1) > std::numeric_limits<real>::epsilon() * 1e6) {
// closestParam -= lDer1 / (qDer1.dot(qDer1) + (q - p).dot(qDer2)); // -der1 / der2
// q = eval(closestParam);
// qDer1 = der1(closestParam);
// qDer2 = der2(closestParam);
// lDer1 = (q - p).dot(qDer1);
// printf("After iter %d, dL is %lf\n", iter, lDer1);
// if (closestParam < seg - std::numeric_limits<real>::epsilon()) {
// closestParam = seg;
// closestDis = (_points[seg] - p).norm();
// break;
// }
// if (closestParam > seg + 1 + std::numeric_limits<real>::epsilon()) {
// closestParam = seg + 1;
// closestDis = (_points[(seg + 1) % _points.size()] - p).norm();
// break;
// }
// closestDis = (q - p).norm();
// iter++;
// }
// return {closestParam, closestDis};
// }
ClosestDescOnSeg getClosestParam(const Vec3 &p) override {
real closestDis = std::numeric_limits<real>::max();
real closestParam;
ClosestDescOnSeg closestDes{};
for (int i = 0; i < _bugles.size(); ++i) {
const Vec3 &A = _points[i];
const Vec3 &B = _points[(i + 1) % _points.size()];
const auto &arc = circularArcs[i];
real dis2Seg = segPtDist(p, A, B).dis;
if (dis2Seg - arc.h > closestDis)
continue;
if ((A - p).norm() < closestDis) {
closestDis = (A - p).norm();
closestParam = i;
}
if ((B - p).norm() < closestDis) {
closestDis = (B - p).norm();
closestParam = i + 1;
}
int segInsertedCnt = arc.theta / DISC_ARC_ANGLE;
for (int j = 0; j < segInsertedCnt; ++j) {
real insertParam = i + j * DISC_ARC_ANGLE / arc.theta;
const Vec3 insertPt = eval(insertParam);
real dis2InsertPt = (p - insertPt).norm();
if (dis2InsertPt < closestDis) {
closestDis = dis2InsertPt;
closestParam = insertParam;
const Vec3 &a = _points[i];
const Vec3 &b = _points[(i + 1) % _points.size()];
const CircularArc<Vec3> &arc = circularArcs[i];
const Vec3 &o = arc.center;
// p 到圆弧平面的投影
const Vec3 projPt = p - _normal.dot(p - a) * _normal;
// projPt到圆的最近点
const Vec3 clsPtOnCircle = o + arc.radius * (projPt - o).normalize();
if ((clsPtOnCircle - a).dot(arc.inCircleDir) > 0) {
// 在圆弧上
real dis = (p - clsPtOnCircle).norm();
if (dis < closestDes.dis) {
closestDes.dis = dis;
Vec3 oa = a - o;
Vec3 oClsPt = clsPtOnCircle - o;
real R2 = arc.radius * arc.radius;
real cosTheta = (oa).dot(oClsPt) / R2;
real theta = std::acos(cosTheta); // [0, pi]
if ((oa.cross(oClsPt)).dot(_normal) < 0) {
theta = 2 * std::numbers::pi - theta;
}
closestDes.t = i + theta / arc.theta;
}
continue;
}
}
// TODO: 为了鲁棒和精度,应该在每个可能最近的seg上做newton iteration
int seg = static_cast<int>(closestParam);
// Q = arc.center + arc.radius * (arc.u * std::cos(phi) + arc.v *
// std::sin(phi)) d2 = (Q - p)^2
Vec3 q = eval(closestParam);
Vec3 qDer1 = der1(closestParam);
Vec3 qDer2 = der2(closestParam);
real lDer1 = (q - p).dot(qDer1);
int iter = 0;
while (abs(lDer1) > std::numeric_limits<real>::epsilon() * 1e6) {
closestParam -= lDer1 / (qDer1.dot(qDer1) + (q - p).dot(qDer2)); // -der1 / der2
q = eval(closestParam);
qDer1 = der1(closestParam);
qDer2 = der2(closestParam);
lDer1 = (q - p).dot(qDer1);
printf("After iter %d, dL is %lf\n", iter, lDer1);
if (closestParam < seg - std::numeric_limits<real>::epsilon()) {
closestParam = seg;
closestDis = (_points[seg] - p).norm();
break;
}
if (closestParam > seg + 1 + std::numeric_limits<real>::epsilon()) {
closestParam = seg + 1;
closestDis = (_points[(seg + 1) % _points.size()] - p).norm();
break;
real paDis = (p - a).norm();
real pbDis = (p - b).norm();
if (paDis < closestDes.dis) {
closestDes.dis = paDis;
closestDes.t = i;
} else {
closestDes.dis = pbDis;
closestDes.t = i + 1;
}
closestDis = (q - p).norm();
iter++;
}
return {closestParam, closestDis};
return closestDes;
}
const std::vector<CircularArc<Vec3>> &getCircularArcs() const { return circularArcs; }
void print() const {
if (_closed)
printf("Closed Polyline: \n");
std::cout << "Closed Polyline: \n";
else
printf("Open Polyline: \n");
printf("Points: {\n");
std::cout << "Open Polyline: \n";
std::cout << "Points: {\n";
for (int i = 0; i < _points.size(); ++i) {
printf("<%lf, %lf, %lf>", _points[i].x(), _points[i].y(), _points[i].z());
std::cout << _points[i].x() << ", " << _points[i].y() << ", " << _points[i].z() << ">";
if (i != _points.size() - 1)
printf(", ");
std::cout << ", ";
}
std::cout << "}" << std::endl;
printf("Bugles: {\n");
std::cout << "}\n";
std::cout << "的可变参数Bugles: {\n";
for (int i = 0; i < _bugles.size(); ++i) {
printf("%lf", _bugles[i]);
std::cout << _bugles[i];
if (i != _bugles.size() - 1)
printf(", ");
std::cout << ", ";
}
std::cout << "}" << std::endl;
std::cout << "}\n";
}
static ClosestDescOnSeg segPtDist(const Vec3 &p, const Vec3 &A, const Vec3 &B) {
Vec3 AB = B - A;
Vec3 AP = p - A;

187
include/solid.hpp

@ -2,7 +2,10 @@
#include "common.hpp"
#include "real.hpp"
#include <cassert>
#include <cstddef>
#include <utility>
#include <vector>
#include "vec.hpp"
#include "line.hpp"
@ -12,88 +15,110 @@ public:
virtual real sdf(const Vec3 &p) = 0;
};
Vec2 get2DRepOf3DPt(const Vec3 &pt3D, const Vec3 &u, const Vec3 &v, const Vec3 &localO) {
inline Vec2 get2DRepOf3DPt(const Vec3 &pt3D, const Vec3 &u, const Vec3 &v, const Vec3 &localO) {
Vec3 OP = pt3D - localO;
return {OP.dot(u), OP.dot(v)};
}
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();
}
class IExtrudedSolid : public ISolid {
public:
Polyline _profile; // TODO: may be replaced by const ref to profile
std::vector<Polyline> _profiles; // TODO: may be replaced by const ref to profile
real _rScale;
public:
IExtrudedSolid(Polyline profile, real rScale) : _profile(std::move(profile)), _rScale(rScale) {}
IExtrudedSolid(std::vector<Polyline> profiles, real rScale)
: _profiles(std::move(profiles)), _rScale(rScale) {}
};
/**
* calculate winding number of a point w.r.t. a segment ab
*/
real unsignedWindingNumberSegment(const Vec3 &p, const Vec3 &a, const Vec3 &b,
const Vec3 &refNormal) {
Vec3 pa = a - p;
Vec3 pb = b - p;
return std::acos(std::clamp(pa.dot(pb) / (pa.norm() * pb.norm()), static_cast<real>(-1.),
static_cast<real>(1.)))
/ (std::numbers::pi * 2);
}
// inline real unsignedWindingNumberSegment(const Vec3 &p, const Vec3 &a, const Vec3 &b,
// const Vec3 &refNormal) {
// Vec3 pa = a - p;
// Vec3 pb = b - p;
// return std::acos(std::clamp(pa.dot(pb) / (pa.norm() * pb.norm()), static_cast<real>(-1.),
// static_cast<real>(1.)))
// / (std::numbers::pi * 2);
// }
class ExtrudedSolidPolyline : public IExtrudedSolid {
private:
Polyline _axis;
Pt2Array _localProfile2D;
std::vector<CircularArc<Vec2>> _localArcs2d;
std::vector<Pt2Array> _localProfiles2D;
std::vector<std::vector<CircularArc<Vec2>>> _localArcs2d;
// Pt2Array _localCircleCenter2D;
// Pt2Array _localInCircleDir;
public:
ExtrudedSolidPolyline(Polyline profile, Polyline axis, real rScale)
: IExtrudedSolid(std::move(profile), rScale), _axis(std::move(axis)) {
assert(_profile.isClosed());
ExtrudedSolidPolyline(std::vector<Polyline> profiles, Polyline axis, real rScale)
: IExtrudedSolid(std::move(profiles), rScale), _axis(std::move(axis)) {
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);
int segCount = _profile.getPoints().size();
_localProfile2D.resize(segCount);
_localArcs2d.resize(segCount);
// _localInCircleDir.resize(segCount);
// _localCircleCenter2D.resize(segCount);
for (int i = 0; i < segCount; ++i) {
_localProfile2D[i] = get2DRepOf3DPt(_profile.getPoints()[i] - Q, N, B, Q);
auto &arc2d = _localArcs2d[i];
const auto &arc3d = _profile.getCircularArcs()[i];
arc2d.center = get2DRepOf3DPt(arc3d.center - Q, N, B, Q);
arc2d.inCircleDir = get2DRepOf3DDir(arc3d.inCircleDir, N, B);
arc2d.radius = arc3d.radius;
size_t profileCount = _profiles.size();
_localProfiles2D.resize(profileCount);
_localArcs2d.resize(profileCount);
for (int i = 0; i < _profiles.size(); ++i) {
const auto &profile = _profiles[i];
size_t segCount = profile.getPoints().size();
_localProfiles2D[i].resize(segCount);
_localArcs2d[i].resize(segCount);
for (int j = 0; j < segCount; ++j) {
// TODO:
_localProfiles2D[i][j] = get2DRepOf3DPt(profile.getPoints()[j] - Q, N, B, 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.radius = arc3d.radius;
arc2d.theta = arc3d.theta;
arc2d.h = arc3d.h;
}
}
}
real sdf(const Vec3 &p) override {
ClosestDescOnSeg closestDesc = _axis.getClosestParam(p);
ClosestDescOnSeg closestDescToAxis = _axis.getClosestParam(p);
// TNB coordinate system
auto t = closestDesc.t;
auto t = closestDescToAxis.t;
Vec3 T = _axis.der1(t).normalize();
Vec3 N = _axis.der2(t).normalize();
Vec3 B = T.cross(N);
Vec3 Q = _axis.eval(t);
Vec3 QP = p - Q;
auto p2D = get2DRepOf3DPt(QP, N, B, Q);
// TODO: to test if p2D is in _localProfile2D
// for (auto i = 0; i < _localProfile2D.size(); ++i) {
// }
PtBoundaryRelation ptProfileRelation = getPtProfileRelation(p2D);
if (ptProfileRelation == OnBoundary) {
return 0; // TODO: 判断OnBoundary的过程可以加一点容差
// 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;
}
}
ClosestDescOnSeg closestDescOnProfile = distance2Profile2D(p2D);
return closestDescOnProfile.dis * static_cast<int>(ptProfileRelation);
// distance
ClosestDescOnSeg closestDescToProfile{};
for (int i = 0; i < _localArcs2d.size(); ++i) {
ClosestDescOnSeg closestDescTemp =
distance2Profile2D(p2D, _localProfiles2D[i], _localArcs2d[i]);
if (closestDescTemp.dis < closestDescToProfile.dis) {
closestDescToProfile = closestDescTemp;
}
}
return closestDescToProfile.dis * static_cast<int>(ptProfileRelation);
}
private:
@ -103,19 +128,18 @@ private:
* out + in = in
* out + out = out
*/
PtBoundaryRelation getPtProfileRelation(const Vec2 &p2D) {
assert(_profile.isClosed());
int segCount = _profile.getBugles().size();
static PtBoundaryRelation getPtProfileRelation(const Vec2 &p2D, const Pt2Array &profile2D,
const std::vector<CircularArc<Vec2>> &arcs2d) {
size_t segCount = arcs2d.size();
// 先判断是否在outline上
// 顺便判断点-扇的位置关系
bool inFan = false;
int onLinesegButHasBugle = -1;
for (int i = 0; i < segCount; ++i) {
const Vec2 &a = _localProfile2D[i];
const Vec2 &b = _localProfile2D[(i + 1) % segCount];
if (_profile.getBugles()[i] == 0) {
//line segment
const Vec2 &a = profile2D[i];
const Vec2 &b = profile2D[(i + 1) % segCount];
if (arcs2d[i].h <= EPS) {
//straight line segment
if (isPointOnSegment(p2D, a, b)) {
return OnBoundary;
}
@ -125,9 +149,9 @@ private:
onLinesegButHasBugle = i;
break;
}
const auto &arc = _profile.getCircularArcs()[i];
real po = (p2D - _localArcs2d[i].center).norm();
if ((p2D - a).dot(_localArcs2d[i].inCircleDir) > 0) {
const auto &arc = arcs2d[i];
real po = (p2D - arc.center).norm();
if ((p2D - a).dot(arc.inCircleDir) > 0) {
if (po == arc.radius) {
return OnBoundary;
}
@ -151,13 +175,13 @@ private:
int majorityIn = 0; // 在多边形内的射线计数
int majorityOut = 0; // 在多边形外的射线计数
for (int rayIdx = 0; rayIdx < numRays; ++rayIdx) {
double angle = (2.0 * std::numbers::pi * rayIdx) / numRays;
double angle = (PI2 * rayIdx) / numRays;
Vec2 rayDir(cos(angle), sin(angle));
int crossings = 0;
for (int i = 0; i < segCount; ++i) {
const Vec2 &a = _localProfile2D[i];
const Vec2 &b = _localProfile2D[(i + 1) % segCount];
const Vec2 &a = profile2D[i];
const Vec2 &b = profile2D[(i + 1) % segCount];
assert(isPointOnSegment(p, a, b));
// if (isPointOnSegment(p2D, a, b))
// {
@ -195,23 +219,20 @@ private:
if (onLinesegButHasBugle != -1) {
// 需要特殊考虑的情况
// 从p2D向inCircle方向前进一小步
Vec2 samplePt = p2D
+ _localArcs2d[onLinesegButHasBugle].center
* std::numeric_limits<real>::epsilon() * 1e6;
Vec2 samplePt = p2D + arcs2d[onLinesegButHasBugle].inCircleDir * EPS;
return !ptInPolygon(samplePt) ? Inside : Outside; // 取反
}
return ptInPolygon(p2D) ^ inFan ? Inside : Outside;
// TODO: 返回on的情况
}
ClosestDescOnSeg distance2Profile2D(const Vec2 &p2D) {
// TODO: 2D 下点到圆弧的距离应该可以直接算,不用这么迭代!
assert(_profile.isClosed());
static ClosestDescOnSeg distance2Profile2D(const Vec2 &p2D, const Pt2Array &profile2D,
const std::vector<CircularArc<Vec2>> &arcs2d) {
size_t segCount = arcs2d.size();
assert(profile2D.size() == segCount);
ClosestDescOnSeg res{};
for (int i = 0; i < _localArcs2d.size(); ++i) {
for (int i = 0; i < segCount; ++i) {
auto disDesc =
distance2Arc2D(p2D, _localProfile2D[i],
_localProfile2D[(i + 1) % _localArcs2d.size()], _localArcs2d[i]);
distance2Arc2D(p2D, profile2D[i], profile2D[(i + 1) % segCount], arcs2d[i]);
if (res.dis > disDesc.dis) {
res.dis = disDesc.dis;
res.t = i + disDesc.t;
@ -220,20 +241,20 @@ private:
return res;
}
ClosestDescOnSeg distance2Arc2D(const Vec2 &p2D, const Vec2 &a, const Vec2 &b,
const CircularArc<Vec2> &arc) {
static ClosestDescOnSeg distance2Arc2D(const Vec2 &p2D, const Vec2 &a, const Vec2 &b,
const CircularArc<Vec2> &arc) {
const Vec2 &center = arc.center;
Vec2 op = p2D - center;
Vec2 q = center + arc.radius * op.normalize(); // closest pt on circle
Vec2 oq = q - center;
Vec2 oa = a - center;
// 判断q是否在弧上
if ((q - a).dot(arc.inCircleDir) > 0) {
// 计算参数
real normMulti = arc.radius * oq.norm();
real cosTheta = (oa).dot(oq) / normMulti;
real sinTheta = (oa).cross(oq) / normMulti;
return {atan2(sinTheta, cosTheta), (p2D - q).norm()};
Vec2 oq = q - center;
Vec2 oa = a - center;
real R2 = arc.radius * arc.radius;
real cosTheta = (oa).dot(oq) / R2;
real sinTheta = (oa).cross(oq) / R2;
return {atan2(sinTheta, cosTheta) / arc.theta, (p2D - q).norm()};
}
real paDis = (a - p2D).norm();
@ -243,12 +264,13 @@ private:
return {1, pbDis};
}
bool isOn2DPolyline(const Vec2 &p2D) {
int segCount = _profile.getBugles().size();
bool isOn2DPolyline(const Vec2 &p2D, const Pt2Array &profile2D,
const std::vector<CircularArc<Vec2>> &arcs2d) {
size_t segCount = arcs2d.size();
for (int i = 0; i < segCount; ++i) {
const Vec2 &a = _localProfile2D[i];
const Vec2 &b = _localProfile2D[(i + 1) % segCount];
if (_profile.getBugles()[i] == 0) {
const Vec2 &a = profile2D[i];
const Vec2 &b = profile2D[(i + 1) % segCount];
if (arcs2d[i].h <= EPS) {
//line segment
if (isPointOnSegment(p2D, a, b)) {
return true;
@ -256,13 +278,16 @@ private:
continue;
}
}
// TODO: 没写完,但是暂时用不到
return true;
}
bool isPointOnSegment(const Vec2 p, const Vec2 &a, const Vec2 &b) {
static bool isPointOnSegment(const Vec2 &p, const Vec2 &a, const Vec2 &b) {
// check collinearity
double crossProduct = (p[1] - a[1]) * (b[0] - a[0]) - (p[0] - a[0]) * (b[1] - a[1]);
if (!isEqual(crossProduct, 0))
if (!isEqual(crossProduct, 0)) {
return false; // Not collinear
}
// Check if point is within segment bounds
return (p[0] >= std::min(a[0], b[0]) && p[0] <= std::max(a[0], b[0])

220
require.md

@ -78,3 +78,223 @@ virtual CPmSolid * create_face_helix(const PMSoft::CPMGePoint3DArray &pt3d,
double radius,
double pitch);
```
//////////////////////////////////////////////////////////////////////////
/// 体生成
//////////////////////////////////////////////////////////////////////////
// 两截面蒙皮(生成台体)
virtual CPmSolid * create_by_faces_to_skin(PmDbPolyline * pStartPoly, PmDbPolyline * pEndPoly, PMSoft::CPMGeVector3D normal/*,BOOL bIsFace*/) override;
// 多截面蒙皮(截面的边均为线段)
virtual CPmSolid * create_by_faces_to_skin(const CArray<PMSoft::CPMGePoint3DArray, PMSoft::CPMGePoint3DArray&> &jmsPts3d, BOOL bIsFace) override;
// 多截面蒙皮(截面的边可能存在凸度)
virtual CPmSolid * create_by_faces_to_skin(const CArray<PMSoft::CPMGePoint3DArray, PMSoft::CPMGePoint3DArray&> &jmPt3d, const CArray<PmGeDoubleArray, PmGeDoubleArray&> &jmbulge,
CArray<PMSoft::CPMGeVector3D, PMSoft::CPMGeVector3D&> &normalArr, const PMSoft::CPMGePoint3DArray &pathPt3d, BOOL bIsFace) override;
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,
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);
/**
* @brief 截面绕轴旋转生成体
*
*
* @note :
* @param : 截面、基点、轴向量、旋转角度
* @return:
* @author: csl
* @date : [11/7/2022]
*/
virtual CPmSolid * createSolidByFaceAroundAxis(const PMSoft::CPMGePoint3DArray &pt3d, const PmGeDoubleArray &bulges, const PMSoft::CPMGeVector3D &plgNormal,
const PMSoft::CPMGePoint3D &apex, const PMSoft::CPMGeVector3D &axis,
double angle) override;
virtual CPmSolid * createSphereFace(const PMSoft::CPMGePoint3D& p, double radius);
virtual CPmSolid * create_face_cylinder_cone(const PMSoft::CPMGePoint3D& axisStart, const PMSoft::CPMGePoint3D& axisEnd, double radius1, double radius2, double start = 0, double end = 360);
virtual CPmSolid * extrudeAdvance(PmDbPolyline * pExtrudePoly,
const PMSoft::CPMGePoint3D &fixedPt,
const PMSoft::CPMGeVector3D &plgNormal,
const PMSoft::CPMGeVector3D &extusionVector,
double scaleFactor,
double twistAngle);
virtual CPmSolid * extrudeAlongPath(const PMSoft::CPMGePoint3DArray &pt3d,
const PmGeDoubleArray &bulge,
PMSoft::CPMGeVector3D normal,
PmDbPolyline * path,
BOOL IsInteset = FALSE) override;
/**
* @brief 带洞截面沿路径拉伸
*
*
* @note :
* @param : 截面必须共面,数组首个元素必须为外包,其余元素为内部洞;拉伸路径可以闭合
* @return:
* @author: csl
* @date : [11/7/2022]
*/
virtual CPmSolid * extrudeAlongPath(const CArray<PmDbPolyline *> & polys,
PmDbPolyline * path) override;
virtual BOOL GetExtents(const CPmSolid *pEntity, PmExtents& extents);
virtual InterferenceType checkInterferenceType(const CPmSolid* Ent,const CPmSolid* otherEnt,double dTol = 0.01);
virtual CPmSolid * extrude(const PMSoft::CPMGePoint3DArray &pt3d, const PmGeDoubleArray &bulge, const PMSoft::CPMGePoint3D &fixedPt, const PMSoft::CPMGeVector3D &plgNormal, const PMSoft::CPMGeVector3D &extusionVector, double scaleFactor, double twistAngle) override;
CPmSolid * extrude(const PMSoft::CPMGePoint3DArray & pt3d, const PmGeDoubleArray & bulge, const PMSoft::CPMGePoint3D &fixedPt, const PMSoft::CPMGeVector3D &extusionVector);
virtual CPmSolid * extrude(PmDbPolyline * pExtrudePoly,
const PMSoft::CPMGePoint3D &fixedPt,
const PMSoft::CPMGeVector3D &plgNormal,
const PMSoft::CPMGeVector3D &extusionVector,
double scaleFactor,
double twistAngle);
// (新弧形) 面拉伸为柱类体测试接口
PMSoft::PMBoolean3d::CCylinderLikeBody * extrudeCylinderBodyTest(const PMSoft::OdexBase2d::PmDbPLine& plSection, const PMSoft::CPMGeVector3D& vecExtru);
PMSoft::PMBoolean3d::CCylinderLikeBody * extrudeCylinderBodyTest(const PMSoft::CPMGePoint3DArray& pts, const PMSoft::PmGeDoubleArray& bulges, const PMSoft::CPMGeVector3D& vecNormal, const PMSoft::CPMGeVector3D& vecExtru);
/**
* @brief 带洞截面拉伸
*
*
* @note :
* @param : 数组首个元素必须为外包,其余元素为内部洞
* @return:
* @author: csl
* @date : [11/7/2022]
*/
virtual CPmSolid * extrude(const CArray<PmDbPolyline *> & polys,
const PMSoft::CPMGePoint3D &fixedPt,
const PMSoft::CPMGeVector3D &plgNormal,
const PMSoft::CPMGeVector3D &extusionVector,
double scaleFactor = 1.0,
double twistAngle = 0.0) override;
/**
* @brief 多段拉伸生成完整体(适用构造柱马牙槎)
*
*
* @note : 只在自主布尔中实现,ACIS未实现
* @param : polys为各段拉伸的起始截面,vctsExtru为每段拉伸的拉伸向量
* 截面与向量的数量应该相同,且至少为2个
* @return:
* @author: csl
* @date : [9/25/2023]
*/
virtual CPmSolid * extrudeStepByStep(const CArray<PmDbPolyline *> & polys, const CArray<PMSoft::CPMGeVector3D> & vctsExtru) override;
virtual CPmSolid * CreateFaceBody_extrude(const PMSoft::CPMGePoint3DArray & pt3d, const PmGeDoubleArray & bugle, const PMSoft::CPMGeVector3D &plgNormal, double dLength);
virtual CPmSolid * CreateFaceBody_extrude(const PMSoft::CPMGePoint3DArray & pt3d,const PmGeDoubleArray & bugle,const PMSoft::CPMGeVector3D &plgNormal,const PMSoft::CPMGeVector3D &extrudeVec);
virtual CPmSolid * CreateFaceBody_extrude(PmDbPolyline * ply, const PMSoft::CPMGeVector3D &plgNormal, const PMSoft::CPMGeVector3D & extrudeVec);
virtual CPmSolid * CreateFaceBody(const PMSoft::CPMGePoint3DArray & pt3d,const PmGeDoubleArray & bulge,const PMSoft::CPMGeVector3D &plgNormal);
virtual CPmSolid * CreateFaceBody(const PmDbPolyline * pFacePolyLine);
//生成自身带洞的面
virtual CPmSolid * CreateFaceBody(const CArray<PmDbPolyline *> & pFacePolyLineArr) override;
virtual CPmSolid * CreateFaceBody_extrudeAlongPath(const PMSoft::CPMGePoint3DArray & pt3d,const PmGeDoubleArray &bulge,PMSoft::CPMGeVector3D normal,PmDbPolyline* path,BOOL IsInteset = FALSE) override;
virtual void getSliceFace(CPmSolid * &pEntity,const PMSoft::CPMGePoint3D & pt, const PMSoft::CPMGeVector3D & normal, double dTol);
virtual CPmSolid* CreateBodyBySliceFace(CPmSolid * pEntity,const PMSoft::CPMGePoint3D & pt, const PMSoft::CPMGeVector3D & normal, double dExtrudeDis);
virtual BOOL GetEntity_AllFaces(CPmSolid * &pEntity);// 体构件转化为面构件
/// 隐藏不需要的面(适用人防墙业务)
virtual BOOL UnHookSpecialFaces(CPmSolid *& pSolid, CArray<CGeBorder, CGeBorder&> & brds);
virtual BOOL UnHookSpecialFaces(CPmSolid *& pSolid, CArray<CGeBorder, CGeBorder&> & brds, BOOL bNeedTransf);
/// 隐藏单面(适用人防墙业务),向量即为面法向量
virtual BOOL UnHookSingleFace(CPmSolid *& pSolid, const CGeBorder & brd, const PMSoft::CPMGeVector3D & normal);
//////////////////////////////////////////////////////////////////////////
/// 其他
//////////////////////////////////////////////////////////////////////////
virtual BOOL AddEntityToDbs(const CPMSolidArr & EntArr,CPM3dEntDataArr & entDataArr,CString & strACISFilePath);
BOOL RemoveVertexNotNeed(PMSoft::CPMGePoint3DArray & PtArr,PmGeDoubleArray & BulgeArr,int & iSize_Pt,int & iSize_Bulge);
/***************************************************************************************************************************************************/
virtual BOOL getCentroid(CPmSolid *pEntity, PMSoft::CPMGePoint3D &centroid);
//describe:获取所需实体的所有符合条件面,判断条件为实体面的法向量和传入向量符合条件
//notice:bGetOrMove,获取符合条件的还是去除符合条件的;bStrict,绝对符合条件还是接近条件(e.g 绝对条件为(线/面)同向时,接近条件为锐角;绝对条件为noZ时,接近条件为非xy平面)
//return:
//
//author:csl
//date:2022/9/14
virtual BOOL GetFaceSuitVec(CPmSolid *& pSolid, FaceNormalType normalType, BOOL bGetOrMove, BOOL bStrict, const PMSoft::CPMGeVector3D & vctNormalStd, const PMSoft::CPMGeTol& tol = PMSoft::CPMGeTol::gTol) override;
// 一组实体 向 指定面进行投影
virtual CPmSolid * CreateEntShadow(const CPMSolidArr & entArr, const PMSoft::CPMGePlane & plane) override;
// 将面实体拆分,每个面作为一个Solid,放在结果数组中。!内存需要调用方管理
virtual BOOL SplitFacesSolid(const CPmSolid * pFacesSolid, CPMSolidArr & facesSplitResult) override;
// 将面Solid转化为体Solid(原始面组必须能构成单个完整体,不能多面,也不能缺面)
virtual BOOL createBodyByFaces(CPmSolid *& pSolid) override;
Loading…
Cancel
Save