`

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

阅读更多

年风向/风能玫瑰图如下所示:一个坐标轴及四个同心团,在同心团分16个区间画弧。


月风向/风能玫瑰图如下所示:
相当于在一个画板中画12个年风向/风能玫瑰图。


代码如下:
DrawWindRoseChartImpl.java代码如下:

 

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代码如下:

 

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;
}
  • 大小: 8.2 KB
  • 大小: 42 KB
分享到:
评论
5 楼 wting 2010-12-24  
看不懂图的意思,不过单纯画线懂几何就行了,嘿嘿。
4 楼 ryxxlong 2010-12-24  
Illum 写道
非常好的分享,风向玫瑰图的用途很广。投个精华



非学感谢,终于来了个知道玫瑰图的了
我分享出来就是希望能帮到那些用到玫瑰图的人
3 楼 Illum 2010-12-23  
非常好的分享,风向玫瑰图的用途很广。投个精华
2 楼 ryxxlong 2010-12-22  
苍山洱海 写道
what's this?

风电场项目中经常要用到的图例,如果有哪位兄弟有做类似项目的话,应该会有点帮助!
1 楼 ryxxlong 2010-12-22  
<p>如果画月风向/风能玫瑰图时,如果不一次性画十二图,还是只画那些有数据的月份的图,代码如下:</p>
<p>
</p>
<pre name="code" class="java">public BufferedImage drawMonthWindRose( int width,
Map&lt;Integer, Map&lt;Integer, Double&gt;&gt; map , RoseChartTypeEnum chartType) throws Exception {
int size = map.size();
//月风向玫瑰图每行画3个小玫瑰图,除3计算行数
int rowCount = size % 3 == 0 ? size /3 : (size / 3 + 1);
int colCount = size &gt;= 3 ? 3 : size;
//如果行数刚好也是3的话,则总图的宽与高相等,高加上edgSpace用来写上图片的title
int height = (rowCount % 3 == 0 ? width : width / 3 * rowCount) + edgSpace;
width = size &gt;= 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&lt;Integer, Map&lt;Integer, Double&gt;&gt; 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;
}</pre>
 代码写得不怎么样,希望大家谅解。
<p> </p>

相关推荐

    JAVA AWT学习手册

    AWT(Abstract Window Toolkit),即抽象窗口工具包,是Java API为Java程序提供的建立图形用户界面的基本工具集,AWT可以用于Java Application和Java Applet的图形用户界面的创建。 AWT工具集简介 AWT工具集是Java ...

    awt包java Android

    awt包java Android awt包java Android awt包java Android awt包java Android awt包java Android awt包java Android awt包java Android awt包java Android awt包java Android awt包java Android awt包java Android ...

    java心型99朵玫瑰程序

    1. 图像处理:程序中的“50.gif”可能是一个静态的心形图像,用于展示玫瑰花的图形。在Java中,可以使用`java.awt.Image`类和`javax.imageio.ImageIO`类来读取、加载和显示图像。通过`Graphics2D`类,开发者可以进行...

    awt.rar_awt_java awt_java绘图

    Java AWT(Abstract Window Toolkit)是Java平台早期的图形用户界面(GUI)工具包,它为开发者提供了构建桌面应用程序的基本组件,如按钮、文本框、菜单等,以及用于在屏幕上绘制图形的能力。这个"awt.rar"压缩包...

    Java的AWT包.pdf

    Swing是建立在AWT之上的,它使用纯Java实现,提供了更多的组件和更现代的外观。Swing的组件被称为轻量级组件,因为它们不依赖于操作系统,而AWT的组件被称为重量级组件,它们与操作系统紧密集成。Swing的许多组件,...

    java awt应用控件

    Java AWT(Abstract Window Toolkit)是Java平台早期的图形用户界面(GUI)工具包,它提供了构建和控制GUI应用程序的基本组件。AWT组件是Java语言中的原始GUI元素,包括按钮、文本框、滚动条等。这些组件使得开发者...

    awt.rar_awt_java awt_java 画图

    在标题"awt.rar_awt_java awt_java 画图"中,我们可以推测这个压缩包可能包含了关于使用AWT进行图形绘制的示例代码或教程。在描述中提到的"如果好看大家多支持啊这是一个具有智能的画图软件啊",这暗示了压缩包可能...

    java 图形界面 java awt swt swing gui

    Java图形用户界面(GUI,Graphical User Interface)是Java编程中的一个重要组成部分,它允许开发者创建交互式的、具有丰富视觉效果的应用程序。在Java中,有三个主要的GUI工具包:AWT(Abstract Window Toolkit),...

    JAVA 程序 源代码 import java.applet.*;import java.awt.*

    总结来说,这段源代码可能涉及一个使用Java AWT库创建GUI的Applet程序,包括图形用户界面的构建、事件处理以及可能的图形绘制。然而,由于Applet的过时,开发者现在可能更倾向于使用JavaFX或者Web技术(如HTML5、...

    Java AWT组件综合练习

    在Java AWT中,开发者可以构建丰富的交互式应用程序。本综合练习旨在帮助你深入理解和熟练运用AWT组件,包括List、Choice、Button以及TextArea。 首先,我们来看`List`组件。`List`是用来显示一系列可选择项的控件...

    Java-AWT

    Java AWT(Abstract Window Toolkit)是Java平台早期的图形用户界面(GUI)工具包,它为开发者提供了构建桌面应用程序的基本组件,如按钮、文本框、菜单等。在Java的早期版本中,AWT是GUI编程的主要框架,但现在已经...

    Java AWT画图

    总之,Java AWT提供了一套完整的图形绘制机制,让开发者能够在Java程序中创建出丰富的可视化界面。对于初学者来说,掌握AWT的绘图技术是理解GUI编程和Java图形处理的基础,同时也为后续学习更先进的Swing和JavaFX库...

    java的awt计算器

    本项目是一个使用Java AWT库构建的简易图形界面计算器。AWT(Abstract Window Toolkit)是Java平台早期提供的用于创建GUI应用程序的一套API。它允许开发者创建窗口、按钮、文本框等组件,并为这些组件添加事件监听器...

    使用Java AWT和Swing实现的简单计算器

    Java AWT(Abstract Window Toolkit)和Swing是Java平台上的两个图形用户界面(GUI)工具包,用于构建桌面应用程序。本项目"使用Java AWT和Swing实现的简单计算器"展示了如何利用这两个库创建一个基本的计算器应用。...

    awt框架图片及代码示例

    提及GWT(Google Web Toolkit),这是一个允许开发者使用Java编写前端应用程序的工具。它将Java代码编译成JavaScript,以便在浏览器中运行。GWT具有丰富的组件库和强大的数据绑定机制,尽管它的代码风格与AWT相似,...

    用java awt组件写的tcp文件传送和接收程序

    Java AWT(Abstract Window Toolkit)是Java早期的图形用户界面(GUI)库,它提供了创建窗口、按钮、文本框等基本组件的能力。TCP(Transmission Control Protocol)是一种面向连接的、可靠的传输层协议,广泛用于...

    java awt 事件处理

    Java AWT(Abstract Window Toolkit)事件处理是Java GUI编程中的核心组成部分,它允许用户与图形用户界面中的组件进行交互。在Java中,事件处理主要涉及事件源、事件、事件监听器和事件处理方法这四个关键概念。 ...

    java awt记事本

    在“java awt记事本”项目中,开发者用AWT库构建了一个类似Windows XP记事本的应用程序,提供了基本的文本编辑功能。下面将详细介绍AWT库以及如何利用它来实现一个简单的记事本应用。 1. **AWT组件**: - `Frame`:...

Global site tag (gtag.js) - Google Analytics