📄 图形相交—相切view.cpp
字号:
// 图形相交—相切View.cpp : implementation of the CMyView class
//
#include "stdafx.h"
#include "图形相交—相切.h"
#include "图形相交—相切Doc.h"
#include "图形相交—相切View.h"
#include "math.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CMyView
IMPLEMENT_DYNCREATE(CMyView, CView)
BEGIN_MESSAGE_MAP(CMyView, CView)
//{{AFX_MSG_MAP(CMyView)
ON_COMMAND(ID_LINE_LINE, OnLineLine)
ON_COMMAND(ID_LINE_CIERCLE1, OnLineCiercle1)
ON_COMMAND(ID_CIRCLE_CIRCLE, OnCircleCircle)
ON_COMMAND(ID_LINE_CIRCLE, OnLineCircle)
ON_WM_RBUTTONDOWN()
ON_WM_KEYDOWN()
ON_COMMAND(ID_PLANE_CYLINDER, OnPlaneCylinder)
ON_COMMAND(ID_PLANE_CONE, OnPlaneCone)
//}}AFX_MSG_MAP
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CMyView construction/destruction
CMyView::CMyView()
{
P0[0]=255;P0[1]=255;
C[0]=120;C[1]=120;C[2]=50;
int i;
for(i=0;i<4;i++)
{P2[i].x=0;P2[i].y=0;}
c1[0]=420;c1[1]=120;c1[2]=50;
c2[0]=420;c2[1]=120;c2[2]=50;
l1[0]=400;l1[1]=50;l2[0]=200;l2[1]=200;
c[0]=320;c[1]=120;c[2]=50;
num=0;
}
CMyView::~CMyView()
{
}
BOOL CMyView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CView::PreCreateWindow(cs);
}
/////////////////////////////////////////////////////////////////////////////
// CMyView drawing
void CMyView::OnDraw(CDC* pDC)
{
CMyDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
}
/////////////////////////////////////////////////////////////////////////////
// CMyView printing
BOOL CMyView::OnPreparePrinting(CPrintInfo* pInfo)
{
// default preparation
return DoPreparePrinting(pInfo);
}
void CMyView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add extra initialization before printing
}
void CMyView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add cleanup after printing
}
/////////////////////////////////////////////////////////////////////////////
// CMyView diagnostics
#ifdef _DEBUG
void CMyView::AssertValid() const
{
CView::AssertValid();
}
void CMyView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CMyDoc* CMyView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMyDoc)));
return (CMyDoc*)m_pDocument;
}
#endif //_DEBUG
void CMyView::Tiso(float p0[3],float x0, float y0, float p[3])
{
p[0]=0.7071*(p0[0]-p0[1])+x0;
p[1]=-0.4082*(p0[0]+p0[1])+0.8165*p0[2]+y0;
p[2]=0;
}
void CMyView::Mydraw()
{
RedrawWindow(); //重绘窗口
CDC*pDC=GetDC();//获得绘图类指针
CPen pen1(PS_SOLID,1,(COLORREF)255),pen2(PS_SOLID,1,(COLORREF)255*255);
CPen* pOldPen=pDC->SelectObject(&pen1);
int k;
if(PushNum==2)
{
//double a,b;
pDC->TextOut(10,10,"按下键盘上的“上”、“下”、“左”、“右”箭头观看变化直线与圆的的相交情况");
k=PLC(l1,l2,c,p1,p2); //调用求切点切线子程序
pDC->Ellipse(c[0]-c[2],c[1]-c[2],c[0]+c[2],c[1]+c[2]); //画出已知圆
pDC->SelectObject(&pen2);
pDC->MoveTo(l1[0],l1[1]); //画直线
pDC->LineTo(l2[0],l2[1]);
switch(k)
{ case -1:pDC->TextOut(10,50,"直线与圆不相交,没有交点!");
break;
case 0:
{pDC->TextOut(10,50,"直线与圆相切,切点为:");
CString e;
e.Format("%e %e",p1[0],p1[1]); //将数字转化为字符串
pDC->TextOut(10,70,e);}
break;
case 1:
{pDC->TextOut(10,50,"直线与圆相交,交点为:");
CString a1,a2;
a1.Format("%e %e",p1[0],p1[1]); //将数字转化为字符串
a2.Format("%e %e",p2[0],p2[1]); //将数字转化为字符串
pDC->TextOut(10,70,a1);
pDC->TextOut(10,90,a2);}
break;
}
}
if(PushNum==3)
{
//char ch;
pDC->TextOut(10,10,"按下键盘上的“上”、“下”、“左”、“右”箭头观看不同点的切线变化");
k=TPC(P0,C,P,L); //调用求切点切线子程序
pDC->Ellipse(C[0]-C[2],C[1]-C[2],C[0]+C[2],C[1]+C[2]); //画出已知圆
pDC->MoveTo(P0[0]-4,P0[1]); //在P0点显示小十字光标
pDC->LineTo(P0[0]+4,P0[1]);
pDC->MoveTo(P0[0],P0[1]-4);
pDC->LineTo(P0[0],P0[1]+4);
if(k==-1) //给定P0点落在圆内
{
pDC->TextOut(20,20," Point is inside the circle! ");
}
else
{
pDC->MoveTo(P0[0]-4,P0[1]);
pDC->LineTo(P0[0]+4,P0[1]);
pDC->MoveTo(P0[0],P0[1]-4);
pDC->LineTo(P0[0],P0[1]+4);
pDC->SelectObject(&pen2); //设置画切线颜色
pDC->MoveTo(P[0],P[1]);
pDC->LineTo(P0[0],P0[1]);
pDC->MoveTo(P[0]-4,P[1]); //在切点处画小十字光标
pDC->LineTo(P[0]+4,P[1]);
pDC->MoveTo(P[0],P[1]-4);
pDC->LineTo(P[0],P[1]+4);
}
}
if(PushNum==4)
{
pDC->TextOut(10,10,"按下键盘上的“上”、“下”、“左”、“右”箭头观看位置或大小不同的两圆相交情况");
k=PCC(c1,c2,p1,p2); //调用两圆相交子程序
pDC->Ellipse(c1[0]-c1[2],c1[1]-c1[2],c1[0]+c1[2],c1[1]+c1[2]); //画出已知圆1
pDC->SelectObject(&pen2);
pDC->Ellipse(c2[0]-c2[2],c2[1]-c2[2],c2[0]+c2[2],c2[1]+c2[2]); //画出已知圆2
switch(k)
{ case -1:pDC->TextOut(10,50,"两个圆相离,没有交点!");
break;
case 0:pDC->TextOut(10,50,"两个圆重合!");
break;
case 1:
{pDC->TextOut(10,50,"两个圆相切,切点为:");
CString b;
b.Format("%e %e",p1[0],p1[1]); //将数字转化为字符串
pDC->TextOut(10,70,b);
}
break;
case 2:
{pDC->TextOut(10,50,"两个圆相交,交点为:");
CString a1,a2;
a1.Format("%e %e",p1[0],p1[1]); //将数字转化为字符串
a2.Format("%e %e",p2[0],p2[1]); //将数字转化为字符串
pDC->TextOut(10,70,a1);
pDC->TextOut(10,90,a2);
pDC->MoveTo(p1[0],p1[1]);
pDC->LineTo(p2[0],p2[1]);
}
break;
}
}
pDC->SelectObject(pOldPen);
ReleaseDC(pDC);
}
int CMyView::TPC(float P0[2],float C[3],float P[2],float L[3])
{
float d,sa,ca,sb,cb,st,ct;
d=sqrt((C[0]-P0[0])*(C[0]-P0[0])+(C[1]-P0[1])*(C[1]-P0[1]));
//计算P0点到圆心的距离为d
if(fabs(d)<fabs(C[2]))return -1; //P0点落在圆内
sa=(C[1]-P0[1])/d;
ca=(C[0]-P0[0])/d;
sb=C[2]/d;
cb=sqrt(d*d-C[2]*C[2])/d;
st=ca*cb-sa*sb;
ct=sa*cb+ca*sb;
P[0]=C[0]-C[2]*ct;
P[1]=C[1]+C[2]*st;
L[0]=P[1]-P0[1];
L[1]=-(P[0]-P0[0]);
L[2]=-P0[0]*P[1]+P[0]*P0[1];
return 1; //相切成立
}
int CMyView::PLL(double P1x,double P1y,double P2x,double P2y,double P3x,double P3y,double P4x,double P4y,double &Px,double &Py)
{
double a,b,c,d,e;
double eps=0; //设置零值的计算精度
a=P2x-P1x; //线段P1P2的X坐标差
b=P4x-P3x; //线段P3P4的X坐标差
c=P2y-P1y; //线段P1P2的Y坐标差
d=P4y-P3y; //线段P3P4的Y坐标差
e=a*d-b*c;
if(fabs(e)<=eps)return -1; //两线段平行或重合
Py=(c*d*(P3x-P1x)+a*d*P1y-b*c*P3y)/e;
if(fabs(c)<=eps)Px=P3x+b*(Py-P3y)/d;
else Px=P1x+a*(Py-P1y)/c;
if((Px-P1x)*(Px-P2x)<=0&&(Px-P3x)*(Px-P4x)<=0)
return 1; //有效交点
else return 0; //无效交点
}
//变量说明:
//p1、p2为已知两圆的圆心坐标及半径,c1、c2为所求两圆的交点坐标
int CMyView::PCC(double c1[3],double c2[3],double p1[2],double p2[2])
{
double d,sa,ca,sb,cb,x1,y1,x2,y2;
d=sqrt((c1[0]-c2[0])*(c1[0]-c2[0])+(c1[1]-c2[1])*(c1[1]-c2[1]));
//计算两圆圆心距离
sa=fabs(c1[2])+fabs(c2[2]);
sb=fabs(c1[2])-fabs(c2[2]);
if(d>sa||d<sb) return -1; //两圆相离
else if(sb==0&&d==0) return 0; //两圆重合
else if(d==sa||d==sb)
{cb=(c1[2]*c1[2]+d*d-c2[2]*c2[2])/(2.0*d*fabs(c1[2]));
sb=sqrt(fabs(1.0-cb*cb));
if(c1[2]>0.0) sb=-sb; //当R1>0时,跟号前为负号
ca=(c2[0]-c1[0])/d; //计算cosα
sa=(c2[1]-c1[1])/d; //计算sinα
x1=fabs(c1[2])*cb;
y1=fabs(c1[2])*sb;
p1[0]=x1*ca-y1*sa+c1[0];
p1[1]=x1*sa+y1*ca+c1[1];
return 1;
}
else
{
cb=(c1[2]*c1[2]+d*d-c2[2]*c2[2])/(2.0*d*fabs(c1[2]));
sb=sqrt(fabs(1.0-cb*cb));
if(c1[2]>0.0) sb=-sb; //当R1>0时,跟号前为负号
ca=(c2[0]-c1[0])/d; //计算cosα
sa=(c2[1]-c1[1])/d; //计算sinα
x1=fabs(c1[2])*cb;
y1=fabs(c1[2])*sb;
x2=x1;
y2=-y1;
p1[0]=x1*ca-y1*sa+c1[0];
p1[1]=x1*sa+y1*ca+c1[1];
p2[0]=x2*ca-y2*sa+c1[0];
p2[1]=x2*sa+y2*ca+c1[1];
return 2;
}
}
//变量说明:p1、p2为所求交点坐标,l为直线的法线方程系数,c为圆心坐标及半径
int CMyView::PLC(double l1[2],double l2[2],double c[3],double p1[2],double p2[2])
{
double d,dd,dp,sa,ca,a,b,c1,xa,ya;
a=l2[1]-l1[1];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -