框选N条(线段,多段线),求不重合闭合区域问题

需求:选择图中所有线条,求所有不重合的闭合区域(根据本人研究,该功能,AutoCAD并未完美实现)

4625f26b42d021fd4143161d97a3a3fc839.jpg

解决方案:

第一步:求解图中所有Line和Pline的交点及端点(记为arPoint),并按照交点将长线段离散为小线段(记为arLine);

第二步:根据arLine和arPoint,求出所有点位引出的向量(记为arVector);

第三步:剔除所有孤立点,即只有引出向量数组为大小为1的点位;

第四步:遍历(对每一个点位引出的方向按照顺时针,方向角最大为原则),可以计算所有有可能的闭合区域arRegion;

第五步:对所有arRegion进行处理,即处理重线问题;

第六步:数据检查,去重,剔除arRegion中具有包含关系的闭合区域;

第七部:对每一个区域进行图案填充;

实现效果:

b146486ac3f27e283a30bfa76b66e0ce250.jpg

转载于:https://my.oschina.net/u/2549097/blog/3012484

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的实现,基于扫描线算法和计算几何的知识: ```cpp #include <bits/stdc++.h> using namespace std; const double eps = 1e-8; const int maxn = 1005; int dcmp(double x) { if (fabs(x) < eps) return 0; return x > 0 ? 1 : -1; } struct Point { double x, y; Point() {} Point(double x, double y) : x(x), y(y) {} bool operator < (const Point& rhs) const { return dcmp(x - rhs.x) < 0 || (dcmp(x - rhs.x) == 0 && dcmp(y - rhs.y) < 0); } bool operator == (const Point& rhs) const { return dcmp(x - rhs.x) == 0 && dcmp(y - rhs.y) == 0; } Point operator + (const Point& rhs) const { return Point(x + rhs.x, y + rhs.y); } Point operator - (const Point& rhs) const { return Point(x - rhs.x, y - rhs.y); } Point operator * (const double& k) const { return Point(x * k, y * k); } double operator * (const Point& rhs) const { return x * rhs.y - y * rhs.x; } }; struct Line { Point st, ed; double angle; Line() {} Line(Point st, Point ed) : st(st), ed(ed) { angle = atan2(ed.y - st.y, ed.x - st.x); } bool operator < (const Line& rhs) const { return angle < rhs.angle; } }; Point get_line_intersection(Line a, Line b) { Point u = a.st - b.st; double t = (b.ed - b.st) * u / (a.ed - a.st) * (b.ed - b.st); return a.st + (a.ed - a.st) * t; } bool on_right(Line l, Point p) { return dcmp((p - l.st) * (l.ed - l.st)) > 0; } vector<Point> HalfPlaneIntersection(vector<Line> lines) { vector<Point> p, res; sort(lines.begin(), lines.end()); int n = lines.size(); for (int i = 0; i < n; i++) { if (i && dcmp(lines[i].angle - lines[i - 1].angle) == 0) continue; while (p.size() > 1 && on_right(lines[i], p.back())) p.pop_back(); while (p.size() > 1 && on_right(lines[i], p[p.size() - 2])) p.pop_back(); p.push_back(get_line_intersection(lines[i], lines[(i + 1) % n])); } while (p.size() > 1 && on_right(lines[0], p.back())) p.pop_back(); while (p.size() > 1 && on_right(lines[0], p[p.size() - 2])) p.pop_back(); if (p.size() < 3) return res; for (int i = 0; i < p.size(); i++) { res.push_back(p[i]); } return res; } int main() { int n; cin >> n; vector<Line> lines; for (int i = 0; i < n; i++) { double x1, y1, x2, y2; cin >> x1 >> y1 >> x2 >> y2; Point a(x1, y1); Point b(x2, y2); lines.push_back(Line(a, b)); } vector<Point> res = HalfPlaneIntersection(lines); cout << res.size() << endl; return 0; } ``` 其中,`HalfPlaneIntersection` 函数接受一个线段集,返回围成的不同闭合区域的对应点集。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值