TA的每日心情 | 开心 2021-3-12 23:18 |
---|
签到天数: 2 天 [LV.1]初来乍到
|
年风向/风能玫瑰图如下所示:一个坐标轴及四个同心团,在同心团分16个区间画弧。

月风向/风能玫瑰图如下所示:
相当图。
代码如下:
DrawWindRoseChartImpl.java代码如下:
- import java.util.*;
- import java.awt.*;
- import java.awt.image.*;
- import java.awt.geom.*;
- import java.text.*;
- public class DrawWindRoseChartImpl implements IDrawWindRoseChart {
-
- private DecimalFormat df = new DecimalFormat("#00.00");
- private int circleNumber = 4; // 圆的圈数 = 4;
- private int space = 10; // 方向标注离图形的空隙
- private int edgSpace = 30; // 图形周边留出的空隙大小,此空隙大小必须至少等于3 * space
-
- public BufferedImage drawYearWindRose(int gWidth, Map< Integer, Double> map,
- RoseChartTypeEnum chartType) throws Exception {
- int gHeight = gWidth + edgSpace; // 加上edgSpace宽度用来写图形的标题
- BufferedImage image = new BufferedImage(gWidth, gHeight,
- BufferedImage.TYPE_INT_ARGB);
- Graphics2D g2 = image.createGraphics();
- String type = "";
- if (chartType == RoseChartTypeEnum.YEAR_WIND_DIRECTION)
- type = "风向";
- else if (chartType ==RoseChartTypeEnum.YEAR_WIND_POWER) {
- type = "风能";
- }else{
- throw new RuntimeException("此方法不能画所要求的风玫瑰图!");
- }
- String title = "年" + type + "玫瑰图";
- g2.setBackground(Color.WHITE);
- // 画板
- g2.fillRect(0, 0, gWidth, gHeight);
- // 基准点距离,当x,y坐标都为基准点距离时就是圆心
- int centerPoint = gWidth / 2;
- // 最大圆半径
- int maxRadius = gWidth / 2 - edgSpace;
- // 步长
- double step = maxRadius / circleNumber;
- g2.setColor(Color.BLACK);
- // 西方向在右边,标注会占距离,所以space*2
- g2.drawString("W", centerPoint - maxRadius - 2 * space, centerPoint);
- // 画x轴
- g2.drawLine(centerPoint - maxRadius, centerPoint, centerPoint
- + maxRadius, centerPoint);
- g2.drawString("E", centerPoint + maxRadius + space, centerPoint);
- g2.drawString("0", centerPoint, centerPoint - maxRadius - space);
- g2.drawString("N", centerPoint, centerPoint - maxRadius - 2 * space);
- // 画y轴
- g2.drawLine(centerPoint, centerPoint - maxRadius, centerPoint,
- centerPoint + maxRadius);
- // 南方向在下边,标注会占距离,所以space*2
- g2.drawString("180", centerPoint - space, centerPoint + maxRadius + 2
- * space);
- g2.drawString("S", centerPoint, centerPoint + maxRadius + 3 * space);
- g2.drawString(title, centerPoint - 3 * space, gHeight - space);
- //不管是否有数据,都必须把坐标及同心圆画上
- for (int i = 1; i <= circleNumber; i++) {
- // step * i即为所画当前圆的半径
- int radius = (int) Math.ceil(step * i) + 1;
- g2.drawOval(centerPoint - radius, centerPoint - radius, radius * 2,
- radius * 2);
- }
- // 只有当有数据时,才标注圆所代表的比例及画弧
- if (map != null && map.size() > 0) {
- // 最大比率
- double maxRation = Collections.max(map.values());
- // 标注比例
- for (int i = 1; i <= circleNumber; i++) {
- // step * i即为所画当前圆的半径
- int radius = (int) Math.ceil(step * i) + 1;
- int dis = (int) (Math.cos(Math.PI / 4) * radius);
- // 标注圆代表的比例数
- g2.drawString(df.format(maxRation / circleNumber * i * 100)
- + "%", centerPoint + dis, centerPoint - dis);
- }
- g2.setColor(Color.RED);
- double startAngle = 0.0;
- double arcAngle = -22.5;
- // 画弧
- for (Map.Entry< Integer, Double> entry : map.entrySet()) {
- double arcRadius = Math.rint(entry.getValue() / maxRation
- * maxRadius);
- int key = entry.getKey();
- // 即是第0风向区,-11.25~11.25
- // 因为awt画弧时0度点与风向玫瑰图的0度点相差90度,所以给画弧的开始点集体加上90度
- if (key == 0)
- startAngle = 90 + 11.25;
- else {
- double angle = -key * 22.5;
- startAngle = angle + 90;
- }
- Arc2D.Double arc = new Arc2D.Double(centerPoint - arcRadius,
- centerPoint - arcRadius, arcRadius * 2, arcRadius * 2,
- startAngle, arcAngle, Arc2D.PIE);
- // 使用awt画弧
- g2.draw(arc);
- }
- }
- g2.dispose();
- return image;
- }
-
- private void drawOneWindRose(Graphics2D g2, int xOffset, int yOffset,
- int gWidth, Map< Integer, Double> map, int month) throws Exception {
- String title = month + "月";
- // 同心圆圆心坐标
- int xCenter = xOffset + gWidth / 2;
- int yCenter = yOffset + gWidth / 2;
- // 最大圆半径
- int maxRadius = gWidth / 2 - edgSpace;
- // 步长
- double step = maxRadius / circleNumber;
- g2.setColor(Color.BLACK);
- // 西方向在右边,标注会占距离,所以space*2
- g2.drawString("W", xCenter - maxRadius - 2 * space, yCenter);
- // 画x轴
- g2.drawLine(xCenter - maxRadius, yCenter, xCenter + maxRadius, yCenter);
- g2.drawString("E", xCenter + maxRadius + space, yCenter);
- g2.drawString("0", xCenter, yCenter - maxRadius - space);
-
- g2.drawString("N", xCenter, yCenter - maxRadius - 2 * space);
- // 画y轴
- g2.drawLine(xCenter, yCenter - maxRadius, xCenter, yCenter + maxRadius);
- g2.drawString("180", xCenter - space, yCenter + maxRadius + 2 * space);
- g2.drawString("S", xCenter, yCenter + maxRadius + 3 * space);
- g2.drawString(title, xCenter + maxRadius, yCenter - maxRadius);
- //不管当月是否有数据,都必须把同心圆画上
- for (int i = 1; i <= circleNumber; i++) {
- // step * i即为所画当前圆的半径
- int radius = (int) Math.ceil(step * i) + 1;
- g2.drawOval(xCenter - radius, yCenter - radius, radius * 2,
- radius * 2);
- }
- // 只有当有数据时,才标注圆所代表的比例及画弧
- if (map != null && map.size() > 0) {
- // 最大比率
- double maxRation = Collections.max(map.values());
- // 标注比例
- for (int i = 1; i <= circleNumber; i++) {
- // step * i即为所画当前圆的半径
- int radius = (int) Math.ceil(step * i) + 1;
- int dis = (int) (Math.cos(Math.PI / 4) * radius);
- // 标注圆代表的比例数
- g2.drawString(df.format(maxRation / circleNumber * i * 100)
- + "%", xCenter + dis, yCenter - dis);
- }
- g2.setColor(Color.RED);
- double startAngle = 0.0;
- double arcAngle = -22.5;
- for (Map.Entry< Integer, Double> entry : map.entrySet()) {
- double arcRadius = Math.rint(entry.getValue() / maxRation
- * maxRadius);
- int key = entry.getKey();
- // 即是第0风向区,-11.25~11.25
- // 因为awt画弧时0度点与风向玫瑰图的0度点相差90度,所以给画弧的开始点集体加上90度
- if (key == 0)
- startAngle = 90 + 11.25;
- else {
- double angle = -key * 22.5;
- startAngle = angle + 90;
- }
- Arc2D.Double arc = new Arc2D.Double(xCenter - arcRadius,
- yCenter - arcRadius, arcRadius * 2, arcRadius * 2,
- startAngle, arcAngle, Arc2D.PIE);
- // 使用awt画弧
- g2.draw(arc);
- }
- }
- }
-
- public BufferedImage drawMonthWindRose(int width,
- Map< Integer, Map< Integer, Double>> map, RoseChartTypeEnum chartType)
- throws Exception {
- //不管有几个月的数据,都画12个图,分四行三列来显示
- //height加上edgSpace用来显示图片的标题
- int height = width * 4 / 3 + edgSpace;
- // 每个月的小玫瑰图所占的宽度,每行或每列的间距为space, 列数值最大为3列,所以只有四个间距。
- int gWidth = (width - space * 4) / 3;
- BufferedImage image = new BufferedImage(width, height,
- BufferedImage.TYPE_INT_ARGB);
- Graphics2D g2 = image.createGraphics();
- String type = "";
- if (chartType == RoseChartTypeEnum.MONTH_WIND_DIRECTION)
- type = "风向";
- else if (chartType == RoseChartTypeEnum.MONTH_WIND_POWER) {
- type = "风能";
- }else{
- throw new RuntimeException("此方法不能画所要求的风玫瑰图!");
- }
- String title = "各月的" + type + "玫瑰图";
- // 画板
- g2.fillRect(0, 0, width, height);
- int count = 0;
- int rowNo = 0;
- int colNo = 0;
- int xOffset = 0;
- int yOffset = 0;
- //不管是否有数据,都画12个图,每月一个图
- for(int i = 1; i <= 12; i++){
- rowNo = count / 3;
- colNo = count % 3;
- xOffset = colNo * (gWidth + space) + space;
- yOffset = rowNo * (gWidth + space) + space;
- Map< Integer, Double> dataMap = (map == null || map.size() == 0) ? null : map.get(i);
- drawOneWindRose(g2, xOffset, yOffset, gWidth, dataMap,
- i);
- count++;
- }
- g2.setColor(Color.BLACK);
- g2.drawString(title, width / 2 - 3 * space, height - 2 * space);
- g2.dispose();
- return image;
- }
-
- }
复制代码 RoseChartTypeEnum代码如下所示: public enum RoseChartTypeEnum {
YEAR_WIND_DIRECTION,YEAR_WIND_POWER,MONTH_WIND_DIRECTION,MONTH_WIND_POWER
}
接口 IDrawWindRoseChart代码如下:- import java.awt.image.*;
- import java.util.*;
- public interface IDrawWindRoseChart {
-
- /**画风向玫瑰图或风能玫瑰图,
- * @param gWidth : BufferedImage的宽度值,因为是画圆,所以只传入一个值,高度值gHeight也使用gWidth
- * @param map : 各扇区的数据集
- * @param chartTypeEnum : 所画玫瑰图的类型
- * @return
- */
- public BufferedImage drawMonthWindRose( int gWidth,
- Map< Integer, Map< Integer, Double>> map , RoseChartTypeEnum chartTypeEnum ) throws Exception;
- public BufferedImage drawYearWindRose( int gWidth,
- Map< Integer, Double> map ,RoseChartTypeEnum chartTypeEnum) throws Exception;
- }
复制代码 如果画月风向/风能玫瑰图时,如果不一次性画十二图,还是只画那些有数据的月份的图,代码如下:- public BufferedImage drawMonthWindRose( int width,
- Map< Integer, Map< Integer, Double>> map , RoseChartTypeEnum chartType) throws Exception {
- int size = map.size();
- //月风向玫瑰图每行画3个小玫瑰图,除3计算行数
- int rowCount = size % 3 == 0 ? size /3 : (size / 3 + 1);
- int colCount = size >= 3 ? 3 : size;
- //如果行数刚好也是3的话,则总图的宽与高相等,高加上edgSpace用来写上图片的title
- int height = (rowCount % 3 == 0 ? width : width / 3 * rowCount) + edgSpace;
- width = size >= 3 ? width : width / 3 * size;
- //每个月的小玫瑰图所占的宽度,每行或每列的间距为20, 列数值最大为3列。
- int gWidth = (width - space * (Math.max(rowCount, colCount) + 1)) / colCount;
- BufferedImage image = new BufferedImage(width , height ,
- BufferedImage.TYPE_INT_ARGB);
- Graphics2D g2 = image.createGraphics();
- String type = "";
- if(chartType == RoseChartTypeEnum.MONTH_WIND_DIRECTION )
- type = "风向";
- else if(chartType == RoseChartTypeEnum.MONTH_WIND_POWER){
- type = "风能";
- }
- String title = "各月的" + type + "玫瑰图";
- // 画板
- g2.fillRect(0, 0, width, height);
- int count = 0;
- int rowNo = 0;
- int colNo = 0;
- int xOffset = 0;
- int yOffset = 0;
- for(Map.Entry< Integer, Map< Integer, Double>> entry : map.entrySet()){
- rowNo = count / 3 ;
- colNo = count % 3 ;
- xOffset = colNo * (gWidth + space) + space;
- yOffset = rowNo * (gWidth + space) + space;
- drawOneWindRose(g2, xOffset, yOffset, gWidth, entry.getValue(), entry.getKey());
- count++;
- }
- g2.setColor(Color.BLACK);
- g2.drawString(title, width / 2 - 3 * space, height - 2 * space);
- g2.dispose();
- return image;
- }
复制代码
源码下载:http://file.javaxxz.com/2014/10/28/235544218.zip |
|