/* * 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.fe.amibe; import gnu.trove.set.hash.TIntHashSet; import gnu.trove.map.hash.TIntIntHashMap; import java.awt.Color; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.lang.reflect.Method; import java.nio.DoubleBuffer; import java.nio.IntBuffer; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.Iterator; import java.util.logging.Logger; import org.jcae.viewer3d.fe.FEDomainAdaptor; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; /** * A FEDomain which get data from the XML/binaries file of the amibe mesher * @author Jerome Robert * @todo implement */ public class AmibeDomain extends FEDomainAdaptor { private File directory; private Document document; private int id; private float[] nodes; private int[] tria3; private Color color; /** * @param document * @param id * @param color This parameter is only used to compute the colors of groups * @throws IOException */ public AmibeDomain(File directory, Document document, int id, Color color) throws IOException { this.directory=directory; this.document=document; this.id=id; this.color=color; tria3=readTria3(); int[] nodesID=makeNodeIDArray(tria3); nodes=readNodes(nodesID); Logger.getLogger(AmibeDomain.class.getName()).finest("number of nodes="+nodes.length+", number of tria3="+tria3.length/3.0); renumberArray(tria3, nodesID); } private File getNodeFile() { Element xmlNodes = (Element) document.getElementsByTagName( "nodes").item(0); String a=((Element)xmlNodes.getElementsByTagName("file").item(0)).getAttribute("location"); return new File(directory, a); } @Override public float[] getNodes() { return nodes; } /* * (non-Javadoc) * @see org.jcae.viewer3d.fe.FEDomainAdaptor#getNumberOfNodes() */ @Override public int getNumberOfNodes() { return nodes.length/3; } /* * (non-Javadoc) * @see org.jcae.viewer3d.fe.FEDomainAdaptor#getNumberOfTria3() */ @Override public int getNumberOfTria3() { return tria3.length/3; } /* * (non-Javadoc) * @see org.jcae.viewer3d.fe.FEDomainAdaptor#getTria3() */ @Override public int[] getTria3() { return tria3; } private File getTriaFile() { Element xmlNodes = (Element) document.getElementsByTagName( "triangles").item(0); Node fn = xmlNodes.getElementsByTagName("file").item(0); String a=((Element)fn).getAttribute("location"); return new File(directory, a); } /** * @param the xml element of DOM tree corresponding to the tag "groups". * @param a group. * @return the xml element of DOM tree corresponding to the group. */ public static Element getXmlGroup(Element xmlGroups, int groupID) { NodeList list = xmlGroups.getElementsByTagName("group"); int length=list.getLength(); Element elt = null; int i = 0; boolean found = false; while (!found && i < length) { elt = (Element) list.item(i); int aId = -1; try { aId = Integer.parseInt(elt.getAttribute("id")); } catch (Exception e) { e.printStackTrace(System.out); } if (groupID == aId) { found = true; } else { i++; } } if (found) { return elt; } else { return null; } } /** * Create the list of needed nodes for a triangle array * @param trias the triangles which require nodes * @return the nodes id */ private int[] makeNodeIDArray(int[] trias) { TIntHashSet set=new TIntHashSet(trias.length/2); for(int i=0; i<trias.length; i++) { set.add(trias[i]); } return set.toArray(); } private float[] readNodes(int[] nodesID) throws IOException { File f=getNodeFile(); // Open the file and then get a channel from the stream FileInputStream fis = new FileInputStream(f); FileChannel fc = fis.getChannel(); // Get the file's size and then map it into memory MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, f.length()); DoubleBuffer nodesBuffer=bb.asDoubleBuffer(); float[] toReturn=new float[nodesID.length*3]; for(int i=0; i<nodesID.length; i++) { int ii=i*3; int iid=nodesID[i]*3; toReturn[ii]=(float) nodesBuffer.get(iid); toReturn[ii+1]=(float) nodesBuffer.get(iid+1); toReturn[ii+2]=(float) nodesBuffer.get(iid+2); } fc.close(); fis.close(); clean(bb); return toReturn; } private int[] readTria3() throws IOException { Element e=getXmlGroup((Element) document.getElementsByTagName("groups").item(0), id); Element numberNode=(Element)e.getElementsByTagName("number").item(0); String v=numberNode.getChildNodes().item(0).getNodeValue(); int number=Integer.parseInt(v); if(number==0) return new int[0]; String groupFileN=((Element)e.getElementsByTagName("file").item(0)).getAttribute("location"); String os=((Element)e.getElementsByTagName("file").item(0)).getAttribute("offset"); if (os.isEmpty()) os = "0"; File groupFile=new File(directory, groupFileN); long offset=Long.parseLong(os); // Open the file and then get a channel from the stream FileInputStream fisG = new FileInputStream(groupFile); FileChannel fcG = fisG.getChannel(); // Get the file's size and then map it into memory MappedByteBuffer bbG = fcG.map(FileChannel.MapMode.READ_ONLY, offset*4, number*4); IntBuffer groups = bbG.asIntBuffer(); File f=getTriaFile(); // Open the file and then get a channel from the stream FileInputStream fis = new FileInputStream(f); FileChannel fc = fis.getChannel(); // Get the file's size and then map it into memory MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, f.length()); IntBuffer trias=bb.asIntBuffer(); int[] toReturn=new int[number*3]; for(int i=0; i<number; i++) { trias.position(groups.get(i)*3); trias.get(toReturn, i*3, 3); } fc.close(); fis.close(); fcG.close(); fisG.close(); clean(bbG); clean(bb); return toReturn; } private void renumberArray(int[] arrayToRenumber, int[] newIndices) { TIntIntHashMap map=new TIntIntHashMap(newIndices.length); for(int i=0; i<newIndices.length; i++) { map.put(newIndices[i], i); } for(int i=0; i<arrayToRenumber.length; i++) { arrayToRenumber[i]=map.get(arrayToRenumber[i]); } } /** * Workaround for Bug ID4724038. * see http://bugs.sun.com/bugdatabase/view_bug.do;:YfiG?bug_id=4724038 */ public static void clean(final MappedByteBuffer buffer) { try { Class cleanerClass=Class.forName("sun.misc.Cleaner"); final Method cleanMethod=cleanerClass.getMethod("clean", null); AccessController.doPrivileged(new PrivilegedAction() { public Object run() { try { Method getCleanerMethod = buffer.getClass().getMethod( "cleaner", new Class[0]); getCleanerMethod.setAccessible(true); Object cleaner = getCleanerMethod.invoke(buffer,new Object[0]); if(cleaner!=null) { cleanMethod.invoke(cleaner, null); } } catch(Exception e) { e.printStackTrace(); } return null; } }); } catch(ClassNotFoundException ex) { //Not a Sun JVM so we exit. } catch (SecurityException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } } /* (non-Javadoc) * @see org.jcae.viewer3d.fe.FEDomainAdaptor#getColor() */ public Color getColor() { return color; } /* (non-Javadoc) * @see org.jcae.viewer3d.fe.FEDomainAdaptor#getID() */ public int getID() { return id; } }