- 积分
- 2191
- 明经币
- 个
- 注册时间
- 2022-4-4
- 在线时间
- 小时
- 威望
-
- 金钱
- 个
- 贡献
-
- 激情
-
|
本帖最后由 枫叶棋语 于 2025-6-28 21:15 编辑
 - #pragma once
- #include <vector>
- // AutoCAD几何头文件
- #include <gepnt2d.h>
- #include <gevec2d.h>
- #include <gelnsg2d.h>
- #include <CgalDef.h>
- #include <looplist.h>
- #include <gepnt3d.h>
- #include <dbpl.h>
- #include <getol.h>
- #include <type_traits>
- #include <utility>
- // ======================
- // AutoCAD兼容类型转换 ,使用LoopList 双向链表快速进行节点删增操作
- // ======================
- class VertexData {
- public:
- union {
- struct {
- double x;
- double y;
- };
- AcGePoint2d cadPoint;
- CgalPoint2d cgalPoint;
- };
- // 最简单的构造函数
- VertexData(const VertexData& other) :x(other.x), y(other.y) {}
- VertexData(const AcGePoint2d& p) : cadPoint(p) {}
- VertexData(const CgalPoint2d& p) : cgalPoint(p) {}
- VertexData(double x, double y) :x(x), y(y) {}
- // 隐式转换,自动转换类型
- operator const AcGePoint2d& () const { return cadPoint; }
- operator const CgalPoint2d& () const { return cgalPoint; }
- operator const AcGePoint3d& () const { return { x,y,0 }; }
- // 基本操作
- void setPoint(const AcGePoint2d& p) { cadPoint = p; }
- void setPoint(const CgalPoint2d& p) { cgalPoint = p; }
- bool operator==(const VertexData& other) const {
- return cadPoint.isEqualTo(other.cadPoint, { 1e-5,1e-5 });
- }
- bool operator < (const VertexData& other) const {
- if (x == other.x) {
- return y < other.y;
- }
- return x < other.x;
- }
- AcGeVector2d operator - (const VertexData& other) const {
- return this->cadPoint - other.cadPoint;
- }
- };
- class SimplePolygon : public LoopList<VertexData> {
- private:
- bool m_isclockwise = false;
- // 多边形处理函数
- void ensureLockWise(bool clockwise = true);
- bool isSelfIntersected() const;
- void removeCollinearVertices(AcGeTol tol = { 1e-5,1e-5 });
- template<typename ResultType>
- std::vector<ResultType> convertSegments() const;
- public:
- SimplePolygon() = default;
- SimplePolygon(AcDbPolyline* polyline, bool isclockwise = false);
- template <typename Container>
- SimplePolygon(const Container& points, bool isclockwise = false);
- bool isValid();
- CgalPolygon2d toCgalPolygon2d() const;
- auto toCgalLines() const { return convertSegments<CgalSegment2d>(); }
- auto toCadLines() const { return convertSegments<AcGeLineSeg2d>(); }
- auto toCgalPointPairs() const { return convertSegments<std::pair<CgalPoint2d, CgalPoint2d>>(); }
- auto toCadPointPairs() const { return convertSegments<std::pair<AcGePoint2d, AcGePoint2d>>(); }
- };
- // 构造函数
- inline SimplePolygon::SimplePolygon(AcDbPolyline* polyline, bool isclockwise) : m_isclockwise(isclockwise) {
- if (!polyline) return;
- AcGePoint2d pnt;
- for (uint i = 0; i < polyline->numVerts(); ++i) {
- polyline->getPointAt(i, pnt);
- push_back(VertexData(pnt));
- }
- this->uniqueAdjacent();
- this->removeCollinearVertices();
- ensureLockWise(m_isclockwise);
- }
- // 容器转换
- template<typename Container>
- inline SimplePolygon::SimplePolygon(const Container& points, bool)
- {
- static_assert(
- std::is_same_v<typename Container::value_type, AcGePoint2d>,
- "Container must contain AcGePoint2d"
- );
- for (const auto& pnt : points) {
- push_back(VertexData(pnt));
- }
- this->uniqueAdjacent();
- this->removeCollinearVertices();
- ensureLockWise(m_isclockwise);
- }
- // 确保多边形方向
- inline void SimplePolygon::ensureLockWise(bool clockwise) {
- if (size() < 3) return;
- double area = 0.0;
- auto* current = front();
- auto* next = current->next;
- do {
- const auto& pt1 = current->data;
- const auto& pt2 = next->data;
- area += (pt2.x - pt1.x) * (pt2.y + pt1.y);
- current = next;
- next = next->next;
- } while (current != front());
- bool isCurrentlyClockwise = area > 0;
- if (isCurrentlyClockwise != clockwise) {
- reverse();
- }
- m_isclockwise = clockwise;
- }
- //移除共线点
- inline void SimplePolygon::removeCollinearVertices(AcGeTol tol) {
- acutPrintf(L"移除共线点开始,原始length = %d", length);
- if (length < 3) return;
- Node* start = front()->next; // 从第二个节点开始操作
- Node* current = start;
- int process = 0;
- do {
- Node* prev = current->prev;
- Node* next = current->next;
- // 计算方向向量(修正向量方向)
- AcGeVector2d v1 = current->data - prev->data;
- AcGeVector2d v2 = next->data - current->data;
- if (v1.isParallelTo(v2, tol)) {
- Node* toRemove = current;
- current = next; // 先移动到下一节点
- removeNode(toRemove);
- continue;
- }
- current = next;
- process++;
- } while (length > 2 && process < length + 1);
- acutPrintf(L"移除共线点结束,还剩length = %d", length);
- }
- // 检查自相交,偷个懒,直接调用CGAL 方法
- inline bool SimplePolygon::isSelfIntersected() const {
- if (length < 4) return false;
- // 转换为CGAL多边形
- auto cgalPoly = toCgalPolygon2d();
- return cgalPoly.is_simple() == false;
- }
- // 判断是否符合条件
- inline bool SimplePolygon::isValid() {
- if (size() < 3) return false;
- if (isSelfIntersected()) return false;
- return true;
- }
- //获取边
- template<typename ResultType>
- inline std::vector<ResultType> SimplePolygon::convertSegments() const {
- std::vector<ResultType> result;
- if (length < 2) return result;
- if (length == 2) {
- result.reserve(1);
- result.emplace_back(head->data, head->next->data);
- return result;
- }
- result.reserve(length);
- auto* current = head;
- do {
- result.emplace_back(current->data, current->next->data);
- current = current->next;
- } while (current != head);
- return result;
- }
- //转换为CGAL Polygon2d
- inline CgalPolygon2d SimplePolygon::toCgalPolygon2d() const
- {
- const std::vector<VertexData>& cadPoints = toVector();
- return CgalPolygon2d(cadPoints.begin(), cadPoints.end());
- }
代码包括判断是否自相交,回环方向,获取边以及兼容CAD 和 CGAL 的二维坐标隐式转换,可以接入CGAL 的应用
|
|