/* * 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 2008, by EADS France */ package org.jcae.vtk; import java.awt.Color; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import org.jcae.opencascade.jni.TopoDS_Edge; import org.jcae.opencascade.jni.TopoDS_Face; import org.jcae.opencascade.jni.TopoDS_Shape; import org.jcae.opencascade.jni.TopoDS_Vertex; import org.jcae.vtk.AbstractNode.ActorCustomiser; import vtk.vtkActor; import vtk.vtkProperty; /** * * @author Julian Ibarz */ public class ViewableCAD extends Viewable { private final OCCMeshExtractor meshExtractor; /** Specify which type of object is selectable */ private ShapeType shapeTypeSelection = ShapeType.FACE; private final Color frontFaceColor = new Color(255 / 2, 255 / 2, 255); private final Color backFaceColor = Color.LIGHT_GRAY;//new Color(255 / 2, 255, 255 / 2); private final Color vertexColor = Color.BLUE; private Color edgeColor = Color.WHITE; private Color freeEdgeColor = Color.GREEN; private final HashMap<TopoDS_Vertex, LeafNode> topoToNodeVertex = new HashMap<TopoDS_Vertex, LeafNode>(); private final HashMap<TopoDS_Edge, LeafNode> topoToNodeEdge = new HashMap<TopoDS_Edge, LeafNode>(); private final HashMap<TopoDS_Face, LeafNode> topoToNodeFaceFront = new HashMap<TopoDS_Face, LeafNode>(); private final HashMap<TopoDS_Face, LeafNode> topoToNodeFaceBack = new HashMap<TopoDS_Face, LeafNode>(); private final HashMap<LeafNode, TopoDS_Shape> nodeToTopo = new HashMap<LeafNode, TopoDS_Shape>(); private Node faces = null; private Node edges = null; private Node vertices = null; private int vertexSize = 4; private int edgeSize = 2; private boolean onlyFreeEdges = false; private Node facesFront, facesBack; public enum ShapeType { VERTEX, EDGE, FACE } private ViewableCAD(OCCMeshExtractor meshExtractor, boolean onlyFreeEdges) { this.meshExtractor = meshExtractor; this.onlyFreeEdges = onlyFreeEdges; computeNodes(); rootNode.refresh(); setShapeTypeSelection(shapeTypeSelection); } public void refresh() { rootNode.removeAllChildren(); computeNodes(); rootNode.refresh(); render(); } public ViewableCAD(TopoDS_Shape shape) { this(new OCCMeshExtractor(shape), false); } public ViewableCAD(TopoDS_Shape shape, boolean onlyFreeEdges) { this(new OCCMeshExtractor(shape), onlyFreeEdges); } public ViewableCAD(String filename) { this(new OCCMeshExtractor(filename), false); } public Color getEdgeColor() { return edgeColor; } public void setEdgeColor(Color edgeColor) { this.edgeColor = edgeColor; for(LeafNode edge : topoToNodeEdge.values()) edge.setColor(edgeColor); edges.refresh(); } public int getEdgeSize() { return edgeSize; } public void setEdgeSize(int edgeSize) { this.edgeSize = edgeSize; // Calling setActorCustomiser() forces edges Node to be refreshed edges.setActorCustomiser(new AbstractNode.ActorCustomiser() { public void customiseActor(vtkActor actor) { actor.GetProperty().SetLineWidth(ViewableCAD.this.edgeSize); } }); edges.refresh(); } protected void testDataChange() { int i = 0; for(LeafNode leaf : rootNode.getLeaves()) { LeafNode.DataProvider data = new LeafNode.DataProvider(); data.setNodes(new float[] {i,0,0,i+1,0,0} ); i+=2; data.setLines(new int[]{2,0,1}); leaf.setDataProvider(data); } rootNode.refresh(); } private void computeNodes() { vertices = new Node(rootNode); vertices.setManager(true); vertices.setActorCustomiser(new AbstractNode.ActorCustomiser() { public void customiseActor(vtkActor actor) { vtkProperty p = actor.GetProperty(); p.SetPointSize(vertexSize); } }); vertices.setSelectionActorCustomiser(new Viewable.SelectionActorCustomiser() { @Override public void customiseActor(vtkActor actor) { super.customiseActor(actor); actor.GetProperty().SetPointSize(vertexSize*2); } }); edges = new Node(rootNode); edges.setManager(true); edges.setActorCustomiser(new AbstractNode.ActorCustomiser() { public void customiseActor(vtkActor actor) { vtkProperty p = actor.GetProperty(); p.SetLineWidth(edgeSize); } }); faces = new Node(rootNode); faces.setActorCustomiser(new AbstractNode.ActorCustomiser() { public void customiseActor(vtkActor actor) { vtkProperty p = actor.GetProperty(); p.BackfaceCullingOn(); } }); facesFront = new Node(faces); facesBack = new Node(faces); facesFront.setManager(true); facesBack.setManager(true); // Add the edges Collection<TopoDS_Edge> freeEdges = meshExtractor.getFreeEdges(); for (TopoDS_Edge edge : meshExtractor.getEdges()) { Color color = edgeColor; if (freeEdges.contains(edge)) color = freeEdgeColor; else if(onlyFreeEdges) continue; LeafNode edgeNode = new LeafNode(edges, new OCCMeshExtractor.EdgeData(edge), color); topoToNodeEdge.put(edge, edgeNode); nodeToTopo.put(edgeNode, edge); } if (!onlyFreeEdges) { // Add vertices for (TopoDS_Vertex vertex : meshExtractor.getVertices()) { LeafNode vertexNode = new LeafNode(vertices, new OCCMeshExtractor.VertexData(vertex), this.vertexColor); topoToNodeVertex.put(vertex, vertexNode); nodeToTopo.put(vertexNode, vertex); } // Add faces for (TopoDS_Face face : meshExtractor.getFaces()) { LeafNode faceNode = new LeafNode(facesFront, new OCCMeshExtractor.FaceData(face, false), this.frontFaceColor); topoToNodeFaceFront.put(face, faceNode); nodeToTopo.put(faceNode, face); LeafNode backFaceNode = new LeafNode(facesBack, new OCCMeshExtractor.FaceData(face, true), this.backFaceColor); topoToNodeFaceBack.put(face, backFaceNode); nodeToTopo.put(backFaceNode, face); } } } public void setTriangleVisible(final boolean b) { ActorCustomiser ac = new AbstractNode.ActorCustomiser() { @Override public void customiseActor(vtkActor actor) { vtkProperty p = actor.GetProperty(); p.LightingOff(); p.SetEdgeVisibility(b ? 1 : 0); p.SetEdgeColor(0.2, 0.2, 0.2); } }; facesBack.setActorCustomiser(ac); facesFront.setActorCustomiser(ac); facesBack.refresh(); facesFront.refresh(); render(); } public Node getEdges() { return edges; } public Collection<TopoDS_Shape> getSelection() { HashSet<TopoDS_Shape> selection = new HashSet<TopoDS_Shape>(selectionNode.size()); for(LeafNode leaf : selectionNode) { selection.add(nodeToTopo.get(leaf)); } return selection; } public void selectSelectionNodes() { for (LeafNode n :rootNode.getLeaves()) n.unselect(); for (LeafNode n : selectionNode) if (n!=null) n.select(); } /** * Set the new selection. * Be careful, the listeners of change selection will not be informed. * * @param selection */ public void setSelection(Collection<TopoDS_Shape> selection) { selectionNode = new HashSet<LeafNode>(selection.size()); for(TopoDS_Shape shape : selection) { if(shape instanceof TopoDS_Vertex) { selectionNode.add(topoToNodeVertex.get((TopoDS_Vertex)shape)); } else if(shape instanceof TopoDS_Edge) { selectionNode.add(topoToNodeEdge.get((TopoDS_Edge)shape)); } else if(shape instanceof TopoDS_Face) { selectionNode.add(topoToNodeFaceFront.get((TopoDS_Face)shape)); selectionNode.add(topoToNodeFaceBack.get((TopoDS_Face)shape)); } } } public OCCMeshExtractor getMeshExtractor() { return meshExtractor; } public ShapeType getShapeTypeSelection() { return shapeTypeSelection; } public void setShapeTypeSelection(ShapeType shapeTypeSelection) { this.shapeTypeSelection = shapeTypeSelection; vertices.setPickable(false); edges.setPickable(false); faces.setPickable(false); setPixelTolerance(0); switch(shapeTypeSelection) { case VERTEX: setPixelTolerance(3); vertices.setPickable(true); break; case EDGE: setPixelTolerance(3); edges.setPickable(true); break; case FACE: faces.setPickable(true); break; default: throw new IllegalStateException(); } } }