xleft

更新时间:2023-03-08 01:15:12 阅读: 评论:0

小知识-世界残疾日

xleft
2023年3月8日发(作者:怎么做课件ppt)

[C#]绘制函数图像.可拖动,可缩放,可调整精度

欸嘿,这就是程序图了,通过⿏标拖拽可以移动,⿏标滚轮可以缩放,右下⾓还可以选择要绘制的函数.项⽬仓库链接在⽂章末尾

基本原理:

Graphics绘图,不⽤我说了吧?如果你不是很懂,留⾔,我会专门写⼀篇⽂章来介绍Graphics.

带⼊求值,没啥难的.线是⼀个个点连起来的,也就是:

然后,标尺,也是⼀个个线呗,那个数字的话,就是这个:

填充⼩三⾓的话,就是这个:

关于优化:

⾸先是计算问题,保证仅仅计算需要显⽰的区域,区域外的坐标不予以计算,以节省资源.

然后是闪屏问题,使⽤BufferedGraphics,既能解决闪屏问题,⼜不会像Bitmap缓冲那样闪屏.

关于绘图闪屏问题,⽹上有很多解决⽅案,最核⼼的,⽆⾮是双缓冲,也就是先将图绘制到缓冲区,再将缓冲区的内容绘制到屏幕上.

实现双缓冲有两种⽅式,⼀就是通过创建⼀个Bitmap,将图画到Bitmap上,然后画完之后,再将Bitmap画到屏幕上

(age()),缺点是会造成撕裂问题.

第⼆种⽅式是BufferedGraphics,这是⼀个⽐Bitmap更好⽤的东西,不会造成撕裂.

封装⼀下:

using;

using;

using;

using;

namespace

{

publicstaticclassFuncDraw

{

///

///根据数字坐标获取像素位置

///

///x坐标

///y坐标

///原点位置

///原点位置

///缩放

///像素位置

publicstaticPointGetPointFromCoords(doublexCoord,doubleyCoord,intxOfft,intyOfft,doublescale)

{

returnnewPoint((int)(xCoord*scale+xOfft),(int)(-yCoord*scale+yOfft));

}

///

///

///

///数字坐标

///原点位置

///缩放

///像素位置

publicstaticPointGetPointFromCoords(PointFcoords,Pointofft,doublescale)

{

returnnewPoint((int)(coords.X*scale+offt.X),(int)(-coords.Y*scale+offt.Y));

}

///

///根据像素位置获取数字坐标

///

///⽔平位置

///竖直位置

///原点位置

///原点位置

///缩放

///输出:数字X坐标

///输出:数字Y坐标

publicstaticvoidGetCoordsFromPoint(intx,inty,intxOfft,intyOfft,doublescale,outdoublexCoord,outdoubleyCoord)

{

xCoord=(x-xOfft)/scale;

yCoord=-((y-yOfft)/scale);

return;

}

///

///根据像素长度返回数字

///

///像素长度

///缩放

///数字

publicstaticdoubleGetNumberFromPixel(intlength,doublescale)

{

returnlength/scale;

}

///

///根据数字来获取它距离原点的像素长度

///

///数字

///缩放

///像素长度

publicstaticdoubleGetPixelFromNumber(intnumber,doublescale)

{

returnnumber*scale;

}

///

///画函数图像

///

///要画的函数

///X的取值

///绘图Graphics

///画线所⽤的Pen

///画函数的区域

///原点的位置

///原点的位置

///缩放参数

publicstaticvoidDrawFunc(Funcfunc,IEnumerableinputs,Graphicsgraphics,Penpen,RectangledrawArea,intxOfft,i

ntyOfft,doublescale)

{

double[]nums=y();

Point[]coords=newPoint[];

intdrawAreaLeft=drawArea.X,

drawAreaRight=drawAreaLeft+,

drawAreaTop=drawArea.Y,

drawAreaBottom=drawAreaTop+;

doubley;

for(inti=0,len=;i

拆箱,所以这样效率⾼⼀些

{

y=(nums[i]);

coords[i]=GetPointFromCoords(nums[i],y,xOfft,yOfft,scale);

}

boolpoint1xIn1,

point1xIn2,

point1yIn1,

point1yIn2,

point2xIn1,

point2xIn2,

point2yIn1,

point2yIn2;

for(inti=1,len=;i

{

Pointpoint1=coords[i-1];

Pointpoint2=coords[i];

point1xIn1=point1.X>=drawAreaLeft;

point1xIn2=point1.X<=drawAreaRight;

point1yIn1=point1.Y>=drawAreaTop;

point1yIn2=point1.Y<=drawAreaBottom;

point2xIn1=point2.X>=drawAreaLeft;

point2xIn2=point2.X<=drawAreaRight;

point2yIn1=point2.Y>=drawAreaTop;

point2yIn2=point2.Y<=drawAreaBottom;

if((!(point1xIn1&&point2xIn1))||(!(point1xIn2&&point2xIn2))||(!(point1yIn1&&point2yIn1))||(!(point1yIn2&&point2yIn2)))

continue;

if(!point1xIn1)

point1=newPoint(drawAreaLeft,(int)(point1.Y+(point2.Y-point1.Y)*((double)drawAreaLeft-point1.X)/(point2.X-point1.X)));//这⾥是

有⼀些奇妙优化的,不要删去.否则将导致某些函数⽆法绘制.

elif(!point2xIn1)

point2=newPoint(drawAreaLeft,(int)(point2.Y+(point1.Y-point2.Y)*((double)drawAreaLeft-point2.X)/(point1.X-point2.X)));

if(!point1xIn2)

point1=newPoint(drawAreaRight,(int)(point2.Y+(point1.Y-point2.Y)*((double)drawAreaRight-point2.X)/(point1.X-point2.X)));

elif(!point2xIn2)

point2=newPoint(drawAreaRight,(int)(point1.Y+(point2.Y-point1.Y)*((double)drawAreaRight-point1.X)/(point2.X-point1.X)));

if(!point1yIn1)

point1=newPoint((int)(point1.X+(point2.X-point1.X)*((double)drawAreaTop-point1.Y)/(point2.Y-point1.Y)),drawAreaTop);

elif(!point2yIn1)

point2=newPoint((int)(point2.X+(point1.X-point2.X)*((double)drawAreaTop-point2.Y)/(point1.Y-point2.Y)),drawAreaTop);

if(!point1yIn2)

point1=newPoint((int)(point2.X+(point1.X-point2.X)*((double)drawAreaBottom-point2.Y)/(point1.Y-point2.Y)),drawAreaBottom);

elif(!point2yIn2)

point2=newPoint((int)(point1.X+(point2.X-point1.X)*((double)drawAreaBottom-point1.Y)/(point2.Y-point1.Y)),drawAreaBottom);

ne(pen,point1,point2);

}

}

///

///画⼀个坐标轴

///

///x轴要画的数

///y轴要画的数

///绘图Graphics

///填充坐标轴三⾓所使⽤的Brush

///画坐标轴所使⽤的Pen

///画坐标数字所使⽤的Font

///画坐标轴的区域

///原点的位置

///远点的位置

///坐标轴上⼩竖线的长度

///缩放参数

///是否绘出数字

publicstaticvoidDrawShaft(IEnumerablexNumbers,IEnumerableyNumbers,Graphicsgraphics,Brushbrush,Penpen,Fontfont,

RectangledrawArea,intxOfft,intyOfft,intbarLength,doublescale,booltext)

{

ActiondrawText;

if(text)

drawText=(point,num)=>ring(ng("F2"),font,brush,point);//使⽤委托,那么接下来就不需要进⾏多余的对text的

判断,⽽直接Invoke就⼻亍

el

drawText=(point,num)=>{};

Point

yTop=newPoint(xOfft,drawArea.Y),

yBottom=newPoint(xOfft,drawArea.Y+),//确认轴的位置

xLeft=newPoint(drawArea.X,yOfft),

xRight=newPoint(drawArea.X+,yOfft);

ne(pen,yTop,yBottom);//画轴

ne(pen,xLeft,xRight);

inttriangleHeight=(int)((/3)*barLength);//坐标轴末端⼩三⾓的⾼度

Point[]

triangle1=newPoint[]{yTop,newPoint(yTop.X-barLength,yTop.Y+triangleHeight),newPoint(yTop.X+barLength,yTop.Y+triangleHeight)

},

triangle2=newPoint[]{xRight,newPoint(xRight.X-triangleHeight,xRight.Y+barLength),newPoint(xRight.X-triangleHeight,xRight.Y-barLe

ngth)};

lygon(brush,triangle1);//画三⾓

lygon(brush,triangle2);

foreach(doublexinxNumbers)

{

PointnumBa=GetPointFromCoords(x,0,xOfft,yOfft,scale);

PointnumEnd=newPoint(numBa.X,numBa.Y-barLength);

ne(pen,numBa,numEnd);//画x轴数

drawText(numBa,x);

drawText(numBa,x);

}

foreach(doubleyinyNumbers)

{

PointnumBa=GetPointFromCoords(0,y,xOfft,yOfft,scale);

PointnumEnd=newPoint(numBa.X+barLength,numBa.Y);

ne(pen,numBa,numEnd);//画y轴数

drawText(numBa,y);

}

}

}

}

注意事项:

Graphics在绘制某些超级远的东西时,例如这个坐标时(2147483647,2147483647),总之就是⾮常⼤,那可能会不能绘制,报

Overflow异常(已解决)

还有⼀些要⽤的内容:

CSDN⽂章:

CSDN⽂章:

更新记录:

最新版本已经⽀持⾃定义函数表达式

项⽬:

项⽬仓库:

本文发布于:2023-03-08 01:15:11,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/zhishi/a/1678209312130111.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

本文word下载地址:xleft.doc

本文 PDF 下载地址:xleft.pdf

上一篇:党组会
下一篇:返回列表
标签:xleft
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 实用文体写作网旗下知识大全大全栏目是一个全百科类宝库! 优秀范文|法律文书|专利查询|