/**风向玫瑰图绘制Demo,默认使用16个风向
 * Created by yang_lei 2017/3/9.
 */
public class RoseChart extends View {
    //图标尺寸
    private int chart_size;

    private static Context context;

    //传入参数(各个风向百分比)
    private List<Float> percentageList;

    //风向标签
    private final String arrPerLabel[] = new String[]{"N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE", "S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW"};

    public RoseChart(Context context, AttributeSet attrs) {
        this(context, attrs, 0, null);
    }

    public RoseChart(Context context) {
        this(context, null);
    }

    /**(默认顺时针方向 N-->NNE-->NE-->ENE-->E.....)
     * @param context
     * @param attrs
     * @param defStyle
     * @param percentageList 风向百分比(默认顺时针方向从正北开始 N-->NNE-->NE-->ENE-->E.....两个方向之间数据不可缺省,数据末尾可以缺省)
     */
    public RoseChart(Context context, AttributeSet attrs, int defStyle, List<Float> percentageList) {
        super(context, attrs, defStyle);

        //初始化 风向百分比 集合
        this.percentageList = percentageList;

        this.context = context;

        /**
         * 获得我们所定义的自定义样式属性
         */
        TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.RoseChart, defStyle, 0);
        chart_size = a.getDimensionPixelSize(R.styleable.RoseChart_chart_size, 0);
        a.recycle();

    }

    @Override
    public void onDraw(Canvas canvas) {

        //画布背景
        canvas.drawColor(getResources().getColor(R.color.blue1));

        float cirX = getWidth() / 2;
        float cirY = getHeight() / 2;
        //计算绘制区域半径
        float radius = (float) (getHeight() * 0.42);//150;

        float arcLeft = cirX - radius;
        float arcTop = cirY - radius;
        float arcRight = cirX + radius;
        float arcBottom = cirY + radius;
        RectF arcRF0 = new RectF(arcLeft, arcTop, arcRight, arcBottom);

        //画笔初始化
        Paint PaintArc = new Paint();
        Paint PaintLabel = new Paint();//汉字标识
        PaintLabel.setColor(Color.WHITE);

        PaintLabel.setAntiAlias(true);
        PaintArc.setAntiAlias(true);
        //位置计算类
        XChartCalc xcalc = new XChartCalc();

        float Percentage = 0.0f;
        float CurrPer = 0.0f;//绘制 扇形区域 当前起始角度
        float CurrPerLabel = 0.0f;//绘制 风向标识 当前起始角度
        float NewRaidus = 0.0f;

        //计算每个扇区的圆心角度数
//        Percentage = 360 / arrPerLabel.length;
//        Percentage = (float) (Math.round(Percentage * 100)) / 100;
        Percentage = (float) round(360.00 / arrPerLabel.length, 2);

        //计算起始扇形区域角度(默认顺时针方向 N-->NNE-->NE-->ENE-->E.....填充扇区)
        CurrPer -= (float) round((Percentage - 4) / 2,2);
        CurrPerLabel -= (float) round((Percentage - 4) / 2,2);

        //绘制三个不同百分比同心圆
        PaintLabel.setStyle(Paint.Style.STROKE);
        PaintLabel.setStrokeCap(Paint.Cap.BUTT);
        canvas.drawCircle(cirX, cirY, radius, PaintLabel);
        canvas.drawCircle(cirX, cirY, (float) (radius * 0.75), PaintLabel);
        canvas.drawCircle(cirX, cirY, (float) (radius * 0.5), PaintLabel);
        canvas.drawCircle(cirX, cirY, (float) (radius * 0.25), PaintLabel);

        //绘制三个不同百分比标识
        //1,取出最大百分比
        Float max = Collections.max(percentageList);

        //绘制 风向 扇区
        for (int i = 0; i < percentageList.size(); i++) {
            //将百分比转换为新扇区的半径
            if (percentageList.get(i) == max) {
                NewRaidus = radius;
            } else {
                NewRaidus = radius * (percentageList.get(i) / max);
                NewRaidus = (float) (Math.round(NewRaidus * 100)) / 100;
            }

            float NewarcLeft = cirX - NewRaidus;
            float NewarcTop = cirY - NewRaidus;
            float NewarcRight = cirX + NewRaidus;
            float NewarcBottom = cirY + NewRaidus;
            RectF NewarcRF = new RectF(NewarcLeft, NewarcTop, NewarcRight, NewarcBottom);

            //分配颜色
//            PaintArc.setARGB(255, arrColorRgb[i][0], arrColorRgb[i][1], arrColorRgb[i][2]);
            PaintArc.setColor(getResources().getColor(R.color.yellow1));
            PaintArc.setAlpha(200);
            //在饼图中显示所占比例
            canvas.drawArc(NewarcRF, CurrPer - 90, Percentage - 4, true, PaintArc);

            //下次的起始角度
            CurrPer += Percentage;
        }

        //2,计算每个同心圆半径所占百分比
        float ThreePercentage = max / 4;
        ThreePercentage = (float) (Math.round(ThreePercentage * 100)) / 100;
        //3,绘制百分比标识
        PaintLabel.setColor(getResources().getColor(R.color.red1));
        PaintLabel.setTextSize(getResources().getDimension(R.dimen.RoseChart_persent));
        PaintLabel.setFakeBoldText(true);
        canvas.drawText(ThreePercentage + "%", cirX + (float) (radius * 0.18), cirY-18, PaintLabel);
        canvas.drawText(ThreePercentage * 2 + "%", cirX + (float) (radius * 0.43), cirY-18, PaintLabel);
        canvas.drawText(ThreePercentage * 3 + "%", cirX + (float) (radius * 0.68), cirY-18, PaintLabel);
        canvas.drawText(ThreePercentage * 4 + "%", cirX + (float) (radius * 0.93), cirY-18, PaintLabel);

        //绘制16个外圈风向标识
        for (int j = 0; j < arrPerLabel.length; j++) {
            //计算百分比标签
            xcalc.CalcArcEndPointXY(cirX, cirY, radius, (float) (CurrPerLabel + (Percentage - 4) * 0.5));
            //标识
            PaintLabel.setColor(Color.WHITE);
            PaintLabel.setTextSize(getResources().getDimension(R.dimen.RoseChart_direction));
            PaintLabel.setStrokeWidth((float) 0.8);
            canvas.drawText(arrPerLabel[j], xcalc.getPosX(), xcalc.getPosY(), PaintLabel);
            //下次的起始角度
            CurrPerLabel += Percentage;
        }

        PaintLabel.setColor(Color.BLACK);
        canvas.drawText("author:Yang_lei", cirX - radius, cirY + radius+context.getResources().getDimension(R.dimen.RoseChart_distance4), PaintLabel);

    }

    public static class XChartCalc {
        private static float x;
        private static float y;
        private static float r;

        public static void CalcArcEndPointXY(float cirX, float cirY, float radius, float Percentage) {
            double a = 2 * Math.PI * (Percentage / 360);
            if (Percentage >= 0 && Percentage < 130) {
                r = radius + context.getResources().getDimension(R.dimen.RoseChart_distance1);
            } else if (Percentage >= 130 && Percentage < 180) {
                r = radius + context.getResources().getDimension(R.dimen.RoseChart_distance2);
            } else if (Percentage == 180) {
                r = radius + context.getResources().getDimension(R.dimen.RoseChart_distance3);
            }  else if (Percentage > 180 && Percentage < 240) {
                r = radius + context.getResources().getDimension(R.dimen.RoseChart_distance4);
            } else if (Percentage > 240 && Percentage < 270) {
                r = radius + context.getResources().getDimension(R.dimen.RoseChart_distance5);
            } else if (Percentage == 270) {
                r = radius + context.getResources().getDimension(R.dimen.RoseChart_distance6);
            } else if (Percentage > 270 && Percentage < 300) {
                r = radius + context.getResources().getDimension(R.dimen.RoseChart_distance5);
            } else if (Percentage >= 300 && Percentage < 330) {
                r = radius + context.getResources().getDimension(R.dimen.RoseChart_distance6);
            } else if (Percentage >=  330 && Percentage < 350){
                r = radius + context.getResources().getDimension(R.dimen.RoseChart_distance3);
            }
            y = cirY - (float) (r * (Math.cos(a)));
            x = cirX + (float) (r * (Math.sin(a)));
        }

        public static float getPosX() {
            return x;
        }

        public static float getPosY() {
            return y;
        }
    }

    /**返回指定小数位数
     * @param v
     * @param scale
     * @return
     */
    public static double round(double v, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException(
                    "The   scale   must   be   a   positive   integer   or   zero");
        }
        BigDecimal b = new BigDecimal(Double.toString(v));
        BigDecimal one = new BigDecimal("1");
        return b.divide(one, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
    }
}

<resources>
    <dimen name="RoseChart_persent">10sp</dimen>
    <dimen name="RoseChart_direction">8sp</dimen>

    <dimen name="RoseChart_distance1">4dp</dimen>
    <dimen name="RoseChart_distance2">8dp</dimen>
    <dimen name="RoseChart_distance3">10dp</dimen>
    <dimen name="RoseChart_distance4">16dp</dimen>
    <dimen name="RoseChart_distance5">22dp</dimen>
    <dimen name="RoseChart_distance6">12dp</dimen>
</resources>

Android 风向玫瑰图绘制相关推荐

  1. 数据可视化 d3操作汇总(二):圆弧、饼图、环图、玫瑰图绘制

    一.圆环绘制 圆环绘制必须要先有一个弧生成器,必须提供的参数有起始角度和中止角度,例如: var dataset = { startAngle: 0 , endAngle: Math.PI * 0.7 ...

  2. 【源码】风向风速图绘制函数WindRose

    本函数实现方向强度直方图的创建,即"风向风速图". This function allows to create a Direction-intensity histogram, ...

  3. python绘制风向玫瑰图

    一.风向.流向角度和数学角关系. 1.数学角和风向角相互转换. 数学角向东为0°,按照逆时针旋转. 北风为0°,即指向南为0°,顺时针增加 数学角转风向角: (1)根据u,v获得数学角: (2)根据数 ...

  4. python 风玫瑰图_python之windrose风向玫瑰图的用法

    1.安装 A package is available and can be downloaded from PyPi and installed using: $ pip install windr ...

  5. matlab 风向玫瑰图

    clear all;close all;clc wind=xlsread('路径名/文件名.xlsx'); dir=wind(:,3); x=0:22.5:360; dir=dir*pi/180; x ...

  6. CAD简单制作风向(风速)玫瑰图

    背景: 风向玫瑰图(简称风玫瑰图)也叫风向频率玫瑰图,它是根据某一地区多年平均统计的各个风向的百分数值,并按一定比例绘制,一般多用8个或16个罗盘方位表示,由于形状酷似玫瑰花朵而得名. 玫瑰图上所表示 ...

  7. 使用java awt画风向玫瑰图及风能玫瑰图程序

    年风向/风能玫瑰图如下所示:一个坐标轴及四个同心团,在同心团分16个区间画弧. 月风向/风能玫瑰图如下所示: 相当于在一个画板中画12个年风向/风能玫瑰图. 代码如下: DrawWindRoseCha ...

  8. [译] 绘制路径:Android 中矢量图渲染

    原文地址:Draw a Path: Rendering Android VectorDrawables 原文作者:Nick Butcher 译文出自:掘金翻译计划 本文永久链接:github.com/ ...

  9. python+matplotlib绘制南丁格尔玫瑰图

    实验:绘制南丁格尔玫瑰图   本实验有一定难度,有人说matplotlib绘图和matlab大同小异,我看除了一些函数名相同之外,其他的像参数和使用方法很不一样.另外我不知道是不是在matlab中画玫 ...

最新文章

  1. linux系统桌面缺色,红旗系统如何用?
  2. 如何在使用新技术前评估其浏览器兼容性
  3. 好奇了好久的「对象」,就这?
  4. AI驱动洞察 智能数据营销时代迎来拐点
  5. c语言编程显示单月日历,任意年月日历输出-题解(C语言代码)
  6. 每日一皮:程序员和黑客的区别
  7. 各大高校女生节横幅来袭,个个都是段子手
  8. 设置log缓存_node多级缓存之redis缓存
  9. python matplotlib模块教程_Python中的Matplotlib模块入门教程
  10. linux查看端口被哪个服务占用的命令
  11. HDU 3333 Turing Tree(树状数组/主席树)
  12. 判断字符串为空 为null
  13. pop3协议解析及代码实现
  14. 【Java】 类和对象
  15. 地震观测仪器的历史和发展趋势(二)
  16. vivox9怎么和计算机共享,vivo手机怎么和笔记本电脑共享文件和网络
  17. 雷泰RAYR3I2MSCL3+高温红外测温仪的参数指标
  18. 基于51单片机的电子万年历的设计-源代码
  19. 云服务器-异地部署集群服务-Kubernetes(K8S)-网络篇
  20. 10004 - Bicoloring

热门文章

  1. arcpy强制升级pip,numpy
  2. 视频教程-Cocos2d-x 游戏开发详解-Cocos
  3. c语言 设置windows2008,调教Windows server 2008系统菜单
  4. 常用工具及常用网站总结
  5. ACCESS中实现密码输入值显示和掩盖的方法
  6. linux系统访问bitlocker分区,我将系统盘启用Bitlocker时,系统提示:“系统找不到指定的文件件”...
  7. 哈工大2018年秋计算机系统复习
  8. 使用selenium自动下载国科大(UCAS)课程资源
  9. 几个cve漏洞库查询网站-什么是CVE?常见漏洞和暴露列表概述
  10. 影响中国网民的十大软件