日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

GDI+绘制极坐标图(Polar Diagram)

發布時間:2024/4/11 编程问答 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 GDI+绘制极坐标图(Polar Diagram) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

這是一個簡單的GDI+的例子。講的是怎么從無到有繪制一個極坐標系,以及在此基礎上繪制數據圖。按照類似的思路,你可以畫出直角坐標系、對數直角系、外太空銀河系……
本文比較淺顯,覺得沒有幫助者請按組合鍵:Alt+F4,走好。
歡迎大家指教,歡迎改造,然后把代碼和圖貼在這里。大家一起看看能把自己的創造力激發到什么程度。
你可以通過本文學到怎么用非數學的方法解決數學問題,以此類推,就算碰到不懂的東西,也可以用自己懂的東西來代替。編程序,尤其是界面編程,只需要「看起來一樣」,更敬業點就「用起來一樣」。至于你要不要用什么jjyy的技術,的技巧,的手段,都是浮云。
不多說了。我們要做的東西最后效果是這樣的。

圖中曲線是一個天線方向圖,非常適合在極坐標下描繪。 文中是直接在窗體上繪制,你完全可以自行封裝到控件里,這樣用起來更加方便。
(正文開始) 寫在前面的話 做事情,一切以目標為出發點,倒著找過去,看有哪些方法技術資源,具體的方法技術手段都是次要的,只要能達到目的。 我不會多線程,如果你需要讓它運行在單獨的線程上,還請自己改造。(似乎還真有這樣ocd的人吧,哈哈)
目標設定 (下面是例子,不針對任何人物、事件、團體、星球) boss接到了一單生意,是幫某山寨廠做一個山寨手機天線的信號測試系統。其中,我分到的部分是做天線方向圖的顯示界面模塊。其實我懂個p的天線、方向圖之類的啊,于是boss告訴我,并強調:我不管你怎么做,總之要「看起來」像這樣。

ok,不管會不會,山寨是本行,拿著原版開始分析。
分析坐標系 說實話,數學那套玩意老早就還給老師了,現在要讓我玩坐標系這樣高深的東西。得虧哥們還有點印象,這樣圓不拉嘰的圖,一般用極坐標來畫是比較方便的。連上Wikipedia復習一下:極坐標是一個二維坐標系統。該坐標系統中的點由一個夾角和一段相對中心點——極點(相當于我們較為熟知的直角坐標系中的原點)的距離來表示。

嗯,很好,亂七八糟的,看不太懂啊,怎么辦。不管了,把這東西先放一遍,還是用山寨的方法解決。把boss給的那張圖拿來分析下,其實就是很多同心圓,和過圓心的輻條(借用自行車術語,雖然不知道正確的名字,就這么叫了吧)。
那么我只需要畫出同心圓,再畫輻條,就ok了吧。畫同心圓怎么畫呢?嗯,我可以這樣,從外面的大圓開始,用DrawEllipse()畫一個圓,然后收縮下半徑,再畫一個,如此這般……好了,有想法就行動,管他是nb方法還是sb方法,一直坐那zb,最后被炒了那才sb。
畫出同心圓的方法。

View Code // 畫圓private void drawCircles(Graphics g, Rectangle rect){// 圓的直徑等于繪圖區域最短邊float diameter = Math.Min(rect.Width, rect.Height);// 半徑float radius = diameter / 2;// 計算圓心(其實就是繪圖區域矩形中心)PointF center = new PointF(rect.X + rect.Width / 2,rect.Y + rect.Height / 2);// 畫幾個圓,先試試5個int count = 5;float diameterStep = diameter / count;float radiusStep = radius / count;// 生成圓的范圍RectangleF cirleRect = new RectangleF();cirleRect.X = center.X - radius;cirleRect.Y = center.Y - radius;cirleRect.Width = cirleRect.Height = diameter;// 畫同心圓for (int i = 0; i < count; i++){g.DrawEllipse(Pens.Gray, cirleRect);cirleRect.X += radiusStep;cirleRect.Y += radiusStep;cirleRect.Width -= diameterStep;cirleRect.Height -= diameterStep;}}

把這段代碼添加到Paint事件里,看看效果如何。

Good,效果還湊合,好像有點鋸齒哦,那我就把抗鋸齒打開,順手把文字抗鋸齒也打開。

1 2 ??? e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;??? // 圖形抗鋸齒 ??? e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias; // 文字抗鋸齒

接下來就要畫輻條了。那個線可不能就像圖里一個十字叉就完事了的,肯定要能自己設n條。想當初就是曾經思維簡單了沒有考慮到這種變數,被客戶和boss煩得天昏地暗。再也不會上當了。
輻條怎么畫呢,思考下,在草稿紙上畫畫先。
(以下都是中學數學,本人上了大學以后數學從沒及格過)

從少到多看看輻條的規律。啊,原來是這樣啊,我不一定非要把輻條看成穿過圓心的,我可以看成從圓心發出的n個射線,把圓切成了n個扇面,每個角度就是360°÷n。這樣那就好辦了,剛才我畫圓的時候已經算出來圓心位置了,只要再算出射線終點的坐標,就可以用DrawLine()畫線了。但是,射線終點又要怎么算呢,我可是要畫到GDI+里哦。

用黑色的筆畫出圓,紅色的畫出GDI+坐標系,那么就可以算出來終點在GDI+下的坐標。圓心(x0,y0)和r半徑剛才我已經算出來了,θ就是360/n?,F在所有參數都確定了,只要把圓心、半徑這幾個我需要使用的變量從畫圓的方法里拿出來大家用,我就可以開始寫畫輻條的方法了。

// 提出來公用float diameter, radius;PointF center;// 畫圓private void drawCircles(Graphics g, Rectangle rect){// (略) }// 輻射線private void drawCrosshair(Graphics g){int count = 8;if (count > 0){// 計算角度float angle = 0;float angleStep = 360 / count;PointF endPoint = new PointF();for (int i = 0; i < count; i++){// 得到終點endPoint = getPoint(angle);g.DrawLine(Pens.Gray, center, endPoint);angle += angleStep;angle %= 360;}}}// 計算終點private PointF getPoint(double angle){PointF pt = new PointF();pt.X = (float)(radius * Math.Cos(angle * Math.PI / 180) + center.X);pt.Y = (float)(radius * Math.Sin(angle * Math.PI / 180) + center.Y);return pt;}

把代碼加到Paint事件畫圓的后面,看看效果。

Yeah, baby,你太聽話了。
永不滿足的客戶·永不結束的工作
沒過半天,客戶就找到boss,要求在輻射線邊上加上角度數字。于是,我「義不容辭」的開始了新一輪改造。
說起加上數字,先前我已經得到了每個射線終點的坐標,那我直接在那坐標上DrawString()出角度數字就行了吧?嗯,在void drawCrosshair()里面先加上這句試試。

1 2 ??? // 畫角度值 ??? g.DrawString(angle.ToString("0") + "°", this.Font, Brushes.Gray, endPoint);


哦,賣糕的,問題多多哦。最下面的字跑出畫面了,上面的和左邊的字跑到圓圈里面,右邊的字也有點往里靠。改改試試看。先把畫圓的區域縮小一點,以便下面的標簽能顯示出來。

1 2 3 4 5 ??? //drawDiagramCircles(e.Graphics, this.ClientRectangle); ??? // 縮小點畫圓的區域 ??? Rectangle rect = this.ClientRectangle; ??? rect.Inflate(0, -20); ??? drawDiagramCircles(e.Graphics, rect);


ok,解決下一個問題。先思考下,什么情況下字會跑到圓里去:θ∈(90°, 270°)這個區間。那我就在這個區間畫文字的時候,把文字往左平移出去就行了。而270°時,我把文字往上移動試試看。在drawCrosshair()畫文字的地方。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 ??? // 把要畫的字符串提出來便于操作 ??? string angleString = angle.ToString("0") + "°"; ??? // 畫角度值,如果文字在90-270度區間內, ??? PointF textPoint = endPoint; ??? if (angle == 270) ??????? textPoint.Y -= TextRenderer.MeasureText(angleString, this.Font).Height; // 用TextRenderer測量字符串大小 ??? else if (angle < 270 && angle > 90) ??????? textPoint.X -= TextRenderer.MeasureText(angleString, this.Font).Width; ??? else ??????? textPoint.X += 8; // 隨便來點漂移 ??? g.DrawString(angleString, this.Font, Brushes.Gray, textPoint);

看看效果。

嗯哼,很好。(其實我覺得最好的辦法是分象限,比如第一象限就增加x、增加y,第二象限就增加x、減少y,第三象限減少x、減少y,第四象限減少x、增加y)
加入數據點
光畫一副坐標系那肯定是什么都干不了的,所以還有最重要的添加數據。所謂一個數據,就是包含了角度、數值的這樣一組數,比如天線對著某個方向(角度)的接收信號強度(數值)。角度很好理解,就是0到360°,然后轉圈。數值就要費點功夫了。用戶添加的數據,肯定是他們采集到的真實數據。這個數據,要映射到我這里做的坐標圖里面,使其同樣大小數值具有同樣的映射點,最小數值映射在圓心,最大數值映射在射線終點。這樣,所有的數據就都可以用這張圖來記錄了。下面使用最簡單的線性映射來設計。所謂線性映射,其實就是這樣。

所以,在全局變量里,我加入了數據范圍的上下限。(可以任意,只要max大于min,不能等于)

1 2 ??? float min = 0; ??? float max = 100;

為了便于后續操作,我決定把「角度 - 數值」這樣一組數據封裝在一個類里,然后用一個列表來存儲管理。

View Code public class PolarValue{float ang = 0;float val = 0;// 角度public float Angle{get { return ang; }set { ang = value; }}// 數值public float Value{get { return val; }set { val = value; }}public PolarValue(float angle, float value){this.ang = angle;this.val = value;}}// 數據列表public List<PolarValue> values = new List<PolarValue>();

現在我有了一組數據點,我需要做的就是把數據點映射到坐標圖上,如此遍歷每一點并連接之,就畫出了我所需要的方向圖。這就是映射的方法。

1 2 3 4 5 6 7 8 9 10 ??? private PointF getMappedPoint(PolarValue pv) ??? { ??????? // 計算映射在坐標圖中的半徑 ??????? float r = radius * (pv.Value - min) / (max - min); ??????? // 計算GDI+坐標 ??????? PointF pt = new PointF(); ??????? pt.X = (float)(r * Math.Cos(pv.Angle * Math.PI / 180) + center.X); ??????? pt.Y = (float)(r * Math.Sin(pv.Angle * Math.PI / 180) + center.Y); ??????? return pt; ??? }

寫到這里,我不由得回頭看了看剛才畫輻條時,為了計算輻條終點而寫的getPoint()方法。這兩個方法實在是太像了,唯一區別就是getMappedPoint()使用變化的數值,而getPoint()使用固定的數值(輻條終點可以認為是r=R,即value=max)?,F在合并這兩個方法,并修改相應調用的地方。

1 2 3 4 5 6 7 8 9 10 11 ??? // 合并后的映射方法 ??? private PointF getMappedPoint(float angle, float value) ??? { ??????? // 計算映射在坐標圖中的半徑 ??????? float r = radius * (value - min) / (max - min); ??????? // 計算GDI+坐標 ??????? PointF pt = new PointF(); ??????? pt.X = (float)(r * Math.Cos(angle * Math.PI / 180) + center.X); ??????? pt.Y = (float)(r * Math.Sin(angle * Math.PI / 180) + center.Y); ??????? return pt; ??? }

修改調用的地方

1 2 3 4 ??? // 在drawCrosshair()中 ??? // (略) ??? // 得到終點 ??? endPoint = getMappedPoint(angle, max);

現在可以一口氣把所有數據點畫出來了。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ??? private void drawPoints(Graphics g, List<PolarValue> pointList) ??? { ??????? // 計算下一點 ??????? PointF nextPt; ??????? for (int i = 0; i < pointList.Count; i++) ??????? { ??????????? if ((i + 1) < pointList.Count) ??????????????? nextPt = getMappedPoint(pointList[i + 1].Angle, pointList[i + 1].Value); ??????????? else ??????????????? nextPt = getMappedPoint(pointList[0].Angle, pointList[0].Value); ??????????? // 連接當前點和下一點 ??????????? g.DrawLine(Pens.Black, nextPt, getMappedPoint(pointList[i].Angle, pointList[i].Value)); ??????? } ??? }

隨便添加幾個數據,順便設置下圓圈數和輻條數,看看效果如何。
圓圈=3,輻條=4

圓圈=6,輻條=8


圓圈=9,輻條=16


一些變化
(以下內容為搞笑) 好了,我們做完了這個項目,送走了天線的客戶?,F在又來了一個游戲的客戶。他要求我們要制作一個類似FIFA或者實況的運動游戲,游戲里面要有一個運動員個人素質參數的查看界面。 我們要怎么做?重新做?不,就著上一個客戶的稍微那么改上一改,就像這樣。

轉自http://bbs.csdn.net/topics/390061628

總結

以上是生活随笔為你收集整理的GDI+绘制极坐标图(Polar Diagram)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 国产特黄aaaaa毛片 | 国产午夜精品无码一区二区 | 亚洲va在线∨a天堂va欧美va | 欧美超逼视频 | 69xav| 美女av网 | 春色av| 午夜av不卡 | 国产精品国产三级国产在线观看 | 日韩成人免费在线视频 | 日本v片 | 久热免费| 制服av网 | 免费高清成人 | 久久女女 | 黄色av小说在线观看 | av毛片网| 欧美精品91 | 中文字幕丝袜 | 最新天堂中文在线 | 日本三级片在线观看 | 日日摸夜夜添狠狠添久久精品成人 | 97在线公开视频 | 久一在线 | 日韩精品一二三区 | 91成人精品国产刺激国语对白 | 在线观看视频免费 | 免费看黄色网址 | 在线免费国产 | 亚洲欧美变态另类丝袜第一区 | 天天射寡妇射 | 国产一区二区视频在线 | 久久久久久亚洲中文字幕无码 | 亚洲综合丁香 | 91精品国产成人观看 | 天天躁日日躁狠狠躁av | 日韩黄色一级大片 | 毛片导航 | 国产精品久久久一区二区 | 超碰青青操 | 国产亚洲欧美日韩精品一区二区三区 | 天天撸天天射 | 久久国产精品网 | xxx国产在线观看 | 嫩草视频在线观看视频 | 欧美做爰啪啪xxxⅹ性 | 久久久精品免费视频 | 欧美一区二区性久久久 | 99久久夜色精品国产亚洲 | 中日韩黄色片 | 美女在线不卡 | 女人18毛片毛片毛片毛片区二 | www.4hu95.com四虎| 网站色| 亚洲av永久无码精品三区在线 | 香蕉视频在线观看视频 | 亚洲骚片 | 三级网站在线免费观看 | 四虎影视成人永久免费观看亚洲欧美 | 久久99国产精品久久99 | 免费在线黄网站 | 无码人妻精品一区二区三区温州 | 手机看片日韩欧美 | 国产又粗又猛又爽又黄 | 天天操免费视频 | 国产伊人自拍 | 色多多在线视频 | 中文字幕亚洲欧美 | 国产精品成人网站 | 韩国毛片基地 | 免费看片黄色 | 在线的av | 午夜成人免费电影 | 日韩一区二区高清 | 日韩精品免费播放 | 女子spa高潮呻吟抽搐 | 日本中文字幕在线观看视频 | 国产综合在线观看视频 | 五月婷婷开心 | 成人激情视频 | 二区三区视频 | 各种含道具高h调教1v1男男 | 真实偷拍激情啪啪对白 | 欧美丝袜一区二区 | 国产精品久久久久久久妇 | 污污网站在线观看视频 | 婷婷视频在线观看 | 国产综合无码一区二区色蜜蜜 | 久久久久久久久综合 | 高清成人 | 日本在线观看视频网站 | 欧美狂猛xxxxx乱大交3 | 国产精品九九九 | 国产精品丝袜黑色高跟鞋的设计特点 | 三年中文在线观看免费观看 | 一区精品视频 | 国产传媒在线观看 | 国产精品久久久久免费 | 国产在线观看免费 |