图表之折线图

最近项目新增一个图表数据查看的。

效果图如下

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));
            }

效果图如下 再调整下线颜色和宽度。就差不多了。

在这里插入图片描述

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