/*
* Project Info: http://jcae.sourceforge.net
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*
* (C) Copyright 2005, by EADS CRC
*/
package org.jcae.viewer3d;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import javax.media.j3d.*;
import javax.vecmath.Color3f;
import javax.vecmath.Point3f;
import com.sun.j3d.utils.picking.PickTool;
/**
* @author Jerome Robert
*
*/
public class MarkUtils
{
/** dummy object to indentify marks in the java3d tree */
public final static Object MARK_IDENTIFIER=new Object();
/** The inset between the text and the border if one is required. */
private static final int BORDER_INSETS = 2;
private static final Appearance LABEL_APPEARANCE=new Appearance();
public static class MarkID
{
private int domainID;
private int typeID;
/**
* @param domainID
* @param typeID
*/
public MarkID(int domainID, int typeID)
{
this.domainID = domainID;
this.typeID = typeID;
}
public int getDomainID()
{
return domainID;
}
public int getTypeID()
{
return typeID;
}
}
static
{
RenderingAttributes ra = new RenderingAttributes();
//ra.setDepthBufferEnable(false);
//ra.setDepthBufferWriteEnable(false);
LABEL_APPEARANCE.setRenderingAttributes(ra);
TransparencyAttributes ta = new TransparencyAttributes(
TransparencyAttributes.BLENDED, 0 );
LABEL_APPEARANCE.setTransparencyAttributes(ta);
}
/**
* @param domain
* @return
*/
static public Node createMarkNode(MarkDomain domain, int domainID)
{
Object[] marks=domain.getMarksTypes();
BranchGroup toReturn=new BranchGroup();
for(int i=0; i<marks.length; i++)
{
float[] coords=domain.getMarks(marks[i]);
if(coords==null) continue;
if(coords.length==0) continue;
Shape3D s3d;
if(marks[i] instanceof PointAttributes)
{
PointArray pa=new PointArray(coords.length/3, GeometryArray.COORDINATES);
pa.setCoordinates(0, coords);
Appearance a=new Appearance();
a.setPointAttributes((PointAttributes) marks[i]);
s3d=new Shape3D(pa, a);
}
else
{
s3d=createLabelShape(marks[i], coords);
s3d.setPickable(false);
toReturn.addChild(s3d);
PointArray pa=new PointArray(coords.length/3, GeometryArray.COORDINATES);
pa.setCoordinates(0, coords);
Appearance a=new Appearance();
a.setColoringAttributes(new ColoringAttributes(
new Color3f(Color.DARK_GRAY), ColoringAttributes.FASTEST));
s3d=new Shape3D(pa, a);
}
s3d.setCapability(Node.ALLOW_PICKABLE_WRITE);
PickTool.setCapabilities(s3d, PickTool.INTERSECT_FULL);
s3d.setUserData(new MarkID(domainID, i));
toReturn.addChild(s3d);
}
toReturn.setCapability(Node.ALLOW_PICKABLE_WRITE);
toReturn.setCapability(Group.ALLOW_CHILDREN_READ);
toReturn.setUserData(MARK_IDENTIFIER);
return toReturn;
}
/**
* @param object
* @param coords
* @return
*/
static protected Shape3D createLabelShape(Object object, float[] coords)
{
Shape3D toReturn=new Shape3D();
ImageComponent2D img;
if(object instanceof BufferedImage)
{
img=new ImageComponent2D(ImageComponent.FORMAT_RGBA, (BufferedImage) object);
}
else if(object instanceof RenderedImage)
{
img=new ImageComponent2D(ImageComponent.FORMAT_RGBA, (RenderedImage) object);
}
else
img=createImageComponent2D(object.toString(), null, null, null);
toReturn.setAppearance(LABEL_APPEARANCE);
for(int i=0; i<coords.length; i+=3)
{
Raster raster = new Raster(new Point3f(coords[i], coords[i+1], coords[i+2]),
Raster.RASTER_COLOR,
0,
0,
img.getWidth(),
img.getHeight(),
img,
null);
toReturn.addGeometry(raster);
}
return toReturn;
}
/**
* J3D.org Copyright (c) 2000 Java Source
* This source is licensed under the GNU LGPL v2.1
* Please read http://www.gnu.org/copyleft/lgpl.html for more information
*/
static protected ImageComponent2D createImageComponent2D(String label, Font font, Color borderColor, Color textColor)
{
// create a disposable 1x1 image so that we can fetch the font
// metrics associated with the font and text label. This will allow
// us to determine the real image size. This is kludgy, but I can't
// think of a better way of doing it!
BufferedImage tmp_img = new BufferedImage(1, 1,
BufferedImage.TYPE_INT_ARGB);
Graphics graphics = tmp_img.getGraphics();
FontMetrics fm;
if (font == null) fm = graphics.getFontMetrics();
else fm = graphics.getFontMetrics(font);
// now we have the metrics, let's work out how big the label is!
Rectangle2D dimensions = fm.getStringBounds(label, graphics);
graphics.dispose();
tmp_img.flush();
int width = (int) dimensions.getWidth()+5;
int height = (int) dimensions.getHeight()+5;
int ascent = fm.getMaxAscent();
if (borderColor != null)
{
width += BORDER_INSETS * 2 + 2;
height += BORDER_INSETS * 2 + 2;
}
tmp_img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
graphics = tmp_img.getGraphics();
if (borderColor != null)
{
graphics.setColor(borderColor);
graphics.drawRect(0, 0, width - 1, height - 1);
if (textColor == null) graphics.setColor(Color.white);
else graphics.setColor(textColor);
graphics.drawString(label, BORDER_INSETS + 1, ascent
+ BORDER_INSETS + 1);
} else
{
if (textColor == null) graphics.setColor(Color.white);
else graphics.setColor(textColor);
graphics.drawString(label, 0, ascent);
}
graphics.dispose();
ImageComponent2D img_comp = new ImageComponent2D(
ImageComponent.FORMAT_RGBA, tmp_img);
return img_comp;
}
/**
* Change the pickable status of a node created with createMarkNode.
* @param marks
*/
public static void setPickable(Node marks, boolean enable)
{
Group g=(Group) marks;
for(int i=0; i<g.numChildren(); i++)
{
Node n=g.getChild(i);
if(n.getUserData() instanceof MarkID)
{
n.setPickable(enable);
}
}
}
}