10#ifndef COMMON_LINE_HPP
11#define COMMON_LINE_HPP
14#include <opencv2/core.hpp>
68 double GetX(
double y)
const;
69 double GetY(
double x)
const;
111 double GetX(
double y)
const;
112 double GetY(
double x)
const;
193 bool (*compare)(
const Line&,
const Line&,
const int&);
206 Line(
int pt1_x,
int pt1_y,
int pt2_x,
int pt2_y);
207 Line(
const std::initializer_list<int>& initial_list);
209 Line(
const cv::Vec4i& line);
210 Line(
const std::vector<int>& list);
214 operator cv::Vec4i()
const;
215 operator std::vector<int>()
const;
219 friend std::ostream&
operator<<(std::ostream& out,
const Line& line);
225 double Length(
bool is_rough =
false)
const;
229 template <
typename T>
233 Line&
Scale(
double factor,
bool round =
true);
234 template <
typename T>
270 Cm_Assert(
a != 0,
"The x-coordinate of the horizontal line can be any value");
272 return -(
b * y +
c) /
a;
289 Cm_Assert(b != 0,
"The y-coordinate of the vertical line can be any value");
291 return -(a * x + c) / b;
310 Cm_Assert(slope != 0,
"The x-coordinate of the horizontal line can be any value");
312 return (y - intercept) / slope;
314 return slope * y + intercept;
316 throw Exception(
"The \"line type\" only supports \"cm::HLINE\" or \"cm::VLINE\" types!");
336 Cm_Assert(slope != 0,
"The x-coordinate of the horizontal line can be any value");
338 return slope * x + intercept;
340 Cm_Assert(slope != 0,
"The y-coordinate of the vertical line can be any value");
342 return (x - intercept) / slope;
344 throw Exception(
"The \"line type\" only supports \"cm::HLINE\" or \"cm::VLINE\" types!");
360 return std::hash<int>()(line.
pt1.
x) ^ std::hash<int>()(line.
pt1.
y) ^ std::hash<int>()(line.
pt2.
x) ^ std::hash<int>()(line.
pt2.
y);
373 this->is_rough = is_rough;
408 this->min_distance = min_distance;
413 compare = [](
const Line& line1,
const Line& line2,
const int& min_distance) {
414 if (std::abs((line1.
pt1.
y + line1.
pt2.
y) - (line2.pt1.y + line2.pt2.y)) / 2.0 <= min_distance)
415 return line1.
pt1.
x < line2.pt1.x;
416 return line1.
pt1.
y < line2.pt1.y;
419 compare = [](
const Line& line1,
const Line& line2,
const int& min_distance) {
420 if (std::abs((line1.
pt1.
y + line1.
pt2.
y) - (line2.pt1.y + line2.pt2.y)) / 2.0 <= min_distance)
421 return line1.
pt2.
x < line2.pt2.x;
422 return line1.
pt2.
y < line2.pt2.y;
427 compare = [](
const Line& line1,
const Line& line2,
const int& min_distance) {
428 if (std::abs((line1.
pt1.
x + line1.
pt2.
x) - (line2.pt1.x + line2.pt2.x)) / 2.0 <= min_distance)
429 return line1.
pt1.
y < line2.pt1.y;
430 return line1.
pt1.
x < line2.pt1.x;
433 compare = [](
const Line& line1,
const Line& line2,
const int& min_distance) {
434 if (std::abs((line1.
pt1.
x + line1.
pt2.
x) - (line2.pt1.x + line2.pt2.x)) / 2.0 <= min_distance)
435 return line1.
pt2.
y < line2.pt2.y;
436 return line1.
pt2.
x < line2.pt2.x;
440 throw Exception(
"The \"line type\" only supports \"cm::HLINE\" or \"cm::VLINE\" types!");
459 return compare(line1, line2, min_distance);
485inline Line::Line(
int pt1_x,
int pt1_y,
int pt2_x,
int pt2_y) : pt1(pt1_x, pt1_y), pt2(pt2_x, pt2_y) {
510inline Line::Line(
const std::initializer_list<int>& initial_list) {
511 auto iter = initial_list.begin();
548inline Line::Line(
const cv::Vec4i& line) : pt1(line[0], line[1]), pt2(line[2], line[3]) {
564 Cm_Assert(list.size() == 4,
"list size must be 4!!!");
607inline Line::operator cv::Vec4i()
const {
608 return {pt1.
x, pt1.
y, pt2.
x, pt2.
y};
620inline Line::operator std::vector<int>()
const {
621 return {pt1.
x, pt1.
y, pt2.
x, pt2.
y};
639 return line1.
pt1 == line2.
pt1 && line1.
pt2 == line2.
pt2;
657 return line1.
pt1 != line2.
pt1 || line1.
pt2 != line2.
pt2;
673 out <<
"{ pt1: { x: " << line.
pt1.
x <<
", y: " << line.
pt1.
y <<
" }, pt2: { x: " << line.
pt2.
x <<
", y: " << line.
pt2.
y <<
" } }";
692 Cm_Assert(index < 4,
"index must be less than 4!");
704 throw Exception(
"Index must be less than 4!");
722 Cm_Assert(index < 4,
"index must be less than 4!");
734 throw Exception(
"Index must be less than 4!");
804 Cm_Assert(!this->
IsPoint(),
"the coordinates of the two points of the line segment are not the same!");
841 Cm_Assert(!this->
IsPoint(),
"the coordinates of the two points of the line segment are not the same!");
881 return std::abs(ge.a * pt.
x + ge.b * pt.
y + ge.c) / std::sqrt(ge.a * ge.a + ge.b * ge.b);
917 throw Exception(
"The type(LineDistanceType) of param \"type\" is incorrect!");
1057 double divisor = this_ge.a * ge.
b - ge.
a * this_ge.b;
1059 Cm_Assert(divisor != 0,
"two parallel lines do not intersect!");
1061 return {(this_ge.b * ge.
c - ge.
b * this_ge.c) / divisor, (ge.
a * this_ge.c - this_ge.a * ge.
c) / divisor};
1082 Cm_Assert(si.
line_type != this->Type(),
"only different types of lines can calculate intersections");
1085 if (this_si.line_type ==
VLINE) {
1098 double x = (this_si.slope * si.
intercept + this_si.intercept) / (1.0 - this_si.slope * si.
slope);
1115 double x = (si.
slope * this_si.intercept + si.
intercept) / (1.0 - si.
slope * this_si.slope);
1116 double y = this_si.slope * x + this_si.intercept;
1155 throw Exception(
"The type(Statistic) of param \"type\" is incorrect!");
1179 throw Exception(
"The type(Statistic) of param \"type\" is incorrect!");
1258 if (is_include_boundaries)
1290 if (std::max(a.x, b.x) < std::min(c.x, d.x) || std::max(c.x, d.x) < std::min(a.x, b.x) || std::max(a.y, b.y) < std::min(c.y, d.y) || std::max(c.y, d.y) < std::min(a.y, b.y))
1293 auto cd_vec = d - c;
1296 return (d - a).
Cross(cd_vec) * (d - b).Cross(cd_vec) <= 0;
1299 throw Exception(
"The type(IntersectType) of param \"type\" is incorrect!");
1333 if (std::max(a.x, b.x) < std::min(c.x, d.x) || std::max(c.x, d.x) < std::min(a.x, b.x) || std::max(a.y, b.y) < std::min(c.y, d.y) || std::max(c.y, d.y) < std::min(a.y, b.y))
1336 auto cd_vec = d - c;
1339 return (d - a).
Cross(cd_vec) * (d - b).Cross(cd_vec) < 0;
1342 throw Exception(
"The type(IntersectType) of param \"type\" is incorrect!");
1383 Cm_Assert(this->
Type() == line.
Type(),
"this function requires line type is same!");
1390 if (pt1.
y < line.
pt1.
y) {
1447 Cm_Assert(this->
Type() != line.
Type(),
"this function requires line type is different!");
1452 switch (align_direction) {
1455 return std::abs(pt.
x -
pt1.
x) <= threshold;
1458 return std::abs(pt.
x -
pt2.
x) <= threshold;
1460 throw Exception(
"The horizontal line \"align direction\" only supports \"cm::LEFT\" or \"cm::RIGHT\" types!");
1463 switch (align_direction) {
1466 return std::abs(pt.
y -
pt1.
y) <= threshold;
1469 return std::abs(pt.
y -
pt2.
y) <= threshold;
1471 throw Exception(
"The vertical line \"align direction\" only supports \"cm::TOP\" or \"cm::BOTTOM\" types!");
1500 return std::max(dst1, std::max(dst2, std::max(dst3, dst4))) <= threshold;
1502 return std::min(dst1, std::min(dst2, std::min(dst3, dst4))) <= threshold;
1504 return (dst1 + dst2 + dst3 + dst4) <= threshold * 4;
1506 throw Exception(
"The type(Statistic) of param \"type\" is incorrect!");
Line & Scale(double factor, bool round=true)
线的坐标缩放操作
bool IsIntersect(const Line &line, IntersectType type=INTERSECT_XY, bool is_include_boundaries=false) const
判断两线是否相交
Point2d Midpoint() const
获取线段中点坐标
double DistanceTo(const Point< T > &pt) const
计算点到直线的距离
LineType Type() const
获取线类型
Point2i pt2
线的第二个点(默认:对于横线是右边的点,对于竖线是下面的点)
Line & TidyLine()
整理线的端点顺序
Line & LimitY(const Interval &interval)
限制线的 y 坐标在指定区间范围内
bool IsAligned(const Line &line, Position align_direction, int threshold=5) const
判断两根线是否对齐
bool IsNear(const Line &line, double threshold=5.0, Statistic type=MAXIMUM) const
判断两线是否接近
Point2i pt1
线的第一个点(默认:对于横线是左边的点;对于竖线是上面的点)
int & operator[](size_t index)
线类重载方括号运算符
double Length(bool is_rough=false) const
获取线的长度
GEEquation GECoefficients() const
计算线的一般方程系数
friend bool operator!=(const Line &line1, const Line &line2)
线类重载不等于号
Line & LimitX(const Interval &interval)
限制线的 x 坐标在指定区间范围内
friend std::ostream & operator<<(std::ostream &out, const Line &line)
线类重载输出流运算符
bool IsPoint() const
判断线是否是一个点
Line SimpleConnect(const Line &line) const
简单合并线
double X(Statistic type) const
获取线的 X 坐标
double Y(Statistic type) const
获取线的 Y 坐标
Point2d Intersect(const Line &line) const
计算两线的交点
friend bool operator==(const Line &line1, const Line &line2)
线类重载等于号
Line & Translate(int dx, int dy)
线的坐标平移操作
bool InInterval(const Interval &x_interval, const Interval &y_interval) const
判断线是否在区间内
Line & Rotate(double angle, const Point< T > ¢er={0, 0})
线的坐标旋转操作
SIEquation SICoefficients() const
计算线的斜截式系数
Point< T > & Scale(double factor, bool round=false)
点的坐标缩放操作
Point< T > & LimitX(U start, U end)
限制点的 x 坐标在区间 [min_x, max_x] 范围内
double Cross(const Point< U > &pt) const
计算叉积
double DistanceTo(const Point< U > &pt) const
计算点到点之间的距离
Point< T > & Rotate(double angle, const Point< U > ¢er={0, 0})
点的坐标旋转操作
Point< T > & Translate(T dx, T dy)
点的坐标平移操作
Point< T > & LimitY(U start, U end)
限制点的 y 坐标在区间 [min_x, max_x] 范围内
#define Cm_Assert(expr, message)
断言宏
bool operator!=(const Interval &interval1, const Interval &interval2)
区间类重载不等于号
LineDistanceType
线与线的间距类型枚举
@ LDIS_MAX_X
线与线之间的最大x坐标距离
@ LDIS_MIN_Y
线与线之间的最小y坐标距离
@ LDIS_MIN_X
线与线之间的最小x坐标距离
@ LDIS_HORIZONTAL
线与线之间的水平距离(通常是竖线与竖线之间的水平距离)
@ LDIS_MAX_Y
线与线之间的最大y坐标距离
@ LDIS_VERTICAL
线与线之间的垂直距离(通常是横线与横线之间的垂直距离)
@ LDIS_VLINE_V
竖线与竖线之间的垂直距离(可能为负数,为负数时表示两竖线在y坐标上相交)
@ LDIS_HLINE_H
横线与横线之间的水平距离(可能为负数,为负数时表示两横线在x坐标上相交)
@ HLINE
横线 (horizontal line)
@ VLINE
竖线 (vertical line)
bool operator==(const Interval &interval1, const Interval &interval2)
区间类重载等于号
std::ostream & operator<<(std::ostream &out, const Interval &interval)
区间类重载输出流运算符
CompareByCoordinate(LineType type, int min_distance=10, bool use_pt1=true)
线的比较仿函数的带参构造函数(通过线的坐标比较)
bool operator()(const Line &line1, const Line &line2) const
线的比较仿函数重载括号运算符
bool operator()(const Line &line1, const Line &line2) const
线的比较仿函数重载括号运算符
CompareByLength(bool is_rough=false)
线的比较仿函数的带参构造函数(通过线的长度比较)
GEEquation()=default
线的一般方程结构体的默认构造函数
GEEquation(double a, double b, double c)
线的一般方程结构体的带参构造函数
double GetX(double y) const
计算 x 坐标
GEEquation(const GEEquation &ge)=default
线的一般方程结构体的拷贝构造函数
double GetY(double x) const
计算 y 坐标
double a
一般方程(ax + by + c = 0)的系数 a
double b
一般方程(ax + by + c = 0)的系数 b
double c
一般方程(ax + by + c = 0)的系数 c
size_t operator()(const Line &line) const
线的哈希仿函数重载括号运算符
double GetY(double x) const
计算 y 坐标
double intercept
斜截式方程(横线:y = kx + b,竖线:x = ky + b)的截距 b
double slope
斜截式方程(横线:y = kx + b,竖线:x = ky + b)的斜率 k
SIEquation()=default
线的斜截式方程结构体的默认构造函数
SIEquation(double slope, double intercept, LineType line_type)
线的斜截式方程结构体的带参构造函数
SIEquation(const SIEquation &ge)=default
线的斜截式方程结构体的拷贝构造函数
LineType line_type
斜截式方程(横线:y = kx + b,竖线:x = ky + b)的线类型
double GetX(double y) const
计算 x 坐标