/* jCAE stand for Java Computer Aided Engineering. Features are : Small CAD
modeler, Finite element mesher, Plugin architecture.
Copyright (C) 2003,2004,2005, by EADS CRC
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 gnu.trove.map.hash.TObjectIntHashMap;
import gnu.trove.iterator.TObjectIntIterator;
import java.io.*;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import java.util.logging.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;
/**
*
* @author Jerome Robert
* @todo handle multiple submesh and <label> element.
*/
public class ComputeEdgesConnectivity
{
private static final Logger logger=Logger.getLogger(ComputeEdgesConnectivity.class.getName());
private static class Edge
{
private final int n1;
private final int n2;
Edge(int n1, int n2)
{
this.n1=n1;
this.n2=n2;
}
final int getN1()
{
return n1;
}
final int getN2()
{
return n2;
}
@Override
public final boolean equals(Object object)
{
if(object instanceof Edge)
{
Edge e=(Edge)object;
return ((e.n1==n1)&&(e.n2==n2))||((e.n1==n2)&&(e.n2==n1));
}
return false;
}
@Override
public final int hashCode()
{
return n1+n2;
}
@Override
public final String toString()
{
return "Edge["+n1+","+n2+"]";
}
}
private final File xmlDir;
private final File xmlFile;
private int numberOfTriangles;
private int numberOfFreeEdges;
private int numberOfMultiEdges;
private Document document;
public ComputeEdgesConnectivity(String dir, String file)
{
xmlFile = new File(dir, file);
xmlDir = new File(dir);
}
public void compute() throws XPathExpressionException, ParserConfigurationException,
SAXException, IOException
{
XPath xpath=XPathFactory.newInstance().newXPath();
document=XMLHelper.parseXML(xmlFile);
String formatVersion = xpath.evaluate("/jcae/@version", document);
if (formatVersion != null && formatVersion.length() > 0)
throw new RuntimeException("File "+xmlFile+" has been written by a newer version of jCAE and cannot be re-read: ");
String trianglesFileName=(String) xpath.evaluate(
"/jcae/mesh/submesh/triangles/file/@location", document, XPathConstants.STRING);
numberOfTriangles=((Double)
xpath.evaluate("/jcae/mesh/submesh/triangles/number/text()",
document, XPathConstants.NUMBER)).intValue();
File trianglesFile=new File(xmlDir, trianglesFileName);
File subDir=trianglesFile.getParentFile();
File freeEdgesFile=new File(subDir, "freeEdges.bin");
File multiEdgesFile=new File(subDir, "multiEdges.bin");
TObjectIntHashMap<Edge> edges=new TObjectIntHashMap<Edge>();
DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(trianglesFile)));
Edge e1, e2, e3;
int n1, n2, n3;
for(int i=0; i<numberOfTriangles; i++)
{
n1=in.readInt();
n2=in.readInt();
n3=in.readInt();
if(n1 < 0 || n2 < 0 || n3 < 0)
continue;
e1=new Edge(n1,n2);
e2=new Edge(n2,n3);
e3=new Edge(n3,n1);
edges.put(e1, edges.get(e1)+1);
edges.put(e2, edges.get(e2)+1);
edges.put(e3, edges.get(e3)+1);
}
logger.fine("Number of imported edges: "+edges.size());
in.close();
TObjectIntIterator<Edge> it=edges.iterator();
DataOutputStream outFree=new DataOutputStream(new BufferedOutputStream(new FileOutputStream(freeEdgesFile)));
DataOutputStream outMulti=new DataOutputStream(new BufferedOutputStream(new FileOutputStream(multiEdgesFile)));
DataOutputStream current;
while(it.hasNext())
{
it.advance();
if( it.value() < 2 )
{
current=outFree;
numberOfFreeEdges++;
}
else if( it.value() > 2 )
{
current=outMulti;
numberOfMultiEdges++;
}
else current=null;
if(current!=null)
{
Edge e=it.key();
current.writeInt(e.getN1());
current.writeInt(e.getN2());
}
}
logger.info("Number of free edges: "+numberOfFreeEdges);
logger.info("Number of multiple edges: "+numberOfMultiEdges);
outFree.close();
outMulti.close();
Element eOldNode=(Element)xpath.evaluate(
"/jcae/mesh/submesh/nodes", document, XPathConstants.NODE);
Element meshElement=(Element)xpath.evaluate(
"/jcae/mesh", document, XPathConstants.NODE);
Element freeMeshElement=XMLHelper.parseXMLString(document,
"<submesh><flag value=\"FreeEdges\"/></submesh>");
freeMeshElement.appendChild(eOldNode.cloneNode(true));
meshElement.appendChild(freeMeshElement);
String s="<beams>";
s+="<number>"+numberOfFreeEdges+"</number>";
s+="<file format=\"integerstream\" location=\""+XMLHelper.canonicalize(xmlDir.toString(), freeEdgesFile.toString())+"\"/>";
s+="</beams>";
Element beamElement=XMLHelper.parseXMLString(document, s);
freeMeshElement.appendChild(beamElement);
Element multiMeshElement=XMLHelper.parseXMLString(document,
"<submesh><flag value=\"MultiEdges\"/></submesh>");
multiMeshElement.appendChild(eOldNode.cloneNode(true));
meshElement.appendChild(multiMeshElement);
s="<beams>";
s+="<number>"+numberOfMultiEdges+"</number>";
s+="<file format=\"integerstream\" location=\""+XMLHelper.canonicalize(xmlDir.toString(), multiEdgesFile.toString())+"\"/>";
s+="</beams>";
beamElement=XMLHelper.parseXMLString(document, s);
multiMeshElement.appendChild(beamElement);
XMLHelper.writeXML(document, xmlFile);
}
}