BambuSrc/libslic3r/Fill/Bridge.hpp

231 lines
6.6 KiB
C++
Raw Normal View History

2025-06-05 02:45:57 +00:00
//
// Created by ylzha on 2025/2/25.
//
#ifndef slic3r_Bridge_hpp_
#define slic3r_Bridge_hpp_
#include "../libslic3r.h"
#include <boost/geometry.hpp>
#include "FillBase.hpp"
namespace bg = boost::geometry;
namespace Slic3r{
class Surface;
// 定义点类型
typedef bg::model::d2::point_xy<double> Point_t;
//定义线段
typedef bg::model::segment<Point_t> Segment;
// 定义多边形类型
typedef bg::model::polygon<Point_t> Polygon_t;
// 多边形集合
typedef bg::model::multi_polygon<Polygon_t> MultiPolygon;
// 定义环类型
typedef bg::model::ring<Point_t> Ring;
// 定义折线类型(用于表示直线)
typedef bg::model::linestring<Point_t> Linestring;
// 定义多边形的外边界和内边界
struct PolygonBoundaries {
Ring outerBoundary; // 外边界
std::vector<Ring> innerBoundaries; // 内边界(可能有多个)
};
struct IdIndex {
size_t id{};
size_t index{};
// 定义小于运算符
bool operator<(const IdIndex& other) const {
return id < other.id;
}
IdIndex(const size_t id, const size_t index) : id(id), index(index) {}
bool operator==(const IdIndex& ii) const {
return id == ii.id && index == ii.index;
}
};
//环路径树结构中节点类型
struct RingNode {
IdIndex id;
Ring ring; //当前环
int orientation{}; //方向 -1 向内 1 向外
std::vector<RingNode> children; //子节点集
RingNode* parent; //父节点
bool isHide{ false }; //在最终路径中是否呈现 false 呈现 true 不呈现
// 构造函数,方便初始化
RingNode(const IdIndex id, const Ring& ring, const int orientation = 0)
: id(id), ring(ring), orientation(orientation), parent(nullptr) {
}
// 重载==运算符方便比较
bool operator==(const RingNode& other) const {
return id.id == other.id.id && id.index == other.id.index;
}
};
//桥接映射
struct BridgeMap {
Point_t from;
Point_t to;
Point_t from2;
Point_t to2;
IdIndex from_ii;
IdIndex to_ii;
size_t edge_index;
BridgeMap(Point_t from, Point_t to, Point_t from2, Point_t to2, IdIndex from_ii, IdIndex to_ii, size_t edge_index) :
from(from), to(to), from2(from2), to2(to2), from_ii(from_ii), to_ii(to_ii), edge_index(edge_index) { }
};
//合并映射
struct MergeMap {
IdIndex ii1; //环1
IdIndex ii2; //环2
std::vector<IdIndex> nodes; //产生的环集
// 构造函数
MergeMap(const IdIndex& i1, const IdIndex& i2, const std::vector<IdIndex>& nodeList)
: ii1(i1), ii2(i2), nodes(nodeList) {
}
};
//struct PointHash {
// std::size_t operator()(const Point_t& p) const {
// std::size_t seed = 0;
// boost::hash_combine(seed, bg::get<0>(p));
// boost::hash_combine(seed, bg::get<1>(p));
// return seed;
// }
//};
//struct PointEqual {
// bool operator()(const Point_t& a, const Point_t& b) const {
// return bg::equals(a, b);
// }
//};
struct PointIndex {
size_t index0;
size_t index1;
Point_t point0;
Point_t point1;
PointIndex(const size_t index0, const size_t index1, const Point_t point0, const Point_t point1) :
index0(index0), index1(index1), point0(point0), point1(point1) { }
};
class Bridge : public Fill {
public:
~Bridge() override = default;
bool is_self_crossing() override { return false; }
protected:
Fill* clone() const override { return new Bridge(*this); }
Polylines fill_surface(const Surface* surface, const FillParams& params) override;
private:
//计算多边形的外边界和内边界
void computePolygonBoundaries(const Polygon_t& polygon);
// 判断两个环是否相交(不包括包含关系)
bool ringsIntersect(const Ring& ring1, const Ring& ring2);
//获取环偏移后的环(可能为空)
std::vector<Ring> offsetRing(const Ring& ring, double distance);
// 查找环非邻边的相交点
std::vector<Point_t> findNonAdjacentIntersections(const Ring& ring);
// 将环拆分成多个环
std::vector<Ring> split(const Ring& ring, const std::vector<Point_t>& intersections);
// 合并两个环
std::vector<Ring> merge(const RingNode& ring1, const RingNode& ring2);
//生成环集
void generateRings();
//形成节点
RingNode formatNode(size_t id, size_t index, const Ring& ring, int orientation);
void addNode(RingNode& node);
void removeNode(IdIndex id);
//查找节点
RingNode& findNode(IdIndex ii);
//形成树
void formatTree();
// 深度优先搜索遍历树
void dfs(RingNode& node, std::vector<IdIndex>& visited, size_t& edge);
//找到多边形环第 N 条边的中心点
Point_t findCenterPointOnEdge(Ring& ring, size_t N, double d0, size_t& e_index);
// 在环上按顺时针方向查找距离给定点d的另一个点
Point_t find_point_at_distance_clockwise(Ring& ring, const Point_t& start_point, double d, size_t& e_index);
size_t findLongestEdgeIndex(const Ring& ring);
//在第N条边上进行内外环桥接并插入桥接点
//o_ii 外环IdIndex i_ii 内环IdIndex
void handleBridge(IdIndex o_ii, IdIndex i_ii, double _offset);
//递归遍历环
void traverseRing(
RingNode& node,
IdIndex parent,
Point_t& start,
Point_t& end,
bool isOutermostLayer //是否最外层
);
//输出所有环
void printRings();
//sf::VertexArray convertToSFML(const Polygon_t& poly, const sf::Color& color);
public:
//输出树结构
void printTree();
//画路径 SFML顶点数组集
//std::vector<sf::Vertex> outputPaths();
//std::vector<sf::VertexArray> convert2vertex();
//std::vector<sf::VertexArray> verteies;
//std::vector<sf::VertexArray> convertBridge();
private:
size_t maxRid = 1; //最大环类型ID值
double offset; //偏移距离
Polygon_t polygon; //2D多边形
double area_threshold; //面积阈值
PolygonBoundaries boundaries; //外/内边界
std::map<size_t, std::vector<RingNode>> ringNodes; //存储不同环类型的节点集合 size_t 环类型id
std::vector<RingNode> nodeHandles; //当前需进行自交或互交处理的节点集合
std::map<IdIndex, std::vector<IdIndex>> splitMap; //分裂映射集
std::vector<MergeMap> mergeMap; //合并映射集
std::map<IdIndex, std::vector<IdIndex>> offsetMap; //偏移后产生的分裂映射集
std::vector<BridgeMap> bridges; //桥接映射
//std::vector<sf::Vertex> path; // 路径
std::vector<Point_t> path; // 路径
bool isFront{ false };
size_t sel_edge_index{ 1 }; //选择桥接边的索引
};
}; // namespace Slic3r
#endif // slic3r_Bridge_hpp_