/* jCAE stand for Java Computer Aided Engineering. Features are : Small CAD modeler, Finite element mesher, Plugin architecture. Copyright (C) 2005, by EADS CRC Copyright (C) 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; import java.io.*; import java.util.StringTokenizer; import java.util.HashMap; import java.util.Iterator; import java.text.FieldPosition; import java.text.ParsePosition; import java.text.NumberFormat; import java.util.Arrays; import gnu.trove.set.hash.TIntHashSet; import java.util.logging.Logger; public class ExtractShell { private static final Logger logger=Logger.getLogger(ExtractShell.class.getName()); private static int lineno = 0; private static final String CR = System.getProperty("line.separator"); private final static NumberFormat FORMAT_I10=new FormatI10(); public static void main(String args[]) { if (args.length != 2) { System.out.println("Usage : ExtractShell inputfile outputfile"); System.exit(1); } String infile = args[0]; String outfile = args[1]; String facesfile = "faces.inc"; TIntHashSet inodes = null; String line = ""; try { FileInputStream in = new FileInputStream(infile); PrintStream outNodes = new PrintStream(new BufferedOutputStream(new FileOutputStream(outfile))); PrintStream outFaces = new PrintStream(new BufferedOutputStream(new FileOutputStream(facesfile))); BufferedReader rd=new BufferedReader(new InputStreamReader(in)); while ((line=rd.readLine())!=null) { lineno++; if (line.trim().equals("-1")) { line = rd.readLine(); lineno++; if (line.trim().equals("2412")) { // read faces outFaces.println(" -1"+CR+line); inodes = readFace(rd, outFaces); outFaces.println(" -1"); } else { // default group // read end of group while (!(line=rd.readLine().trim()).equals("-1")) lineno++; lineno++; } } } in.close(); in = new FileInputStream(infile); rd = new BufferedReader(new InputStreamReader(in)); lineno = 0; while ((line=rd.readLine())!=null) { lineno++; if (line.trim().equals("-1")) { line = rd.readLine(); lineno++; if (line.trim().equals("2411") || line.trim().equals("781")) { // read nodes outNodes.println(" -1"+CR+line); readNodes(rd, outNodes, inodes); outNodes.println(" -1"); } else if (line.trim().equals("164")) { // read unit outNodes.println(" -1"+CR+line); readUnit(rd, outNodes); outNodes.println(" -1"); } else { // default group // read end of group while (!(line=rd.readLine().trim()).equals("-1")) lineno++; lineno++; } } } in.close(); outNodes.close(); outFaces.close(); // Append faces.inc to output file outNodes = new PrintStream(new BufferedOutputStream(new FileOutputStream(outfile, true))); in = new FileInputStream(facesfile); rd = new BufferedReader(new InputStreamReader(in)); while ((line=rd.readLine())!=null) outNodes.println(line); in.close(); outNodes.close(); } catch(Exception e) { e.printStackTrace(); System.exit(1); } } private static void readUnit(BufferedReader rd, PrintStream outNodes) { String line = ""; try { //retrieve the second line line = rd.readLine(); outNodes.println(line); line = rd.readLine(); lineno += 2; outNodes.println(line); while(!(line = rd.readLine()).trim().equals("-1")) { lineno++; outNodes.println(line); } lineno++; } catch(Exception e) { e.printStackTrace(); System.exit(1); } } private static void readNodes(BufferedReader rd, PrintStream outNodes, TIntHashSet inodes) { logger.fine("Reading nodes"); String line = ""; int count = 0; int inner = 0; try { while(!(line=rd.readLine()).trim().equals("-1")) { lineno++; //First number : the node's id StringTokenizer st = new StringTokenizer(line); int index = Integer.parseInt(st.nextToken()); boolean found = inodes.contains(index); if (found) count++; else inner++; if (found) outNodes.println(line); line = rd.readLine(); lineno++; if (found) outNodes.println(line); } lineno++; } catch(Exception e) { e.printStackTrace(); System.exit(1); } logger.info("Found "+count+" nodes on shell and "+inner+" internal nodes"); } private static TIntHashSet readFace(BufferedReader rd, PrintStream outFaces) { TIntHashSet inodes = new TIntHashSet(); logger.fine("Reading triangles"); HashMap<Face, Face> facemap = new HashMap<Face, Face>(); String line = ""; try { int index = 0; int tetra118 = 0; int inner = 0; Face [] f = new Face[4]; while (!(line=rd.readLine()).trim().equals("-1")) { lineno++; // first line: type of object StringTokenizer st = new StringTokenizer(line); // Volume label is not needed st.nextToken(); String type = st.nextToken(); int p1 = 0, p2 = 0, p3 = 0, p4 = 0; if (type.equals("118")) { tetra118++; line=rd.readLine(); lineno++; // P2 tetrahedron // Vertices are in position 1 3 5 10 st = new StringTokenizer(line); p1 = Integer.valueOf(st.nextToken()).intValue(); st.nextToken(); p2 = Integer.valueOf(st.nextToken()).intValue(); st.nextToken(); p3 = Integer.valueOf(st.nextToken()).intValue(); st.nextToken(); st.nextToken(); st.nextToken(); line=rd.readLine().trim(); lineno++; st = new StringTokenizer(line); st.nextToken(); p4 = Integer.valueOf(st.nextToken()).intValue(); f[0] = new Face(p1, p2, p3); f[1] = new Face(p1, p2, p4); f[2] = new Face(p1, p3, p4); f[3] = new Face(p2, p3, p4); for (int i = 0; i < 4; i++) { if (!facemap.containsKey(f[i])) { index++; f[i].label = index; facemap.put(f[i], f[i]); } else { inner++; f[i] = facemap.get(f[i]); } f[i].count++; } } else if (type.equals("21") || type.equals("22") || type.equals("23") || type.equals("24")) { rd.readLine(); rd.readLine(); lineno += 2; } else { System.out.println("Unknown field type: "+type+" ...ignored"); st.nextToken(); st.nextToken(); st.nextToken(); int nr = Integer.valueOf(st.nextToken()).intValue(); for (int i = nr; i > 0; i -= 8) { rd.readLine(); lineno++; } } } logger.info("Found "+tetra118+" quadratic tetrahedron, with "+inner+" inner triangles"); lineno++; } catch(Exception e) { e.printStackTrace(); System.exit(1); } int index = 0; for (Iterator<Face> it = facemap.values().iterator(); it.hasNext(); ) { Face f = it.next(); if (f.count != 1) continue; index++; outFaces.println(FORMAT_I10.format(index)+" 91 1 1 1 3"); outFaces.println(FORMAT_I10.format(f.v[0])+FORMAT_I10.format(f.v[1])+FORMAT_I10.format(f.v[2])); inodes.add(f.v[0]); inodes.add(f.v[1]); inodes.add(f.v[2]); } logger.info("Found "+index+" triangles"); return inodes; } private static class Face { public final int [] v = new int[3]; public int count = 0; public int label = 0; public Face(int i, int j, int k) { int t; v[0] = i; v[1] = j; v[2] = k; // Sort vertices to speed up this.equals if (v[0] > v[1]) { t = v[0]; v[0] = v[1]; v[1] = t; } if (v[1] > v[2]) { t = v[1]; v[1] = v[2]; v[2] = t; } if (v[0] > v[1]) { t = v[0]; v[0] = v[1]; v[1] = t; } assert v[0] < v[1] && v[1] < v[2]; } @Override public final int hashCode() { return v[0] + v[1] + v[2]; } @Override public final boolean equals(Object o) { if (o == null) return false; if (!(o instanceof Face)) return false; Face that = (Face) o; return (that.v[0] == v[0] && that.v[1] == v[1] && that.v[2] == v[2]); } } public static class FormatI10 extends NumberFormat { /* (non-Javadoc) * @see java.text.NumberFormat#format(double, java.lang.StringBuffer, java.text.FieldPosition) */ @Override public final StringBuffer format(double number, StringBuffer toAppendTo, FieldPosition pos) { return format((long)number, toAppendTo, pos); } /* (non-Javadoc) * @see java.text.NumberFormat#format(long, java.lang.StringBuffer, java.text.FieldPosition) */ @Override public final StringBuffer format(long number, StringBuffer toAppendTo, FieldPosition pos) { StringBuffer s=new StringBuffer(); s.append(number); int n=10-s.length(); if(n>0) { char[] c=new char[n]; Arrays.fill(c, ' '); toAppendTo.append(c); toAppendTo.append(s); } return toAppendTo; } /* (non-Javadoc) * @see java.text.NumberFormat#parse(java.lang.String, java.text.ParsePosition) */ @Override public final Number parse(String source, ParsePosition parsePosition) { throw new UnsupportedOperationException(); } } }