]> gerrit.simantics Code Review - simantics/3d.git/commitdiff
Very crude API for creating pipeline components 27/3127/1
authorMarko Luukkainen <marko.luukkainen@semantum.fi>
Tue, 20 Aug 2019 13:32:05 +0000 (16:32 +0300)
committerMarko Luukkainen <marko.luukkainen@semantum.fi>
Tue, 20 Aug 2019 13:32:05 +0000 (16:32 +0300)
gitlab #28

Change-Id: I2c593b81fdcb3a3b996369b4bb2a8a9f6eb43906

org.simantics.g3d/src/org/simantics/g3d/scl/ScriptNodeMap.java
org.simantics.plant3d/scl/Plant3d/Utils/ComponentUtils.scl
org.simantics.plant3d/src/org/simantics/plant3d/actions/AddComponentAction.java
org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/InlineComponent.java
org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/controlpoint/PipeControlPoint.java
org.simantics.plant3d/src/org/simantics/plant3d/utils/ComponentUtils.java

index 359f5c3e137b5b416b4794b9e66d09e8de212857..4af8e5a0b829a8e3caf2154c3f490db49da7e8ad 100644 (file)
@@ -225,14 +225,15 @@ public abstract class ScriptNodeMap<E extends INode> implements NodeMap<Object,E
             return;
         if (DEBUG)System.out.println("domainModified");
         // FIXME : this is called by IMapping id DB thread
-        session.asyncRequest(new ReadRequest() {
-            
-            @SuppressWarnings("unchecked")
-            @Override
-            public void run(ReadGraph graph) throws DatabaseException {
-                update(graph);
-            }
-        });
+        dirty = true;
+//        session.asyncRequest(new ReadRequest() {
+//            
+//            @SuppressWarnings("unchecked")
+//            @Override
+//            public void run(ReadGraph graph) throws DatabaseException {
+//                update(graph);
+//            }
+//        });
         
     }
     
@@ -289,6 +290,13 @@ public abstract class ScriptNodeMap<E extends INode> implements NodeMap<Object,E
                 requestCommit = false;
                 doCommit();
             }
+            session.syncRequest(new ReadRequest() { 
+              @SuppressWarnings("unchecked")
+              @Override
+              public void run(ReadGraph graph) throws DatabaseException {
+                  update(graph);
+              }
+            });
         }
     }
     
index 8778eed04261968743fb7a77fae5c0b8cbe38020..c3ef6365677dcd22fd347564c7f63edc47cd97b6 100644 (file)
@@ -17,4 +17,65 @@ importJava "org.simantics.plant3d.utils.ComponentUtils" where
    createBranchSplit :: P3DRootNode -> <Proc> PipelineComponent
    createEquipment :: P3DRootNode -> Item -> <Proc> Equipment
    createDefaultNozzle :: P3DRootNode -> Equipment -> <Proc> Nozzle
+   
+   @JavaName addComponent
+   addComponent :: P3DRootNode -> PipelineComponent -> InsertInstruction -> <Proc> PipelineComponent
+   
+importJava "org.simantics.plant3d.utils.ComponentUtils$InsertInstruction" where
+   data InsertInstruction
+   
+   @JavaName "<init>"
+   createInsertInstruction :: () -> InsertInstruction
+   
+   setTypeUri :: InsertInstruction -> String -> <Proc> ()
+   setPosition :: InsertInstruction -> PositionType -> <Proc> ()
+   setInsertPosition :: InsertInstruction -> PositionType -> <Proc> ()
+   setLength :: InsertInstruction -> Maybe Double -> <Proc> ()
+   setAngle :: InsertInstruction -> Maybe Double -> <Proc> ()
+   setDiameter :: InsertInstruction -> Maybe Double -> <Proc> ()
+   setTurnRadius :: InsertInstruction -> Maybe Double -> <Proc> ()
+   
+createFixedLength :: String -> PositionType -> PositionType -> <Proc> InsertInstruction 
+createFixedLength typeUri position insertPosition = do
+  instruction = createInsertInstruction ()
+  setTypeUri instruction typeUri
+  setPosition instruction position
+  setInsertPosition instruction insertPosition
+  instruction
+  
+createVariableLength :: String -> PositionType -> PositionType -> Double -> <Proc> InsertInstruction 
+createVariableLength typeUri position insertPosition length = do
+  instruction = createInsertInstruction ()
+  setTypeUri instruction typeUri
+  setPosition instruction position
+  setInsertPosition instruction insertPosition
+  setLength instruction (Just length)
+  instruction
+  
+createFixedTurn :: String -> PositionType -> PositionType -> <Proc> InsertInstruction 
+createFixedTurn typeUri position insertPosition = do
+  instruction = createInsertInstruction ()
+  setTypeUri instruction typeUri
+  setPosition instruction position
+  setInsertPosition instruction insertPosition
+  instruction
+  
+createVariableTurn :: String -> PositionType -> PositionType -> Double -> <Proc> InsertInstruction 
+createVariableTurn typeUri position insertPosition angle = do
+  instruction = createInsertInstruction ()
+  setTypeUri instruction typeUri
+  setPosition instruction position
+  setInsertPosition instruction insertPosition
+  setAngle instruction (Just angle)
+  instruction
+   
+createSizeChange :: String -> PositionType -> PositionType -> Double -> Double -> <Proc> InsertInstruction 
+createSizeChange typeUri position insertPosition diameter radius = do
+  instruction = createInsertInstruction ()
+  setTypeUri instruction typeUri
+  setPosition instruction position
+  setInsertPosition instruction insertPosition
+  setDiameter instruction (Just diameter)
+  setTurnRadius instruction (Just radius)
+  instruction   
    
\ No newline at end of file
index 119820178c8e9ff2b02275788608fe5937a12fba..defee7024561616c386089806168175f591399cc 100644 (file)
@@ -27,6 +27,7 @@ import org.simantics.plant3d.scenegraph.controlpoint.PipeControlPoint.PositionTy
 import org.simantics.plant3d.scenegraph.controlpoint.PipingRules;
 import org.simantics.plant3d.utils.ComponentUtils;
 import org.simantics.plant3d.utils.Item;
+import org.simantics.plant3d.utils.ComponentUtils.InsertInstruction;
 import org.simantics.plant3d.utils.Item.Type;
 import org.simantics.utils.threads.ThreadUtils;
 import org.simantics.utils.ui.ExceptionUtils;
@@ -168,162 +169,175 @@ public class AddComponentAction extends vtkSwtAction {
        }
        
        public void doInsert(PositionType position) {
-               try  {
-                       PipelineComponent newComponent = ComponentUtils.createComponent(root,toAdd.getUri());
-                       PipeControlPoint newPcp = newComponent.getControlPoint();
-                       
-                       PipeControlPoint toPcp = component.getControlPoint();
-                       PipeRun pipeRun = toPcp.getPipeRun();
-                       
-                       Vector3d dir = null;
-                       Vector3d pos = null;
-               
-                       
-                       if (toPcp.isInline()) {
-                           switch (position) {
-                   case NEXT: 
-                       if (toPcp.isDualInline())
-                           toPcp = toPcp.getSubPoint().get(0);
-                       
-                       break;
-                   case PREVIOUS:
-                       if (toPcp.isDualSub())
-                           toPcp = toPcp.parent;
-                   }
-                           Vector3d start = new Vector3d();
-                           Vector3d end = new Vector3d();
-                   dir = new Vector3d();
-                   toPcp.getInlineControlPointEnds(start, end, dir);
-                   dir.normalize();
-                  switch (position) {
-                case NEXT:
-                    pos = new Vector3d(end);
-                    break;
-                case PREVIOUS:
-                    pos = new Vector3d(start);
-                    break;
-                case SPLIT:
-                    pos = new Vector3d(toPcp.getWorldPosition());
-                    break;
-                }
-                  
-                       } else if (toPcp.isDirected()) {
-                           dir = new Vector3d(toPcp.getDirection(Direction.NEXT));
-                           pos = new Vector3d(toPcp.getWorldPosition());
-                       } else if (toPcp.isTurn() && toPcp.isFixed()) {
-                           dir = new Vector3d(toPcp.getDirection(position == PositionType.NEXT ? Direction.NEXT : Direction.PREVIOUS));
-                pos = new Vector3d(toPcp.getWorldPosition());
-                if (!lengthAdjustable) {
-                    Vector3d v = new Vector3d(dir);
-                    v.scale(toPcp.getInlineLength());
-                    pos.add(v);
-                } else {
-                    if (insertPosition == PositionType.NEXT) {
-                        Vector3d v = new Vector3d(dir);
-                        v.scale(toPcp.getInlineLength());
-                        pos.add(v);
-                    } else if (insertPosition == PositionType.SPLIT) {
-                        // scale 0.5*length so that we don't remove the length twice from the new component
-                        Vector3d v = new Vector3d(dir);
-                        v.scale(toPcp.getInlineLength()*0.5);  
-                        pos.add(v);
-                    }
-                }
-                       }
-                       
-                       
-                       if (!toAdd.isSizeChange()) {
-                               String name = component.getPipeRun().getUniqueName(toAdd.getName());
-                               newComponent.setName(name);
-
-                               pipeRun.addChild(newComponent);
-                               if (toAdd.isVariable()) {
-                                       // TODO: these options are not stored into DB. Should they?!
-                                       if (toAdd.getType() == Type.INLINE) {
-                                               newPcp.setLength(length);
-//                                             newPcp.setFixed(true);
-                                       } else if (toAdd.getType() == Type.TURN) {
-                                               newPcp.setTurnAngle(angle);
-//                                             newPcp.setFixed(true);
-                                       }
-                               }
-                               newComponent.updateParameters();
-                               
-                           Vector3d v = new Vector3d(dir);
-                           if (insertAdjustable) {
-                           if (insertPosition == PositionType.NEXT)
-                               v.scale(newComponent.getControlPoint().getInlineLength());
-                           else if (insertPosition == PositionType.SPLIT)
-                               v.set(0, 0, 0);
-                           else if (insertPosition == PositionType.PREVIOUS)
-                               v.scale(-newComponent.getControlPoint().getInlineLength());
-                           } else {
-                               v.scale(newComponent.getControlPoint().getInlineLength());
-                           }
-                switch (position) {
-                case NEXT:
-                    pos.add(v);
-                    break;
-                case PREVIOUS:
-                    pos.sub(v);
-                    break;
-                case SPLIT:
-                    break;
-                }
-                               
-                               switch (position) {
-                               case NEXT: 
-                                       if (toPcp.isDualInline())
-                                               toPcp = toPcp.getSubPoint().get(0);
-                                       newPcp.insert(toPcp, Direction.NEXT);
-                                       newPcp.setWorldPosition(pos);
-                                       break;
-                               case PREVIOUS:
-                                       if (toPcp.isDualSub())
-                                               toPcp = toPcp.parent;
-                                       newPcp.insert(toPcp, Direction.PREVIOUS);
-                                       newPcp.setWorldPosition(pos);
-                                       break;
-                               case SPLIT:
-                                       PipingRules.splitVariableLengthComponent(newComponent, (InlineComponent)component, true);
-                               }
-                       } else {
-                               PipeRun other = new PipeRun();
-                               String n = root.getUniqueName("PipeRun");
-                               other.setName(n);
-                               other.setPipeDiameter(diameter);
-                               other.setTurnRadius(turnRadius);
-                               root.addChild(other);
-                               
-                               
-                               if (position == PositionType.NEXT) {
-                                       PipingRules.addSizeChange(false, pipeRun, other, (InlineComponent)newComponent, toPcp, null);
-                       } else if (position == PositionType.PREVIOUS){
-                               PipingRules.addSizeChange(true, pipeRun, other, (InlineComponent)newComponent, toPcp, null);
-                       }
-                               newPcp.setWorldPosition(pos);
-                               // TODO : chicken-egg problem
-                               newComponent.updateParameters();
-                           Vector3d v = new Vector3d(dir);
-                v.scale(newComponent.getControlPoint().getLength()*0.5);
-                switch (position) {
-                case NEXT:
-                    pos.add(v);
-                    break;
-                case PREVIOUS:
-                    pos.sub(v);
-                    break;
-                case SPLIT:
-                    break;
-                }
-                newPcp.setWorldPosition(pos);
-                               
-                       }
-                       
-                       
-               } catch (Exception e) {
-                       ExceptionUtils.logAndShowError("Cannot add component", e);
-               }
+           try  {
+               InsertInstruction inst = new InsertInstruction();
+               inst.typeUri = toAdd.getUri();
+               inst.angle = angle;
+               inst.diameter = diameter;
+               inst.length = length;
+               inst.turnRadius = turnRadius;
+               inst.insertPosition = insertPosition;
+               inst.position = position;
+               ComponentUtils.addComponent(root, component, inst);
+           } catch (Exception e) {
+           ExceptionUtils.logAndShowError("Cannot add component", e);
+        }
+//             try  {
+//                     PipelineComponent newComponent = ComponentUtils.createComponent(root,toAdd.getUri());
+//                     PipeControlPoint newPcp = newComponent.getControlPoint();
+//                     
+//                     PipeControlPoint toPcp = component.getControlPoint();
+//                     PipeRun pipeRun = toPcp.getPipeRun();
+//                     
+//                     Vector3d dir = null;
+//                     Vector3d pos = null;
+//             
+//                     
+//                     if (toPcp.isInline()) {
+//                         switch (position) {
+//                 case NEXT: 
+//                     if (toPcp.isDualInline())
+//                         toPcp = toPcp.getSubPoint().get(0);
+//                     
+//                     break;
+//                 case PREVIOUS:
+//                     if (toPcp.isDualSub())
+//                         toPcp = toPcp.parent;
+//                 }
+//                         Vector3d start = new Vector3d();
+//                         Vector3d end = new Vector3d();
+//                 dir = new Vector3d();
+//                 toPcp.getInlineControlPointEnds(start, end, dir);
+//                 dir.normalize();
+//                switch (position) {
+//                case NEXT:
+//                    pos = new Vector3d(end);
+//                    break;
+//                case PREVIOUS:
+//                    pos = new Vector3d(start);
+//                    break;
+//                case SPLIT:
+//                    pos = new Vector3d(toPcp.getWorldPosition());
+//                    break;
+//                }
+//                
+//                     } else if (toPcp.isDirected()) {
+//                         dir = new Vector3d(toPcp.getDirection(Direction.NEXT));
+//                         pos = new Vector3d(toPcp.getWorldPosition());
+//                     } else if (toPcp.isTurn() && toPcp.isFixed()) {
+//                         dir = new Vector3d(toPcp.getDirection(position == PositionType.NEXT ? Direction.NEXT : Direction.PREVIOUS));
+//                pos = new Vector3d(toPcp.getWorldPosition());
+//                if (!lengthAdjustable) {
+//                    Vector3d v = new Vector3d(dir);
+//                    v.scale(toPcp.getInlineLength());
+//                    pos.add(v);
+//                } else {
+//                    if (insertPosition == PositionType.NEXT) {
+//                        Vector3d v = new Vector3d(dir);
+//                        v.scale(toPcp.getInlineLength());
+//                        pos.add(v);
+//                    } else if (insertPosition == PositionType.SPLIT) {
+//                        // scale 0.5*length so that we don't remove the length twice from the new component
+//                        Vector3d v = new Vector3d(dir);
+//                        v.scale(toPcp.getInlineLength()*0.5);  
+//                        pos.add(v);
+//                    }
+//                }
+//                     }
+//                     
+//                     
+//                     if (!toAdd.isSizeChange()) {
+//                             String name = component.getPipeRun().getUniqueName(toAdd.getName());
+//                             newComponent.setName(name);
+//
+//                             pipeRun.addChild(newComponent);
+//                             if (toAdd.isVariable()) {
+//                                     // TODO: these options are not stored into DB. Should they?!
+//                                     if (toAdd.getType() == Type.INLINE) {
+//                                             newPcp.setLength(length);
+////                                           newPcp.setFixed(true);
+//                                     } else if (toAdd.getType() == Type.TURN) {
+//                                             newPcp.setTurnAngle(angle);
+////                                           newPcp.setFixed(true);
+//                                     }
+//                             }
+//                             newComponent.updateParameters();
+//                             
+//                         Vector3d v = new Vector3d(dir);
+//                         if (insertAdjustable) {
+//                         if (insertPosition == PositionType.NEXT)
+//                             v.scale(newComponent.getControlPoint().getInlineLength());
+//                         else if (insertPosition == PositionType.SPLIT)
+//                             v.set(0, 0, 0);
+//                         else if (insertPosition == PositionType.PREVIOUS)
+//                             v.scale(-newComponent.getControlPoint().getInlineLength());
+//                         } else {
+//                             v.scale(newComponent.getControlPoint().getInlineLength());
+//                         }
+//                switch (position) {
+//                case NEXT:
+//                    pos.add(v);
+//                    break;
+//                case PREVIOUS:
+//                    pos.sub(v);
+//                    break;
+//                case SPLIT:
+//                    break;
+//                }
+//                             
+//                             switch (position) {
+//                             case NEXT: 
+//                                     if (toPcp.isDualInline())
+//                                             toPcp = toPcp.getSubPoint().get(0);
+//                                     newPcp.insert(toPcp, Direction.NEXT);
+//                                     newPcp.setWorldPosition(pos);
+//                                     break;
+//                             case PREVIOUS:
+//                                     if (toPcp.isDualSub())
+//                                             toPcp = toPcp.parent;
+//                                     newPcp.insert(toPcp, Direction.PREVIOUS);
+//                                     newPcp.setWorldPosition(pos);
+//                                     break;
+//                             case SPLIT:
+//                                     PipingRules.splitVariableLengthComponent(newComponent, (InlineComponent)component, true);
+//                             }
+//                     } else {
+//                             PipeRun other = new PipeRun();
+//                             String n = root.getUniqueName("PipeRun");
+//                             other.setName(n);
+//                             other.setPipeDiameter(diameter);
+//                             other.setTurnRadius(turnRadius);
+//                             root.addChild(other);
+//                             
+//                             
+//                             if (position == PositionType.NEXT) {
+//                                     PipingRules.addSizeChange(false, pipeRun, other, (InlineComponent)newComponent, toPcp, null);
+//                     } else if (position == PositionType.PREVIOUS){
+//                             PipingRules.addSizeChange(true, pipeRun, other, (InlineComponent)newComponent, toPcp, null);
+//                     }
+//                             newPcp.setWorldPosition(pos);
+//                             // TODO : chicken-egg problem
+//                             newComponent.updateParameters();
+//                         Vector3d v = new Vector3d(dir);
+//                v.scale(newComponent.getControlPoint().getLength()*0.5);
+//                switch (position) {
+//                case NEXT:
+//                    pos.add(v);
+//                    break;
+//                case PREVIOUS:
+//                    pos.sub(v);
+//                    break;
+//                case SPLIT:
+//                    break;
+//                }
+//                newPcp.setWorldPosition(pos);
+//                             
+//                     }
+//                     
+//                     
+//             } catch (Exception e) {
+//                     ExceptionUtils.logAndShowError("Cannot add component", e);
+//             }
        }
        
        public boolean mouseClicked(MouseEvent e) {
index 61a4bcb26118977f9b38c5224a44b4c1d2de38b6..1fd83da110d3f36bf8739db214d325444d8e74e9 100644 (file)
@@ -51,6 +51,10 @@ public class InlineComponent extends PipelineComponent {
                return !controlPoint.isFixed();
        }
        
+       public boolean isSizeChange() {
+           return controlPoint.isSizeChange();
+       }
+       
        @RelatedGetValue(Plant3D.URIs.HasRotationAngle)
        @GetPropertyValue(name="Rotation Angle", value=Plant3D.URIs.HasRotationAngle, tabId = "Default")
        public Double getRotationAngle() {
index 2d8c00b22f5c20f7e09da25b99da30db78b1662d..8e3e6bbdc1c926d28270e3900f7d8648a7f01cf3 100644 (file)
@@ -289,7 +289,7 @@ public class PipeControlPoint extends G3DNode implements IP3DNode {
     }
        
        public void setTurnAngle(Double turnAngle) {
-               if (Double.isInfinite(turnAngle) || Double.isNaN(turnAngle)) {
+               if (turnAngle == null || Double.isInfinite(turnAngle) || Double.isNaN(turnAngle)) {
                        return;
                }
                if (this.turnAngle != null && Math.abs(this.turnAngle-turnAngle) < MathTools.NEAR_ZERO)
index 800b6fde93479bc7c11a6468359a1f43d26f0d34..4a4888090aff7a0dd08756d35b6ba8e4607bdd02 100644 (file)
@@ -5,10 +5,13 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import javax.vecmath.Vector3d;
+
 import org.simantics.Simantics;
 import org.simantics.db.ReadGraph;
 import org.simantics.db.Resource;
 import org.simantics.db.common.request.ReadRequest;
+import org.simantics.db.common.utils.NameUtils;
 import org.simantics.db.exception.DatabaseException;
 import org.simantics.g3d.scenegraph.GeometryProvider;
 import org.simantics.layer0.Layer0;
@@ -21,12 +24,19 @@ import org.simantics.plant3d.scenegraph.P3DRootNode;
 import org.simantics.plant3d.scenegraph.PipeRun;
 import org.simantics.plant3d.scenegraph.PipelineComponent;
 import org.simantics.plant3d.scenegraph.TurnComponent;
+import org.simantics.plant3d.scenegraph.controlpoint.PipeControlPoint;
+import org.simantics.plant3d.scenegraph.controlpoint.PipingRules;
+import org.simantics.plant3d.scenegraph.controlpoint.PipeControlPoint.Direction;
+import org.simantics.plant3d.scenegraph.controlpoint.PipeControlPoint.PositionType;
+import org.simantics.plant3d.utils.Item.Type;
+import org.simantics.utils.ui.ExceptionUtils;
 
 public class ComponentUtils {
 
        
        private static Map<String,Class<? extends PipelineComponent>> clazzes = new HashMap<String, Class<? extends PipelineComponent>>();
        private static Map<String,GeometryProvider> providers = new HashMap<String,GeometryProvider>();
+       private static Map<String,String> names = new HashMap<String,String>();
        
        public static void preloadCache() {
                Simantics.getSession().asyncRequest(new ReadRequest() {
@@ -89,6 +99,7 @@ public class ComponentUtils {
                        providers.put(typeURI, provider);
                        if (graph.isInheritedFrom(type, p3d.PipelineComponent))
                            clazzes.put(typeURI,getClazz(graph, type));
+                       names.put(typeURI, NameUtils.getSafeName(graph, type));
                        return;
                }
                throw new DatabaseException("Cannot find component for " + typeURI);
@@ -189,8 +200,7 @@ public class ComponentUtils {
        }
        
        public static Equipment createEquipment(P3DRootNode root, Item equipmentType) throws Exception {
-           Equipment equipment = root.createEquipment();
-        equipment.setType(equipmentType.getUri());
+           Equipment equipment = createEquipment(root, equipmentType.getUri());
         String n = root.getUniqueName(equipmentType.getName());
         equipment.setName(n);
         root.addChild(equipment);
@@ -218,4 +228,250 @@ public class ComponentUtils {
         // root.getNodeMap().commit("Add nozzle " + n);
         return nozzle;
        }
+       
+       public static class InsertInstruction {
+           public String typeUri;
+           
+           public PositionType position = PositionType.NEXT;
+           public PositionType insertPosition = PositionType.NEXT;
+           
+           // Reducer requires pipe specs
+           public Double diameter;
+           public Double turnRadius;
+           
+           // Variable length 
+           public Double length;
+           
+           // Variable angle
+           public Double angle;
+
+        public String getTypeUri() {
+            return typeUri;
+        }
+
+        public void setTypeUri(String typeUri) {
+            this.typeUri = typeUri;
+        }
+
+        public PositionType getPosition() {
+            return position;
+        }
+
+        public void setPosition(PositionType position) {
+            this.position = position;
+        }
+
+        public PositionType getInsertPosition() {
+            return insertPosition;
+        }
+
+        public void setInsertPosition(PositionType insertPosition) {
+            this.insertPosition = insertPosition;
+        }
+
+        public Double getDiameter() {
+            return diameter;
+        }
+
+        public void setDiameter(Double diameter) {
+            this.diameter = diameter;
+        }
+
+        public Double getTurnRadius() {
+            return turnRadius;
+        }
+
+        public void setTurnRadius(Double turnRadius) {
+            this.turnRadius = turnRadius;
+        }
+
+        public Double getLength() {
+            return length;
+        }
+
+        public void setLength(Double length) {
+            this.length = length;
+        }
+
+        public Double getAngle() {
+            return angle;
+        }
+
+        public void setAngle(Double angle) {
+            this.angle = angle;
+        }
+
+       }
+       
+       public static PipelineComponent addComponent(P3DRootNode root, PipelineComponent component,  InsertInstruction inst) throws Exception {
+          
+        PipelineComponent newComponent = ComponentUtils.createComponent(root, inst.typeUri);
+        PipeControlPoint newPcp = newComponent.getControlPoint();
+        
+        PipeControlPoint toPcp = component.getControlPoint();
+        PipeRun pipeRun = toPcp.getPipeRun();
+        
+        String typeName = names.get(inst.typeUri);
+        if (typeName == null)
+            typeName = "Component";
+        
+        Vector3d dir = null;
+        Vector3d pos = null;
+    
+        PositionType position = inst.position;
+        PositionType insertPosition = inst.insertPosition;
+        boolean lengthAdjustable = false;
+        if (newComponent instanceof InlineComponent) {
+            lengthAdjustable = ((InlineComponent)newComponent).isVariableLength(); 
+        }
+        boolean insertAdjustable = false;
+        if (component instanceof InlineComponent) {
+            insertAdjustable = ((InlineComponent)component).isVariableLength();
+        }
+        boolean sizeChange = false;
+        if (newComponent instanceof InlineComponent) {
+            sizeChange = ((InlineComponent)newComponent).isSizeChange();
+        }
+        
+        if (toPcp.isInline()) {
+            switch (position) {
+            case NEXT: 
+                if (toPcp.isDualInline())
+                    toPcp = toPcp.getSubPoint().get(0);
+                
+                break;
+            case PREVIOUS:
+                if (toPcp.isDualSub())
+                    toPcp = toPcp.parent;
+            }
+            Vector3d start = new Vector3d();
+            Vector3d end = new Vector3d();
+            dir = new Vector3d();
+            toPcp.getInlineControlPointEnds(start, end, dir);
+            dir.normalize();
+           switch (position) {
+            case NEXT:
+                pos = new Vector3d(end);
+                break;
+            case PREVIOUS:
+                pos = new Vector3d(start);
+                break;
+            case SPLIT:
+                pos = new Vector3d(toPcp.getWorldPosition());
+                break;
+            }
+           
+        } else if (toPcp.isDirected()) {
+            dir = new Vector3d(toPcp.getDirection(Direction.NEXT));
+            pos = new Vector3d(toPcp.getWorldPosition());
+        } else if (toPcp.isTurn() && toPcp.isFixed()) {
+            dir = new Vector3d(toPcp.getDirection(position == PositionType.NEXT ? Direction.NEXT : Direction.PREVIOUS));
+            pos = new Vector3d(toPcp.getWorldPosition());
+            if (!lengthAdjustable) {
+                Vector3d v = new Vector3d(dir);
+                v.scale(toPcp.getInlineLength());
+                pos.add(v);
+            } else {
+                if (insertPosition == PositionType.NEXT) {
+                    Vector3d v = new Vector3d(dir);
+                    v.scale(toPcp.getInlineLength());
+                    pos.add(v);
+                } else if (insertPosition == PositionType.SPLIT) {
+                    // scale 0.5*length so that we don't remove the length twice from the new component
+                    Vector3d v = new Vector3d(dir);
+                    v.scale(toPcp.getInlineLength()*0.5);  
+                    pos.add(v);
+                }
+            }
+        }
+        
+        
+        if (!sizeChange) {
+            String name = component.getPipeRun().getUniqueName(typeName);
+            newComponent.setName(name);
+
+            pipeRun.addChild(newComponent);
+            // TODO: these options are not stored into DB. Should they?!
+            if (newComponent instanceof InlineComponent && ((InlineComponent)newComponent).isVariableLength()) {
+                newPcp.setLength(inst.length);
+            } else if (newComponent instanceof TurnComponent && ((TurnComponent)newComponent).isVariableAngle()) {
+                newPcp.setTurnAngle(inst.angle);
+            }
+            
+            newComponent.updateParameters();
+            
+            Vector3d v = new Vector3d(dir);
+            if (insertAdjustable) {
+                if (insertPosition == PositionType.NEXT)
+                    v.scale(newComponent.getControlPoint().getInlineLength());
+                else if (insertPosition == PositionType.SPLIT)
+                    v.set(0, 0, 0);
+                else if (insertPosition == PositionType.PREVIOUS)
+                    v.scale(-newComponent.getControlPoint().getInlineLength());
+            } else {
+                v.scale(newComponent.getControlPoint().getInlineLength());
+            }
+            switch (position) {
+            case NEXT:
+                pos.add(v);
+                break;
+            case PREVIOUS:
+                pos.sub(v);
+                break;
+            case SPLIT:
+                break;
+            }
+            
+            switch (position) {
+            case NEXT: 
+                if (toPcp.isDualInline())
+                    toPcp = toPcp.getSubPoint().get(0);
+                newPcp.insert(toPcp, Direction.NEXT);
+                newPcp.setWorldPosition(pos);
+                break;
+            case PREVIOUS:
+                if (toPcp.isDualSub())
+                    toPcp = toPcp.parent;
+                newPcp.insert(toPcp, Direction.PREVIOUS);
+                newPcp.setWorldPosition(pos);
+                break;
+            case SPLIT:
+                PipingRules.splitVariableLengthComponent(newComponent, (InlineComponent)component, true);
+            }
+        } else {
+            PipeRun other = new PipeRun();
+            String n = root.getUniqueName("PipeRun");
+            other.setName(n);
+            other.setPipeDiameter(inst.diameter);
+            other.setTurnRadius(inst.turnRadius);
+            root.addChild(other);
+            
+            
+            if (position == PositionType.NEXT) {
+                PipingRules.addSizeChange(false, pipeRun, other, (InlineComponent)newComponent, toPcp, null);
+            } else if (position == PositionType.PREVIOUS){
+                PipingRules.addSizeChange(true, pipeRun, other, (InlineComponent)newComponent, toPcp, null);
+            }
+            newPcp.setWorldPosition(pos);
+            // TODO : chicken-egg problem
+            newComponent.updateParameters();
+            Vector3d v = new Vector3d(dir);
+            v.scale(newComponent.getControlPoint().getLength()*0.5);
+            switch (position) {
+            case NEXT:
+                pos.add(v);
+                break;
+            case PREVIOUS:
+                pos.sub(v);
+                break;
+            case SPLIT:
+                break;
+            }
+            newPcp.setWorldPosition(pos);
+            
+        }
+                   
+              
+           return newComponent;
+       }
 }