C++构造函数写法,以Cura的多边形类Polygons举例

C++构造函数写法,以Cura的类Polygons举例

Cura的类以clipper为基础设计,下面是Polygons的类的源码,可以充分学拷贝构造,重载=等的写法。

Polygon的定义

class Polygon : public PolygonRef
{
    ClipperLib::Path poly;
public:
    Polygon()
    : PolygonRef(poly)
    {
    }

    Polygon(const ConstPolygonRef& other)
    : PolygonRef(poly)
    , poly(*other.path)
    {
    }

    Polygon(const Polygon& other)
    : PolygonRef(poly)
    , poly(*other.path)
    {
    }

    Polygon(Polygon&& moved)
    : PolygonRef(poly)
    , poly(std::move(moved.poly))
    {
    }

    virtual ~Polygon()
    {
    }

    Polygon& operator=(const ConstPolygonRef& other) = delete; // copying a single polygon is generally not what you want
//     {
//         path = other.path;
//         poly = *other.path;
//         return *this;
//     }

    Polygon& operator=(Polygon&& other) //!< move assignment
    {
        poly = std::move(other.poly);
        return *this;
    }
};

Polygon的类,它继承自PolygonRef。这个类主要用于表示多边形,并提供了构造函数、拷贝构造函数、移动构造函数、析构函数以及赋值运算符重载等成员函数。

  1. 默认构造函数:创建一个空的多边形对象。
  2. 拷贝构造函数:根据传入的ConstPolygonRef对象创建一个新的多边形对象,复制其内部的poly成员变量。
  3. 移动构造函数:根据传入的Polygon对象创建一个新的多边形对象,将传入对象的poly成员变量移动到新对象中。
  4. 析构函数:释放多边形对象所占用的资源。
  5. 赋值运算符重载(删除):禁止使用赋值运算符来复制单个多边形对象,因为通常这样做不是预期的行为。
  6. 赋值运算符重载(移动):根据传入的Polygon对象,将其poly成员变量移动到当前对象中。

Polygons的定义

class Polygons
{
    friend class Polygon;
    friend class PolygonRef;
    friend class ConstPolygonRef;
protected:
    ClipperLib::Paths paths;
public:
    unsigned int size() const
    {
        return paths.size();
    }

    /*!
     * Convenience function to check if the polygon has no points.
     *
     * \return `true` if the polygon has no points, or `false` if it does.
     */
    bool empty() const;

    unsigned int pointCount() const; //!< Return the amount of points in all polygons

    PolygonRef operator[] (unsigned int index)
    {
        POLY_ASSERT(index < size() && index <= static_cast<unsigned int>(std::numeric_limits<int>::max()));
        return paths[index];
    }
    ConstPolygonRef operator[] (unsigned int index) const
    {
        POLY_ASSERT(index < size() && index <= static_cast<unsigned int>(std::numeric_limits<int>::max()));
        return paths[index];
    }
    ClipperLib::Paths::iterator begin()
    {
        return paths.begin();
    }
    ClipperLib::Paths::const_iterator begin() const
    {
        return paths.begin();
    }
    ClipperLib::Paths::iterator end()
    {
        return paths.end();
    }
    ClipperLib::Paths::const_iterator end() const
    {
        return paths.end();
    }
    /*!
     * Remove a polygon from the list and move the last polygon to its place
     * 
     * \warning changes the order of the polygons!
     */
    void remove(unsigned int index)
    {
        POLY_ASSERT(index < size() && index <= static_cast<unsigned int>(std::numeric_limits<int>::max()));
        if (index < paths.size() - 1)
        {
            paths[index] = std::move(paths.back());
        }
        paths.resize(paths.size() - 1);
    }
    /*!
     * Remove a range of polygons
     */
    void erase(ClipperLib::Paths::iterator start, ClipperLib::Paths::iterator end)
    {
        paths.erase(start, end);
    }
    void clear()
    {
        paths.clear();
    }
    void add(ConstPolygonRef& poly)
    {
        paths.push_back(*poly.path);
    }
    void add(const ConstPolygonRef& poly)
    {
        paths.push_back(*poly.path);
    }
    void add(Polygon&& other_poly)
    {
        paths.emplace_back(std::move(*other_poly));
    }
    void add(const Polygons& other)
    {
        std::copy(other.paths.begin(), other.paths.end(), std::back_inserter(paths));
    }
    /*!
     * Add a 'polygon' consisting of two points
     */
    void addLine(const Point from, const Point to)
    {
        paths.emplace_back(ClipperLib::Path{from, to});
    }

    template<typename... Args>
    void emplace_back(Args... args)
    {
        paths.emplace_back(args...);
    }

    PolygonRef newPoly()
    {
        paths.emplace_back();
        return PolygonRef(paths.back());
    }
    PolygonRef back()
    {
        return PolygonRef(paths.back());
    }
    ConstPolygonRef back() const
    {
        return ConstPolygonRef(paths.back());
    }

    Polygons() {}

    Polygons(const Polygons& other) { paths = other.paths; }
    Polygons(Polygons&& other) { paths = std::move(other.paths); }
    Polygons& operator=(const Polygons& other) { paths = other.paths; return *this; }
    Polygons& operator=(Polygons&& other) { paths = std::move(other.paths); return *this; }

    bool operator==(const Polygons& other) const =delete;
    ...

Polygons的类,它用于表示很多多边形的集合。该类具有以下成员函数和成员变量:

  • friend class Polygon;:声明了Polygon类为友元类,允许Polygon类访问Polygons类的私有成员。
  • friend class PolygonRef;:声明了PolygonRef类为友元类,允许PolygonRef类访问Polygons类的私有成员。
  • friend class ConstPolygonRef;:声明了ConstPolygonRef类为友元类,允许ConstPolygonRef类访问Polygons类的私有成员。
  • protected: ClipperLib::Paths paths;:定义了一个受保护的成员变量paths,类型为ClipperLib::Paths,用于存储多边形的路径信息。
  • public: unsigned int size() const:返回多边形集合的大小。
  • bool empty() const;:检查多边形集合是否为空,如果为空则返回true,否则返回false
  • unsigned int pointCount() const;:返回所有多边形中的点的数量。
  • PolygonRef operator[] (unsigned int index):重载下标运算符,返回指定索引处的多边形引用。
  • ConstPolygonRef operator[] (unsigned int index) const:重载常量下标运算符,返回指定索引处的常量多边形引用。
  • ClipperLib::Paths::iterator begin():返回多边形集合的起始迭代器。
  • ClipperLib::Paths::const_iterator begin() const:返回常量多边形集合的起始迭代器。
  • ClipperLib::Paths::iterator end():返回多边形集合的结束迭代器。
  • ClipperLib::Paths::const_iterator end() const:返回常量多边形集合的结束迭代器。
  • void remove(unsigned int index):从列表中移除一个多边形,并将最后一个多边形移动到其位置。
  • void erase(ClipperLib::Paths::iterator start, ClipperLib::Paths::iterator end):移除指定范围内的多边形。
  • void clear():清空多边形集合。
  • void add(ConstPolygonRef& poly):添加一个多边形引用到集合中。
  • void add(const ConstPolygonRef& poly):添加一个常量多边形引用到集合中。
  • void add(Polygon&& other_poly):添加一个右值引用的多边形到集合中。
  • void add(const Polygons& other):将另一个多边形集合添加到当前集合中。
  • void addLine(const Point from, const Point to):添加一条由两个点组成的线段作为多边形。
  • template<typename... Args> void emplace_back(Args... args):在集合末尾添加一个新的多边形。
  • PolygonRef newPoly():创建一个新的多边形并返回其引用。
  • PolygonRef back():返回最后一个多边形的引用。
  • ConstPolygonRef back() const:返回最后一个常量多边形的引用。
  • Polygons() {}:默认构造函数。
  • Polygons(const Polygons& other) { paths = other.paths; }:拷贝构造函数,复制另一个多边形集合的路径信息。
  • Polygons(Polygons&& other) { paths = std::move(other.paths); }:移动构造函数,将另一个多边形集合的路径信息移动到当前对象。
  • Polygons& operator=(const Polygons& other) { paths = other.paths; return *this; }:赋值运算符重载,将另一个多边形集合的路径信息赋值给当前对象。
  • Polygons& operator=(Polygons&& other) { paths = std::move(other.paths); return *this; }:移动赋值运算符重载,将另一个多边形集合的路径信息移动赋值给当前对象。
  • bool operator==(const Polygons& other) const =delete;:删除等于运算符重载,禁止使用等号比较两个多边形集合。

总结

  • 19
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
上述代码的逻辑存在问题。 首先,当 `distance < 0` 时,不能简单地认为顶点在多边形外部,而应该根据具体的情况来判断。如果顶点在多边形内部,`distance` 的值是正的,如果顶点在多边形边界上,`distance` 的值是 0,如果顶点在多边形外部,`distance` 的值是负的。 其次,在计算两个多边形的交集时,需要保证两个多边形都是凸多边形 。如果两个多边形中有一个不是凸多边形,则无法使用 `cv::intersectConvexConvex()` 函数计算交集。 最后,在计算多边形面积时,需要保证多边形的顶点按照顺序排列,否则计算结果可能不正确。 下面是一份修改后的代码,供参考: ```cpp bool isPolygonInside(const std::vector<cv::Point>& polygon1, const std::vector<cv::Point>& polygon2, double& outsideArea) { // Check if all vertices of polygon1 are inside polygon2 for (const auto& vertex : polygon1) { double distance = cv::pointPolygonTest(polygon2, vertex, true); if (distance < 0) { // Vertex is outside polygon2 // Calculate area of polygon1 outside polygon2 cv::Mat polygon1Mat = cv::Mat(polygon1).reshape(1); cv::Mat polygon2Mat = cv::Mat(polygon2).reshape(1); std::vector<cv::Point2f> intersectionPolygon; if (cv::isContourConvex(polygon1) && cv::isContourConvex(polygon2)) { cv::Mat intersectionMat; cv::intersectConvexConvex(polygon1Mat, polygon2Mat, intersectionMat); if (cv::countNonZero(intersectionMat) > 0) { intersectionMat.reshape(2).copyTo(intersectionPolygon); } } else { cv::Rect rect1 = cv::boundingRect(polygon1Mat); cv::Rect rect2 = cv::boundingRect(polygon2Mat); cv::Rect intersectionRect = rect1 & rect2; if (!intersectionRect.empty()) { cv::Mat intersectionMat = cv::Mat::zeros(intersectionRect.size(), CV_8UC1); cv::fillConvexPoly(intersectionMat, polygon1 - rect1.tl(), cv::Scalar(255)); cv::fillConvexPoly(intersectionMat, polygon2 - rect2.tl(), cv::Scalar(0), cv::LINE_AA); std::vector<std::vector<cv::Point>> contours; cv::findContours(intersectionMat, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); if (!contours.empty()) { intersectionPolygon = contours[0]; } } } double intersectionArea = std::abs(cv::contourArea(intersectionPolygon)); double polygon1Area = std::abs(cv::contourArea(polygon1)); outsideArea = polygon1Area - intersectionArea; return false; } } // All vertices of polygon1 are inside polygon2 return true; } ``` 这份代码对于两个多边形进行了一些限制,只有当两个多边形都为凸多边形时,才会使用 `cv::intersectConvexConvex()` 函数计算交集。对于非凸多边形,使用包围盒和填充算法来计算交集。同时,对于计算多边形面积时,先将多边形按照顺序排列,再使用 `cv::contourArea()` 函数计算面积,以保证计算结果正确。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值