1335 lines
47 KiB
C++
1335 lines
47 KiB
C++
#include "../ClipperUtils.hpp"
|
||
#include "../ExPolygon.hpp"
|
||
#include "../Surface.hpp"
|
||
#include "../ShortestPath.hpp"
|
||
#include <windows.h>
|
||
#include <sstream>
|
||
#include <string>
|
||
#include <filesystem>
|
||
|
||
#include "Bridge.hpp"
|
||
|
||
|
||
namespace Slic3r {
|
||
|
||
/* Polylines Bridge::fill_surface(const Surface* surface, const FillParams& params)
|
||
{
|
||
auto thread_id = std::this_thread::get_id();
|
||
std::stringstream ss;
|
||
std::string base_path = "D:/logs/";
|
||
ss << base_path << "thread-" << thread_id;
|
||
std::string file_name = ss.str();
|
||
short index = 1;
|
||
while (std::filesystem::exists(file_name)) {
|
||
file_name = ss.str() + "-" + std::to_string(index);
|
||
}
|
||
std::ofstream outfile(file_name + ".txt");
|
||
|
||
Polylines polylines_out;
|
||
{
|
||
Points points = surface->expolygon.contour.points;
|
||
Point first = points[0];
|
||
points.push_back(first);
|
||
outfile << "OutPoint\n";
|
||
for (Point one : points) {
|
||
double x = one.x();
|
||
double y = one.y();
|
||
outfile << "Point(" << x << "," << y << "),\n";
|
||
Point_t temp = { x ,y };
|
||
}
|
||
}
|
||
{
|
||
Polygons inPolygons = surface->expolygon.holes;
|
||
for (Polygon one : inPolygons) {
|
||
Points points = one.points;
|
||
Point first = points[0];
|
||
points.push_back(first);
|
||
outfile << "InPoint\n";
|
||
for (Point two : points) {
|
||
double x = two.x();
|
||
double y = two.y();
|
||
outfile << "Point(" << x << "," << y << "),\n";
|
||
}
|
||
}
|
||
}
|
||
outfile.close();
|
||
return polylines_out;
|
||
}*/
|
||
/*Polylines Bridge::fill_surface(const Surface* surface, const FillParams& params)
|
||
{
|
||
Polylines polylines_out;
|
||
Polygon_t polygon;
|
||
|
||
auto thread_id = std::this_thread::get_id();
|
||
std::stringstream ss;
|
||
std::string base_path = "D:/logs/";
|
||
ss << base_path << "thread-" << thread_id;
|
||
std::string file_name = ss.str();
|
||
std::ofstream outfile(file_name + ".txt", std::ios_base::app);
|
||
|
||
{
|
||
double area = surface->expolygon.contour.area();
|
||
//>e+08
|
||
if (area < 9000000000) {
|
||
return polylines_out;
|
||
}
|
||
Points points = surface->expolygon.contour.points;
|
||
Point first = points[0];
|
||
points.push_back(first);
|
||
std::vector<Point_t> outerBoundary;
|
||
outerBoundary.reserve(points.size());
|
||
//outfile << "//**********Out**********\n";
|
||
for (Point one : points) {
|
||
double x = one.x();
|
||
double y = one.y();
|
||
//outfile << "Point(" << x << "," << y << "),\n";
|
||
Point_t temp = { x ,y };
|
||
outerBoundary.push_back(temp);
|
||
}
|
||
bg::append(polygon.outer(), outerBoundary);
|
||
}
|
||
|
||
{
|
||
Polygons inPolygons = surface->expolygon.holes;
|
||
for (Polygon one : inPolygons) {
|
||
Ring innerRing;
|
||
innerRing.reserve(one.points.size() + 1);
|
||
Points points = one.points;
|
||
Point first = points[0];
|
||
points.push_back(first);
|
||
//outfile << "//**********In**********\n";
|
||
for (Point two : points) {
|
||
double x = two.x();
|
||
double y = two.y();
|
||
//outfile << "Point(" << x << "," << y << "),\n";
|
||
Point_t temp = { x,y };
|
||
innerRing.push_back(temp);
|
||
}
|
||
polygon.inners().push_back(innerRing);
|
||
}
|
||
}
|
||
|
||
this->polygon = polygon;
|
||
this->offset = 30000;
|
||
printTree();
|
||
int b_size = bridges.size();
|
||
BridgeMap bm = bridges[0];
|
||
IdIndex parent(1, 1);
|
||
traverseRing(findNode(bm.from_ii), parent, bm.from, bm.from2, true);
|
||
Point_t last = { bm.from.x(),bm.from.y() };
|
||
path.emplace_back(last);
|
||
|
||
outfile << "//**********Line**********\n";
|
||
for (Point_t one : path) {
|
||
double x = one.x();
|
||
double y = one.y();
|
||
outfile << "Point(" << x << "," << y << "),\n";
|
||
}
|
||
|
||
for (size_t i = 0; i + 1 < path.size(); ++i) {
|
||
//outfile << "//**********Line**********\n";
|
||
Point p1 = { path[i].x(),path[i].y() };
|
||
Point p2 = { path[i + 1].x() ,path[i + 1].y() };
|
||
//outfile << "Point(" << p1 << "," << p2 << "),\n";
|
||
Polyline line = { p1, p2 };
|
||
polylines_out.push_back(line);
|
||
}
|
||
|
||
outfile.close();
|
||
return polylines_out;
|
||
}*/
|
||
Polylines Bridge::fill_surface(const Surface* surface, const FillParams& params)
|
||
{
|
||
Polylines polylines_out;
|
||
Polygon_t polygon;
|
||
polylines_out.clear();
|
||
{
|
||
double area = surface->expolygon.contour.area();
|
||
//>e+08
|
||
if (area < 900000000) {
|
||
return polylines_out;
|
||
}
|
||
Points points = surface->expolygon.contour.points;
|
||
Point first = points[0];
|
||
points.push_back(first);
|
||
std::vector<Point_t> outerBoundary;
|
||
outerBoundary.reserve(points.size());
|
||
for (Point one : points) {
|
||
double x = one.x();
|
||
double y = one.y();
|
||
Point_t temp = { x ,y };
|
||
outerBoundary.push_back(temp);
|
||
}
|
||
bg::append(polygon.outer(), outerBoundary);
|
||
}
|
||
|
||
{
|
||
Polygons inPolygons = surface->expolygon.holes;
|
||
for (Polygon one : inPolygons) {
|
||
Ring innerRing;
|
||
innerRing.reserve(one.points.size() + 1);
|
||
Points points = one.points;
|
||
Point first = points[0];
|
||
points.push_back(first);
|
||
for (Point two : points) {
|
||
double x = two.x();
|
||
double y = two.y();
|
||
Point_t temp = { x,y };
|
||
innerRing.push_back(temp);
|
||
}
|
||
polygon.inners().push_back(innerRing);
|
||
}
|
||
}
|
||
|
||
this->polygon = polygon;
|
||
//auto abc = float(scale_(this->overlap - 0.5 * this->spacing));
|
||
//if (abc < 0) {
|
||
// abc = -abc;
|
||
//}
|
||
//this->offset = abc;
|
||
this->offset = 40000;
|
||
printTree();
|
||
int b_size = bridges.size();
|
||
BridgeMap bm = bridges[0];
|
||
IdIndex parent(1, 1);
|
||
traverseRing(findNode(bm.from_ii), parent, bm.from, bm.from2, true);
|
||
Point_t last = { bm.from.x(),bm.from.y() };
|
||
path.emplace_back(last);
|
||
|
||
for (size_t i = 0; i + 1 < path.size(); ++i) {
|
||
Point p1 = { path[i].x(),path[i].y() };
|
||
Point p2 = { path[i + 1].x() ,path[i + 1].y() };
|
||
Polyline line = { p1, p2 };
|
||
polylines_out.push_back(line);
|
||
}
|
||
|
||
return polylines_out;
|
||
}
|
||
|
||
//void Bridge::_fill_surface_single(const FillParams& params, unsigned int thickness_layers, const std::pair<float, Point>& direction, ExPolygon expolygon, Polylines& polylines_out)
|
||
//{
|
||
// expolygon.rotate(-direction.first);
|
||
//
|
||
// this->_min_spacing = scale_(this->spacing);
|
||
// assert(params.density > 0.0001f && params.density <= 1.f);
|
||
// this->_line_spacing = coord_t(coordf_t(this->_min_spacing) / params.density);
|
||
// this->_diagonal_distance = this->_line_spacing * 2;
|
||
// this->_line_oscillation = this->_line_spacing - this->_min_spacing; // only for Line infill
|
||
// BoundingBox bounding_box = expolygon.contour.bounding_box();
|
||
//
|
||
// // define flow spacing according to requested density
|
||
// if (params.density > 0.9999f && !params.dont_adjust) {
|
||
// this->_line_spacing = this->_adjust_solid_spacing(bounding_box.size()(0), this->_line_spacing);
|
||
// this->spacing = unscale<double>(this->_line_spacing);
|
||
// }
|
||
// else {
|
||
// // extend bounding box so that our pattern will be aligned with other layers
|
||
// // Transform the reference point to the rotated coordinate system.
|
||
// bounding_box.merge(align_to_grid(
|
||
// bounding_box.min,
|
||
// Point(this->_line_spacing, this->_line_spacing),
|
||
// direction.second.rotated(-direction.first)));
|
||
// }
|
||
// Polygon outPolygon = bounding_box.polygon();
|
||
// Polygon_t polygon;
|
||
// std::vector<Point_t> outerBoundary;
|
||
// outerBoundary.reserve(outPolygon.points.size());
|
||
// for (Point one : outPolygon.points) {
|
||
// double x = one.x();
|
||
// double y = one.y();
|
||
// Point_t temp = { x,y };
|
||
// outerBoundary.push_back(temp);
|
||
// }
|
||
// bg::append(polygon.outer(), outerBoundary);
|
||
//
|
||
// //std::vector<Point_t> innerBoundary;
|
||
//
|
||
// Polygons inPolygons = expolygon.holes;
|
||
// for (Polygon one :inPolygons) {
|
||
// Ring innerRing;
|
||
// for (Point two: one.points) {
|
||
// double x = two.x();
|
||
// double y = two.y();
|
||
// Point_t temp = { x,y };
|
||
// innerRing.push_back(temp);
|
||
// }
|
||
// polygon.inners().push_back(innerRing);
|
||
// }
|
||
// this->polygon = polygon;
|
||
// this->offset = float(scale_(this->overlap - 0.5 * this->spacing));
|
||
// printTree();
|
||
// for (size_t i = 0; i + 1 < path.size(); ++i) {
|
||
//
|
||
// Point p1 = { path[i].x(),path[i].y()};
|
||
// Point p2 = { path[i + 1].x(),path[i + 1].y()};
|
||
// Polyline line = { p1, p2 };
|
||
// polylines_out.push_back(line);
|
||
// }
|
||
//}
|
||
|
||
/*void Bridge::_fill_surface_single(const FillParams& params, unsigned int thickness_layers, const std::pair<float, Point>& direction, ExPolygon expolygon, Polylines& polylines_out)
|
||
{
|
||
|
||
|
||
//this->_min_spacing = scale_(this->spacing);
|
||
//assert(params.density > 0.0001f && params.density <= 1.f);
|
||
//this->_line_spacing = coord_t(coordf_t(this->_min_spacing) / params.density);
|
||
//this->_diagonal_distance = this->_line_spacing * 2;
|
||
//this->_line_oscillation = this->_line_spacing - this->_min_spacing; // only for Line infill
|
||
//BoundingBox bounding_box = expolygon.contour.bounding_box();
|
||
|
||
//// define flow spacing according to requested density
|
||
////根据要求的密度定义流间距
|
||
//if (params.density > 0.9999f && !params.dont_adjust) {
|
||
// this->_line_spacing = this->_adjust_solid_spacing(bounding_box.size()(0), this->_line_spacing);
|
||
// this->spacing = unscale<double>(this->_line_spacing);
|
||
//}
|
||
//else {
|
||
// // extend bounding box so that our pattern will be aligned with other layers
|
||
// // Transform the reference point to the rotated coordinate system.
|
||
// //扩展边界框,使我们的图案与其他层对齐
|
||
// //将参考点变换到旋转坐标系。
|
||
// bounding_box.merge(align_to_grid(
|
||
// bounding_box.min,
|
||
// Point(this->_line_spacing, this->_line_spacing),
|
||
// direction.second.rotated(-direction.first)));
|
||
//}
|
||
|
||
BoundingBox bounding_box = expolygon.contour.bounding_box();
|
||
Polygon outPolygon = bounding_box.polygon();
|
||
Polygon_t polygon;
|
||
std::vector<Point_t> outerBoundary;
|
||
outerBoundary.reserve(outPolygon.points.size());
|
||
for (Point one : outPolygon.points) {
|
||
double x = one.x();
|
||
double y = one.y();
|
||
Point_t temp = { x,y };
|
||
outerBoundary.push_back(temp);
|
||
}
|
||
bg::append(polygon.outer(), outerBoundary);
|
||
|
||
//std::vector<Point_t> innerBoundary;
|
||
|
||
Polygons inPolygons = expolygon.holes;
|
||
for (Polygon one : inPolygons) {
|
||
Ring innerRing;
|
||
innerRing.reserve(one.points.size());
|
||
for (Point two : one.points) {
|
||
double x = two.x();
|
||
double y = two.y();
|
||
Point_t temp = { x,y };
|
||
innerRing.push_back(temp);
|
||
}
|
||
polygon.inners().push_back(innerRing);
|
||
}
|
||
int inSize = polygon.inners().size();
|
||
// Bridge bridge(polygon, float(scale_(this->overlap - 0.5 * this->spacing)));
|
||
this->polygon = polygon;
|
||
this->offset = float(scale_(this->overlap - 0.5 * this->spacing));
|
||
printTree();
|
||
//outputPaths();
|
||
|
||
for (size_t i = 0; i + 1 < path.size(); ++i) {
|
||
|
||
Point p1 = { path[i].x(),path[i].y()};
|
||
Point p2 = { path[i + 1].x(),path[i + 1].y()};
|
||
Polyline line = { p1, p2 };
|
||
polylines_out.push_back(line);
|
||
}
|
||
}*/
|
||
|
||
|
||
// 为 std::pair<size_t, size_t> 定义哈希函数
|
||
//template<>
|
||
//struct std::hash<std::pair<size_t, size_t>> {
|
||
// std::size_t operator()(const std::pair<size_t, size_t>& p) const noexcept {
|
||
// return std::hash<size_t>()(p.first) ^ (std::hash<size_t>()(p.second) << 1);
|
||
// }
|
||
//};
|
||
|
||
//判断两个点是否相等
|
||
bool equal(Point_t p1, Point_t p2) {
|
||
return p1.x() == p2.x() && p1.y() == p2.y();
|
||
}
|
||
|
||
// 计算点到原点的距离平方
|
||
double distance_to_origin_sq(const Point_t& p) {
|
||
return bg::get<0>(p) * bg::get<0>(p) + bg::get<1>(p) * bg::get<1>(p);
|
||
}
|
||
|
||
//将节点加入处理节点集合中
|
||
RingNode Bridge::formatNode(const size_t id, const size_t index, const Ring& ring, const int orientation) {
|
||
Ring ringNode;
|
||
ringNode.assign(ring.begin(), ring.end());
|
||
RingNode node({ id, index }, ringNode, orientation);
|
||
return node;
|
||
}
|
||
void Bridge::addNode(RingNode& node) {
|
||
|
||
// 检查键是否存在
|
||
const auto it = ringNodes.find(node.id.id);
|
||
if (it != ringNodes.end()) {
|
||
// 键已存在,将新节点添加到对应向量的末尾
|
||
it->second.emplace_back(node);
|
||
}
|
||
else {
|
||
// 键不存在,创建一个新的向量并插入到 map 中
|
||
ringNodes[node.id.id] = { node };
|
||
}
|
||
}
|
||
|
||
void Bridge::removeNode(IdIndex id) {
|
||
auto it = ringNodes.find(id.id);
|
||
if (it != ringNodes.end()) {
|
||
std::vector<RingNode>& nodes = it->second;
|
||
nodes.erase(std::remove_if(nodes.begin(), nodes.end(),
|
||
[id](RingNode x) { return x.id.id == id.id && x.id.index == id.index; }),
|
||
nodes.end());
|
||
}
|
||
}
|
||
|
||
//查找节点
|
||
RingNode& Bridge::findNode(const IdIndex ii) {
|
||
const auto it = ringNodes.find(ii.id);
|
||
std::vector<RingNode>& nodes = it->second;
|
||
const auto it1 = std::find_if(nodes.begin(), nodes.end(), [ii](const RingNode& node) {
|
||
return node.id.index == ii.index;
|
||
});
|
||
return *it1;
|
||
}
|
||
|
||
|
||
//计算多边形的外边界和内边界
|
||
void Bridge::computePolygonBoundaries(Polygon_t& polygon) {
|
||
// 提取外边界
|
||
boundaries.outerBoundary = bg::exterior_ring(polygon);
|
||
// 获取内边界
|
||
const auto& interiors = bg::interior_rings(polygon);
|
||
for (const auto& inner : interiors) {
|
||
boundaries.innerBoundaries.push_back(inner);
|
||
}
|
||
}
|
||
|
||
// 判断多边形A是否包含多边形B
|
||
bool isPolygonContained(const Polygon_t& polyA, const Polygon_t& polyB) {
|
||
// 检查B的所有点是否都在A内部
|
||
for (const auto& point : bg::exterior_ring(polyB)) {
|
||
if (!bg::within(point, polyA)) {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
// 检查A和B的环是否有交叉
|
||
std::vector<Polygon_t> intersection;
|
||
bg::intersection(polyA, polyB, intersection);
|
||
|
||
// 如果交集的总面积等于B的面积,则A包含B
|
||
double totalArea = 0.0;
|
||
for (const auto& poly : intersection) {
|
||
totalArea += bg::area(poly);
|
||
}
|
||
|
||
return std::abs(totalArea - bg::area(polyB)) < 1e-9;
|
||
}
|
||
|
||
|
||
// 判断两个环是否相交(不包括包含关系)
|
||
bool Bridge::ringsIntersect(const RingNode rn1, const RingNode rn2)
|
||
{
|
||
// 将环转换为多边形
|
||
Polygon_t poly1, poly2;
|
||
bg::append(poly1.outer(), rn1.ring);
|
||
bg::append(poly2.outer(), rn2.ring);
|
||
|
||
// 首先检查是否相交(包括边界相交)
|
||
if (!bg::intersects(poly1, poly2)) {
|
||
return false;
|
||
}
|
||
|
||
if (bg::area(poly1) == bg::area(poly2)) {
|
||
return false;
|
||
}
|
||
// 如果存在包含关系,则不算作相交
|
||
if (isPolygonContained(poly1, poly2) || isPolygonContained(poly2, poly1)) {
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
|
||
//获取环偏移后的环(可能为空)
|
||
std::vector<Ring> Bridge::offsetRing(const Ring& ring, const double distance) {
|
||
// 将环包装成多边形
|
||
Polygon_t inputPolygon;
|
||
inputPolygon.outer() = ring;
|
||
// 修复几何数据
|
||
bg::correct(inputPolygon);
|
||
|
||
// 使用 multi_polygon 作为 buffer 的输出类型
|
||
bg::model::multi_polygon<Polygon_t> result;
|
||
// 使用对称距离策略
|
||
bg::buffer(inputPolygon, result,
|
||
bg::strategy::buffer::distance_symmetric<double>(distance),
|
||
bg::strategy::buffer::side_straight(),
|
||
bg::strategy::buffer::join_round(),
|
||
bg::strategy::buffer::end_round(),
|
||
bg::strategy::buffer::point_circle());
|
||
// 提取偏移后的环
|
||
std::vector<Ring> offsetRing;
|
||
for (const auto& poly : result) {
|
||
if (std::abs(bg::area(poly.outer())) > area_threshold) {
|
||
offsetRing.emplace_back(poly.outer());
|
||
}
|
||
}
|
||
return offsetRing;
|
||
}
|
||
|
||
|
||
// 合并多个环
|
||
std::vector<Ring> Bridge::merge(std::vector<RingNode> rns, const RingNode rn) {
|
||
|
||
// 将环转换为多边形
|
||
std::vector<Polygon_t> input;
|
||
for (RingNode _rn : rns) {
|
||
Polygon_t poly;
|
||
std::vector<Point_t> outerBoundary(_rn.ring.begin(), _rn.ring.end());
|
||
bg::assign_points(poly.outer(), outerBoundary);
|
||
input.push_back(poly);
|
||
}
|
||
|
||
Polygon_t poly2;
|
||
std::vector<Point_t> outerBoundary2(rn.ring.begin(), rn.ring.end());
|
||
bg::append(poly2.outer(), outerBoundary2);
|
||
// 合并所有结果多边形
|
||
MultiPolygon result;
|
||
if (input.size() > 1) {
|
||
// 初始化当前多边形为外多边形
|
||
bg::convert(poly2, result);
|
||
// 依次从当前多边形中减去每个内多边形
|
||
for (const auto& inner : input) {
|
||
MultiPolygon temp;
|
||
bg::difference(result, inner, temp);
|
||
result = temp;
|
||
}
|
||
}
|
||
else {
|
||
if (rns[0].orientation == -1 && rn.orientation == 1) {
|
||
bg::difference(input[0], poly2, result);
|
||
}
|
||
else if (rns[0].orientation == 1 && rn.orientation == -1) {
|
||
bg::difference(poly2, input[0], result);
|
||
}
|
||
else if (rns[0].orientation == 1 && rn.orientation == 1) {
|
||
bg::union_(input[0], poly2, result);
|
||
}
|
||
}
|
||
std::vector<Ring> allRings;
|
||
|
||
for (const auto& poly : result) {
|
||
allRings.emplace_back(poly.outer());
|
||
}
|
||
//// 过滤掉被其他环完全包含的环
|
||
std::vector<Ring> disjointRings;
|
||
for (size_t i = 0; i < allRings.size(); ++i) {
|
||
bool isContained = false;
|
||
for (size_t j = 0; j < allRings.size(); ++j) {
|
||
if (i != j && bg::within(allRings[i], allRings[j])) {
|
||
isContained = true;
|
||
break;
|
||
}
|
||
}
|
||
if (!isContained) {
|
||
disjointRings.push_back(allRings[i]);
|
||
}
|
||
}
|
||
return disjointRings;
|
||
}
|
||
|
||
// 比较函数:按 orientation 从大到小排序
|
||
bool compareByOrientationDesc(const RingNode& a, const RingNode& b) {
|
||
return a.orientation > b.orientation;
|
||
}
|
||
|
||
//生成环集
|
||
void Bridge::generateRings() {
|
||
|
||
//获取多边形的外边界和内边界
|
||
computePolygonBoundaries(polygon);
|
||
Ring ring = boundaries.outerBoundary;
|
||
bg::correct(ring);
|
||
RingNode node = formatNode(maxRid++, 1, ring, -1);
|
||
nodeHandles.emplace_back(node);
|
||
addNode(node);
|
||
for (auto& inner : boundaries.innerBoundaries) {
|
||
bg::correct(inner);
|
||
RingNode node = formatNode(maxRid++, 1, inner, 1);
|
||
nodeHandles.emplace_back(node);
|
||
addNode(node);
|
||
}
|
||
int m = 0;
|
||
double t = 0.5;
|
||
|
||
//遍历当前用于判断互交的节点集
|
||
while (!nodeHandles.empty()) {
|
||
std::vector<RingNode> nodes; //互交后产生的节点
|
||
bool isFind = false;
|
||
do {
|
||
isFind = false;
|
||
nodes.clear();
|
||
// 按 orientation 从大到小排序
|
||
std::sort(nodeHandles.begin(), nodeHandles.end(), compareByOrientationDesc);
|
||
int r = nodeHandles.size();
|
||
std::vector<std::vector<int>> matrix(r, std::vector<int>(r, 0)); // 初始化为0
|
||
for (size_t i = 0; i < nodeHandles.size(); ++i) {
|
||
for (size_t j = i + 1; j < nodeHandles.size(); ++j) {
|
||
if (ringsIntersect(nodeHandles[i], nodeHandles[j])) {
|
||
matrix[i][j] = 1;
|
||
isFind = true;
|
||
}
|
||
}
|
||
}
|
||
|
||
std::set<int> dIndex;
|
||
for (size_t j = r - 1; j > 0; --j) {
|
||
std::vector<RingNode> rVector;
|
||
for (size_t i = 0; i < j; ++i) {
|
||
if (matrix[i][j] == 1) {
|
||
rVector.push_back(nodeHandles[i]);
|
||
dIndex.insert(i);
|
||
dIndex.insert(j);
|
||
|
||
//将i行全部置为0
|
||
std::vector<int>& row = matrix[i];
|
||
for (int& element : row) {
|
||
element = 0;
|
||
}
|
||
}
|
||
}
|
||
if (rVector.size() > 0) {
|
||
std::vector<Ring> rings = merge(rVector, nodeHandles[j]);
|
||
std::vector<IdIndex> id_indices;
|
||
for (auto& ring2 : rings) {
|
||
int orientation = (rVector[0].orientation + nodeHandles[j].orientation) <= 0 ? -1 : 1;
|
||
// 外与内 外与外 -> 向内; 内与内 -> 向外
|
||
if (rVector.size() > 1) {
|
||
orientation = -1;
|
||
}
|
||
RingNode node1 = formatNode(++maxRid, 1, ring2, orientation);
|
||
if (bg::area(node1.ring) > area_threshold) {
|
||
nodes.emplace_back(node1);
|
||
addNode(node1);
|
||
IdIndex _ii(maxRid, 1);
|
||
id_indices.emplace_back(_ii);
|
||
}
|
||
}
|
||
if (id_indices.size() > 0) {
|
||
for (RingNode rn : rVector) {
|
||
MergeMap mm(rn.id, nodeHandles[j].id, id_indices);
|
||
mergeMap.emplace_back(mm);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
// 逆向遍历删除,避免影响前面元素的索引
|
||
for (auto it = dIndex.rbegin(); it != dIndex.rend(); ++it) {
|
||
int index = *it;
|
||
if (index >= 0 && index < nodeHandles.size()) {
|
||
nodeHandles.erase(nodeHandles.begin() + index);
|
||
}
|
||
}
|
||
//是否存在互交
|
||
if (!nodes.empty()) {
|
||
for (auto& n : nodes) {
|
||
nodeHandles.emplace_back(n);
|
||
}
|
||
}
|
||
} while (isFind);
|
||
|
||
std::vector<RingNode> offsetNodes;
|
||
//偏移
|
||
for (auto node : nodeHandles) {
|
||
std::vector<Ring> ring0 = offsetRing(node.ring, static_cast<double>(node.orientation) * offset * t);
|
||
if (ring0.size() == 1) {
|
||
RingNode node0 = formatNode(node.id.id, ++node.id.index, ring0[0], node.orientation);
|
||
if (bg::area(node0.ring) > area_threshold) {
|
||
addNode(node0);
|
||
offsetNodes.emplace_back(node0);
|
||
}
|
||
}
|
||
else if (ring0.size() > 1) {
|
||
std::vector<IdIndex> id_indices;
|
||
for (auto r : ring0) {
|
||
RingNode node0 = formatNode(++maxRid, 1, r, node.orientation);
|
||
if (bg::area(node0.ring) > area_threshold) {
|
||
addNode(node0);
|
||
offsetNodes.emplace_back(node0);
|
||
IdIndex ii(maxRid, 1);
|
||
id_indices.emplace_back(ii);
|
||
}
|
||
}
|
||
//分裂映射
|
||
offsetMap.insert(std::pair<IdIndex, std::vector<IdIndex>>({ node.id.id,node.id.index }, id_indices));
|
||
}
|
||
}
|
||
t = 1;
|
||
//清空
|
||
nodeHandles.clear();
|
||
if (!offsetNodes.empty()) {
|
||
if (offsetNodes.size() == 2) {
|
||
Polygon_t poly1, poly2;
|
||
bg::append(poly1.outer(), offsetNodes[0].ring);
|
||
bg::append(poly2.outer(), offsetNodes[1].ring);
|
||
std::vector<IdIndex> id_indices;
|
||
if (offsetNodes[0].orientation == 1 && isPolygonContained(poly1, poly2)) {
|
||
MergeMap mm(offsetNodes[0].id, offsetNodes[1].id, id_indices);
|
||
containMap.emplace_back(mm);
|
||
break;
|
||
}
|
||
if (offsetNodes[1].orientation == 1 && isPolygonContained(poly2, poly1)) {
|
||
MergeMap mm(offsetNodes[1].id, offsetNodes[0].id, id_indices);
|
||
containMap.emplace_back(mm);
|
||
break;
|
||
}
|
||
}
|
||
//重填
|
||
nodeHandles.insert(nodeHandles.end(), offsetNodes.begin(), offsetNodes.end());
|
||
}
|
||
}
|
||
}
|
||
|
||
//形成树
|
||
void Bridge::formatTree() {
|
||
|
||
//遍历不同环类型的节点集合
|
||
for (auto& ringNode : ringNodes) {
|
||
// 使用反向迭代器进行反序遍历
|
||
std::vector<RingNode>& vec = ringNode.second;
|
||
const auto it0 = ringNode.second.begin();
|
||
if (it0->orientation == 1) { // 向外 倒序
|
||
for (size_t i = ringNode.second.size() - 1; i > 0; i--) {
|
||
ringNode.second[i].children.emplace_back(ringNode.second[i - 1]);
|
||
ringNode.second[i - 1].parent = &ringNode.second[i];
|
||
}
|
||
}
|
||
else { //向内 正序
|
||
for (int i = 0; i < vec.size() - 1; i++) {
|
||
ringNode.second[i].children.emplace_back(ringNode.second[i + 1]);
|
||
ringNode.second[i + 1].parent = &ringNode.second[i];
|
||
}
|
||
}
|
||
}
|
||
|
||
//遍历分裂/合并映射
|
||
for (auto& map : offsetMap) { //偏移产生的分裂
|
||
RingNode& it1 = findNode(map.first);
|
||
for (const auto& ii : map.second) {
|
||
RingNode& it2 = findNode(ii);
|
||
it1.children.emplace_back(it2);
|
||
}
|
||
}
|
||
for (auto& map : containMap) {
|
||
RingNode& it1 = findNode(map.ii1); //内
|
||
RingNode& it2 = findNode(map.ii2); //外
|
||
it2.children.insert(it2.children.end(), it1.children.begin(), it1.children.end());
|
||
it1.isHide = true;
|
||
}
|
||
for (auto& map : mergeMap) { //合并
|
||
RingNode& it1 = findNode(map.ii1);
|
||
RingNode& it2 = findNode(map.ii2);
|
||
|
||
for (const auto& ii : map.nodes) {
|
||
RingNode& it = findNode(ii);
|
||
std::cout << it1.id.id << "," << it1.id.index << ":"
|
||
<< it2.id.id << "," << it2.id.index
|
||
<< "->" << it.id.id << "," << it.id.index
|
||
<< std::endl;
|
||
if (it1.orientation == -1 && it2.orientation == 1) {
|
||
it1.parent->children.emplace_back(it);
|
||
it.parent = it1.parent;
|
||
IdIndex _ii = it1.id;
|
||
|
||
//将it1从父节点的子节点集中移除
|
||
it1.parent->children.erase(std::remove_if(it1.parent->children.begin(), it1.parent->children.end(),
|
||
[_ii](RingNode x) { return x.id.id == _ii.id && x.id.index == _ii.index; }),
|
||
it1.parent->children.end());
|
||
//it作为it2子节点的父节点
|
||
for (auto& c : it2.children) {
|
||
c.parent = ⁢
|
||
}
|
||
it.children.insert(it.children.end(), it2.children.begin(), it2.children.end());
|
||
}
|
||
else if (it1.orientation == 1 && it2.orientation == -1) //外 内
|
||
{
|
||
it2.parent->children.emplace_back(it);
|
||
it2.isHide = true;
|
||
it1.isHide = true;
|
||
IdIndex _ii = it2.id;
|
||
//将it2从父节点的子节点集中移除
|
||
it2.parent->children.erase(std::remove_if(it2.parent->children.begin(), it2.parent->children.end(),
|
||
[_ii](RingNode x) { return x.id.id == _ii.id && x.id.index == _ii.index; }),
|
||
it2.parent->children.end());
|
||
|
||
it.children.insert(it.children.end(), it1.children.begin(), it1.children.end());
|
||
}
|
||
else if (it1.orientation == 1 && it2.orientation == 1) { //外 外
|
||
//it作为it1子节点的父节点
|
||
it.children.insert(it.children.end(), it1.children.begin(), it1.children.end());
|
||
it.children.insert(it.children.end(), it2.children.begin(), it2.children.end());
|
||
}
|
||
else if (it1.orientation == -1 && it2.orientation == -1) {// 内 内
|
||
it1.parent->children.emplace_back(it);
|
||
IdIndex _ii = it1.id;
|
||
//将it1从父节点的子节点集中移除
|
||
it1.parent->children.erase(std::remove_if(it1.parent->children.begin(), it1.parent->children.end(),
|
||
[_ii](RingNode x) { return x.id.id == _ii.id && x.id.index == _ii.index; }),
|
||
it1.parent->children.end());
|
||
|
||
it2.parent->children.emplace_back(it);
|
||
IdIndex _ii2 = it2.id;
|
||
//将it2从父节点的子节点集中移除
|
||
it2.parent->children.erase(std::remove_if(it2.parent->children.begin(), it2.parent->children.end(),
|
||
[_ii2](RingNode x) { return x.id.id == _ii2.id && x.id.index == _ii2.index; }),
|
||
it2.parent->children.end());
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
}
|
||
|
||
//树遍历
|
||
void Bridge::dfs(RingNode& node, std::vector<IdIndex>& visited) {
|
||
bool flag = false;
|
||
for (auto& one : visited) {
|
||
if (one == node.id) {
|
||
flag = true;
|
||
break;
|
||
}
|
||
}
|
||
if (flag) {
|
||
return;
|
||
}
|
||
visited.emplace_back(node.id);
|
||
// 处理当前节点
|
||
std::cout << "rId: " << node.id.id << ", rIndex: " << node.id.index
|
||
<< ", orientation: " << node.orientation
|
||
<< ", isHide: " << (node.isHide ? "true" : "false") << std::endl;
|
||
|
||
Polygon_t poly;
|
||
bg::assign(poly, node.ring);
|
||
//verteies.push_back(convertToSFML(poly, sf::Color::Red));
|
||
|
||
// 递归遍历子节点
|
||
for (auto& child : node.children) {
|
||
handleBridge(node.id, child.id);
|
||
dfs(findNode(child.id), visited);
|
||
}
|
||
}
|
||
|
||
|
||
//找到多边形环第 N 条边的中心点
|
||
Point_t Bridge::findCenterPointOnEdge(Ring& ring, size_t N, double d0, size_t& e_index) {
|
||
|
||
// 获取第 N 条边的两个端点
|
||
const Point_t start = ring[N];
|
||
const Point_t end = ring[N + 1];
|
||
// 计算中点
|
||
const double mid_x = (start.x() + end.x()) / 2;
|
||
const double mid_y = (start.y() + end.y()) / 2;
|
||
|
||
Point_t p(mid_x, mid_y);
|
||
if (d0 > 0) {
|
||
std::size_t n = ring.size() - 1; // 环的边数
|
||
double remainingDist = d0;
|
||
|
||
// 计算 p0 到边终点(顺时针方向下一点)的距离
|
||
double distToEnd = bg::distance(p, ring[N + 1]);
|
||
|
||
// 如果 d0 小于等于到边终点的距离,直接在当前边上计算
|
||
if (remainingDist <= distToEnd) {
|
||
// 计算从 p0 到边终点的方向向量
|
||
double dx = bg::get<0>(ring[N + 1]) - bg::get<0>(p);
|
||
double dy = bg::get<1>(ring[N + 1]) - bg::get<1>(p);
|
||
double length = std::sqrt(dx * dx + dy * dy);
|
||
|
||
if (length < 1e-9) {
|
||
// 特殊情况:p0 几乎是边的终点
|
||
return ring[N + 1];
|
||
}
|
||
// 归一化方向向量
|
||
double unitDx = dx / length;
|
||
double unitDy = dy / length;
|
||
|
||
// 计算新点坐标
|
||
double newX = bg::get<0>(p) + unitDx * remainingDist;
|
||
double newY = bg::get<1>(p) + unitDy * remainingDist;
|
||
|
||
Point_t p0(newX, newY);
|
||
e_index = N;
|
||
return p0;
|
||
}
|
||
|
||
// 剩余距离超过当前边,需要继续到下一条边
|
||
remainingDist -= distToEnd;
|
||
|
||
// 沿顺时针方向继续搜索后续边
|
||
for (std::size_t i = 2; i < n; ++i) {
|
||
std::size_t currentIndex = (N + i) % n;
|
||
Segment edge(ring[currentIndex], ring[currentIndex + 1]);
|
||
double edgeLength = bg::distance(edge.first, edge.second);
|
||
|
||
// 如果剩余距离小于等于当前边长度,在当前边上计算
|
||
if (remainingDist <= edgeLength) {
|
||
// 计算边的方向向量
|
||
double dx = bg::get<0>(edge.second) - bg::get<0>(edge.first);
|
||
double dy = bg::get<1>(edge.second) - bg::get<1>(edge.first);
|
||
double length = std::sqrt(dx * dx + dy * dy);
|
||
|
||
if (length < 1e-9) {
|
||
e_index = currentIndex;
|
||
return edge.first;
|
||
}
|
||
|
||
// 归一化方向向量
|
||
double unitDx = dx / length;
|
||
double unitDy = dy / length;
|
||
|
||
// 计算新点坐标
|
||
double newX = bg::get<0>(edge.first) + unitDx * remainingDist;
|
||
double newY = bg::get<1>(edge.first) + unitDy * remainingDist;
|
||
Point_t p0(newX, newY);
|
||
e_index = currentIndex;
|
||
return p0;
|
||
}
|
||
// 否则继续到下一条边
|
||
remainingDist -= edgeLength;
|
||
}
|
||
}
|
||
else {
|
||
e_index = N;
|
||
}
|
||
return p;
|
||
}
|
||
|
||
|
||
// 计算点到线段的最近点
|
||
Point_t closest_point_on_segment(const Point_t p, const Point_t& seg_start, const Point_t& seg_end) {
|
||
const double x = bg::get<0>(p);
|
||
const double y = bg::get<1>(p);
|
||
const double x1 = bg::get<0>(seg_start);
|
||
const double y1 = bg::get<1>(seg_start);
|
||
const double x2 = bg::get<0>(seg_end);
|
||
const double y2 = bg::get<1>(seg_end);
|
||
|
||
// 线段向量
|
||
const double dx = x2 - x1;
|
||
const double dy = y2 - y1;
|
||
|
||
// 如果线段长度为零,返回起点
|
||
if (dx == 0 && dy == 0) {
|
||
return seg_start;
|
||
}
|
||
|
||
// 计算投影参数t
|
||
double t = ((x - x1) * dx + (y - y1) * dy) / (dx * dx + dy * dy);
|
||
|
||
// 限制 t 在 [0,1] 范围内,确保投影点在线段上
|
||
t = std::max(0.0, std::min(1.0, t));
|
||
|
||
// 计算投影点坐标
|
||
return Point_t(bg::get<0>(seg_start) + t * dx,
|
||
bg::get<1>(seg_start) + t * dy);
|
||
}
|
||
|
||
// 在环的边上查找离给定点最近的点
|
||
Point_t find_closest_point_on_ring_edges(Ring& ring, const Point_t& p0, size_t& e_index1) {
|
||
Point_t closest = ring[0]; // 初始化为Ring的第一个点
|
||
double minDist = bg::distance(p0, closest);
|
||
|
||
// 遍历Ring的每条边
|
||
for (size_t i = 0; i < ring.size(); ++i) {
|
||
// 获取当前边的两个端点
|
||
Point_t a = ring[i];
|
||
Point_t b = ring[(i + 1) % ring.size()]; // 处理闭合边
|
||
|
||
// 计算点到边的最近点
|
||
Point_t projection = closest_point_on_segment(p0, a, b);
|
||
|
||
// 计算距离
|
||
double dist = bg::distance(p0, projection);
|
||
|
||
// 更新最近点
|
||
if (dist < minDist) {
|
||
minDist = dist;
|
||
closest = projection;
|
||
e_index1 = i;
|
||
}
|
||
}
|
||
return closest;
|
||
}
|
||
|
||
Point_t Bridge::find_point_at_distance_clockwise(Ring& ring, const Point_t& start_point, size_t _index, double d, size_t& e_index)
|
||
{
|
||
// 确保环是闭合的(首尾点相同)
|
||
Ring normalized_r1 = ring;
|
||
if (!normalized_r1.empty() && !bg::equals(normalized_r1.front(), normalized_r1.back())) {
|
||
normalized_r1.push_back(normalized_r1.front());
|
||
}
|
||
double remaining_distance = d;
|
||
size_t current_edge = _index;
|
||
Point_t current_point = start_point;
|
||
while (remaining_distance > 0) {
|
||
// 获取当前边的终点
|
||
Point_t next_point = normalized_r1[(current_edge + 1) % normalized_r1.size()];
|
||
|
||
// 计算当前边剩余长度
|
||
double edge_length = bg::distance(current_point, next_point);
|
||
|
||
if (edge_length >= remaining_distance) {
|
||
// 目标点在当前边上
|
||
double ratio = remaining_distance / edge_length;
|
||
double x = current_point.x() + ratio * (next_point.x() - current_point.x());
|
||
double y = current_point.y() + ratio * (next_point.y() - current_point.y());
|
||
e_index = current_edge;
|
||
return Point_t(x, y);
|
||
}
|
||
else {
|
||
// 目标点在下一条边上,更新剩余距离
|
||
remaining_distance -= edge_length;
|
||
current_point = next_point;
|
||
current_edge = (current_edge + 1) % normalized_r1.size();
|
||
}
|
||
}
|
||
e_index = _index;
|
||
return start_point;
|
||
}
|
||
|
||
//在环上寻找长度最大的边索引
|
||
size_t Bridge::findLongestEdgeIndex(const Ring& ring) {
|
||
|
||
std::vector<size_t> max_indices;
|
||
double max_length = 0.0;
|
||
const size_t n = ring.size();
|
||
|
||
// 遍历所有边,收集最大长度边的索引
|
||
for (size_t i = 0; i < n - 1; ++i) {
|
||
const auto& p1 = ring[i];
|
||
const auto& p2 = ring[i + 1];
|
||
const double current_length = bg::distance(p1, p2);
|
||
|
||
if (current_length > max_length) {
|
||
max_length = current_length;
|
||
max_indices.clear();
|
||
max_indices.push_back(i);
|
||
}
|
||
else if (current_length == max_length) {
|
||
max_indices.push_back(i);
|
||
}
|
||
}
|
||
isFront = !isFront;
|
||
if (max_indices.size() > 1) {
|
||
sel_edge_index = isFront ? max_indices[0] : max_indices[max_indices.size() - 1];
|
||
}
|
||
else {
|
||
sel_edge_index = isFront ? (max_indices[0] + 1) % (n - 1) : (max_indices[0] - 1 + n) % (n - 1);
|
||
}
|
||
return sel_edge_index;
|
||
|
||
}
|
||
|
||
|
||
//点在环上的位置索引
|
||
int findPointIndex(const Ring& ring, const Point_t& p0) {
|
||
for (size_t i = 0; i < ring.size(); ++i) {
|
||
if (equal(ring[i], p0)) {
|
||
return static_cast<int>(i);
|
||
}
|
||
}
|
||
return -1; // 未找到
|
||
}
|
||
|
||
|
||
void insert_point_on_ring(Ring& ring, Point_t& point, size_t index, RingNode& rn) {
|
||
size_t s0 = rn.ring.size();
|
||
size_t s = ring.size();
|
||
const auto insertPos = ring.begin() + index + 1;
|
||
ring.insert(insertPos, point);
|
||
bg::correct(ring); //调整方向为顺时针
|
||
size_t s1 = ring.size();
|
||
size_t s01 = rn.ring.size();
|
||
}
|
||
|
||
|
||
//在第N条边上进行内外环桥接,并插入桥接点
|
||
void Bridge::handleBridge(IdIndex o_ii, IdIndex i_ii)
|
||
{
|
||
//判断环上是否存在桥接
|
||
for (auto& b : bridges) {
|
||
if (b.to_ii == i_ii) {
|
||
return;
|
||
}
|
||
}
|
||
|
||
RingNode& inner = findNode(i_ii);
|
||
RingNode& outer = findNode(o_ii);
|
||
|
||
size_t edge_index_inner = findLongestEdgeIndex(inner.ring);
|
||
size_t edge_index_outer = findLongestEdgeIndex(outer.ring);
|
||
|
||
double _offset = 0;
|
||
Point_t p0, p1, p2, p3;
|
||
size_t p0_index = 0, p0_index_1 = 0, p1_index = 0, p2_index = 0, p2_index_1 = 0, p3_index = 0;
|
||
bool _f = false;
|
||
int _loop = 0;
|
||
do {
|
||
//从内到外
|
||
p0 = findCenterPointOnEdge(inner.ring, edge_index_inner, _offset, p0_index);
|
||
Point_t p0_o = find_closest_point_on_ring_edges(outer.ring, p0, p0_index_1);
|
||
//从外到内
|
||
p2 = findCenterPointOnEdge(outer.ring, edge_index_outer, _offset, p2_index);
|
||
Point_t p2_i = find_closest_point_on_ring_edges(inner.ring, p2, p2_index_1);
|
||
double _d0 = bg::distance(p0, p0_o);
|
||
double _d1 = bg::distance(p2, p2_i);
|
||
if (_d0 > (2 * offset) && _d1 > (2 * offset)) {
|
||
_offset += offset;
|
||
_f = true;
|
||
continue;
|
||
}
|
||
if (_d0 < _d1) {
|
||
//从内到外
|
||
p2 = p0_o;
|
||
p2_index = p0_index_1;
|
||
}
|
||
else {
|
||
p0 = p2_i;
|
||
p0_index = p2_index_1;
|
||
}
|
||
p1 = find_point_at_distance_clockwise(inner.ring, p0, p0_index, offset, p1_index);
|
||
p3 = find_point_at_distance_clockwise(outer.ring, p2, p2_index, offset, p3_index);
|
||
if (!bridges.empty()) {
|
||
BridgeMap bm = bridges.back();
|
||
double d0 = bg::distance(bm.to, p2);
|
||
double d1 = bg::distance(bm.to2, p2);
|
||
double d2 = bg::distance(bm.to, p3);
|
||
double d3 = bg::distance(bm.to2, p3);
|
||
if (d0 < offset || d1 < offset || d2 < offset || d3 < offset) {
|
||
_offset += offset;
|
||
_f = true;
|
||
}
|
||
else {
|
||
_f = false;
|
||
}
|
||
}
|
||
|
||
} while (_f);
|
||
Segment seg1(p2, p1);
|
||
Segment seg2(p3, p0);
|
||
insert_point_on_ring(inner.ring, p1, p1_index, inner);
|
||
insert_point_on_ring(inner.ring, p0, p0_index, inner);
|
||
insert_point_on_ring(outer.ring, p3, p3_index, outer);
|
||
insert_point_on_ring(outer.ring, p2, p2_index, outer);
|
||
|
||
if (bg::intersects(seg1, seg2)) {
|
||
BridgeMap edge(p2, p1, p3, p0, o_ii, i_ii, edge_index_outer);
|
||
bridges.push_back(edge);
|
||
}
|
||
else {
|
||
BridgeMap edge(p2, p0, p3, p1, o_ii, i_ii, edge_index_outer);
|
||
bridges.push_back(edge);
|
||
}
|
||
|
||
}
|
||
|
||
|
||
//输出树结构
|
||
void Bridge::printTree() {
|
||
generateRings();
|
||
formatTree();
|
||
// 用于记录已访问的节点
|
||
//std::unordered_set<std::pair<size_t, size_t>> visited;
|
||
std::vector<IdIndex> visited;
|
||
dfs(findNode({ 1,1 }), visited);
|
||
}
|
||
|
||
int findIndex(std::vector<Point_t> points, const Point_t& p0) {
|
||
for (int i = 0; i < points.size(); ++i) {
|
||
if (equal(points[i], p0)) {
|
||
return static_cast<int>(i);
|
||
}
|
||
}
|
||
return -1; // 未找到
|
||
}
|
||
|
||
|
||
//递归遍历环
|
||
void Bridge::traverseRing(
|
||
RingNode& node,
|
||
IdIndex parent,
|
||
Point_t& start,
|
||
Point_t& end,
|
||
bool isOutermostLayer
|
||
) {
|
||
int size = node.ring.size();
|
||
int s_index = findPointIndex(node.ring, start);
|
||
int e_index = findPointIndex(node.ring, end);
|
||
std::vector<Point_t> c_points;
|
||
std::vector<Point_t> cc_points;
|
||
std::vector<Point_t> points;
|
||
for (int i = s_index; !equal(node.ring[i], end); i = (i + 1) % size) {
|
||
c_points.emplace_back(node.ring[i]);
|
||
}
|
||
c_points.emplace_back(end);
|
||
for (int i = s_index; !equal(node.ring[i], end); i = (i - 1 + size) % size) {
|
||
cc_points.emplace_back(node.ring[i]);
|
||
}
|
||
cc_points.emplace_back(end);
|
||
|
||
if (cc_points.size() > c_points.size()) {
|
||
points.assign(cc_points.begin(), cc_points.end());
|
||
}
|
||
else
|
||
{
|
||
points.assign(c_points.begin(), c_points.end());
|
||
}
|
||
int index = 0;
|
||
do {
|
||
//转换成SFML 顶点
|
||
/* path.emplace_back(sf::Vertex(
|
||
sf::Vector2f(static_cast<float>(points[index].x()),
|
||
static_cast<float>(points[index].y())),
|
||
node.id.id == 1 ? sf::Color::Red : sf::Color::White
|
||
));*/
|
||
path.emplace_back(points[index]);
|
||
|
||
BridgeMap* bridge = nullptr;
|
||
//判断该点是否为桥接点
|
||
for (auto& bm : bridges) {
|
||
if (equal(bm.from, points[index]) || equal(bm.from2, points[index])) {
|
||
bridge = &bm;
|
||
break;
|
||
}
|
||
}
|
||
if (bridge != nullptr) {
|
||
RingNode& rn = findNode(bridge->to_ii); //to 环
|
||
if (equal(bridge->from, points[index])) {
|
||
traverseRing(rn, node.id, bridge->to, bridge->to2, false);
|
||
index = findIndex(points, bridge->from2);
|
||
}
|
||
else if (equal(bridge->from2, points[index])) {
|
||
traverseRing(rn, node.id, bridge->to2, bridge->to, false);
|
||
index = findIndex(points, bridge->from);
|
||
/*if (index == -1)
|
||
index = findIndex(points, bridge->from2);*/
|
||
}
|
||
if (index == -1) {
|
||
std::cout << bridge->from.x() << "," << bridge->from.y() << std::endl;
|
||
break;
|
||
}
|
||
/* path.emplace_back(sf::Vertex(
|
||
sf::Vector2f(static_cast<float>(points[index].x()),
|
||
static_cast<float>(points[index].y())),
|
||
sf::Color::Red
|
||
));*/
|
||
path.emplace_back(points[index]);
|
||
}
|
||
index += isOutermostLayer ? -1 : 1;
|
||
} while (index > 0 && index < points.size());
|
||
|
||
|
||
}
|
||
|
||
//画路径 SFML顶点数组集
|
||
//std::vector<sf::Vertex> Bridge::outputPaths()
|
||
//{
|
||
// printTree();
|
||
// //第一个桥接边
|
||
// BridgeMap bm = bridges[0];
|
||
// IdIndex parent(1, 1);
|
||
// //遍历
|
||
// traverseRing(findNode(bm.from_ii), bm.from_ii, bm.from, bm.from2, true);
|
||
// //形成闭环
|
||
// path.emplace_back(sf::Vertex(
|
||
// sf::Vector2f(static_cast<float>(bm.from.x()),
|
||
// static_cast<float>(bm.from.y())),
|
||
// sf::Color::Red
|
||
// ));
|
||
// return path;
|
||
//}
|
||
|
||
// 将 Boost 多边形转换为 SFML 顶点数组
|
||
//sf::VertexArray Bridge::convertToSFML(const Polygon_t& poly, const sf::Color& color)
|
||
//{
|
||
// sf::VertexArray vertices(sf::LineStrip);
|
||
//
|
||
// // 外环
|
||
// for (const auto& pt : poly.outer()) {
|
||
// vertices.append(sf::Vertex(
|
||
// sf::Vector2f(static_cast<float>(pt.x()),
|
||
// static_cast<float>(pt.y())),
|
||
// color
|
||
// ));
|
||
// }
|
||
// return vertices;
|
||
//}
|
||
|
||
//所有环转换成顶点数组集
|
||
//std::vector<sf::VertexArray> Bridge::convert2vertex()
|
||
//{
|
||
// std::vector<sf::VertexArray> verteies;
|
||
// for (const auto& map : ringNodes) {
|
||
// for (const auto& m : map.second) {
|
||
// if (m.isHide) continue;
|
||
// Polygon_t poly;
|
||
// bg::assign(poly, m.ring);
|
||
// verteies.push_back(convertToSFML(poly, sf::Color::Red));
|
||
// }
|
||
// }
|
||
// return verteies;
|
||
//}
|
||
|
||
//std::vector<sf::VertexArray> Bridge::convertBridge()
|
||
//{
|
||
// std::vector<sf::VertexArray> verteies;
|
||
// for (const auto& map : bridges) {
|
||
// sf::VertexArray arr(sf::LineStrip);
|
||
// arr.append(sf::Vertex(
|
||
// sf::Vector2f(static_cast<float>(map.from.x()),
|
||
// static_cast<float>(map.from.y())),
|
||
// sf::Color::White
|
||
// ));
|
||
// arr.append(sf::Vertex(
|
||
// sf::Vector2f(static_cast<float>(map.to.x()),
|
||
// static_cast<float>(map.to.y())),
|
||
// sf::Color::White
|
||
// ));
|
||
// sf::VertexArray arr1(sf::LineStrip);
|
||
// arr1.append(sf::Vertex(
|
||
// sf::Vector2f(static_cast<float>(map.from2.x()),
|
||
// static_cast<float>(map.from2.y())),
|
||
// sf::Color::White
|
||
// ));
|
||
// arr1.append(sf::Vertex(
|
||
// sf::Vector2f(static_cast<float>(map.to2.x()),
|
||
// static_cast<float>(map.to2.y())),
|
||
// sf::Color::White
|
||
// ));
|
||
// verteies.push_back(arr);
|
||
// verteies.push_back(arr1);
|
||
// }
|
||
// return verteies;
|
||
//}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
} // namespace Slic3r
|
||
|
||
|