圖表之折線圖

最近項目新增一個圖表數據查看的。

效果圖如下

Image text

各個折線點x,y點座標很好計算。不好畫的是如何讓這個折線不穿過這個空心圓

如果折線穿過空心圓,則變成下面這個樣子

Image text

折線點畫圓沒錯,但是直接連接折線點肯定和圓有相交,但是這又是個空心圓,如果是實心圓,則先畫線,再畫圓就可以直接覆蓋在上面。but 。。產品就是這麼虐心,搞個空心圓。。so。實現起來難度就大那麼一丟丟了。

既然不能直接連接圓中心,那就是需計算連接圓的那個點。

![Image text](3.png在這裏插入圖片描述

現把兩個圓心座標(x1,y1),(x2,y2),兩個中心點連接的線和圓1交點(dx1,dy1),和圓2的交點(dx2,dy2).顯然。我們不能直接連接(x1,y1)到(x2,y2).否則就是上面圖的效果。

我們要連接的就是(dx1,dy1)和(dx2,dy2).這樣不會畫到圓裏面,並且和圓相連。

要計算dx1,dy1,dx2,dy2.則需要利用三角函數。

如上圖。要計算dx1,dy1,我們已經知道圓的半徑r,如果再知道角度angle。

dx1 = r*cos(angle)+x1;
dy1 = y1-r*sin(angle) ;

現在的問題就變成如何計算angle角度了?

我們利用圓1和圓2的中心點的組成的直角三角形,則可以計算angle的正切值,

tan(angle)=(y1-y2)/(x2-x1);

因此角度

angle=atan((y1-y2)/(x2-x1));

同樣的dx2,和dy2也相應的

dx2 = (x2 - radius * Math.sin(angle2))  
dy2 = (y2 + radius * Math.cos(angle2))  

角度angle2的正切值

tan(angle2) = (x2-x1)/(y1-y2);  
angle2 =  atan(x2-x1)/(y1-y2); 

有同學就說了,angle2不就是90-angle嗎?,計算出angle,angle2不就相當於已經計算出來了。
這裏就不得不提Math裏面的那些關於三角函數的方法了。

我們直接打印
System.out.println(Math.sin(30))

輸出
-0.9880316240928618

咦?我們記得初中時三角函數sin30=0.5.這裏的-0.988xxxxx是個什麼東東
莫急,我們再看

我們再打印
System.out.println(Math.sin(Math.toRadians(30)))
輸出
0.49999999999999994
好像和0.5已經很接近了。因爲這裏計算的都是double類型。而double類型計算會丟失精度,
so 0.5就變成了0.49999999999
這就說明Math方法裏面的三角函數傳入的不是我們所認爲的角度,而是弧度,同樣的,反切函數計算出來的也不是角度,而是弧度。
如果上面我們利用90-angle.則我們還要把計算出來的angle轉換爲角度,然後再把90-角度,計算的時候還要轉換爲弧度。比如上計算angle2計算步驟更多。

			//這裏計算出來的是弧度
            double angle = Math.atan((y1-ly2)/(x2-lx1));

            float dx1 = (float) (x1 + radius*Math.cos(angle));
            float dy1 = (float) (y1 - radius*Math.sin(angle));
            double angle2 = Math.atan((x2-x1)/(y1-y2));
            float dx2=0,dy2=0;
            dx2 = (float) (x2 - radius * Math.sin(angle2));
            dy2 = (float) (y2 + radius * Math.cos(angle2));

至此。我們dx1,dx2,dy1,dy2全部都計算出來了,只要連接就可以。效果圖如下

在這裏插入圖片描述

後一個圓在前一個圓上方的好像已經
完美連接了,在下方的還是會穿過圓。需區分開來

			if (y1>y2) {
                 dx2 = (float) (x2 - radius * Math.sin(angle2));
                 dy2 = (float) (y2 + radius * Math.cos(angle2));
            }else{
                dx2 = (float) (x2 + radius * Math.sin(angle2));
                dy2 = (float) (y2 - radius * Math.cos(angle2));
            }

效果圖如下 再調整下線顏色和寬度。就差不多了。

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章