/* jCAE stand for Java Computer Aided Engineering. Features are : Small CAD
modeler, Finite element mesher, Plugin architecture.
Copyright (C) 2003,2004,2005,2006, by EADS CRC
Copyright (C) 2007,2008, by EADS France
This library 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 library 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 library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.jcae.mesh.xmldata;
import java.util.List;
import org.jcae.mesh.amibe.patch.Mesh2D;
import org.jcae.mesh.amibe.ds.Mesh;
import org.jcae.mesh.amibe.ds.Triangle;
import org.jcae.mesh.amibe.ds.Vertex;
import gnu.trove.map.hash.TObjectIntHashMap;
import gnu.trove.list.array.TIntArrayList;
import gnu.trove.set.hash.TIntHashSet;
import java.io.IOException;
import java.util.Collection;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.TreeSet;
import java.util.logging.Logger;
public class MeshWriter
{
private static final Logger logger=Logger.getLogger(MeshWriter.class.getName());
/**
* Used by {@link #writeObject(org.jcae.mesh.amibe.patch.Mesh2D, String, String, int)}
*/
private static void writeObjectNodes(Collection<Vertex> nodelist,
Vertex outer, AmibeWriter out, TObjectIntHashMap<Vertex> nodeIndex)
throws IOException
{
// Write interior nodes first
int nref = 0;
int i = 0;
for(Vertex v: nodelist)
{
if (v == outer)
continue;
int ref1d = v.getRef();
if (0 == ref1d)
{
out.addNode(v);
nodeIndex.put(v, i);
i++;
}
else
nref++;
}
// Write boundary nodes and 1D references
if (nref > 0)
{
// Duplicate nodes, which are endpoints of 2D degenerated edges,
// are written at the end so that indices of regular vertices
// do not have to be modified during 2D->3D conversion.
ArrayList<Vertex> duplicate3DNodes = new ArrayList<Vertex>();
TIntHashSet refs = new TIntHashSet(nref);
nref = 0;
for(Vertex v: nodelist)
{
if (v == outer)
continue;
int ref1d = v.getRef();
if (0 == ref1d)
continue;
if (!refs.contains(ref1d))
{
refs.add(ref1d);
out.addNode(v);
out.addNodeRef(Math.abs(ref1d));
nodeIndex.put(v, i);
i++;
nref++;
}
else
duplicate3DNodes.add(v);
}
for (Vertex v: duplicate3DNodes)
{
out.addNode(v);
out.addNodeRef(Math.abs(v.getRef()));
nodeIndex.put(v, i);
i++;
nref++;
}
}
// Eventually add outer vertex. It is not written onto disk, but its
// index may be used by outer triangles.
nodeIndex.put(outer, i);
}
/**
* Used by {@link #writeObject(org.jcae.mesh.amibe.patch.Mesh2D, String, String, int)}
*/
private static void writeObjectTriangles(Collection<Triangle> trianglelist,
TObjectIntHashMap<Vertex> nodeIndex, AmibeWriter aw, boolean writeOuter) throws IOException
{
int nrTriangles=0;
// First write inner triangles
for(Triangle f: trianglelist)
{
if (!f.isWritable())
continue;
aw.addTriangle(
nodeIndex.get(f.getV0()),
nodeIndex.get(f.getV1()),
nodeIndex.get(f.getV2()));
nrTriangles++;
}
if(writeOuter)
{
// Next write outer triangles
for(Triangle f: trianglelist)
{
if (f.isWritable())
continue;
aw.addTriangle(
-nodeIndex.get(f.getV0()),
-nodeIndex.get(f.getV1()),
-nodeIndex.get(f.getV2()));
nrTriangles++;
}
}
}
private static void writeObjectGroups(Mesh mesh, AmibeWriter aw)
throws IOException
{
int cnt=0;
HashMap<Integer, TIntArrayList> groupMap = new HashMap<Integer, TIntArrayList>();
HashMap<Integer, TIntArrayList> bgroupMap = new HashMap<Integer, TIntArrayList>();
for(Triangle f: mesh.getTriangles())
{
if (!f.isWritable())
continue;
int id = f.getGroupId();
TIntArrayList list = groupMap.get(id);
if (list == null)
{
list = new TIntArrayList(100);
groupMap.put(id, list);
}
list.add(cnt);
cnt++;
}
List<Vertex> beams = mesh.getBeams();
for(int i = 0 ; i < beams.size(); i+=2)
{
int id = mesh.getBeamGroup(i/2);
TIntArrayList list = bgroupMap.get(id);
if (list == null)
{
list = new TIntArrayList(100);
bgroupMap.put(id, list);
}
list.add(i/2);
}
// Sort group ids
TreeSet<Integer> sortedKeys = new TreeSet<Integer>();
sortedKeys.addAll(groupMap.keySet());
sortedKeys.addAll(bgroupMap.keySet());
for (int id: sortedKeys)
{
String name = mesh.getGroupName(id);
aw.nextGroup(name == null ? Integer.toString(id) : name);
TIntArrayList list = groupMap.get(id);
if(list != null)
for(int i = 0, n = list.size(); i < n; i++)
aw.addTriaToGroup(list.get(i));
list = bgroupMap.get(id);
if(list != null)
for(int i = 0, n = list.size(); i < n; i++)
aw.addBeamToGroup(list.get(i));
}
}
/**
* Write the current object to an Amibe 2D XML file and binary files.
*
* @param submesh mesh to be written on disk
* @param xmlDir name of the XML file
* @param brepFile basename of the brep file
* @param index shape index
*/
public static void writeObject(Mesh2D submesh, String xmlDir, String brepFile, int index)
throws IOException
{
AmibeWriter aw = new AmibeWriter.Dim2(xmlDir, index);
Collection<Triangle> trianglelist = submesh.getTriangles();
Collection<Vertex> nodelist = submesh.getNodes();
if (nodelist == null)
{
nodelist = new LinkedHashSet<Vertex>(trianglelist.size() / 2);
for (Triangle t: trianglelist)
{
if (!t.isWritable())
continue;
for (int j = 0; j < 3; j++)
{
Vertex v = t.getV(j);
if (!nodelist.contains(v))
nodelist.add(v);
}
}
}
TObjectIntHashMap<Vertex> nodeIndex=new TObjectIntHashMap<Vertex>(nodelist.size());
aw.setShape(brepFile);
aw.setSubShape(index);
writeObjectNodes(nodelist, submesh.outerVertex, aw, nodeIndex);
writeObjectTriangles(trianglelist, nodeIndex, aw, true);
aw.finish();
}
/**
* Write the current object to an Amibe 3D XML file and binary files.
*
* @param submesh mesh to be written on disk
* @param xmlDir name of the XML file
* @param brepFile basename of the brep file
*/
public static void writeObject3D(Mesh submesh, String xmlDir, String brepFile)
throws IOException
{
logger.info("Write mesh into "+xmlDir+java.io.File.separator+JCAEXMLData.xml3dFilename);
Collection<Triangle> trianglelist = submesh.getTriangles();
Collection<Vertex> nodelist = submesh.getNodes();
if (nodelist == null)
{
nodelist = new LinkedHashSet<Vertex>(trianglelist.size() / 2);
for (Triangle t: trianglelist)
{
if (!t.isWritable())
continue;
for (int j = 0; j < 3; j++)
{
Vertex v = t.getV(j);
if (!nodelist.contains(v))
nodelist.add(v);
}
}
nodelist.addAll(submesh.getBeams());
}
TObjectIntHashMap<Vertex> nodeIndex=new TObjectIntHashMap<Vertex>(nodelist.size());
AmibeWriter.Dim3 aw = new AmibeWriter.Dim3(xmlDir, false,
submesh.hasPersistentReferences());
if (brepFile != null)
aw.setShape(brepFile);
writeObjectNodes(nodelist, submesh.outerVertex, aw, nodeIndex);
writeObjectTriangles(trianglelist, nodeIndex, aw, false);
writeObjectGroups(submesh, aw);
writeObjectNodeGroups(submesh, aw, nodeIndex);
List<Vertex> beams = submesh.getBeams();
for(int i = 0; i<beams.size(); i+=2)
aw.addBeam(
nodeIndex.get(beams.get(i)),
nodeIndex.get(beams.get(i+1)));
aw.finish();
}
private static void writeObjectNodeGroups(Mesh submesh, AmibeWriter.Dim3 aw,
TObjectIntHashMap<Vertex> nodeIndex) throws IOException {
for(Entry<String, Collection<Vertex>> e: submesh.getVertexGroup().entrySet())
{
aw.nextNodeGroup(e.getKey());
for(Vertex v:e.getValue())
aw.addNodeToGroup(nodeIndex.get(v));
}
}
}