📄 dyx_point.cpp
字号:
#include "StdAfx.h"
#include <math.h>
#include "DYX_Point.h"
#include "DYX_Vector.h"
#include "DYX_LineCircle.h"
#include "DYX_Math.h"
#include "DYX_MeshDefinition.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//-------------------------------------
// Implementation of Class Point2D
//-------------------------------------
void Point2D::operator=(const Point2D &P)
{
this->x = P.x;
this->y = P.y;
}
BOOL Point2D::operator==(const Point2D &P) const
{
if(fabs(this->x-P.x) < MEAN_ERR && fabs(this->y-P.y) < MEAN_ERR)
return TRUE;
else
return FALSE;
}
BOOL Point2D::operator!=(const Point2D &P) const
{
if(fabs(this->x-P.x) >= MEAN_ERR || fabs(this->y-P.y) >= MEAN_ERR)
return TRUE;
else
return FALSE;
}
Point2D Point2D::operator+(const Point2D &P) const
{
Point2D Pt;
Pt.x = this->x + P.x;
Pt.y = this->y + P.y;
return Pt;
}
Point2D Point2D::operator-(const Point2D &P) const
{
Point2D Pt;
Pt.x = this->x - P.x;
Pt.y = this->y - P.y;
return Pt;
}
void Point2D::SetPoint(const double x1, const double y1)
{
this->x = x1;
this->y = y1;
}
void Point2D::SetPoint(const double Pt[2])
{
this->x = Pt[0];
this->y = Pt[1];
}
void Point2D::SetPoint(const Point2D Pt)
{
this->x = Pt.x;
this->y = Pt.y;
}
double Point2D::Multiply(const Point2D &P, const Point2D &Q) const
{
// r = Multiply(P,Q), 得到(P-O)*(Q-O)的叉积
// r>0 : Q在矢量OP的逆时针方向;
// r=0 : op->P->Q 三点共线;
// r<0 : Q在矢量OP的顺时针方向
return ((P.x-this->x)*(Q.y-this->y)-(Q.x-this->x)*(P.y-this->y));
}
double Point2D::dotMultiply(const Point2D &P, const Point2D &Q) const
{
// ---------------------------------------------------------------------------
// O为当前点,r=dotMultiply(P,Q),得到矢量(P-O)和(Q-O)的点积,如果两个矢量都非零矢量
// r<0:两矢量夹角为锐角;
// r=0:两矢量夹角为直角;
// r>0:两矢量夹角为钝角
//------------------------------------------------------------------------------
return ((P.x-this->x)*(Q.x-this->x)+(P.y-this->y)*(Q.y-this->y));
}
void Point2D::Move(const double x1, const double y1)
{
this->x += x1;
this->y += y1;
}
double Point2D::Distance(const Point2D &P) const
{
// 返回两点之间欧氏距离
return sqrt((P.x-this->x)*(P.x-this->x)+(P.y-this->y)*(P.y-this->y));
}
double Point2D::Distance(const LineSeg2D &L) const
{
// 求当前点到线段L所在直线的最短距离
return fabs(L.sp.Multiply(*this, L.ep)) / L.Distance();
}
void Point2D::Rotate(const Point2D &RotateCenter, const double dAngle)
{
// 返回当前点以点Cent为圆心逆时针旋转dAngle(单位:弧度)后所在的位置
double x1 = this->x - RotateCenter.x;
double y1 = this->y - RotateCenter.y;
this->x = x1*cos(dAngle) - y1*sin(dAngle) + RotateCenter.x;
this->y = y1*cos(dAngle) + x1*sin(dAngle) + RotateCenter.y;
}
BOOL Point2D::IsEqualTo(const Point2D &P, const double Tol) const
{
// 判断两个点是否重合
return ( (fabs(P.x-this->x) < Tol) && (fabs(P.y-this->y) < Tol) );
}
BOOL Point2D::OnLineSeg(const LineSeg2D &L) const
{
// 设点为Q,线段为P1P2 ,判断点Q在该线段上的依据是:( Q - P1 ) × ( P2 - P1 ) = 0
// 且 Q 在以 P1,P2为对角顶点的矩形内。前者保证Q点在直线P1P2上,
// 后者是保证Q点不在线段P1P2的延长线或反向延长线上。
return ( fabs(Multiply(L.sp, L.ep)) < EPS &&
(this->x-L.sp.x)*(this->x-L.ep.x) <= 0.0 &&
(this->y-L.sp.y)*(this->y-L.ep.y) <= 0.0 );
}
double Point2D::Angle(const Point2D &B) const
{
// 返回顶角在当前点A,终点在B的有向线段与X轴正向的夹角。
// 角度小于PI,返回正值
// 角度大于PI,返回负值
Vector2D Vt(B.x-this->x, B.y-this->y);
return Vt.Angle();
}
double Point2D::Angle(const Point2D &B, const Point2D &C) const
{
// 返回顶角在当前点A,起始边为AB,终止边为AC的夹角(单位:弧度)
// 角度小于PI,返回正值
// 角度大于PI,返回负值
//
// 可以用于求线段之间的夹角
//
// We define the angle theta between two vectors v and w by the formula
// v . w
// cos Q = --------------
// ||v|| ||w||
// so that
// v . w = ||v|| ||w|| cos Q
double x1 = B.x - this->x;
double y1 = B.y - this->y;
double x2 = C.x - this->x;
double y2 = C.y - this->y;
double cosAngle = x1*x2 + y1*y2;
double norm = (x1*x1+y1*y1) * (x2*x2+y2*y2);
cosAngle /= sqrt( norm );
if (cosAngle >= 1.0-EPS )
return 0.0;
if (cosAngle <= -1.0+EPS )
return PI;
double dAngle = acos(cosAngle);
if (x1*y2-y1*x2 < 0.0)
return (-dAngle); // 说明矢量AO->BO为顺时针方向
else // 说明矢量AO->BO为逆时针方向
return dAngle;
}
double Point2D::TriangleAngle(const Point2D &B, const Point2D &C) const
{
// 三角形余玄定理:a^2=b^2+c^2-2bcCOS(Angle)。
// a, b, c为边长,Angle为BC两条线间的夹角。
// 返回值在0->PI之间。
double a2 = (B.x-C.x)*(B.x-C.x) + (B.y-C.y)*(B.y-C.y);
double b2 = (this->x-C.x)*(this->x-C.x) + (this->y-C.y)*(this->y-C.y);
double c2 = (this->x-B.x)*(this->x-B.x) + (this->y-B.y)*(this->y-B.y);
if(a2 < MEAN_ERR || b2 < MEAN_ERR || c2 < MEAN_ERR)
{
::AfxMessageBox(_T("The three points are colliear."));
return 0.0;
}
double cosAngle = (b2+c2-a2) / (2.0*sqrt(b2*c2));
if(cosAngle >= 1.0-EPS)
return 0.0;
else if(cosAngle <= EPS-1.0)
return PI;
else
return acos(cosAngle);
}
double Point2D::TriangleArea(const Point2D &B, const Point2D &C) const
{
// To obtain the directional area of triangle.
// area > 0.0 if A->B->C are counter-clockwise;
// area < 0.0 if A->B->C are clockwise;
// area == 0 if A, B and C are colliear.
return (0.5*((B.x-this->x)*(C.y-this->y) - (C.x-this->x)*(B.y-this->y)));
}
double Point2D::Relation(const LineSeg2D &L) const
{
// 本函数是根据下面的公式写的,P是点C到线段AB所在直线的垂足
//
// AC dot AB
// r = ---------
// ||AB||^2
//
// (Cx-Ax)(Bx-Ax) + (Cy-Ay)(By-Ay)
// = -------------------------------
// L^2
//
// r has the following meaning:
//
// r=0 P = A
// r=1 P = B
// r<0 P is on the backward extension of AB
// r>1 P is on the forward extension of AB
// 0<r<1 P is interior to AB
double dot = L.sp.dotMultiply(*this, L.ep);
double dist = L.Distance();
return dot / (dist*dist);
}
Point2D Point2D::Perpendicular(const LineSeg2D &L) const
{
// 求点C到线段AB所在直线的垂足 P
double r = this->Relation(L);
Point2D tmpPt;
tmpPt.x = L.sp.x + r*(L.ep.x-L.sp.x);
tmpPt.y = L.sp.y + r*(L.ep.y-L.sp.y);
return tmpPt;
}
double Point2D::NearestDistance(const LineSeg2D &L, Point2D &P) const
{
// -------------------------------------------------
// 求当前点到线段L的最短距离,并返回线段上距该点最近的点Pt
// 注意:Pt是线段L上到当前点最近的点,不一定是垂足
//----------------------------------------------------
double r = this->Relation(L);
if(r < 0.0)
{
P = L.sp;
return this->Distance(L.sp);
}
if(r > 1.0)
{
P = L.ep;
return this->Distance(L.ep);
}
P = this->Perpendicular(L);
return this->Distance(P);
}
void Point2D::TangentialPoint(const Circle2D &Cir, Point2D &P1, Point2D &P2) const
{
// 求通过当前点到给定圆的切点。
// p---圆心坐标, r---圆半径, sp---圆外一点, Pt1,Pt2---切点坐标
Circle2D tmpCir;
tmpCir.x = (Cir.x+this->x) / 2.0;
tmpCir.y = (Cir.y+this->y) / 2.0;
double dx2 = tmpCir.x-Cir.x;
double dy2 = tmpCir.y-Cir.y;
tmpCir.r = sqrt(dx2*dx2+dy2*dy2);
tmpCir.Intersect(Cir, P1, P2);
}
Point2D Point2D::Symmetry(const Line2D &L) const
{
// 求当前点关于直线L的对称点
Point2D tmpPt;
tmpPt.x=((L.b*L.b-L.a*L.a)*x-2*L.a*L.b*y-2*L.a*L.c)/(L.a*L.a+L.b*L.b);
tmpPt.y=((L.a*L.a-L.b*L.b)*y-2*L.a*L.b*x-2*L.b*L.c)/(L.a*L.a+L.b*L.b);
return tmpPt;
}
BOOL Point2D::Inside(const Circle2D &Cir) const
{
// 当前点在圆内(包括边界)时,返回true
double d2 = (this->x-Cir.x)*(this->x-Cir.x)+(this->y-Cir.y)*(this->y-Cir.y);
double r2 = Cir.r*Cir.r;
if(d2 <= r2)
return TRUE;
else
return FALSE;
}
BOOL Point2D::Inside(const MyRectangle &Rect, const double dGap) const
{
// 当前点在矩形内部(包括边界)时,返回true
MyRectangle tmpRect(Rect);
Point2D tmpPt(*this);
double rotAngle = -tmpRect.RotateAngle;
if(fabs(rotAngle) > EPS)
{
tmpRect.Rotate(tmpRect.LowLeft, rotAngle);
tmpPt.Rotate(tmpRect.LowLeft, rotAngle);
}
double x1 = tmpRect.LowLeft.x + dGap;
double y1 = tmpRect.LowLeft.y + dGap;
double x2 = tmpRect.LowLeft.x + tmpRect.Width - dGap;
double y2 = tmpRect.LowLeft.y + tmpRect.Length - dGap;
if( x1 <= tmpPt.x && tmpPt.x <= x2 &&
y1 <= tmpPt.y && tmpPt.y <= y2 )
return TRUE;
else
return FALSE;
}
//-------------------------------------
// Implementation of Class Point3D
//-------------------------------------
void Point3D::operator=(const Point3D &P)
{
this->x = P.x;
this->y = P.y;
this->z = P.z;
}
BOOL Point3D::operator==(const Point3D &P) const
{
if( fabs(this->x-P.x) < MEAN_ERR &&
fabs(this->y-P.y) < MEAN_ERR &&
fabs(this->z-P.z) < MEAN_ERR )
return TRUE;
else
return FALSE;
}
BOOL Point3D::operator!=(const Point3D &P) const
{
if( fabs(this->x-P.x) >= MEAN_ERR ||
fabs(this->y-P.y) >= MEAN_ERR ||
fabs(this->z-P.z) >= MEAN_ERR )
return TRUE;
else
return FALSE;
}
Point3D Point3D::operator+(const Point3D &P) const
{
Point3D tmpPt;
tmpPt.x = this->x + P.x;
tmpPt.y = this->y + P.y;
tmpPt.z = this->y + P.z;
return tmpPt;
}
Point3D Point3D::operator-(const Point3D &P) const
{
Point3D tmpPt;
tmpPt.x = this->x - P.x;
tmpPt.y = this->y - P.y;
tmpPt.z = this->z - P.z;
return tmpPt;
}
void Point3D::SetPoint(const double x1, const double y1, const double z1)
{
this->x = x1;
this->y = y1;
this->z = z1;
}
void Point3D::SetPoint(const double Pt[3])
{
this->x = Pt[0];
this->y = Pt[1];
this->z = Pt[2];
}
double Point3D::Distance(const Point3D &P) const
{
// 返回两点之间欧氏距离
return sqrt((P.x-this->x)*(P.x-this->x) + (P.y-this->y)*(P.y-this->y) + (P.z-this->z)*(P.z-this->z));
}
void MyTest(void)
{
Point2D P1(0, 0);
MyRectangle Rect(P1, 4, 2);
Point2D P2(-1, 2);
Circle2D Cir(P2, 0.5);
BOOL bFlag = Cir.Inside(Rect);
Rect.Rotate(Rect.LowLeft, 90.0*DEG_To_RAD);
bFlag = Cir.Inside(Rect);
Rect.Offset(0.5);
// TCHAR text[80];
// _stprintf(text, _T("%lf\t%lf"), inPt.x, inPt.y);
// str += text;
// ::AfxMessageBox(str);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -