#include "../ClipperUtils.hpp" #include "../ExPolygon.hpp" #include "../Surface.hpp" #include "../ShortestPath.hpp" #include "Bridge.hpp" //#include //#include // //#include //#include //#include //#include //#include //namespace mpd = boost::multiprecision::decimal; namespace Slic3r { // 为 std::pair 定义哈希函数 //template<> //struct std::hash> { // std::size_t operator()(const std::pair& p) const noexcept { // return std::hash()(p.first) ^ (std::hash()(p.second) << 1); // } //}; Polylines Bridge::fill_surface(const Surface* surface, const FillParams& params) { Polylines polylines_out; //BoundingBox bounding_box = surface->expolygon.contour.bounding_box(); Points points = surface->expolygon.contour.points; Point first = points[0]; points.push_back(first); //Polygon outPolygon = bounding_box.polygon(); Polygon_t polygon; std::vector outerBoundary; outerBoundary.reserve(points.size()); int precision = 1e7; for (Point one : points) { double x = one.x(); double y = one.y(); //double x_result = x / 1000000.0 + 200; //double y_result = y / 1000000.0 + 200; //double stored_x = std::round(x_result * precision) / precision; //double stored_y = std::round(y_result * precision) / precision; //Point_t temp = { stored_x ,stored_y }; Point_t temp = { x ,y }; outerBoundary.push_back(temp); } bg::append(polygon.outer(), outerBoundary); //std::vector innerBoundary; //Polygons inPolygons = surface->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; auto abc = float(scale_(this->overlap - 0.5 * this->spacing)); if (abc < 0) { abc = -abc; } //this->offset = abc/ 1000000.0; this->offset = 4000000; printTree(); int size = ringNodes.begin()->second.size(); //第一个桥接边 int b_size = bridges.size(); BridgeMap bm = bridges[0]; IdIndex parent(1, 1); //遍历 traverseRing(findNode(bm.from_ii), parent, bm.from, bm.from2, true); //outputPaths(); 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()+200)* 1000000.0,(path[i].y()+200) * 1000000.0 }; //Point p2 = { (path[i + 1].x()+200) * 1000000.0,(path[i + 1].y()+200) * 1000000.0 }; 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& 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(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 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 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& 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(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 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 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); } }*/ bool is_point_on_segment(const Point_t& p, const Segment& seg, double tolerance = 1e-6) { // 计算点到线段的距离 double dist = bg::distance(p, seg); // 检查距离是否在容差范围内 if (dist > tolerance) { return false; } // 获取线段端点 const Point_t& p1 = seg.first; const Point_t& p2 = seg.second; // 检查点是否在线段的边界框内 double min_x = std::min(p1.x(), p2.x()); double max_x = std::max(p1.x(), p2.x()); double min_y = std::min(p1.y(), p2.y()); double max_y = std::max(p1.y(), p2.y()); // 考虑容差 return (p.x() >= min_x - tolerance) && (p.x() <= max_x + tolerance) && (p.y() >= min_y - tolerance) && (p.y() <= max_y + tolerance); } // 计算点到原点的距离平方 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); } // 找到环中距离原点最近的点作为起点 void reorder_ring_start_point(Ring& ring) { // 找到距离原点最近的点 auto min_it = std::min_element(ring.begin(), ring.end(), [](const Point_t& a, const Point_t& b) { return distance_to_origin_sq(a) < distance_to_origin_sq(b); }); // 旋转环使最近的点成为起点 std::rotate(ring.begin(), min_it, ring.end() - 1); // end()-1 保留闭合点 // 确保环保持闭合 if (!bg::equals(ring.front(), ring.back())) { ring.back() = ring.front(); } } //将节点加入处理节点集合中 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) { reorder_ring_start_point(node.ring); // 检查键是否存在 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& 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& 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(const 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); } } // 判断两个环是否相交(不包括包含关系) bool Bridge::ringsIntersect(const Ring& ring1, const Ring& ring2) { // 首先检查是否相交(包括边界相交) if (!bg::intersects(ring1, ring2)) { return false; } // 然后排除包含关系 bool ring1_inside_ring2 = bg::within(ring1, ring2); bool ring2_inside_ring1 = bg::within(ring2, ring1); // 如果存在包含关系,则不算作相交 if (ring1_inside_ring2 || ring2_inside_ring1) { return false; } return true; } //获取环偏移后的环(可能为空) std::vector Bridge::offsetRing(const Ring& ring, const double distance) { // 将环包装成多边形 Polygon_t inputPolygon; inputPolygon.outer() = ring; // 修复几何数据 bg::correct(inputPolygon); // 使用 multi_polygon 作为 buffer 的输出类型 bg::model::multi_polygon result; // 使用对称距离策略 bg::buffer(inputPolygon, result, bg::strategy::buffer::distance_symmetric(distance), bg::strategy::buffer::side_straight(), bg::strategy::buffer::join_round(), bg::strategy::buffer::end_round(), bg::strategy::buffer::point_circle()); // 提取偏移后的环 std::vector offsetRing; for (const auto& poly : result) { offsetRing.emplace_back(poly.outer()); } return offsetRing; } // 查找环非邻边的相交点 std::vector Bridge::findNonAdjacentIntersections(const Ring& ring) { Polygon_t poly; bg::append(poly.outer(), ring); std::vector intersections; std::vector> segments; const size_t num_points = bg::num_points(poly.outer()); // 构建所有边的线段 for (int i = 0; i < num_points - 1; ++i) { segments.emplace_back(poly.outer()[i], poly.outer()[i + 1]); } // 遍历所有非邻边对 for (size_t i = 0; i < segments.size(); ++i) { for (size_t j = i + 2; j < segments.size(); ++j) { if ((i == 0 && j == segments.size() - 1)) continue; // 排除相邻边 std::vector intersection_points; bg::intersection(segments[i], segments[j], intersection_points); for (const auto& point : intersection_points) { // 检查相交点是否为多边形的顶点 bool is_vertex = false; for (const auto& vertex : polygon.outer()) { if (bg::equals(point, vertex)) { is_vertex = true; break; } } if (!is_vertex) { intersections.push_back(point); } } } } return intersections; } // 将环拆分成多个环 std::vector Bridge::split(const Ring& ring, const std::vector& intersections) { std::vector rings; std::vector visited(ring.size(), false); Ring extendedRing = ring; // 插入相交点到环中 for (const auto& intersection : intersections) { for (size_t i = 0; i < ring.size(); ++i) { Segment seg(ring[i], ring[(i + 1) % ring.size()]); if (bg::within(intersection, seg)) { extendedRing.insert(extendedRing.begin() + i + 1, intersection); break; } } } std::vector newVisited(extendedRing.size(), false); for (size_t i = 0; i < extendedRing.size(); ++i) { if (newVisited[i]) continue; Ring newRing; size_t current = i; do { newRing.push_back(extendedRing[current]); newVisited[current] = true; current = (current + 1) % extendedRing.size(); } while (current != i); if (newRing.size() > 2) { rings.push_back(newRing); } } return rings; } // 在环的指定位置插入点 void insert_point_in_ring(Ring& ring, const Point_t& point, size_t after_index) { auto it = ring.begin(); std::advance(it, after_index + 1); ring.insert(it, point); } // 找到环上应该插入交点的位置 std::vector> find_insertion_points(const Ring& ring, const std::vector& intersections) { std::vector> insertion_points; for (const auto& p : intersections) { double min_dist = std::numeric_limits::max(); size_t best_segment = 0; for (size_t i = 0; i < ring.size() - 1; ++i) { Point_t seg_start = ring[i]; Point_t seg_end = ring[i + 1]; // 计算点到线段的距离 double dist = bg::distance(p, bg::model::segment(seg_start, seg_end)); if (dist < min_dist) { min_dist = dist; best_segment = i; } } if (min_dist < 1e-6) { // 使用小的容差值 insertion_points.emplace_back(best_segment, p); } } // 按插入位置排序,从后往前插入 std::sort(insertion_points.begin(), insertion_points.end(), [](const auto& a, const auto& b) { return a.first > b.first; }); return insertion_points; } // 合并两个环 std::vector Bridge::merge(const RingNode& ring1, const RingNode& ring2) { // 将环转换为多边形 Polygon_t poly1, poly2; bg::append(poly1.outer(), ring1.ring); bg::append(poly2.outer(), ring2.ring); bg::correct(poly1); // 确保多边形是有效的 bg::correct(poly2); // 确保多边形是有效的 std::vector intersection_points; bg::intersection(poly1, poly2, intersection_points); // 将交点插入到两个多边形中 auto insertions1 = find_insertion_points(poly1.outer(), intersection_points); for (const auto& ins : insertions1) { insert_point_in_ring(poly1.outer(), ins.second, ins.first); } auto insertions2 = find_insertion_points(poly2.outer(), intersection_points); for (const auto& ins : insertions2) { insert_point_in_ring(poly2.outer(), ins.second, ins.first); } // 计算多边形交、差布尔运算 /* MultiPolygon mp0; bg::intersection(poly1, poly2, mp0);*/ MultiPolygon mp1; bg::difference(poly1, poly2, mp1); MultiPolygon mp2; bg::difference(poly2,poly1, mp2); // 合并所有结果多边形 MultiPolygon result; //result.insert(result.end(), mp0.begin(), mp0.end()); if (ring1.orientation == -1 && ring2.orientation == 1) { result.insert(result.end(), mp1.begin(), mp1.end()); } else if(ring1.orientation == 1 && ring2.orientation == -1){ result.insert(result.end(), mp2.begin(), mp2.end()); } else { result.insert(result.end(), mp1.begin(), mp1.end()); result.insert(result.end(), mp2.begin(), mp2.end()); } std::vector allRings; for (const auto& poly : result) { allRings.emplace_back(poly.outer()); } //for (const auto& poly : result) { // allRings.push_back(poly.outer()); // for (const auto& inner : poly.inners()) { // allRings.push_back(inner); // } //} //// 过滤掉被其他环完全包含的环 std::vector 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 allRings; } //生成环集 void Bridge::generateRings() { //获取多边形的外边界和内边界 computePolygonBoundaries(polygon); //外边界 std::vector rings = offsetRing(boundaries.outerBoundary, -offset / 2); for (auto& r : rings) { RingNode node = formatNode(maxRid++, 1, r, -1); nodeHandles.emplace_back(node); addNode(node); } //内边界 偏移 std::map offRings; //存放待偏移的环 for (auto& inner : boundaries.innerBoundaries) { offRings.insert({{maxRid++,1},inner }); } std::vector tempRings; for (auto& r : offRings) { std::vector _rings = offsetRing(r.second, offset / 2); if (_rings.size() == 1) { RingNode node1 = formatNode(r.first.id, r.first.index + 1, _rings[0], 1); if (bg::area(node1.ring) > area_threshold) { addNode(node1); tempRings.emplace_back(node1); } } else if (_rings.size() > 1) { std::vector id_indices; for (auto& r1 : _rings) { RingNode node0 = formatNode(++maxRid, 1, r1, 1); if (bg::area(node0.ring) > area_threshold) { addNode(node0); tempRings.emplace_back(node0); IdIndex ii(maxRid, 1); id_indices.emplace_back(ii); } } //分裂映射 offsetMap.insert(std::pair>({ r.first.id,r.first.index }, id_indices)); } } nodeHandles.insert(nodeHandles.end(), tempRings.begin(), tempRings.end()); //遍历当前用于判断自/互交的节点集 while (!nodeHandles.empty()) { std::vector interNodes; //产生互交的节点集 std::vector nodes; //互交后产生的节点 for (auto it1 = nodeHandles.begin(); it1 != nodeHandles.end(); ++it1) { //互交判断&处理 auto it2 = std::next(it1); for (;it2 != nodeHandles.end(); ++it2) { if (ringsIntersect(it1->ring, it2->ring)) { //合并 std::vector rings = merge(*it1, *it2); std::vector id_indices; for (const auto& ring2 : rings) { // 外与内 外与外 -> 向内; 内与内 -> 向外 const int orientation = (it1->orientation + it2->orientation) <= 0 ? -1 : 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); } } MergeMap mm(it1->id, it2->id, id_indices); mergeMap.emplace_back(mm); interNodes.emplace_back(*it1); interNodes.emplace_back(*it2); it1++; break; } } } //删除互交节点 for (auto& n : interNodes) { nodeHandles.erase(std::remove(nodeHandles.begin(), nodeHandles.end(), n), nodeHandles.end()); } //是否存在互交 if (!nodes.empty()) { for (auto& n : nodes) { nodeHandles.emplace_back(n); } } std::vector offsetNodes; //偏移 for (auto& node : nodeHandles) { //if (node.orientation == 1) continue; std::vector ring0 = offsetRing(node.ring, static_cast(node.orientation) * offset); 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 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>({node.id.id,node.id.index }, id_indices)); } } //清空 nodeHandles.clear(); if (!offsetNodes.empty()) { //重填 nodeHandles.insert(nodeHandles.end(), offsetNodes.begin(), offsetNodes.end()); } } } //形成树 void Bridge::formatTree() { //遍历不同环类型的节点集合 for (auto& ringNode : ringNodes) { // 使用反向迭代器进行反序遍历 std::vector& vec = ringNode.second; const auto it0 = ringNode.second.begin(); if (it0->orientation == 1) { // 向外 倒序 for (int 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 : mergeMap) { //合并 RingNode& it1 = findNode(map.ii1); RingNode& it2 = findNode(map.ii2); for (const auto& ii : map.nodes) { RingNode& it = findNode(ii); if (it.orientation == -1) { //向内 //内 外 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); it.parent = it2.parent; 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作为it1子节点的父节点 for (auto& c : it1.children) { c.parent = ⁢ } it.children.insert(it.children.end(), it1.children.begin(), it1.children.end()); } else if (it1.orientation == 1 && it2.orientation == 1) { //外 外 //it作为it1子节点的父节点 for (auto& c : it1.children) { c.parent = ⁢ } it.children.insert(it.children.end(), it1.children.begin(), it1.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) {// 内 内 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()); it2.parent->children.emplace_back(it); //it.parent = it2.parent; 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()); } } else { //向外 //it1.parent = ⁢ //将it1的子节点作为it的子节点 it.children.insert(it.children.end(), it1.children.begin(), it1.children.end()); it1.children.clear(); //清空it1的子节点集 //it2.parent = ⁢ it.children.insert(it.children.end(), it2.children.begin(), it2.children.end()); it2.children.clear(); } RingNode* it_parent = it.parent; //判断是否互交 if (ringsIntersect(it.ring, it_parent->ring)) { //合并 std::vector rings = merge(it1, *it1.parent); const int orientation = (it1.orientation + it1.parent->orientation) <= 0 ? -1 : 1; RingNode node1 = formatNode(++maxRid, 1, rings[0], orientation); if (bg::area(node1.ring) > area_threshold) { addNode(node1); findNode(node1.id).children.insert(findNode(node1.id).children.end(), it1.children.begin(), it1.children.end()); if (it_parent->parent != nullptr) { IdIndex ii = it_parent->id; it_parent->parent->children.erase(std::remove_if(it_parent->parent->children.begin(), it_parent->parent->children.end(), [ii](RingNode x) { return x.id.id == ii.id && x.id.index == ii.index; }), it_parent->parent->children.end()); it_parent->parent->children.emplace_back(node1); } } } } } } //树遍历 //void Bridge::dfs(RingNode& node, std::unordered_set>& visited, size_t& edge) { // if (visited.find({ node.id.id, node.id.index }) != visited.end()) { // return; // } // visited.insert({ node.id.id, node.id.index }); // edge++; // // 处理当前节点 // std::cout << "rId: " << node.id.id << ", rIndex: " << node.id.index // << ", orientation: " << node.orientation // << ", isHide: " << (node.isHide ? "true" : "false") << std::endl; // // Polygon poly; // bg::assign(poly, node.ring); // verteies.push_back(convertToSFML(poly, sf::Color::Red)); // // // 递归遍历子节点 // for (auto& child : node.children) { // handleBridge(node.id, child.id, child.ring.size(),edge); // dfs(findNode(child.id), visited, edge); // } //} void Bridge::dfs(RingNode& node, std::vector& visited, size_t& edge) { auto& it = std::find_if(visited.begin(), visited.end(), [node](const IdIndex& ii) { return ii.id == node.id.id && ii.index == node.id.index; }); if (it != visited.end()) { return; } visited.emplace_back(node.id); edge++; // 处理当前节点 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, child.ring.size(), edge); dfs(findNode(child.id), visited, edge); } } //找到多边形环第 N 条边的中心点 Point_t Bridge::findCenterPointOnEdge(Ring& ring, size_t N) { // 获取第 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); const auto insertPos = ring.begin() + N + 1; ring.insert(insertPos, p); bg::correct(ring); //调整方向为顺时针 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 const double t = ((x - x1) * dx + (y - y1) * dy) / (dx * dx + dy * dy); // 根据t值确定最近点 if (t <= 0.0) { return seg_start; } else if (t >= 1.0) { return seg_end; } else { return Point_t(x1 + t * dx, y1 + t * dy); } } // 在环的边上查找离给定点最近的点 Point_t find_closest_point_on_ring_edges(Ring& ring, const Point_t& p0) { // 验证环是否闭合 if (ring.size() < 2 || !bg::equals(ring.front(), ring.back())) { throw std::runtime_error("Ring is not closed"); } Point_t closest_point; double min_distance = std::numeric_limits::max(); size_t e_index = 0; // 遍历环的所有边 for (size_t i = 0; i < ring.size() - 1; ++i) { const Point_t& p1 = ring[i]; const Point_t& p2 = ring[i + 1]; // 计算线段上的最近点 Point_t projected_point = closest_point_on_segment(p0, p1, p2); // 计算距离 double distance = bg::distance(p0, projected_point); // 更新最近点 if (distance < min_distance) { min_distance = distance; closest_point = projected_point; e_index = i; } } //插入 ring.insert(ring.begin()+e_index+1, closest_point); bg::correct(ring); //调整方向为顺时针 return closest_point; } // 找到点所在的边(返回边起点索引) std::pair find_edge_containing_point(const Ring& ring, const Point_t& point) { for (size_t i = 0; i < ring.size() - 1; ++i) { const Point_t& p1 = ring[i]; const Point_t& p2 = ring[i + 1]; // 计算点到线段的距离 double seg_length = bg::distance(p1, p2); if (seg_length == 0) continue; // 忽略零长度边 // 计算点在边上的投影参数t double t = ((bg::get<0>(point) - bg::get<0>(p1)) * (bg::get<0>(p2) - bg::get<0>(p1)) + (bg::get<1>(point) - bg::get<1>(p1)) * (bg::get<1>(p2) - bg::get<1>(p1))) / (seg_length * seg_length); // 如果点在当前边上 if (t >= 0.0 && t <= 1.0) { Point_t proj( bg::get<0>(p1) + t * (bg::get<0>(p2) - bg::get<0>(p1)), bg::get<1>(p1) + t * (bg::get<1>(p2) - bg::get<1>(p1)) ); // 检查投影点与实际点的距离是否足够近 if (bg::distance(point, proj) < 1e-6) { return { i, t }; } } } } Point_t Bridge::find_point_at_distance_clockwise(Ring& ring, const Point_t& start_point, double d) { // 1. 找到起点所在的边 std::pair p = find_edge_containing_point(ring, start_point); size_t edge_index = p.first; double t = p.second; // 计算从起点到当前边终点的剩余距离 const Point_t& p1 = ring[edge_index]; const Point_t& p2 = ring[(edge_index + 1) % ring.size() ]; double remaining_on_edge = (1.0 - t) * bg::distance(p1, p2); // 3. 如果剩余距离足够 if (remaining_on_edge >= d) { double new_t = t + d / bg::distance(p1, p2); Point_t p(bg::get<0>(p1) + new_t * (bg::get<0>(p2) - bg::get<0>(p1)), bg::get<1>(p1) + new_t * (bg::get<1>(p2) - bg::get<1>(p1))); auto insertPos = ring.begin() + edge_index + 1; ring.insert(insertPos, p); bg::correct(ring); //调整方向为顺时针 return p; } // 4. 否则继续遍历后续边 double accumulated_distance = remaining_on_edge; size_t current_index = (edge_index + 1) % (ring.size() - 1); while (accumulated_distance < d) { const Point_t& p1 = ring[current_index]; const Point_t& p2 = ring[(current_index + 1) % (ring.size() - 1)]; double segment_length = bg::distance(p1, p2); if (accumulated_distance + segment_length >= d) { double ratio = (d - accumulated_distance) / segment_length; //在current_index 插入 Point_t p(bg::get<0>(p1) + ratio * (bg::get<0>(p2) - bg::get<0>(p1)), bg::get<1>(p1) + ratio * (bg::get<1>(p2) - bg::get<1>(p1))); auto insertPos = ring.begin() + current_index + 1; ring.insert(insertPos, p); bg::correct(ring); //调整方向为顺时针 return p; } accumulated_distance += segment_length; current_index = (current_index + 1) % (ring.size() - 1); } return Point_t(); } // 判断点是否在线段内部(非端点) bool is_point_inside_segment(const Point_t& p, const Segment& seg) { double x = bg::get<0>(p); double y = bg::get<1>(p); double x1 = bg::get<0>(seg.first); double y1 = bg::get<1>(seg.first); double x2 = bg::get<0>(seg.second); double y2 = bg::get<1>(seg.second); // 检查点是否在线段的包围盒内 if ((x < std::min(x1, x2) - 1e-6) || (x > std::max(x1, x2) + 1e-6) || (y < std::min(y1, y2) - 1e-6) || (y > std::max(y1, y2) + 1e-6)) { return false; } // 向量叉积判断共线(可跳过,因为 intersects 已保证相交) double cross = (x - x1) * (y2 - y1) - (y - y1) * (x2 - x1); if (std::abs(cross) > 1e-6) return false; return true; } // 判断两线段是否在内部相交(排除端点接触) bool segments_cross(const Segment& seg1, const Segment& seg2) { if (!bg::intersects(seg1, seg2)) return false; std::vector points; bg::intersection(seg1, seg2, points); if (points.empty()) return false; // 检查交点是否在两条线段的内部 for (const auto& p : points) { if (is_point_inside_segment(p, seg1) && is_point_inside_segment(p, seg2)) { return true; } } return false; } //在环上寻找长度最大的边索引 size_t Bridge::findLongestEdgeIndex(const Ring& ring) { if (ring.size() < 4) { throw std::invalid_argument("Ring must have at least 4 points"); } std::vector 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 { /*std::random_device rd; std::mt19937 gen(rd()); std::uniform_int_distribution<> dis(1, n);*/ sel_edge_index = isFront?(max_indices[0] + 1) % (n - 1):(max_indices[0]-1+n)%(n-1); } return sel_edge_index; } //判断两个点是否相等 bool equal(Point_t p1, Point_t p2) { return p1.x() == p2.x() && p1.y() == p2.y(); } //在第N条边上进行内外环桥接,并插入桥接点 void Bridge::handleBridge(IdIndex o_ii, IdIndex i_ii,const size_t ring_size, const size_t N) { //随机选择桥接的边 RingNode& inner = findNode(i_ii); RingNode& outer = findNode(o_ii); //从内到外 size_t edge_index = findLongestEdgeIndex(inner.ring); Point_t p0 = findCenterPointOnEdge(inner.ring, edge_index); Point_t p1 = find_point_at_distance_clockwise(inner.ring, p0, offset); Point_t p2 = find_closest_point_on_ring_edges(outer.ring, p0); Point_t p3 = find_point_at_distance_clockwise(outer.ring, p2, offset); //从外到内 edge_index = findLongestEdgeIndex(outer.ring); Point_t p2_1 = findCenterPointOnEdge(outer.ring, edge_index); Point_t p3_1 = find_point_at_distance_clockwise(outer.ring, p2_1, offset); Point_t p0_1 = find_closest_point_on_ring_edges(inner.ring, p2_1); Point_t p1_1 = find_point_at_distance_clockwise(inner.ring, p0_1, offset); //判断环上是否存在桥接 bool isExist = false; for (auto& b : bridges) { if (b.to_ii == i_ii) { isExist = true; break; } } if (isExist) return; if (bg::distance(p1, p2) < bg::distance(p1_1, p2_1)) { Segment seg1(p2, p1); Segment seg2(p3, p0); if (bg::intersects(seg1, seg2)) { BridgeMap edge(p2, p1, p3, p0, o_ii, i_ii); bridges.push_back(edge); } else { BridgeMap edge(p2, p0, p3, p1, o_ii, i_ii); bridges.push_back(edge); } } else { Segment seg1(p2_1, p1_1); Segment seg2(p3_1, p0_1); if (bg::intersects(seg1, seg2)) { BridgeMap edge(p2_1, p1_1, p3_1, p0_1, o_ii, i_ii); bridges.push_back(edge); } else { BridgeMap edge(p2_1, p0_1, p3_1, p1_1, o_ii, i_ii); bridges.push_back(edge); } } } //输出所有环 void Bridge::printRings() { generateRings(); // 输出环中的点信息 std::cout << "Points in the ring:" << std::endl; for (const auto& map : ringNodes) { std::cout << "(" << map.first << std::endl; for (const auto& node : map.second) { std::cout << "{" << node.id.id << "," << node.id.index << "," << node.orientation << std::endl; for (const auto& point : node.ring) { std::cout << "(" << bg::get<0>(point) << "," << bg::get<1>(point) << ")"; } std::cout << "}" << std::endl; } std::cout << ")" << std::endl; } } //输出树结构 void Bridge::printTree() { generateRings(); formatTree(); // 用于记录已访问的节点 //std::unordered_set> visited; std::vector visited; size_t edge = 1; dfs(findNode({ 1,1 }), visited,edge); } //点在环上的位置索引 int findPointIndex(const Ring& ring, const Point_t& p0) { for (size_t i = 0; i < ring.size(); ++i) { if (ring[i].x() == p0.x() && ring[i].y() == p0.y()) { return static_cast(i); } } return -1; // 未找到 } int findIndex(std::vector points, const Point_t& p0) { for (int i = 0; i < points.size(); ++i) { if (equal(points[i], p0)){ return static_cast(i); } } return -1; // 未找到 } //递归遍历环 void Bridge::traverseRing( RingNode& node, IdIndex parent, Point_t& start, Point_t& end, bool isOutermostLayer ) { //得到start点在环ring上的索引位置 int size = node.ring.size(); int s_index = findPointIndex(node.ring, start); int e_index = findPointIndex(node.ring, end); std::vector c_points; std::vector cc_points; std::vector 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(points[index].x()), static_cast(points[index].y())), sf::Color::Red ));*/ 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) break; /* path.emplace_back(sf::Vertex( sf::Vector2f(static_cast(points[index].x()), static_cast(points[index].y())), sf::Color::Red ));*/ path.emplace_back(points[index]); } index += isOutermostLayer ? -1 : 1; } while (index > 0 && index < points.size()); } //画路径 SFML顶点数组集 //std::vector Bridge::outputPaths() //{ // printTree(); // //第一个桥接边 // BridgeMap bm = bridges[0]; // IdIndex parent(1,1); // //遍历 // traverseRing(findNode(bm.from_ii), parent, bm.from, bm.from2, true); // //形成闭环 // path.emplace_back(sf::Vertex( // sf::Vector2f(static_cast(bm.from.x()), // static_cast(bm.from.y())), // sf::Color::Red // )); // return path; // //} } // namespace Slic3r