基本几何对象(6)——Triangle

定义Triangle类,用于多边形的三角耳切。

下面给出Triangle的声明。

class Triangle : public Geometry
{
    private:
        Point _vecs[3] = {Point()};
    
    public:
        Triangle() {};

        Triangle(const Point &point0, const Point &point1, const Point &point2);

        Triangle(const double x0, const double y0, const double x1, const double y1, const double x2, const double y2);

        Triangle(const Triangle &triangle);

        const Type type() const override;

        const bool empty() const override;

        const double length() const override;

        void clear() override;

        Triangle *clone() const override;

        double area() const;

        // 顶角度数(弧度制)
        double angle(const size_t index) const;

        void reorder_points(const bool cw = true);

        // 判断点顺序是否为顺时针
        bool is_cw() const;

        Point &operator[](const size_t index);

        const Point &operator[](const size_t index) const;

        Triangle &operator=(const Triangle &triangle);

        Triangle operator+(const Point &point) const;

        Triangle operator-(const Point &point) const;

        void operator+=(const Point &point);

        void operator-=(const Point &point);

        void transform(const double a, const double b, const double c, const double d, const double e, const double f) override;

        void transform(const double mat[6]) override;

        void translate(const double tx, const double ty) override;

        void rotate(const double x, const double y, const double rad) override; // 弧度制

        void scale(const double x, const double y, const double k) override;

        Polygon convex_hull() const override;

        AABBRect bounding_rect() const override;

        Polygon mini_bounding_rect() const override;

        // 内接圆圆心
        Point inner_circle_center() const;

        // 内接圆半径
        double inner_circle_radius() const;
};

下面给出Triangle的实现。

Triangle::Triangle(const Point &point0, const Point &point1, const Point &point2)
{
    _vecs[0] = point0;
    _vecs[1] = point1;
    _vecs[2] = point2;
}

Triangle::Triangle(const double x0, const double y0, const double x1, const double y1, const double x2, const double y2)
{
    _vecs[0].x = x0;
    _vecs[0].y = y0;
    _vecs[1].x = x1;
    _vecs[1].y = y1;
    _vecs[2].x = x2;
    _vecs[2].y = y2;
}

Triangle::Triangle(const Triangle &triangle)
{
    _vecs[0] = triangle._vecs[0];
    _vecs[1] = triangle._vecs[1];
    _vecs[2] = triangle._vecs[2];
}

const Type Triangle::type() const
{
    return Type::TRIANGLE;
}

const bool Triangle::empty() const
{
    return _vecs[0] == _vecs[1] || _vecs[1] == _vecs[2] || _vecs[0] == _vecs[2];
}

const double Triangle::length() const
{
    return Geo::distance(_vecs[0], _vecs[1]) + Geo::distance(_vecs[1], _vecs[2]) + Geo::distance(_vecs[0], _vecs[2]);
}

void Triangle::clear()
{
    for (size_t i = 0; i < 3; ++i)
    {
        _vecs[i].clear();
    }
}

Triangle *Triangle::clone() const
{
    return new Triangle(*this);
}

double Triangle::area() const
{
    if (empty())
    {
        return 0;
    }
    const double a = Geo::distance(_vecs[0], _vecs[1]);
    const double b = Geo::distance(_vecs[1], _vecs[2]);
    const double c = Geo::distance(_vecs[0], _vecs[2]);
    const double p = (a + b + c) / 2;
    return std::sqrt(p * (p - a) * (p - b) * (p- c));
}

double Triangle::angle(const size_t index) const
{
    assert(0 <= index && index <= 2);
    if (empty())
    {
        return 0;
    }

    const double len0 = Geo::distance(_vecs[1], _vecs[2]);
    const double len1 = Geo::distance(_vecs[0], _vecs[2]);
    const double len2 = Geo::distance(_vecs[0], _vecs[1]);

    switch (index)
    {
    case 0:
        return std::acos((len1 * len1 + len2 * len2 - len0 * len0) / (2 * len1 * len2));
    case 1:
        return std::acos((len0 * len0 + len2 * len2 - len1 * len1) / (2 * len0 * len2));
    case 2:
        return std::acos((len0 * len0 + len1 * len1 - len2 * len2) / (2 * len0 * len1));
    default:
        return 0; 
    }
}

void Triangle::reorder_points(const bool cw)
{
    if (cw)
    {
        if (!is_cw())
        {
            std::swap(_vecs[1], _vecs[2]);
        }
    }
    else
    {
        if (is_cw())
        {
            std::swap(_vecs[1], _vecs[2]);
        }
    }
}

bool Triangle::is_cw() const
{
    return Geo::is_on_left(_vecs[2], _vecs[1], _vecs[0]);
}

Point &Triangle::operator[](const size_t index)
{
    assert(0 <= index && index <= 2);
    return _vecs[index];
}

const Point &Triangle::operator[](const size_t index) const
{
    assert(0 <= index && index <= 2);
    return _vecs[index];
}

Triangle &Triangle::operator=(const Triangle &triangle)
{
    if (this != &triangle)
    {
        _vecs[0] = triangle._vecs[0];
        _vecs[1] = triangle._vecs[1];
        _vecs[2] = triangle._vecs[2];
    }
    return *this;
}

Triangle Triangle::operator+(const Point &point) const
{
    Triangle triangle(*this);
    triangle._vecs[0] += point;
    triangle._vecs[1] += point;
    triangle._vecs[2] += point;
    return triangle;
}

Triangle Triangle::operator-(const Point &point) const
{
    Triangle triangle(*this);
    triangle._vecs[0] -= point;
    triangle._vecs[1] -= point;
    triangle._vecs[2] -= point;
    return triangle;
}

void Triangle::operator+=(const Point &point)
{
    _vecs[0] += point;
    _vecs[1] += point;
    _vecs[2] += point;
}

void Triangle::operator-=(const Point &point)
{
    _vecs[0] -= point;
    _vecs[1] -= point;
    _vecs[2] -= point;
}

void Triangle::transform(const double a, const double b, const double c, const double d, const double e, const double f)
{
    _vecs[0].transform(a, b, c, d, e, f);
    _vecs[1].transform(a, b, c, d, e, f);
    _vecs[2].transform(a, b, c, d, e, f);
}

void Triangle::transform(const double mat[6])
{
    _vecs[0].transform(mat);
    _vecs[1].transform(mat);
    _vecs[2].transform(mat);
}

void Triangle::translate(const double tx, const double ty)
{
    _vecs[0].translate(tx, ty);
    _vecs[1].translate(tx, ty);
    _vecs[2].translate(tx, ty);
}

void Triangle::rotate(const double x, const double y, const double rad) // 弧度制
{
    _vecs[0].rotate(x, y, rad);
    _vecs[1].rotate(x, y, rad);
    _vecs[2].rotate(x, y, rad);
}

void Triangle::scale(const double x, const double y, const double k)
{
    _vecs[0].scale(x, y, k);
    _vecs[1].scale(x, y, k);
    _vecs[2].scale(x, y, k);
}

Polygon Triangle::convex_hull() const
{
    if (empty())
    {
        return Polygon();
    }
    else
    {
        return Polygon({_vecs[0], _vecs[1], _vecs[2], _vecs[0]});
    }
}

AABBRect Triangle::bounding_rect() const
{
    if (empty())
    {
        return AABBRect();
    }

    const double left = std::min(_vecs[0].x, std::min(_vecs[1].x, _vecs[2].x));
    const double right = std::max(_vecs[0].x, std::max(_vecs[1].x, _vecs[2].x));
    const double top = std::max(_vecs[0].y, std::max(_vecs[1].y, _vecs[2].y));
    const double bottom = std::min(_vecs[0].y, std::min(_vecs[1].y, _vecs[2].y));
    return AABBRect(left, top, right, bottom);
}

Polygon Triangle::mini_bounding_rect() const
{
    if (empty())
    {
        return Polygon();
    }

    double cs, area = DBL_MAX;
    AABBRect rect, temp;
    for (size_t i = 0; i < 3; ++i)
    {
        Triangle triangle(*this);
        cs = (triangle[i].x * triangle[i < 2 ? i + 1 : 0].y - triangle[i < 2 ? i + 1 : 0].x * triangle[i].y)
            / (triangle[i < 2 ? i + 1 : 0].length() * triangle[i].length());
        triangle.rotate(triangle[i].x, triangle[i].y, std::acos(cs));
        temp = triangle.bounding_rect();
        if (temp.area() < area)
        {
            rect = temp;
            area = temp.area();
            rect.rotate(triangle[i].x, triangle[i].y, -std::acos(cs));
        }
    }
    return rect;
}

Point Triangle::inner_circle_center() const
{
    const double a = Geo::distance(_vecs[1], _vecs[2]);
    const double b = Geo::distance(_vecs[0], _vecs[2]);
    const double c = Geo::distance(_vecs[0], _vecs[1]);
    return (_vecs[0] * a + _vecs[1] * b + _vecs[2] * c) / (a + b + c);
}

double Triangle::inner_circle_radius() const
{
    const double a = Geo::distance(_vecs[1], _vecs[2]);
    const double b = Geo::distance(_vecs[0], _vecs[2]);
    const double c = Geo::distance(_vecs[0], _vecs[1]);
    const double p = (a + b + c) / 2;
    return std::sqrt((p - a) * (p - b) * (p - c) / p);
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值