hierarchicalvertexdatarenderer.java

来自「Semantic Web Ontology Editor」· Java 代码 · 共 267 行

JAVA
267
字号
package org.mindswap.swoop.utils.graph.hierarchy;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;

/*
 * Created on Jul 17, 2005
 *
 * TODO To change the template for this generated file go to
 * Window - Preferences - Java - Code Style - Code Templates
 */

/**
 * @author Dave Wang
 *
 * TODO To change the template for this generated type comment go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
public class HierarchicalVertexDataRenderer implements SizeConstants
{
		
	//private static final Color classColor = new Color(128, 128, 128);
	//private static final Color selectedClassColor = new Color(255, 255, 225);
	//private static final Color highlightedColor   = new Color(128, 255, 255);
	
	private static HierarchicalVertexDataRenderer myInstance = null;
	
	public static HierarchicalVertexDataRenderer getInstance()
	{
		if (myInstance == null)
			return new HierarchicalVertexDataRenderer();
		else
			return myInstance;
	}
	
	private HierarchicalVertexDataRenderer()
	{}
	
	public void render( Graphics2D g2d, int x, int y, ClassTreeNode node)
	{
		int r = node.getSubTreeSize() * SizeConstants.unitSize;
		int numChildren = node.getNumChildren();
		
		// center of top class node (OWL:Thing )is the same as the ontology node
		//   this setting is important.  Subsequent mouse clicks relies on this to 
		//   find its children.
		node.setLocalCenterPoint(x, y);
		
		
		Color aColor = node.getFillColor();
		
		TreeNodeSizeInfo info = node.getChildNodeSizeInfo();
		for (int i = 0; i < numChildren; i++ )
		{
			ClassTreeNode child = node.getChild( i );
			render(g2d, x, y, r, child, numChildren - 1, i, info, aColor );
		}
	}
	
	// x,y are parent's center
	public void render( Graphics2D g2d, int x, int y, int radius, ClassTreeNode node, 
			            int numSiblings, int index, TreeNodeSizeInfo siblingInfo, 
						Color currentColor)
	{
		int r = node.getRadius();
		
		// if node is selected/highlighted, use those colors :)
		// if parent is 'selected' mark this child with selected color as well
		if ( currentColor != node.getColorScheme().getTreeNodeSelectFillColor( node ) )
			currentColor = node.getFillColor();
		g2d.setColor( currentColor );
		
		// if a node is listBrowsed, we get that color and overrides the others
		if ( node.getIsListBrowsed() )
			g2d.setColor( node.getFillColor() );
		
		AffineTransform old_xform = g2d.getTransform();
		
		double rotationAngle = 0;
		
		g2d.translate(x, y);
		
		
		AffineTransform localForm = node.getLocalXForm();
		// if nodes do not have localForm yet, compute it; otherwise, reuse it
		if ( localForm == null )
		{
			if (numSiblings == 0)
			{
				localForm = AffineTransform.getTranslateInstance(0,0); // no op transform to prevent NullPointerException
			}
			else
			{
				double increAngle = 360.00/(numSiblings + 1);
				double currentAngle = increAngle * index;
				if (siblingInfo.areSameSize) // all siblings are the same size.
				{
					rotationAngle = currentAngle * 2 * Math.PI / 360.00; 
					localForm    = AffineTransform.getRotateInstance( rotationAngle );
					AffineTransform translation = AffineTransform.getTranslateInstance( radius/2 , 0 );
					localForm.concatenate( translation );
					//g2d.transform( localForm );
				}
				else if ( index == 0) // largest node
				{
					rotationAngle = currentAngle * 2 * Math.PI / 360.00; 
					localForm    = AffineTransform.getRotateInstance( rotationAngle );
					AffineTransform translation = AffineTransform.getTranslateInstance( radius - r - (SizeConstants.unitSize/2), 0 );
					localForm.concatenate( translation );
					//g2d.transform( localForm );
				}
				else // has at least one sibling that's larger
				{
					if ( siblingInfo.isFirstChildBig ) // largest sibling dominates
					{
						ClassTreeNode bigSib = node.getParent().getChild(0);
						Point2D.Double bigSibCenter = bigSib.getLocalCenter();
						if ( index == 1)
						{
							double angle = 0;
							double increment = 10;
							boolean isFitting = false;
							while ( !isFitting )
							{
								rotationAngle = (90 + 20 + angle) * 2 * Math.PI / 360.0;
								localForm = AffineTransform.getTranslateInstance( bigSibCenter.x, bigSibCenter.y );
								localForm.concatenate( AffineTransform.getRotateInstance(rotationAngle));
								localForm.concatenate( AffineTransform.getTranslateInstance( node.getRadius() + bigSib.getRadius() + SizeConstants.unitSize, 0));
								angle = angle + increment;
								
								Point2D.Double origin = new Point2D.Double(0, 0);
								origin = (Point2D.Double)localForm.transform(origin, origin);
								double dist = Math.sqrt( Math.pow( origin.x, 2) + Math.pow(origin.y, 2) );
								if ( dist <= (radius - node.getRadius()))
									isFitting = true;
							}
							
							//g2d.transform( localForm );
							
						}
						else
						{		
							/* Computing the angle needed to rotate the current node by wrt the 
							 *  largest sibling.
							 * Computing the distance needed to translate the current node by
							 *  wrt to the center of the largest sibling.
							 *  
							 * The computed distance is the same distance between current node's
							 *  previous sibling to the largest sibling.
							 * The compute rotation gives a distance between the current node's
							 *  center and its previous sibling's center of (r1 + r2 + spacing*3),
							 *  where r1 is preivous sib's radius, r2 is current node's radius, and
							 *  spaceing = sizeConstants.unitSize/2
							 * 
							 * Computing theta relies on the fact that the triangle A-B-C 
							 *  (where A is the center of the largest sibling, B is the 
							 *  center of the previous sibling, and C is the center of the 
							 *  projected current node), is isoscele.  Splitting the triangle
							 *  by bisecting its lone odd angle into 2 right triangles, we use
							 *  arcsine to calculate the required angle.
							 * 
							 */
							ClassTreeNode prevSib = node.getParent().getChild( index - 1);
							int sibRadius  = prevSib.getRadius();
							int thisRadius = node.getRadius();
							int radiiSum = sibRadius + thisRadius + SizeConstants.unitSize/2 + SizeConstants.unitSize;
							Point2D.Double sibCenter = prevSib.getLocalCenter();
							double dCenterToSib = Math.sqrt( Math.pow(bigSibCenter.x - sibCenter.x, 2) + Math.pow(bigSibCenter.y - sibCenter.y, 2) );
							double theta = Math.asin( (radiiSum/2) / dCenterToSib) * 2;
									
							rotationAngle = theta + prevSib.getRotationAngle();
							
							localForm = AffineTransform.getTranslateInstance( bigSibCenter.x, bigSibCenter.y );
							localForm.concatenate( AffineTransform.getRotateInstance(rotationAngle));
							localForm.concatenate( AffineTransform.getTranslateInstance( dCenterToSib, 0));
							//g2d.transform( localForm );
						}
					}
					else // largest sibling isn't too dominating
					{
						ClassTreeNode prevSib = node.getParent().getChild( index - 1);
						int sibRadius  = prevSib.getRadius();
						int thisRadius = node.getRadius();
						int radiiSum = sibRadius + thisRadius + SizeConstants.unitSize/2;
						Point2D.Double sibCenter = prevSib.getLocalCenter();
						double dCenterToSib = Math.sqrt( Math.pow(sibCenter.x, 2) + Math.pow(sibCenter.y, 2) );
						double theta = Math.asin( (radiiSum/2) / dCenterToSib) * 2;
						
						rotationAngle = theta + prevSib.getRotationAngle();
						
						localForm    = AffineTransform.getRotateInstance( rotationAngle );
						AffineTransform translation = AffineTransform.getTranslateInstance( dCenterToSib, 0);
						localForm.concatenate( translation );
					}
				}
			}
			//System.out.println("Computed localXForm");
		}
		
		g2d.transform( localForm );
		g2d.fillOval( -r, -r, 2*r, 2*r );
		g2d.setColor( node.getOutlineColor() );
		g2d.drawOval( -r, -r, 2*r, 2*r );

		Point2D.Double origin = new Point2D.Double(0, 0);			
		Point2D.Double result = (Point2D.Double)localForm.transform( origin, origin);
		node.setLocalCenterPoint( result.x, result.y );
		node.setGlobalTransform( g2d.getTransform() );
		node.setRotationAngle( rotationAngle );
		node.setLocalXForm( localForm );
		
		double [] mat = new double [6];
		localForm.getMatrix( mat );
		
		int numChildren = node.getNumChildren();		
		//int maxChildRadius = getMaxChildRadius( node );
		TreeNodeSizeInfo info = node.getChildNodeSizeInfo();
		for (int i = 0; i < numChildren; i++)
		{
			ClassTreeNode childNode = node.getChild( i );
			render(g2d, 0, 0, r, childNode, numChildren - 1, i, info, currentColor );
		}
		g2d.setTransform( old_xform );
	}

	/*
	private TreeNodeSizeInfo getChildNodeSizeInfo( ClassTreeNode node)
	{
		int numChildren = node.getNumChildren();
		if (numChildren == 0)
			return null;
		int maxChildRadius = Integer.MIN_VALUE;
		ClassTreeNode largestNode = null;
		boolean isFirstTime = true;
		boolean areSameSize = true;
		boolean isFirstChildLarge = false;
		for (int i = 0; i < numChildren; i++ )
		{
			ClassTreeNode child = node.getChild( i );
			if ( i == 0 ) //largest node
			{
				if ( (2 * child.getRadius()) > (node.getRadius() * 0.75) )
					isFirstChildLarge = true;
			}
			int childsize = child.getRadius();
			if ((!isFirstTime) && ( maxChildRadius != childsize))
				areSameSize = false;
			if ( maxChildRadius < childsize)
			{
				maxChildRadius = childsize;
				largestNode = child;
			}
			if ( isFirstTime )
				isFirstTime = !isFirstTime;
		}
		TreeNodeSizeInfo info = new TreeNodeSizeInfo();
		info.areSameSize = areSameSize;
		info.maxRadius = maxChildRadius;
		info.myLargestNode = largestNode;
		info.isFirstChildBig = isFirstChildLarge;
		return info;
	}
	*/
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?