
[C#]繪制函數圖像.可拖動,可縮放,可調整精度
欸嘿,這就是程序圖了,通過?標拖拽可以移動,?標滾輪可以縮放,右下?還可以選擇要繪制的函數.項?倉庫鏈接在?章末尾
基本原理:
Graphics繪圖,不?我說了吧?如果你不是很懂,留?,我會專門寫?篇?章來介紹Graphics.
帶?求值,沒啥難的.線是?個個點連起來的,也就是:
然后,標尺,也是?個個線唄,那個數字的話,就是這個:
填充?三?的話,就是這個:
關于優化:
?先是計算問題,保證僅僅計算需要顯?的區域,區域外的坐標不予以計算,以節省資源.
然后是閃屏問題,使?BufferedGraphics,既能解決閃屏問題,?不會像Bitmap緩沖那樣閃屏.
關于繪圖閃屏問題,?上有很多解決?案,最核?的,??是雙緩沖,也就是先將圖繪制到緩沖區,再將緩沖區的內容繪制到屏幕上.
實現雙緩沖有兩種?式,?就是通過創建?個Bitmap,將圖畫到Bitmap上,然后畫完之后,再將Bitmap畫到屏幕上
(age()),缺點是會造成撕裂問題.
第?種?式是BufferedGraphics,這是?個?Bitmap更好?的東西,不會造成撕裂.
封裝?下:
using;
using;
using;
using;
namespace
{
publicstaticclassFuncDraw
{
///
///根據數字坐標獲取像素位置
///
///
///
///
///
///
///
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));
}
///
///根據像素位置獲取數字坐標
///
///
///
///
///
///
///
///
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;
}
///
///畫函數圖像
///
///
///
///
///
///
///
///
///
publicstaticvoidDrawFunc(Func
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);
}
}
///
///畫?個坐標軸
///
///
///
///
///
///
///
///
///
///
///
///
///
publicstaticvoidDrawShaft(IEnumerable
RectangledrawArea,intxOfft,intyOfft,intbarLength,doublescale,booltext)
{
Action
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,感謝您對本站的認可!
本文鏈接:http://www.newhan.cn/zhishi/a/1678209312130111.html
版權聲明:本站內容均來自互聯網,僅供演示用,請勿用于商業和其他非法用途。如果侵犯了您的權益請與我們聯系,我們將在24小時內刪除。
本文word下載地址:xleft.doc
本文 PDF 下載地址:xleft.pdf
| 留言與評論(共有 0 條評論) |