|
为了实现计算凸包的函数,我们需要确保 cross 函数和比较函数 cmp 都已经定义好。这里我们使用 AcGePoint2d 类型,它是 AutoCAD ObjectARX 库中的一个点类,包含 x 和 y 坐标。
首先,我们需要定义 cross 函数来计算两个向量的叉积。然后,我们需要一个比较函数 cmp 来按照字典序对点进行排序(即先按 x 坐标升序排列,如果 x 相同,则按 y 坐标升序排列)。
- #include <vector>
- #include <algorithm>
- #include <acge.h> // 包含 AcGePoint2d 的头文件
- // 比较函数,用于按字典序排序
- bool cmp(const AcGePoint2d& p1, const AcGePoint2d& p2) {
- return (p1.x() < p2.x()) || (p1.x() == p2.x() && p1.y() < p2.y());
- }
- // 计算两个向量的叉积
- double cross(const AcGePoint2d& O, const AcGePoint2d& A, const AcGePoint2d& B) {
- return (A.x() - O.x()) * (B.y() - O.y()) - (A.y() - O.y()) * (B.x() - O.x());
- }
- // 计算凸包
- std::vector<AcGePoint2d> convexhull(const std::vector<AcGePoint2d>& points) {
- std::vector<AcGePoint2d> result;
-
- if (points.size() < 3)
- return result;
-
- std::vector<AcGePoint2d> tmp_points = points;
- // 首先将所有点按照字典序排序
- std::sort(tmp_points.begin(), tmp_points.end(), cmp);
-
- // 上凸包
- for (const auto& point : tmp_points) {
- while (result.size() > 1 && cross(result[result.size()-2], result.back(), point) <= 0) {
- result.pop_back();
- }
- result.push_back(point);
- }
-
- // 下凸包
- int t = result.size() + 1; // 注意这里的+1是为了区分上下凸包
- for (int i = tmp_points.size() - 2; i >= 0; --i) {
- while (result.size() > t && cross(result[result.size()-2], result.back(), tmp_points[i]) <= 0) {
- result.pop_back();
- }
- result.push_back(tmp_points[i]);
- }
-
- // 删除最后一个重复点
- result.pop_back();
-
- return result;
- }
复制代码 |
|