/*
* 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 2007, by EADS France
*/
package org.jcae.viewer3d.fd;
import java.awt.Color;
import java.util.*;
import java.util.logging.Logger;
import javax.media.j3d.*;
import javax.vecmath.Color3f;
import javax.vecmath.Point3d;
import javax.vecmath.Point3f;
import org.jcae.viewer3d.*;
import com.sun.j3d.utils.geometry.GeometryInfo;
import com.sun.j3d.utils.picking.PickIntersection;
/**
* The J3D node of this viewable has the following structure
*<pre>
* parentBranchGroup
* |
* +-domainBg
* |
* +-wire Shape3D (also in wires Collection)
* |
* +-slots Shape3D (also in slots Collection)
* |
* +-plate Shape3d (also in plates Collection)
* |
* +-plate wireframe Shape3d
*</pre>
* @author Jerome Robert
*
*/
public class ViewableFD extends ViewableAdaptor
{
private final static Logger LOGGER=Logger.getLogger(ViewableFD.class.getName());
public final static byte SELECT_PLATE=1;
private static final float zFactorAbs=Float.parseFloat(System.getProperty(
"javax.media.j3d.zFactorAbs", "20.0f"));
private static final float zFactorRel=Float.parseFloat(System.getProperty(
"javax.media.j3d.zFactorRel", "2.0f"));
private final static PolygonAttributes PLATE_POLYGON_ATTRIBUTE=new PolygonAttributes(
PolygonAttributes.POLYGON_FILL, PolygonAttributes.CULL_NONE,
3.0f * zFactorAbs, false, 2.0f * zFactorRel);
private final static PolygonAttributes BORDER_POLYGON_ATTRIBUTE=new PolygonAttributes(
PolygonAttributes.POLYGON_LINE, PolygonAttributes.CULL_NONE,
2.0f * zFactorAbs, false, zFactorRel);
private final static PolygonAttributes SELECT_POLYGON_ATTRIBUTE=new PolygonAttributes(
PolygonAttributes.POLYGON_FILL, PolygonAttributes.CULL_NONE,
zFactorAbs, false, zFactorRel);
private final static LineAttributes SLOT_ATTRIBUTE=new LineAttributes();
/**
* dummy object to make difference between plate Shape3D and wireframe
* plate Shape3D
*/
private final static Object PLATE_IDENTIFIER=new Object();
/**
* dummy object to make difference between solid Shape3D and wireframe
* solid Shape3D
*/
private final static Object SOLID_IDENTIFIER=new Object();
static
{
SLOT_ATTRIBUTE.setLinePattern(LineAttributes.PATTERN_USER_DEFINED);
SLOT_ATTRIBUTE.setPatternMask(0x5555);
SLOT_ATTRIBUTE.setLineWidth(2.0f);
}
/**
* Used to set a typed integer in the UserData field of a J3D Node
* Cannot use java.lang.Integer because it is final
*/
private static abstract class IntegerUserData
{
private int value;
public IntegerUserData(int value)
{
this.value=value;
}
public int getValue()
{
return value;
}
}
private static class WireDomainID extends IntegerUserData
{
public WireDomainID(int domainID)
{
super(domainID);
}
}
private static class SlotDomainID extends IntegerUserData
{
public SlotDomainID(int domainID)
{
super(domainID);
}
}
private static class XLineID extends IntegerUserData
{
public XLineID(int id)
{
super(id);
}
}
private static class SlotID extends IntegerUserData
{
private byte type;
public SlotID(int id, byte type)
{
super(id);
this.type=type;
}
public byte getType()
{
return type;
}
}
private static class YLineID extends IntegerUserData
{
public YLineID(int id)
{
super(id);
}
}
private static class ZLineID extends IntegerUserData
{
public ZLineID(int id)
{
super(id);
}
}
protected FDProvider provider;
protected BranchGroup parentBranchGroup=new BranchGroup();
private Shape3D selectedPlates;
private Shape3D selectedWires, selectedJunctions;
private SelectionManager selectionManager;
private Map<Integer, BranchGroup> domainToBranchGroup=new HashMap<Integer, BranchGroup>();
private Collection<Shape3D> plates=new ArrayList<Shape3D>();
private Collection<Shape3D> wires=new ArrayList<Shape3D>();
private Collection<Shape3D> slots=new ArrayList<Shape3D>();
private Collection<Shape3D> solids=new ArrayList<Shape3D>();
private Collection<Node> marks=new ArrayList<Node>();
private boolean platePickable;
private boolean wirePickable;
private boolean slotPickable;
private boolean markPickable;
private boolean cellPicking;
private CellManager cellManager;
/**
*
*/
public ViewableFD(FDProvider provider)
{
this.provider=provider;
selectionManager=new SelectionManager(provider);
cellManager=new CellManager(provider);
parentBranchGroup.setCapability(Group.ALLOW_CHILDREN_EXTEND);
parentBranchGroup.setCapability(Group.ALLOW_CHILDREN_READ);
parentBranchGroup.setCapability(Group.ALLOW_CHILDREN_WRITE);
selectedPlates=new Shape3D();
selectedPlates.setCapability(Shape3D.ALLOW_GEOMETRY_WRITE);
selectedPlates.setCapability(Shape3D.ALLOW_GEOMETRY_READ);
Appearance a=new Appearance();
a.setTransparencyAttributes(new TransparencyAttributes(TransparencyAttributes.FASTEST, 0.5f));
a.setPolygonAttributes(SELECT_POLYGON_ATTRIBUTE);
selectedPlates.setPickable(false);
selectedPlates.setAppearance(a);
parentBranchGroup.addChild(selectedPlates);
selectedWires=new Shape3D();
selectedWires.setCapability(Shape3D.ALLOW_GEOMETRY_WRITE);
selectedWires.setCapability(Shape3D.ALLOW_GEOMETRY_READ);
a=new Appearance();
a.setTransparencyAttributes(new TransparencyAttributes(TransparencyAttributes.FASTEST, 0.5f));
a.setLineAttributes(new LineAttributes(3, LineAttributes.PATTERN_SOLID, false));
selectedWires.setPickable(false);
selectedWires.setAppearance(a);
parentBranchGroup.addChild(selectedWires);
selectedJunctions=new Shape3D();
selectedJunctions.setCapability(Shape3D.ALLOW_GEOMETRY_WRITE);
selectedJunctions.setCapability(Shape3D.ALLOW_GEOMETRY_READ);
a=new Appearance();
a.setPointAttributes(new PointAttributes(4, false));
a.setColoringAttributes(new ColoringAttributes(
new Color3f(Color.RED), ColoringAttributes.FASTEST));
selectedJunctions.setPickable(false);
selectedJunctions.setAppearance(a);
parentBranchGroup.addChild(selectedJunctions);
domainsChanged(provider.getDomainIDs());
}
private void createPlates(Integer iDomainId, BranchGroup platesBg, FDDomain domain)
{
float[] coordinates=createQuadArray(domain);
if(coordinates.length<3)
return;
QuadArray qa=new QuadArray(coordinates.length/3, GeometryArray.COORDINATES);
qa.setCoordinates(0, coordinates);
coordinates=null;
GeometryInfo gi=new GeometryInfo(qa);
//new NormalGenerator().generateNormals(gi);
Geometry geom=gi.getIndexedGeometryArray();
geom.setCapability(GeometryArray.ALLOW_COORDINATE_READ);
geom.setCapability(GeometryArray.ALLOW_COUNT_READ);
geom.setCapability(GeometryArray.ALLOW_FORMAT_READ);
geom.setCapability(IndexedGeometryArray.ALLOW_COORDINATE_INDEX_READ);
geom.setCapabilityIsFrequent(GeometryArray.ALLOW_COORDINATE_READ);
geom.setCapabilityIsFrequent(GeometryArray.ALLOW_COUNT_READ);
geom.setCapabilityIsFrequent(GeometryArray.ALLOW_FORMAT_READ);
geom.setCapabilityIsFrequent(IndexedGeometryArray.ALLOW_COORDINATE_INDEX_READ);
geom.setUserData(iDomainId);
Appearance a=new Appearance();
ColoringAttributes ca=new ColoringAttributes(new Color3f(domain.getColor()),
ColoringAttributes.SHADE_FLAT);
a.setColoringAttributes(ca);
/*Material m=new Material();
m.setAmbientColor(new Color3f(domain.getColor()));
m.setDiffuseColor(new Color3f(domain.getColor()));
m.setEmissiveColor(new Color3f(Color.WHITE));
a.setMaterial(m);*/
a.setPolygonAttributes(PLATE_POLYGON_ATTRIBUTE);
Shape3D s3d=new Shape3D(geom, a);
s3d.setCapability(Shape3D.ALLOW_GEOMETRY_READ);
s3d.setCapability(Node.ALLOW_PICKABLE_WRITE);
s3d.setUserData(PLATE_IDENTIFIER);
plates.add(s3d);
platesBg.addChild(s3d);
a=new Appearance();
ca=new ColoringAttributes(new Color3f(domain.getColor().darker()),
ColoringAttributes.SHADE_FLAT);
a.setColoringAttributes(ca);
a.setPolygonAttributes(BORDER_POLYGON_ATTRIBUTE);
s3d=new Shape3D(geom, a);
s3d.setCapability(Shape3D.ALLOW_GEOMETRY_READ);
s3d.setPickable(false);
LOGGER.finest("Plates bounds="+s3d.getBounds());
platesBg.addChild(s3d);
}
private void createWires(Integer iDomainId, BranchGroup platesBg, FDDomain domain)
{
LineArray[] las=createLineArray(domain);
if(las.length==0)
return;
Shape3D s3d=new Shape3D(las[0]);
s3d.setBoundsAutoCompute(false); //Auto compute for LineArray seems buggy
BoundingBox bb=computeBounds(las[0]);
for(int i=1; i<las.length; i++)
{
s3d.addGeometry(las[i]);
bb.combine(computeBounds(las[i]));
}
s3d.setBounds(bb);
Appearance a=new Appearance();
ColoringAttributes ca=new ColoringAttributes(new Color3f(domain.getColor()),
ColoringAttributes.SHADE_FLAT);
a.setColoringAttributes(ca);
s3d.setAppearance(a);
s3d.setCapability(Shape3D.ALLOW_GEOMETRY_READ);
s3d.setCapability(Node.ALLOW_PICKABLE_WRITE);
s3d.setUserData(new WireDomainID(iDomainId.intValue()));
LOGGER.finest("Wires bounds="+s3d.getBounds());
platesBg.addChild(s3d);
wires.add(s3d);
}
private void createSlots(Integer iDomainId, BranchGroup platesBg, FDDomain domain)
{
LineArray[] las=createSlotArray(domain);
if(las.length==0)
return;
Shape3D s3d=new Shape3D(las[0]);
s3d.setBoundsAutoCompute(false); //Auto compute for LineArray seems buggy
BoundingBox bb=computeBounds(las[0]);
for(int i=1; i<las.length; i++)
{
s3d.addGeometry(las[i]);
bb.combine(computeBounds(las[i]));
}
s3d.setBounds(bb);
Appearance a=new Appearance();
ColoringAttributes ca=new ColoringAttributes(new Color3f(domain.getColor()),
ColoringAttributes.SHADE_FLAT);
a.setColoringAttributes(ca);
a.setLineAttributes(SLOT_ATTRIBUTE);
s3d.setAppearance(a);
s3d.setCapability(Shape3D.ALLOW_GEOMETRY_READ);
s3d.setCapability(Node.ALLOW_PICKABLE_WRITE);
s3d.setUserData(new SlotDomainID(iDomainId.intValue()));
s3d.setCapability(Node.ALLOW_PICKABLE_READ);
platesBg.addChild(s3d);
slots.add(s3d);
}
/**
*
* @param cells Input array: {i_min, j_min, k_min, i_max, j_max, k_max}
* @param index the index where to put the cube in the output coordinates arrays
* @param indexi the index where to put the cube in the output indices arrays
* @param indices indices output array
* @param coordinates coordinates output array
*/
private void createSolidCube(int[] cells, int indexi, int index, int[] indices, float[] coordinates)
{
// 5/-----------/6
// / /|
// / / | z
// 0/-----------/ | /
// | 1| | /
// | | |7 -----> x
// | | / |
// | | / |
// | |/ y
// 3 /-----------/ 2
int ic=index*3;
int ii=indexi*4;
coordinates[ic]=(float) provider.getXGrid(cells[0]); //X0
coordinates[ic+1]=(float) provider.getYGrid(cells[1]); //Y0
coordinates[ic+2]=(float) provider.getZGrid(cells[2]); //Z0
coordinates[ic+3]=(float) provider.getXGrid(cells[0]+1); //X1
coordinates[ic+4]=coordinates[ic+1]; //Y1
coordinates[ic+5]=coordinates[ic+2]; //Z1
coordinates[ic+6]=coordinates[ic+3]; //X2
coordinates[ic+7]=(float) provider.getYGrid(cells[1]+1); //Y2
coordinates[ic+8]=coordinates[ic+2]; //Z2
coordinates[ic+9]=coordinates[ic]; //X3
coordinates[ic+10]=coordinates[ic+7]; //Y3
coordinates[ic+11]=coordinates[ic+2]; //Z3
coordinates[ic+12]=coordinates[ic]; //X4
coordinates[ic+13]=coordinates[ic+7]; //Y4
coordinates[ic+14]=(float) provider.getZGrid(cells[2]+1); //Z4
coordinates[ic+15]=coordinates[ic]; //X5
coordinates[ic+16]=coordinates[ic+1]; //Y5
coordinates[ic+17]=coordinates[ic+14]; //Z5
coordinates[ic+18]=coordinates[ic+3]; //X6
coordinates[ic+19]=coordinates[ic+1]; //Y6
coordinates[ic+20]=coordinates[ic+14]; //Z6
coordinates[ic+21]=coordinates[ic+3]; //X7
coordinates[ic+22]=coordinates[ic+7]; //Y7
coordinates[ic+23]=coordinates[ic+14]; //Z7
//0123 face
indices[ii]=index;
indices[ii+1]=index+1;
indices[ii+2]=index+2;
indices[ii+3]=index+3;
//0543
indices[ii+4]=index;
indices[ii+5]=index+5;
indices[ii+6]=index+4;
indices[ii+7]=index+3;
//0561
indices[ii+8]=index;
indices[ii+9]=index+5;
indices[ii+10]=index+6;
indices[ii+11]=index+1;
//3274
indices[ii+12]=index+3;
indices[ii+13]=index+2;
indices[ii+14]=index+7;
indices[ii+15]=index+4;
//2761
indices[ii+16]=index+2;
indices[ii+17]=index+7;
indices[ii+18]=index+6;
indices[ii+19]=index+1;
//4765
indices[ii+20]=index+4;
indices[ii+21]=index+7;
indices[ii+22]=index+6;
indices[ii+23]=index+5;
}
private interface CoordinatesComputer
{
void compute(int[] indices, float[] out);
}
private class CoordinatesComputerXZ implements CoordinatesComputer
{
public void compute(int[] wire, float[] coordinates)
{
coordinates[0]=(float) provider.getXGrid(wire[0]);
coordinates[1]=(float) (provider.getYGrid(wire[2])+provider.getYGrid(wire[2]+1))/2;
coordinates[2]=(float) provider.getZGrid(wire[3]);
coordinates[3]=(float) provider.getXGrid(wire[1]);
coordinates[4]=coordinates[1];
coordinates[5]=coordinates[2];
}
}
private class CoordinatesComputerXY implements CoordinatesComputer
{
public void compute(int[] wire, float[] coordinates)
{
coordinates[0]=(float) provider.getXGrid(wire[0]);
coordinates[1]=(float) provider.getYGrid(wire[2]);
coordinates[2]=(float) (provider.getZGrid(wire[3])+provider.getZGrid(wire[3]+1))/2;
coordinates[3]=(float) provider.getXGrid(wire[1]);
coordinates[4]=coordinates[1];
coordinates[5]=coordinates[2];
}
}
private class CoordinatesComputerYZ implements CoordinatesComputer
{
public void compute(int[] wire, float[] coordinates)
{
coordinates[0]=(float) (provider.getXGrid(wire[2])+provider.getXGrid(wire[2]+1))/2;
coordinates[1]=(float) provider.getYGrid(wire[0]);
coordinates[2]=(float) provider.getZGrid(wire[3]);
coordinates[3]=coordinates[0];
coordinates[4]=(float) provider.getYGrid(wire[1]);
coordinates[5]=coordinates[2];
}
}
private class CoordinatesComputerYX implements CoordinatesComputer
{
public void compute(int[] wire, float[] coordinates)
{
coordinates[0]=(float) provider.getXGrid(wire[2]);
coordinates[1]=(float) provider.getYGrid(wire[0]);
coordinates[2]=(float) (provider.getZGrid(wire[3])+provider.getZGrid(wire[3]+1))/2;
coordinates[3]=coordinates[0];
coordinates[4]=(float) provider.getYGrid(wire[1]);
coordinates[5]=coordinates[2];
}
}
private class CoordinatesComputerZY implements CoordinatesComputer
{
public void compute(int[] wire, float[] coordinates)
{
coordinates[0]=(float) (provider.getXGrid(wire[2])+provider.getXGrid(wire[2]+1))/2;
coordinates[1]=(float) provider.getYGrid(wire[3]);
coordinates[2]=(float) provider.getZGrid(wire[0]);
coordinates[3]=coordinates[0];
coordinates[4]=coordinates[1];
coordinates[5]=(float) provider.getZGrid(wire[1]);
}
}
private class CoordinatesComputerZX implements CoordinatesComputer
{
public void compute(int[] wire, float[] coordinates)
{
coordinates[0]=(float) provider.getXGrid(wire[2]);
coordinates[1]=(float) (provider.getYGrid(wire[3])+provider.getYGrid(wire[3]+1))/2;
coordinates[2]=(float) provider.getZGrid(wire[0]);
coordinates[3]=coordinates[0];
coordinates[4]=coordinates[1];
coordinates[5]=(float) provider.getZGrid(wire[1]);
}
}
/**
* @param domain
* @param toReturn a collection to add LineArray
* @param type FDDomain.XZ_SLOT
* @param coordinatesComputer
*/
private void createSlotArray(
FDDomain domain,
Collection<LineArray> toReturn,
byte type,
CoordinatesComputer coordinatesComputer)
{
int k=0;
Iterator it=domain.getSlotIterator(type);
while(it.hasNext())
{
Object o=it.next();
float[] coordinates;
if(o instanceof int[])
{
int[] wire=(int[])o;
coordinates=new float[6];
coordinatesComputer.compute(wire, coordinates);
}
else
{
coordinates=(float[]) o;
}
//printFloatDebug(coordinates);
LineArray la=new LineArray(6, GeometryArray.COORDINATES);
setGeometryCapabilities(la);
la.setCoordinates(0, coordinates);
la.setUserData(new SlotID(k, type));
toReturn.add(la);
k++;
}
}
/**
* @param domain
* @return
*/
private LineArray[] createSlotArray(FDDomain domain)
{
Collection<LineArray> toReturn=new ArrayList<LineArray>();
createSlotArray(domain, toReturn, FDDomain.XZ_SLOT, new CoordinatesComputerXZ());
createSlotArray(domain, toReturn, FDDomain.XY_SLOT, new CoordinatesComputerXY());
createSlotArray(domain, toReturn, FDDomain.YZ_SLOT, new CoordinatesComputerYZ());
createSlotArray(domain, toReturn, FDDomain.YX_SLOT, new CoordinatesComputerYX());
createSlotArray(domain, toReturn, FDDomain.ZY_SLOT, new CoordinatesComputerZY());
createSlotArray(domain, toReturn, FDDomain.ZX_SLOT, new CoordinatesComputerZX());
return toReturn.toArray(new LineArray[toReturn.size()]);
}
private static BoundingBox computeBounds(GeometryArray array)
{
float[] coords=new float[array.getVertexCount()];
array.getCoordinates(0, coords);
float xmin=Float.POSITIVE_INFINITY;
float ymin=Float.POSITIVE_INFINITY;
float zmin=Float.POSITIVE_INFINITY;
float xmax=Float.NEGATIVE_INFINITY;
float ymax=Float.NEGATIVE_INFINITY;
float zmax=Float.NEGATIVE_INFINITY;
for(int i=0; i<coords.length;)
{
if(coords[i]<xmin)
xmin=coords[i];
if(coords[i]>xmax)
xmax=coords[i];
i++;
if(coords[i]<ymin)
ymin=coords[i];
if(coords[i]>ymax)
ymax=coords[i];
i++;
if(coords[i]<zmin)
zmin=coords[i];
if(coords[i]>zmax)
zmax=coords[i];
i++;
}
BoundingBox toReturn=new BoundingBox(
new Point3d(xmin, ymin, zmin),
new Point3d(xmax, ymax, zmax));
return toReturn;
}
/* (non-Javadoc)
* @see jcae.viewer3d.Viewable#domainsChanged(java.util.Collection)
*/
@Override
synchronized public void domainsChangedPerform(int[] domainId)
{
Set<Integer> ids=new HashSet<Integer>(Utils.intArrayToCollection(provider.getDomainIDs()));
for(int d=0; d<domainId.length; d++)
{
Integer iDomainId=new Integer(domainId[d]);
LOGGER.finest("Create BranchGroup for domain nr"+
Integer.toHexString(domainId[d])+ "provider="+provider+" ids="+ids);
BranchGroup old=domainToBranchGroup.get(iDomainId);
if(old!=null)
{
old.detach();
domainToBranchGroup.remove(iDomainId);
plates.removeAll(Collections.list(old.getAllChildren()));
}
if(!ids.contains(iDomainId))
continue;
BranchGroup domainBg=new BranchGroup();
domainBg.setCapability(BranchGroup.ALLOW_DETACH);
domainBg.setCapability(Group.ALLOW_CHILDREN_READ);
FDDomain domain=(FDDomain)provider.getDomain(domainId[d]);
createPlates(iDomainId, domainBg, domain);
createWires(iDomainId, domainBg, domain);
createSlots(iDomainId, domainBg, domain);
createSolids(iDomainId, domainBg, domain);
Node m=MarkUtils.createMarkNode(domain, iDomainId.intValue());
marks.add(m);
domainBg.addChild(m);
parentBranchGroup.addChild(domainBg);
domainToBranchGroup.put(iDomainId, domainBg);
}
unselectAll();
setPlatePicking(platePickable);
setWirePicking(wirePickable);
setSlotPicking(slotPickable);
setMarkPicking(markPickable);
}
/**
* @param domainId
* @param domainBg
* @param domain
*/
private void createSolids(Integer domainId, BranchGroup domainBg, FDDomain domain)
{
Iterator<int[]> it=domain.getSolidIterator();
int[] indices=new int[domain.getNumberOfSolid()*24];
if(indices.length==0)
return;
float[] coordinates=new float[domain.getNumberOfSolid()*24];
int index=0, indexi=0;
while(it.hasNext())
{
int[] array=it.next();
createSolidCube(array, indexi, index, indices, coordinates);
index+=8; //8 nodes in a cube
indexi+=6; //6 faces in a cube
}
GeometryInfo gi=new GeometryInfo(GeometryInfo.QUAD_ARRAY);
gi.setCoordinateIndices(indices);
gi.setCoordinates(coordinates);
//gi.recomputeIndices();
//new NormalGenerator().generateNormals(gi);
Geometry geom=gi.getIndexedGeometryArray();
geom.setCapability(GeometryArray.ALLOW_COORDINATE_READ);
geom.setCapability(GeometryArray.ALLOW_COUNT_READ);
geom.setCapability(GeometryArray.ALLOW_FORMAT_READ);
geom.setCapability(IndexedGeometryArray.ALLOW_COORDINATE_INDEX_READ);
geom.setCapabilityIsFrequent(GeometryArray.ALLOW_COORDINATE_READ);
geom.setCapabilityIsFrequent(GeometryArray.ALLOW_COUNT_READ);
geom.setCapabilityIsFrequent(GeometryArray.ALLOW_FORMAT_READ);
geom.setCapabilityIsFrequent(IndexedGeometryArray.ALLOW_COORDINATE_INDEX_READ);
geom.setUserData(domainId);
Appearance a=new Appearance();
ColoringAttributes ca=new ColoringAttributes(new Color3f(domain.getColor()),
ColoringAttributes.SHADE_FLAT);
a.setColoringAttributes(ca);
/*Material m=new Material();
m.setAmbientColor(new Color3f(domain.getColor()));
m.setDiffuseColor(new Color3f(domain.getColor()));
m.setEmissiveColor(new Color3f(Color.WHITE));
a.setMaterial(m);*/
a.setPolygonAttributes(PLATE_POLYGON_ATTRIBUTE);
Shape3D s3d=new Shape3D(geom, a);
s3d.setCapability(Shape3D.ALLOW_GEOMETRY_READ);
s3d.setCapability(Node.ALLOW_PICKABLE_WRITE);
s3d.setUserData(SOLID_IDENTIFIER);
solids.add(s3d);
domainBg.addChild(s3d);
a=new Appearance();
ca=new ColoringAttributes(new Color3f(domain.getColor().darker()),
ColoringAttributes.SHADE_FLAT);
a.setColoringAttributes(ca);
a.setPolygonAttributes(BORDER_POLYGON_ATTRIBUTE);
s3d=new Shape3D(geom, a);
s3d.setCapability(Shape3D.ALLOW_GEOMETRY_READ);
s3d.setPickable(false);
domainBg.addChild(s3d);
}
/**
* @param markPickable2
*/
public void setMarkPicking(boolean enable)
{
LOGGER.finest("enable="+enable);
markPickable=enable;
Iterator<Node> it=marks.iterator();
while(it.hasNext())
{
Node n=it.next();
MarkUtils.setPickable(n, enable);
}
}
/* (non-Javadoc)
* @see jcae.viewer3d.Viewable#getDomainProvider()
*/
@Override
public DomainProvider getDomainProvider()
{
return provider;
}
/* (non-Javadoc)
* @see jcae.viewer3d.Viewable#setDomainVisible(java.util.Map)
*/
public void setDomainVisible(Map<Integer, Boolean> map)
{
// TODO Auto-generated method stub
throw new UnsupportedOperationException();
}
public void setDomainPickable(int domainID, boolean enable)
{
LOGGER.finest("domainID="+Integer.toHexString(domainID)
+" enable="+enable);
BranchGroup bg=domainToBranchGroup.get(new Integer(domainID));
if(bg==null)
{
LOGGER.info("domain 0x"+Integer.toHexString(domainID)+
" is empty. Cannot change pickable status");
return;
}
Enumeration e=bg.getAllChildren();
while(e.hasMoreElements())
{
Node n=(Node) e.nextElement();
LOGGER.finest(""+n.getUserData());
if(n.getUserData()==MarkUtils.MARK_IDENTIFIER)
{
LOGGER.finest("MarkUtils.setPickable("+n+","+enable);
MarkUtils.setPickable(n, enable);
}
else if(n.getUserData()!=null)
{
LOGGER.finest("setPickable("+n+","+enable);
n.setPickable(enable);
}
}
}
public void setPlatePicking(boolean enable)
{
LOGGER.finest("enable="+enable);
platePickable=enable;
Iterator<Shape3D> it=plates.iterator();
while(it.hasNext())
{
Node n=it.next();
n.setPickable(enable);
}
}
public void setWirePicking(boolean enable)
{
LOGGER.finest("enable="+enable);
wirePickable=enable;
Iterator<Shape3D> it=wires.iterator();
while(it.hasNext())
{
Node n=it.next();
n.setPickable(enable);
}
}
public void setSlotPicking(boolean enable)
{
LOGGER.finest("enable="+enable);
slotPickable=enable;
Iterator<Shape3D> it=slots.iterator();
while(it.hasNext())
{
Node n=it.next();
n.setPickable(enable);
}
}
/* (non-Javadoc)
* @see org.jcae.viewer3d.Viewable#pick(com.sun.j3d.utils.picking.PickResult)
*/
@Override
public void pick(PickViewable result)
{
if(result==null)
return;
if(result.getObject().getUserData()==PLATE_IDENTIFIER)
{
pickPlate(result);
}
if(result.getObject().getUserData()==SOLID_IDENTIFIER)
{
pickSolid(result);
}
else if(result.getObject().getUserData() instanceof WireDomainID)
{
if(cellPicking)
pickWireCell(result);
else
pickWire(result);
}
else if(result.getObject().getUserData() instanceof SlotDomainID)
{
if(cellPicking)
pickSlotCell(result);
else
pickSlot(result);
}
else if(result.getObject().getUserData() instanceof MarkUtils.MarkID)
{
pickJunction(result);
}
fireSelectionChanged();
}
private void pickSlotCell(PickViewable result)
{
int domainId=((SlotDomainID)result.getObject().getUserData()).getValue();
PickIntersection pi = result.getIntersection();
SlotID o=(SlotID)pi.getGeometryArray().getUserData();
Point3d[] cds=pi.getPrimitiveCoordinates();
Point3d point=pi.getPointCoordinates();
Geometry la=null;
boolean toSelected=!cellManager.isSlotSelected(o.getType(), domainId, o.getValue(), cds, point);
if(toSelected)
{
la=cellManager.selectSlot(o.getType(), domainId, o.getValue(), cds, point);
selectedWires.addGeometry(la);
}
else
{
la=cellManager.unselectSlot(o.getType(), domainId, o.getValue(), cds, point);
selectedWires.removeGeometry(la);
}
}
private void pickWireCell(PickViewable result)
{
int domainId=((WireDomainID)result.getObject().getUserData()).getValue();
PickIntersection pi = result.getIntersection();
IntegerUserData o=(IntegerUserData)pi.getGeometryArray().getUserData();
Point3d[] cds=pi.getPrimitiveCoordinates();
Point3d point=pi.getPointCoordinates();
Geometry la=null;
boolean toSelect=false;
if(o instanceof XLineID)
{
toSelect=!cellManager.isXWireSelected(domainId, o.getValue(), cds, point);
}
else if(o instanceof YLineID)
{
toSelect=!cellManager.isYWireSelected(domainId, o.getValue(), cds, point);
}
else if(o instanceof ZLineID)
{
toSelect=!cellManager.isZWireSelected(domainId, o.getValue(), cds, point);
}
if(toSelect)
{
if(o instanceof XLineID)
{
la=cellManager.selectXWire(domainId, o.getValue(), cds, point);
}
else if(o instanceof YLineID)
{
la=cellManager.selectYWire(domainId, o.getValue(), cds, point);
}
else if(o instanceof ZLineID)
{
la=cellManager.selectZWire(domainId, o.getValue(), cds, point);
}
selectedWires.addGeometry(la);
}
else
{
if(o instanceof XLineID)
{
la=cellManager.unselectXWire(domainId, o.getValue(), cds, point);
}
else if(o instanceof YLineID)
{
la=cellManager.unselectYWire(domainId, o.getValue(), cds, point);
}
else if(o instanceof ZLineID)
{
la=cellManager.unselectZWire(domainId, o.getValue(), cds, point);
}
selectedWires.removeGeometry(la);
}
}
private void pickJunction(PickViewable result)
{
int domainId=((MarkUtils.MarkID)result.getObject().getUserData()).getDomainID();
PickIntersection pi = result.getIntersection();
int typeId=((MarkUtils.MarkID)result.getObject().getUserData()).getTypeID();
int[] idx = pi.getPrimitiveVertexIndices();
int markID=idx[0];
boolean toSelect=!selectionManager.isMarkSelected(domainId, typeId, markID);
if(toSelect)
{
Point3d[] cds=pi.getPrimitiveCoordinates();
PointArray pa=new PointArray(cds.length, GeometryArray.COORDINATES);
pa.setCoordinates(0, cds);
selectedJunctions.addGeometry(pa);
selectionManager.selectMark(domainId, typeId, markID, pa);
}
else
{
selectedJunctions.removeGeometry(
selectionManager.getGeometryForMark(domainId, typeId, markID));
selectionManager.unselectMark(domainId, typeId, markID);
}
}
private void pickWire(PickViewable result)
{
int domainId=((WireDomainID)result.getObject().getUserData()).getValue();
PickIntersection pi = result.getIntersection();
IntegerUserData o=(IntegerUserData)pi.getGeometryArray().getUserData();
boolean toSelect=false;
if(o instanceof XLineID)
{
toSelect=!selectionManager.isXWireSelected(domainId, o.getValue());
}
else if(o instanceof YLineID)
{
toSelect=!selectionManager.isYWireSelected(domainId, o.getValue());
}
else if(o instanceof ZLineID)
{
toSelect=!selectionManager.isZWireSelected(domainId, o.getValue());
}
if(toSelect)
{
Point3d[] cds=pi.getPrimitiveCoordinates();
LineArray la=new LineArray(cds.length, GeometryArray.COORDINATES);
la.setCoordinates(0, cds);
selectedWires.addGeometry(la);
if(o instanceof XLineID)
{
selectionManager.selectXWire(domainId, o.getValue(), la);
}
else if(o instanceof YLineID)
{
selectionManager.selectYWire(domainId, o.getValue(), la);
}
else if(o instanceof ZLineID)
{
selectionManager.selectZWire(domainId, o.getValue(), la);
}
}
else
{
Geometry toRemove=null;
if(o instanceof XLineID)
{
toRemove=selectionManager.getGeometryForXWire(
domainId, o.getValue());
selectionManager.unselectXWire(domainId, o.getValue());
}
else if(o instanceof YLineID)
{
toRemove=selectionManager.getGeometryForYWire(
domainId, o.getValue());
selectionManager.unselectYWire(domainId, o.getValue());
}
else if(o instanceof ZLineID)
{
toRemove=selectionManager.getGeometryForZWire(
domainId, o.getValue());
selectionManager.unselectZWire(domainId, o.getValue());
}
selectedWires.removeGeometry(toRemove);
}
}
private void pickSlot(PickViewable result)
{
int domainId=((SlotDomainID)result.getObject().getUserData()).getValue();
PickIntersection pi = result.getIntersection();
SlotID o=(SlotID)pi.getGeometryArray().getUserData();
boolean toSelect=!selectionManager.isSlotSelected(o.getType(), domainId, o.getValue());
if(toSelect)
{
Point3d[] cds=pi.getPrimitiveCoordinates();
LineArray la=new LineArray(cds.length, GeometryArray.COORDINATES);
la.setCoordinates(0, cds);
selectedWires.addGeometry(la);
selectionManager.selectSlot(o.getType(), domainId, o.getValue(), la);
}
else
{
Geometry toRemove=selectionManager.getGeometryForSlot(
o.getType(), domainId, o.getValue());
selectionManager.unselectSlot(o.getType(), domainId, o.getValue());
selectedWires.removeGeometry(toRemove);
}
}
private void pickPlate(PickViewable result)
{
PickIntersection pi = result.getIntersection();
// indices of the picked quad
// Indices are set to vertex indices, as this is not an Index
// Geometry object
// => easy to find the plate index from this
int[] idx = pi.getPrimitiveVertexIndices();
int plateID=idx[0]/4;
int domainID=((Integer)pi.getGeometryArray().getUserData()).intValue();
boolean toSelect=!selectionManager.isPlateSelected(plateID, domainID);
if(toSelect)
{
Point3d[] pc=pi.getPrimitiveCoordinates();
LOGGER.finest("domainID: "+domainID);
LOGGER.finest("coordinates: "+Arrays.asList(pc));
QuadArray qa=new QuadArray(4, GeometryArray.COORDINATES);
qa.setCoordinates(0, pi.getPrimitiveCoordinates());
selectedPlates.addGeometry(qa);
selectionManager.selectPlate(plateID, domainID, qa);
}
else
{
selectedPlates.removeGeometry(
selectionManager.getGeometryForPlate(domainID, plateID));
selectionManager.unselectPlate(plateID, domainID);
}
}
private void pickSolid(PickViewable result)
{
PickIntersection pi = result.getIntersection();
// indices of the picked quad
// Indices are set to vertex indices, as this is not an Index
// Geometry object
// => easy to find the plate index from this
int[] idx = pi.getPrimitiveVertexIndices();
int solidID=idx[0]/24;
int domainID=((Integer)pi.getGeometryArray().getUserData()).intValue();
boolean toSelect=!selectionManager.isSolidSelected(solidID, domainID);
if(toSelect)
{
LOGGER.finest("cellid= "+idx[0]/24);
LOGGER.finest("domainID: "+domainID);
IndexedGeometryArray iga=(IndexedGeometryArray)pi.getGeometryArray();
int[] indices=new int[24];
iga.getCoordinateIndices(solidID*24, indices);
float[] coordinates=new float[24*3];
Point3f p=new Point3f();
for(int i=0, j=0; i<indices.length; i++)
{
iga.getCoordinate(indices[i], p);
coordinates[j++]=p.x;
coordinates[j++]=p.y;
coordinates[j++]=p.z;
}
QuadArray qa=new QuadArray(24, GeometryArray.COORDINATES);
qa.setCoordinates(0, coordinates);
selectedPlates.addGeometry(qa);
selectionManager.selectSolid(solidID, domainID, qa);
}
else
{
selectedPlates.removeGeometry(
selectionManager.getGeometryForSolid(domainID, solidID));
selectionManager.unselectSolid(solidID, domainID);
}
}
/* (non-Javadoc)
* @see org.jcae.viewer3d.Viewable#getBranchGroup(org.jcae.viewer3d.View)
*/
@Override
public Node getJ3DNode()
{
return parentBranchGroup;
}
/* (non-Javadoc)
* @see org.jcae.viewer3d.Viewable#unselectAll()
*/
@Override
public void unselectAll()
{
selectionManager.unselectAll();
selectedPlates.removeAllGeometries();
selectedWires.removeAllGeometries();
selectedJunctions.removeAllGeometries();
cellManager.unselectAll();
fireSelectionChanged();
}
private LineArray[] createLineArray(FDDomain domain)
{
Iterator<int[]> it=domain.getXWireIterator();
Collection<LineArray> toReturn=new ArrayList<LineArray>();
int k=0;
while(it.hasNext())
{
int[] wire=it.next();
float[] coordinates=new float[6];
coordinates[0]=(float) provider.getXGrid(wire[0]);
coordinates[1]=(float) provider.getYGrid(wire[1]);
coordinates[2]=(float) provider.getZGrid(wire[2]);
coordinates[3]=(float) provider.getXGrid(wire[3]);
coordinates[4]=coordinates[1];
coordinates[5]=coordinates[2];
//printFloatDebug(coordinates);
LineArray la=new LineArray(6, GeometryArray.COORDINATES);
setGeometryCapabilities(la);
la.setCoordinates(0, coordinates);
la.setUserData(new XLineID(k));
toReturn.add(la);
k++;
}
k=0;
it=domain.getYWireIterator();
while(it.hasNext())
{
int[] wire=it.next();
float[] coordinates=new float[6];
coordinates[0]=(float) provider.getXGrid(wire[0]);
coordinates[1]=(float) provider.getYGrid(wire[1]);
coordinates[2]=(float) provider.getZGrid(wire[2]);
coordinates[3]=coordinates[0];
coordinates[4]=(float) provider.getYGrid(wire[3]);
coordinates[5]=coordinates[2];
//printFloatDebug(coordinates);
LineArray la=new LineArray(6, GeometryArray.COORDINATES);
setGeometryCapabilities(la);
la.setCoordinates(0, coordinates);
la.setUserData(new YLineID(k));
toReturn.add(la);
k++;
}
k=0;
it=domain.getZWireIterator();
while(it.hasNext())
{
int[] wire=it.next();
float[] coordinates=new float[6];
coordinates[0]=(float) provider.getXGrid(wire[0]);
coordinates[1]=(float) provider.getYGrid(wire[1]);
coordinates[2]=(float) provider.getZGrid(wire[2]);
coordinates[3]=coordinates[0];
coordinates[4]=coordinates[1];
coordinates[5]=(float) provider.getZGrid(wire[3]);
//printFloatDebug(coordinates);
LineArray la=new LineArray(6, GeometryArray.COORDINATES);
setGeometryCapabilities(la);
la.setCoordinates(0, coordinates);
la.setUserData(new ZLineID(k));
toReturn.add(la);
k++;
}
return toReturn.toArray(new LineArray[toReturn.size()]);
}
private static void printFloatDebug(float[] f)
{
for(int i=0; i<f.length; i++)
{
System.out.print(f[i]+", ");
}
System.out.println();
}
private static void setGeometryCapabilities(Geometry geom)
{
geom.setCapability(GeometryArray.ALLOW_COORDINATE_READ);
geom.setCapability(GeometryArray.ALLOW_COUNT_READ);
geom.setCapability(GeometryArray.ALLOW_FORMAT_READ);
geom.setCapability(IndexedGeometryArray.ALLOW_COORDINATE_INDEX_READ);
geom.setCapabilityIsFrequent(GeometryArray.ALLOW_COORDINATE_READ);
geom.setCapabilityIsFrequent(GeometryArray.ALLOW_COUNT_READ);
geom.setCapabilityIsFrequent(GeometryArray.ALLOW_FORMAT_READ);
geom.setCapabilityIsFrequent(IndexedGeometryArray.ALLOW_COORDINATE_INDEX_READ);
}
private float[] createQuadArray(FDDomain domain)
{
int numberOfPlates=domain.getNumberOfXPlate()+domain.getNumberOfYPlate()+domain.getNumberOfZPlate();
float[] coordinates=new float[numberOfPlates*12];
Iterator<int[]> it=domain.getXPlateIterator();
int k=0;
while(it.hasNext())
{
int[] plate=it.next();
float x=(float)provider.getXGrid(plate[0]);
float y1=(float)provider.getYGrid(plate[1]);
float z1=(float)provider.getZGrid(plate[2]);
float y2=(float)provider.getYGrid(plate[3]);
float z2=(float)provider.getZGrid(plate[4]);
coordinates[k++]=x;
coordinates[k++]=y1;
coordinates[k++]=z1;
coordinates[k++]=x;
coordinates[k++]=y2;
coordinates[k++]=z1;
coordinates[k++]=x;
coordinates[k++]=y2;
coordinates[k++]=z2;
coordinates[k++]=x;
coordinates[k++]=y1;
coordinates[k++]=z2;
}
it=domain.getYPlateIterator();
while(it.hasNext())
{
int[] plate=it.next();
float y=(float)provider.getYGrid(plate[0]);
float x1=(float)provider.getXGrid(plate[1]);
float z1=(float)provider.getZGrid(plate[2]);
float x2=(float)provider.getXGrid(plate[3]);
float z2=(float)provider.getZGrid(plate[4]);
coordinates[k++]=x1;
coordinates[k++]=y;
coordinates[k++]=z1;
coordinates[k++]=x1;
coordinates[k++]=y;
coordinates[k++]=z2;
coordinates[k++]=x2;
coordinates[k++]=y;
coordinates[k++]=z2;
coordinates[k++]=x2;
coordinates[k++]=y;
coordinates[k++]=z1;
}
it=domain.getZPlateIterator();
while(it.hasNext())
{
int[] plate=it.next();
float z=(float)provider.getZGrid(plate[0]);
float x1=(float)provider.getXGrid(plate[1]);
float y1=(float)provider.getYGrid(plate[2]);
float x2=(float)provider.getXGrid(plate[3]);
float y2=(float)provider.getYGrid(plate[4]);
coordinates[k++]=x1;
coordinates[k++]=y1;
coordinates[k++]=z;
coordinates[k++]=x1;
coordinates[k++]=y2;
coordinates[k++]=z;
coordinates[k++]=x2;
coordinates[k++]=y2;
coordinates[k++]=z;
coordinates[k++]=x2;
coordinates[k++]=y1;
coordinates[k++]=z;
}
return coordinates;
}
/** Return the current selection */
public FDSelection[] getSelection()
{
if(cellPicking)
return cellManager.getSelection();
return selectionManager.getSelection();
}
/**
* Tell the viewer to select wire and slot by elementary element
*/
public void setCellPicking(boolean b)
{
this.cellPicking=b;
}
}