You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

如何修改CGAL定义的Cartesian Point_2坐标以限制精度?

解决CGAL Point_2派生类无法修改坐标的问题

问题背景

你通过继承CGAL的Point_2实现了业务类TPoint,需要将坐标精度限制到毫米级,但发现基类的base成员是私有,无法直接修改坐标值。

可行解决方案

1. 优先采用组合而非继承(推荐)

CGAL的几何类设计为值类型,更适合用组合方式封装,而非继承。将CGALPoint作为TPoint的私有成员,通过创建新的CGALPoint来更新坐标:

typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef K::Point_2 CGALPoint;

double RoundPrecision(double number, int precision) {
  double decimals = std::pow(10, precision);
  return (std::round(number * decimals)) / decimals;
}

class TPoint {
private:
    CGALPoint m_point;

public:
    // 支持多种构造方式
    TPoint() = default;
    TPoint(double x, double y) : m_point(x, y) {}
    TPoint(const CGALPoint& p) : m_point(p) {}

    // 暴露坐标读取接口
    double x() const { return m_point.x(); }
    double y() const { return m_point.y(); }

    void RoundTo(int precision) {
        if (precision >= 0) {
            double lX = RoundPrecision(x(), precision);
            double lY = RoundPrecision(y(), precision);
            // 直接创建新的CGAL点替换内部成员
            m_point = CGALPoint(lX, lY);
        }
    }

    // 提供访问内部CGAL点的方法,兼容CGAL其他算法
    const CGALPoint& get_cgal_point() const { return m_point; }
};

2. 若必须继承:通过赋值替换当前对象

如果因为业务限制必须继承CGALPoint,可以利用Point_2的赋值运算符,创建四舍五入后的新点并赋值给当前对象:

typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef K::Point_2 CGALPoint;

double RoundPrecision(double number, int precision) {
  double decimals = std::pow(10, precision);
  return (std::round(number * decimals)) / decimals;
}

class TPoint : public CGALPoint {
public:
    // 继承基类所有构造函数
    using CGALPoint::CGALPoint;

    void RoundTo(int precision) {
        if (precision >= 0) {
            double lX = RoundPrecision(x(), precision);
            double lY = RoundPrecision(y(), precision);
            // 用新点覆盖当前对象
            *this = CGALPoint(lX, lY);
        }
    }
};

这个方法绕开了私有成员的限制,本质是用新的Point_2实例替换当前对象的内容,符合CGAL值类型的设计逻辑。

3. 不推荐的方案:强制访问私有成员

不要尝试用reinterpret_cast直接访问基类的base成员,也不要修改CGAL源码添加友元——这些操作会破坏封装,依赖CGAL的内部实现细节,版本更新后必然失效,风险极高。

为什么不推荐继承CGAL几何类?

CGAL的核心几何类(如Point_2)设计为不可变值类型,没有提供修改坐标的接口,目的是保证几何计算的一致性和线程安全。继承这类值类型容易引发对象切片、行为不一致等问题,组合是更安全、更符合设计意图的选择。

内容的提问来源于stack exchange,提问作者huckfinn

火山引擎 最新活动