/* jCAE stand for Java Computer Aided Engineering. Features are : Small CAD modeler, Finite element mesher, Plugin architecture. Copyright (C) 2011, 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.amibe.ds; import gnu.trove.map.hash.TIntObjectHashMap; import gnu.trove.map.hash.TObjectIntHashMap; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.PrintStream; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; public class TraceRecord implements TraceInterface { private static final int NR_METHODS = 80; private static final int NR_LINES_BY_METHOD = 40; private static final Logger LOGGER=Logger.getLogger(TraceRecord.class.getName()); private static final String MANY_SPACES = " "; private String logName; private List<String> commands = new ArrayList<String>(); private PrintStream out = System.out; private boolean disabled; private int indentLevel; private String tab = ""; private int cntLines; private int cntMethods; private int cntClasses; private int labelVertex; private final TObjectIntHashMap<Vertex> mapVertexId = new TObjectIntHashMap<Vertex>(); private final TIntObjectHashMap<Vertex> mapIdVertex = new TIntObjectHashMap<Vertex>(); private int labelTriangle; private final TObjectIntHashMap<Triangle> mapTriangleId = new TObjectIntHashMap<Triangle>(); private final TIntObjectHashMap<Triangle> mapIdTriangle = new TIntObjectHashMap<Triangle>(); public void setLogFile(String logName) { this.logName = logName; try { out = new PrintStream(new FileOutputStream(logName+".py")); } catch (FileNotFoundException ex) { LOGGER.log(Level.SEVERE, null, ex); } } public void setHooks(String[] commands) { this.commands = new ArrayList<String>(commands.length); for (String s : commands) this.commands.add(s); } public void createMesh(String meshName, Mesh mesh) { String meshVariable = meshName; println("import org.jcae.mesh.amibe.traits.MeshTraitsBuilder"); println("import org.jcae.mesh.xmldata.MeshWriter"); println("import org.jcae.mesh.amibe.ds.Mesh"); println("cntModule = 0"); println("mods = []"); println("while True:"); startScope(); println("try:"); startScope(); println("mods.append(__import__(\""+logName+"_cl%d\" % cntModule))"); println("cntModule += 1"); endScope(); println("except ImportError:"); startScope(); println("break"); endScope(); endScope(); println("mtb = org.jcae.mesh.amibe.traits.MeshTraitsBuilder.getDefault3D()"); println("mtb.addTraceReplay()"); if (mesh.getNodes() instanceof Set) println("mtb.addNodeSet()"); else println("mtb.addNodeList()"); println(meshVariable+" = org.jcae.mesh.amibe.ds.Mesh(mtb)"); println("[m.c("+meshVariable+") for m in mods]"); println("org.jcae.mesh.xmldata.MeshWriter.writeObject3D("+meshVariable+ ", \""+logName+"-out\""+", None)"); out.close(); try { out = new PrintStream(new FileOutputStream(logName+"_cl"+cntClasses+".py")); } catch (FileNotFoundException ex) { LOGGER.log(Level.SEVERE, null, ex); } println("class c():"); startScope(); println("def startMethodHook(self):"); if (commands.isEmpty()) commands.add("pass"); for (String cmd : commands) println(" "+cmd); println("def __init__(self, m):"); startScope(); println("self.m = m"); mapIdVertex.put(-1, mesh.outerVertex); mapVertexId.put(mesh.outerVertex, -1); println("self.m.getTrace().add(self.m.outerVertex, -1)"); for (Vertex v : mesh.getNodes()) { createAndAdd(v); println("self.m.add(v)"); checkLines(); } for (Triangle t : mesh.getTriangles()) { if (!t.hasAttributes(AbstractHalfEdge.OUTER)) { createAndAdd(t); println("self.m.add(t)"); checkLines(); } } if (mesh.hasAdjacency()) { println("self.m.buildAdjacency()"); addAdjacentTriangles(mesh); } checkLines(); } public void setDisabled(boolean b) { disabled = b; } public boolean getDisabled() { return disabled; } private void createAndAdd(Vertex v) { add(v); println("v = self.m.createVertex("+v.getX()+","+v.getY()+","+v.getZ()+")"); println("self.m.getTrace().add(v, "+labelVertex+")"); } public void add(Vertex v) { labelVertex++; mapIdVertex.put(labelVertex, v); mapVertexId.put(v, labelVertex); } public void add(Vertex v, int id) { throw new UnsupportedOperationException("Not supported yet."); } public void remove(Vertex v) { int id = mapVertexId.get(v); println("self.m.getTrace().remove(self.m.getTrace().getVertex("+id+"))"); mapIdVertex.remove(id); mapVertexId.remove(v); } public Vertex getVertex(int id) { return mapIdVertex.get(id); } public int getVertexId(Vertex v) { return mapVertexId.get(v); } private void createAndAdd(Triangle t) { add(t); println("vTemp0 = self.m.getTrace().getVertex("+mapVertexId.get(t.getV0())+")"); println("vTemp1 = self.m.getTrace().getVertex("+mapVertexId.get(t.getV1())+")"); println("vTemp2 = self.m.getTrace().getVertex("+mapVertexId.get(t.getV2())+")"); println("t = self.m.createTriangle(vTemp0, vTemp1, vTemp2)"); println("t.setGroupId("+t.getGroupId()+")"); if (!t.isReadable()) println("t.setReadable(False)"); if (!t.isWritable()) println("t.setWritable(False)"); println("self.m.getTrace().add(t, "+labelTriangle+")"); } public void add(Triangle t) { labelTriangle++; mapIdTriangle.put(labelTriangle, t); mapTriangleId.put(t, labelTriangle); } public void add(Triangle t, int id) { throw new UnsupportedOperationException("Not supported yet."); } public void remove(Triangle t) { int id = mapTriangleId.get(t); println("self.m.getTrace().remove(self.m.getTrace().getTriangle("+id+"))"); mapIdTriangle.remove(id); mapTriangleId.remove(t); } public Triangle getTriangle(int id) { return mapIdTriangle.get(id); } public int getTriangleId(Triangle t) { return mapTriangleId.get(t); } public void addAdjacentTriangles(Mesh m) { if (disabled) return; for (Triangle t : m.getTriangles()) { if (!t.hasAttributes(AbstractHalfEdge.BOUNDARY | AbstractHalfEdge.NONMANIFOLD)) continue; if (t.hasAttributes(AbstractHalfEdge.OUTER)) continue; AbstractHalfEdge ot = t.getAbstractHalfEdge(); println("t = self.m.getTrace().getTriangle("+mapTriangleId.get(t)+")"); println("ot = t.getAbstractHalfEdge()"); println("for i in xrange(3):"); startScope(); for (int i = 0; i < 3; i++) { ot = ot.next(); println("ot = ot.next()"); if (ot.hasAttributes(AbstractHalfEdge.BOUNDARY | AbstractHalfEdge.NONMANIFOLD)) { Triangle s = ot.sym().getTri(); if (!mapTriangleId.contains(s)) { add(s); println("self.m.getTrace().add(ot.sym().getTri(), "+mapTriangleId.get(s)+")"); } } } endScope(); checkLines(); } } private void startScope() { indentLevel += 1; tab = MANY_SPACES.substring(0, 4*indentLevel); } private void endScope() { indentLevel -= 1; tab = MANY_SPACES.substring(0, 4*indentLevel); } public void edgeSwap(AbstractHalfEdge h) { if (disabled) return; println("t = self.m.getTrace().getTriangle("+mapTriangleId.get(h.getTri())+")"); println("ot = t.getAbstractHalfEdge()"); if (h.getLocalNumber() == 1) println("ot = ot.next()"); else if(h.getLocalNumber() == 2) println("ot = ot.prev()"); println("self.m.edgeSwap(ot)"); checkLines(); } public void edgeCollapse(AbstractHalfEdge h, Vertex v) { if (disabled) return; createAndAdd(v); remove(h.origin()); remove(h.destination()); println("t = self.m.getTrace().getTriangle("+mapTriangleId.get(h.getTri())+")"); println("ot = t.getAbstractHalfEdge()"); if (h.getLocalNumber() == 1) println("ot = ot.next()"); else if(h.getLocalNumber() == 2) println("ot = ot.prev()"); println("self.m.edgeCollapse(ot, self.m.getTrace().getVertex("+mapVertexId.get(v)+"))"); checkLines(); } public void vertexSplitBefore(AbstractHalfEdge h, Vertex v) { if (disabled) return; createAndAdd(v); if (h.hasAttributes(AbstractHalfEdge.NONMANIFOLD)) println("# NONMANIFOLD vertexSplit"); println("t = self.m.getTrace().getTriangle("+mapTriangleId.get(h.getTri())+")"); println("ot = t.getAbstractHalfEdge()"); if (h.getLocalNumber() == 1) println("ot = ot.next()"); else if(h.getLocalNumber() == 2) println("ot = ot.prev()"); println("ot = self.m.vertexSplit(ot, self.m.getTrace().getVertex("+mapVertexId.get(v)+"))"); } public void vertexSplitAfter(AbstractHalfEdge h, Vertex v) { if (disabled) return; if (h.hasAttributes(AbstractHalfEdge.NONMANIFOLD)) { println("fanIt = ot.fanIterator()"); for (Iterator<AbstractHalfEdge> fanIt = h.fanIterator(); fanIt.hasNext();) { println("ot = fanIt.next()"); traceSplitTriangle(fanIt.next()); } } else traceSplitTriangle(h); checkLines(); } /* * When edge (od) is manifold, vertex split adds two triangles * and returned edge is (on) on t1. * When edge (od) is non-manifold, returned edge is either (on) * or (dn). By convention, t1 cannot be outer (and thus t3). * Returned edge either belongs to t1 or t3. * V1 V1 * /'\ /|\ * / \ / | \ * / \ / | \ * / \ / | \ * / t1 \ / t1 v| t3 \ * o +-------------------+ d ---> o +---------+---------+ d * \ t2 / \ t4 | t2 / * \ / \ | / * \ / \ | / * \ / \ | / * \,/ \|/ * V2 V2 */ private void traceSplitTriangle(AbstractHalfEdge h) { if(mapTriangleId.contains(h.getTri())) { // h is on t1 // Add t4 add(h.sym().getTri()); println("self.m.getTrace().add(ot.sym().getTri(), "+mapTriangleId.get(h.sym().getTri())+")"); // Add t3 add(h.next().sym().getTri()); println("self.m.getTrace().add(ot.next().sym().getTri(), " + mapTriangleId.get(h.next().sym().getTri()) + ")"); } else { // h is on t3 // Add t3 add(h.getTri()); println("self.m.getTrace().add(ot.getTri(), "+mapTriangleId.get(h.getTri())+")"); // Add t4. WARNING: t2 and t4 are outer and are not connected! add(h.prev().sym().prev().sym().getTri()); println("self.m.getTrace().add(ot.prev().sym().prev().sym().getTri(), " + mapTriangleId.get(h.prev().sym().prev().sym().getTri()) + ")"); } } public void moveVertex(Vertex v) { if (!disabled && mapVertexId.containsKey(v)) { println("# Vertex "+v); println("v = self.m.getTrace().getVertex("+mapVertexId.get(v)+")"); println("v.moveTo("+v.getX()+", "+v.getY()+", "+v.getZ()+")"); } checkLines(); } private void checkLines() { if (cntLines > NR_LINES_BY_METHOD) { out.println(tab+"self.cont"+cntMethods+"()\n"); if (indentLevel > 0) endScope(); out.println(tab+"def cont"+cntMethods+"(self):"); startScope(); out.println(tab+"self.startMethodHook()"); cntLines = 0; cntMethods++; checkMethods(); } } private void checkMethods() { if (cntMethods > NR_METHODS) { out.println(tab+"pass"); cntClasses++; endScope(); endScope(); out.close(); try { out = new PrintStream(new FileOutputStream(logName+"_cl"+cntClasses+".py")); } catch (FileNotFoundException ex) { LOGGER.log(Level.SEVERE, null, ex); } out.println(tab+"class c():"); startScope(); out.println(tab+"def startMethodHook(self):"); if (commands.isEmpty()) commands.add("pass"); for (String cmd : commands) out.println(tab+" "+cmd); out.println(tab+"def __init__(self, m):"); startScope(); out.println(tab+"self.m = m"); cntMethods = 0; } } public void println(String x) { if (!disabled) { out.println(tab+x); cntLines++; } } public void finish() { cntClasses++; endScope(); endScope(); out.close(); } }