Excel 如何画有效边界

Excel 如何画有效边界,第1张

“规划求解”是一组命令的组成部分(有时也称作假设分析 (假设分析:该过程通过更改单元格中的值来查看这些更改对工作表中公式结果的影响。例如,更改分期支付表中的利率可以调整支付金额。)工具)。
借助“规划求解”,可求得工作表上某个单元格(称为目标单元格)中公式 (公式:单元格中的一系列值、单元格引用、名称或运算符的组合,可生成新的值。公式总是以等号 (=) 开始。)的最优值。
“规划求解”将对直接或间接与目标单元格中的公式相关的一组单元格进行处理。“规划求解”将调整所指定的变动单元格(称为可变单元格)中的值,从目标单元格公式中求得所指定的结果。可以应用约束条件 (约束条件:“规划求解”中设置的限制条件。可以将约束条件应用于可变单元格、目标单元格或其他与目标单元格直接或间接相关的单元格。)
来限制“规划求解”可在模型中使用的值,而且约束条件可以引用影响目标单元格公式的其他单元格。

#include "MyFaceh"
#include "Edgeh"
#include "Bucketh"
#include "P2Dh"
#define Number 4//N为闭合多边形顶点数,顶点存放在整型二维数组Point[N]中
class CTestView : public CView
{
protected: // create from serialization only
CTestView();
DECLARE_DYNCREATE(CTestView)
// Attributes
public:
CTestDoc GetDocument();
// Operations
public:
void GetMaxX();//获得屏幕的最大x值
void GetMaxY();//获得屏幕的最大y值
void ReadPoint();//读入顶点表
void ReadFace();//读入面表
void InitParameter();//参数初始化
void VisualVector(int);//求视向量分量
void NormalVector(int,int,int);//求法向量
double Product(P3D &,P3D &);//求向量的数量积
void SetCoord();//坐标设置
void DrawSmoothObject(CDC mdc);//面顶点设置
void DrawFace(CDC pDC);//画各个面
void Project(P3D &);//透视投影
void CreatBucket();//建立桶结点
void Et();//构造边表
void AddAet(Edge );//将边插入Aet表
void AetOrder();//对Aet表进行排序
void PolygonFill(CDC);//下闭上开填充多边形
MyRGB Interpolation(int,int,int,MyRGB &,MyRGB &);//线性插值
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CTestView)
public:
virtual void OnDraw(CDC pDC); // overridden to draw this view
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
virtual BOOL OnPreparePrinting(CPrintInfo pInfo);
virtual void OnBeginPrinting(CDC pDC, CPrintInfo pInfo);
virtual void OnEndPrinting(CDC pDC, CPrintInfo pInfo);
//}}AFX_VIRTUAL
// Implementation
public:
virtual ~CTestView();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected:
int MaxX,MaxY;//屏幕水平和垂直的最大坐标
P3D P[9],ViewP,N,S;//N法向量,S视向量
MyFace F[7];//面表
double R,Theta,Phi,D;//R,Theta,Phi视点在用户坐标系的球坐标,D视距
double k[9];//运算常量
double O1,O2,O3;//视点球坐标分量
P2D Point[4],ScreenP;//屏幕坐标系的二维坐标点
int Face;//面
CDC Picture;//双缓冲
Bucket CurrentB,HeadB;//桶指针
Edge E[Number],CurrentE,HeadE,T1,T2;//边表指针
BOOL Play;//动画开关
// Generated message map functions
protected:
//{{AFX_MSG(CTestView)
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnRButtonDblClk(UINT nFlags, CPoint point);
afx_msg BOOL OnEraseBkgnd(CDC pDC);
afx_msg void OnMENUPlay();
afx_msg void OnTimer(UINT nIDEvent);
afx_msg void OnUpdateMENUPlay(CCmdUI pCmdUI);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
#ifndef _DEBUG // debug version in TestViewcpp
inline CTestDoc CTestView::GetDocument()
{ return (CTestDoc)m_pDocument; }
#endif
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line
#endif // !defined(AFX_TESTVIEW_H__A75FDCFB_621C_4E38_A154_C344803E6372__INCLUDED_)
// TestViewcpp : implementation of the CTestView class
//
#include "stdafxh"
#include "Testh"
#include "TestDoch"
#include "TestViewh"
#define ROUND(a) int(a+05)//四舍五入
#define PI 31415926//圆周率
#include "cmath"//数学头文件
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CTestView
IMPLEMENT_DYNCREATE(CTestView, CView)
BEGIN_MESSAGE_MAP(CTestView, CView)
//{{AFX_MSG_MAP(CTestView)
ON_WM_LBUTTONDOWN()
ON_WM_RBUTTONDBLCLK()
ON_WM_ERASEBKGND()
ON_COMMAND(ID_MENUPlay, OnMENUPlay)
ON_WM_TIMER()
ON_UPDATE_COMMAND_UI(ID_MENUPlay, OnUpdateMENUPlay)
//}}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()
/////////////////////////////////////////////////////////////////////////////
// CTestView construction/destruction
CTestView::CTestView()
{
// TODO: add construction code here
Play=FALSE;
R=7000;D=1000;Theta=-10;Phi=20;
}
CTestView::~CTestView()
{
}
BOOL CTestView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CView::PreCreateWindow(cs);
}
/////////////////////////////////////////////////////////////////////////////
// CTestView drawing
void CTestView::OnDraw(CDC pDC)
{
CTestDoc pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
}
/////////////////////////////////////////////////////////////////////////////
// CTestView printing
BOOL CTestView::OnPreparePrinting(CPrintInfo pInfo)
{
// default preparation
return DoPreparePrinting(pInfo);
}
void CTestView::OnBeginPrinting(CDC /pDC/, CPrintInfo /pInfo/)
{
// TODO: add extra initialization before printing
}
void CTestView::OnEndPrinting(CDC /pDC/, CPrintInfo /pInfo/)
{
// TODO: add cleanup after printing
}
/////////////////////////////////////////////////////////////////////////////
// CTestView diagnostics
#ifdef _DEBUG
void CTestView::AssertValid() const
{
CView::AssertValid();
}
void CTestView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CTestDoc CTestView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CTestDoc)));
return (CTestDoc)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CTestView message handlers
void CTestView::GetMaxX()//获得屏幕宽度
{
CRect Rect;
GetClientRect(&Rect);
MaxX=Rectright;
}
void CTestView::GetMaxY()//获得屏幕高度
{
CRect Rect;
GetClientRect(&Rect);
MaxY=Rectbottom;
}
void CTestView::ReadPoint()//读入8个顶点坐标
{
double a=100;//正方体边长
//x,y,z和顶点颜色
P[1]x=-a;P[1]y=-a;P[1]z=-a;P[1]cred=00;P[1]cgreen=10;P[1]cblue=10;
P[2]x=-a;P[2]y=a;P[2]z=-a;P[2]cred=10;P[2]cgreen=00;P[2]cblue=10;
P[3]x=-a;P[3]y=a;P[3]z=a;P[3]cred=00;P[3]cgreen=00;P[3]cblue=10;
P[4]x=-a;P[4]y=-a;P[4]z=a;P[4]cred=00;P[4]cgreen=00;P[4]cblue=00;
P[5]x=a;P[5]y=-a;P[5]z=-a;P[5]cred=00;P[5]cgreen=10;P[5]cblue=00;
P[6]x=a;P[6]y=a;P[6]z=-a;P[6]cred=10;P[6]cgreen=10;P[6]cblue=10;
P[7]x=a;P[7]y=a;P[7]z=a;P[7]cred=10;P[7]cgreen=00;P[7]cblue=00;
P[8]x=a;P[8]y=-a;P[8]z=a;P[8]cred=10;P[8]cgreen=10;P[8]cblue=00;
}
void CTestView::ReadFace()//读入6个面坐标
{
//面的边数,面的顶点编号,面的颜色
F[1]En=4;F[1]p[1]=1;F[1]p[2]=4;F[1]p[3]=3;F[1]p[4]=2;//左面
F[2]En=4;F[2]p[1]=5;F[2]p[2]=6;F[2]p[3]=7;F[2]p[4]=8;//右面
F[3]En=4;F[3]p[1]=8;F[3]p[2]=4;F[3]p[3]=1;F[3]p[4]=5;//底面
F[4]En=4;F[4]p[1]=7;F[4]p[2]=6;F[4]p[3]=2;F[4]p[4]=3;//顶面
F[5]En=4;F[5]p[1]=3;F[5]p[2]=4;F[5]p[3]=8;F[5]p[4]=7;//前面
F[6]En=4;F[6]p[1]=2;F[6]p[2]=6;F[6]p[3]=5;F[6]p[4]=1;//后面
}
void CTestView::VisualVector(int pt)//求视矢量分量
{
O1=Rk[5];O2=Rk[6];O3=Rk[4];//观察坐标系的视点球坐标
Sx=O1-P[pt]x;Sy=O2-P[pt]y;Sz=O3-P[pt]z;//视矢量
}
void CTestView::NormalVector(int p1,int p2,int p3)//求表面法矢量分量
{
P3D F,H;
//求第一条边的分量
Fx=P[p2]x-P[p1]x;Fy=P[p2]y-P[p1]y;Fz=P[p2]z-P[p1]z;
//求第二条边的分量
Hx=P[p3]x-P[p1]x;Hy=P[p3]y-P[p1]y;Hz=P[p3]z-P[p1]z;
//法向量为第一和第二个向量的叉积
Nx=FyHz-FzHy;Ny=FzHx-FxHz;Nz=FxHy-FyHx;
}
double CTestView::Product(P3D &v,P3D &n)//求矢量的数量积
{
double NProduct;
NProduct=vxnx+vyny+vznz;
return(NProduct);
}
void CTestView::Project(P3D &P)//透视变换
{
ViewPx=k[1]Px-k[3]Py;//观察坐标系三维坐标
ViewPy=-k[7]Px-k[8]Py+k[2]Pz;
ViewPz=-k[5]Px-k[6]Py-k[4]Pz+R;
ScreenPx=DViewPx/ViewPz;//屏幕坐标系二维坐标
ScreenPy=ROUND(DViewPy/ViewPz);
ScreenPc=Pc;
}
void CTestView::InitParameter()//透视变换初始化参数
{
k[1]=sin(PITheta/180);
k[2]=sin(PIPhi/180);
k[3]=cos(PITheta/180);
k[4]=cos(PIPhi/180);
k[5]=k[3]k[2];
k[6]=k[1]k[2];
k[7]=k[3]k[4];
k[8]=k[1]k[4];
}
void CTestView::OnLButtonDown(UINT nFlags, CPoint point)//鼠标左键函数
{
// TODO: Add your message handler code here and/or call default
R=R+100;
SetCoord();
CView::OnLButtonDown(nFlags, point);
}
void CTestView::OnRButtonDblClk(UINT nFlags, CPoint point)//鼠标右键函数
{
// TODO: Add your message handler code here and/or call default
R=R-100;
SetCoord();
CView::OnRButtonDblClk(nFlags, point);
}
void CTestView::SetCoord()//坐标设置
{
CRect Rect;
GetClientRect(&Rect);
CDC MemDC;
CBitmap Bitmap,OldBitmap;
BitmapLoadBitmap(IDB_BITMAP2);
MemDCCreateCompatibleDC(GetDC());
OldBitmap=MemDCSelectObject(&Bitmap);
MemDCBitBlt(0,0,RectWidth(),RectHeight(),&Picture,0,0,SRCCOPY);
int P1,P2,P3;//面的顶点
for(Face=1;Face<=6;Face++)
{
P1=F[Face]p[1];//面的第一个顶点
P2=F[Face]p[2];//面的第二个顶点
P3=F[Face]p[3];//面的第三个顶点
VisualVector(P1);//求视矢量
NormalVector(P1,P2,P3);//求法矢量
if(Product(S,N)>=0)//判断数量积正负
DrawSmoothObject(&MemDC);//数量积大于零,表面画出
}
CClientDC dc(this);
dcBitBlt(0,0,RectWidth(),RectHeight(),&MemDC,0,0,SRCCOPY);
MemDCSelectObject(OldBitmap);
}
void CTestView::DrawSmoothObject(CDC mdc)//面顶点设置
{
int TotalEdge=F[Face]En;//计算每个面的总边数
for(int edge=1;edge<=TotalEdge;edge++)//边循环
{
P3D Vertex;
int PointNumber=F[Face]p[edge];//面的顶点号
Vertex=P[PointNumber];
Project(Vertex);//透视投影
Point[edge-1]=ScreenP;
}
CreatBucket();//初始化桶
Et();//用于建立边表
PolygonFill(mdc);//进行填充
}
//有效边表算法开始
void CTestView::PolygonFill(CDC mdc)//下闭上开多边形填充
{
HeadE=NULL;
for(CurrentB=HeadB;CurrentB!=NULL;CurrentB=CurrentB->next)//访问所有桶结点
{
for(CurrentE=CurrentB->p;CurrentE!=NULL;CurrentE=CurrentE->next)//访问桶中排序前的边结点
{
Edge TEdge=new Edge;
TEdge->k=CurrentE->k;
TEdge->x=CurrentE->x;
TEdge->yMax=CurrentE->yMax;
TEdge->x1=CurrentE->x1;
TEdge->y1=CurrentE->y1;
TEdge->c1=CurrentE->c1;
TEdge->x2=CurrentE->x2;
TEdge->y2=CurrentE->y2;
TEdge->c2=CurrentE->c2;
TEdge->next=NULL;
AddAet(TEdge);//将该边插入临时Aet表
}
AetOrder();//使得Aet表按照x递增的顺序存放
T1=HeadE;//根据ymax抛弃扫描完的边结点
if(T1==NULL)
{
return;
}
while(CurrentB->ScanLine>=T1->yMax)//放弃该结点,Aet表指针后移
{
T1=T1->next;
HeadE=T1;
if(HeadE==NULL)
{
return;
}
}
if(T1->next!=NULL)
{
T2=T1;
T1=T2->next;
}
while(T1!=NULL)
{
if(CurrentB->ScanLine>=T1->yMax)//跳过一个结点
{
T2->next=T1->next;
T1->next=NULL;
T1=T2->next;
}
else
{
T2=T1;
T1=T2->next;
}
}
MyRGB Is,It,Ip;
if(CurrentE!=NULL)//扫描线上两边共线
{
Is=Interpolation(CurrentB->ScanLine,HeadE->y1,HeadE->y2,HeadE->c1,HeadE->c2);
It=Interpolation(CurrentB->ScanLine,HeadE->next->y2,HeadE->next->y1,HeadE->c2,HeadE->c1);
}
else
{
Is=Interpolation(CurrentB->ScanLine,HeadE->y1,HeadE->y2,HeadE->c1,HeadE->c2);
It=Interpolation(CurrentB->ScanLine,HeadE->next->y2,HeadE->next->y1,HeadE->next->c2,HeadE->next->c1);
}
BOOL In=false;//设置一个BOOL变量In,初始值为假
int xb,xe;//扫描线区间的起点和终点
for(T1=HeadE;T1!=NULL;T1=T1->next)//填充扫描线和多边形相交的区间
{
if(In==false)
{
xb=ROUND(T1->x)-1;
In=true;//每访问一个结点,把In值取反一次
}
else//如果In值为真,则填充从当前结点的x值开始到下一结点的x值结束的区间
{
xe=ROUND(T1->x);
for(double x=xb;x<=xe;x++)
{
Ip=Interpolation(ROUND(x),xb,xe,Is,It);
mdc->SetPixel(MaxX/2+ROUND(x),MaxY/2+CurrentB->ScanLine,RGB((BYTE)(Ipred255),(BYTE)(Ipgreen255),(BYTE)(Ipblue255)));
}
In=false;
}
}
for(T1=HeadE;T1!=NULL;T1=T1->next)//边连贯性
{
T1->x=T1->x+T1->k;//x=x+1/k
}
}
delete HeadB;
delete CurrentB;
delete CurrentE;
delete HeadE;
}
void CTestView::CreatBucket()//初始化桶结点
{
int ScanMin,ScanMax;//确定扫描线的最小值和最大值
ScanMax=ScanMin=Point[0]y;
for(int i=1;i<Number;i++)
{
if(Point[i]y<ScanMin)
{
ScanMin=Point[i]y;//扫描线的最小值
}
if(Point[i]y>ScanMax)
{
ScanMax=Point[i]y;//扫描线的最大值
}
}
for(i=ScanMin;i<=ScanMax;i++)//建立桶结点
{
if(ScanMin==i)
{
HeadB=new Bucket;//建立桶的头结点
CurrentB=HeadB;//CurrentB为Bucket当前结点指针
CurrentB->ScanLine=ScanMin;
CurrentB->p=NULL;//没有连接边链表
CurrentB->next=NULL;
}
else//建立桶的其它结点
{
CurrentB->next=new Bucket;//新建一个桶结点
CurrentB=CurrentB->next;//使CurrentB指向新建的桶结点
CurrentB->ScanLine=i;
CurrentB->p=NULL;//没有连接边链表
CurrentB->next=NULL;
}
}
}
void CTestView::Et()//构造边表
{
for(int i=0;i<Number;i++)//访问每个顶点
{
CurrentB=HeadB;//从桶链表的头结点开始循环
int j=i+1;//边的第二个顶点,Point[i]和Point[j]构成边
if(j==Number) j=0;//保证多边形的闭合
if(Point[j]y>Point[i]y)//边在扫描线的上方
{
while(CurrentB->ScanLine!=Point[i]y)//在桶内寻找该边的yMin
{
CurrentB=CurrentB->next;//在桶内寻找该边的yMin
}
E[i]x=Point[i]x;//计算Aet表的值
E[i]yMax=Point[j]y;
E[i]k=double((Point[j]x-Point[i]x))/(Point[j]y-Point[i]y);//代表1/k
E[i]x1=Point[i]x;
E[i]y1=Point[i]y;
E[i]c1=Point[i]c;
E[i]x2=Point[j]x;
E[i]y2=Point[j]y;
E[i]c2=Point[j]c;
E[i]next=NULL;
CurrentE=CurrentB->p;//获得桶上链接边表的地址
if(CurrentE==NULL)//当前桶结点上没有链接边结点
{
CurrentE=&E[i];//赋边的起始地址
CurrentB->p=CurrentE;//第一个边结点直接连接到对应的桶中
}
else
{
while(CurrentE->next!=NULL)//如果当前边已连有边结点
{
CurrentE=CurrentE->next;//移动指针到当前边的最后一个边结点
}
CurrentE->next=&E[i];//把当前边接上去
}
}
if(Point[j]y<Point[i]y)//边在扫描线的下方
{
while(CurrentB->ScanLine!=Point[j]y)
{
CurrentB=CurrentB->next;
}
E[i]x=Point[j]x;
E[i]yMax=Point[i]y;
E[i]k=double((Point[i]x-Point[j]x))/(Point[i]y-Point[j]y);
E[i]x1=Point[i]x;
E[i]y1=Point[i]y;
E[i]c1=Point[i]c;
E[i]x2=Point[j]x;
E[i]y2=Point[j]y;
E[i]c2=Point[j]c;
E[i]next=NULL;
CurrentE=CurrentB->p;
if(CurrentE==NULL)
{
CurrentE=&E[i];
CurrentB->p=CurrentE;
}
else
{
while(CurrentE->next!=NULL)
{
CurrentE=CurrentE->next;
}
CurrentE->next=&E[i];
}
}
}
CurrentB=NULL;
CurrentE=NULL;
}
void CTestView::AddAet(Edge NewEdge)//边插入Aet表
{
T1=HeadE;
if(T1==NULL)//Aet表为空,将Aet表置为TEdge
{
T1=NewEdge;
HeadE=T1;
}
else
{
while(T1->next!=NULL)//Aet表不为空,将TEdge连在该边之后
{
T1=T1->next;
}
T1->next=NewEdge;
}
}
void CTestView::AetOrder()//对Aet表进行排序
{
T1=HeadE;
if(T1==NULL)
{
return;
}
if(T1->next==NULL)//如果该Aet表没有再连Aet表
{
return;//桶结点只有一条边,不需要排序
}
else
{
if(T1->next->x<T1->x)//Aet表按x值排序
{
T2=T1->next;
T1->next=T2->next;
T2->next=T1;
HeadE=T2;
}
T2=HeadE;
T1=HeadE->next;
while(T1->next!=NULL)//继续两两比较相连的Aet表的x值,进行排序
{
if(T1->next->x<T1->x)
{
T2->next=T1->next;
T1->next=T1->next->next;
T2->next->next=T1;
T2=T2->next;
}
else
{
T2=T1;
T1=T1->next;
}
}
}
}
MyRGB CTestView::Interpolation(int m,int m1,int m2,MyRGB &c1,MyRGB &c2)//线性插值
{
MyRGB I;
Ired=double(m-m2)/(m1-m2)c1red+double(m1-m)/(m1-m2)c2red;
Igreen=double(m-m2)/(m1-m2)c1green+double(m1-m)/(m1-m2)c2green;
Iblue=double(m-m2)/(m1-m2)c1blue+double(m1-m)/(m1-m2)c2blue;
return I;
}
BOOL CTestView::OnEraseBkgnd(CDC pDC)//设置背景函数
{
// TODO: Add your message handler code here and/or call default
CRect Rect;
pDC->GetClipBox(&Rect);
pDC->FillSolidRect(Rect,RGB(0,0,0));
//return CView::OnEraseBkgnd(pDC);
return true;
}
void CTestView::OnMENUPlay()//动画按钮函数
{
// TODO: Add your command handler code here
Play=PlayFALSE:TRUE;
if (Play)
//设置动画的时间步
SetTimer(1,15,NULL);
else
KillTimer(1);
}
void CTestView::OnTimer(UINT nIDEvent)//动画时间函数
{
// TODO: Add your message handler code here and/or call default
GetMaxX();GetMaxY();
Phi-=6;
Theta-=6;
InitParameter();
ReadPoint();
ReadFace();
SetCoord();
CView::OnTimer(nIDEvent);
}
void CTestView::OnUpdateMENUPlay(CCmdUI pCmdUI) //动画按钮状态函数
{
// TODO: Add your command update UI handler code here
if(Play)
pCmdUI ->SetCheck(TRUE);
else
pCmdUI ->SetCheck(FALSE);
}

中医舌诊时,舌根表肾、舌中表脾胃、舌边表肝胆、舌尖表心肺。观其色,白而色淡为寒症或气血亏虚;红色而鲜为热证或气血过旺。紫色为血淤气滞。舌尖红,可能肺热、气血过旺《和高热食物或某种营养素过量》、机械摩擦、外感邪热等有关。这是不懂中医的人小常识。中医不可用于急症的诊断,可作为养生调理或西医确诊后的治疗。借用QQ号的人回答,并非东方梦本人。


欢迎分享,转载请注明来源:内存溢出

原文地址: https://www.outofmemory.cn/yw/13411548.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-07-31
下一篇 2023-07-31

发表评论

登录后才能评论

评论列表(0条)

保存