// SVG円グラフへの変換モジュール // Copyright (c) 2000 JUSTSYSTEM Corporation import java.io.*; import org.w3c.dom.*; public class SvgCircleGraph { public static final String nameSpaceURI = "http://www.myDomain/svg/cg"; public void Transform( Document doc ) { NodeList nodeList = null; nodeList = doc.getElementsByTagNameNS( nameSpaceURI, "circle" ); int nodeCount = nodeList.getLength(); for( int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++ ) { Circle( (Element)(nodeList.item( nodeIndex )), doc ); } } protected void Circle( Element circle, Document doc ) { Node parent = circle.getParentNode(); StringBuffer move = new StringBuffer(); // 中心点・半径の取得 int cx = Integer.parseInt( circle.getAttribute( "cx" ) ); int cy = Integer.parseInt( circle.getAttribute( "cy" ) ); int r = Integer.parseInt( circle.getAttribute( "r" ) ); // 初期開始点 int x0 = cx; int y0 = cy-r; // 開始点 int x = x0; int y = y0; // 各扇形の描画 NodeList arcList = circle.getElementsByTagNameNS( nameSpaceURI, "arc" ); int arcCount = arcList.getLength(); double angleSum = 0; for( int arcIndex = 0; arcIndex < arcCount; arcIndex++ ) { StringBuffer path = new StringBuffer(); // 円の中心への移動 path.append( "M"+Integer.toString( cx )+","+Integer.toString( cy )+" " ); // 開始点(絶対座標)へ線を引く path.append( "L"+Integer.toString( x )+","+Integer.toString( y )+" " ); Element arc = (Element)(arcList.item(arcIndex)); String angleStr = arc.getAttribute( "angle" ); double angle = 0; if( angleStr != null && angleStr.length() > 0 ) { angle = Integer.parseInt( arc.getAttribute( "angle" ) ); // 角度 } else { angle = 360-angleSum; // 指定されていなければ残り全部と考える。 } String color = arc.getAttribute( "color" ); // 色 angleSum += angle; // 開始点の、初期開始点からの相対座標を求める int sx = x - x0; int sy = y - y0; // 終了点の、初期開始点からの相対座標を求める int ex = 0, ey = 0; ex = (int)(r * Math.sin( Math.toRadians( angleSum ) )); ey = (int)(r * ( 1 - Math.cos( Math.toRadians( angleSum ) ) )); // 終了点を、開始点からの相対座標に変換する int rex = ex-sx; int rey = ey-sy; // 開始点と終了点が等しい場合は円を描く if( rex == 0 && rey == 0 && (angle > 180 || angle < -180) ) { Node circleNode = doc.createElement( "circle" ); parent.appendChild( circleNode ); ((Element)circleNode).setAttribute( "cx", Integer.toString( cx ) ); ((Element)circleNode).setAttribute( "cy", Integer.toString( cy ) ); ((Element)circleNode).setAttribute( "r", Integer.toString( r ) ); ((Element)circleNode).setAttribute( "style", "fill:"+color ); continue; // 開始点は変わらない。 } // それ以外は中心点からの線・弧・閉じる線を描く // 角度が180度未満なら String largeArcFlag = angle < 180 ? "0" : "1"; path.append( "a"+Integer.toString(r)+","+Integer.toString(r)+" 0 "+largeArcFlag+",1 "+Integer.toString(rex)+","+Integer.toString(rey)+" z" ); // 新たなノードの作成 Node pathNode = doc.createElement( "path" ); parent.appendChild( pathNode ); ((Element)pathNode).setAttribute( "d", path.toString() ); ((Element)pathNode).setAttribute( "style", "fill:"+color ); // 開始位置の更新 x += rex; y += rey; } // 元要素(circle)の削除 parent.removeChild( circle ); } }