package org.simantics.plant3d.editor; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.Session; import org.simantics.db.WriteGraph; import org.simantics.db.exception.DatabaseException; import org.simantics.g3d.ontology.G3D; import org.simantics.g3d.scenegraph.base.INode; import org.simantics.g3d.scenegraph.base.ParentNode; import org.simantics.g3d.vtk.common.AbstractVTKNodeMap; import org.simantics.g3d.vtk.common.VtkView; import org.simantics.objmap.graph.IMapping; import org.simantics.plant3d.ontology.Plant3D; import org.simantics.plant3d.scenegraph.IP3DNode; import org.simantics.plant3d.scenegraph.IP3DVisualNode; import org.simantics.plant3d.scenegraph.P3DParentNode; import org.simantics.plant3d.scenegraph.P3DRootNode; import org.simantics.plant3d.scenegraph.ParameterizedNode; import org.simantics.plant3d.scenegraph.PipeRun; import org.simantics.plant3d.scenegraph.controlpoint.PipeControlPoint; import org.simantics.plant3d.scenegraph.controlpoint.PipingRules; import vtk.vtkProp; import vtk.vtkProp3D; public class P3DNodeMap extends AbstractVTKNodeMap { private static final boolean DEBUG = false; public P3DNodeMap(Session session, IMapping mapping, VtkView panel, P3DRootNode rootNode) { super(session, mapping, panel, rootNode); rootNode.setNodeMap(this); } @Override protected void updateActor(INode n, Set ids) { if (DEBUG) System.out.println("P3DNodeMap update " + debugString(n)); if (!(n instanceof IP3DVisualNode)) { if (n instanceof PipeControlPoint) { n = ((PipeControlPoint)n).getPipelineComponent(); if (n == null) return; } else { return; } } IP3DVisualNode node = (IP3DVisualNode)n; if (DEBUG) { System.out.print("P3DNodeMap update " + debugString(node)); for (String s : ids) System.out.print(" " + s); System.out.println(); } if (ids.contains(Plant3D.URIs.hasGeometry)) { node.visualize(view); updateRenderObjectsFor(node); updateTransform(node); } if (n instanceof ParameterizedNode) { ParameterizedNode geom = (ParameterizedNode)n; for (String id : geom.getParameterMap().keySet()) { if (ids.contains(id)) { node.visualize(view); updateRenderObjectsFor(node); updateTransform(node); break; } } } else if (n instanceof PipeRun) { // FIXME: may require rule based update! PipeRun run = (PipeRun)n; Set ids2 = new HashSet(); ids2.add(Plant3D.URIs.hasGeometry); for (PipeControlPoint pcp : run.getControlPoints()) { updateActor(pcp, ids2); } } if (ids.contains(G3D.URIs.hasPosition) || ids.contains(G3D.URIs.hasOrientation) || ids.contains(G3D.URIs.hasWorldPosition) || ids.contains(G3D.URIs.hasWorldOrientation)) { updateTransform(node); } } private void updateTransform(IP3DNode node) { if (DEBUG) System.out.println("P3DNodeMap update Transform " + debugString(node)); node.update(view.getRenderer()); if (node instanceof ParentNode) { ParentNode p = (ParentNode)node; for (IP3DNode n : p.getNodes()) updateTransform(n); } } @Override protected Collection getActors(INode n) { List props = new ArrayList(); if (!(n instanceof IP3DVisualNode)) return props; IP3DVisualNode node = (IP3DVisualNode)n; for (vtkProp3D p : ((IP3DVisualNode)node).getActors()) props.add(p); return props; } @Override protected void removeActor(INode n) { if (DEBUG) System.out.println("P3DNodeMap.removeActor " + debugString(n)); if (!(n instanceof IP3DVisualNode)) return; IP3DVisualNode node = (IP3DVisualNode)n; remActor(node); if (node instanceof P3DParentNode) { for (IP3DNode n2 : ((P3DParentNode)node).getNodes()) if (n2 instanceof IP3DVisualNode) removeActor((IP3DVisualNode)n2); } } @Override protected void addActor(INode n) { if (DEBUG) System.out.println("P3DNodeMap.addActor " + debugString(n)); if (!(n instanceof IP3DVisualNode)) return; IP3DVisualNode node = (IP3DVisualNode)n; if (hasActor(node)) { if (DEBUG) System.out.println("Node already has an actor"); return; } if (Thread.currentThread() != view.getThreadQueue().getThread()) throw new RuntimeException("Illegal thread."); view.lock(); node.visualize(view); for (vtkProp3D act : node.getActors()) { nodeToActor.add(node, act); actorToNode.put(act, node); } if (DEBUG) System.out.println("Added " + node.getActors().size() + " actors"); if (node instanceof P3DParentNode) { for (IP3DNode n2 : ((P3DParentNode)node).getNodes()) if (n2 instanceof IP3DVisualNode) addActor((IP3DVisualNode)n2); } updateTransform(node); view.unlock(); } private boolean hasActor(IP3DVisualNode node) { List list = nodeToActor.getValues(node); if (list == null || list.size() == 0) return false; return true; } private void remActor(IP3DVisualNode node) { if (Thread.currentThread() != view.getThreadQueue().getThread()) throw new RuntimeException("Illegal thread."); List list = nodeToActor.getValues(node); if (list != null) { for (vtkProp obj : list) { actorToNode.remove(obj); } nodeToActor.remove(node); view.lock(); node.stopVisualize(); view.unlock(); } } @Override protected void update(ReadGraph graph) throws DatabaseException { validate(); // System.out.println("Graph updates"); super.update(graph); validate(); } @Override public void commit(String commitMessage) { validate(); // System.out.println("Graph commit"); super.commit(commitMessage); } @Override protected void commit(WriteGraph graph) throws DatabaseException { super.commit(graph); validateGraph(graph); } @Override protected void doCommit() { // System.out.println("Do commit"); validate(); super.doCommit(); } private void validate() { for (INode node : rootNode.getNodes()) { if (node instanceof PipeRun) PipingRules.validate((PipeRun)node); } } @Override public synchronized void preRender() { // System.out.println("P3DNodeMap preRender"); // super.preRender(); try { // boolean b = false; // synchronized (syncMutex) { // b = PipingRules.update(); // } // if (b) // super.preRender(); boolean b = true; while (b) { updateCycle(); b = PipingRules.update(); } } catch (Exception e) { e.printStackTrace(); } } protected void validateGraph(ReadGraph graph) throws DatabaseException { Plant3D P3D = Plant3D.getInstance(graph); Resource root = (Resource)mapping.inverseGet(rootNode); if (!graph.isInstanceOf(root, P3D.Plant)) throw new DatabaseException("Root is not a Plant"); Set equipment = new HashSet<>(); Set pipeRuns = new HashSet<>(); for (Resource r : graph.getObjects(root, P3D.children)) { if (graph.isInstanceOf(r, P3D.Equipment)) { equipment.add(r); } else if (graph.isInstanceOf(r, P3D.PipeRun)) { pipeRuns.add(r); } else { throw new DatabaseException("Unknown resource " + r+ " " + mapping.get(r)); } } Set nozzles = new HashSet<>(); for (Resource e : equipment) { for (Resource n : graph.getObjects(e, P3D.HasNozzle)) { if (graph.isInstanceOf(n, P3D.Nozzle)) { nozzles.add(n); } else { throw new DatabaseException("Unknown nozzle resource " + n+ " " + mapping.get(n)); } } } Set components = new HashSet<>(); for (Resource run : pipeRuns) { for (Resource c : graph.getObjects(run, P3D.children)) { if (graph.isInstanceOf(c, P3D.PipelineComponent)) { components.add(c); } else { throw new DatabaseException("Unknown component resource " + c + " " + mapping.get(c)); } } } for (Resource c : components) { for (Resource connected : graph.getObjects(c, P3D.Connects)) { if (!components.contains(connected) && !nozzles.contains(connected)) { throw new DatabaseException("Unbrowsable component resource " + connected + " " + mapping.get(connected) +" connected to " + c + " " + mapping.get(c)); } Collection connectedConnected = graph.getObjects(connected, P3D.Connects); if (!connectedConnected.contains(c)) { throw new DatabaseException("Component resource " + c + " " + mapping.get(c) + " is connected to " + connected + " " + mapping.get(connected) +", but its has no connection back."); } } } } }