旧代码,几何相关
开源代码gpc含有多边形切割算法。
double CalDis(const double x1, const double y1,
const double x2, const double y2)
{
return sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1));
}
double CalDis(const double ptx, const double pty,
const double x1, const double y1,
const double x2, const double y2)
{
double f = (x2-x1)*(ptx-x1) + (y2-y1)*(pty-y1);
if (f<=0)
return CalDis(ptx, pty, x1, y1);
double d = (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1);
if (f>d)
return CalDis(ptx, pty, x2, y2);
f = f/d;
double projX = (x1 + (x2 - x1)*f);
double projY = (y1 + (y2 - y1)*f);
return CalDis(ptx, pty, projX, projY);
}
线段交点
//--------------------------------------------------------------------------------
//Function:
//get the point of two lines
//Parameters:
// leftPoint [in]: the start point of first line
// rightPoint [in]: the end point of first line
// point1 [in]:the start point of second line
// point2 [in]: the end point of second line
// point [out]:the cross point
//Return:
// two lines have cross point whether or not
//-------------------------------------------------------------------------------
bool LineOperate::GetCrossPoint(const POINT &leftpoint,const POINT &rightpoint,
const POINT &point1,const POINT &point2,
POINT &point)
{
if (leftpoint.x == rightpoint.x)//clip by x line
{
if (point1.x == point2.x)//平行线不切割
{
return(false);
}
else if (leftpoint.x == point1.x)//首点落在切割线上
{
point.x = point1.x;
point.y = point1.y;
return(true);
}
else if (leftpoint.x == point2.x)//尾点落在切割线上
{
point.x = point2.x;
point.y = point2.y;
return(true);
}
else if (leftpoint.x > point1.x && leftpoint.x > point2.x)//不相交
{
return(false);
}
else if (leftpoint.x < point1.x && leftpoint.x < point2.x)//不相交
{
return(false);
}
else
{
double x = static_cast<double>(leftpoint.x);
double y = point1.y +
static_cast<double>(x - point1.x)
/ static_cast<double>(point2.x-point1.x)
* static_cast<double>(point2.y - point1.y) ;
point.x = static_cast<int>(x);
point.y = static_cast<int>(y);
return(true);
}
}
if (leftpoint.y == rightpoint.y)//clip by y line
{
if (point1.y == point2.y)//平行线不切割
{
return(false);
}
else if (leftpoint.y == point1.y)//首点落在切割线上
{
point.x = point1.x;
point.y = point1.y;
return(true);
}
else if (leftpoint.y == point2.y)//尾点落在切割线上
{
point.x = point2.x;
point.y = point2.y;
return(true);
}
else if (leftpoint.y > point1.y && leftpoint.y > point2.y)//不相交
{
return(false);
}
else if (leftpoint.y < point1.y && leftpoint.y < point2.y)//不相交
{
return(false);
}
else
{
double y = static_cast<double>(leftpoint.y);
double x = point1.x +
static_cast<double>(y - point1.y)
/ static_cast<double>(point2.y - point1.y)
* static_cast<double>(point2.x - point1.x) ;
point.x = static_cast<int>(x);
point.y = static_cast<int>(y);
return(true);
}
}
return(false);
}
线段切割
//-----------------------------------------------------------------------------------------
//Function:
//clip line arithmetic
//Parameters:
// input_point_vec [in]: the vector of points of the clipped line
// start_point [in]: the start point of the clipping line
// end_pointt [in]:the end point of the clipping line
// n [out]: the number of new NODE
//Return:
// None
//-----------------------------------------------------------------------------------------
void LineOperate::ClipLineByLine(POINT_VEC& input_point_vec, const POINT& start_point,
const POINT& end_point)
{
POINT temp_point;
NODE_CLIP_POINT crossPoint;
if (COORD_MIN_NUM > input_point_vec.size())
{
throw BbException(NORMAL_ERR, _T("mif_road coord num error"));
}
else
{
for (POINT_VEC::iterator it_point = input_point_vec.begin();
it_point + 1 != input_point_vec.end(); it_point++)
{
POINT current_point;
POINT next_point;
current_point.x = (*it_point).x;
current_point.y = (*it_point).y;
next_point.x = (*(it_point + 1)).x;
next_point.y = (*(it_point + 1)).y;
//if the line and the clipline have crosspoint
if (TRUE == GetCrossPoint(start_point, end_point, current_point, next_point, temp_point))
{
//if cross point is the start point of the current line
if (temp_point.x == static_cast<LONG>(current_point.x) &&
temp_point.y == static_cast<LONG>(current_point.y))
{
(*it_point).node_type = NODEPOINT;//set the NODE flag for this point
//if cross point is not the first point of the clipped line
/* if (it_point != input_point_vec.begin())
{
n++;
} */
}
//if cross point is the end point of the current line, no deal
else if (temp_point.x == static_cast<long>(next_point.x) && temp_point.y == static_cast<long>(next_point.y))
{
}
//other cases,set the NODE flag for the crosspoint and
//insert the crosspoint into the clipped line at the next position of current point
else
{
crossPoint.x = temp_point.x;
crossPoint.y = temp_point.y;
crossPoint.node_type = NODEPOINT;
it_point = input_point_vec.insert(it_point + 1, crossPoint);
//n++;
}
}
}
}
return;
}
矢量角度
//------------------------------------------------------------------------------------------
//Function:
//get the distance of one point to the line
//Parameters:
// start_point [in]: the start point of the line
// end_point [in]: the end point of the line
//Return:
// 2点矢量方向(起始点指向终点)与水平方向的夹角(0度~360度)
//------------------------------------------------------------------------------------------
double LineOperate::GetTwoPointVectorAngle(POINT start_point, POINT end_point)
{
if (start_point.x == end_point.x)
{
if (start_point.y < end_point.y)//垂直情况(起始点在下,终点在上)
{
return(PI / 2);
}
else if (start_point.y > end_point.y)//垂直情况(起始点在上,终点在下)
{
return(3* PI / 2);
}
else//同一个点情况
{
return(0);
}
}
else if (start_point.y == end_point.y)
{
if (start_point.y < end_point.y)//水平情况(起始点在左,终点在右)
{
return(0);
}
else if (start_point.y > end_point.y)//水平情况(起始点在右,终点在左)
{
return(PI);
}
else//同一个点情况
{
return(0);
}
}
else if ((start_point.x < end_point.x) && (start_point.y < end_point.y))//角度第一象限情况(起始点在下,终点在上)
{
return(atan(static_cast<double>(end_point.y - start_point.y) /
static_cast<double>(end_point.x - start_point.x)));
}
else if ((start_point.x > end_point.x) && (start_point.y < end_point.y))//角度第二象限情况(起始点在下,终点在上)
{
return(PI - atan(static_cast<double>(end_point.y - start_point.y) /
static_cast<double>(start_point.x - end_point.x)));
}
else if ((start_point.x > end_point.x) && (start_point.y > end_point.y))//角度第三象限情况(起始点在上,终点在下)
{
return(PI + atan(static_cast<double>(start_point.y - end_point.y) /
static_cast<double>(start_point.x - end_point.x)));
}
else if ((start_point.x < end_point.x) && (start_point.y > end_point.y))//角度第四象限情况(起始点在上,终点在下)
{
return (2* PI - atan(static_cast<double>(start_point.y - end_point.y) /
static_cast<double>(end_point.x - start_point.x)));
}
else
{
CSERROR("求2点角度异常");
return(0);
}
}