/* * 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 2009, by EADS France */ package org.jcae.vtk; import gnu.trove.list.array.TIntArrayList; import gnu.trove.set.hash.TIntHashSet; import gnu.trove.map.hash.TIntIntHashMap; import java.io.IOException; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.logging.Level; import java.util.logging.Logger; import org.jcae.mesh.xmldata.AmibeReader; import org.jcae.mesh.xmldata.AmibeReader.Group; import org.jcae.mesh.xmldata.AmibeReader.SubMesh; import org.xml.sax.SAXException; /** * * @author Jerome Robert */ public class AmibeToMesh { private final static Logger LOGGER=Logger.getLogger(AmibeToMesh.class.getName()); private Map<String, LeafNode.DataProvider> triangles = new HashMap<String, LeafNode.DataProvider>(); private Map<String, LeafNode.DataProvider> beams = new HashMap<String, LeafNode.DataProvider>(); int triaCount = 0; public Map<String, LeafNode.DataProvider> getTriangles() { return Collections.unmodifiableMap(triangles); } public Map<String, LeafNode.DataProvider> getBeams() { return Collections.unmodifiableMap(beams); } /** * Create the list of needed nodes for a triangle array * @param trias the triangles which require nodes * @return the nodes id */ private static int[] makeNodeIDArray(int[] ... ids) { int n = 0; for(int[] id:ids) n += id.length; TIntHashSet set = new TIntHashSet(n/2); for(int[] id:ids) set.addAll(id); TIntArrayList list = new TIntArrayList(set.size()); list.add(set.toArray()); list.sort(); return list.toArray(); } private static void renumberArray(int[] newIndices, int[] ... arraysToRenumber) { TIntIntHashMap map = new TIntIntHashMap(newIndices.length); for (int i = 0; i < newIndices.length; i++) map.put(newIndices[i], i); for(int[] arrayToRenumber:arraysToRenumber) for (int i = 0; i < arrayToRenumber.length; i++) arrayToRenumber[i] = map.get(arrayToRenumber[i]); } /** Create an index array for triangles to be used as input from createCells */ // copied from vtk-util to avoid loading VTK native libraries private static int[] createTriangleCells(int[] cells, int offsetID) { int k = 0; int nCell = cells.length / 3; int[] fCells = new int[nCell * 4]; for (int i = 0; i < nCell * 3; i += 3) { fCells[k++] = 3; fCells[k++] = cells[i] + offsetID; fCells[k++] = cells[i + 1] + offsetID; fCells[k++] = cells[i + 2] + offsetID; } return fCells; } /** * Create an index array for beams to be used as input from createCells * change {a, b, c, d} to {2, a, b, 2, c, d} */ // copied from vtk-util to avoid loading VTK native libraries private static int[] createBeamCells(int[] beams) { int numberOfBeam = beams.length / 2; int k = 0; int j = 0; int[] fCells = new int[3 * numberOfBeam]; for (int i = 0; i < numberOfBeam; i++) { fCells[k++] = 2; fCells[k++] = beams[j++]; fCells[k++] = beams[j++]; } return fCells; } private static class TriaData extends LeafNode.DataProvider { private final AmibeReader.Dim3 provider; private final String id; TriaData(AmibeReader.Dim3 provider, String id) { this.provider = provider; this.id = id; } @Override public void load() { try { SubMesh sm = provider.getSubmeshes().get(0); Group g = sm.getGroup(id); int[] triangles = g.readTria3(); int[] nodesID = makeNodeIDArray(triangles); setNodes(sm.readNodes(nodesID)); renumberArray(nodesID, triangles); setPolys(triangles.length/3, createTriangleCells(triangles, 0)); } catch (IOException ex) { LOGGER.log(Level.SEVERE, ex.getMessage(), ex); } } } private static class BeamData extends LeafNode.DataProvider { private final AmibeReader.Dim3 provider; private final String id; BeamData(AmibeReader.Dim3 provider, String id) { this.provider = provider; this.id = id; } @Override public void load() { try { SubMesh sm = provider.getSubmeshes().get(0); Group g = sm.getGroup(id); int[] beams = g.readBeams(); int[] nodesID = makeNodeIDArray(beams); setNodes(sm.readNodes(nodesID)); renumberArray(nodesID, beams); setLines(createBeamCells(beams)); } catch (IOException ex) { LOGGER.log(Level.SEVERE, ex.getMessage(), ex); } } } public AmibeToMesh(String filePath) throws SAXException, IOException { this(filePath, null); } public AmibeToMesh(String filePath, String[] groupExtraction) throws SAXException, IOException { triaCount = 0; AmibeReader.Dim3 reader = new AmibeReader.Dim3(filePath); SubMesh sm = reader.getSubmeshes().get(0); List<Group> grps = sm.getGroups(); if(groupExtraction == null) { groupExtraction = new String[grps.size()]; for(int i=0; i<groupExtraction.length; i++) groupExtraction[i]=grps.get(i).getName(); } for(String id : groupExtraction) { Group g = sm.getGroup(id); if(g != null) { if(g.getNumberOfTrias() > 0) { triaCount += g.getNumberOfTrias(); triangles.put(id, new TriaData(reader, id)); } if(g.getNumberOfBeams() > 0) beams.put(id, new BeamData(reader, id)); } } } public int getNumberOfTriangles() { return triaCount; } }