#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
#include <map>
using namespace std;
struct Point {
double x, y;
Point() {}
Point(double _x, double _y) : x(_x), y(_y) {}
};
struct Line {
Point p1, p2;
double angle;
Line() {}
Line(Point _p1, Point _p2) : p1(_p1), p2(_p2) {
angle = atan2(p2.y - p1.y, p2.x - p1.x);
}
bool operator < (const Line& other) const {
return angle < other.angle;
}
};
bool is_closed_loop(vector<Line>& lines) {
map<Point, int> point_count;
for (const Line& line : lines) {
point_count[line.p1]++;
point_count[line.p2]++;
}
for (const auto& p : point_count) {
if (p.second != 2) {
return false;
}
}
return true;
}
vector<Line> reorder_lines(vector<Line>& lines) {
// Sort the lines by their angle with respect to the first point
sort(lines.begin(), lines.end());
// Find the leftmost point
Point leftmost_point = lines[0].p1;
for (const Line& line : lines) {
if (line.p1.x < leftmost_point.x) {
leftmost_point = line.p1;
}
if (line.p2.x < leftmost_point.x) {
leftmost_point = line.p2;
}
}
// Build a map of the endpoints of each line
map<Point, Line*> endpoint_map;
for (Line& line : lines) {
endpoint_map[line.p1] = &line;
endpoint_map[line.p2] = &line;
}
// Reorder the lines starting from the leftmost point
vector<Line> ordered_lines;
Point current_point = leftmost_point;
Line* current_line = endpoint_map[current_point];
ordered_lines.push_back(*current_line);
endpoint_map.erase(current_point);
while (!endpoint_map.empty()) {
// Find the next line in clockwise direction
Line* next_line = nullptr;
double min_angle_diff = INFINITY;
for (auto& p : endpoint_map) {
Line* line = p.second;
if (line->p1 == current_point) {
double angle_diff = line->angle - current_line->angle;
if (angle_diff < 0) {
angle_diff += 2 * M_PI;
}
if (angle_diff < min_angle_diff) {
next_line = line;
min_angle_diff = angle_diff;
}
}
if (line->p2 == current_point) {
double angle_diff = current_line->angle - line->angle;
if (angle_diff < 0) {
angle_diff += 2 * M_PI;
}
if (angle_diff < min_angle_diff) {
next_line = line;
min_angle_diff = angle_diff;
}
}
}
// Update the current point and line
if (next_line == nullptr) {
cerr << "Error: Failed to find the next line." << endl;
exit(1);
}
current_line = next_line;
ordered_lines.push_back(*current_line);
endpoint_map.erase(current_line
//接下来是实现代码的第二部分,即排序和输出结果。
// 定义比较函数,用于平衡树排序
bool cmp(const Line &a, const Line &b) {
if (a.maxY < b.minY) return true;
if (a.minY > b.maxY) return false;
if (a.k != b.k) return a.k < b.k;
return a.b < b.b;
}
// 排序并输出结果
void sortAndOutput(vector<Line> &lines) {
// 构造平衡树
set<Line, bool(*)(const Line&, const Line&)> bst(cmp);
for (const auto &line : lines) {
bst.insert(line);
}
// 按顺序输出结果
int cnt = 0;
for (const auto &line : bst) {
if (cnt == 0) {
// 第一条线,保存为起点
start = line.a;
}
else {
// 连接两条线段
end = line.b;
cout << "(" << start.x << "," << start.y << ")" << "->"
<< "(" << end.x << "," << end.y << ")" << endl;
start = end;
}
cnt++;
}
// 输出最后一条线段
end = lines[0].a;
cout << "(" << start.x << "," << start.y << ")" << "->"
<< "(" << end.x << "," << end.y << ")" << endl;
}
这部分的主要工作是将线段按照从上到下、斜率、截距等方式排序,并使用平衡树进行排序。然后按照顺序输出线段,将它们组成轮廓。
最后,我们可以将上面的所有代码组合在一起,得到完整的算法实现:
#include <iostream>
#include <vector>
#include <algorithm>
#include <set>
using namespace std;
// 线段类
class Line {
public:
Point a, b; // 线段的两个端点
double k, b; // 线段的斜率和截距
double maxY, minY; // 线段的最大y值和最小y值
Line(const Point &a, const Point &b) {
// 确保a是上端点,b是下端点
if (a.y > b.y) {
this->a = b;
this->b = a;
}
else {
this->a = a;
this->b = b;
}
// 计算斜率和截距
if (this->a.x == this->b.x) {
k = INFINITY;
b = this->a.x;
}
else {
k = (double)(this->a.y - this->b.y) / (double)(this->a.x - this->b.x);
b = this->a.y - k * this->a.x;
}
// 计算最大y值和最小y值
maxY = max(this->a.y, this->b.y);
minY = min(this->a.y, this->b.y);
}
};
// 定义比较函数,用于平

2437

被折叠的 条评论
为什么被折叠?



