表格线识别通用库文档
载入中...
搜索中...
未找到
rect.hpp
浏览该文件的文档.
1/*
2 * @Descrirection: 矩形类 头文件及其实现
3 * @Version:
4 * @Autor: dreamy-xay
5 * @Date: 2023-12-01 15:02:12
6 * @LastEditors: LL
7 * @LastEditTime: 2024-05-20
8 */
9
10#ifndef COMMON_RECT_HPP
11#define COMMON_RECT_HPP
12
13#include <iostream>
14#include <opencv2/core.hpp>
15#include <vector>
16
17#include "common/base/line.hpp"
18#include "common/base/point.hpp"
19#include "common/enum.h"
20#include "common/macro.h"
21#include "common/type.h"
22
23namespace cm {
24
31class Rect {
32 public:
34 int x;
36 int y;
38 int width;
40 int height;
41
59 struct Hash {
60 size_t operator()(const Rect& rect) const;
61 };
62
72 struct Margin {
74 int top;
76 int right;
78 int bottom;
80 int left;
81
82 explicit Margin(int top, int right, int bottom, int left);
83 explicit Margin(int top, int left_and_right, int bottom);
84 explicit Margin(int top_and_bottom, int left_and_right);
85 Margin(int margin);
86 };
87
88 Rect();
89 Rect(int x, int y, int width, int height);
90 Rect(Point2i pt1, Point2i pt2);
91 Rect(const Rect& rect);
92 Rect(const cv::Vec4i& rect);
93 Rect(const cv::Rect& rect);
94 Rect(const std::vector<int>& list);
95 ~Rect();
96 operator cv::Rect() const;
97 operator cv::Vec4i() const;
98 operator std::vector<int>() const;
99
100 friend bool operator==(const Rect& rect1, const Rect& rect2);
101 friend bool operator!=(const Rect& rect1, const Rect& rect2);
102 friend bool operator<(const Rect& rect1, const Rect& rect2);
103 friend bool operator>(const Rect& rect1, const Rect& rect2);
104 friend bool operator<=(const Rect& rect1, const Rect& rect2);
105 friend bool operator>=(const Rect& rect1, const Rect& rect2);
106
107 friend std::ostream& operator<<(std::ostream& out, const Rect& rect);
108
109 bool IsPoint() const;
110
111 template <typename U>
112 bool Include(const Point<U>& pt, const Margin& margin = 0, bool is_include_boundaries = true) const;
113
114 bool Include(const Line& line, const Margin& margin = 0, bool is_include_boundaries = true) const;
115 bool Include(const Rect& rect, const Margin& margin = 0, bool is_include_boundaries = true) const;
116 bool IsIntersect(const Rect& rect, IntersectType type = INTERSECT_XY, const Margin& margin = 0, bool is_include_boundaries = false) const;
117 bool IsIntersect(const Line& line, IntersectType type = INTERSECT_XY, const Margin& margin = 0, bool is_include_boundaries = true) const;
118
119 Rect Intersect(const Rect& rect) const;
120 Line Intersect(const Line& line) const;
121 Rect Union(const Rect& rect) const;
122 Point2i DiagonalPoint(bool is_left_top = false) const;
123 Point2d CenterPoint() const;
124 Rect& Translate(int dx, int dy);
125 Rect& Scale(double factor);
126 Rect& Scale(const Margin& margin);
127 Rect& TidyRect();
128};
129
140inline size_t Rect::Hash::operator()(const Rect& rect) const {
141 return std::hash<int>()(rect.x) ^ std::hash<int>()(rect.y) ^ std::hash<int>()(rect.width) ^ std::hash<int>()(rect.height);
142}
143
156inline Rect::Margin::Margin(int top, int right, int bottom, int left) : top(top), right(right), bottom(bottom), left(left) {}
157
169inline Rect::Margin::Margin(int top, int left_and_right, int bottom) : top(top), right(left_and_right), bottom(bottom), left(left_and_right) {}
170
182
192inline Rect::Margin::Margin(int margin) : top(margin), right(margin), bottom(margin), left(margin) {}
193
201inline Rect::Rect() : x{}, y{}, width{}, height{} {}
202
215inline Rect::Rect(int x, int y, int width, int height) : x(x), y(y), width(width), height(height) {
216 this->TidyRect();
217}
218
229inline Rect::Rect(Point2i pt1, Point2i pt2) : x(pt1.x), y(pt1.y), width(pt2.x - pt1.x), height(pt2.y - pt1.y) {
230 this->TidyRect();
231}
232
242inline Rect::Rect(const Rect& rect) : x(rect.x), y(rect.y), width(rect.width), height(rect.height) {}
243
253inline Rect::Rect(const cv::Rect& rect) : x(rect.x), y(rect.y), width(rect.width), height(rect.height) {
254 this->TidyRect();
255}
256
266inline Rect::Rect(const cv::Vec4i& rect) : x(rect[0]), y(rect[1]), width(rect[2]), height(rect[3]) {
267 this->TidyRect();
268}
269
279inline Rect::Rect(const std::vector<int>& list) {
280 Cm_Assert(list.size() == 4, "list size must be 4!!!");
281
282 x = list[0];
283 y = list[1];
284 width = list[2];
285 height = list[3];
286
287 this->TidyRect();
288}
289
297inline Rect::~Rect() {}
298
308inline Rect::operator cv::Rect() const {
309 return cv::Rect(x, y, width, height);
310}
311
321inline Rect::operator cv::Vec4i() const {
322 return {x, y, width, height};
323}
324
334inline Rect::operator std::vector<int>() const {
335 return {x, y, width, height};
336}
337
352inline bool operator==(const Rect& rect1, const Rect& rect2) {
353 return rect1.x == rect2.x && rect1.y == rect2.y && rect1.width == rect2.width && rect1.height == rect2.height;
354}
355
370inline bool operator!=(const Rect& rect1, const Rect& rect2) {
371 return rect1.x != rect2.x || rect1.y != rect2.y || rect1.width != rect2.width || rect1.height != rect2.height;
372}
373
390inline bool operator<(const Rect& rect1, const Rect& rect2) {
391 if (rect1.x == rect2.x) { // 如果x相同,比较y
392 if (rect1.y == rect2.y) { // 如果y相同,比较宽
393 if (rect1.width == rect2.width) // 如果宽相同,比较高
394 return rect1.height < rect2.height;
395 return rect1.width < rect2.width;
396 }
397 return rect1.y < rect2.y;
398 }
399 return rect1.x < rect2.x;
400}
401
418inline bool operator>(const Rect& rect1, const Rect& rect2) {
419 if (rect1.x == rect2.x) { // 如果x相同,比较y
420 if (rect1.y == rect2.y) { // 如果y相同,比较宽
421 if (rect1.width == rect2.width) // 如果宽相同,比较高
422 return rect1.height > rect2.height;
423 return rect1.width > rect2.width;
424 }
425 return rect1.y > rect2.y;
426 }
427 return rect1.x > rect2.x;
428}
429
446inline bool operator<=(const Rect& rect1, const Rect& rect2) {
447 if (rect1.x == rect2.x) { // 如果x相同,比较y
448 if (rect1.y == rect2.y) { // 如果y相同,比较宽
449 if (rect1.width == rect2.width) // 如果宽相同,比较高
450 return rect1.height <= rect2.height;
451 return rect1.width <= rect2.width;
452 }
453 return rect1.y <= rect2.y;
454 }
455 return rect1.x <= rect2.x;
456}
457
474inline bool operator>=(const Rect& rect1, const Rect& rect2) {
475 if (rect1.x == rect2.x) { // 如果x相同,比较y
476 if (rect1.y == rect2.y) { // 如果y相同,比较宽
477 if (rect1.width == rect2.width) // 如果宽相同,比较高
478 return rect1.height >= rect2.height;
479 return rect1.width >= rect2.width;
480 }
481 return rect1.y >= rect2.y;
482 }
483 return rect1.x >= rect2.x;
484}
485
498inline std::ostream& operator<<(std::ostream& out, const Rect& rect) {
499 out << "{ x: " << rect.x << ", y: " << rect.y << ", width: " << rect.width << ", height: " << rect.height << " }";
500 return out;
501}
502
514inline bool Rect::IsPoint() const {
515 return width == 0 && height == 0;
516}
517
536template <typename U>
537inline bool Rect::Include(const Point<U>& pt, const Margin& margin, bool is_include_boundaries) const {
539 return pt.x >= (x - margin.left) && pt.x <= (x + width + margin.right) && pt.y >= (y - margin.top) && pt.y <= (y + height + margin.bottom);
540 else
541 return pt.x > (x - margin.left) && pt.x < (x + width + margin.right) && pt.y > (y - margin.top) && pt.y < (y + height + margin.bottom);
542}
543
559inline bool Rect::Include(const Line& line, const Margin& margin, bool is_include_boundaries) const {
560 return this->Include(line.pt1, margin, is_include_boundaries) && this->Include(line.pt2, margin, is_include_boundaries);
561}
562
578inline bool Rect::Include(const Rect& rect, const Margin& margin, bool is_include_boundaries) const {
579 return this->Include(Point2i(rect.x, rect.y), margin, is_include_boundaries) && this->Include(Point2i(rect.x + rect.width, rect.y), margin, is_include_boundaries) && this->Include(Point2i(rect.x, rect.y + rect.height), margin, is_include_boundaries) && this->Include(Point2i(rect.x + rect.width, rect.y + rect.height), margin, is_include_boundaries);
580}
581
598inline bool Rect::IsIntersect(const Rect& rect, IntersectType type, const Margin& margin, bool is_include_boundaries) const {
599 switch (type) {
600 case INTERSECT_X: // 水平方向上相交
601 return Line(x - margin.left, y, x + width + margin.right, y).IsIntersect(Line(rect.x, rect.y, rect.x + rect.width, rect.y), INTERSECT_X, is_include_boundaries);
602 case INTERSECT_Y: // 垂直方向上相交
603 return Line(x, y - margin.top, x, y + height + margin.bottom).IsIntersect(Line(rect.x, rect.y, rect.x, rect.y + rect.height), INTERSECT_Y, is_include_boundaries);
604 case INTERSECT_XY: // 两个方向上都相交
605 return Line(x - margin.left, y, x + width + margin.right, y).IsIntersect(Line(rect.x, rect.y, rect.x + rect.width, rect.y), INTERSECT_X, is_include_boundaries) && Line(x, y - margin.top, x, y + height + margin.bottom).IsIntersect(Line(rect.x, rect.y, rect.x, rect.y + rect.height), INTERSECT_Y, is_include_boundaries);
606 default:
607 throw Exception("The type(IntersectType) of param \"type\" is incorrect!");
608 }
609}
610
627inline bool Rect::IsIntersect(const Line& line, IntersectType type, const Margin& margin, bool is_include_boundaries) const {
628 switch (type) {
629 case INTERSECT_X: // 水平方向上相交
630 return Line(x - margin.left, y, x + width + margin.right, y).IsIntersect(line, INTERSECT_X, is_include_boundaries);
631 case INTERSECT_Y: // 垂直方向上相交
633 case INTERSECT_XY: { // 线段至少有个点在矩形内,或者线段与矩阵四条边中一条边相交
634 auto diagonal_pt = std::move(this->DiagonalPoint()); // 右下方的对角点
635 return this->Include(line.pt1, margin, is_include_boundaries) ||
636 this->Include(line.pt2, margin, is_include_boundaries) ||
641 }
642 default:
643 throw Exception("The type(IntersectType) of param \"type\" is incorrect!");
644 }
645}
646
658inline Rect Rect::Intersect(const Rect& rect) const {
659 int max_top_x = std::max(x, rect.x); // 两个矩形中上边界最大值
660 int max_left_y = std::max(y, rect.y); // 两个矩形中左边界最大值
661 int min_bottom_x = std::min(x + width, rect.x + rect.width); // 两个矩形中下边界最小值
662 int min_right_y = std::min(y + height, rect.y + rect.height); // 两个矩形中有边界最大值
663
665}
666
682inline Line Rect::Intersect(const Line& line) const {
683 Cm_Assert(this->IsIntersect(line), "the line do not intersect with rectangle!");
684
685 bool is_pt1_in_rect = this->Include(line.pt1, 0, true);
686 bool is_pt2_in_rect = this->Include(line.pt2, 0, true);
687
689 return line;
690 else {
691 if (is_pt1_in_rect && !this->Include(line.pt1, 0, false)) {
692 if (line.pt2.x == line.pt1.x)
693 return {line.pt1, {line.pt2.x, line.pt2.y > y ? y + height : y}};
694 else if (line.pt2.y == line.pt1.y)
695 return {line.pt1, {line.pt2.x > x ? x + width : x, line.pt2.y}};
696 } else if (is_pt2_in_rect && !this->Include(line.pt2, 0, false)) {
697 if (line.pt1.x == line.pt2.x)
698 return {line.pt2, {line.pt1.x, line.pt1.y > y ? y + height : y}};
699 else if (line.pt1.y == line.pt2.y)
700 return {line.pt2, {line.pt1.x > x ? x + width : x, line.pt1.y}};
701 }
702
703 Point2i diagonal_pt = std::move(this->DiagonalPoint()); // 右下方的对角点
704
705 std::vector<Line> lines;
706 lines.emplace_back(x, y, diagonal_pt.x, y); // 上边界线
707 lines.emplace_back(x, y, x, diagonal_pt.y); // 左边界线
708 lines.emplace_back(x, diagonal_pt.y, diagonal_pt.x, diagonal_pt.y); // 下边界线
709 lines.emplace_back(diagonal_pt.x, y, diagonal_pt.x, diagonal_pt.y); // 右边界线
710
711 auto CalcIntersection = [](const std::vector<Line>& lines, const Line& line) -> std::pair<Point2d, int> {
712 int num_lines = lines.size();
713 for (int i = 0; i < num_lines; ++i)
714 if (line.IsIntersect(lines[i]))
715 return {line.Intersect(lines[i]), i};
716 return {{0, 0}, -1};
717 };
718
720 auto& intersection = is_pt1_in_rect ? line.pt1 : line.pt2;
722
723 if (intersection_info.second == -1)
724 return {intersection, intersection};
725
726 return {CalcIntersection(lines, line).first, intersection};
727 } else {
729
730 lines.erase(lines.begin() + intersection1_info.second);
731
732 return {intersection1_info.first, CalcIntersection(lines, line).first};
733 }
734 }
735}
736
748inline Rect Rect::Union(const Rect& rect) const {
749 Point2i pt1 = this->DiagonalPoint();
750 Point2i pt2 = rect.DiagonalPoint();
751 int min_top = std::min(x, rect.x);
752 int min_left = std::min(y, rect.y);
753 int max_bottom = std::max(pt1.x, pt2.x);
754 int max_right = std::max(pt1.y, pt2.y);
756}
757
770 if (is_left_top)
771 return {x, y};
772 else
773 return {x + width, y + height};
774}
775
786 return {x + width / 2.0, y + height / 2.0};
787}
788
801inline Rect& Rect::Translate(int dx, int dy) {
802 x += dx; // 计算偏移之后的x
803 y += dy; // 计算偏移之后的y
804 return *this;
805}
806
818inline Rect& Rect::Scale(double factor) {
819 x *= factor; // 计算新的x
820 y *= factor; // 计算新的y
821 width *= factor; // 计算新宽
822 height *= factor; // 计算新高
823
824 return *this;
825}
826
838inline Rect& Rect::Scale(const Margin& margin) {
839 x -= margin.left; // 计算新的x
840 y -= margin.top; // 计算新的y
841 width += margin.left + margin.right; // 计算新宽
842 height += margin.top + margin.bottom; // 计算新高
843
844 return *this;
845}
846
857 if (width < 0) {
858 width = -width;
859 x -= width;
860 }
861 if (height < 0) {
862 height = -height;
863 y -= height;
864 }
865 return *this;
866}
867
868} // namespace cm
869
870#endif
通用异常类
Definition type.h:39
线类
Definition line.hpp:31
bool IsIntersect(const Line &line, IntersectType type=INTERSECT_XY, bool is_include_boundaries=false) const
判断两线是否相交
Definition line.hpp:1257
Point2i pt2
线的第二个点(默认:对于横线是右边的点,对于竖线是下面的点)
Definition line.hpp:203
Point2i pt1
线的第一个点(默认:对于横线是左边的点;对于竖线是上面的点)
Definition line.hpp:201
点类
Definition point.hpp:52
T y
点的 y 坐标
Definition point.hpp:57
T x
点的 x 坐标
Definition point.hpp:55
矩形类
Definition rect.hpp:31
friend bool operator>=(const Rect &rect1, const Rect &rect2)
矩形类重载大于等于号
Definition rect.hpp:474
int x
矩形的左上角 x 坐标(仅当矩形宽高为正数时)
Definition rect.hpp:34
friend bool operator==(const Rect &rect1, const Rect &rect2)
矩形类重载等于号
Definition rect.hpp:352
bool IsIntersect(const Rect &rect, IntersectType type=INTERSECT_XY, const Margin &margin=0, bool is_include_boundaries=false) const
判断所给矩形是否与矩形相交(不算边界)
Definition rect.hpp:598
Rect & Translate(int dx, int dy)
矩形平移
Definition rect.hpp:801
friend bool operator<(const Rect &rect1, const Rect &rect2)
矩形类重载小于号
Definition rect.hpp:390
Rect Intersect(const Rect &rect) const
计算两相交矩形所返回的新矩形(包含边界)
Definition rect.hpp:658
int width
矩形的宽度
Definition rect.hpp:38
int y
矩形的左上角 y 坐标(仅当矩形宽高为正数时)
Definition rect.hpp:36
Point2d CenterPoint() const
获取矩形的中心坐标
Definition rect.hpp:785
Rect Union(const Rect &rect) const
计算两个矩形的并集
Definition rect.hpp:748
Rect & TidyRect()
整理矩形
Definition rect.hpp:856
Point2i DiagonalPoint(bool is_left_top=false) const
获取矩形的对角点坐标
Definition rect.hpp:769
Rect & Scale(double factor)
矩形缩放
Definition rect.hpp:818
Rect()
矩形类的默认构造函数
Definition rect.hpp:201
bool IsPoint() const
判断矩形是否为一个点
Definition rect.hpp:514
~Rect()
矩形类默认析构函数
Definition rect.hpp:297
friend bool operator<=(const Rect &rect1, const Rect &rect2)
矩形类重载小于等于号
Definition rect.hpp:446
int height
矩形的高度
Definition rect.hpp:40
friend std::ostream & operator<<(std::ostream &out, const Rect &rect)
矩形类重载输出流运算符
Definition rect.hpp:498
friend bool operator>(const Rect &rect1, const Rect &rect2)
矩形类重载大于号
Definition rect.hpp:418
friend bool operator!=(const Rect &rect1, const Rect &rect2)
矩形类重载不等于号
Definition rect.hpp:370
bool Include(const Point< U > &pt, const Margin &margin=0, bool is_include_boundaries=true) const
判断所给点是否被矩形包含
Definition rect.hpp:537
#define Cm_Assert(expr, message)
断言宏
Definition macro.h:109
bool operator>=(const Interval &interval1, const Interval &interval2)
区间类重载大于等于号
Definition interval.hpp:310
bool operator!=(const Interval &interval1, const Interval &interval2)
区间类重载不等于号
Definition interval.hpp:232
Point< int > Point2i
整型坐标点类型
Definition point.hpp:111
bool operator<(const Interval &interval1, const Interval &interval2)
区间类重载小于号
Definition interval.hpp:250
IntersectType
相交类型枚举
Definition enum.h:56
@ INTERSECT_Y
y坐标上相交
Definition enum.h:60
@ INTERSECT_X
x坐标上相交
Definition enum.h:58
@ INTERSECT_XY
xy坐标上相交
Definition enum.h:62
bool operator==(const Interval &interval1, const Interval &interval2)
区间类重载等于号
Definition interval.hpp:214
bool operator<=(const Interval &interval1, const Interval &interval2)
区间类重载小于等于号
Definition interval.hpp:290
std::ostream & operator<<(std::ostream &out, const Interval &interval)
区间类重载输出流运算符
Definition interval.hpp:328
bool operator>(const Interval &interval1, const Interval &interval2)
区间类重载大于号
Definition interval.hpp:270
矩形的哈希仿函数
Definition rect.hpp:59
size_t operator()(const Rect &rect) const
矩形类的哈希仿函数
Definition rect.hpp:140
矩形外边距结构体
Definition rect.hpp:72
int bottom
下边距
Definition rect.hpp:78
int right
右边距
Definition rect.hpp:76
int left
左边距
Definition rect.hpp:80
int top
上边距
Definition rect.hpp:74
Margin(int top, int right, int bottom, int left)
矩形外边距结构体的带参构造函数
Definition rect.hpp:156