X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=org.simantics.plant3d%2Fsrc%2Forg%2Fsimantics%2Fplant3d%2Futils%2FComponentUtils.java;h=438e0bd6a96eae87cf8121640a11bfd350409161;hb=47a78f85f52d380243f8138a8104f79299c3c86c;hp=4a4888090aff7a0dd08756d35b6ba8e4607bdd02;hpb=11cf079ab699e65f6c97b86745a3c8cbd65817b8;p=simantics%2F3d.git diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/utils/ComponentUtils.java b/org.simantics.plant3d/src/org/simantics/plant3d/utils/ComponentUtils.java index 4a488809..438e0bd6 100644 --- a/org.simantics.plant3d/src/org/simantics/plant3d/utils/ComponentUtils.java +++ b/org.simantics.plant3d/src/org/simantics/plant3d/utils/ComponentUtils.java @@ -1,20 +1,26 @@ package org.simantics.plant3d.utils; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import javax.vecmath.Vector3d; import org.simantics.Simantics; import org.simantics.db.ReadGraph; +import org.simantics.db.RequestProcessor; 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.math.MathTools; import org.simantics.g3d.scenegraph.GeometryProvider; +import org.simantics.g3d.scenegraph.ParametricGeometryProvider; import org.simantics.layer0.Layer0; +import org.simantics.plant3d.geometry.ParameterRead; import org.simantics.plant3d.ontology.Plant3D; import org.simantics.plant3d.scenegraph.EndComponent; import org.simantics.plant3d.scenegraph.Equipment; @@ -25,36 +31,43 @@ 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; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.simantics.plant3d.scenegraph.controlpoint.PipingRules; public class ComponentUtils { + private final static Logger LOGGER = LoggerFactory.getLogger(ComponentUtils.class); private static Map> clazzes = new HashMap>(); private static Map providers = new HashMap(); private static Map names = new HashMap(); - public static void preloadCache() { - Simantics.getSession().asyncRequest(new ReadRequest() { - - @Override - public void run(ReadGraph graph) throws DatabaseException { - List types = new ArrayList(); - types.add(Plant3D.URIs.Builtin_Straight); - types.add(Plant3D.URIs.Builtin_Elbow); - types.add(Plant3D.URIs.Builtin_ConcentricReducer); - types.add(Plant3D.URIs.Builtin_BranchSplitComponent); - types.add(Plant3D.URIs.Builtin_EccentricReducer); + public static void preloadCache(RequestProcessor session) { + try { + session.syncRequest(new ReadRequest() { - for (String typeURI : types) { - load(graph, typeURI); + @Override + public void run(ReadGraph graph) throws DatabaseException { + List types = new ArrayList(); + types.add(Plant3D.URIs.Builtin_Straight); + types.add(Plant3D.URIs.Builtin_Elbow); + types.add(Plant3D.URIs.Builtin_ConcentricReducer); + types.add(Plant3D.URIs.Builtin_BranchSplitComponent); + types.add(Plant3D.URIs.Builtin_EccentricReducer); + types.add(Plant3D.URIs.Builtin_Elbow45); + types.add(Plant3D.URIs.Builtin_Elbow90); + + for (String typeURI : types) { + load(graph, typeURI); + } } - } - }); + }); + } catch (DatabaseException e) { + LOGGER.error("ComponentUtils.preloadCache() failed unexpectedly", e); + } } private static GeometryProvider getProvider(ReadGraph graph, Resource type) throws DatabaseException { @@ -72,6 +85,11 @@ public class ComponentUtils { } if (geom != null) { GeometryProvider provider = graph.adapt(geom, GeometryProvider.class); + if (provider instanceof ParametricGeometryProvider) { + Map params = graph.syncRequest(new ParameterRead(type)); + if (params.size() > 0) + ((ParametricGeometryProvider)provider).setProperties(params); + } return provider; } return null; @@ -98,7 +116,7 @@ public class ComponentUtils { if (provider != null || graph.hasStatement(type,p3d.NonVisibleComponent)) { providers.put(typeURI, provider); if (graph.isInheritedFrom(type, p3d.PipelineComponent)) - clazzes.put(typeURI,getClazz(graph, type)); + clazzes.put(typeURI,getClazz(graph, type)); names.put(typeURI, NameUtils.getSafeName(graph, type)); return; } @@ -160,7 +178,20 @@ public class ComponentUtils { */ public static Equipment createEquipment(P3DRootNode root, String typeURI) throws Exception { - GeometryProvider provider = providers.get(typeURI); + GeometryProvider provider = providers.get(typeURI); + if (provider == null) { + load(typeURI); + provider = providers.get(typeURI); + } + Equipment equipment = root.createEquipment(); + equipment.setType(typeURI); + equipment.setGeometry(provider); + root.addChild(equipment); + return equipment; + } + + public static Equipment createEquipmentWithNozzles(P3DRootNode root, String typeURI, String nozzleTypeUri) throws Exception { + GeometryProvider provider = providers.get(typeURI); if (provider == null) { load(typeURI); provider = providers.get(typeURI); @@ -169,6 +200,12 @@ public class ComponentUtils { equipment.setType(typeURI); equipment.setGeometry(provider); root.addChild(equipment); + + for (int i = 0; i < equipment.numberOfFixedNozzles(); i++) { + createNozzle(root, equipment, new Item(nozzleTypeUri, "Nozzle")); + + } + return equipment; } @@ -200,278 +237,514 @@ public class ComponentUtils { } public static Equipment createEquipment(P3DRootNode root, Item equipmentType) throws Exception { - Equipment equipment = createEquipment(root, equipmentType.getUri()); + Equipment equipment = createEquipment(root, equipmentType.getUri()); + String n = root.getUniqueName(equipmentType.getName()); + equipment.setName(n); + return equipment; + } + + public static Equipment createEquipmentWithNozzles(P3DRootNode root, Item equipmentType, Item nozzleType) throws Exception { + Equipment equipment = createEquipmentWithNozzles(root, equipmentType.getUri(), nozzleType.getUri()); String n = root.getUniqueName(equipmentType.getName()); equipment.setName(n); - root.addChild(equipment); return equipment; - } - - + } public static Nozzle createDefaultNozzle(P3DRootNode root, Equipment equipment) throws Exception { - return createNozzle(root, equipment, new Item(Plant3D.URIs.Builtin_Nozzle, "Nozzle")); + return createNozzle(root, equipment, new Item(Plant3D.URIs.Builtin_Nozzle, "Nozzle")); } public static Nozzle createNozzle(P3DRootNode root, Equipment equipment, Item nozzleType) throws Exception { - Nozzle nozzle = root.createNozzle(); - nozzle.setType(nozzleType.getUri()); - String n = root.getUniqueName(nozzleType.getName()); - nozzle.setName(n); - PipeRun pipeRun = new PipeRun(); - n = root.getUniqueName("PipeRun"); - pipeRun.setName(n); - nozzle.setPipeRun(pipeRun); - - equipment.addChild(nozzle); - root.addChild(pipeRun); - // root.getNodeMap().commit("Add nozzle " + n); - return nozzle; + Nozzle nozzle = root.createNozzle(); + nozzle.setType(nozzleType.getUri()); + String n = root.getUniqueName(nozzleType.getName()); + nozzle.setName(n); + PipeRun pipeRun = new PipeRun(); + n = root.getUniqueName("PipeRun"); + pipeRun.setName(n); + nozzle.setPipeRun(pipeRun); + + equipment.addChild(nozzle); + root.addChild(pipeRun); + // 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 typeUri; + + public PositionType position = PositionType.NEXT; + public PositionType insertPosition = PositionType.NEXT; - public String getTypeUri() { - return typeUri; - } + // Component name + public String name; + + // Reducer requires pipe specs + public Double diameter; + public Double thickness; + public Double turnRadius; + + // Variable length + public Double length; + + // Variable angle + public Double angle; + + // Rotation angle used with turns and rotated inline. + public Double rotationAngle; - public void setTypeUri(String typeUri) { - this.typeUri = typeUri; - } + public String getTypeUri() { + return typeUri; + } - public PositionType getPosition() { - return position; - } + public void setTypeUri(String typeUri) { + this.typeUri = typeUri; + } - public void setPosition(PositionType position) { - this.position = position; - } + public PositionType getPosition() { + return position; + } - public PositionType getInsertPosition() { - return insertPosition; - } + public void setPosition(PositionType position) { + this.position = position; + } - public void setInsertPosition(PositionType insertPosition) { - this.insertPosition = insertPosition; - } + public PositionType getInsertPosition() { + return insertPosition; + } - public Double getDiameter() { - return diameter; - } + public void setInsertPosition(PositionType insertPosition) { + this.insertPosition = insertPosition; + } - public void setDiameter(Double diameter) { - this.diameter = diameter; - } + public String getName() { + return name; + } - public Double getTurnRadius() { - return turnRadius; - } + public void setName(String name) { + this.name = name; + } - public void setTurnRadius(Double turnRadius) { - this.turnRadius = turnRadius; - } + public Double getDiameter() { + return diameter; + } - public Double getLength() { - return length; - } + public void setDiameter(Double diameter) { + this.diameter = diameter; + } + + public double getThickness() { + return thickness; + } + + public void setThickness(double thickness) { + this.thickness = thickness; + } - public void setLength(Double length) { - this.length = length; - } + public Double getTurnRadius() { + return turnRadius; + } - public Double getAngle() { - return angle; - } + public void setTurnRadius(Double turnRadius) { + this.turnRadius = turnRadius; + } - public void setAngle(Double angle) { - this.angle = angle; + 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 Double getRotationAngle() { + return rotationAngle; + } + + public void setRotationAngle(Double rotationAngle) { + this.rotationAngle = rotationAngle; } } 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); + + PipelineComponent newComponent = ComponentUtils.createComponent(root, inst.typeUri); + if (inst.name != null) + newComponent.setName(inst.name); + + 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() || ((InlineComponent)newComponent).isModifialble(); + } + 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.getDualSub(); + pipeRun = toPcp.getPipeRun(); + } + + break; + case PREVIOUS: + if (toPcp.isDualSub()) { + toPcp = toPcp.parent; + pipeRun = toPcp.getPipeRun(); + } + break; + default: + break; + } + 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; + default: + break; + } - 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; + } else if (toPcp.isDirected()) { + dir = new Vector3d(toPcp.getDirection(Direction.NEXT)); + pos = new Vector3d(toPcp.getWorldPosition()); + } else if (toPcp.isTurn() && toPcp.asFixedAngle()) { + 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); + } + } + } + + String name = component.getPipeRun().getUniqueName(typeName); + newComponent.setName(name); + + pipeRun.addChild(newComponent); + if (newPcp.isSizeChange()) + newComponent.setAlternativePipeRun(pipeRun); + + if (newComponent instanceof InlineComponent) { + InlineComponent inlineComponent = (InlineComponent)newComponent; + if (inlineComponent.isVariableLength()|| inlineComponent.isModifialble()) { + newPcp.setLength(inst.length); + newComponent.setParameter("length", inst.length); + } + if (inst.rotationAngle != null) + ((InlineComponent) newComponent).setRotationAngle(inst.rotationAngle); + } else if (newComponent instanceof TurnComponent) { + TurnComponent turnComponent = (TurnComponent)newComponent; + if (turnComponent.isVariableAngle()) { + newPcp.setTurnAngle(inst.angle); + newComponent.setParameter("turnAngle", inst.angle); + } + if (inst.rotationAngle != null) + ((TurnComponent) newComponent).setRotationAngle(inst.rotationAngle); + } + + + newComponent.updateParameters(); + + Vector3d v = new Vector3d(dir); + if (insertAdjustable) { + // Prevent moving of adjacent components - always insert at end of a connected variable length component + if (position == PositionType.NEXT && component.getNext() != null || + position == PositionType.PREVIOUS && component.getPrevious() != null) + insertPosition = PositionType.PREVIOUS; + + 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; + default: + break; + } + + switch (position) { + case NEXT: + if (toPcp.isDualInline()) + toPcp = toPcp.getDualSub(); + newPcp.setWorldPosition(pos); + if (toPcp.getNext() != null) + PipingRules.splitVariableLengthComponent(newComponent, (InlineComponent)component, false); + else + newPcp.insert(toPcp, Direction.NEXT); + break; + case PREVIOUS: + if (toPcp.isDualSub()) + toPcp = toPcp.parent; + newPcp.setWorldPosition(pos); + if (toPcp.getPrevious() != null) + PipingRules.splitVariableLengthComponent(newComponent, (InlineComponent)component, false); + else + newPcp.insert(toPcp, Direction.PREVIOUS); + break; + case SPLIT: + PipingRules.splitVariableLengthComponent(newComponent, (InlineComponent)component, true); + default: + break; + } + + // Move the size change and the rest of the components in the pipe run to a new pipe run + if (sizeChange) { + PipeRun other = new PipeRun(); + String n = root.getUniqueName("PipeRun"); + other.setName(n); + other.setPipeDiameter(inst.diameter); + other.setPipeThickness(inst.thickness); + other.setTurnRadius(inst.turnRadius); + root.addChild(other); + + other.addChild(newComponent.getControlPoint().getDualSub()); + newComponent.setAlternativePipeRun(other); + + boolean forward = position != PositionType.PREVIOUS; + PipelineComponent comp = forward ? newComponent.getNext() : newComponent.getPrevious(); + while (comp != null && comp.getPipeRun() == pipeRun) { + if (comp.getParent() == pipeRun) { + comp.deattach(); + other.addChild(comp); + } else { + comp.setPipeRun(other); + } + + // Reset parameters to match new pipe run + comp.updateParameters(); + + comp = forward ? comp.getNext() : comp.getPrevious(); + } + + newComponent.updateParameters(); + } + + return newComponent; + } + + public static boolean connect(PipelineComponent current, PipelineComponent endTo) throws Exception { + return connect(current, endTo, null, null); + } + + /** + * Connects component to another component + * @param current + * @param endTo + * @param endType + * @param position + * @return + * @throws Exception + */ + public static boolean connect(PipelineComponent current, PipelineComponent endTo, PositionType endType, Vector3d position) throws Exception{ + PipeControlPoint endCP = endTo.getControlPoint(); + boolean reversed; + if (current.getNext() == null) + reversed = false; + else if (current.getPrevious() == null) + reversed = true; + else + return false; + + PipeRun pipeRun = current.getPipeRun(); + P3DRootNode root = (P3DRootNode)current.getRootNode(); + PipeControlPoint currentCP = current.getControlPoint(); + + if (endType == null || endType == PositionType.NEXT || endType == PositionType.PREVIOUS) { + + + + boolean requiresReverse = false; + if (!reversed && endCP.getPrevious() != null) { + if (endCP.getNext() != null) + return false; + requiresReverse = true; + } else if (reversed && endCP.getNext() != null) { + if (endCP.getPrevious() != null) + return false; + requiresReverse = true; + } + PipeRun other = endCP.getPipeRun(); + boolean mergeRuns = other == null ? true : pipeRun.canMerge(other); + + if (requiresReverse) { + // Pipe line must be traversible with next/previous relations without direction change. + // Now the component, where we are connecting the created pipeline is defined in different order. + PipingRules.reverse(other); + + } + + if (mergeRuns) { + // Runs have compatible specs and must be merged + if (other != null && pipeRun != other) + pipeRun.merge(other); + else if (other == null) { + if (!(endTo instanceof Nozzle)) { + pipeRun.addChild(endTo); + } else { + endTo.setPipeRun(pipeRun); + } + } + if (!reversed) { + currentCP.setNext(endCP); + endCP.setPrevious(currentCP); + } else { + currentCP.setPrevious(endCP); + endCP.setNext(currentCP); + } + } else { + // Runs do not have compatible specs, and a reducer must be attached in between. + InlineComponent reducer = ComponentUtils.createReducer(root); + PipeControlPoint pcp = reducer.getControlPoint(); + + Vector3d endPos = endCP.getWorldPosition(); + Vector3d currentPos = currentCP.getWorldPosition(); + Vector3d v = new Vector3d(endPos); + v.sub(currentPos); + v.scale(0.5); + v.add(currentPos); + + PipingRules.addSizeChange(reversed, pipeRun, other, reducer, currentCP, endCP); + + pcp.setWorldPosition(v); + reducer.updateParameters(); + } + PipingRules.positionUpdate(endCP); + return true; + + } else if (endType == PositionType.SPLIT) { + InlineComponent branchSplit = createBranchSplit((InlineComponent)endTo, position); + if (branchSplit == null) + return false; + PipeControlPoint branchSplitCP = branchSplit.getControlPoint(); + PipeControlPoint pcp = new PipeControlPoint(branchSplit,pipeRun); + branchSplitCP.children.add(pcp); + pcp.parent = branchSplitCP; + pcp.setWorldOrientation(branchSplitCP.getWorldOrientation()); + pcp.setWorldPosition(branchSplitCP.getWorldPosition()); + + + if(!reversed) { + pcp.setPrevious(currentCP); + currentCP.setNext(pcp); + } else { + pcp.setNext(currentCP); + currentCP.setPrevious(pcp); + } + PipingRules.positionUpdate(endCP); + return true; + } + return false; + } + + public static InlineComponent createBranchSplit(InlineComponent component, Vector3d pos) throws Exception{ + if (!component.isVariableLength()) + return null; + PipeRun pipeRun = component.getPipeRun(); + Vector3d sStart = new Vector3d(); + Vector3d sEnd = new Vector3d(); + component.getControlPoint().getInlineControlPointEnds(sStart, sEnd); + + if (MathTools.distance(sStart, sEnd) < (pipeRun.getPipeDiameter()*0.5)) + return null; + + + Vector3d p = MathTools.closestPointOnEdge(new Vector3d(pos), sStart, sEnd); + if (p == sStart) { + Vector3d v = new Vector3d(sEnd); + v.sub(sStart); + v.normalize(); + v.scale(component.getPipeRun().getPipeDiameter()*0.5); + p.add(v); + } else if (p == sEnd) { + Vector3d v = new Vector3d(sStart); + v.sub(sEnd); + v.normalize(); + v.scale(component.getPipeRun().getPipeDiameter()*0.5); + p.add(v); + } + + P3DRootNode root = (P3DRootNode)component.getRootNode(); + InlineComponent branchSplit = ComponentUtils.createBranchSplit(root); + String branchName = component.getPipeRun().getUniqueName("Branch"); + branchSplit.setName(branchName); + component.getPipeRun().addChild(branchSplit); + PipeControlPoint branchSplitCP = branchSplit.getControlPoint(); + branchSplitCP.setWorldPosition(p); + PipingRules.splitVariableLengthComponent(branchSplit, component, false); + return branchSplit; + } + + public static Collection getPipelineComponentNames(P3DRootNode root) { + Collection usedNames = root.getChild().stream() + .filter(n -> n instanceof PipeRun) + .flatMap(n -> ((PipeRun)n).getChild().stream()) + .filter(n -> n instanceof PipelineComponent) + .map(n -> ((PipelineComponent)n).getName()) + .collect(Collectors.toSet()); + return usedNames; } }