From: Marko Luukkainen Date: Thu, 4 Apr 2019 12:55:24 +0000 (+0300) Subject: Publish Plant3D feature X-Git-Tag: v1.43.0~271^2 X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=commitdiff_plain;h=refs%2Fchanges%2F32%2F2832%2F1;p=simantics%2F3d.git Publish Plant3D feature Change-Id: If41206e5e25a27b027e4fb260d9ed43b1cbdf951 --- diff --git a/org.simantics.plant3d.modeling.feature/.project b/org.simantics.plant3d.modeling.feature/.project new file mode 100644 index 00000000..e40eea0c --- /dev/null +++ b/org.simantics.plant3d.modeling.feature/.project @@ -0,0 +1,17 @@ + + + org.simantics.plant3d.modeling.feature + + + + + + org.eclipse.pde.FeatureBuilder + + + + + + org.eclipse.pde.FeatureNature + + diff --git a/org.simantics.plant3d.modeling.feature/build.properties b/org.simantics.plant3d.modeling.feature/build.properties new file mode 100644 index 00000000..64f93a9f --- /dev/null +++ b/org.simantics.plant3d.modeling.feature/build.properties @@ -0,0 +1 @@ +bin.includes = feature.xml diff --git a/org.simantics.plant3d.modeling.feature/feature.xml b/org.simantics.plant3d.modeling.feature/feature.xml new file mode 100644 index 00000000..e307342b --- /dev/null +++ b/org.simantics.plant3d.modeling.feature/feature.xml @@ -0,0 +1,58 @@ + + + + + [Enter Feature Description here.] + + + + [Enter Copyright Description here.] + + + + [Enter License Description here.] + + + + + + + + + + + + + + + + + + + diff --git a/org.simantics.plant3d.ontology/.classpath b/org.simantics.plant3d.ontology/.classpath new file mode 100644 index 00000000..ad32c83a --- /dev/null +++ b/org.simantics.plant3d.ontology/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/org.simantics.plant3d.ontology/.gitignore b/org.simantics.plant3d.ontology/.gitignore new file mode 100644 index 00000000..ae3c1726 --- /dev/null +++ b/org.simantics.plant3d.ontology/.gitignore @@ -0,0 +1 @@ +/bin/ diff --git a/org.simantics.plant3d.ontology/.project b/org.simantics.plant3d.ontology/.project new file mode 100644 index 00000000..bbacda45 --- /dev/null +++ b/org.simantics.plant3d.ontology/.project @@ -0,0 +1,34 @@ + + + org.simantics.plant3d.ontology + + + + + + org.simantics.graph.builder + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + org.simantics.graph.nature + + diff --git a/org.simantics.plant3d.ontology/.settings/org.eclipse.jdt.core.prefs b/org.simantics.plant3d.ontology/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..c537b630 --- /dev/null +++ b/org.simantics.plant3d.ontology/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,7 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/org.simantics.plant3d.ontology/META-INF/MANIFEST.MF b/org.simantics.plant3d.ontology/META-INF/MANIFEST.MF new file mode 100644 index 00000000..f74fbe6b --- /dev/null +++ b/org.simantics.plant3d.ontology/META-INF/MANIFEST.MF @@ -0,0 +1,19 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Plant3D Ontology +Bundle-SymbolicName: org.simantics.plant3d.ontology +Bundle-Version: 1.0.0.qualifier +Bundle-Vendor: VTT +Require-Bundle: org.eclipse.core.runtime, + org.simantics.layer0;bundle-version="1.1.0", + org.simantics.g3d.ontology;bundle-version="1.0.0", + org.simantics.simulation.ontology;bundle-version="1.1.0", + org.simantics.viewpoint.ontology;bundle-version="1.2.0", + org.simantics.g3d.csg.ontology;bundle-version="1.0.0", + org.simantics.structural.ontology;bundle-version="1.2.0", + org.simantics.action.ontology;bundle-version="1.1.0", + org.simantics.image2.ontology;bundle-version="1.2.0", + org.simantics.silk.ontology;bundle-version="1.1.0", + org.simantics.project.ontology;bundle-version="1.2.0" +Bundle-RequiredExecutionEnvironment: JavaSE-1.6 +Export-Package: org.simantics.plant3d.ontology diff --git a/org.simantics.plant3d.ontology/build.properties b/org.simantics.plant3d.ontology/build.properties new file mode 100644 index 00000000..e85b630a --- /dev/null +++ b/org.simantics.plant3d.ontology/build.properties @@ -0,0 +1,5 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + graph.tg diff --git a/org.simantics.plant3d.ontology/graph/images/Component.png b/org.simantics.plant3d.ontology/graph/images/Component.png new file mode 100644 index 00000000..0d43ef5b Binary files /dev/null and b/org.simantics.plant3d.ontology/graph/images/Component.png differ diff --git a/org.simantics.plant3d.ontology/graph/images/Component.svg b/org.simantics.plant3d.ontology/graph/images/Component.svg new file mode 100644 index 00000000..eaf30346 --- /dev/null +++ b/org.simantics.plant3d.ontology/graph/images/Component.svg @@ -0,0 +1,128 @@ + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/org.simantics.plant3d.ontology/graph/images/Elbow.png b/org.simantics.plant3d.ontology/graph/images/Elbow.png new file mode 100644 index 00000000..bbaa16ea Binary files /dev/null and b/org.simantics.plant3d.ontology/graph/images/Elbow.png differ diff --git a/org.simantics.plant3d.ontology/graph/images/Elbow.svg b/org.simantics.plant3d.ontology/graph/images/Elbow.svg new file mode 100644 index 00000000..611748ac --- /dev/null +++ b/org.simantics.plant3d.ontology/graph/images/Elbow.svg @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + diff --git a/org.simantics.plant3d.ontology/graph/images/Nozzle.png b/org.simantics.plant3d.ontology/graph/images/Nozzle.png new file mode 100644 index 00000000..48cf03e8 Binary files /dev/null and b/org.simantics.plant3d.ontology/graph/images/Nozzle.png differ diff --git a/org.simantics.plant3d.ontology/graph/images/Nozzle.svg b/org.simantics.plant3d.ontology/graph/images/Nozzle.svg new file mode 100644 index 00000000..0dd815c8 --- /dev/null +++ b/org.simantics.plant3d.ontology/graph/images/Nozzle.svg @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/org.simantics.plant3d.ontology/graph/images/Straight.png b/org.simantics.plant3d.ontology/graph/images/Straight.png new file mode 100644 index 00000000..459919e5 Binary files /dev/null and b/org.simantics.plant3d.ontology/graph/images/Straight.png differ diff --git a/org.simantics.plant3d.ontology/graph/images/Straight.svg b/org.simantics.plant3d.ontology/graph/images/Straight.svg new file mode 100644 index 00000000..117e6ec1 --- /dev/null +++ b/org.simantics.plant3d.ontology/graph/images/Straight.svg @@ -0,0 +1,96 @@ + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + diff --git a/org.simantics.plant3d.ontology/graph/images/eye.png b/org.simantics.plant3d.ontology/graph/images/eye.png new file mode 100644 index 00000000..0e78cfd6 Binary files /dev/null and b/org.simantics.plant3d.ontology/graph/images/eye.png differ diff --git a/org.simantics.plant3d.ontology/graph/images/eye.svg b/org.simantics.plant3d.ontology/graph/images/eye.svg new file mode 100644 index 00000000..cfb5620e --- /dev/null +++ b/org.simantics.plant3d.ontology/graph/images/eye.svg @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/org.simantics.plant3d.ontology/graph/images/factory.png b/org.simantics.plant3d.ontology/graph/images/factory.png new file mode 100644 index 00000000..aad23e32 Binary files /dev/null and b/org.simantics.plant3d.ontology/graph/images/factory.png differ diff --git a/org.simantics.plant3d.ontology/graph/images/factory.svg b/org.simantics.plant3d.ontology/graph/images/factory.svg new file mode 100644 index 00000000..e05205cb --- /dev/null +++ b/org.simantics.plant3d.ontology/graph/images/factory.svg @@ -0,0 +1,308 @@ + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/org.simantics.plant3d.ontology/graph/images/point.png b/org.simantics.plant3d.ontology/graph/images/point.png new file mode 100644 index 00000000..54bf5e49 Binary files /dev/null and b/org.simantics.plant3d.ontology/graph/images/point.png differ diff --git a/org.simantics.plant3d.ontology/graph/images/point.svg b/org.simantics.plant3d.ontology/graph/images/point.svg new file mode 100644 index 00000000..ee80b683 --- /dev/null +++ b/org.simantics.plant3d.ontology/graph/images/point.svg @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/org.simantics.plant3d.ontology/graph/images/rotate.png b/org.simantics.plant3d.ontology/graph/images/rotate.png new file mode 100644 index 00000000..bcc829f0 Binary files /dev/null and b/org.simantics.plant3d.ontology/graph/images/rotate.png differ diff --git a/org.simantics.plant3d.ontology/graph/images/rotate.svg b/org.simantics.plant3d.ontology/graph/images/rotate.svg new file mode 100644 index 00000000..1b8d04bf --- /dev/null +++ b/org.simantics.plant3d.ontology/graph/images/rotate.svg @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + diff --git a/org.simantics.plant3d.ontology/graph/images/tank.png b/org.simantics.plant3d.ontology/graph/images/tank.png new file mode 100644 index 00000000..44015a37 Binary files /dev/null and b/org.simantics.plant3d.ontology/graph/images/tank.png differ diff --git a/org.simantics.plant3d.ontology/graph/images/tank.svg b/org.simantics.plant3d.ontology/graph/images/tank.svg new file mode 100644 index 00000000..8e8784f1 --- /dev/null +++ b/org.simantics.plant3d.ontology/graph/images/tank.svg @@ -0,0 +1,184 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/org.simantics.plant3d.ontology/graph/images/translate.png b/org.simantics.plant3d.ontology/graph/images/translate.png new file mode 100644 index 00000000..21f52847 Binary files /dev/null and b/org.simantics.plant3d.ontology/graph/images/translate.png differ diff --git a/org.simantics.plant3d.ontology/graph/images/translate.svg b/org.simantics.plant3d.ontology/graph/images/translate.svg new file mode 100644 index 00000000..b600c2fd --- /dev/null +++ b/org.simantics.plant3d.ontology/graph/images/translate.svg @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + diff --git a/org.simantics.plant3d.ontology/graph/images/translate_d.png b/org.simantics.plant3d.ontology/graph/images/translate_d.png new file mode 100644 index 00000000..f4b3b608 Binary files /dev/null and b/org.simantics.plant3d.ontology/graph/images/translate_d.png differ diff --git a/org.simantics.plant3d.ontology/graph/images/translate_d.svg b/org.simantics.plant3d.ontology/graph/images/translate_d.svg new file mode 100644 index 00000000..16669294 --- /dev/null +++ b/org.simantics.plant3d.ontology/graph/images/translate_d.svg @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + diff --git a/org.simantics.plant3d.ontology/graph/plant3d.pgraph b/org.simantics.plant3d.ontology/graph/plant3d.pgraph new file mode 100644 index 00000000..8edc9f61 --- /dev/null +++ b/org.simantics.plant3d.ontology/graph/plant3d.pgraph @@ -0,0 +1,158 @@ +L0 = +PROJ = +SIM = +//STR = +G3D = + +P3D = : L0.Ontology + @L0.new + L0.HasResourceClass "org.simantics.plant3d.ontology.Plant3D" : L0.String + +P3D.ImportedOntologies : PROJ.NamespaceRequirement + L0.HasDescription "Specifies the ontologies required by a Plant3D Feature." : L0.String + PROJ.RequiresNamespace + "http://www.simantics.org/Layer0-1.0" : L0.URI + "http://www.simantics.org/Simulation-1.0" : L0.URI + +P3D.Node +P3D = + + +P3D.Builtin : L0.Library + +P3D.Builtin.GeometryProvider +VP = +PROJ = +SIM = +IMAGE = +ACT = +P3D = +CSG = +SILK = + + +PBC = P3D.P3DBrowseContext : VP.BrowseContext + VP.BrowseContext.IsIncludedIn PROJ.ProjectBrowseContext + @VP.constantImageRule P3D.Plant IMAGES.Factory + @VP.constantImageRule P3D.Equipment IMAGES.Tank + @VP.constantImageRule P3D.TurnComponent IMAGES.Elbow + @VP.constantImageRule P3D.Nozzle IMAGES.Nozzle + @VP.constantImageRule P3D.InlineComponent IMAGES.Component + @VP.constantImageRule P3D.Builtin.Straight IMAGES.Straight + @VP.constantImageRule P3D.EndComponent IMAGES.Component + @VP.constantImageRule P3D.PipeRun IMAGES.Straight + @VP.relationChildRule PROJ.Project L0.ConsistsOf P3D.Plant + @VP.relationChildRule P3D.Node P3D.childen P3D.Node + @VP.relationChildRule P3D.Node P3D.HasNozzle P3D.Node + + +IMAGES = P3D.Images : L0.Library +IMAGES.Component : IMAGE.PngImage + @L0.loadBytes "images/Component.png" +IMAGES.Elbow : IMAGE.PngImage + @L0.loadBytes "images/Elbow.png" +IMAGES.Factory : IMAGE.PngImage + @L0.loadBytes "images/factory.png" +IMAGES.Nozzle : IMAGE.PngImage + @L0.loadBytes "images/Nozzle.png" +IMAGES.Straight : IMAGE.PngImage + @L0.loadBytes "images/Straight.png" +IMAGES.Tank : IMAGE.PngImage + @L0.loadBytes "images/tank.png" + +MAC = P3D.P3DActionContext : VP.BrowseContext + VP.BrowseContext.IsIncludedIn PROJ.ProjectActionContext + + +MAC.newContribution : L0.Template + @template %actionContext %label %action %image + %actionContext + VP.BrowseContext.HasActionContribution _ : VP.ActionContribution + L0.HasLabel %label + VP.ActionContribution.HasImage %image + VP.ActionContribution.HasCategory VP.NewActionCategory + VP.ActionContribution.HasNodeType P3D.Plant + VP.ActionContribution.HasAction %action + +MAC.newTypeContribution : L0.Template + @template %actionContext %label %action %type %image + %actionContext + VP.BrowseContext.HasActionContribution _ : VP.ActionContribution + L0.HasLabel %label + VP.ActionContribution.HasImage %image + VP.ActionContribution.HasCategory VP.NewActionCategory + VP.ActionContribution.HasNodeType %type + VP.ActionContribution.HasAction %action + +MAC.editTypeContribution : L0.Template + @template %actionContext %label %action %type %image + %actionContext + VP.BrowseContext.HasActionContribution _ : VP.ActionContribution + L0.HasLabel %label + VP.ActionContribution.HasImage %image + VP.ActionContribution.HasCategory VP.EditActionCategory + VP.ActionContribution.HasNodeType %type + VP.ActionContribution.HasAction %action \ No newline at end of file diff --git a/org.simantics.plant3d.ontology/src/org/simantics/plant3d/ontology/Plant3D.java b/org.simantics.plant3d.ontology/src/org/simantics/plant3d/ontology/Plant3D.java new file mode 100644 index 00000000..394da937 --- /dev/null +++ b/org.simantics.plant3d.ontology/src/org/simantics/plant3d/ontology/Plant3D.java @@ -0,0 +1,349 @@ +package org.simantics.plant3d.ontology; + +import org.simantics.db.RequestProcessor; +import org.simantics.db.Resource; +import org.simantics.db.ReadGraph; +import org.simantics.db.request.Read; +import org.simantics.db.Session; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.service.QueryControl; + +public class Plant3D { + + public final Resource Builtin; + public final Resource Builtin_BallValve; + public final Resource Builtin_BallValveGeometryProvider; + public final Resource Builtin_BranchSplitComponent; + public final Resource Builtin_Cap; + public final Resource Builtin_CapGeometryProvider; + public final Resource Builtin_CheckValve; + public final Resource Builtin_CheckValveGeometryProvider; + public final Resource Builtin_ConcentricReducer; + public final Resource Builtin_EccentricReducer; + public final Resource Builtin_Elbow; + public final Resource Builtin_ElbowGeometryProvider; + public final Resource Builtin_GeometryProvider; + public final Resource Builtin_HorizontalTank; + public final Resource Builtin_HorizontalTankGeometryProvider; + public final Resource Builtin_Nozzle; + public final Resource Builtin_NozzleGeometryProvider; + public final Resource Builtin_Pump; + public final Resource Builtin_PumpGeometryProvider; + public final Resource Builtin_ReducerGeometryProvider; + public final Resource Builtin_Straight; + public final Resource Builtin_StraightGeometryProvider; + public final Resource Builtin_VerticalTank; + public final Resource Builtin_VerticalTankGeometryProvider; + public final Resource CodeComponent; + public final Resource Connects; + public final Resource DualConnectedComponent; + public final Resource EndComponent; + public final Resource Equipment; + public final Resource FixedAngleTurnComponent; + public final Resource FixedLengthInlineComponent; + public final Resource HasAlternativePipeRun; + public final Resource HasBranch0; + public final Resource HasBranch1; + public final Resource HasBranch2; + public final Resource HasBranch3; + public final Resource HasBranch4; + public final Resource HasBranch5; + public final Resource HasBranch6; + public final Resource HasBranch7; + public final Resource HasBranch8; + public final Resource HasBranch9; + public final Resource HasNext; + public final Resource HasNozzle; + public final Resource HasNozzleDefinition; + public final Resource HasNozzleDefinition_Inverse; + public final Resource HasNozzleId; + public final Resource HasNozzleId_Inverse; + public final Resource HasNozzleRestriction; + public final Resource HasNozzleRestriction_Inverse; + public final Resource HasPipeDiameter; + public final Resource HasPipeDiameter_Inverse; + public final Resource HasPipeRun; + public final Resource HasPrevious; + public final Resource HasTurnAxis; + public final Resource HasTurnAxis_Inverse; + public final Resource HasTurnRadius; + public final Resource HasTurnRadius_Inverse; + public final Resource Images; + public final Resource Images_Component; + public final Resource Images_Elbow; + public final Resource Images_Factory; + public final Resource Images_Nozzle; + public final Resource Images_Straight; + public final Resource Images_Tank; + public final Resource ImportedOntologies; + public final Resource InlineComponent; + public final Resource IsReversed; + public final Resource IsReversed_Inverse; + public final Resource LibraryComponent; + public final Resource MultiConnectedComponent; + public final Resource NextInverse; + public final Resource Node; + public final Resource NonVisibleComponent; + public final Resource Nozzle; + public final Resource NozzleOf; + public final Resource OffsetComponent; + public final Resource P3DActionContext; + public final Resource P3DActionContext_editTypeContribution; + public final Resource P3DActionContext_newContribution; + public final Resource P3DActionContext_newTypeContribution; + public final Resource P3DBrowseContext; + public final Resource Parameter; + public final Resource PipeRun; + public final Resource PipelineComponent; + public final Resource PipelineComponentTag; + public final Resource Plant; + public final Resource PreviousInverse; + public final Resource SingleConnectedComponent; + public final Resource SizeChangeComponent; + public final Resource TurnComponent; + public final Resource VariableAngleTurnComponent; + public final Resource VariableLengthInlineComponent; + public final Resource childen; + public final Resource childen_Inverse; + public final Resource hasGeometry; + public final Resource hasParameter; + public final Resource hasParameterValue; + + public static class URIs { + public static final String Builtin = "http://www.simantics.org/Plant3D-0.1/Builtin"; + public static final String Builtin_BallValve = "http://www.simantics.org/Plant3D-0.1/Builtin/BallValve"; + public static final String Builtin_BallValveGeometryProvider = "http://www.simantics.org/Plant3D-0.1/Builtin/BallValveGeometryProvider"; + public static final String Builtin_BranchSplitComponent = "http://www.simantics.org/Plant3D-0.1/Builtin/BranchSplitComponent"; + public static final String Builtin_Cap = "http://www.simantics.org/Plant3D-0.1/Builtin/Cap"; + public static final String Builtin_CapGeometryProvider = "http://www.simantics.org/Plant3D-0.1/Builtin/CapGeometryProvider"; + public static final String Builtin_CheckValve = "http://www.simantics.org/Plant3D-0.1/Builtin/CheckValve"; + public static final String Builtin_CheckValveGeometryProvider = "http://www.simantics.org/Plant3D-0.1/Builtin/CheckValveGeometryProvider"; + public static final String Builtin_ConcentricReducer = "http://www.simantics.org/Plant3D-0.1/Builtin/ConcentricReducer"; + public static final String Builtin_EccentricReducer = "http://www.simantics.org/Plant3D-0.1/Builtin/EccentricReducer"; + public static final String Builtin_Elbow = "http://www.simantics.org/Plant3D-0.1/Builtin/Elbow"; + public static final String Builtin_ElbowGeometryProvider = "http://www.simantics.org/Plant3D-0.1/Builtin/ElbowGeometryProvider"; + public static final String Builtin_GeometryProvider = "http://www.simantics.org/Plant3D-0.1/Builtin/GeometryProvider"; + public static final String Builtin_HorizontalTank = "http://www.simantics.org/Plant3D-0.1/Builtin/HorizontalTank"; + public static final String Builtin_HorizontalTankGeometryProvider = "http://www.simantics.org/Plant3D-0.1/Builtin/HorizontalTankGeometryProvider"; + public static final String Builtin_Nozzle = "http://www.simantics.org/Plant3D-0.1/Builtin/Nozzle"; + public static final String Builtin_NozzleGeometryProvider = "http://www.simantics.org/Plant3D-0.1/Builtin/NozzleGeometryProvider"; + public static final String Builtin_Pump = "http://www.simantics.org/Plant3D-0.1/Builtin/Pump"; + public static final String Builtin_PumpGeometryProvider = "http://www.simantics.org/Plant3D-0.1/Builtin/PumpGeometryProvider"; + public static final String Builtin_ReducerGeometryProvider = "http://www.simantics.org/Plant3D-0.1/Builtin/ReducerGeometryProvider"; + public static final String Builtin_Straight = "http://www.simantics.org/Plant3D-0.1/Builtin/Straight"; + public static final String Builtin_StraightGeometryProvider = "http://www.simantics.org/Plant3D-0.1/Builtin/StraightGeometryProvider"; + public static final String Builtin_VerticalTank = "http://www.simantics.org/Plant3D-0.1/Builtin/VerticalTank"; + public static final String Builtin_VerticalTankGeometryProvider = "http://www.simantics.org/Plant3D-0.1/Builtin/VerticalTankGeometryProvider"; + public static final String CodeComponent = "http://www.simantics.org/Plant3D-0.1/CodeComponent"; + public static final String Connects = "http://www.simantics.org/Plant3D-0.1/Connects"; + public static final String DualConnectedComponent = "http://www.simantics.org/Plant3D-0.1/DualConnectedComponent"; + public static final String EndComponent = "http://www.simantics.org/Plant3D-0.1/EndComponent"; + public static final String Equipment = "http://www.simantics.org/Plant3D-0.1/Equipment"; + public static final String FixedAngleTurnComponent = "http://www.simantics.org/Plant3D-0.1/FixedAngleTurnComponent"; + public static final String FixedLengthInlineComponent = "http://www.simantics.org/Plant3D-0.1/FixedLengthInlineComponent"; + public static final String HasAlternativePipeRun = "http://www.simantics.org/Plant3D-0.1/HasAlternativePipeRun"; + public static final String HasBranch0 = "http://www.simantics.org/Plant3D-0.1/HasBranch0"; + public static final String HasBranch1 = "http://www.simantics.org/Plant3D-0.1/HasBranch1"; + public static final String HasBranch2 = "http://www.simantics.org/Plant3D-0.1/HasBranch2"; + public static final String HasBranch3 = "http://www.simantics.org/Plant3D-0.1/HasBranch3"; + public static final String HasBranch4 = "http://www.simantics.org/Plant3D-0.1/HasBranch4"; + public static final String HasBranch5 = "http://www.simantics.org/Plant3D-0.1/HasBranch5"; + public static final String HasBranch6 = "http://www.simantics.org/Plant3D-0.1/HasBranch6"; + public static final String HasBranch7 = "http://www.simantics.org/Plant3D-0.1/HasBranch7"; + public static final String HasBranch8 = "http://www.simantics.org/Plant3D-0.1/HasBranch8"; + public static final String HasBranch9 = "http://www.simantics.org/Plant3D-0.1/HasBranch9"; + public static final String HasNext = "http://www.simantics.org/Plant3D-0.1/HasNext"; + public static final String HasNozzle = "http://www.simantics.org/Plant3D-0.1/HasNozzle"; + public static final String HasNozzleDefinition = "http://www.simantics.org/Plant3D-0.1/HasNozzleDefinition"; + public static final String HasNozzleDefinition_Inverse = "http://www.simantics.org/Plant3D-0.1/HasNozzleDefinition/Inverse"; + public static final String HasNozzleId = "http://www.simantics.org/Plant3D-0.1/HasNozzleId"; + public static final String HasNozzleId_Inverse = "http://www.simantics.org/Plant3D-0.1/HasNozzleId/Inverse"; + public static final String HasNozzleRestriction = "http://www.simantics.org/Plant3D-0.1/HasNozzleRestriction"; + public static final String HasNozzleRestriction_Inverse = "http://www.simantics.org/Plant3D-0.1/HasNozzleRestriction/Inverse"; + public static final String HasPipeDiameter = "http://www.simantics.org/Plant3D-0.1/HasPipeDiameter"; + public static final String HasPipeDiameter_Inverse = "http://www.simantics.org/Plant3D-0.1/HasPipeDiameter/Inverse"; + public static final String HasPipeRun = "http://www.simantics.org/Plant3D-0.1/HasPipeRun"; + public static final String HasPrevious = "http://www.simantics.org/Plant3D-0.1/HasPrevious"; + public static final String HasTurnAxis = "http://www.simantics.org/Plant3D-0.1/HasTurnAxis"; + public static final String HasTurnAxis_Inverse = "http://www.simantics.org/Plant3D-0.1/HasTurnAxis/Inverse"; + public static final String HasTurnRadius = "http://www.simantics.org/Plant3D-0.1/HasTurnRadius"; + public static final String HasTurnRadius_Inverse = "http://www.simantics.org/Plant3D-0.1/HasTurnRadius/Inverse"; + public static final String Images = "http://www.simantics.org/Plant3D-0.1/Images"; + public static final String Images_Component = "http://www.simantics.org/Plant3D-0.1/Images/Component"; + public static final String Images_Elbow = "http://www.simantics.org/Plant3D-0.1/Images/Elbow"; + public static final String Images_Factory = "http://www.simantics.org/Plant3D-0.1/Images/Factory"; + public static final String Images_Nozzle = "http://www.simantics.org/Plant3D-0.1/Images/Nozzle"; + public static final String Images_Straight = "http://www.simantics.org/Plant3D-0.1/Images/Straight"; + public static final String Images_Tank = "http://www.simantics.org/Plant3D-0.1/Images/Tank"; + public static final String ImportedOntologies = "http://www.simantics.org/Plant3D-0.1/ImportedOntologies"; + public static final String InlineComponent = "http://www.simantics.org/Plant3D-0.1/InlineComponent"; + public static final String IsReversed = "http://www.simantics.org/Plant3D-0.1/IsReversed"; + public static final String IsReversed_Inverse = "http://www.simantics.org/Plant3D-0.1/IsReversed/Inverse"; + public static final String LibraryComponent = "http://www.simantics.org/Plant3D-0.1/LibraryComponent"; + public static final String MultiConnectedComponent = "http://www.simantics.org/Plant3D-0.1/MultiConnectedComponent"; + public static final String NextInverse = "http://www.simantics.org/Plant3D-0.1/NextInverse"; + public static final String Node = "http://www.simantics.org/Plant3D-0.1/Node"; + public static final String NonVisibleComponent = "http://www.simantics.org/Plant3D-0.1/NonVisibleComponent"; + public static final String Nozzle = "http://www.simantics.org/Plant3D-0.1/Nozzle"; + public static final String NozzleOf = "http://www.simantics.org/Plant3D-0.1/NozzleOf"; + public static final String OffsetComponent = "http://www.simantics.org/Plant3D-0.1/OffsetComponent"; + public static final String P3DActionContext = "http://www.simantics.org/Plant3D-0.1/P3DActionContext"; + public static final String P3DActionContext_editTypeContribution = "http://www.simantics.org/Plant3D-0.1/P3DActionContext/editTypeContribution"; + public static final String P3DActionContext_newContribution = "http://www.simantics.org/Plant3D-0.1/P3DActionContext/newContribution"; + public static final String P3DActionContext_newTypeContribution = "http://www.simantics.org/Plant3D-0.1/P3DActionContext/newTypeContribution"; + public static final String P3DBrowseContext = "http://www.simantics.org/Plant3D-0.1/P3DBrowseContext"; + public static final String Parameter = "http://www.simantics.org/Plant3D-0.1/Parameter"; + public static final String PipeRun = "http://www.simantics.org/Plant3D-0.1/PipeRun"; + public static final String PipelineComponent = "http://www.simantics.org/Plant3D-0.1/PipelineComponent"; + public static final String PipelineComponentTag = "http://www.simantics.org/Plant3D-0.1/PipelineComponentTag"; + public static final String Plant = "http://www.simantics.org/Plant3D-0.1/Plant"; + public static final String PreviousInverse = "http://www.simantics.org/Plant3D-0.1/PreviousInverse"; + public static final String SingleConnectedComponent = "http://www.simantics.org/Plant3D-0.1/SingleConnectedComponent"; + public static final String SizeChangeComponent = "http://www.simantics.org/Plant3D-0.1/SizeChangeComponent"; + public static final String TurnComponent = "http://www.simantics.org/Plant3D-0.1/TurnComponent"; + public static final String VariableAngleTurnComponent = "http://www.simantics.org/Plant3D-0.1/VariableAngleTurnComponent"; + public static final String VariableLengthInlineComponent = "http://www.simantics.org/Plant3D-0.1/VariableLengthInlineComponent"; + public static final String childen = "http://www.simantics.org/Plant3D-0.1/childen"; + public static final String childen_Inverse = "http://www.simantics.org/Plant3D-0.1/childen/Inverse"; + public static final String hasGeometry = "http://www.simantics.org/Plant3D-0.1/hasGeometry"; + public static final String hasParameter = "http://www.simantics.org/Plant3D-0.1/hasParameter"; + public static final String hasParameterValue = "http://www.simantics.org/Plant3D-0.1/hasParameterValue"; + } + + public static Resource getResourceOrNull(ReadGraph graph, String uri) { + try { + return graph.getResource(uri); + } catch(DatabaseException e) { + System.err.println(e.getMessage()); + return null; + } + } + + public Plant3D(ReadGraph graph) { + Builtin = getResourceOrNull(graph, URIs.Builtin); + Builtin_BallValve = getResourceOrNull(graph, URIs.Builtin_BallValve); + Builtin_BallValveGeometryProvider = getResourceOrNull(graph, URIs.Builtin_BallValveGeometryProvider); + Builtin_BranchSplitComponent = getResourceOrNull(graph, URIs.Builtin_BranchSplitComponent); + Builtin_Cap = getResourceOrNull(graph, URIs.Builtin_Cap); + Builtin_CapGeometryProvider = getResourceOrNull(graph, URIs.Builtin_CapGeometryProvider); + Builtin_CheckValve = getResourceOrNull(graph, URIs.Builtin_CheckValve); + Builtin_CheckValveGeometryProvider = getResourceOrNull(graph, URIs.Builtin_CheckValveGeometryProvider); + Builtin_ConcentricReducer = getResourceOrNull(graph, URIs.Builtin_ConcentricReducer); + Builtin_EccentricReducer = getResourceOrNull(graph, URIs.Builtin_EccentricReducer); + Builtin_Elbow = getResourceOrNull(graph, URIs.Builtin_Elbow); + Builtin_ElbowGeometryProvider = getResourceOrNull(graph, URIs.Builtin_ElbowGeometryProvider); + Builtin_GeometryProvider = getResourceOrNull(graph, URIs.Builtin_GeometryProvider); + Builtin_HorizontalTank = getResourceOrNull(graph, URIs.Builtin_HorizontalTank); + Builtin_HorizontalTankGeometryProvider = getResourceOrNull(graph, URIs.Builtin_HorizontalTankGeometryProvider); + Builtin_Nozzle = getResourceOrNull(graph, URIs.Builtin_Nozzle); + Builtin_NozzleGeometryProvider = getResourceOrNull(graph, URIs.Builtin_NozzleGeometryProvider); + Builtin_Pump = getResourceOrNull(graph, URIs.Builtin_Pump); + Builtin_PumpGeometryProvider = getResourceOrNull(graph, URIs.Builtin_PumpGeometryProvider); + Builtin_ReducerGeometryProvider = getResourceOrNull(graph, URIs.Builtin_ReducerGeometryProvider); + Builtin_Straight = getResourceOrNull(graph, URIs.Builtin_Straight); + Builtin_StraightGeometryProvider = getResourceOrNull(graph, URIs.Builtin_StraightGeometryProvider); + Builtin_VerticalTank = getResourceOrNull(graph, URIs.Builtin_VerticalTank); + Builtin_VerticalTankGeometryProvider = getResourceOrNull(graph, URIs.Builtin_VerticalTankGeometryProvider); + CodeComponent = getResourceOrNull(graph, URIs.CodeComponent); + Connects = getResourceOrNull(graph, URIs.Connects); + DualConnectedComponent = getResourceOrNull(graph, URIs.DualConnectedComponent); + EndComponent = getResourceOrNull(graph, URIs.EndComponent); + Equipment = getResourceOrNull(graph, URIs.Equipment); + FixedAngleTurnComponent = getResourceOrNull(graph, URIs.FixedAngleTurnComponent); + FixedLengthInlineComponent = getResourceOrNull(graph, URIs.FixedLengthInlineComponent); + HasAlternativePipeRun = getResourceOrNull(graph, URIs.HasAlternativePipeRun); + HasBranch0 = getResourceOrNull(graph, URIs.HasBranch0); + HasBranch1 = getResourceOrNull(graph, URIs.HasBranch1); + HasBranch2 = getResourceOrNull(graph, URIs.HasBranch2); + HasBranch3 = getResourceOrNull(graph, URIs.HasBranch3); + HasBranch4 = getResourceOrNull(graph, URIs.HasBranch4); + HasBranch5 = getResourceOrNull(graph, URIs.HasBranch5); + HasBranch6 = getResourceOrNull(graph, URIs.HasBranch6); + HasBranch7 = getResourceOrNull(graph, URIs.HasBranch7); + HasBranch8 = getResourceOrNull(graph, URIs.HasBranch8); + HasBranch9 = getResourceOrNull(graph, URIs.HasBranch9); + HasNext = getResourceOrNull(graph, URIs.HasNext); + HasNozzle = getResourceOrNull(graph, URIs.HasNozzle); + HasNozzleDefinition = getResourceOrNull(graph, URIs.HasNozzleDefinition); + HasNozzleDefinition_Inverse = getResourceOrNull(graph, URIs.HasNozzleDefinition_Inverse); + HasNozzleId = getResourceOrNull(graph, URIs.HasNozzleId); + HasNozzleId_Inverse = getResourceOrNull(graph, URIs.HasNozzleId_Inverse); + HasNozzleRestriction = getResourceOrNull(graph, URIs.HasNozzleRestriction); + HasNozzleRestriction_Inverse = getResourceOrNull(graph, URIs.HasNozzleRestriction_Inverse); + HasPipeDiameter = getResourceOrNull(graph, URIs.HasPipeDiameter); + HasPipeDiameter_Inverse = getResourceOrNull(graph, URIs.HasPipeDiameter_Inverse); + HasPipeRun = getResourceOrNull(graph, URIs.HasPipeRun); + HasPrevious = getResourceOrNull(graph, URIs.HasPrevious); + HasTurnAxis = getResourceOrNull(graph, URIs.HasTurnAxis); + HasTurnAxis_Inverse = getResourceOrNull(graph, URIs.HasTurnAxis_Inverse); + HasTurnRadius = getResourceOrNull(graph, URIs.HasTurnRadius); + HasTurnRadius_Inverse = getResourceOrNull(graph, URIs.HasTurnRadius_Inverse); + Images = getResourceOrNull(graph, URIs.Images); + Images_Component = getResourceOrNull(graph, URIs.Images_Component); + Images_Elbow = getResourceOrNull(graph, URIs.Images_Elbow); + Images_Factory = getResourceOrNull(graph, URIs.Images_Factory); + Images_Nozzle = getResourceOrNull(graph, URIs.Images_Nozzle); + Images_Straight = getResourceOrNull(graph, URIs.Images_Straight); + Images_Tank = getResourceOrNull(graph, URIs.Images_Tank); + ImportedOntologies = getResourceOrNull(graph, URIs.ImportedOntologies); + InlineComponent = getResourceOrNull(graph, URIs.InlineComponent); + IsReversed = getResourceOrNull(graph, URIs.IsReversed); + IsReversed_Inverse = getResourceOrNull(graph, URIs.IsReversed_Inverse); + LibraryComponent = getResourceOrNull(graph, URIs.LibraryComponent); + MultiConnectedComponent = getResourceOrNull(graph, URIs.MultiConnectedComponent); + NextInverse = getResourceOrNull(graph, URIs.NextInverse); + Node = getResourceOrNull(graph, URIs.Node); + NonVisibleComponent = getResourceOrNull(graph, URIs.NonVisibleComponent); + Nozzle = getResourceOrNull(graph, URIs.Nozzle); + NozzleOf = getResourceOrNull(graph, URIs.NozzleOf); + OffsetComponent = getResourceOrNull(graph, URIs.OffsetComponent); + P3DActionContext = getResourceOrNull(graph, URIs.P3DActionContext); + P3DActionContext_editTypeContribution = getResourceOrNull(graph, URIs.P3DActionContext_editTypeContribution); + P3DActionContext_newContribution = getResourceOrNull(graph, URIs.P3DActionContext_newContribution); + P3DActionContext_newTypeContribution = getResourceOrNull(graph, URIs.P3DActionContext_newTypeContribution); + P3DBrowseContext = getResourceOrNull(graph, URIs.P3DBrowseContext); + Parameter = getResourceOrNull(graph, URIs.Parameter); + PipeRun = getResourceOrNull(graph, URIs.PipeRun); + PipelineComponent = getResourceOrNull(graph, URIs.PipelineComponent); + PipelineComponentTag = getResourceOrNull(graph, URIs.PipelineComponentTag); + Plant = getResourceOrNull(graph, URIs.Plant); + PreviousInverse = getResourceOrNull(graph, URIs.PreviousInverse); + SingleConnectedComponent = getResourceOrNull(graph, URIs.SingleConnectedComponent); + SizeChangeComponent = getResourceOrNull(graph, URIs.SizeChangeComponent); + TurnComponent = getResourceOrNull(graph, URIs.TurnComponent); + VariableAngleTurnComponent = getResourceOrNull(graph, URIs.VariableAngleTurnComponent); + VariableLengthInlineComponent = getResourceOrNull(graph, URIs.VariableLengthInlineComponent); + childen = getResourceOrNull(graph, URIs.childen); + childen_Inverse = getResourceOrNull(graph, URIs.childen_Inverse); + hasGeometry = getResourceOrNull(graph, URIs.hasGeometry); + hasParameter = getResourceOrNull(graph, URIs.hasParameter); + hasParameterValue = getResourceOrNull(graph, URIs.hasParameterValue); + } + + public static Plant3D getInstance(ReadGraph graph) { + Session session = graph.getSession(); + Plant3D ret = session.peekService(Plant3D.class); + if(ret == null) { + QueryControl qc = graph.getService(QueryControl.class); + ret = new Plant3D(qc.getIndependentGraph(graph)); + session.registerService(Plant3D.class, ret); + } + return ret; + } + + public static Plant3D getInstance(RequestProcessor session) throws DatabaseException { + Plant3D ret = session.peekService(Plant3D.class); + if(ret == null) { + ret = session.syncRequest(new Read() { + public Plant3D perform(ReadGraph graph) throws DatabaseException { + QueryControl qc = graph.getService(QueryControl.class); + return new Plant3D(qc.getIndependentGraph(graph)); + } + }); + session.registerService(Plant3D.class, ret); + } + return ret; + } + +} + diff --git a/org.simantics.plant3d.product.feature/.project b/org.simantics.plant3d.product.feature/.project new file mode 100644 index 00000000..e08a90ed --- /dev/null +++ b/org.simantics.plant3d.product.feature/.project @@ -0,0 +1,17 @@ + + + org.simantics.plant3d.product.feature + + + + + + org.eclipse.pde.FeatureBuilder + + + + + + org.eclipse.pde.FeatureNature + + diff --git a/org.simantics.plant3d.product.feature/build.properties b/org.simantics.plant3d.product.feature/build.properties new file mode 100644 index 00000000..64f93a9f --- /dev/null +++ b/org.simantics.plant3d.product.feature/build.properties @@ -0,0 +1 @@ +bin.includes = feature.xml diff --git a/org.simantics.plant3d.product.feature/feature.xml b/org.simantics.plant3d.product.feature/feature.xml new file mode 100644 index 00000000..d5fcf108 --- /dev/null +++ b/org.simantics.plant3d.product.feature/feature.xml @@ -0,0 +1,46 @@ + + + + + [Enter Feature Description here.] + + + + [Enter Copyright Description here.] + + + + [Enter License Description here.] + + + + + + + + + + + + + + + diff --git a/org.simantics.plant3d.product/.classpath b/org.simantics.plant3d.product/.classpath new file mode 100644 index 00000000..ad32c83a --- /dev/null +++ b/org.simantics.plant3d.product/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/org.simantics.plant3d.product/.gitignore b/org.simantics.plant3d.product/.gitignore new file mode 100644 index 00000000..ae3c1726 --- /dev/null +++ b/org.simantics.plant3d.product/.gitignore @@ -0,0 +1 @@ +/bin/ diff --git a/org.simantics.plant3d.product/.project b/org.simantics.plant3d.product/.project new file mode 100644 index 00000000..5ace73e5 --- /dev/null +++ b/org.simantics.plant3d.product/.project @@ -0,0 +1,28 @@ + + + org.simantics.plant3d.product + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/org.simantics.plant3d.product/.settings/org.eclipse.jdt.core.prefs b/org.simantics.plant3d.product/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..c537b630 --- /dev/null +++ b/org.simantics.plant3d.product/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,7 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/org.simantics.plant3d.product/META-INF/MANIFEST.MF b/org.simantics.plant3d.product/META-INF/MANIFEST.MF new file mode 100644 index 00000000..4730f353 --- /dev/null +++ b/org.simantics.plant3d.product/META-INF/MANIFEST.MF @@ -0,0 +1,11 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Product +Bundle-SymbolicName: org.simantics.plant3d.product;singleton:=true +Bundle-Version: 1.0.0.qualifier +Bundle-Activator: org.simantics.plant3d.product.Activator +Require-Bundle: org.eclipse.core.runtime, + org.eclipse.ui;bundle-version="3.7.0" +Bundle-ActivationPolicy: lazy +Bundle-RequiredExecutionEnvironment: JavaSE-1.6 +Bundle-Vendor: VTT diff --git a/org.simantics.plant3d.product/build.properties b/org.simantics.plant3d.product/build.properties new file mode 100644 index 00000000..e1d2dead --- /dev/null +++ b/org.simantics.plant3d.product/build.properties @@ -0,0 +1,6 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + plugin.xml,\ + splash.bmp diff --git a/org.simantics.plant3d.product/plant3d.product b/org.simantics.plant3d.product/plant3d.product new file mode 100644 index 00000000..66e34df5 --- /dev/null +++ b/org.simantics.plant3d.product/plant3d.product @@ -0,0 +1,52 @@ + + + + + + + + Simantics Plant3D + + + + + + + + --launcher.XXMaxPermSize +192m +-fixerrors + -ea +-Xmx600M +-Xshare:off +-XX:MaxPermSize=192m +-Djava.net.preferIPv4Stack=true +-Dide.gc=true + -XstartOnFirstThread -Dorg.eclipse.swt.internal.carbon.smallFonts + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/org.simantics.plant3d.product/plugin.xml b/org.simantics.plant3d.product/plugin.xml new file mode 100644 index 00000000..c7215caf --- /dev/null +++ b/org.simantics.plant3d.product/plugin.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + diff --git a/org.simantics.plant3d.product/splash.bmp b/org.simantics.plant3d.product/splash.bmp new file mode 100644 index 00000000..aca08ba3 Binary files /dev/null and b/org.simantics.plant3d.product/splash.bmp differ diff --git a/org.simantics.plant3d.product/src/org/simantics/plant3d/product/Activator.java b/org.simantics.plant3d.product/src/org/simantics/plant3d/product/Activator.java new file mode 100644 index 00000000..87c1fac3 --- /dev/null +++ b/org.simantics.plant3d.product/src/org/simantics/plant3d/product/Activator.java @@ -0,0 +1,30 @@ +package org.simantics.plant3d.product; + +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; + +public class Activator implements BundleActivator { + + private static BundleContext context; + + static BundleContext getContext() { + return context; + } + + /* + * (non-Javadoc) + * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext) + */ + public void start(BundleContext bundleContext) throws Exception { + Activator.context = bundleContext; + } + + /* + * (non-Javadoc) + * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext) + */ + public void stop(BundleContext bundleContext) throws Exception { + Activator.context = null; + } + +} diff --git a/org.simantics.plant3d/.classpath b/org.simantics.plant3d/.classpath new file mode 100644 index 00000000..ad32c83a --- /dev/null +++ b/org.simantics.plant3d/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/org.simantics.plant3d/.gitignore b/org.simantics.plant3d/.gitignore new file mode 100644 index 00000000..ae3c1726 --- /dev/null +++ b/org.simantics.plant3d/.gitignore @@ -0,0 +1 @@ +/bin/ diff --git a/org.simantics.plant3d/.project b/org.simantics.plant3d/.project new file mode 100644 index 00000000..c40cd1af --- /dev/null +++ b/org.simantics.plant3d/.project @@ -0,0 +1,28 @@ + + + org.simantics.plant3d + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/org.simantics.plant3d/.settings/org.eclipse.jdt.core.prefs b/org.simantics.plant3d/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..c537b630 --- /dev/null +++ b/org.simantics.plant3d/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,7 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/org.simantics.plant3d/META-INF/MANIFEST.MF b/org.simantics.plant3d/META-INF/MANIFEST.MF new file mode 100644 index 00000000..6f2e691d --- /dev/null +++ b/org.simantics.plant3d/META-INF/MANIFEST.MF @@ -0,0 +1,39 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Plant3d +Bundle-SymbolicName: org.simantics.plant3d;singleton:=true +Bundle-Version: 1.0.0.qualifier +Bundle-Activator: org.simantics.plant3d.Activator +Bundle-Vendor: VTT +Require-Bundle: org.eclipse.core.runtime, + org.eclipse.ui, + org.eclipse.ui, + org.simantics.db;bundle-version="1.1.0", + org.simantics.db.common;bundle-version="1.1.0", + org.simantics.db.layer0;bundle-version="1.1.0", + org.simantics.project;bundle-version="1.0.1", + org.simantics.plant3d.ontology;bundle-version="1.0.0", + org.simantics.g3d;bundle-version="1.0.0", + org.simantics.g3d.ontology;bundle-version="1.0.0", + org.simantics.g3d.csg.ontology;bundle-version="1.0.0", + org.simantics.selectionview;bundle-version="1.0.0", + org.simantics.selectionview.ontology;bundle-version="1.0.0", + org.simantics.browsing.ui.swt;bundle-version="1.1.0", + vtk;bundle-version="5.8.0", + org.simantics.g3d.vtk;bundle-version="1.0.0", + javax.vecmath;bundle-version="1.5.2", + org.eclipse.ui.views;bundle-version="3.5.1", + org.simantics.opencascade;bundle-version="1.0.0", + org.jcae.opencascade;bundle-version="6.5.2", + org.eclipse.ui.console;bundle-version="3.5.100", + org.simantics.objmap2;bundle-version="1.0.0", + org.apache.log4j;bundle-version="1.2.15", + org.simantics.ui;bundle-version="1.0.0", + org.simantics.opencascade.vtk;bundle-version="1.0.0", + org.simantics.browsing.ui.platform;bundle-version="1.1.0", + org.simantics.structural.ui;bundle-version="1.1.1" +Bundle-RequiredExecutionEnvironment: JavaSE-1.6 +Bundle-ActivationPolicy: lazy +Export-Package: org.simantics.plant3d.editor, + org.simantics.plant3d.property, + org.simantics.plant3d.scenegraph diff --git a/org.simantics.plant3d/adapters.xml b/org.simantics.plant3d/adapters.xml new file mode 100644 index 00000000..4fc03c1e --- /dev/null +++ b/org.simantics.plant3d/adapters.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.simantics.plant3d/build.properties b/org.simantics.plant3d/build.properties new file mode 100644 index 00000000..c6d4e0ab --- /dev/null +++ b/org.simantics.plant3d/build.properties @@ -0,0 +1,7 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + plugin.xml,\ + adapters.xml,\ + icons/ diff --git a/org.simantics.plant3d/icons/Component.png b/org.simantics.plant3d/icons/Component.png new file mode 100644 index 00000000..0d43ef5b Binary files /dev/null and b/org.simantics.plant3d/icons/Component.png differ diff --git a/org.simantics.plant3d/icons/Elbow.png b/org.simantics.plant3d/icons/Elbow.png new file mode 100644 index 00000000..bbaa16ea Binary files /dev/null and b/org.simantics.plant3d/icons/Elbow.png differ diff --git a/org.simantics.plant3d/icons/Nozzle.png b/org.simantics.plant3d/icons/Nozzle.png new file mode 100644 index 00000000..48cf03e8 Binary files /dev/null and b/org.simantics.plant3d/icons/Nozzle.png differ diff --git a/org.simantics.plant3d/icons/Straight.png b/org.simantics.plant3d/icons/Straight.png new file mode 100644 index 00000000..459919e5 Binary files /dev/null and b/org.simantics.plant3d/icons/Straight.png differ diff --git a/org.simantics.plant3d/icons/factory.png b/org.simantics.plant3d/icons/factory.png new file mode 100644 index 00000000..aad23e32 Binary files /dev/null and b/org.simantics.plant3d/icons/factory.png differ diff --git a/org.simantics.plant3d/icons/middle.png b/org.simantics.plant3d/icons/middle.png new file mode 100644 index 00000000..4e3d03e7 Binary files /dev/null and b/org.simantics.plant3d/icons/middle.png differ diff --git a/org.simantics.plant3d/icons/middle.svg b/org.simantics.plant3d/icons/middle.svg new file mode 100644 index 00000000..670c3b42 --- /dev/null +++ b/org.simantics.plant3d/icons/middle.svg @@ -0,0 +1,190 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/org.simantics.plant3d/icons/plus.png b/org.simantics.plant3d/icons/plus.png new file mode 100644 index 00000000..1d6b816f Binary files /dev/null and b/org.simantics.plant3d/icons/plus.png differ diff --git a/org.simantics.plant3d/icons/plus.svg b/org.simantics.plant3d/icons/plus.svg new file mode 100644 index 00000000..7338a019 --- /dev/null +++ b/org.simantics.plant3d/icons/plus.svg @@ -0,0 +1,184 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/org.simantics.plant3d/icons/tank.png b/org.simantics.plant3d/icons/tank.png new file mode 100644 index 00000000..44015a37 Binary files /dev/null and b/org.simantics.plant3d/icons/tank.png differ diff --git a/org.simantics.plant3d/icons/translate.png b/org.simantics.plant3d/icons/translate.png new file mode 100644 index 00000000..21f52847 Binary files /dev/null and b/org.simantics.plant3d/icons/translate.png differ diff --git a/org.simantics.plant3d/icons/translate_d.png b/org.simantics.plant3d/icons/translate_d.png new file mode 100644 index 00000000..f4b3b608 Binary files /dev/null and b/org.simantics.plant3d/icons/translate_d.png differ diff --git a/org.simantics.plant3d/icons/x-axis.png b/org.simantics.plant3d/icons/x-axis.png new file mode 100644 index 00000000..8eb8a0d5 Binary files /dev/null and b/org.simantics.plant3d/icons/x-axis.png differ diff --git a/org.simantics.plant3d/icons/x-axis.svg b/org.simantics.plant3d/icons/x-axis.svg new file mode 100644 index 00000000..e5c2293f --- /dev/null +++ b/org.simantics.plant3d/icons/x-axis.svg @@ -0,0 +1,82 @@ + + + + + + + + + image/svg+xml + + + + + + + X + + + diff --git a/org.simantics.plant3d/icons/y-axis.png b/org.simantics.plant3d/icons/y-axis.png new file mode 100644 index 00000000..ca60724b Binary files /dev/null and b/org.simantics.plant3d/icons/y-axis.png differ diff --git a/org.simantics.plant3d/icons/y-axis.svg b/org.simantics.plant3d/icons/y-axis.svg new file mode 100644 index 00000000..65eddcf5 --- /dev/null +++ b/org.simantics.plant3d/icons/y-axis.svg @@ -0,0 +1,83 @@ + + + + + + + + + image/svg+xml + + + + + + + Y + + + diff --git a/org.simantics.plant3d/icons/z-axis.png b/org.simantics.plant3d/icons/z-axis.png new file mode 100644 index 00000000..11a57417 Binary files /dev/null and b/org.simantics.plant3d/icons/z-axis.png differ diff --git a/org.simantics.plant3d/icons/z-axis.svg b/org.simantics.plant3d/icons/z-axis.svg new file mode 100644 index 00000000..02e200dc --- /dev/null +++ b/org.simantics.plant3d/icons/z-axis.svg @@ -0,0 +1,83 @@ + + + + + + + + + image/svg+xml + + + + + + + Z + + + diff --git a/org.simantics.plant3d/plugin.xml b/org.simantics.plant3d/plugin.xml new file mode 100644 index 00000000..e256683a --- /dev/null +++ b/org.simantics.plant3d/plugin.xml @@ -0,0 +1,259 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/Activator.java b/org.simantics.plant3d/src/org/simantics/plant3d/Activator.java new file mode 100644 index 00000000..dcb18b5b --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/Activator.java @@ -0,0 +1,50 @@ +package org.simantics.plant3d; + +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +/** + * The activator class controls the plug-in life cycle + */ +public class Activator extends AbstractUIPlugin { + + // The plug-in ID + public static final String PLUGIN_ID = "org.simantics.plant3d"; //$NON-NLS-1$ + + // The shared instance + private static Activator plugin; + + /** + * The constructor + */ + public Activator() { + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext) + */ + public void start(BundleContext context) throws Exception { + super.start(context); + plugin = this; + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext) + */ + public void stop(BundleContext context) throws Exception { + plugin = null; + super.stop(context); + } + + /** + * Returns the shared instance + * + * @return the shared instance + */ + public static Activator getDefault() { + return plugin; + } + +} diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/actions/AddComponentAction.java b/org.simantics.plant3d/src/org/simantics/plant3d/actions/AddComponentAction.java new file mode 100644 index 00000000..bf220dd8 --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/actions/AddComponentAction.java @@ -0,0 +1,268 @@ +package org.simantics.plant3d.actions; + +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.util.HashSet; +import java.util.Set; + +import javax.vecmath.Vector3d; + +import org.eclipse.swt.widgets.Display; +import org.simantics.g3d.scenegraph.NodeMap; +import org.simantics.g3d.scenegraph.base.INode; +import org.simantics.g3d.vtk.action.vtkAction; +import org.simantics.g3d.vtk.common.InteractiveVtkPanel; +import org.simantics.plant3d.Activator; +import org.simantics.plant3d.dialog.ComponentSelectionDialog; +import org.simantics.plant3d.gizmo.TerminalSelectionGizmo; +import org.simantics.plant3d.scenegraph.InlineComponent; +import org.simantics.plant3d.scenegraph.P3DRootNode; +import org.simantics.plant3d.scenegraph.PipeRun; +import org.simantics.plant3d.scenegraph.PipelineComponent; +import org.simantics.plant3d.scenegraph.controlpoint.PipeControlPoint; +import org.simantics.plant3d.scenegraph.controlpoint.PipeControlPoint.Direction; +import org.simantics.plant3d.scenegraph.controlpoint.PipeControlPoint.PositionType; +import org.simantics.plant3d.scenegraph.controlpoint.PipingRules; +import org.simantics.plant3d.utils.ComponentUtils; +import org.simantics.plant3d.utils.Item; +import org.simantics.plant3d.utils.Item.Type; +import org.simantics.utils.threads.AWTThread; +import org.simantics.utils.threads.ThreadUtils; +import org.simantics.utils.ui.ExceptionUtils; + +import vtk.vtkProp; + +public class AddComponentAction extends vtkAction { + + + private P3DRootNode root; + private PipelineComponent component; + private NodeMap nodeMap; + + private TerminalSelectionGizmo gizmo; + + private Set allowed = new HashSet(); + + private Item toAdd = null; + + public AddComponentAction(InteractiveVtkPanel panel, P3DRootNode root) { + super(panel); + this.root = root; + setText("Add Component"); + setImageDescriptor(Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/Component.png")); + nodeMap = root.getNodeMap(); + gizmo = new TerminalSelectionGizmo(panel); + } + + public void setComponent(PipelineComponent component) { + this.component = component; + + allowed.clear(); + if (component.getNext() == null) { + allowed.add(PositionType.NEXT); + } + if (component.getPrevious() == null) { + allowed.add(PositionType.PREVIOUS); + } + if (component instanceof InlineComponent && !component.getControlPoint().isFixed()){ + allowed.add(PositionType.SPLIT); + } + setEnabled(allowed.size() > 0); + } + + private Double length; + private Double angle; + private Double diameter; + private Double turnRadius; + + @Override + public void run() { + ComponentSelectionDialog dialog = new ComponentSelectionDialog(Display.getCurrent().getActiveShell(), allowed); + if (dialog.open() == ComponentSelectionDialog.CANCEL) + return; + toAdd = dialog.getSelected(); + if (toAdd == null) + return; + this.length = dialog.getLength(); + this.angle = dialog.getAngle(); + this.diameter = dialog.getDiameter(); + this.turnRadius = dialog.getTurnRadius(); + allowed = dialog.filterAllowed(); + gizmo.setComponent(component, allowed); + super.run(); + panel.repaint(); + } + + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_ESCAPE) + panel.useDefaultAction(); + + + } + + public void attach() { + if (component == null) + return; + + super.attach(); + ThreadUtils.asyncExec(AWTThread.getThreadAccess(), new Runnable() { + public void run() { + attachUI(); + } + }); + + } + + public void deattach() { +// deactivate(); + component = null; + nodeMap.commit(); + deattachUI(); + super.deattach(); + panel.repaint(); + } + + private void attachUI() { + //panel.setCursor(activeCursor); + gizmo.attach(panel.GetRenderer()); + } + + private void deattachUI() { + //panel.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + gizmo.deattach(); + } + + @Override + public void mouseMoved(MouseEvent e) { + panel.getDefaultAction().mouseMoved(e); + } + + @Override + public void mousePressed(MouseEvent e) { + panel.getDefaultAction().mousePressed(e); + } + + @Override + public void mouseReleased(MouseEvent e) { + panel.getDefaultAction().mouseReleased(e); + } + + @Override + public void mouseDragged(MouseEvent e) { + panel.getDefaultAction().mouseDragged(e); + } + + public void doInsert(PositionType position) { + try { + PipelineComponent newComponent = ComponentUtils.createComponent(root,toAdd.getUri()); + PipeControlPoint newPcp = newComponent.getControlPoint(); + + PipeControlPoint toPcp = component.getControlPoint(); + Vector3d start = new Vector3d(); + Vector3d end = new Vector3d(); + Vector3d dir = new Vector3d(); + toPcp.getInlineControlPointEnds(start, end, dir); + dir.normalize(); + + switch (position) { + case NEXT: + if (toPcp.isDualInline()) + toPcp = toPcp.getSubPoint().get(0); + + break; + case PREVIOUS: + if (toPcp.isDualSub()) + toPcp = toPcp.parent; + } + PipeRun pipeRun = toPcp.getPipeRun(); + + 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(); + + dir.scale(newComponent.getControlPoint().getLength()*0.5); + start.sub(dir); + end.add(dir); + switch (position) { + case NEXT: + if (toPcp.isDualInline()) + toPcp = toPcp.getSubPoint().get(0); + newPcp.insert(toPcp, Direction.NEXT); + newPcp.setWorldPosition(end); + break; + case PREVIOUS: + if (toPcp.isDualSub()) + toPcp = toPcp.parent; + newPcp.insert(toPcp, Direction.PREVIOUS); + newPcp.setWorldPosition(start); + 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); + newPcp.setWorldPosition(end); + } else if (position == PositionType.PREVIOUS){ + PipingRules.addSizeChange(true, pipeRun, other, (InlineComponent)newComponent, toPcp, null); + newPcp.setWorldPosition(start); + } + // TODO : chicken-egg problem + newComponent.updateParameters(); + dir.scale(newComponent.getControlPoint().getLength()*0.5); + start.sub(dir); + end.add(dir); + if (position == PositionType.NEXT) { + newPcp.setWorldPosition(end); + } else if (position == PositionType.PREVIOUS){ + newPcp.setWorldPosition(start); + } + } + + + } catch (Exception e) { + ExceptionUtils.logAndShowError("Cannot add component", e); + } + } + + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() == 1 && e.getButton() == MouseEvent.BUTTON1) { + int type = panel.getPickType(); + panel.setPickType(0); + vtkProp[] picked = panel.pick(e.getX(), e.getY()); + panel.setPickType(type); + PositionType position = gizmo.getPickedPosition(picked); + if (position != null) { + doInsert(position); + panel.useDefaultAction(); + return; + } + } + panel.getDefaultAction().mouseClicked(e); + } +} diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/actions/AddEquipmentAction.java b/org.simantics.plant3d/src/org/simantics/plant3d/actions/AddEquipmentAction.java new file mode 100644 index 00000000..6c66909a --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/actions/AddEquipmentAction.java @@ -0,0 +1,33 @@ +package org.simantics.plant3d.actions; + +import org.eclipse.jface.action.Action; +import org.simantics.plant3d.scenegraph.Equipment; +import org.simantics.plant3d.scenegraph.P3DRootNode; +import org.simantics.plant3d.utils.Item; +import org.simantics.utils.ui.ExceptionUtils; + +public class AddEquipmentAction extends Action { + + P3DRootNode root; + private Item item; + + public AddEquipmentAction(P3DRootNode root, Item item) { + this.root = root; + this.item = item; + setText("Add " + item.getName()); + } + + @Override + public void run() { + try { + Equipment equipment = root.createEquipment(); + equipment.setType(item.getUri()); + String n = root.getUniqueName(item.getName()); + equipment.setName(n); + root.addChild(equipment); + root.getNodeMap().commit(); + } catch (Exception e) { + ExceptionUtils.logAndShowError("Cannot create equipment",e); + } + } +} diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/actions/AddNozzleAction.java b/org.simantics.plant3d/src/org/simantics/plant3d/actions/AddNozzleAction.java new file mode 100644 index 00000000..e6b8ecd6 --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/actions/AddNozzleAction.java @@ -0,0 +1,49 @@ +package org.simantics.plant3d.actions; + +import org.eclipse.jface.action.Action; +import org.simantics.plant3d.Activator; +import org.simantics.plant3d.scenegraph.Equipment; +import org.simantics.plant3d.scenegraph.Nozzle; +import org.simantics.plant3d.scenegraph.P3DRootNode; +import org.simantics.plant3d.scenegraph.PipeRun; +import org.simantics.plant3d.utils.Item; +import org.simantics.utils.ui.ExceptionUtils; + +public class AddNozzleAction extends Action { + + P3DRootNode root; + private Item item; + private Equipment equipment; + + public AddNozzleAction(P3DRootNode root, Item item) { + this.root = root; + this.item = item; + setText("Add " + item.getName()); + setImageDescriptor(Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/Nozzle.png")); + } + + public void setEquipment(Equipment equipment) { + this.equipment = equipment; + } + + @Override + public void run() { + try { + Nozzle nozzle = root.createNozzle(); + nozzle.setType(item.getUri()); + String n = root.getUniqueName(item.getName()); + nozzle.setName(n); + PipeRun pipeRun = new PipeRun(); + n = root.getUniqueName("PipeRun"); + pipeRun.setName(n); + nozzle.setPipeRun(pipeRun); + + equipment.addChild(nozzle); + //root.addChild(nozzle); + root.addChild(pipeRun); + root.getNodeMap().commit(); + } catch (Exception e) { + ExceptionUtils.logAndShowError("Cannot create equipment",e); + } + } +} diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/actions/RoutePipeAction.java b/org.simantics.plant3d/src/org/simantics/plant3d/actions/RoutePipeAction.java new file mode 100644 index 00000000..0310311d --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/actions/RoutePipeAction.java @@ -0,0 +1,1188 @@ +package org.simantics.plant3d.actions; + +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import javax.vecmath.Point3d; +import javax.vecmath.Tuple3d; +import javax.vecmath.Vector3d; + +import org.simantics.g3d.math.MathTools; +import org.simantics.g3d.math.Ray; +import org.simantics.g3d.scenegraph.NodeMap; +import org.simantics.g3d.scenegraph.base.INode; +import org.simantics.g3d.tools.ConstraintDetector; +import org.simantics.g3d.tools.DummyConstraintDetector; +import org.simantics.g3d.vtk.action.vtkAction; +import org.simantics.g3d.vtk.common.InteractiveVtkPanel; +import org.simantics.g3d.vtk.gizmo.TranslateAxisGizmo; +import org.simantics.g3d.vtk.utils.vtkUtil; +import org.simantics.plant3d.Activator; +import org.simantics.plant3d.gizmo.SplitPointSelectionGizmo; +import org.simantics.plant3d.gizmo.TerminalSelectionGizmo; +import org.simantics.plant3d.ontology.Plant3D; +import org.simantics.plant3d.scenegraph.EndComponent; +import org.simantics.plant3d.scenegraph.InlineComponent; +import org.simantics.plant3d.scenegraph.Nozzle; +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.PipeControlPoint.Direction; +import org.simantics.plant3d.scenegraph.controlpoint.PipeControlPoint.PositionType; +import org.simantics.plant3d.scenegraph.controlpoint.PipingRules; +import org.simantics.plant3d.utils.ComponentUtils; +import org.simantics.utils.threads.AWTThread; +import org.simantics.utils.threads.ThreadUtils; +import org.simantics.utils.ui.ExceptionUtils; + +import vtk.vtkProp; +import vtk.vtkTextActor; + +public class RoutePipeAction extends vtkAction { + enum LockType { + X, Y, Z, XY, YZ, XZ, NONE, CUSTOM + }; + + LockType lock = LockType.NONE; + private double BRANCH_SNAP_DISTANCE = 0.05; + private double NOZZLE_SNAP_DISTANCE = 0.05; + + private double istep = 10.0; + private int decimals = 2; + + private P3DRootNode root; + private PipelineComponent startComponent; + private PipeRun pipeRun; + + private TranslateAxisGizmo translateAxisGizmo = new TranslateAxisGizmo(); + private SplitPointSelectionGizmo splitPointSelectionGizmo; + private TerminalSelectionGizmo terminalSelectionGizmo; + private NodeMap nodeMap; + + private enum ToolState{NOT_ACTIVE, INITIALIZING, SELECTING_POSITION, SELECTING_SPLIT, ROUTING}; + private ToolState state = ToolState.NOT_ACTIVE; + + private ConstraintDetector detector = new DummyConstraintDetector(); + + private boolean useDefault = false; + private Vector3d direction = null; + private Vector3d previousPosition = null; + private Vector3d currentPosition = null; + + boolean step = false; + + PipelineComponent endTo = null; + PositionType endType = null; + PipeControlPoint endPort = null; + + boolean reversed = false; + + private Set allowed = new HashSet(); + + + public RoutePipeAction(InteractiveVtkPanel panel, P3DRootNode root) { + super(panel); + this.root = root; + setText("Route Pipe"); + setImageDescriptor(Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/Straight.png")); + nodeMap = root.getNodeMap(); + splitPointSelectionGizmo = new SplitPointSelectionGizmo(panel); + terminalSelectionGizmo = new TerminalSelectionGizmo(panel); + } + + public void setComponent(PipelineComponent component) { + this.startComponent = component; + allowed.clear(); + if (this.startComponent.getNext() == null) + allowed.add(PositionType.NEXT); + if (this.startComponent.getPrevious() == null && !(this.startComponent instanceof Nozzle)) + allowed.add(PositionType.PREVIOUS); + if (this.startComponent instanceof InlineComponent && !this.startComponent.getControlPoint().isFixed()) + allowed.add(PositionType.SPLIT); + setEnabled(allowed.size() > 0); + } + + public void deattach() { + deactivate(); + startComponent = null; + nodeMap.commit(); + deattachUI(); + super.deattach(); + panel.repaint(); + } + + public void attach() { + if (startComponent == null) + return; + + super.attach(); + ThreadUtils.asyncExec(AWTThread.getThreadAccess(), new Runnable() { + public void run() { +// attachUI(); + try { + activate(); + } catch (Exception e) { + deattach(); + ExceptionUtils.logAndShowError(e); + } + + } + }); + + } + +// private void attachUI() { +// //panel.setCursor(activeCursor); +// translateAxisGizmo.attach(panel.GetRenderer()); +// } + + private void deattachUI() { + //panel.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + if (translateAxisGizmo.isAttached()) + translateAxisGizmo.deattach(); + if (splitPointSelectionGizmo.isAttached()) + splitPointSelectionGizmo.deattach(); + if (terminalSelectionGizmo.isAttached()) + terminalSelectionGizmo.deattach(); + if (infoActor != null) { + panel.GetRenderer().RemoveActor(infoActor); + infoActor.Delete(); + infoActor = null; + } + } + + private List added = new ArrayList(); + + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_ESCAPE) + panel.useDefaultAction(); + if (lock != LockType.CUSTOM) { + if ((e.getModifiersEx() & KeyEvent.SHIFT_DOWN_MASK) > 0) { + if (e.getKeyCode() == KeyEvent.VK_X) { + if (lock != LockType.XY && lock != LockType.XZ) { + setLockType(LockType.XY, false); + } else if (lock == LockType.XY) { + setLockType(LockType.XZ, false); + } else { + setLockType(LockType.NONE, false); + } + } + if (e.getKeyCode() == KeyEvent.VK_Y) { + if (lock != LockType.XY && lock != LockType.YZ) { + setLockType(LockType.XY, false); + } else if (lock == LockType.XY) { + setLockType(LockType.YZ, false); + } else { + setLockType(LockType.NONE, false); + } + } + if (e.getKeyCode() == KeyEvent.VK_Z) { + if (lock != LockType.XZ && lock != LockType.YZ) { + setLockType(LockType.XZ, false); + } else if (lock == LockType.XZ) { + setLockType(LockType.YZ, false); + } else { + setLockType(LockType.NONE, false); + } + } + } else { + if (e.getKeyCode() == KeyEvent.VK_X) { + if (lock != LockType.X) + setLockType(LockType.X,false); + else + setLockType(LockType.NONE,false); + } + if (e.getKeyCode() == KeyEvent.VK_Y) { + if (lock != LockType.Y) + setLockType(LockType.Y,false); + else + setLockType(LockType.NONE, false); + } + if (e.getKeyCode() == KeyEvent.VK_Z) { + if (lock != LockType.Z) + setLockType(LockType.Z, false); + else + setLockType(LockType.NONE, false); + } + } + } + if (e.getKeyCode() == KeyEvent.VK_C) { + useDefault = !useDefault; + System.out.println("UseDefault " + useDefault); + } + + + + + update(); + + } + + + private void update() { + panel.repaint(); + } + private void update(double x, double y) { + switch (state) { + case NOT_ACTIVE: + return; // TODO : throw Exception? + case INITIALIZING: + return; + case SELECTING_POSITION: + return; + case SELECTING_SPLIT: + return; + case ROUTING: + updateRouting(x,y); + break; + } + return; + } + + boolean startRemovable = false; + + private void activate() throws Exception { + state = ToolState.INITIALIZING; + added.clear(); + + if (allowed.size() == 1) { + pipeRun = startComponent.getPipeRun(); + PipeControlPoint start = startComponent.getControlPoint(); + boolean requiresBranching = false; + if (start.getNext() == null) + reversed = false; + else if (start.getPrevious() == null) { + reversed = true; + } else { + requiresBranching = true; + } + + if (requiresBranching) { + activateSplit(start); + } else { + activateNextPrev(start); + } + } else if (allowed.size() == 0) { + panel.useDefaultAction(); + state = ToolState.NOT_ACTIVE; + return; + } else { + terminalSelectionGizmo.setComponent(startComponent, allowed); + terminalSelectionGizmo.attach(panel.GetRenderer()); + state = ToolState.SELECTING_POSITION; + panel.repaint(); + } + + } + + + + private void activateNextPrev(PipeControlPoint start) throws Exception{ + if (!reversed && start.isDualInline()) + start = start.getSubPoint().get(0); + else if (reversed && start.isDualSub()) + start = start.parent; + + pipeRun = start.getPipeRun(); + setPreviousPosition(start.getWorldPosition()); + + boolean startWithTurn = false; + if (startComponent instanceof Nozzle) { + direction = startComponent.getControlPoint().getDirectedControlPointDirection(); + lock = LockType.CUSTOM; + } else if (startComponent instanceof PipelineComponent){ + if (startComponent instanceof InlineComponent) { + direction = startComponent.getControlPoint().getPathLegDirection(reversed ? Direction.PREVIOUS : Direction.NEXT); + lock = LockType.CUSTOM; + if (startComponent.getType().equals(Plant3D.URIs.Builtin_Straight)) { + startWithTurn = true; + direction = null; + lock = LockType.NONE; + } + Vector3d v = new Vector3d(); + if (!reversed) { + start.getControlPointEnds(v, previousPosition); + } else { + start.getControlPointEnds(previousPosition,v); + } + } else if (startComponent instanceof TurnComponent) { + if (start.isFixed()) { + direction = startComponent.getControlPoint().getPathLegDirection(reversed ? Direction.PREVIOUS : Direction.NEXT); + lock = LockType.CUSTOM; + } else { + direction = null; + lock = LockType.NONE; + } + } else if (startComponent instanceof EndComponent) { + throw new Exception("Not supported"); + } + + } else { + throw new Exception("Not supported"); + } + currentPosition = new Vector3d(previousPosition); + state = ToolState.ROUTING; + if (direction != null) { + direction.normalize(); + + } + startRemovable = start.isDeletable(); + start.setDeletable(false); + + if (startWithTurn) { + addPoint(); + } else { + if (direction != null) + currentPosition.add(direction); + InlineComponent straight = ComponentUtils.createStraight(root); + PipeControlPoint straightCP = straight.getControlPoint(); + straight.setName(pipeRun.getUniqueName("Pipe")); + pipeRun.addChild(straight); + added.add(straight); + + if (!reversed) { + start.setNext(straightCP); + straightCP.setPrevious(start); + } else { + start.setPrevious(straightCP); + straightCP.setNext(start); + } + } + translateAxisGizmo.attach(panel.GetRenderer()); + setPreviousPosition(previousPosition); + updateCurrentPoint(); + } + + private void setPreviousPosition(Vector3d v) { + previousPosition = new Vector3d(v); + if (translateAxisGizmo.isAttached()) + translateAxisGizmo.setPosition(previousPosition); + } + + private void activateBranch(PipeControlPoint start) throws Exception{ + pipeRun = start.getPipeRun(); + setPreviousPosition(start.getWorldPosition()); + + direction = null; + lock = LockType.NONE; + + currentPosition = new Vector3d(previousPosition); + state = ToolState.ROUTING; + if (direction != null) { + direction.normalize(); + + } + startRemovable = start.isDeletable(); + start.setDeletable(false); + + + if (direction != null) + currentPosition.add(direction); + InlineComponent straight = ComponentUtils.createStraight(root); + PipeControlPoint straightCP = straight.getControlPoint(); + straight.setName(pipeRun.getUniqueName("Pipe")); + pipeRun.addChild(straight); + added.add(straight); + + if (!reversed) { + start.setNext(straightCP); + straightCP.setPrevious(start); + + } else { + start.setPrevious(straightCP); + straightCP.setNext(start); + + } + + translateAxisGizmo.attach(panel.GetRenderer()); + setPreviousPosition(previousPosition); + updateCurrentPoint(); + } + + private void activateSplit(PipeControlPoint start) throws Exception{ + Point3d p1 = new Point3d(); + Point3d p2 = new Point3d(); + start.getInlineControlPointEnds(p1, p2); + splitPointSelectionGizmo.setSplit(p1, p2); + splitPointSelectionGizmo.attach(panel.GetRenderer()); + state = ToolState.SELECTING_SPLIT; + } + public void deactivate() { + for (PipelineComponent component : added) { + component.getControlPoint().setDeletable(true); + } + + added.clear(); + startComponent.getControlPoint().setDeletable(startRemovable); + + direction = null; + + setLockType(LockType.NONE, true); + startComponent = null; + endTo = null; + endPort = null; + endType = null; + pipeRun = null; + allowed.clear(); + currentPosition = null; + previousPosition = null; + startRemovable = false; + detector.clearConstraintHighlights(); + state = ToolState.NOT_ACTIVE; + setEnabled(false); + + + } + + private void setLockType(LockType type, boolean force) { + if (force || lock != LockType.CUSTOM) { + lock = type; + + switch (lock) { + case CUSTOM: + case NONE: + translateAxisGizmo.setType(6); + break; + case X: + translateAxisGizmo.setType(0); + break; + case Y: + translateAxisGizmo.setType(1); + break; + case Z: + translateAxisGizmo.setType(2); + break; + case XY: + translateAxisGizmo.setType(3); + break; + case XZ: + translateAxisGizmo.setType(4); + break; + case YZ: + translateAxisGizmo.setType(5); + break; + + } + } + } + + @Override + public void mousePressed(MouseEvent e) { + if (useDefault) { + panel.getDefaultAction().mousePressed(e); + } + } + + @Override + public void mouseReleased(MouseEvent e) { + if (useDefault) { + panel.getDefaultAction().mouseReleased(e); + } + } + + @Override + public void mouseClicked(MouseEvent e) { + if (useDefault) { + panel.getDefaultAction().mouseClicked(e); + return; + } + if (state == ToolState.ROUTING) { + try { + if (e.getClickCount() == 1) { + if (e.getButton() == MouseEvent.BUTTON1) { + if (this.added.size() > 0) { + + setLockType(LockType.NONE,true); + if (endTo != null) { + + endPiping(); + } else { + addPoint(); + } + } else { + throw new RuntimeException("kjf"); + // // user was selecting position of branch + // lastPoint.set(startPoint); + // controlPoints.add(new Point3d(startPoint)); + // if (selectionLine != null) + // selectionLine.removeFromParent(); + // selectionLine = null; + } + } else if (e.getButton() ==MouseEvent.BUTTON2){ + // detector.updateConstraintReference(); + } else if (e.getButton() == MouseEvent.BUTTON3){ + endPiping(); + } + } + } catch(Exception err) { + err.printStackTrace(); + } + } else if (state == ToolState.SELECTING_POSITION) { + if (e.getClickCount() == 1 && e.getButton() == MouseEvent.BUTTON1) { + int type = panel.getPickType(); + panel.setPickType(0); + vtkProp[] picked = panel.pick(e.getX(), e.getY()); + panel.setPickType(type); + PositionType position = terminalSelectionGizmo.getPickedPosition(picked); + if (position != null) { + terminalSelectionGizmo.deattach(); + try { + if (position == PositionType.SPLIT) { + activateSplit(startComponent.getControlPoint()); + } else if (position == PositionType.NEXT || position == PositionType.PREVIOUS) { + reversed = position == PositionType.PREVIOUS; + activateNextPrev(startComponent.getControlPoint()); + } else { + panel.useDefaultAction(); + } + } catch (Exception err) { + ExceptionUtils.logAndShowError(err); + panel.useDefaultAction(); + } + } + } + } else if (state == ToolState.SELECTING_SPLIT) { + if (e.getClickCount() == 1 && e.getButton() == MouseEvent.BUTTON1) { + Tuple3d t = splitPointSelectionGizmo.getSplitPoint(); + splitPointSelectionGizmo.deattach(); + if (t == null) { + panel.useDefaultAction(); + return; + } + try { + Vector3d pos = new Vector3d(t); + InlineComponent branchSplit = createBranchSplit((InlineComponent)startComponent, pos); + PipeControlPoint branchSplitCP = branchSplit.getControlPoint(); + reversed = false; + PipeRun newRun = new PipeRun(); + String n = root.getUniqueName("PipeRun"); + newRun.setName(n); + root.addChild(newRun); + PipeControlPoint pcp = new PipeControlPoint(branchSplit,newRun); + branchSplitCP.children.add(pcp); + pcp.parent = branchSplitCP; + pcp.setWorldOrientation(branchSplitCP.getWorldOrientation()); + pcp.setWorldPosition(branchSplitCP.getWorldPosition()); + startComponent = branchSplit; + activateBranch(pcp); + } catch (Exception err) { + ExceptionUtils.logAndShowError(err); + panel.useDefaultAction(); + } + } + } + + } + + private InlineComponent createBranchSplit(InlineComponent component, Vector3d pos) throws Exception{ + InlineComponent branchSplit = ComponentUtils.createBranchSplit(root); + String branchName = component.getPipeRun().getUniqueName("Branch"); + branchSplit.setName(branchName); + component.getPipeRun().addChild(branchSplit); + PipeControlPoint branchSplitCP = branchSplit.getControlPoint(); + branchSplitCP.setWorldPosition(pos); + PipingRules.splitVariableLengthComponent(branchSplit, component, false); + return branchSplit; + } + + @Override + public void mouseMoved(MouseEvent e) { + if (useDefault) { + panel.getDefaultAction().mouseMoved(e); + return; + } + step = ((e.getModifiers() & MouseEvent.CTRL_DOWN_MASK) > 0); + update(e.getX(), e.getY()); + } + + @Override + public void mouseDragged(MouseEvent e) { + if (useDefault) + panel.getDefaultAction().mouseDragged(e); + } + + + + + private List isOverNode(int x, int y) { + List nodes = new ArrayList(); + vtkProp picked[] = panel.pick2(x, y); + if (picked !=null) { + for (int i = 0; i < picked.length; i++) { + nodes.add(nodeMap.getNode(picked[i])); + } + } + return nodes; + } + + + + private void updateRouting(double x, double y) { +// if(input.keyPressed(KeyEvent.VK_ESCAPE)) { +// controlPoints.clear(); +// end(); +// return; +// } +// if (input.keyPressed(KeyEvent.VK_C)) { +// useCamera = !useCamera; +// cameraAction.setChecked(useCamera); +// } + if (useDefault) { + //panel.getDefaultAction().update(); + return; + } + + endTo = null; + endType = null; + endPort = null; + + Ray ray = vtkUtil.createMouseRay(panel.GetRenderer(),x, y); + Vector3d o = new Vector3d(ray.pos); + Vector3d d = ray.dir; + + + if (!updateCurrentPoint(o, d)) + return; + //Point3d startPoint = new Point3d(); + double mu[] = new double[2]; + + + + INode hoverObject = null; + + List hover = isOverNode((int)x,(int)y); + if (hover.size() > 0) { + hoverObject = hover.get(0); + } +// System.out.println(hoverObject + " " + getLast()); + if (hoverObject != null) { + if (hoverObject.equals(getLast()) ) { + boolean set = false; + for (int i = 1; i < hover.size(); i++) { + hoverObject = hover.get(i); + if (!getLast().equals(hoverObject)) { + set = true; + break; + } + } + if (!set) + hoverObject = null; + } + } +// System.out.println(hoverObject); + if (hoverObject != null) { + + if (lock == LockType.NONE) { + if (hoverObject instanceof Nozzle && endingToNozzle(hoverObject,o,d)) { + endTo = (Nozzle)hoverObject; + } else if (hoverObject instanceof InlineComponent && ((InlineComponent)hoverObject).isVariableLength()) { + endTo = (InlineComponent)hoverObject; + endType = endingToStraight(endTo,mu,o,d); + } else if (hoverObject instanceof PipelineComponent && (endPort = endingToComponent(hoverObject,o,d)) != null) { + endTo = (PipelineComponent)hoverObject; + } else { + updateRoute(o,d); + } + } else { + if (hoverObject instanceof InlineComponent && ((InlineComponent)hoverObject).isVariableLength() && (endType = endingLockToStraight(hoverObject,mu)) != null) { + endTo = (InlineComponent)hoverObject;; + } else if (hoverObject instanceof Nozzle && endingLockToNozzle(hoverObject)) { + endTo = (Nozzle)hoverObject; + } else if ((hoverObject instanceof PipelineComponent) && ((endPort = endingLockToComponent(hoverObject)) != null)) { + endTo = (PipelineComponent)hoverObject; + } else { + updateRoute(o,d); + } + } + if (added.contains(endTo)) + endTo = null; + + } else { + updateRoute(o,d); + } + + panel.repaint(); + + + + + } + + private boolean updateCurrentPoint(Vector3d o, Vector3d d) { + + Vector3d point = new Vector3d(this.previousPosition); + + switch(lock) { + case X: + MathTools.intersectStraightStraight(point, new Vector3d(1.0,0.0,0.0), o,d, currentPosition, new Vector3d()); + if (step) { + currentPosition.x = Math.round(istep * currentPosition.x) / istep; + BigDecimal bx = new BigDecimal(currentPosition.x); + bx.setScale(decimals, BigDecimal.ROUND_HALF_UP); + currentPosition.x = bx.doubleValue(); + } + break; + case Y: + MathTools.intersectStraightStraight(point, new Vector3d(0.0,1.0,0.0), o,d, currentPosition, new Vector3d()); + if (step) { + currentPosition.y = Math.round(istep * currentPosition.y) / istep; + BigDecimal bx = new BigDecimal(currentPosition.y); + bx.setScale(decimals, BigDecimal.ROUND_HALF_UP); + currentPosition.y = bx.doubleValue(); + } + break; + case Z: + MathTools.intersectStraightStraight(point, new Vector3d(0.0,0.0,1.0), o,d, currentPosition, new Vector3d()); + if (step) { + currentPosition.z = Math.round(istep * currentPosition.z) / istep; + BigDecimal bx = new BigDecimal(currentPosition.z); + bx.setScale(decimals, BigDecimal.ROUND_HALF_UP); + currentPosition.z = bx.doubleValue(); + }break; + case XY: + MathTools.intersectStraightPlane(o, d, point, new Vector3d(0.0,0.0,1.0), currentPosition); + break; + case XZ: + MathTools.intersectStraightPlane(o, d, point, new Vector3d(0.0,1.0,0.0), currentPosition); + break; + case YZ: + MathTools.intersectStraightPlane(o, d, point, new Vector3d(1.0,0.0,0.0), currentPosition); + break; + case NONE: + Vector3d normal = new Vector3d(panel.GetRenderer().GetActiveCamera().GetDirectionOfProjection()); + normal.normalize(); + + MathTools.intersectStraightPlane(o, d, point, normal, currentPosition); + break; + case CUSTOM: + MathTools.intersectStraightStraight(point, new Vector3d(direction), o,d, currentPosition, new Vector3d()); + double dist = MathTools.distanceFromPlane(new Vector3d(currentPosition), direction, previousPosition); + if (dist < 0.0) + currentPosition.set(previousPosition); + break; + default: + return false; + } + return true; + } + + private Vector3d getLockDir() { + switch (lock) { + case CUSTOM: + return direction; + case X: + return new Vector3d(1,0,0); + case Y: + return new Vector3d(0,1,0); + case Z: + return new Vector3d(0,0,1); + } + return null; + } + + private void updateRoute(Vector3d o, Vector3d d) { + detector.clearConstraintHighlights(); + Point3d previousPipePoint = new Point3d(previousPosition); + String s = ""; + if (lock == LockType.NONE) { + Point3d p = detector.getSnappedPoint(o, d, new Vector3d(previousPipePoint)); + if (p != null) + currentPosition = new Vector3d(p); + s += detector.getSnapString(); + + } else { + Vector3d dir = new Vector3d(currentPosition); + dir.sub(previousPipePoint); + Point3d p = detector.getPointSnap(new Vector3d(previousPipePoint), dir); + if (p != null) + currentPosition = new Vector3d(p); + s += detector.getSnapString(); + + } + + updateCurrentPoint(); + s += currentPosition.toString(); + setInfoText(s); + } + + vtkTextActor infoActor; + + private void setInfoText(String text) { + //System.out.println(text); + if (infoActor == null) { + infoActor = new vtkTextActor(); + infoActor.GetTextProperty().SetColor(0.0, 0.0, 0.0); + infoActor.GetTextProperty().ShadowOff(); + infoActor.GetTextProperty().ItalicOff(); + infoActor.GetTextProperty().BoldOff(); + infoActor.GetTextProperty().SetFontSize(18); + infoActor.GetTextProperty().Delete(); + infoActor.GetProperty().SetColor(0.0, 0.0, 0.0); + infoActor.GetProperty().Delete(); + + + infoActor.SetPosition(10,10); + panel.GetRenderer().AddActor(infoActor); + } + infoActor.SetInput(text); + } + + private boolean endingToNozzle(INode nozzleNode,Vector3d o, Vector3d d) { + Nozzle nozzle = (Nozzle)nozzleNode; + PipeControlPoint pcp =nozzle.getControlPoint(); + if (pcp != null && (pcp.getNext() != null || + pcp.getPrevious() != null)) + return false; // nozzle is already connected to pipe + currentPosition = pcp.getWorldPosition(); + Point3d previousPipePoint = new Point3d(previousPosition); + Point3d p = detector.getSnappedPoint(o, d, new Vector3d(previousPipePoint)); + if (p != null) { + if (MathTools.distance(p, currentPosition) > NOZZLE_SNAP_DISTANCE) { + return false; + } + } + + updateCurrentPoint(); + + setInfoText("Connect to nozzle " + currentPosition); + return true; + + } + + private PositionType endingToStraight(INode straightNode, double mu[], Vector3d o, Vector3d d) { + InlineComponent s = (InlineComponent)straightNode; + String info = ""; + Point3d sStart = new Point3d(); + Point3d sEnd = new Point3d(); + s.getControlPointEnds(sStart, sEnd); + //detector.clearConstraintHighlights(); + + Point3d previousPipePoint = new Point3d(previousPosition); + //String st = ""; + if (lock == LockType.NONE) { + Point3d p = detector.getSnappedPoint(o, d, new Vector3d(previousPipePoint)); + if (p != null) { + currentPosition = new Vector3d(p); + // snapping is detected, check if snapped point can create branch with straight + PositionType t = endingLockToStraight(s, mu); + if (t != null) + return t; + // if not, we'll have to remove highlight that was added when snapped point was detected + detector.clearConstraintHighlights(); + } + + + Vector3d sDir = new Vector3d(sEnd); + sDir.sub(sStart); + MathTools.intersectStraightStraight(sStart, sDir, o, d, currentPosition, new Point3d(), mu); + + + } else { + throw new RuntimeException("Lock shouldn't be on"); + + } + + updateCurrentPoint(); + + // branch point must lie between straight's ends. If connection point is exactly + // on straight end user may want to connect pipes to each other + // TODO : take account sizes of inline components) + // TODO : actually make connection if its detected + boolean connectPrev = false; + boolean connectNext = false; + + if (mu[0] < 0.0) { + currentPosition.set(sStart); + connectPrev = true; + } + else if (mu[0] > 1.0) { + currentPosition.set(sEnd); + connectNext = true; + } + boolean connect = false; + if (connectPrev) { + PipeControlPoint pcp = s.getControlPoint(); + if (pcp.getPrevious() == null) + connect = true; + } else if (connectNext) { + PipeControlPoint pcp = s.getControlPoint(); + if (pcp.getNext() == null) + connect = true; + } + + updateCurrentPoint(); + + if (connect) + info += "Connect pipes :"; + else + info += "Make Branch :"; + + setInfoText(info + currentPosition + " " + Math.max(0.0, Math.min(mu[0], 1.0))); + if (connect) { + if (connectNext) { + return PositionType.NEXT; + } else { + return PositionType.PREVIOUS; + } + + } + return PositionType.SPLIT; + + } + + private PipeControlPoint endingToComponent(INode componentNode, Vector3d o, Vector3d d) { + PipelineComponent component = (PipelineComponent)componentNode; + PipeControlPoint pcp = component.getControlPoint(); + if (component instanceof EndComponent) { + if (pcp.getNext() != null || pcp.getPrevious() != null) + return null; + return pcp; + } else if (component instanceof TurnComponent) { + if (pcp.getNext() == null || pcp.getPrevious() == null) + return pcp; + return null; + } else if (component instanceof InlineComponent) { + // TODO : scan all empty pcps of the component and select closest one. + if (pcp.getNext() == null || pcp.getPrevious() == null) + return pcp; + return null; + } + + return null; + } + + private PositionType endingLockToStraight(INode straightNode, double mu[]) { + InlineComponent s = (InlineComponent)straightNode; + Point3d sStart = new Point3d();//G3DTools.getPoint(s.getHasControlPoint().getPreviousPoint().getLocalPosition()); + Point3d sEnd = new Point3d(); //G3DTools.getPoint(s.getHasControlPoint().getNextPoint().getLocalPosition()); + s.getControlPoint().getInlineControlPointEnds(sStart, sEnd); + Vector3d sDir = new Vector3d(sEnd); + sDir.sub(sStart); + Vector3d dir = new Vector3d(currentPosition); + Point3d prev = new Point3d(previousPosition); + dir.sub(prev); + // intersection point in pipe where branch would be inserted to + Vector3d branchPoint = new Vector3d(); + // intersection point in straight pipe that is currently routed + Vector3d routePoint = new Vector3d(); + MathTools.intersectStraightStraight(sStart, sDir, new Vector3d(prev), dir, branchPoint, routePoint, mu); + routePoint.sub(branchPoint); + // startPoint of branch must be between pipe ends + // TODO : take account sizes of elbows (or other components) + // branch point must be between pipe ends and intersection points must be quite close to each othert + if (mu[0] > 0.0 && mu[0] < 1.0 && routePoint.lengthSquared() < BRANCH_SNAP_DISTANCE) { + currentPosition.set(branchPoint); + + updateCurrentPoint(); + + setInfoText("Make branch (l) :" + currentPosition + " " + Math.max(0.0, Math.min(mu[0], 1.0)) + " " + routePoint.lengthSquared()); + return PositionType.SPLIT; + } + return null; + } + + private boolean endingLockToNozzle(INode nozzleNode) { + Nozzle nozzle = (Nozzle)nozzleNode; + Vector3d dir = new Vector3d(currentPosition); + Point3d prev = new Point3d(previousPosition); + dir.sub(prev); + Vector3d nozzleLoc = nozzle.getWorldPosition(); + double u[] = new double[1]; + Vector3d closest = MathTools.closestPointOnStraight(new Point3d(nozzleLoc), new Point3d(prev), new Vector3d(dir), u); + double dist = MathTools.distanceSquared(nozzleLoc,closest); + if (dist < BRANCH_SNAP_DISTANCE) { + // FIXME : directions should be checked (insert an elbow) + currentPosition.set(nozzleLoc); + updateCurrentPoint(); + setInfoText("Connect to nozzle (l) :" + currentPosition); + return true; + } + //System.out.println(u[0]); + return false; + } + + private PipeControlPoint endingLockToComponent(INode componentNode) { + // we'll must scan all free pcp's and their direction to accept the connection. + return null; + } + + private void addPoint() throws Exception { + InlineComponent previous = (InlineComponent)getLast(); + PipeControlPoint previousCP = previous.getControlPoint(); + TurnComponent turn = ComponentUtils.createTurn(root); + InlineComponent straight = ComponentUtils.createStraight(root); + PipeControlPoint turnCP = turn.getControlPoint(); + PipeControlPoint straightCP = straight.getControlPoint(); + straight.setName(pipeRun.getUniqueName("Pipe")); + turn.setName(pipeRun.getUniqueName("Elbow")); + pipeRun.addChild(turn); + pipeRun.addChild(straight); + added.add(turn); + added.add(straight); + + turnCP.setDeletable(false); // mark turnCP nonDeletable so that PipingRules won't delete it immediately. + + if (!reversed) { + previousCP.setNext(turnCP); + turnCP.setPrevious(previousCP); + turnCP.setNext(straightCP); + straightCP.setPrevious(turnCP); + } else { + previousCP.setPrevious(turnCP); + turnCP.setNext(previousCP); + turnCP.setPrevious(straightCP); + straightCP.setNext(turnCP); + } + + turnCP.setWorldPosition(currentPosition); + turnCP.setTurnAngle(0.0); + turnCP.setLength(0.0); + straightCP.setWorldPosition(currentPosition); + straightCP.setLength(0.0); + + setPreviousPosition(currentPosition); + updateCurrentPoint(); + + + + } + + /** + * Updates tool graphics for current point + */ + private void updateCurrentPoint() { +// PipeComponentProvider.createStraightEdges(pipeShapes.get(pipeShapes.size() - 1), controlPoints.get(controlPoints.size() - 1), currentPoint, pipeDiameter*0.5); + InlineComponent straight = (InlineComponent)added.get(added.size()-1); + // FIXME : does not take account space the the previous elbow reserves. + Vector3d v = new Vector3d(); + v.sub(currentPosition, previousPosition); + double length = v.length(); + v.scale(0.5); + v.add(previousPosition); + straight.getControlPoint().setWorldPosition(v); + straight.getControlPoint().setLength(length); + try { + PipingRules.positionUpdate(straight.getControlPoint(),false); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + private PipelineComponent getLast() { + if (added.size() == 0) + return startComponent; + return added.get(added.size()-1); + } + + + /** + * Removes last point from pipeline + */ + public void removePoint() { + if (added.size() < 3) + return; + InlineComponent straight = (InlineComponent)added.remove(added.size()-1); + TurnComponent turn = (TurnComponent)added.remove(added.size()-1); + straight.getControlPoint().remove(); + turn.getControlPoint().remove(); + if (added.size() > 1) { + setPreviousPosition(added.get(added.size()-2).getWorldPosition()); + } else { + setPreviousPosition(startComponent.getWorldPosition()); + if (direction != null) + setLockType(LockType.CUSTOM, true); + } + + } + + private void endPiping() throws Exception { + state = ToolState.NOT_ACTIVE; + + if (endTo != null) { + PipeControlPoint endCP = endTo.getControlPoint(); + if (endType == null || endType == PositionType.NEXT || endType == PositionType.PREVIOUS) { + + PipelineComponent current = getLast(); + PipeControlPoint currentCP = current.getControlPoint(); + + boolean requiresReverse = false; + if (!reversed && endCP.getPrevious() != null) { + requiresReverse = true; + } else if (reversed && endCP.getNext() != null) { + requiresReverse = true; + } + PipeRun other = endCP.getPipeRun(); + boolean mergeRuns = pipeRun.equalSpecs(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 (pipeRun != other) // FIXME: temporary workaround. + PipingRules.merge(pipeRun, other); + 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(); + PipeControlPoint ocp = pcp.getSubPoint().get(0); + + 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(); + } + + } else if (endType == PositionType.SPLIT) { + InlineComponent branchSplit = createBranchSplit((InlineComponent)endTo, currentPosition); + 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()); + + PipelineComponent current = getLast(); + PipeControlPoint currentCP = current.getControlPoint(); + + + if(!reversed) { + pcp.setPrevious(currentCP); + currentCP.setNext(pcp); + } else { + pcp.setNext(currentCP); + currentCP.setPrevious(pcp); + } + + } + PipingRules.positionUpdate(endCP); + } + panel.useDefaultAction(); + } +} diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/browser/P3DBrowser.java b/org.simantics.plant3d/src/org/simantics/plant3d/browser/P3DBrowser.java new file mode 100644 index 00000000..176fbaaa --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/browser/P3DBrowser.java @@ -0,0 +1,15 @@ +package org.simantics.plant3d.browser; + +import java.util.Set; + +import org.simantics.structural.ui.modelBrowser.ModelBrowser2; + +public class P3DBrowser extends ModelBrowser2 { + + + @Override + protected Set getBrowseContexts() { + return browseContexts; + } + +} diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/dialog/ComponentContentProvider.java b/org.simantics.plant3d/src/org/simantics/plant3d/dialog/ComponentContentProvider.java new file mode 100644 index 00000000..fe55fdfa --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/dialog/ComponentContentProvider.java @@ -0,0 +1,26 @@ +package org.simantics.plant3d.dialog; + +import java.util.List; + +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.Viewer; +import org.simantics.plant3d.utils.Item; + +public class ComponentContentProvider implements IStructuredContentProvider { + + @Override + public Object[] getElements(Object inputElement) { + List list = (List)inputElement; + return list.toArray(); + } + + @Override + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + + } + @Override + public void dispose() { + + } + +} diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/dialog/ComponentLabelProvider.java b/org.simantics.plant3d/src/org/simantics/plant3d/dialog/ComponentLabelProvider.java new file mode 100644 index 00000000..ab32c894 --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/dialog/ComponentLabelProvider.java @@ -0,0 +1,16 @@ +package org.simantics.plant3d.dialog; + +import org.eclipse.jface.viewers.LabelProvider; +import org.simantics.plant3d.utils.Item; + +public class ComponentLabelProvider extends LabelProvider{ + + @Override + public String getText(Object element) { + Item item = (Item)element; + return item.getName(); + } + + + +} diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/dialog/ComponentSelectionDialog.java b/org.simantics.plant3d/src/org/simantics/plant3d/dialog/ComponentSelectionDialog.java new file mode 100644 index 00000000..33d5882c --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/dialog/ComponentSelectionDialog.java @@ -0,0 +1,332 @@ +package org.simantics.plant3d.dialog; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.ListViewer; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.KeyAdapter; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.ExpandBar; +import org.eclipse.swt.widgets.ExpandItem; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; +import org.simantics.db.exception.DatabaseException; +import org.simantics.plant3d.scenegraph.controlpoint.PipeControlPoint.PositionType; +import org.simantics.plant3d.utils.Item; +import org.simantics.plant3d.utils.Item.Type; +import org.simantics.plant3d.utils.P3DUtil; +import org.simantics.utils.ui.ExceptionUtils; + +public class ComponentSelectionDialog extends Dialog implements ISelectionChangedListener{ + + private Item selected; + private Set allowed; + private Set filterAllowed; + private Double angle; + private Double length; + + private Text lengthText; + private Text angleText; + + private Double diameter; + private Double turnRadius; + + private Text diameterText; + private Text turnRadiusText; + + private boolean inlineSplit = false; + + + public ComponentSelectionDialog(Shell parentShell, Set allowed) { + super(parentShell); + this.allowed = allowed; + filterAllowed = new HashSet(); + } + + @Override + protected Control createDialogArea(Composite parent) { + Composite composite = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(2,false); + layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN); + layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN); + layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING); + layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING); + composite.setLayout(layout); + composite.setLayoutData(new GridData(GridData.FILL_BOTH)); + applyDialogFont(composite); + + // TODO : we need better classification than inline,turn, and end: + // * fixed length inlines + // * fixed angle turns + // * size changes (requires input for pipe run specs) + // * variable length inlines (input for length) + // * variable angle turns (input for angle) + // * ends + + List ends = null; + List turns = null; + List inlines = null; + try { + ends = P3DUtil.getEnds(); + turns= P3DUtil.getTurns(); + inlines = P3DUtil.getInlines(); + } catch (DatabaseException e) { + Label label = new Label(composite, SWT.NONE); + label.setText("Cannot load pipeline components: " + e.getMessage()); + ExceptionUtils.logError(e); + return composite; + } + + ExpandBar expandBar = new ExpandBar(composite, SWT.NONE); + + + ExpandItem inlineItem = new ExpandItem(expandBar, SWT.NONE); + inlineItem.setText("Inline"); + ListViewer inlineViewer = new ListViewer(expandBar); + inlineViewer.setLabelProvider(new ComponentLabelProvider()); + inlineViewer.setContentProvider(new ComponentContentProvider()); + + ExpandItem turnItem = new ExpandItem(expandBar, SWT.NONE); + turnItem.setText("Turn"); + ListViewer turnViewer = new ListViewer(expandBar); + turnViewer.setLabelProvider(new ComponentLabelProvider()); + turnViewer.setContentProvider(new ComponentContentProvider()); + + ExpandItem endItem = new ExpandItem(expandBar, SWT.NONE); + endItem.setText("End"); + ListViewer endViewer = new ListViewer(expandBar); + endViewer.setLabelProvider(new ComponentLabelProvider()); + endViewer.setContentProvider(new ComponentContentProvider()); + + + inlineItem.setControl(inlineViewer.getList()); + turnItem.setControl(turnViewer.getList()); + endItem.setControl(endViewer.getList()); + + inlineViewer.setInput(inlines); + turnViewer.setInput(turns); + endViewer.setInput(ends); + + inlineItem.setHeight(inlineViewer.getList().computeSize(SWT.DEFAULT, SWT.DEFAULT).y); + turnItem.setHeight(turnViewer.getList().computeSize(SWT.DEFAULT, SWT.DEFAULT).y); + endItem.setHeight(endViewer.getList().computeSize(SWT.DEFAULT, SWT.DEFAULT).y); + + inlineViewer.addSelectionChangedListener(this); + turnViewer.addSelectionChangedListener(this); + endViewer.addSelectionChangedListener(this); + + GridDataFactory.fillDefaults().grab(true, true).align(SWT.FILL, SWT.FILL).span(2, 1).applyTo(expandBar); + GridDataFactory.fillDefaults().minSize(500, 500).hint(500, 500).applyTo(composite); + + + Label label = new Label(composite, SWT.NONE); + label.setText("Length"); + lengthText = new Text(composite, SWT.SINGLE|SWT.BORDER); + label = new Label(composite, SWT.NONE); + label.setText("Angle"); + angleText = new Text(composite, SWT.SINGLE|SWT.BORDER); + + label = new Label(composite, SWT.NONE); + label.setText("Diameter"); + diameterText = new Text(composite, SWT.SINGLE|SWT.BORDER); + label = new Label(composite, SWT.NONE); + label.setText("Turn Radius"); + turnRadiusText = new Text(composite, SWT.SINGLE|SWT.BORDER); + + lengthText.setEnabled(false); + angleText.setEnabled(false); + turnRadiusText.setEnabled(false); + diameterText.setEnabled(false); + + lengthText.addKeyListener(new KeyAdapter() { + @Override + public void keyReleased(KeyEvent e) { + try { + length = Double.parseDouble(lengthText.getText()); + } catch (NumberFormatException err) { + length = null; + } + validate(); + } + }); + + angleText.addKeyListener(new KeyAdapter() { + @Override + public void keyReleased(KeyEvent e) { + try { + angle = Double.parseDouble(angleText.getText()); + } catch (NumberFormatException err) { + angle = null; + } + validate(); + } + }); + + diameterText.addKeyListener(new KeyAdapter() { + @Override + public void keyReleased(KeyEvent e) { + try { + diameter = Double.parseDouble(diameterText.getText()); + } catch (NumberFormatException err) { + diameter = null; + } + validate(); + } + }); + + turnRadiusText.addKeyListener(new KeyAdapter() { + @Override + public void keyReleased(KeyEvent e) { + try { + turnRadius = Double.parseDouble(turnRadiusText.getText()); + } catch (NumberFormatException err) { + turnRadius = null; + } + validate(); + } + }); + + GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.TOP).applyTo(lengthText); + GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.TOP).applyTo(angleText); + GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.TOP).applyTo(diameterText); + GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.TOP).applyTo(turnRadiusText); + + if (!allowed.contains(PositionType.NEXT) && !allowed.contains(PositionType.PREVIOUS)) { + turnViewer.getList().setEnabled(false); + endViewer.getList().setEnabled(false); + inlineSplit = true; + } + + return composite; + } + + + @Override + public void selectionChanged(SelectionChangedEvent event) { + IStructuredSelection sel = (IStructuredSelection)event.getSelection(); + selected = (Item)sel.getFirstElement(); + validate(); + } + + private void validate() { + filterAllowed.clear(); + Set filterAllowed = new HashSet(); + boolean ok = true; + if (selected.isCode())// TODO : instead of disabling the button, we should filter the content. + ok = false; + + if (selected.isVariable()) { + if (selected.getType() == Type.INLINE) { + filterAllowed.add(PositionType.NEXT); + filterAllowed.add(PositionType.PREVIOUS); + if (inlineSplit) { + lengthText.setEnabled(false); + angleText.setEnabled(false); + ok = false; + + } else { + lengthText.setEnabled(true); + angleText.setEnabled(false); + if (length == null) + ok = false; + } + } else if (selected.getType() == Type.TURN) { + filterAllowed.add(PositionType.NEXT); + filterAllowed.add(PositionType.PREVIOUS); + lengthText.setEnabled(false); + angleText.setEnabled(true); + if (angle == null) + ok = false; + } else { + // this should not happen + lengthText.setEnabled(false); + angleText.setEnabled(false); + } + } else { + lengthText.setEnabled(false); + angleText.setEnabled(false); + } + if (selected.isSizeChange()) { + filterAllowed.add(PositionType.NEXT); + filterAllowed.add(PositionType.PREVIOUS); + if (inlineSplit) { + turnRadiusText.setEnabled(false); + diameterText.setEnabled(false); + ok = false; + } else { + turnRadiusText.setEnabled(true); + diameterText.setEnabled(true); + if (diameter == null || turnRadius == null) + ok = false; + } + + } else { + turnRadiusText.setEnabled(false); + diameterText.setEnabled(false); + } + if (!selected.isSizeChange() && !selected.isVariable()) { + switch (selected.getType()) { + case END: + filterAllowed.add(PositionType.NEXT); + filterAllowed.add(PositionType.PREVIOUS); + break; + case NOZZLE: + case EQUIPMENT: + break; + case INLINE: + filterAllowed.add(PositionType.NEXT); + filterAllowed.add(PositionType.PREVIOUS); + filterAllowed.add(PositionType.SPLIT); + case TURN: + filterAllowed.add(PositionType.NEXT); + filterAllowed.add(PositionType.PREVIOUS); + } + } + + for (PositionType t : filterAllowed) { + if (allowed.contains(t)) + this.filterAllowed.add(t); + } + + getButton(OK).setEnabled(ok); + } + + public Item getSelected() { + return selected; + } + + public Double getAngle() { + return angle; + } + + public Double getLength() { + return length; + } + + public Double getDiameter() { + return diameter; + } + + public Double getTurnRadius() { + return turnRadius; + } + + public Set filterAllowed() { + return filterAllowed; + } + + +} diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/editor/P3DContentOutlinePage.java b/org.simantics.plant3d/src/org/simantics/plant3d/editor/P3DContentOutlinePage.java new file mode 100644 index 00000000..c675b111 --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/editor/P3DContentOutlinePage.java @@ -0,0 +1,151 @@ +package org.simantics.plant3d.editor; + +import org.eclipse.jface.action.IMenuListener; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.jface.resource.LocalResourceManager; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.swt.events.MenuDetectEvent; +import org.eclipse.swt.events.MenuDetectListener; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.Menu; +import org.simantics.db.Resource; +import org.simantics.g3d.scenegraph.base.INode; +import org.simantics.g3d.scenegraph.base.ParentNode; +import org.simantics.g3d.vtk.common.NodeSelectionProvider2; +import org.simantics.g3d.vtk.common.VTKContentOutlinePage; +import org.simantics.plant3d.Activator; +import org.simantics.plant3d.scenegraph.EndComponent; +import org.simantics.plant3d.scenegraph.Equipment; +import org.simantics.plant3d.scenegraph.InlineComponent; +import org.simantics.plant3d.scenegraph.Nozzle; +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; + +public class P3DContentOutlinePage extends VTKContentOutlinePage{ + + private static final boolean DEBUG = false; + protected Menu contextMenu; + + private LocalResourceManager manager = new LocalResourceManager(JFaceResources.getResources()); + + private Image nozzleImage; + private Image pipeImage; + private Image tankImage; + private Image elbowImage; + private Image componentImage; + + public P3DContentOutlinePage(ParentNode rootNode, NodeSelectionProvider2 provider) { + super(rootNode,provider); + + nozzleImage = manager.createImage(Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/Nozzle.png")); + pipeImage = manager.createImage(Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/Straight.png")); + tankImage = manager.createImage(Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/tank.png")); + elbowImage = manager.createImage(Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/Elbow.png")); + componentImage = manager.createImage(Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/Component.png")); + } + + @Override + protected void createProviders(TreeViewer viewer) { + viewer.setContentProvider(new ScenegraphContentProvider() { + @Override + public Object[] getChildren(Object parentElement) { + if (parentElement instanceof P3DRootNode) { + return ((P3DRootNode)parentElement).getChild().toArray(); + } + if (!DEBUG) { + if (parentElement instanceof PipeRun) { + return ((PipeRun)parentElement).getSortedChild().toArray(); + } + } else { + if (parentElement instanceof PipelineComponent) { + return new Object[]{((PipelineComponent) parentElement).getControlPoint()}; + } else if (parentElement instanceof PipeControlPoint) { + return new Object[]{((PipeControlPoint) parentElement).getPipelineComponent()}; + } + } + return super.getChildren(parentElement); + } + + @Override + public boolean hasChildren(Object element) { + if (element instanceof P3DRootNode) { + return ((P3DRootNode)element).getChild().size() > 0; + } + if (!DEBUG) { + if (element instanceof PipeRun) { + return ((PipeRun)element).getChild().size() > 0; + } + } else { + if (element instanceof PipelineComponent) { + return ((PipelineComponent) element).getControlPoint() != null; + } else if (element instanceof PipeControlPoint) { + return ((PipeControlPoint) element).getPipelineComponent() != null; + } + } + return super.hasChildren(element); + } + }); + viewer.setLabelProvider(new P3DLabelProvider()); + + hookContextMenu(viewer); + viewer.getTree().addMenuDetectListener(new MenuDetectListener() { + + @Override + public void menuDetected(MenuDetectEvent e) { + contextMenu.setLocation(e.x, e.y); + contextMenu.setVisible(true); + } + }); + + } + + @Override + public void dispose() { + manager.dispose(); + super.dispose(); + } + + protected void hookContextMenu(TreeViewer viewer) { + MenuManager menuMgr = new MenuManager("#PopupMenu"); + menuMgr.setRemoveAllWhenShown(true); + menuMgr.addMenuListener(new IMenuListener() { + public void menuAboutToShow(IMenuManager manager) { + createContextMenu(manager); + } + }); + contextMenu = menuMgr.createContextMenu(viewer.getTree()); + } + + protected void createContextMenu(IMenuManager manager) { + + } + + private class P3DLabelProvider extends ScenegraphLabelProvider { + @Override + public Image getImage(Object element) { + if (element instanceof PipelineComponent) { + PipelineComponent comp = (PipelineComponent)element; + if (comp instanceof TurnComponent) { + return elbowImage; + } else if (comp instanceof EndComponent) { + return componentImage; + } else if (comp instanceof Nozzle) { + return nozzleImage; + } else if (comp.getControlPoint().isFixed()) { + return componentImage; + } + return pipeImage; + } else if (element instanceof Equipment) { + return tankImage; + } else if (element instanceof PipeRun) { + return pipeImage; + } + return null; + } + } +} diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/editor/P3DNodeMap.java b/org.simantics.plant3d/src/org/simantics/plant3d/editor/P3DNodeMap.java new file mode 100644 index 00000000..b0989513 --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/editor/P3DNodeMap.java @@ -0,0 +1,246 @@ +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.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.InteractiveVtkPanel; +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 org.simantics.utils.threads.AWTThread; + +import vtk.vtkProp; +import vtk.vtkProp3D; + +public class P3DNodeMap extends AbstractVTKNodeMap { + + private static final boolean DEBUG = false; + + public P3DNodeMap(Session session, IMapping mapping, InteractiveVtkPanel 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 " + 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 " + node); + for (String s : ids) + System.out.print(" " + s); + System.out.println(); + } + + if (ids.contains(Plant3D.URIs.hasGeometry)) { + node.visualize(panel); + updateRenderObjectsFor(node); + updateTransform(node); + } + if (n instanceof ParameterizedNode) { + ParameterizedNode geom = (ParameterizedNode)n; + for (String id : geom.getParameterMap().keySet()) { + if (ids.contains(id)) { + node.visualize(panel); + 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 " + node); + + node.update(panel.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 " + 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 " + n); + if (!(n instanceof IP3DVisualNode)) + return; + IP3DVisualNode node = (IP3DVisualNode)n; + + if (hasActor(node)) + return; + if (Thread.currentThread() != AWTThread.getThreadAccess().getThread()) + throw new RuntimeException("Illegal thread."); + + panel.lock(); + + node.visualize(panel); + + for (vtkProp3D act : node.getActors()) { + nodeToActor.add(node, act); + actorToNode.put(act, node); + } + + if (node instanceof P3DParentNode) { + for (IP3DNode n2 : ((P3DParentNode)node).getNodes()) + if (n2 instanceof IP3DVisualNode) + addActor((IP3DVisualNode)n2); + } + + updateTransform(node); + + panel.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() != AWTThread.getThreadAccess().getThread()) + throw new RuntimeException("Illegal thread."); + + List list = nodeToActor.getValues(node); + if (list != null) { + for (vtkProp obj : list) { + actorToNode.remove(obj); + } + nodeToActor.remove(node); + panel.lock(); + + node.stopVisualize(); + + panel.unlock(); + } + } + + @Override + protected void update(ReadGraph graph) throws DatabaseException { + validate(); +// System.out.println("Graph updates"); + super.update(graph); + validate(); + } + + @Override + public void commit() { + validate(); +// System.out.println("Graph commit"); + super.commit(); + + } + @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(); + } + + } + +} diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/editor/Plant3DEditor.java b/org.simantics.plant3d/src/org/simantics/plant3d/editor/Plant3DEditor.java new file mode 100644 index 00000000..9d0c3b82 --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/editor/Plant3DEditor.java @@ -0,0 +1,498 @@ +package org.simantics.plant3d.editor; + +import java.awt.Component; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.eclipse.jface.action.IMenuListener; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.ISelectionProvider; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.ui.views.contentoutline.IContentOutlinePage; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.Session; +import org.simantics.db.common.request.ReadRequest; +import org.simantics.db.exception.DatabaseException; +import org.simantics.g3d.scenegraph.IG3DNode; +import org.simantics.g3d.scenegraph.NodeMap; +import org.simantics.g3d.scenegraph.base.INode; +import org.simantics.g3d.vtk.action.RemoveAction; +import org.simantics.g3d.vtk.action.RotateAction; +import org.simantics.g3d.vtk.action.TranslateAction; +import org.simantics.g3d.vtk.action.vtkCameraAndSelectorAction; +import org.simantics.g3d.vtk.common.HoverHighlighter; +import org.simantics.g3d.vtk.common.InteractiveVtkPanel; +import org.simantics.g3d.vtk.common.NodeSelectionProvider2; +import org.simantics.g3d.vtk.common.SelectionHighlighter; +import org.simantics.g3d.vtk.shape.vtkShape; +import org.simantics.g3d.vtk.utils.vtkPanelUtil; +import org.simantics.objmap.graph.IMapping; +import org.simantics.objmap.graph.Mappings; +import org.simantics.objmap.graph.schema.IMappingSchema; +import org.simantics.plant3d.actions.AddComponentAction; +import org.simantics.plant3d.actions.AddEquipmentAction; +import org.simantics.plant3d.actions.AddNozzleAction; +import org.simantics.plant3d.actions.RoutePipeAction; +import org.simantics.plant3d.scenegraph.EndComponent; +import org.simantics.plant3d.scenegraph.Equipment; +import org.simantics.plant3d.scenegraph.IP3DNode; +import org.simantics.plant3d.scenegraph.InlineComponent; +import org.simantics.plant3d.scenegraph.Nozzle; +import org.simantics.plant3d.scenegraph.P3DRootNode; +import org.simantics.plant3d.scenegraph.PipeRun; +import org.simantics.plant3d.scenegraph.PipelineComponent; +import org.simantics.plant3d.scenegraph.SchemaBuilder; +import org.simantics.plant3d.scenegraph.TurnComponent; +import org.simantics.plant3d.scenegraph.controlpoint.ControlPointFactory; +import org.simantics.plant3d.scenegraph.controlpoint.PipeControlPoint; +import org.simantics.plant3d.scenegraph.controlpoint.PipingRules; +import org.simantics.plant3d.utils.ComponentUtils; +import org.simantics.plant3d.utils.Item; +import org.simantics.plant3d.utils.P3DUtil; +import org.simantics.selectionview.StandardPropertyPage; +import org.simantics.ui.workbench.IPropertyPage; +import org.simantics.ui.workbench.IResourceEditorInput; +import org.simantics.ui.workbench.ResourceEditorPart; +import org.simantics.utils.threads.AWTThread; +import org.simantics.utils.threads.ThreadUtils; +import org.simantics.utils.ui.ExceptionUtils; +import org.simantics.utils.ui.SWTAWTComponent; + +import vtk.vtkActor; +import vtk.vtkAxesActor; +import vtk.vtkCameraPass; +import vtk.vtkDefaultPass; +import vtk.vtkLightsPass; +import vtk.vtkOrientationMarkerWidget; +import vtk.vtkRenderPassCollection; +import vtk.vtkRenderer; +import vtk.vtkSequencePass; + + +public class Plant3DEditor extends ResourceEditorPart { + + private Composite parent; + private Resource input; + private InteractiveVtkPanel panel; + private SWTAWTComponent component; + + private P3DRootNode rootNode; + private IMapping mapping; + + private NodeSelectionProvider2 selectionProvider; + + private vtkCameraAndSelectorAction cameraAction; + private TranslateAction translateAction; + private RotateAction rotateAction; + private RemoveAction removeAction; + private RoutePipeAction routePipeAction; + private AddComponentAction addComponentAction; + + private P3DNodeMap nodeMap; + + @Override + public void createPartControl(Composite parent) { + this.parent = parent; + parent.setLayout (new FillLayout ()); + component = new SWTAWTComponent(parent,SWT.NONE) { + + @Override + protected Component createSwingComponent() { + if (panel == null) { + panel = new InteractiveVtkPanel(); + vtkPanelUtil.registerPanel(panel); + createScene(); + } + return panel; + } + }; + + IResourceEditorInput rei = (IResourceEditorInput)getEditorInput(); + input = rei.getResource(); + + + //IActionBars actionBars = getEditorSite().getActionBars(); + + hookContextMenu(); + + component.syncPopulate(); + + panel.addMouseListener(new java.awt.event.MouseAdapter() { + @Override + public void mouseClicked(final java.awt.event.MouseEvent e) { + if (e.getButton() == java.awt.event.MouseEvent.BUTTON3) { + Display.getDefault().asyncExec(new Runnable() { + public void run() { + contextMenu.setLocation(e.getXOnScreen(), e.getYOnScreen()); + contextMenu.setVisible(true); + } + }); + } + } + }); + + + cameraAction = new vtkCameraAndSelectorAction(panel); + panel.setDefaultAction(cameraAction); + panel.useDefaultAction(); + panel.setPickType(4); + + try { + ControlPointFactory.preloadCache(); + ComponentUtils.preloadCache(); + } catch (Exception e) { + ExceptionUtils.logAndShowError("Cannot open Plant3D editor",e); + return; + } + + try { + getSession().syncRequest(new ReadRequest() { + + @SuppressWarnings({ "rawtypes", "unchecked" }) + @Override + public void run(ReadGraph graph) throws DatabaseException { + PipingRules.setEnabled(false); + IMappingSchema schema = getSchema(graph); + mapping = Mappings.createWithListening(schema); + rootNode = (P3DRootNode)mapping.map(graph, input); + // update control points. + // TODO : this should be optimized. + try { + for (INode node : rootNode.getChild()) { + if (node instanceof PipeRun) { + for (PipelineComponent pc : ((PipeRun) node).getChild()) + pc.sync(); + } else if (node instanceof Equipment) { + for (PipelineComponent pc : ((Equipment) node).getChild()) + pc.sync(); + } + } + + for (INode node : rootNode.getChild()) { + if (node instanceof PipeRun) { + for (PipelineComponent pc : ((PipeRun) node).getChild()) + pc.sync2(); + } else if (node instanceof Equipment) { + for (PipelineComponent pc : ((Equipment) node).getChild()) + pc.sync2(); + } + } + for (INode node : rootNode.getChild()) { + if (node instanceof PipeRun) { + PipingRules.validate((PipeRun)node); + } + } + PipingRules.setEnabled(true); + for (INode node : rootNode.getChild()) { + if (node instanceof PipeRun) { + PipeRun run = (PipeRun)node; + for (PipeControlPoint pcp : run.getControlPoints()) + PipingRules.positionUpdate(pcp); + + } + } + } catch (Exception e) { + throw new DatabaseException(e); + } + nodeMap = createNodeMap(getSession(), mapping, panel,rootNode); + } + }); + + if (rootNode == null) + throw new RuntimeException("Scenegraph loading failed."); + populate(); + + selectionProvider = new NodeSelectionProvider2(this,mapping,nodeMap); + + cameraAction.addSelectionChangedListener(selectionProvider); + + cameraAction.addHoverChangedListener(new HoverHighlighter(panel,nodeMap)); + selectionProvider.addSelectionChangedListener(new SelectionHighlighter(panel,nodeMap)); + + getSite().setSelectionProvider(selectionProvider); + getSite().getPage().addPostSelectionListener(selectionProvider); + + //outlinePage = new ScenegraphOutlinePage(rootNode); + + + parent.addDisposeListener(new DisposeListener() { + + @Override + public void widgetDisposed(DisposeEvent e) { + getSite().getPage().removePostSelectionListener(selectionProvider); + + ThreadUtils.asyncExec(AWTThread.getThreadAccess(), new Runnable() { + + @Override + public void run() { + PipingRules.setEnabled(false); + nodeMap.delete(); + PipingRules.setEnabled(true); + vtkPanelUtil.unregisterPanel(panel); + + } + }); + mapping.dispose(); + component.dispose(); + + + } + }); + } catch (DatabaseException e1) { + ExceptionUtils.logAndShowError("Cannot open Plant3D editor",e1); + return; + } + + translateAction = new TranslateAction(panel,nodeMap); + rotateAction = new RotateAction(panel,nodeMap); + removeAction = new RemoveAction(nodeMap) { + public void setNode(IG3DNode node) { + super.setNode(node); + + + } + }; + routePipeAction = new RoutePipeAction(panel,rootNode); + addComponentAction = new AddComponentAction(panel, rootNode); + + } + + public void populate() { + ThreadUtils.asyncExec(AWTThread.getThreadAccess(), new Runnable() { + + @Override + public void run() { + nodeMap.populate(); + } + }); + + } + + protected IMappingSchema getSchema(ReadGraph graph) throws DatabaseException { + IMappingSchema schema = SchemaBuilder.getSchema(graph); + return schema; + } + + protected P3DNodeMap createNodeMap(Session session, IMapping mapping, InteractiveVtkPanel panel, P3DRootNode rootNode) { + return new P3DNodeMap(session, mapping, panel,rootNode); + } + + @Override + public void setFocus() { + component.setFocus(); + } + + private void createScene() { + vtkRenderer ren1 = panel.GetRenderer(); + + boolean multiPass = false; + if (multiPass) { + + vtkLightsPass lightsPass = new vtkLightsPass(); + vtkDefaultPass defaultPass = new vtkDefaultPass(); + + + vtkRenderPassCollection passes = new vtkRenderPassCollection(); + passes.AddItem(lightsPass); + passes.AddItem(defaultPass); + + vtkSequencePass seq = new vtkSequencePass(); + seq.SetPasses(passes); + + + + vtkCameraPass cameraPass = new vtkCameraPass(); + cameraPass.SetDelegatePass(seq); + + ren1.SetPass(cameraPass); + + } +// ren1.GetRenderWindow().LineSmoothingOn(); +// ren1.GetRenderWindow().PointSmoothingOn(); +// ren1.GetRenderWindow().PolygonSmoothingOn(); +// ren1.GetRenderWindow().SetMultiSamples(2); + + + + ren1.SetBackground2(1,1,1); // background color white + ren1.SetBackground(0.9,0.9,0.9); + ren1.SetGradientBackground(true); + + // vtkActor grid = vtkShape.createGridActor(8,1.0,1|2|4); + vtkActor grid = vtkShape.createGridActor(8,1.0, 2 ); + grid.SetPickable(0); + ren1.AddActor(grid); + panel.addDeletable(grid); + + { + vtkAxesActor axes = new vtkAxesActor(); + axes.GetXAxisCaptionActor2D().GetCaptionTextProperty().SetColor(0,0,0); + axes.GetYAxisCaptionActor2D().GetCaptionTextProperty().SetColor(0,0,0); + axes.GetZAxisCaptionActor2D().GetCaptionTextProperty().SetColor(0,0,0); + axes.GetXAxisCaptionActor2D().GetCaptionTextProperty().SetShadow(0); + axes.GetYAxisCaptionActor2D().GetCaptionTextProperty().SetShadow(0); + axes.GetZAxisCaptionActor2D().GetCaptionTextProperty().SetShadow(0); + axes.GetXAxisCaptionActor2D().GetCaptionTextProperty().ItalicOff(); + axes.GetYAxisCaptionActor2D().GetCaptionTextProperty().ItalicOff(); + axes.GetZAxisCaptionActor2D().GetCaptionTextProperty().ItalicOff(); + axes.GetXAxisCaptionActor2D().GetCaptionTextProperty().Delete(); + axes.GetYAxisCaptionActor2D().GetCaptionTextProperty().Delete(); + axes.GetZAxisCaptionActor2D().GetCaptionTextProperty().Delete(); + axes.GetXAxisCaptionActor2D().Delete(); + axes.GetYAxisCaptionActor2D().Delete(); + axes.GetZAxisCaptionActor2D().Delete(); + vtkOrientationMarkerWidget widget = new vtkOrientationMarkerWidget(); + widget.SetOutlineColor(0.9300, 0.5700, 0.1300 ); + widget.SetOrientationMarker(axes); + widget.SetInteractor(panel.getRenderWindowInteractor()); + //widget.SetViewport(0.8, 0.0, 1.0, 0.2); // bottom right + //widget.SetViewport(0.0, 0.0, 0.4, 0.4); + widget.SetViewport(0.0, 0.0, 0.2, 0.2); // bottom left + widget.SetEnabled(1); + widget.InteractiveOff(); + } + + + } + + protected Menu contextMenu; + + protected void hookContextMenu() { + MenuManager menuMgr = new MenuManager("#PopupMenu"); + menuMgr.setRemoveAllWhenShown(true); + menuMgr.addMenuListener(new IMenuListener() { + public void menuAboutToShow(IMenuManager manager) { + createContextMenu(manager); + } + }); + + contextMenu = menuMgr.createContextMenu(parent); + } + + protected void createContextMenu(IMenuManager m) { + List selected = selectionProvider.getSelectedNodes(); + try { + if (selected.size() == 0) { + for (Item eq : P3DUtil.getEquipments()) { + m.add(new AddEquipmentAction(rootNode, eq)); + } + } else if (selected.size() == 1) { + IP3DNode node = (IP3DNode)selected.get(0); + if (node instanceof Equipment) { + m.add(translateAction); + m.add(rotateAction); + for (Item eq : P3DUtil.getNozzles()) { + AddNozzleAction add = new AddNozzleAction(rootNode, eq); + add.setEquipment((Equipment)node); + m.add(add); + } + } else if (node instanceof Nozzle) { + m.add(translateAction); + m.add(rotateAction); + Nozzle nozzle = (Nozzle)node; + m.add(routePipeAction); + routePipeAction.setComponent(nozzle); + routePipeAction.setEnabled(nozzle.getNext() == null && nozzle.getPrevious() == null); + m.add(addComponentAction); + addComponentAction.setComponent(nozzle); + } else if (node instanceof TurnComponent) { + m.add(translateAction); + TurnComponent component = (TurnComponent)node; + m.add(routePipeAction); + routePipeAction.setComponent(component); + routePipeAction.setEnabled(component.getNext() == null || component.getPrevious() == null); + m.add(addComponentAction); + addComponentAction.setComponent(component); + } else if (node instanceof EndComponent) { + m.add(translateAction); + m.add(addComponentAction); + addComponentAction.setComponent((PipelineComponent)node); + } else if (node instanceof InlineComponent) { + //m.add(translateInlineAction); + InlineComponent component = (InlineComponent)node; + m.add(routePipeAction); + routePipeAction.setComponent(component); + m.add(addComponentAction); + addComponentAction.setComponent(component); + } + + m.add(removeAction); + translateAction.setNode(node); + rotateAction.setNode(node); + removeAction.setNode(node); + + } + } catch (DatabaseException e) { + ExceptionUtils.logAndShowError(e); + } + } + + private IContentOutlinePage createOutline() { + if (rootNode == null || selectionProvider == null) + return null; + //IContentOutlinePage outlinePage = new VTKContentOutlinePage(rootNode, selectionProvider); + IContentOutlinePage outlinePage = new P3DContentOutlinePage(rootNode, selectionProvider) { + protected void createContextMenu(IMenuManager manager) { + Plant3DEditor.this.createContextMenu(manager); + }; + }; + outlinePage.addSelectionChangedListener(new ISelectionChangedListener() { + + @Override + public void selectionChanged(SelectionChangedEvent event) { + selectionProvider.selectionChanged(event); + } + }); + return outlinePage; + } + + @SuppressWarnings("rawtypes") + @Override + public Object getAdapter(Class adapter) { + if (IPropertyPage.class.equals(adapter)) + return new StandardPropertyPage(getSite(),getPropertyContexts()); + if (IContentOutlinePage.class.equals(adapter)) { + return createOutline(); + } + if (NodeMap.class.equals(adapter)) { + return nodeMap; + } + if (INode.class.equals(adapter)) { + return rootNode; + } + if (IMapping.class.equals(adapter)) { + return mapping; + } + if (InteractiveVtkPanel.class.equals(adapter)) { + return panel; + } + if (ISelectionProvider.class.equals(adapter)) + return selectionProvider; + return super.getAdapter(adapter); + } + + public Set getPropertyContexts() { + Set result = new HashSet(); + result.add("http://www.simantics.org/Project-1.0/ProjectBrowseContext"); + return result; + } + + public P3DRootNode getRootNode() { + return rootNode; + } + + public IMapping getMapping() { + return mapping; + } +} diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/geometry/BallValveGeometryProvider.java b/org.simantics.plant3d/src/org/simantics/plant3d/geometry/BallValveGeometryProvider.java new file mode 100644 index 00000000..b0da882a --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/geometry/BallValveGeometryProvider.java @@ -0,0 +1,48 @@ +package org.simantics.plant3d.geometry; + +import java.util.Collection; +import java.util.Collections; +import java.util.Map; + +import org.jcae.opencascade.jni.TopoDS_Shape; +import org.simantics.db.Resource; +import org.simantics.g3d.math.MathTools; +import org.simantics.opencascade.OccTriangulator; + +public class BallValveGeometryProvider extends BuiltinGeometryProvider { + + public BallValveGeometryProvider(Resource resource) { + super(resource); + } + + private double radius = 0.01; + + @Override + public Collection getModel() throws Exception { + TopoDS_Shape cyl = OccTriangulator.makeCylinder(new double[] {-radius*2, 0.0, 0.0}, new double[] { 1.0, 0.0, 0.0 }, radius, radius*4); + TopoDS_Shape sph = OccTriangulator.makeSphere(0, 0, 0, radius*1.5); + TopoDS_Shape shape = OccTriangulator.makeCompound(new TopoDS_Shape[]{cyl, sph}); + cyl.delete(); + sph.delete(); + return Collections.singletonList(shape); + } + + @Override + public void setProperties(Map props) { + if (props.containsKey("radius")) { + radius = (Double)props.get("radius"); + } + if (radius < MathTools.NEAR_ZERO) + radius = MathTools.NEAR_ZERO; + + } + + @Override + public void updateCalculatedProperties(Map returnProps) { + returnProps.put("length", radius*4); + + } + + + +} diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/geometry/BuiltinGeometryProvider.java b/org.simantics.plant3d/src/org/simantics/plant3d/geometry/BuiltinGeometryProvider.java new file mode 100644 index 00000000..5250cc9e --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/geometry/BuiltinGeometryProvider.java @@ -0,0 +1,29 @@ +package org.simantics.plant3d.geometry; + +import java.util.Map; + +import org.eclipse.core.runtime.IAdaptable; +import org.simantics.db.Resource; +import org.simantics.opencascade.ParametricSolidModelProvider; + +public abstract class BuiltinGeometryProvider implements ParametricSolidModelProvider, IAdaptable{ + + private Resource resource; + + public BuiltinGeometryProvider(Resource resource) { + this.resource = resource; + } + + @Override + public Object getAdapter(Class adapter) { + if (Resource.class == adapter) + return resource; + return null; + } + + @Override + public void updateCalculatedProperties(Map returnProps) { + + } + +} diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/geometry/CapGeometryProvider.java b/org.simantics.plant3d/src/org/simantics/plant3d/geometry/CapGeometryProvider.java new file mode 100644 index 00000000..4161d941 --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/geometry/CapGeometryProvider.java @@ -0,0 +1,96 @@ +package org.simantics.plant3d.geometry; + +import java.util.Collection; +import java.util.Collections; +import java.util.Map; + +import org.jcae.opencascade.jni.BRepBuilderAPI_MakeEdge; +import org.jcae.opencascade.jni.BRepBuilderAPI_MakeFace; +import org.jcae.opencascade.jni.BRepBuilderAPI_MakeWire; +import org.jcae.opencascade.jni.BRepPrimAPI_MakeRevol; +import org.jcae.opencascade.jni.GC_MakeArcOfCircle; +import org.jcae.opencascade.jni.GC_MakeSegment; +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_Wire; +import org.simantics.db.Resource; +import org.simantics.g3d.math.MathTools; + +public class CapGeometryProvider extends BuiltinGeometryProvider { + + public CapGeometryProvider(Resource resource) { + super(resource); + } + + private double radius = 0.01; + + @Override + public Collection getModel() throws Exception { +// TopoDS_Shape cyl = OccTriangulator.makeCylinder(new double[] {0.0, 0.0, 0.0}, new double[] { 1.0, 0.0, 0.0 }, radius, radius*0.25); +// return Collections.singletonList(cyl); + double length = radius * 0.5; + double p0[] = new double[]{ length, 0.0,0.0}; + double p1[] = new double[]{length*0.8, radius*0.6,0.0}; + double p2[] = new double[]{length*0.5, radius,0.0}; + double p3[] = new double[]{ 0.0, radius,0.0}; + double p4[] = new double[]{ 0.0, 0.0,0.0}; + GC_MakeArcOfCircle m1 = new GC_MakeArcOfCircle(p0,p1,p2); + GC_MakeSegment s1 = new GC_MakeSegment(p2,p3); + GC_MakeSegment s2 = new GC_MakeSegment(p3,p4); + + BRepBuilderAPI_MakeEdge edge = new BRepBuilderAPI_MakeEdge(m1.value()); + TopoDS_Edge e1 = (TopoDS_Edge)edge.shape(); + edge.delete(); + + edge = new BRepBuilderAPI_MakeEdge(s1.value()); + TopoDS_Edge e2 = (TopoDS_Edge)edge.shape(); + edge.delete(); + + edge = new BRepBuilderAPI_MakeEdge(s2.value()); + TopoDS_Edge e3 = (TopoDS_Edge)edge.shape(); + edge.delete(); + + BRepBuilderAPI_MakeWire wire = new BRepBuilderAPI_MakeWire(e1,e2,e3); + TopoDS_Wire w = (TopoDS_Wire)wire.shape(); + wire.delete(); + + BRepBuilderAPI_MakeFace face = new BRepBuilderAPI_MakeFace(w); + TopoDS_Face F = (TopoDS_Face) face.shape(); + face.delete(); + + BRepPrimAPI_MakeRevol revol = new BRepPrimAPI_MakeRevol(F,new double[]{0.0,0.0,0.0,1.0,0.0,0.0}); + TopoDS_Shape shape = revol.shape(); + revol.delete(); + + m1.delete(); + s1.delete(); + s2.delete(); + e1.delete(); + e2.delete(); + e3.delete(); + w.delete(); + F.delete(); + + return Collections.singletonList(shape); + } + + @Override + public void setProperties(Map props) { + if (props.containsKey("radius")) { + radius = (Double)props.get("radius"); + } + if (radius < MathTools.NEAR_ZERO) + radius = MathTools.NEAR_ZERO; + + } + + @Override + public void updateCalculatedProperties(Map returnProps) { + returnProps.put("length", radius*4); + + } + + + +} diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/geometry/CheckValveGeometryProvider.java b/org.simantics.plant3d/src/org/simantics/plant3d/geometry/CheckValveGeometryProvider.java new file mode 100644 index 00000000..85f4c7aa --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/geometry/CheckValveGeometryProvider.java @@ -0,0 +1,47 @@ +package org.simantics.plant3d.geometry; + +import java.util.Collection; +import java.util.Collections; +import java.util.Map; + +import org.jcae.opencascade.jni.TopoDS_Shape; +import org.simantics.db.Resource; +import org.simantics.g3d.math.MathTools; +import org.simantics.opencascade.OccTriangulator; + +public class CheckValveGeometryProvider extends BuiltinGeometryProvider { + + public CheckValveGeometryProvider(Resource resource) { + super(resource); + } + + private double radius = 0.01; + + @Override + public Collection getModel() throws Exception { + double l = radius*0.2; + TopoDS_Shape cyl = OccTriangulator.makeCylinder(new double[] {-radius, 0.0, 0.0}, new double[] { 1.0, 0.0, 0.0 }, radius, l); + TopoDS_Shape con = OccTriangulator.makeCone(new double[] {-radius, 0.0, 0.0}, new double[] { 1.0, 0.0, 0.0 }, radius*0.1, radius,radius*2); + TopoDS_Shape shape = OccTriangulator.makeFuse(cyl, con); + cyl.delete(); + con.delete(); + return Collections.singletonList(shape); + } + + @Override + public void setProperties(Map props) { + if (props.containsKey("radius")) { + radius = (Double)props.get("radius"); + } + if (radius < MathTools.NEAR_ZERO) + radius = MathTools.NEAR_ZERO; + + } + + @Override + public void updateCalculatedProperties(Map returnProps) { + returnProps.put("length", radius*2); + + } + +} diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/geometry/ElbowGeometryProvider.java b/org.simantics.plant3d/src/org/simantics/plant3d/geometry/ElbowGeometryProvider.java new file mode 100644 index 00000000..46aea58c --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/geometry/ElbowGeometryProvider.java @@ -0,0 +1,47 @@ +package org.simantics.plant3d.geometry; + +import java.util.Collection; +import java.util.Collections; +import java.util.Map; + +import org.jcae.opencascade.jni.TopoDS_Shape; +import org.simantics.db.Resource; +import org.simantics.g3d.math.MathTools; +import org.simantics.opencascade.OccTriangulator; + +public class ElbowGeometryProvider extends BuiltinGeometryProvider { + + public ElbowGeometryProvider(Resource resource) { + super(resource); + } + + private double radius = 0.01; + private double turnRadius = 0.05; + private double turnAngle = Math.PI * 0.5; + + @Override + public Collection getModel() throws Exception { + double t = Math.tan((Math.PI - turnAngle) * 0.5); + double R = 0.0; + if (t > MathTools.NEAR_ZERO) + R = turnRadius / t; + TopoDS_Shape shape = OccTriangulator.makeTorus(new double[]{-R,0.0,-turnRadius}, new double[] { 0.0, 1.0, 0.0 }, turnRadius, radius,0.0,Math.PI*2.0,turnAngle); +// System.out.println("Create elbow tr:" + turnRadius + " r:" + radius + " angle:" +turnAngle + " " + R); + return Collections.singletonList(shape); + } + + @Override + public void setProperties(Map props) { + if (props.containsKey("turnRadius")) + turnRadius = (Double)props.get("turnRadius"); + if (props.containsKey("turnAngle")) + turnAngle = (Double)props.get("turnAngle"); + if (props.containsKey("radius")) { + radius = (Double)props.get("radius"); + } + if (radius < MathTools.NEAR_ZERO) + radius = MathTools.NEAR_ZERO; + } + +} + diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/geometry/HorizontalTankGeometryProvider.java b/org.simantics.plant3d/src/org/simantics/plant3d/geometry/HorizontalTankGeometryProvider.java new file mode 100644 index 00000000..7a3dc41b --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/geometry/HorizontalTankGeometryProvider.java @@ -0,0 +1,101 @@ +package org.simantics.plant3d.geometry; + +import java.util.Collection; +import java.util.Collections; +import java.util.Map; + +import org.jcae.opencascade.jni.BRepBuilderAPI_MakeEdge; +import org.jcae.opencascade.jni.BRepBuilderAPI_MakeFace; +import org.jcae.opencascade.jni.BRepBuilderAPI_MakeWire; +import org.jcae.opencascade.jni.BRepPrimAPI_MakeRevol; +import org.jcae.opencascade.jni.GC_MakeArcOfCircle; +import org.jcae.opencascade.jni.GC_MakeSegment; +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_Wire; +import org.simantics.db.Resource; +import org.simantics.opencascade.OccTriangulator; + +public class HorizontalTankGeometryProvider extends BuiltinGeometryProvider { + + public HorizontalTankGeometryProvider(Resource resource) { + super(resource); + } + + private double length = 1.0; + private double radius = 0.2; + + @Override + public Collection getModel() throws Exception { + + double p0[] = new double[]{-length*0.50, 0.0,0.0}; + double p1[] = new double[]{-length*0.488, radius*0.6,0.0}; + double p2[] = new double[]{-length*0.46, radius,0.0}; + double p3[] = new double[]{ length*0.46, radius,0.0}; + double p4[] = new double[]{ length*0.488, radius*0.6,0.0}; + double p5[] = new double[]{ length*0.50, 0.0,0.0}; + + GC_MakeArcOfCircle m1 = new GC_MakeArcOfCircle(p0,p1,p2); + GC_MakeSegment s1 = new GC_MakeSegment(p2,p3); + GC_MakeArcOfCircle m2 = new GC_MakeArcOfCircle(p3,p4,p5); + + BRepBuilderAPI_MakeEdge edge = new BRepBuilderAPI_MakeEdge(m1.value()); + TopoDS_Edge e1 = (TopoDS_Edge)edge.shape(); + edge.delete(); + + edge = new BRepBuilderAPI_MakeEdge(s1.value()); + TopoDS_Edge e2 = (TopoDS_Edge)edge.shape(); + edge.delete(); + + edge = new BRepBuilderAPI_MakeEdge(m2.value()); + TopoDS_Edge e3 = (TopoDS_Edge)edge.shape(); + edge.delete(); + + BRepBuilderAPI_MakeWire wire = new BRepBuilderAPI_MakeWire(e1,e2,e3); + TopoDS_Wire w = (TopoDS_Wire)wire.shape(); + wire.delete(); + + BRepBuilderAPI_MakeFace face = new BRepBuilderAPI_MakeFace(w); + TopoDS_Face F = (TopoDS_Face) face.shape(); + face.delete(); + + BRepPrimAPI_MakeRevol revol = new BRepPrimAPI_MakeRevol(F,new double[]{0.0,0.0,0.0,1.0,0.0,0.0}); + TopoDS_Shape shape = revol.shape(); + revol.delete(); + + m1.delete(); + s1.delete(); + m2.delete(); + e1.delete(); + e2.delete(); + e3.delete(); + w.delete(); + F.delete(); + + TopoDS_Shape shape2 = OccTriangulator.makeTranslation(shape, 0.0, radius, 0.0); + shape.delete(); + shape = shape2; + TopoDS_Shape box = OccTriangulator.makeBox(-length*0.4, 0.0, -radius*0.5, -length*0.3, radius, radius*0.5); + shape2 = OccTriangulator.makeFuse(shape, box); + shape.delete(); + box.delete(); + box = OccTriangulator.makeBox(length*0.3, 0.0, -radius*0.5, length*0.4, radius, radius*0.5); + shape = OccTriangulator.makeFuse(shape2, box); + shape2.delete(); + box.delete(); + + return Collections.singletonList(shape); + } + + @Override + public void setProperties(Map props) { + if (props.containsKey("length")) + length = (Double)props.get("length"); + if (props.containsKey("radius")) { + radius = (Double)props.get("radius"); + } + + } + +} diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/geometry/NozzleGeometryProvider.java b/org.simantics.plant3d/src/org/simantics/plant3d/geometry/NozzleGeometryProvider.java new file mode 100644 index 00000000..cdfe73cc --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/geometry/NozzleGeometryProvider.java @@ -0,0 +1,40 @@ +package org.simantics.plant3d.geometry; + +import java.util.Collection; +import java.util.Collections; +import java.util.Map; + +import org.jcae.opencascade.jni.TopoDS_Shape; +import org.simantics.db.Resource; +import org.simantics.opencascade.OccTriangulator; + +public class NozzleGeometryProvider extends BuiltinGeometryProvider { + + public NozzleGeometryProvider(Resource resource) { + super(resource); + } + + private double length = 0.1; + private double radius = 0.01; + + @Override + public Collection getModel() throws Exception { + TopoDS_Shape shape = OccTriangulator.makeCylinder(new double[] {-length, 0.0, 0.0}, new double[] { 1.0, 0.0, 0.0 }, radius, length); + TopoDS_Shape shape2 = OccTriangulator.makeCylinder(new double[] {-length*0.25, 0.0, 0.0}, new double[] { 1.0, 0.0, 0.0 }, radius*1.2, length*0.25); + TopoDS_Shape shape3 = OccTriangulator.makeCompound(new TopoDS_Shape[]{shape,shape2}); + shape.delete(); + shape2.delete(); + return Collections.singletonList(shape3); + } + + @Override + public void setProperties(Map props) { + if (props.containsKey("length")) + length = (Double)props.get("length"); + if (props.containsKey("radius")) { + radius = (Double)props.get("radius"); + } + + } + +} diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/geometry/PumpGeometryProvider.java b/org.simantics.plant3d/src/org/simantics/plant3d/geometry/PumpGeometryProvider.java new file mode 100644 index 00000000..a7c32a66 --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/geometry/PumpGeometryProvider.java @@ -0,0 +1,72 @@ +package org.simantics.plant3d.geometry; + +import java.util.Collection; +import java.util.Collections; +import java.util.Map; + +import org.jcae.opencascade.jni.BRepBuilderAPI_MakeEdge; +import org.jcae.opencascade.jni.BRepBuilderAPI_MakeFace; +import org.jcae.opencascade.jni.BRepBuilderAPI_MakeWire; +import org.jcae.opencascade.jni.BRepPrimAPI_MakeRevol; +import org.jcae.opencascade.jni.GC_MakeArcOfCircle; +import org.jcae.opencascade.jni.GC_MakeSegment; +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_Wire; +import org.simantics.db.Resource; +import org.simantics.opencascade.OccTriangulator; + +public class PumpGeometryProvider extends BuiltinGeometryProvider { + + public PumpGeometryProvider(Resource resource) { + super(resource); + } + + private double length = 0.5; + private double width = 0.25; + + @Override + public Collection getModel() throws Exception { + double h = width * 0.5; + double h2 = width * 0.1; + double ld2 = length * 0.5; + double wd2 = width * 0.5; + + double r1 = width * 0.5; + double r2 = r1 *0.2; + double r3 = r1 *0.5; + + double l1 = length * 0.2; + double l2 = length * 0.2; + double l2b = l2 + length * 0.1; + double l3 = length * 0.6; + + double dir[] = new double[]{1.0,0.0,0.0}; + + TopoDS_Shape foundation = OccTriangulator.makeBox(-ld2, 0.0, -wd2, ld2, h2, wd2); + TopoDS_Shape rotator = OccTriangulator.makeCylinder(new double[]{-ld2,h+h2,0.0}, dir, r1, l1); + TopoDS_Shape axis = OccTriangulator.makeCylinder(new double[]{-ld2+l1,h+h2,0.0}, dir, r2, l2b); + TopoDS_Shape motor = OccTriangulator.makeCylinder(new double[]{-ld2+l1+l2,h+h2,0.0}, dir, r3, l3); + TopoDS_Shape motorBox = OccTriangulator.makeBox(-ld2+l1+l2, h2, -r3, ld2, h2+h-r3, r3); + + TopoDS_Shape shape = OccTriangulator.makeCompound(new TopoDS_Shape[]{foundation,rotator,axis,motor,motorBox}); + foundation.delete(); + rotator.delete(); + axis.delete(); + motor.delete(); + motorBox.delete(); + return Collections.singletonList(shape); + } + + @Override + public void setProperties(Map props) { + if (props.containsKey("length")) + length = (Double)props.get("length"); + if (props.containsKey("width")) { + width = (Double)props.get("width"); + } + + } + +} diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/geometry/ReducerGeometryProvider.java b/org.simantics.plant3d/src/org/simantics/plant3d/geometry/ReducerGeometryProvider.java new file mode 100644 index 00000000..d3387f79 --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/geometry/ReducerGeometryProvider.java @@ -0,0 +1,57 @@ +package org.simantics.plant3d.geometry; + +import java.util.Collection; +import java.util.Collections; +import java.util.Map; + +import org.jcae.opencascade.jni.TopoDS_Shape; +import org.simantics.db.Resource; +import org.simantics.g3d.math.MathTools; +import org.simantics.opencascade.OccTriangulator; + +public class ReducerGeometryProvider extends BuiltinGeometryProvider { + + public ReducerGeometryProvider(Resource resource) { + super(resource); + } + + private double radius = 0.01; + private double radius2 = 0.02; + + @Override + public Collection getModel() throws Exception { +// GP_Circ circ = new GP_Circ(new double[]{-length*0.5, 0.0, 0.0,1.0,0.0,0.0}, radius); +// GP_Circ circ2 = new GP_Circ(new double[]{length*0.5, 0.0, 0.0,1.0,0.0,0.0}, radius2); +// System.out.println("Reducer " + length + " " + radius + " " + radius2); + double length = Math.max(0.1, Math.abs(radius-radius2)*4.0); + TopoDS_Shape shape; + if (Math.abs(radius-radius2) < MathTools.NEAR_ZERO) { + shape = OccTriangulator.makeCylinder(new double[] {-length*0.5, 0.0, 0.0}, new double[] { 1.0, 0.0, 0.0 }, radius, length); + } else { + shape = OccTriangulator.makeCone(new double[] {-length*0.5, 0.0, 0.0}, new double[] { 1.0, 0.0, 0.0 }, radius,radius2, length); + } + return Collections.singletonList(shape); + } + + @Override + public void setProperties(Map props) { + + + if (props.containsKey("radius")) { + radius = (Double)props.get("radius"); + } + if (props.containsKey("radius2")) { + radius2 = (Double)props.get("radius2"); + } + + + + } + + @Override + public void updateCalculatedProperties(Map returnProps) { + returnProps.put("length", Math.max(0.1, Math.abs(radius-radius2)*4.0)); + + } + +} diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/geometry/StraightGeometryProvider.java b/org.simantics.plant3d/src/org/simantics/plant3d/geometry/StraightGeometryProvider.java new file mode 100644 index 00000000..ac63f915 --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/geometry/StraightGeometryProvider.java @@ -0,0 +1,44 @@ +package org.simantics.plant3d.geometry; + +import java.util.Collection; +import java.util.Collections; +import java.util.Map; + +import org.jcae.opencascade.jni.TopoDS_Shape; +import org.simantics.db.Resource; +import org.simantics.g3d.math.MathTools; +import org.simantics.opencascade.OccTriangulator; + +public class StraightGeometryProvider extends BuiltinGeometryProvider { + + public StraightGeometryProvider(Resource resource) { + super(resource); + } + + private double length = 1.0; + private double radius = 0.01; + + @Override + public Collection getModel() throws Exception { + TopoDS_Shape shape = OccTriangulator.makeCylinder(new double[] {-length*0.5, 0.0, 0.0}, new double[] { 1.0, 0.0, 0.0 }, radius, length); +// System.out.println("Create straight l:" + length + " r:" + radius); + return Collections.singletonList(shape); + } + + @Override + public void setProperties(Map props) { + if (props.containsKey("length")) + length = (Double)props.get("length"); + if (props.containsKey("radius")) { + radius = (Double)props.get("radius"); + } + if (length < 0.0) + length = 0.0; + if (radius < MathTools.NEAR_ZERO) + radius = MathTools.NEAR_ZERO; + + } + + + +} diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/geometry/VerticalTankGeometryProvider.java b/org.simantics.plant3d/src/org/simantics/plant3d/geometry/VerticalTankGeometryProvider.java new file mode 100644 index 00000000..5cb078e0 --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/geometry/VerticalTankGeometryProvider.java @@ -0,0 +1,87 @@ +package org.simantics.plant3d.geometry; + +import java.util.Collection; +import java.util.Collections; +import java.util.Map; + +import org.jcae.opencascade.jni.BRepBuilderAPI_MakeEdge; +import org.jcae.opencascade.jni.BRepBuilderAPI_MakeFace; +import org.jcae.opencascade.jni.BRepBuilderAPI_MakeWire; +import org.jcae.opencascade.jni.BRepPrimAPI_MakeRevol; +import org.jcae.opencascade.jni.GC_MakeArcOfCircle; +import org.jcae.opencascade.jni.GC_MakeSegment; +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_Wire; +import org.simantics.db.Resource; + +public class VerticalTankGeometryProvider extends BuiltinGeometryProvider { + + public VerticalTankGeometryProvider(Resource resource) { + super(resource); + } + + private double height = 1.0; + private double radius = 0.2; + + @Override + public Collection getModel() throws Exception { + + double p0[] = new double[]{ 0.0, height,0.0}; + double p1[] = new double[]{radius*0.6,height*0.98,0.0}; + double p2[] = new double[]{ radius,height*0.94,0.0}; + double p3[] = new double[]{ radius, 0.0,0.0}; + double p4[] = new double[]{ 0.0, 0.0,0.0}; + + GC_MakeArcOfCircle m1 = new GC_MakeArcOfCircle(p0,p1,p2); + GC_MakeSegment s1 = new GC_MakeSegment(p2,p3); + GC_MakeSegment s2 = new GC_MakeSegment(p3,p4); + + BRepBuilderAPI_MakeEdge edge = new BRepBuilderAPI_MakeEdge(m1.value()); + TopoDS_Edge e1 = (TopoDS_Edge)edge.shape(); + edge.delete(); + + edge = new BRepBuilderAPI_MakeEdge(s1.value()); + TopoDS_Edge e2 = (TopoDS_Edge)edge.shape(); + edge.delete(); + + edge = new BRepBuilderAPI_MakeEdge(s2.value()); + TopoDS_Edge e3 = (TopoDS_Edge)edge.shape(); + edge.delete(); + + BRepBuilderAPI_MakeWire wire = new BRepBuilderAPI_MakeWire(e1,e2,e3); + TopoDS_Wire w = (TopoDS_Wire)wire.shape(); + wire.delete(); + + BRepBuilderAPI_MakeFace face = new BRepBuilderAPI_MakeFace(w); + TopoDS_Face F = (TopoDS_Face) face.shape(); + face.delete(); + + BRepPrimAPI_MakeRevol revol = new BRepPrimAPI_MakeRevol(F,new double[]{0.0,0.0,0.0,0.0,1.0,0.0}); + TopoDS_Shape shape = revol.shape(); + revol.delete(); + + m1.delete(); + s1.delete(); + s2.delete(); + e1.delete(); + e2.delete(); + e3.delete(); + w.delete(); + F.delete(); + + return Collections.singletonList(shape); + } + + @Override + public void setProperties(Map props) { + if (props.containsKey("height")) + height = (Double)props.get("height"); + if (props.containsKey("radius")) { + radius = (Double)props.get("radius"); + } + + } + +} diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/gizmo/SplitPointSelectionGizmo.java b/org.simantics.plant3d/src/org/simantics/plant3d/gizmo/SplitPointSelectionGizmo.java new file mode 100644 index 00000000..336fdbd5 --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/gizmo/SplitPointSelectionGizmo.java @@ -0,0 +1,151 @@ +package org.simantics.plant3d.gizmo; + +import java.awt.event.MouseEvent; +import java.awt.event.MouseMotionListener; +import java.util.ArrayList; +import java.util.Collection; + +import javax.vecmath.AxisAngle4d; +import javax.vecmath.Point3d; +import javax.vecmath.Tuple3d; +import javax.vecmath.Vector2d; +import javax.vecmath.Vector3d; + +import org.simantics.g3d.math.MathTools; +import org.simantics.g3d.math.Ray; +import org.simantics.g3d.scenegraph.RenderListener; +import org.simantics.g3d.shape.Color4d; +import org.simantics.g3d.shape.Cone; +import org.simantics.g3d.shape.Cylinder; +import org.simantics.g3d.shape.Mesh; +import org.simantics.g3d.vtk.common.InteractiveVtkPanel; +import org.simantics.g3d.vtk.gizmo.vtkGizmo; +import org.simantics.g3d.vtk.shape.MeshActor; +import org.simantics.g3d.vtk.utils.vtkUtil; + +import vtk.vtkProp; + +public class SplitPointSelectionGizmo extends vtkGizmo { + + MeshActor actor; + + InteractiveVtkPanel panel; + private RenderListener listener; + private MouseMotionListener mouseListener; + + Point3d start; + Point3d end; + Vector3d dir; + + Vector2d mousePos = new Vector2d(); + + Vector3d pa = new Vector3d(); + Vector3d pb = new Vector3d(); + + Tuple3d splitPoint = null; + + public SplitPointSelectionGizmo(InteractiveVtkPanel panel) { + this.panel = panel; + + int res = 16; + + Mesh cone_x = Cone.create(0.1, res); + cone_x.rotate(MathTools.getQuat(new AxisAngle4d(0,0,-1,Math.PI*0.5))); + cone_x.translate(new Vector3d(0.8,0,0)); + + Mesh tube_x = Cylinder.create(MathTools.ORIGIN, new Vector3d(0.8,0,0), 0.05, res); + tube_x.add(cone_x); + + Color4d z_col = new Color4d(0,1,0,1); + tube_x.setColor(z_col); + + actor = new MeshActor(); + actor.setMesh(tube_x); + + this.listener = new RenderListener() { + @Override + public void preRender() { + Ray ray = vtkUtil.createMouseRay(getRenderer(), mousePos.x, mousePos.y); + //ray.dir.add(ray.pos); + //if (MathTools.intersectLineLine(start, end, ray.pos, ray.dir, pa, pb)) { + double mu[] = new double[2]; + if (MathTools.intersectStraightStraight(start, dir, ray.pos, ray.dir, pa, pb,mu)) { + splitPoint = pa; + if (mu[0] < 0.0) + splitPoint = start; + else if (mu[0] > 1.0) + splitPoint = end; + Vector3d dir = new Vector3d(splitPoint); + dir.sub(pb); + double length = dir.length(); + dir.scale(1.0/length); + AxisAngle4d aa = MathTools.createRotation(MathTools.X_AXIS, dir); + setRotation(aa); + setScale(length); + setPosition(pb); + actor.SetVisibility(1); + } else { + splitPoint = null; + actor.SetVisibility(0); + } + + } + + @Override + public void postRender() { + + } + }; + + this.mouseListener = new MouseMotionListener() { + + @Override + public void mouseMoved(MouseEvent e) { + mousePos.x = e.getX(); + mousePos.y = e.getY(); + SplitPointSelectionGizmo.this.panel.repaint(); + } + + @Override + public void mouseDragged(MouseEvent e) { + mousePos.x = e.getX(); + mousePos.y = e.getY(); + SplitPointSelectionGizmo.this.panel.repaint(); + } + }; + + } + + public void setSplit(Point3d start, Point3d end) { + this.start = start; + this.end = end; + dir = new Vector3d(end); + dir.sub(start); + } + + @Override + public void attach(Object renderingPart) { + super.attach(renderingPart); + panel.addListener(listener); + panel.addMouseMotionListener(mouseListener); + } + + @Override + public void deattach() { + panel.removeListener(listener); + panel.removeMouseMotionListener(mouseListener); + super.deattach(); + } + + @Override + public Collection getGizmo() { + Collection coll = new ArrayList(); + coll.add(actor); + return coll; + } + + public Tuple3d getSplitPoint() { + return splitPoint; + } + +} diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/gizmo/TerminalSelectionGizmo.java b/org.simantics.plant3d/src/org/simantics/plant3d/gizmo/TerminalSelectionGizmo.java new file mode 100644 index 00000000..422e022a --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/gizmo/TerminalSelectionGizmo.java @@ -0,0 +1,251 @@ +package org.simantics.plant3d.gizmo; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Set; + +import javax.vecmath.Point2d; +import javax.vecmath.Vector3d; + +import org.simantics.g3d.scenegraph.RenderListener; +import org.simantics.g3d.tools.PluginTools; +import org.simantics.g3d.vtk.common.InteractiveVtkPanel; +import org.simantics.g3d.vtk.gizmo.vtkGizmo; +import org.simantics.g3d.vtk.utils.vtkUtil; +import org.simantics.plant3d.Activator; +import org.simantics.plant3d.scenegraph.InlineComponent; +import org.simantics.plant3d.scenegraph.PipelineComponent; +import org.simantics.plant3d.scenegraph.controlpoint.PipeControlPoint.PositionType; + +import vtk.vtkCellArray; +import vtk.vtkFloatArray; +import vtk.vtkPNGReader; +import vtk.vtkPoints; +import vtk.vtkPolyData; +import vtk.vtkPolyDataMapper2D; +import vtk.vtkPolygon; +import vtk.vtkProp; +import vtk.vtkRenderer; +import vtk.vtkTexture; +import vtk.vtkTexturedActor2D; + +public class TerminalSelectionGizmo extends vtkGizmo { + + + + vtkTexturedActor2D prevProp; + vtkTexturedActor2D nextProp; + vtkTexturedActor2D middleProp; + + boolean showPrev = false; + boolean showNext = false; + boolean showMiddle = false; + + Vector3d middle = new Vector3d(); + Vector3d prev = new Vector3d(); + Vector3d next = new Vector3d(); + + InteractiveVtkPanel panel; + + private RenderListener listener; + public TerminalSelectionGizmo(InteractiveVtkPanel panel) { + this.panel = panel; + this.listener = new RenderListener() { + + @Override + public void preRender() { + + if (showMiddle) { + Point2d p = vtkUtil.getScreenCoordinates(getRenderer(), middle); + middleProp.SetDisplayPosition((int)p.x, (int)p.y); + } + if (showPrev) { + Point2d p = vtkUtil.getScreenCoordinates(getRenderer(), prev); + prevProp.SetDisplayPosition((int)p.x, (int)p.y); + } + if (showNext) { + Point2d p = vtkUtil.getScreenCoordinates(getRenderer(), next); + nextProp.SetDisplayPosition((int)p.x, (int)p.y); + } + } + + @Override + public void postRender() { + + + } + }; + } + + @Override + public void attach(Object renderingPart) { + if (nextProp == null) { + loadData(); + + } + panel.addListener(listener); + + super.attach(renderingPart); + + } + + @Override + public Collection getGizmo() { + List list = new ArrayList(); + if (showPrev) { + list.add(prevProp); + } + if (showNext) { + list.add(nextProp); + + } + if (showMiddle) { + list.add(middleProp); + } + return list; + } + + protected void attachActors() { + vtkRenderer ren = getRenderer(); + if (showPrev) { + ren.AddActor(prevProp); + } + if (showNext) { + ren.AddActor(nextProp); + } + if (showMiddle) { + ren.AddActor(middleProp); + } + + } + + @Override + protected void deattachActors() { + panel.removeListener(listener); + vtkRenderer ren = getRenderer(); + ren.RemoveActor(prevProp); + ren.RemoveActor(nextProp); + ren.RemoveActor(middleProp); + } + + public void setComponent(PipelineComponent component, Set allowed) { +// showPrev = component.getPrevious() == null; +// showNext = component.getNext() == null; +// showMiddle = (component instanceof InlineComponent) && !component.getControlPoint().isFixed(); + showPrev = allowed.contains(PositionType.PREVIOUS); + showNext = allowed.contains(PositionType.NEXT); + showMiddle = allowed.contains(PositionType.SPLIT); + + middle = component.getControlPoint().getWorldPosition(); + component.getControlPoint().getControlPointEnds(prev, next); + + } + + private void loadData() { + String middleTexFile = PluginTools.getAbsolutePath(Activator.getDefault().getBundle(), "icons/middle.png"); + String plusTexFile = PluginTools.getAbsolutePath(Activator.getDefault().getBundle(), "icons/plus.png"); + if (middleTexFile == null || plusTexFile == null) + throw new RuntimeException("Cannot resolve required image files."); + + vtkPoints points = new vtkPoints(); + points.InsertNextPoint(-8, -8, 0.0); + points.InsertNextPoint( 8, -8, 0.0); + points.InsertNextPoint( 8, 8, 0.0); + points.InsertNextPoint(-8, 8, 0.0); + + + vtkCellArray cellArray = new vtkCellArray(); + vtkPolygon polygon = new vtkPolygon(); + polygon.GetPointIds().SetNumberOfIds(4); + polygon.GetPointIds().SetId(0, 0); + polygon.GetPointIds().SetId(1, 1); + polygon.GetPointIds().SetId(2, 2); + polygon.GetPointIds().SetId(3, 3); + + cellArray.InsertNextCell(polygon); + + vtkPolyData quad = new vtkPolyData(); + quad.SetPoints(points); + quad.SetPolys(cellArray); + + vtkFloatArray texCoords = new vtkFloatArray(); + + texCoords.SetNumberOfComponents(2); + + texCoords.InsertNextTuple2(0.0, 0.0); + texCoords.InsertNextTuple2(1.0, 0.0); + texCoords.InsertNextTuple2(1.0, 1.0); + texCoords.InsertNextTuple2(0.0, 1.0); + + quad.GetPointData().SetTCoords(texCoords); + + vtkPNGReader middleReader = new vtkPNGReader(); + middleReader.SetFileName(middleTexFile); + + vtkPNGReader plusReader = new vtkPNGReader(); + plusReader.SetFileName(plusTexFile); + + vtkTexture middleTex = new vtkTexture(); + middleTex.SetInputConnection(middleReader.GetOutputPort()); + middleTex.SetInterpolate(1); + + vtkTexture plusTex = new vtkTexture(); + plusTex.SetInputConnection(plusReader.GetOutputPort()); + plusTex.SetInterpolate(1); + + vtkPolyDataMapper2D mapper = new vtkPolyDataMapper2D(); + mapper.SetInput(quad); + + nextProp = new vtkTexturedActor2D(); + prevProp = new vtkTexturedActor2D(); + middleProp = new vtkTexturedActor2D(); + + nextProp.SetMapper(mapper); + nextProp.SetTexture(plusTex); + nextProp.SetPickable(1); + + prevProp.SetMapper(mapper); + prevProp.SetTexture(plusTex); + prevProp.SetPickable(1); + + middleProp.SetMapper(mapper); + middleProp.SetTexture(middleTex); + middleProp.SetPickable(1); + + + plusReader.GetOutputPort().Delete(); + plusReader.Delete(); + middleReader.GetOutputPort().Delete(); + middleReader.Delete(); + middleTex.Delete(); + plusTex.Delete(); + + mapper.Delete(); + quad.GetPointData().Delete(); + quad.Delete(); + points.Delete(); + polygon.GetPointIds().Delete(); + polygon.Delete(); + cellArray.Delete(); + texCoords.Delete(); + + } + + + public PositionType getPickedPosition(vtkProp[] picked) { + if (picked == null) + return null; + for (vtkProp p : picked) { + if (p.equals(middleProp)) + return PositionType.SPLIT; + if (p.equals(nextProp)) + return PositionType.NEXT; + if (p.equals(prevProp)) + return PositionType.PREVIOUS; + } + return null; + } + + +} diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/handlers/NewPlantHandler.java b/org.simantics.plant3d/src/org/simantics/plant3d/handlers/NewPlantHandler.java new file mode 100644 index 00000000..42e64cfe --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/handlers/NewPlantHandler.java @@ -0,0 +1,54 @@ +package org.simantics.plant3d.handlers; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; +import org.simantics.Simantics; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.request.WriteRequest; +import org.simantics.db.common.utils.NameUtils; +import org.simantics.db.exception.DatabaseException; +import org.simantics.layer0.Layer0; +import org.simantics.plant3d.Activator; +import org.simantics.plant3d.utils.P3DUtil; + +public class NewPlantHandler extends AbstractHandler { + + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + final Resource library = Simantics.getProject().get(); + + Job job = new Job("Create Plant ") { + @Override + protected IStatus run(IProgressMonitor monitor) { + monitor.beginTask("Create Plant" , IProgressMonitor.UNKNOWN); + try { + Simantics.getSession().syncRequest(new WriteRequest() { + + @Override + public void perform(WriteGraph graph) throws DatabaseException { + Layer0 l0 = Layer0.getInstance(graph); + String modelName = NameUtils.findFreshName(graph, "Plant", library); + Resource model = P3DUtil.createModel(graph, modelName); + graph.claim(library, l0.ConsistsOf, model); + + } + }); + return Status.OK_STATUS; + } catch (DatabaseException e) { + return new Status(IStatus.ERROR, Activator.PLUGIN_ID, getName() + " failed.",e); + } + } + + + }; + job.setUser(true); + job.schedule(); + return null; + } +} diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/project/P3DPerspectiveFactory.java b/org.simantics.plant3d/src/org/simantics/plant3d/project/P3DPerspectiveFactory.java new file mode 100644 index 00000000..fd2e5d1f --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/project/P3DPerspectiveFactory.java @@ -0,0 +1,14 @@ +package org.simantics.plant3d.project; + +import org.eclipse.ui.IPageLayout; +import org.eclipse.ui.IPerspectiveFactory; + +public class P3DPerspectiveFactory implements IPerspectiveFactory { + + @Override + public void createInitialLayout(IPageLayout layout) { + layout.setEditorAreaVisible(true); + + } + +} diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/project/P3DProjectFeature.java b/org.simantics.plant3d/src/org/simantics/plant3d/project/P3DProjectFeature.java new file mode 100644 index 00000000..a39292f9 --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/project/P3DProjectFeature.java @@ -0,0 +1,21 @@ +package org.simantics.plant3d.project; + +import org.simantics.project.ProjectKeys; +import org.simantics.project.exception.ProjectException; +import org.simantics.project.features.AbstractProjectFeature; +import org.simantics.project.features.IProjectFeature; + +public class P3DProjectFeature extends AbstractProjectFeature implements IProjectFeature { + + private static final String DEFAULT_PERSPECTIVE = "org.simantics.plant3d.perspective"; + + public P3DProjectFeature() { + // TODO Auto-generated constructor stub + } + + @Override + public void configure() throws ProjectException { + getProjectElement().setHint(ProjectKeys.DEFAULT_PERSPECTIVE, DEFAULT_PERSPECTIVE); + } + +} diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/property/P3DSelectionProcessor.java b/org.simantics.plant3d/src/org/simantics/plant3d/property/P3DSelectionProcessor.java new file mode 100644 index 00000000..54941609 --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/property/P3DSelectionProcessor.java @@ -0,0 +1,169 @@ +package org.simantics.plant3d.property; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.IWorkbenchSite; +import org.simantics.Simantics; +import org.simantics.browsing.ui.swt.PartNameListener; +import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.common.utils.NameUtils; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.management.ISessionContext; +import org.simantics.db.request.Read; +import org.simantics.g3d.property.PropertyTabContributor; +import org.simantics.g3d.property.PropertyTabUtil; +import org.simantics.g3d.scenegraph.IG3DNode; +import org.simantics.g3d.tools.AdaptationUtils; +import org.simantics.g3d.vtk.property.VTKPropertyTabContributor; +import org.simantics.objmap.structural.StructuralResource; +import org.simantics.selectionview.BasicPropertyTab; +import org.simantics.selectionview.ComparableTabContributor; +import org.simantics.selectionview.PropertyTabContributorImpl; +import org.simantics.selectionview.SelectionProcessor; +import org.simantics.utils.datastructures.Callback; + +import vtk.vtkProp; + +public class P3DSelectionProcessor implements SelectionProcessor { + + private static final boolean DEBUG = false; + @Override + public Collection process(Object selection, ReadGraph backend) { +// System.out.println(getClass().getSimpleName() + " incoming selection: " + ObjectUtils.toString(selection)); + + + Collection result = new ArrayList(); + Collection resourceCollection = AdaptationUtils.adaptToCollection(selection, Resource.class); + Collection structuralResourceCollection = AdaptationUtils.adaptToCollection(selection, StructuralResource.class); + Collection propCollection = AdaptationUtils.adaptToCollection(selection, vtkProp.class); + Collection nodeCollection = AdaptationUtils.adaptToCollection(selection, IG3DNode.class); + boolean readOnly = false; + if (resourceCollection.size() == 0 && structuralResourceCollection.size() > 0) { + for (StructuralResource sr : structuralResourceCollection) { + if (sr.isStructural() && !sr.isStructuralRoot()) + readOnly = true; + resourceCollection.add(sr.getResource()); + } + } + + + if (nodeCollection.size() == 1) { + IG3DNode node = nodeCollection.iterator().next(); + List contributors = PropertyTabUtil.getContributors(node); + int i = 100; + for (PropertyTabContributor c : contributors) { + result.add(new ComparableTabContributor(c, i--, node, c.getId())); + } + } + + if (DEBUG) { + if (propCollection.size() == 1) { + vtkProp prop = propCollection.iterator().next(); + if (prop == null) + throw new NullPointerException(); + result.add(new ComparableTabContributor(new VTKPropertyTabContributor(), -2, prop, "VTK")); + } + + if (resourceCollection.size() > 0) { + if (resourceCollection.size() > 1) + result.add(new ComparableTabContributor(new MultiSelectionTabContibutor(),0, resourceCollection, "Graph")); + else if (resourceCollection.size() == 1){ + try { + Resource r = resourceCollection.iterator().next(); + result.add(new ComparableTabContributor(new P3DBasicPropertyTab(!readOnly), 0, r, "Graph")); + + } catch (Exception e) { + e.printStackTrace(); + } + } + } + } + + if(result.size() == 0) { + result.add(new ComparableTabContributor(new NoneSelectionTabContributor(),0, resourceCollection, "Empty")); + } + + return result; + } + + public class P3DBasicPropertyTab extends BasicPropertyTab { + + boolean enabled; + public P3DBasicPropertyTab(boolean enabled) { + this.enabled = enabled; + } + public void updatePartName(ISelection forSelection, Callback updateCallback) { + Read read = getPartNameReadRequest(forSelection); + if (read == null) { + updateCallback.run("Override to control part name (PropertyTabContributorImpl.updatePartName)"); + } else { + Simantics.getSession().asyncRequest(read, new PartNameListener(updateCallback)); + } + } + public Read getPartNameReadRequest(ISelection forSelection) { + final Resource r = AdaptationUtils.adaptToSingle(forSelection, Resource.class); + if (r == null) + return null; + return new Read() { + @Override + public String perform(ReadGraph graph) throws DatabaseException { + return NameUtils.getSafeName(graph, r); + } + }; + } + + @Override + public void createControls(Composite body, IWorkbenchSite site, + ISessionContext context, WidgetSupport support) { + // TODO Auto-generated method stub + super.createControls(body, site, context, support); + ((Composite)parameterExplorer.getExplorerControl()).setEnabled(enabled); + } + } + + + + public class MultiSelectionTabContibutor extends PropertyTabContributorImpl { + public void createControls(org.eclipse.swt.widgets.Composite body, org.eclipse.ui.IWorkbenchSite site, org.simantics.db.management.ISessionContext context, org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport support) { + //Composite composite = new Composite(body, SWT.NONE); + } + + public Read getPartNameReadRequest(ISelection forSelection) { + final Collection coll = AdaptationUtils.adaptToCollection(forSelection, Resource.class); + if (coll.size() == 0) + return null; + return new Read() { + @Override + public String perform(ReadGraph graph) throws DatabaseException { + String title = ""; + for (Resource r : coll) { + title += NameUtils.getSafeName(graph, r) +","; + } + System.out.println(title); + return title.substring(0,title.length()-1); + } + }; + } + } + + public class NoneSelectionTabContributor extends PropertyTabContributorImpl { + @Override + public void createControls(Composite body, IWorkbenchSite site, + ISessionContext context, WidgetSupport support) { + //Composite composite = new Composite(body, SWT.NONE); + + } + + public void updatePartName(ISelection forSelection, Callback updateCallback) { + updateCallback.run("No Selection"); + } + } + + +} diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/EndComponent.java b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/EndComponent.java new file mode 100644 index 00000000..5df76c0f --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/EndComponent.java @@ -0,0 +1,53 @@ +package org.simantics.plant3d.scenegraph; + +import java.util.HashMap; +import java.util.Map; + +import org.simantics.g3d.scenegraph.base.ParentNode; +import org.simantics.objmap.graph.annotations.DynamicGraphType; +import org.simantics.objmap.graph.annotations.GetType; +import org.simantics.objmap.graph.annotations.SetType; +import org.simantics.plant3d.ontology.Plant3D; +import org.simantics.plant3d.scenegraph.controlpoint.PipeControlPoint; +import org.simantics.plant3d.scenegraph.controlpoint.ControlPointFactory; + +@DynamicGraphType(Plant3D.URIs.EndComponent) +public class EndComponent extends PipelineComponent { + + private String type; + PipeControlPoint controlPoint; + + @GetType(Plant3D.URIs.EndComponent) + public String getType() { + return type; + } + + @SetType(Plant3D.URIs.EndComponent) + public void setType(String type) throws Exception { + this.type = type; + controlPoint = ControlPointFactory.create(this); + + } + + @Override + public PipeControlPoint getControlPoint() { + return controlPoint; + } + + @Override + public void setParent(ParentNode parent, String name) { + super.setParent(parent, name); + setPipeRun((PipeRun)parent); + } + + @Override + public Map updateParameterMap() { + Map map = new HashMap(); + + PipeRun pipeRun = getPipeRun(); + if (pipeRun != null) { + map.put("radius", pipeRun.getPipeDiameter() * 0.5); + } + return map; + } +} diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/Equipment.java b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/Equipment.java new file mode 100644 index 00000000..3bac765c --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/Equipment.java @@ -0,0 +1,125 @@ +package org.simantics.plant3d.scenegraph; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import javax.vecmath.Quat4d; +import javax.vecmath.Vector3d; + +import org.simantics.g3d.math.MathTools; +import org.simantics.g3d.property.annotations.CompoundGetPropertyValue; +import org.simantics.g3d.property.annotations.CompoundSetPropertyValue; +import org.simantics.objmap.graph.annotations.CompoundRelatedGetValue; +import org.simantics.objmap.graph.annotations.CompoundRelatedSetValue; +import org.simantics.objmap.graph.annotations.DynamicGraphType; +import org.simantics.objmap.graph.annotations.GetType; +import org.simantics.objmap.graph.annotations.RelatedElementsAdd; +import org.simantics.objmap.graph.annotations.RelatedElementsGet; +import org.simantics.objmap.graph.annotations.RelatedElementsRem; +import org.simantics.objmap.graph.annotations.SetType; +import org.simantics.plant3d.ontology.Plant3D; +import org.simantics.plant3d.scenegraph.controlpoint.PipingRules; + + +@DynamicGraphType(Plant3D.URIs.Equipment) +public class Equipment extends P3DParentGeometryNode { + + private String type; + + @GetType(Plant3D.URIs.Equipment) + public String getType() { + return type; + } + + @SetType(Plant3D.URIs.Equipment) + public void setType(String type) { + this.type = type; + } + + + @RelatedElementsAdd(Plant3D.URIs.HasNozzle) + public void addChild(Nozzle node) { + Set ids = new HashSet(); + for (Nozzle n : getChild()) { + ids.add(n.getNozzleId()); + } + int newId = 0; + while (ids.contains(newId)) + newId++; + addNode(Plant3D.URIs.HasNozzle,node); + node.setNozzleId(newId); + } + + @RelatedElementsGet(Plant3D.URIs.HasNozzle) + public Collection getChild() { + return getNodes(Plant3D.URIs.HasNozzle); + } + + @RelatedElementsRem(Plant3D.URIs.HasNozzle) + public void remChild(Nozzle node) { + removeNode(Plant3D.URIs.HasNozzle, node); + } + + @Override + @CompoundRelatedGetValue(objRelation=Plant3D.URIs.hasParameter,objType=Plant3D.URIs.Parameter,valRelation=Plant3D.URIs.hasParameterValue) + @CompoundGetPropertyValue(name="Parameters",tabId="Parameters",value="parameters") + public Map getParameterMap() { + return super.getParameterMap(); + } + + @Override + @CompoundRelatedSetValue(Plant3D.URIs.hasParameter) + @CompoundSetPropertyValue(value="parameters") + public void setParameterMap(Map parameters) { + super.setParameterMap(parameters); + } + + @Override + protected double[] getColor() { + return new double[]{1,0,0}; + } + + @Override + protected double[] getSelectedColor() { + return new double[]{0.5,0,0.5}; + } + + @Override + public void setPosition(Vector3d position) { + if (MathTools.equals(position, getPosition())) + return; + super.setPosition(position); + for (Nozzle n : getChild()) { + n.getControlPoint()._setWorldPosition(n.getWorldPosition()); + n.getControlPoint()._setWorldOrientation(n.getWorldOrientation()); + } + for (Nozzle n : getChild()) { + try { + PipingRules.requestUpdate(n.getControlPoint()); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + @Override + public void setOrientation(Quat4d orientation) { + if (MathTools.equals(orientation, getOrientation())) + return; + super.setOrientation(orientation); + for (Nozzle n : getChild()) { + n.getControlPoint()._setWorldPosition(n.getWorldPosition()); + n.getControlPoint()._setWorldOrientation(n.getWorldOrientation()); + } + for (Nozzle n : getChild()) { + try { + PipingRules.requestUpdate(n.getControlPoint()); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + +} diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/GeometryNode.java b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/GeometryNode.java new file mode 100644 index 00000000..8d7ba9d9 --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/GeometryNode.java @@ -0,0 +1,239 @@ +package org.simantics.plant3d.scenegraph; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.jcae.opencascade.jni.TopoDS_Shape; +import org.simantics.g3d.math.MathTools; +import org.simantics.g3d.scenegraph.NodeHighlighter; +import org.simantics.g3d.vtk.utils.vtkUtil; +import org.simantics.objmap.graph.annotations.RelatedGetObj; +import org.simantics.objmap.graph.annotations.RelatedSetObj; +import org.simantics.opencascade.OccTriangulator; +import org.simantics.opencascade.ParametricSolidModelProvider; +import org.simantics.opencascade.SolidModelProvider; +import org.simantics.opencascade.vtk.vtkSolidObject; +import org.simantics.plant3d.ontology.Plant3D; + +import vtk.vtkActor; +import vtk.vtkPanel; +import vtk.vtkProp3D; +import vtk.vtkProperty; +import vtk.vtkRenderer; + +public abstract class GeometryNode extends P3DNode implements ParameterizedNode, NodeHighlighter { + + private TopoDS_Shape solidModel; + private vtkSolidObject solidObject; + + private Map currentParameters; + private Map calculatedParameters; + + private boolean parametersUpdated = true; + + public GeometryNode() { + currentParameters = new HashMap(); + calculatedParameters = new HashMap(); + } + + @Override + public void visualize(vtkPanel panel) { + if (solidModelProvider != null) { + + updateParameters(); + if (solidModel == null || parametersUpdated) { + createGeometry(); + } + } + if ((solidObject == null || parametersUpdated) && solidModel != null) { + solidObject = new vtkSolidObject(panel, solidModel); + } + if (solidObject != null) { + solidObject.visualizeSolid(true,true, false,false); + updateVisuals(true, true); + } + parametersUpdated = false; + + } + + public void updateParameters() { + if (solidModelProvider instanceof ParametricSolidModelProvider) { + ((ParametricSolidModelProvider)solidModelProvider).setProperties(currentParameters); + ((ParametricSolidModelProvider)solidModelProvider).updateCalculatedProperties(calculatedParameters); + } + } + + private void createGeometry() { + Collection shapes; + try { + shapes = solidModelProvider.getModel(); + if (shapes.size() == 1) { + solidModel = shapes.iterator().next(); + } else { + solidModel = OccTriangulator.makeCompound(shapes.toArray(new TopoDS_Shape[shapes.size()])); + for (TopoDS_Shape shape : shapes) { + shape.delete(); + } + } +// shapes.clear(); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + public Map getParameterMap() { + return Collections.unmodifiableMap(currentParameters); + } + + public Map getCalculatedParameters() { + return calculatedParameters; + } + + public void setParametersUpdated(boolean parametersUpdated) { + this.parametersUpdated = parametersUpdated; + } + + public void setParameterMap(Map parameters) { + for (String id : parameters.keySet()) { + Object currentValue = currentParameters.get(id); + Object newValue = parameters.get(id); + if (currentValue == newValue) + continue; + if (currentValue instanceof Double) { + if (Math.abs((Double)currentValue-(Double)newValue) < MathTools.NEAR_ZERO) + continue; + } + currentParameters.put(id, newValue); + parametersUpdated = true; + firePropertyChanged(id); + } + } + + private SolidModelProvider solidModelProvider; + + @RelatedGetObj(Plant3D.URIs.hasGeometry) + public SolidModelProvider getGeometry() { + return solidModelProvider; + } + + @RelatedSetObj(Plant3D.URIs.hasGeometry) + public void setGeometry(final SolidModelProvider provider) { + if (provider != null && provider.equals(solidModelProvider)) + return; + + if (solidModelProvider != null) { + deleteData(); + } + solidModelProvider = provider; + firePropertyChanged(Plant3D.URIs.hasGeometry); + } + + private void deleteData() { + solidModelProvider = null; + if (solidObject != null) { + solidObject.clearActors(); + solidObject = null; + } + if (solidModel != null) { + solidModel.delete(); + solidModel = null; + } + } + + @Override + public Collection getActors() { + List list = new ArrayList(); + if (solidObject != null) + list.addAll(solidObject.getActors()); + return list; + } + + @Override + public void stopVisualize() { + if (solidObject != null) { + solidObject.clearActorsAWT(); + solidObject = null; + } + if (solidModel != null) { + solidModel.delete(); + solidModel = null; + } + + } + + private boolean selected = false; + private boolean hover = false; + + @Override + public void highlight(HighlightEventType type) { + if (type == HighlightEventType.Selection || type == HighlightEventType.ClearSelection) { + selected = type == HighlightEventType.Selection; +// hingeA.visualizeSolid(selected,true,false); +// hingeB.visualizeSolid(selected,true,false); + updateVisuals(true, false); +// update(null); + } else { + hover = type == HighlightEventType.Hover; + updateVisuals(false, true); + } + + + } + + protected double[] getSelectedColor() { + return new double[]{1,0,0}; + } + + protected double[] getColor() { + return new double[]{1,1,0}; + } + + private void updateVisuals(boolean s, boolean h) { + if (solidObject != null) { + if (s) { + double color[]; + if (selected) { + color = getSelectedColor(); + + } else { + color = getColor(); + + } + for (vtkProp3D prop : solidObject.getSolid()) { + vtkProperty property = ((vtkActor)prop).GetProperty(); + property.SetColor(color); + property.Delete(); + } + } + if (h) { + double color[] = new double[]{0,0,0}; + if (hover) + color = new double[]{1,0,1}; + for (vtkProp3D prop : solidObject.getEdges()) { + vtkProperty property = ((vtkActor)prop).GetProperty(); + property.SetColor(color); + property.Delete(); + } + + } + } else { +// if (s) { +// axes.addToRenderer(); +// axes.setAxesVisibility(selected); +// } + } + } + + public void update(vtkRenderer ren) { + vtkUtil.updateTransform(getActors(), getWorldPosition(), getWorldOrientation()); + } + + public TopoDS_Shape getSolidModel() { + return solidModel; + } +} diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/IP3DNode.java b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/IP3DNode.java new file mode 100644 index 00000000..56086afc --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/IP3DNode.java @@ -0,0 +1,11 @@ +package org.simantics.plant3d.scenegraph; + +import org.simantics.g3d.scenegraph.IG3DNode; + +import vtk.vtkRenderer; + +public interface IP3DNode extends IG3DNode { + + public void update(vtkRenderer ren); + +} diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/IP3DVisualNode.java b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/IP3DVisualNode.java new file mode 100644 index 00000000..ff568b5c --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/IP3DVisualNode.java @@ -0,0 +1,19 @@ +package org.simantics.plant3d.scenegraph; + +import java.util.Collection; + +import vtk.vtkPanel; +import vtk.vtkProp3D; +import vtk.vtkRenderer; + +public interface IP3DVisualNode extends IP3DNode { + public String getName(); + public void setName(String name); + + public void visualize(vtkPanel panel); + public void stopVisualize(); + + public void update(vtkRenderer ren); + + public Collection getActors(); +} diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/InlineComponent.java b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/InlineComponent.java new file mode 100644 index 00000000..88b1fab3 --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/InlineComponent.java @@ -0,0 +1,81 @@ +package org.simantics.plant3d.scenegraph; + +import java.util.HashMap; +import java.util.Map; + +import org.simantics.g3d.scenegraph.base.ParentNode; +import org.simantics.objmap.graph.annotations.DynamicGraphType; +import org.simantics.objmap.graph.annotations.GetType; +import org.simantics.objmap.graph.annotations.SetType; +import org.simantics.plant3d.ontology.Plant3D; +import org.simantics.plant3d.scenegraph.controlpoint.ControlPointFactory; +import org.simantics.plant3d.scenegraph.controlpoint.PipeControlPoint; + +@DynamicGraphType(Plant3D.URIs.InlineComponent) +public class InlineComponent extends PipelineComponent { + + private String type; + private PipeControlPoint controlPoint; + + @GetType(Plant3D.URIs.InlineComponent) + public String getType() { + return type; + } + + @SetType(Plant3D.URIs.InlineComponent) + public void setType(String type) throws Exception{ + this.type = type; + controlPoint = ControlPointFactory.create(this); + + } + + @Override + public PipeControlPoint getControlPoint() { + return controlPoint; + } + + @Override + public void setParent(ParentNode parent, String name) { + super.setParent(parent, name); + setPipeRun((PipeRun)parent); + } + + public boolean isVariableLength() { + return !controlPoint.isFixed(); + } + + @Override + public void updateParameters() { + super.updateParameters(); + if (!isVariableLength()) { + Map calculated = getCalculatedParameters(); + if (calculated.containsKey("length")) { + controlPoint.setLength((Double)calculated.get("length")); + } + } + } + + @Override + public Map updateParameterMap() { + Map map = new HashMap(); + if (controlPoint != null) { + if (!Double.isNaN(controlPoint.getLength())) + map.put("length", controlPoint.getLength()); + if (controlPoint.isDualInline()) { + PipeControlPoint sub = controlPoint.getSubPoint().get(0); + PipeRun pipeRun = sub.getPipeRun(); + if (pipeRun != null) { + map.put("radius2", pipeRun.getPipeDiameter() * 0.5); + } + } + } + + PipeRun pipeRun = getPipeRun(); + if (pipeRun != null) { + map.put("radius", pipeRun.getPipeDiameter() * 0.5); + } + return map; + } + + +} diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/Nozzle.java b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/Nozzle.java new file mode 100644 index 00000000..9c4ad6f6 --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/Nozzle.java @@ -0,0 +1,153 @@ +package org.simantics.plant3d.scenegraph; + +import java.util.HashMap; +import java.util.Map; + +import javax.vecmath.Quat4d; +import javax.vecmath.Vector3d; + +import org.simantics.g3d.property.annotations.GetPropertyValue; +import org.simantics.objmap.graph.annotations.DynamicGraphType; +import org.simantics.objmap.graph.annotations.GetType; +import org.simantics.objmap.graph.annotations.RelatedGetObj; +import org.simantics.objmap.graph.annotations.RelatedGetValue; +import org.simantics.objmap.graph.annotations.RelatedSetObj; +import org.simantics.objmap.graph.annotations.RelatedSetValue; +import org.simantics.objmap.graph.annotations.SetType; +import org.simantics.plant3d.ontology.Plant3D; +import org.simantics.plant3d.scenegraph.controlpoint.ControlPointFactory; +import org.simantics.plant3d.scenegraph.controlpoint.PipeControlPoint; + + +@DynamicGraphType(Plant3D.URIs.Nozzle) +public class Nozzle extends PipelineComponent { + + private String type; + private PipeControlPoint controlPoint; + + @GetType(Plant3D.URIs.Nozzle) + public String getType() { + return type; + } + + @SetType(Plant3D.URIs.Nozzle) + public void setType(String type) throws Exception{ + this.type = type; + _createCP(); + + } + + private int id = 0; + + @RelatedGetValue(Plant3D.URIs.HasNozzleId) + @GetPropertyValue(name="Nozzle ID", value=Plant3D.URIs.HasNozzleId, tabId="Default") + public int getNozzleId() { + return id; + } + + @RelatedSetValue(Plant3D.URIs.HasNozzleId) + public void setNozzleId(int id) { + if (id == this.id) + return; + this.id = id; + firePropertyChanged(Plant3D.URIs.HasNozzleId); + } + + private void _createCP() throws Exception{ + if (controlPoint != null) + return; + if (getPipeRun() != null) { + controlPoint = ControlPointFactory.create(this); + // TODO : these should not be needed. + controlPoint.setDeletable(false); + controlPoint.setFixed(true); + } + } + + @RelatedSetObj(Plant3D.URIs.HasPipeRun) + @Override + public void setPipeRun(PipeRun pipeRun) { + super.setPipeRun(pipeRun); + try { + _createCP(); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + firePropertyChanged(Plant3D.URIs.HasPipeRun); + } + + @RelatedGetObj(Plant3D.URIs.HasPipeRun) + @Override + public PipeRun getPipeRun() { + return super.getPipeRun(); + } + + @Override + public PipeControlPoint getControlPoint() { + return controlPoint; + } + + + @Override + public void setPosition(Vector3d position) { + super.setPosition(position); + updateCP(); + } + + @Override + public void setOrientation(Quat4d orientation) { + super.setOrientation(orientation); + updateCP(); + } + + private void updateCP() { + if (controlPoint == null) + return; + if (controlPoint.getPipeRun() == null) + return; + controlPoint._setWorldPosition(getWorldPosition()); + controlPoint._setWorldOrientation(getWorldOrientation()); + } + + + @Override + public Map updateParameterMap() { + Map map = new HashMap(); + + PipeRun pipeRun = getPipeRun(); + if (pipeRun != null) { + map.put("length", pipeRun.getPipeDiameter() * 2.0); + map.put("radius", pipeRun.getPipeDiameter() * 0.5); + } + return map; + } + + @Override + protected double[] getColor() { + return new double[]{0.7,0.7,0.7}; + } + + @Override + protected double[] getSelectedColor() { + return new double[]{0.5,0,0.5}; + } + + public boolean isConnected() { + PipeControlPoint pcp = getControlPoint(); + return (pcp.getNext() != null || pcp.getPrevious() != null); + } + + public boolean isNextConnected() { + PipeControlPoint pcp = getControlPoint(); + return (pcp.getNext() != null); + } + + public boolean isPrevConnected() { + PipeControlPoint pcp = getControlPoint(); + return (pcp.getNext() != null); + } + + +} diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/P3DNode.java b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/P3DNode.java new file mode 100644 index 00000000..84e1535e --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/P3DNode.java @@ -0,0 +1,34 @@ +package org.simantics.plant3d.scenegraph; + +import org.simantics.g3d.property.annotations.GetPropertyValue; +import org.simantics.g3d.property.annotations.SetPropertyValue; +import org.simantics.g3d.scenegraph.G3DNode; +import org.simantics.layer0.Layer0; +import org.simantics.objmap.graph.annotations.RelatedGetValue; +import org.simantics.objmap.graph.annotations.RelatedSetValue; + +public abstract class P3DNode extends G3DNode implements IP3DVisualNode { + private String name; + + + @RelatedGetValue(Layer0.URIs.HasName) + @GetPropertyValue(value = Layer0.URIs.HasName, tabId = "Default", name = "Name") + public String getName() { + return name; + } + + @RelatedSetValue(Layer0.URIs.HasName) + @SetPropertyValue(Layer0.URIs.HasName) + public void setName(String name) { + if (name == null) + return; + this.name = name; + firePropertyChanged(Layer0.URIs.HasName); + } + + @Override + public String toString() { + return getName(); + } + +} diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/P3DParentGeometryNode.java b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/P3DParentGeometryNode.java new file mode 100644 index 00000000..c7492008 --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/P3DParentGeometryNode.java @@ -0,0 +1,235 @@ +package org.simantics.plant3d.scenegraph; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.jcae.opencascade.jni.TopoDS_Shape; +import org.simantics.g3d.math.MathTools; +import org.simantics.g3d.scenegraph.NodeHighlighter; +import org.simantics.g3d.vtk.utils.vtkUtil; +import org.simantics.objmap.graph.annotations.RelatedGetObj; +import org.simantics.objmap.graph.annotations.RelatedSetObj; +import org.simantics.opencascade.OccTriangulator; +import org.simantics.opencascade.ParametricSolidModelProvider; +import org.simantics.opencascade.SolidModelProvider; +import org.simantics.opencascade.vtk.vtkSolidObject; +import org.simantics.plant3d.ontology.Plant3D; + +import vtk.vtkActor; +import vtk.vtkPanel; +import vtk.vtkProp3D; +import vtk.vtkProperty; +import vtk.vtkRenderer; + +public class P3DParentGeometryNode extends P3DParentNode implements ParameterizedNode, NodeHighlighter{ + private TopoDS_Shape solidModel; + private vtkSolidObject solidObject; + + private Map currentParameters; + private Map calculatedParameters; + + private boolean parametersUpdated = true; + + + public P3DParentGeometryNode() { + currentParameters = new HashMap(); + calculatedParameters = new HashMap(); + } + + @Override + public void visualize(vtkPanel ren) { + if (solidModelProvider != null) { + + updateParameters(); + + if (solidModel == null || parametersUpdated) { + createGeometry(); + } + } + if ((solidObject == null || parametersUpdated) && solidModel != null) { + solidObject = new vtkSolidObject(ren, solidModel); + } + if (solidObject != null) { + solidObject.visualizeSolid(true,true, false,false); + updateVisuals(true, true); + } + parametersUpdated = false; + + } + + public void updateParameters() { + if (solidModelProvider instanceof ParametricSolidModelProvider) { + ((ParametricSolidModelProvider)solidModelProvider).setProperties(currentParameters); + ((ParametricSolidModelProvider)solidModelProvider).updateCalculatedProperties(calculatedParameters); + } + } + + private void createGeometry() { + Collection shapes; + try { + shapes = solidModelProvider.getModel(); + if (shapes.size() == 1) { + solidModel = shapes.iterator().next(); + } else { + solidModel = OccTriangulator.makeCompound(shapes.toArray(new TopoDS_Shape[shapes.size()])); + for (TopoDS_Shape shape : shapes) { + shape.delete(); + } + } +// shapes.clear(); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + + + public Map getParameterMap() { + return Collections.unmodifiableMap(currentParameters); + } + + public void setParameterMap(Map parameters) { + for (String id : parameters.keySet()) { + Object currentValue = currentParameters.get(id); + Object newValue = parameters.get(id); + if (currentValue == newValue) + continue; + if (currentValue instanceof Double) { + if (Math.abs((Double)currentValue-(Double)newValue) < MathTools.NEAR_ZERO) + continue; + } + currentParameters.put(id, newValue); + parametersUpdated = true; + firePropertyChanged(id); + } + } + + + private SolidModelProvider solidModelProvider; + + @RelatedGetObj(Plant3D.URIs.hasGeometry) + public SolidModelProvider getGeometry() { + return solidModelProvider; + } + + @RelatedSetObj(Plant3D.URIs.hasGeometry) + public void setGeometry(final SolidModelProvider provider) { + if (provider != null && provider.equals(solidModelProvider)) + return; + + if (solidModelProvider != null) { + deleteData(); + } + solidModelProvider = provider; + firePropertyChanged(Plant3D.URIs.hasGeometry); + } + + private void deleteData() { + solidModelProvider = null; + if (solidObject != null) { + solidObject.clearActors(); + solidObject = null; + } + if (solidModel != null) { + solidModel.delete(); + solidModel = null; + } + } + + @Override + public Collection getActors() { + List list = new ArrayList(); + if (solidObject != null) + list.addAll(solidObject.getActors()); + return list; + } + + @Override + public void stopVisualize() { + if (solidObject != null) { + solidObject.clearActorsAWT(); + solidObject = null; + } + if (solidModel != null) { + solidModel.delete(); + solidModel = null; + } + + } + + private boolean selected = false; + private boolean hover = false; + + @Override + public void highlight(HighlightEventType type) { + if (type == HighlightEventType.Selection || type == HighlightEventType.ClearSelection) { + selected = type == HighlightEventType.Selection; +// hingeA.visualizeSolid(selected,true,false); +// hingeB.visualizeSolid(selected,true,false); + updateVisuals(true, false); +// update(null); + } else { + hover = type == HighlightEventType.Hover; + updateVisuals(false, true); + } + + + } + + protected double[] getSelectedColor() { + return new double[]{1,0,0}; + } + + protected double[] getColor() { + return new double[]{1,1,0}; + } + + private void updateVisuals(boolean s, boolean h) { + if (solidObject != null) { + if (s) { + double color[]; + if (selected) { + color = getSelectedColor(); + + } else { + color = getColor(); + + } + for (vtkProp3D prop : solidObject.getSolid()) { + vtkProperty property = ((vtkActor)prop).GetProperty(); + property.SetColor(color); + property.Delete(); + } + } + if (h) { + double color[] = new double[]{0,0,0}; + if (hover) + color = new double[]{1,0,1}; + for (vtkProp3D prop : solidObject.getEdges()) { + vtkProperty property = ((vtkActor)prop).GetProperty(); + property.SetColor(color); + property.Delete(); + } + + } + } else { +// if (s) { +// axes.addToRenderer(); +// axes.setAxesVisibility(selected); +// } + } + } + + public void update(vtkRenderer ren) { + vtkUtil.updateTransform(getActors(), getWorldPosition(), getWorldOrientation()); + } + + public TopoDS_Shape getSolidModel() { + return solidModel; + } +} diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/P3DParentNode.java b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/P3DParentNode.java new file mode 100644 index 00000000..08c289da --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/P3DParentNode.java @@ -0,0 +1,194 @@ +package org.simantics.plant3d.scenegraph; + +import java.util.HashSet; +import java.util.Set; + +import javax.vecmath.Quat4d; +import javax.vecmath.Vector3d; + +import org.simantics.g3d.math.MathTools; +import org.simantics.g3d.ontology.G3D; +import org.simantics.g3d.property.annotations.GetPropertyValue; +import org.simantics.g3d.property.annotations.PropertyContributor; +import org.simantics.g3d.property.annotations.SetPropertyValue; +import org.simantics.g3d.scenegraph.IG3DNode; +import org.simantics.g3d.scenegraph.base.ParentNode; +import org.simantics.g3d.tools.NodeTools; +import org.simantics.layer0.Layer0; +import org.simantics.objmap.graph.annotations.RelatedGetValue; +import org.simantics.objmap.graph.annotations.RelatedSetValue; + +@PropertyContributor +public abstract class P3DParentNode extends ParentNode implements IP3DVisualNode { + + private String name; + + + + + @RelatedGetValue(Layer0.URIs.HasName) + @GetPropertyValue(value = Layer0.URIs.HasName, tabId = "Default", name = "Name") + public String getName() { + return name; + } + + @RelatedSetValue(Layer0.URIs.HasName) + @SetPropertyValue(Layer0.URIs.HasName) + public void setName(String name) { + if (name == null) + return; + this.name = name; + firePropertyChanged(Layer0.URIs.HasName); + } + + @Override + public String toString() { + return getName(); + } + + private Vector3d position = new Vector3d(); + private Quat4d orientation = MathTools.getIdentityQuat(); + + @Override + @GetPropertyValue(value = G3D.URIs.hasOrientation, tabId = "Transform", name = "Orientation") + public Quat4d getOrientation() { + return orientation; + } + + @RelatedGetValue(G3D.URIs.hasOrientation) + public double[] getOrientationArr() { + double arr[] = new double[4]; + orientation.get(arr); + return arr; + + } + + @Override + @GetPropertyValue(value = G3D.URIs.hasPosition, tabId = "Transform", name = "Position") + public Vector3d getPosition() { + return position; + } + + @RelatedGetValue(G3D.URIs.hasPosition) + public double[] getPositionArr() { + double arr[] = new double[3]; + position.get(arr); + return arr; + } + + @Override + @SetPropertyValue(G3D.URIs.hasOrientation) + public void setOrientation(Quat4d orientation) { + assert(orientation != null); + this.orientation = orientation; + + firePropertyChanged(G3D.URIs.hasOrientation); + } + + @Override + @SetPropertyValue(G3D.URIs.hasPosition) + public void setPosition(Vector3d position) { + assert(position != null); + this.position = position; + + firePropertyChanged(G3D.URIs.hasPosition); + } + + @RelatedSetValue(G3D.URIs.hasOrientation) + public void setOrientation(double[] arr) { + if (arr == null) + return; + setOrientation(new Quat4d(arr)); + } + + @RelatedSetValue(G3D.URIs.hasPosition) + public void setPosition(double[] arr) { + if (arr == null) + return; + setPosition(new Vector3d(arr)); + } + + @Override + @GetPropertyValue(value = G3D.URIs.hasWorldPosition, tabId = "Transform", name = "World Position") + public Vector3d getWorldPosition() { + IG3DNode parent = (IG3DNode)getParent(); + if (parent == null) + return position; + return NodeTools.getWorldPosition(parent, new Vector3d(position)); + } + + + public Vector3d getWorldPosition(Vector3d localPosition) { + return NodeTools.getWorldPosition(this,localPosition); + } + + + @Override + @GetPropertyValue(value = G3D.URIs.hasWorldOrientation, tabId = "Transform", name = "World Orientation") + public Quat4d getWorldOrientation() { + return getWorldOrientation(new Quat4d(orientation)); + } + + public Quat4d getWorldOrientation(Quat4d localOrientation) { + IG3DNode parent = (IG3DNode)getParent(); + if (parent == null) + return localOrientation; + return NodeTools.getWorldOrientation(parent, localOrientation); + } + + @Override + public Vector3d getLocalPosition(Vector3d worldPosition) { + IG3DNode parent = (IG3DNode)getParent(); + if (parent == null) + return worldPosition; + return NodeTools.getLocalPosition(parent,new Vector3d(worldPosition)); + } + + @Override + public Quat4d getLocalOrientation(Quat4d worldOrientation) { + IG3DNode parent = (IG3DNode)getParent(); + if (parent == null) + return worldOrientation; + return NodeTools.getLocalOrientation(parent, new Quat4d(worldOrientation)); + } + + @Override + @SetPropertyValue(G3D.URIs.hasWorldPosition) + public void setWorldPosition(Vector3d position) { + Vector3d localPos = getLocalPosition(position); + setPosition(localPos); + } + + @Override + @SetPropertyValue(G3D.URIs.hasWorldOrientation) + public void setWorldOrientation(Quat4d orientation) { + Quat4d localOr = getLocalOrientation(orientation); + setOrientation(localOr); + } + + @Override + public Object getAdapter(Class adapter) { + if (IG3DNode.class == adapter) + return this; + return null; + } + + public String getUniqueName(String prefix) { + Set names = new HashSet(); + for (IP3DNode node : getNodes()) { + if (!(node instanceof IP3DVisualNode)) + continue; + IP3DVisualNode n = (IP3DVisualNode)node; + names.add(n.getName()); + } + int i = 1; + while (true) { + String genName = prefix + "_" + i; + if (!names.contains(genName)) + return genName; + i++; + } + } + + +} diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/P3DRootNode.java b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/P3DRootNode.java new file mode 100644 index 00000000..5a968604 --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/P3DRootNode.java @@ -0,0 +1,170 @@ +package org.simantics.plant3d.scenegraph; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +import javax.vecmath.Quat4d; +import javax.vecmath.Vector3d; + +import org.simantics.g3d.math.MathTools; +import org.simantics.g3d.scenegraph.IG3DNode; +import org.simantics.g3d.scenegraph.NodeMap; +import org.simantics.g3d.scenegraph.NodeMapProvider; +import org.simantics.g3d.scenegraph.base.INode; +import org.simantics.g3d.scenegraph.base.NodeException; +import org.simantics.g3d.scenegraph.base.ParentNode; +import org.simantics.objmap.graph.annotations.GraphType; +import org.simantics.objmap.graph.annotations.RelatedElementsAdd; +import org.simantics.objmap.graph.annotations.RelatedElementsGet; +import org.simantics.objmap.graph.annotations.RelatedElementsRem; +import org.simantics.plant3d.editor.P3DNodeMap; +import org.simantics.plant3d.ontology.Plant3D; + +import vtk.vtkProp; + +@GraphType(Plant3D.URIs.Plant) +public class P3DRootNode extends ParentNode implements IG3DNode, NodeMapProvider { + + + @RelatedElementsAdd(Plant3D.URIs.childen) + public void addChild(IP3DVisualNode node) { + addNode(Plant3D.URIs.childen,node); + } + + @RelatedElementsGet(Plant3D.URIs.childen) + public Collection getChild() { + return getNodes(Plant3D.URIs.childen); + } + + @RelatedElementsRem(Plant3D.URIs.childen) + public void remChild(IP3DNode node) { + removeNode(Plant3D.URIs.childen, node); + } + + private P3DNodeMap nodeMap; + + public void setNodeMap(P3DNodeMap nodeMap) { + this.nodeMap = nodeMap; + } + + @Override + public NodeMap getNodeMap() { + return nodeMap; + } + + @Override + public ParentNode getParent() { + return null; + } + + @Override + public ParentNode getRootNode() { + return this; + } + + public javax.vecmath.Quat4d getOrientation() { + return MathTools.getIdentityQuat(); + }; + + @Override + public Vector3d getPosition() { + return new Vector3d(); + } + + @Override + public Quat4d getWorldOrientation() { + return MathTools.getIdentityQuat(); + } + + @Override + public Vector3d getWorldPosition() { + return new Vector3d(); + } + + @Override + public Quat4d getWorldOrientation(Quat4d localOrientation) { + return localOrientation; + } + + @Override + public Vector3d getWorldPosition(Vector3d localPosition) { + return localPosition; + } + + @Override + public Quat4d getLocalOrientation(Quat4d worldOrientation) { + return worldOrientation; + } + + @Override + public Vector3d getLocalPosition(Vector3d worldPosition) { + return worldPosition; + } + + @Override + public void setPosition(Vector3d position) { + throw new NodeException("Cannot set root node position"); + } + + @Override + public void setOrientation(Quat4d orientation) { + throw new NodeException("Cannot set root node orientation"); + } + + @Override + public void setWorldOrientation(Quat4d orientation) { + throw new NodeException("Cannot set root node orientation"); + } + + @Override + public void setWorldPosition(Vector3d position) { + throw new NodeException("Cannot set root node orientation"); + } + + public String getUniqueName(String prefix) { + Set names = new HashSet(); + for (INode node : getChild()) { + if (!(node instanceof IP3DVisualNode)) + continue; + IP3DVisualNode n = (IP3DVisualNode)node; + names.add(n.getName()); + } + int i = 1; + while (true) { + String genName = prefix + "_" + i; + if (!names.contains(genName)) + return genName; + i++; + } + } + + + @SuppressWarnings("rawtypes") + @Override + public Object getAdapter(Class adapter) { + if (NodeMap.class == adapter) + return nodeMap; + return null; + } + + public Nozzle createNozzle() { + return new Nozzle(); + } + + public Equipment createEquipment() { + return new Equipment(); + } + + public InlineComponent createInline() { + return new InlineComponent(); + } + + public EndComponent createEnd() { + return new EndComponent(); + } + + public TurnComponent createTurn() { + return new TurnComponent(); + } +} diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/ParameterizedNode.java b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/ParameterizedNode.java new file mode 100644 index 00000000..7aa0e808 --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/ParameterizedNode.java @@ -0,0 +1,14 @@ +package org.simantics.plant3d.scenegraph; + +import java.util.Map; +import java.util.Set; + +import org.simantics.g3d.scenegraph.IG3DNode; + +public interface ParameterizedNode extends IG3DNode { + + + public Map getParameterMap(); + public void setParameterMap(Map parameters); + +} diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/PipeRun.java b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/PipeRun.java new file mode 100644 index 00000000..2932f1d2 --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/PipeRun.java @@ -0,0 +1,161 @@ +package org.simantics.plant3d.scenegraph; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import org.simantics.g3d.math.MathTools; +import org.simantics.g3d.property.annotations.GetPropertyValue; +import org.simantics.g3d.property.annotations.PropertyTabBlacklist; +import org.simantics.g3d.property.annotations.SetPropertyValue; +import org.simantics.g3d.scenegraph.IG3DNode; +import org.simantics.objmap.graph.annotations.GraphType; +import org.simantics.objmap.graph.annotations.RelatedElementsAdd; +import org.simantics.objmap.graph.annotations.RelatedElementsGet; +import org.simantics.objmap.graph.annotations.RelatedElementsRem; +import org.simantics.objmap.graph.annotations.RelatedGetValue; +import org.simantics.objmap.graph.annotations.RelatedSetValue; +import org.simantics.plant3d.ontology.Plant3D; +import org.simantics.plant3d.scenegraph.controlpoint.PipeControlPoint; + +import vtk.vtkPanel; +import vtk.vtkProp3D; +import vtk.vtkRenderer; + +@GraphType(Plant3D.URIs.PipeRun) +@PropertyTabBlacklist("Transform") +public class PipeRun extends P3DParentNode { + + private double pipeDiameter = 0.1; + private double turnRadius = 0.2; + + @Override + public void update(vtkRenderer ren) { + + } + + @Override + public void visualize(vtkPanel panel) { + + } + + @Override + public Collection getActors() { + return Collections.EMPTY_LIST; + } + + @Override + public void stopVisualize() { + + } + + @RelatedGetValue(Plant3D.URIs.HasTurnRadius) + @GetPropertyValue(value=Plant3D.URIs.HasTurnRadius, name = "Elbow radius") + public double getTurnRadius() { + return turnRadius; + } + + @RelatedSetValue(Plant3D.URIs.HasTurnRadius) + @SetPropertyValue(Plant3D.URIs.HasTurnRadius) + public void setTurnRadius(double turnRadius) { + this.turnRadius = turnRadius; + firePropertyChanged(Plant3D.URIs.HasTurnRadius); + } + + @RelatedGetValue(Plant3D.URIs.HasPipeDiameter) + @GetPropertyValue(value=Plant3D.URIs.HasPipeDiameter, name = "Diameter") + public double getPipeDiameter() { + return pipeDiameter; + } + + @RelatedSetValue(Plant3D.URIs.HasPipeDiameter) + @SetPropertyValue(Plant3D.URIs.HasPipeDiameter) + public void setPipeDiameter(double pipeDiameter) { + this.pipeDiameter = pipeDiameter; + firePropertyChanged(Plant3D.URIs.HasPipeDiameter); + } + + @RelatedElementsAdd(Plant3D.URIs.childen) + public void addChild(PipelineComponent node) { + addNode(Plant3D.URIs.childen,node); + } + + @RelatedElementsGet(Plant3D.URIs.childen) + public Collection getChild() { + Collection coll = new ArrayList(); + for (IG3DNode n : getNodes(Plant3D.URIs.childen)) { + coll.add((PipelineComponent)n); + } + return coll; + } + + @RelatedElementsRem(Plant3D.URIs.childen) + public void remChild(PipelineComponent node) { + removeNode(Plant3D.URIs.childen, node); + } + + + public List getSortedChild() { + List coll = new ArrayList(); + for (IG3DNode n : getNodes(Plant3D.URIs.childen)) { + coll.add((PipelineComponent)n); + } + Collections.sort(coll, new ComponentComparator()); + return coll; + } + public void addChild(PipeControlPoint node) { + addNode("pipecp",node); + } + + public void remChild(PipeControlPoint node) { + removeNode("pipecp", node); + } + + public void deattachChild(PipeControlPoint node) { + deattachNode("pipecp", node); + } + + public Collection getControlPoints() { + Collection coll = new ArrayList(); + for (IG3DNode n : getNodes("pipecp")) { + coll.add((PipeControlPoint)n); + } + return coll; + } + + public boolean equalSpecs(PipeRun other) { + if (!MathTools.equals(pipeDiameter,other.pipeDiameter)) + return false; + if (!MathTools.equals(turnRadius,other.turnRadius)) + return false; + return true; + } + + private class ComponentComparator implements Comparator { + @Override + public int compare(PipelineComponent o1, PipelineComponent o2) { + if (o1 == o2) + return 0; + int i = 1; + PipelineComponent c = o1.getPrevious(); + while (c != null) { + if (c == o2) + return i; + c = c.getPrevious(); + i++; + } + i = -1; + c = o1.getNext(); + while (c != null) { + if (c == o2) + return i; + c = c.getNext(); + i--; + } + return 0; + + } + } +} diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/PipelineComponent.java b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/PipelineComponent.java new file mode 100644 index 00000000..8fe597ca --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/PipelineComponent.java @@ -0,0 +1,394 @@ +package org.simantics.plant3d.scenegraph; + +import java.util.Collections; +import java.util.Map; + +import javax.vecmath.Quat4d; +import javax.vecmath.Tuple3d; +import javax.vecmath.Vector3d; + +import org.simantics.g3d.math.MathTools; +import org.simantics.g3d.property.annotations.GetPropertyValue; +import org.simantics.g3d.property.annotations.PropertyContributor; +import org.simantics.objmap.graph.annotations.RelatedGetObj; +import org.simantics.objmap.graph.annotations.RelatedSetObj; +import org.simantics.plant3d.ontology.Plant3D; +import org.simantics.plant3d.scenegraph.controlpoint.PipeControlPoint; +import org.simantics.plant3d.scenegraph.controlpoint.PipeControlPoint.Type; +import org.simantics.plant3d.scenegraph.controlpoint.PipingRules; + +/** + * + * @author Marko Luukkainen + * + */ +@PropertyContributor +public abstract class PipelineComponent extends GeometryNode { + + + private PipeRun pipeRun; + private PipeRun alternativePipeRun; + private PipelineComponent next; + private PipelineComponent previous; + + /** + * Sets the pipe run. + * + * With in-line,turn, and end components, the pipe run is the parent object in the scene-graph. + * With nozzles, the pipe run setting is explicit (nozzle has to be linked to the piperun, since the parent object is equipment). + * With size change components (in-line), there is also alternative pipe run, which must match the next component's pipe run. + * + * @param pipeRun + */ + public void setPipeRun(PipeRun pipeRun) { + if (pipeRun == this.pipeRun) + return; + this.pipeRun = pipeRun; + if (getControlPoint() != null) { + getControlPoint().deattach(); + if (pipeRun != null) { + pipeRun.addChild(getControlPoint()); + } + } + updateParameters(); + } + + @RelatedGetObj(Plant3D.URIs.HasAlternativePipeRun) + public PipeRun getAlternaitvePipeRun() { + return alternativePipeRun; + } + + @RelatedSetObj(Plant3D.URIs.HasAlternativePipeRun) + public void setAlternativePipeRun(PipeRun pipeRun) { + if (this.alternativePipeRun == pipeRun) + return; + this.alternativePipeRun = pipeRun; + if (getControlPoint().isDualInline()) { + PipeControlPoint sub = getControlPoint().getSubPoint().get(0); + if (sub.getParent() != this.alternativePipeRun) + this.alternativePipeRun.addChild(sub); + } + firePropertyChanged(Plant3D.URIs.HasAlternativePipeRun); + } + + @Override + public void updateParameters() { + setParameterMap(updateParameterMap()); + super.updateParameters(); + } + + public abstract void setType(String typeURI) throws Exception; + + @RelatedGetObj(Plant3D.URIs.HasNext) + public PipelineComponent getNext() { + return next; + } + + @RelatedSetObj(Plant3D.URIs.HasNext) + public void setNext(PipelineComponent comp) { + if (next == comp) + return; + this.next = comp; + syncNext(); + firePropertyChanged(Plant3D.URIs.HasNext); + if (comp != null) + comp.sync(); +// System.out.println(this + " next " + comp); + } + + + @RelatedGetObj(Plant3D.URIs.HasPrevious) + public PipelineComponent getPrevious() { + return previous; + } + + @RelatedSetObj(Plant3D.URIs.HasPrevious) + public void setPrevious(PipelineComponent comp) { + if (previous == comp) + return; + this.previous = comp; + + firePropertyChanged(Plant3D.URIs.HasPrevious); + if (comp != null) + comp.sync(); +// System.out.println(this + " prev " + comp); + } + private PipelineComponent branch0; + + @RelatedGetObj(Plant3D.URIs.HasBranch0) + public PipelineComponent getBranch0() { + return branch0; + } + + @RelatedSetObj(Plant3D.URIs.HasBranch0) + public void setBranch0(PipelineComponent comp) { + if (branch0 == comp) + return; + this.branch0 = comp; + syncBranch0(); + firePropertyChanged(Plant3D.URIs.HasBranch0); + if (comp != null) + comp.sync(); +// System.out.println(this + " next " + comp); + } + + + + private PipeControlPoint getBranchPoint() { + PipeControlPoint branchPoint; + if (getControlPoint().getSubPoint().size() > 0) { + branchPoint = getControlPoint().getSubPoint().get(0); + } else { + if (branch0.getPipeRun() == null) + return null; + branchPoint = new PipeControlPoint(this,branch0.getPipeRun()); + branchPoint.setFixed(false); + branchPoint.setType(Type.END); + branchPoint.parent = getControlPoint(); + getControlPoint().children.add(branchPoint); + branchPoint.setWorldOrientation(getControlPoint().getWorldOrientation()); + branchPoint.setWorldPosition(getControlPoint().getWorldPosition()); + } + return branchPoint; + } + + private boolean _connectNext(PipeControlPoint pcp, PipeControlPoint nextPCP) { + if (nextPCP == null) + return false; + if (pcp.getNext() != nextPCP) { + pcp.setNext(nextPCP); + } + if (pcp.isDualInline()) { + PipeControlPoint sub = pcp.getSubPoint().get(0); + if (sub.getNext() != nextPCP) + sub.setNext(nextPCP); + } + return true; + } + + private boolean _connectPrev(PipeControlPoint pcp, PipeControlPoint prevPCP) { + if (prevPCP == null) + return false; + if (prevPCP.isDualInline()) + prevPCP = prevPCP.getSubPoint().get(0); + if (pcp.getPrevious() != prevPCP) { + pcp.setPrevious(prevPCP); + } + if (pcp.isDualInline()) { + PipeControlPoint sub = pcp.getSubPoint().get(0); + if (sub.getPrevious() != prevPCP) + sub.setPrevious(prevPCP); + } + return true; + } + + + + private boolean syncNext() { + + if (getControlPoint() != null) { + if (next != null ) { + if (next.getControlPoint() != null && next.getPipeRun() != null) { + + // TODO, relying that the other direction is connected. + boolean nxt = next.getPrevious() == this; + boolean br0 = next.getBranch0() == this; + if (nxt){ + return _connectNext(getControlPoint(), next.getControlPoint()); + } else if (br0) { + return _connectNext(getControlPoint(), next.getBranchPoint()); + } + } else { + return false; + } + + } else if (getControlPoint().getPrevious() != null) { + getControlPoint().setNext(null); + } + } else { + return false; + } + return true; + } + + private boolean syncPrevious() { + + if (getControlPoint() != null) { + if (previous != null ) { + if (previous.getControlPoint() != null && previous.getPipeRun() != null) { + + // TODO, relying that the other direction is connected. + boolean prev = previous.getNext() == this; + boolean br0 = previous.getBranch0() == this; + if (prev){ + return _connectPrev(getControlPoint(), previous.getControlPoint()); + } else if (br0) { + return _connectPrev(getControlPoint(), previous.getBranchPoint()); + } + } else { + return false; + } + + } else if (getControlPoint().getPrevious() != null) { + getControlPoint().setPrevious(null); + } + } else { + return false; + } + return true; + } + + private boolean syncBranch0() { + if (getControlPoint() != null) { + if (getControlPoint().isDualInline()) { + branch0 = null; + return false; + } + if (branch0 != null) { + if (branch0.getControlPoint() != null && branch0.getPipeRun() != null) { + PipeControlPoint branchPoint = getBranchPoint(); + PipeControlPoint pcp = branch0.getControlPoint(); + // TODO, relying that the other direction is connected. + boolean next = branch0.getPrevious() == this; // this --> branch0 + boolean prev = branch0.getNext() == this; + if (next) { + _connectNext(branchPoint, pcp); + } else if (prev){ + _connectPrev(branchPoint, pcp); + } + } else { + return false; + } + + } else if (getControlPoint().getSubPoint().size() > 0) { // TODO : this may cause problems? (Removes branch point, before branch has been set?) + getControlPoint().getSubPoint().get(0).remove(); + getControlPoint().children.clear(); + } + } else { + return false; + } + return true; + } + + public void sync() { + syncPrevious(); + syncNext(); + syncBranch0(); + } + + public void sync2() { +// if (getControlPoint().isDualInline()) { +// PipeControlPoint sub = getControlPoint().getSubPoint().get(0); +// next.getControlPoint().getPipeRun().addChild(sub); +// } + getControlPoint()._setWorldOrientation(getWorldOrientation()); + getControlPoint()._setWorldPosition(getWorldPosition()); + } + + public Map updateParameterMap() { + return Collections.EMPTY_MAP; + } + + public PipeRun getPipeRun() { + return pipeRun; + } + + public abstract String getType(); + public abstract PipeControlPoint getControlPoint(); + + @Override + public void remove() { + PipeControlPoint pcp = getControlPoint(); + if (pcp != null) { + pcp.remove(); + } + super.remove(); + } + + @Override + protected double[] getColor() { + if (getControlPoint() == null || !getControlPoint().isFixed()) + return new double[]{0.7,0.7,0.7}; + else + return new double[]{1.0,0.0,0.0}; + } + + @Override + protected double[] getSelectedColor() { + return new double[]{0.5,0,0.5}; + } + + @Override + public void setOrientation(Quat4d orientation) { + if (MathTools.equals(orientation, getOrientation())) + return; + super.setOrientation(orientation); + if (getControlPoint() != null) { + getControlPoint()._setWorldOrientation(getWorldOrientation()); + try { + PipingRules.requestUpdate(getControlPoint()); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + + @Override + public void setPosition(Vector3d position) { + if (MathTools.equals(position, getPosition())) + return; + super.setPosition(position); + if (getControlPoint() != null) { + getControlPoint()._setWorldPosition(getWorldPosition()); + try { + PipingRules.requestUpdate(getControlPoint()); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + + + public void _setWorldPosition(Vector3d position) { + Vector3d localPos = getLocalPosition(position); + super.setPosition(localPos); + } + + public void _setWorldOrientation(Quat4d orientation) { + Quat4d localOr = getLocalOrientation(orientation); + super.setOrientation(localOr); + } + + @GetPropertyValue(name="Flow Length", value="flowlength", tabId = "Default") + public Double getFlowLength() { + PipeControlPoint pcp = getControlPoint(); + if (pcp == null) + return null; + switch (pcp.getType()) { + case INLINE: + return pcp.getLength(); + case END: + return null; + case TURN: { + double r = getPipeRun().getTurnRadius(); + double a = pcp.getTurnAngle(); + return a*r; + } + default: + return null; + } + } + + public void getControlPointEnds(Tuple3d p1, Tuple3d p2) { + getControlPoint().getControlPointEnds(p1, p2); + } + + public Vector3d getNormal() { + Vector3d v = new Vector3d(); + MathTools.rotate(getWorldOrientation(), MathTools.Z_AXIS, v); + return v; + } + +} diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/SchemaBuilder.java b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/SchemaBuilder.java new file mode 100644 index 00000000..761e1707 --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/SchemaBuilder.java @@ -0,0 +1,45 @@ +package org.simantics.plant3d.scenegraph; + +import org.simantics.Simantics; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.request.Read; +import org.simantics.objmap.graph.schema.IMappingSchema; +import org.simantics.objmap.graph.schema.MappingSchemas; +import org.simantics.objmap.graph.schema.SimpleSchema; +import org.simantics.opencascade.SolidModelProvider; +import org.simantics.plant3d.ontology.Plant3D; + +public class SchemaBuilder { + public static IMappingSchema getSchema() throws DatabaseException{ + return Simantics.getSession().syncRequest(new Read>() { + @Override + public IMappingSchema perform(ReadGraph g) + throws DatabaseException { + return getSchema(g); + } + }); + } + + public static IMappingSchema getSchema(ReadGraph g) throws DatabaseException{ + try { + SimpleSchema schema = new SimpleSchema(); + schema.addLinkType(MappingSchemas.fromAnnotations(g, Equipment.class)); + schema.addLinkType(MappingSchemas.fromAnnotations(g, InlineComponent.class)); + schema.addLinkType(MappingSchemas.fromAnnotations(g, TurnComponent.class)); + schema.addLinkType(MappingSchemas.fromAnnotations(g, EndComponent.class)); + schema.addLinkType(MappingSchemas.fromAnnotations(g, Nozzle.class)); + schema.addLinkType(MappingSchemas.fromAnnotations(g, P3DRootNode.class)); + schema.addLinkType(MappingSchemas.fromAnnotations(g, PipeRun.class)); + + schema.addLinkType(MappingSchemas.fromAdaptable(g, Plant3D.URIs.Builtin_GeometryProvider, SolidModelProvider.class)); + return schema; + } catch (IllegalAccessException e) { + throw new DatabaseException(e); + } catch (InstantiationException e) { + throw new DatabaseException(e); + } + } + +} diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/TurnComponent.java b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/TurnComponent.java new file mode 100644 index 00000000..6050b60f --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/TurnComponent.java @@ -0,0 +1,83 @@ +package org.simantics.plant3d.scenegraph; + +import java.util.HashMap; +import java.util.Map; + +import javax.vecmath.Vector3d; + +import org.simantics.g3d.math.MathTools; +import org.simantics.g3d.property.annotations.GetPropertyValue; +import org.simantics.g3d.scenegraph.base.ParentNode; +import org.simantics.objmap.graph.annotations.DynamicGraphType; +import org.simantics.objmap.graph.annotations.GetType; +import org.simantics.objmap.graph.annotations.SetType; +import org.simantics.plant3d.ontology.Plant3D; +import org.simantics.plant3d.scenegraph.controlpoint.ControlPointFactory; +import org.simantics.plant3d.scenegraph.controlpoint.PipeControlPoint; + +@DynamicGraphType(Plant3D.URIs.TurnComponent) +public class TurnComponent extends PipelineComponent { + + + private String type; + private PipeControlPoint controlPoint; + + @GetType(Plant3D.URIs.TurnComponent) + public String getType() { + return type; + } + + @SetType(Plant3D.URIs.TurnComponent) + public void setType(String type) throws Exception{ + this.type = type; + controlPoint = ControlPointFactory.create(this); + } + + @Override + public PipeControlPoint getControlPoint() { + return controlPoint; + } + + @Override + public void setParent(ParentNode parent, String name) { + super.setParent(parent, name); + setPipeRun((PipeRun)parent); + } + + @Override + public Map updateParameterMap() { + Map map = new HashMap(); + + PipeRun pipeRun = getPipeRun(); + if (pipeRun != null) { + map.put("turnRadius", pipeRun.getTurnRadius()); + map.put("radius", pipeRun.getPipeDiameter() * 0.5); + } + if (controlPoint != null && controlPoint.getTurnAngle() != null && !Double.isNaN(controlPoint.getTurnAngle())) { + map.put("turnAngle", controlPoint.getTurnAngle()); + } + return map; + } + + + public Double getTurnAngle() { + return getControlPoint().getTurnAngle(); + } + + @GetPropertyValue(name="Turn Angle", value="turn angle", tabId = "Default") + public Double getTurnAngleDeg() { + Double d = getControlPoint().getTurnAngle(); + if (d == null) + return null; + return MathTools.radToDeg(d); + } + + public Vector3d getTurnAxis() { + return getControlPoint().getTurnAxis(); + } + + @Override + public Vector3d getNormal() { + return getTurnAxis(); + } +} diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/controlpoint/ControlPointFactory.java b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/controlpoint/ControlPointFactory.java new file mode 100644 index 00000000..193cdd27 --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/controlpoint/ControlPointFactory.java @@ -0,0 +1,134 @@ +package org.simantics.plant3d.scenegraph.controlpoint; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.simantics.Simantics; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.request.Read; +import org.simantics.plant3d.ontology.Plant3D; +import org.simantics.plant3d.scenegraph.PipelineComponent; +import org.simantics.plant3d.scenegraph.controlpoint.PipeControlPoint.Type; +import org.simantics.plant3d.utils.Item; +import org.simantics.plant3d.utils.P3DUtil; + +public class ControlPointFactory { + + private static Map cache = new HashMap(); + + + public static void preloadCache() throws Exception { + List items = P3DUtil.getEnds(); + items.addAll(P3DUtil.getInlines()); + items.addAll(P3DUtil.getNozzles()); + items.addAll(P3DUtil.getTurns()); + + for (Item item : items) { + Instruction inst = createInstruction(item.getUri()); + cache.put(item.getUri(), inst); + } + } + + public static PipeControlPoint create(PipelineComponent component) throws Exception { + Instruction inst = cache.get(component.getType()); + if (inst == null) { + inst = createInstruction(component.getType()); + cache.put(component.getType(), inst); + } + if (inst == null) { + return null; + } + + PipeControlPoint pcp = new PipeControlPoint(component); + pcp.setType(inst.type); + pcp.setFixed(inst.fixed); + switch(inst.type) { + case END: + + break; + case INLINE: + if (inst.isOffset || inst.isSizeChange) { + PipeControlPoint sub = new PipeControlPoint(component); + pcp.children.add(sub); + sub.parent = pcp; + sub.setType(inst.type); + sub.setFixed(inst.fixed); + sub.setSub(true); +// pcp.setOffset(0.0); + if (inst.isOffset) + pcp.setOffset(0.0); + } + + break; + case TURN: + + break; + } + return pcp; + } + + + private static class Instruction { + Type type; + boolean fixed; + boolean isOffset; + boolean isSizeChange; + + + } + + private static Instruction createInstruction(final String type) throws Exception { + return Simantics.getSession().syncRequest(new Read() { + @Override + public Instruction perform(ReadGraph graph) throws DatabaseException { + Resource res = graph.getResource(type); + Plant3D p3d = Plant3D.getInstance(graph); + Instruction i = new Instruction(); + i.fixed = false; + i.isOffset = false; + i.isSizeChange = false; + i.type = Type.INLINE; + if (graph.isInheritedFrom(res, p3d.Nozzle)) { + i.fixed = true; + i.isOffset = false; + i.isSizeChange = false; + i.type = Type.END; + } else if (graph.isInheritedFrom(res, p3d.InlineComponent)){ + + i.type = Type.INLINE; + if (graph.hasStatement(res,p3d.VariableLengthInlineComponent)) { + i.fixed = false; + } else if (graph.hasStatement(res,p3d.FixedLengthInlineComponent)) { + i.fixed = true; + } + + if (graph.hasStatement(res,p3d.SizeChangeComponent)) { + i.isSizeChange = true; + } + + if (graph.hasStatement(res,p3d.OffsetComponent)) { + i.isOffset = true; + } + + } else if (graph.isInheritedFrom(res, p3d.TurnComponent)) { + i.type = Type.TURN; + if (graph.hasStatement(res,p3d.VariableAngleTurnComponent)) { + i.fixed = false; + } else if (graph.hasStatement(res,p3d.FixedAngleTurnComponent)) { + i.fixed = true; + } + } else if (graph.isInheritedFrom(res, p3d.EndComponent)) { + i.fixed = false; + i.type = Type.END; + } else { + return null; + } + return i; + } + }); + } + +} diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/controlpoint/PipeControlPoint.java b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/controlpoint/PipeControlPoint.java new file mode 100644 index 00000000..02bce622 --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/controlpoint/PipeControlPoint.java @@ -0,0 +1,1077 @@ +package org.simantics.plant3d.scenegraph.controlpoint; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import javax.vecmath.AxisAngle4d; +import javax.vecmath.Matrix3d; +import javax.vecmath.Quat4d; +import javax.vecmath.Tuple3d; +import javax.vecmath.Vector3d; + +import org.simantics.g3d.math.MathTools; +import org.simantics.g3d.property.annotations.GetPropertyValue; +import org.simantics.g3d.scenegraph.G3DNode; +import org.simantics.plant3d.scenegraph.IP3DNode; +import org.simantics.plant3d.scenegraph.PipeRun; +import org.simantics.plant3d.scenegraph.PipelineComponent; + +import vtk.vtkRenderer; + + +public class PipeControlPoint extends G3DNode implements IP3DNode { + + public enum Type{INLINE,TURN,END}; + public enum Direction{NEXT,PREVIOUS}; + public enum PositionType {SPLIT,NEXT,PREVIOUS,PORT} + + private PipelineComponent component; + + private Type type; + private boolean fixed = true; + private boolean deletable = true; + private boolean sub = false; + + public PipeControlPoint(PipelineComponent component) { + this.component = component; + if (component.getPipeRun() != null) + component.getPipeRun().addChild(this); + + } + + public PipeControlPoint(PipelineComponent component, PipeRun piperun) { + this.component = component; + piperun.addChild(this); + } + + @Override + public void update(vtkRenderer ren) { + try { + PipingRules.requestUpdate(this); + } catch (Exception e) { + e.printStackTrace(); + } + + } + + public PipeRun getPipeRun() { + return (PipeRun)getParent(); + } + + public PipelineComponent getPipelineComponent() { + return component; + } + + public Type getType() { + return type; + } + + public void setType(Type type) { + this.type = type; + } + + @GetPropertyValue(name="Fixed",tabId="Debug",value="fixed") + public boolean isFixed() { + return fixed; + } + + + public void setFixed(boolean fixed) { + this.fixed = fixed; + } + + public void setSub(boolean sub) { + this.sub = sub; + } + + @GetPropertyValue(name="Deletable",tabId="Debug",value="deletable") + public boolean isDeletable() { + return deletable; + } + + public void setDeletable(boolean deletable) { + this.deletable = deletable; + } + + public boolean isPathLegEnd() { + return type != Type.INLINE; + } + + public boolean isEnd() { + return type == Type.END; + } + + public boolean isTurn() { + return type == Type.TURN; + } + + public boolean isInline() { + return type == Type.INLINE; + } + + public boolean isDirected() { + return fixed && isEnd(); + } + + public boolean isNonDirected() { + return !fixed && isEnd(); + } + + public boolean isVariableLength() { + return !fixed && isInline(); + } + + public boolean isVariableAngle() { + return !fixed && isTurn(); + } + + public boolean isBranchEnd() { + return deletable && isEnd(); + } + + public boolean isOffset() { + return offset != null; + } + + public boolean isDualSub() { + return parent != null && sub; + } + + public boolean isDualInline() { + return children.size() == 1 && children.get(0).isDualSub(); + } + + public boolean isSizeChange() { + if (children.size() == 0) + return false; + if (!isDualInline()) + return false; + return getPipeRun() != children.get(0).getPipeRun(); + } + + + private PipeControlPoint next; + private PipeControlPoint previous; + + public PipeControlPoint getNext() { + return next; + } + + public PipeControlPoint getPrevious() { + return previous; + } + + public void setNext(PipeControlPoint next) { + if (isEnd() && previous != null && next != null) + throw new RuntimeException("End control points are allowed to have only one connection"); +// if (next != null && getPipeRun() == null) +// throw new RuntimeException("Cannot connect control point befor piperun has been set"); + this.next = next; + if (component != null) { + if (parent == null || sub) + component.setNext(next != null ? next.component : null); + else + component.setBranch0(next != null ? next.component : null); + } + } + + public void setPrevious(PipeControlPoint previous) { + if (isEnd() && next != null && previous != null) + throw new RuntimeException("End control points are allowed to have only one connection"); +// if (previous != null && getPipeRun() == null) +// throw new RuntimeException("Cannot connect control point befor piperun has been set"); + this.previous = previous; + if (component != null) + if (parent == null || sub) + component.setPrevious(previous != null ? previous.component : null); + else + component.setBranch0(previous != null ? previous.component : null); + } + + public PipeControlPoint parent; + public List children = new ArrayList(); + + public List getSubPoint() { + return children; + } + + public PipeControlPoint getParentPoint() { + return parent; + } + + + + + + + + + private double length; + private Double turnAngle; + private Vector3d turnAxis; + + private Double offset; + private Double rotationAngle; + + @GetPropertyValue(name="Length",tabId="Debug",value="length") + public double getLength() { + return length; + } + + public void setLength(double l) { + if (Double.isInfinite(l) || Double.isNaN(l)) { + return; + } + if (Math.abs(this.length-l) < MathTools.NEAR_ZERO) + return; + this.length = l; + firePropertyChanged("length"); + if (isDualInline()) + getSubPoint().get(0).setLength(l); + } + + @GetPropertyValue(name="Turn Angle",tabId="Debug",value="turnAngle") + public Double getTurnAngle() { + return turnAngle; + } + + @GetPropertyValue(name="Turn Axis",tabId="Debug",value="turnAxis") + public Vector3d getTurnAxis() { + return turnAxis; + } + + @GetPropertyValue(name="Offset",tabId="Debug",value="offset") + public Double getOffset() { + return offset; + } + + @GetPropertyValue(name="Rotation Angle",tabId="Debug",value="rotationAngle") + public Double getRotationAngle() { + return rotationAngle; + } + + public void setTurnAngle(Double turnAngle) { + if (Double.isInfinite(turnAngle) || Double.isNaN(turnAngle)) { + return; + } + if (this.turnAngle != null && Math.abs(this.turnAngle-turnAngle) < MathTools.NEAR_ZERO) + return; + this.turnAngle = turnAngle; + firePropertyChanged("turnAngle"); + } + + public void setTurnAxis(Vector3d turnAxis) { + this.turnAxis = turnAxis; + firePropertyChanged("turnAxis"); + } + + public void setOffset(Double offset) { + if (Double.isInfinite(offset) || Double.isNaN(offset)) { + return; + } + if (this.offset != null && Math.abs(this.offset-offset) < MathTools.NEAR_ZERO) + return; + this.offset = offset; + firePropertyChanged("offset"); + } + + public void setRotationAngle(Double rotationAngle) { + if (Double.isInfinite(rotationAngle) || Double.isNaN(rotationAngle)) { + return; + } + if (this.rotationAngle != null && Math.abs(this.rotationAngle-rotationAngle) < MathTools.NEAR_ZERO) + return; + this.rotationAngle = rotationAngle; + firePropertyChanged("rotationAngle"); + } + + public Vector3d getSizeChangeOffsetVector(Vector3d dir) { + if (rotationAngle == null) + rotationAngle = 0.0; + Quat4d q = getControlPointOrientationQuat(dir, rotationAngle); + Vector3d v = new Vector3d(0.0,0.0,offset); + Vector3d offset = new Vector3d(); + MathTools.rotate(q, v, offset); + return offset; + } + + @GetPropertyValue(name="Next",tabId="Debug",value="next") + private String getNextString() { + if (next == null) + return null; + return next.toString(); + } + + @GetPropertyValue(name="Previous",tabId="Debug",value="previous") + private String getPrevString() { + if (previous == null) + return null; + return previous.toString(); + } + + public Quat4d getControlPointOrientationQuat(double angle) { + + if (turnAxis == null) { + Vector3d dir = getPathLegDirection(Direction.NEXT); + if (dir.lengthSquared() > MathTools.NEAR_ZERO) + dir.normalize(); + return getControlPointOrientationQuat(dir, angle); + } else { + Vector3d dir = getPathLegDirection(Direction.PREVIOUS); + dir.negate(); + if (dir.lengthSquared() > MathTools.NEAR_ZERO) + dir.normalize(); + return getControlPointOrientationQuat(dir, turnAxis, angle); + } + } + + + + public static Quat4d getControlPointOrientationQuat(Vector3d dir, double angle) { + if (dir.lengthSquared() < MathTools.NEAR_ZERO) + return MathTools.getIdentityQuat(); + + + Vector3d up = new Vector3d(0.0, 1.0, 0.0); + double a = up.angle(dir); + if (a < 0.1 || (Math.PI - a) < 0.1) { + up.set(1.0, 0.0, 0.0); + } + + + return getControlPointOrientationQuat(dir, up, angle); + } + + public static Quat4d getControlPointOrientationQuat(Vector3d dir, Vector3d up, double angle) { + if (dir.lengthSquared() < MathTools.NEAR_ZERO) + return MathTools.getIdentityQuat(); + + final Vector3d front = new Vector3d(1.0,0.0,0.0); + + Quat4d q1 = new Quat4d(); + + + Vector3d right = new Vector3d(); + + right.cross(dir, up); + up.cross(right, dir); + right.normalize(); + up.normalize(); + + Matrix3d m = new Matrix3d(); + m.m00 = dir.x; + m.m10 = dir.y; + m.m20 = dir.z; + m.m01 = up.x; + m.m11 = up.y; + m.m21 = up.z; + m.m02 = right.x; + m.m12 = right.y; + m.m22 = right.z; + + //q1.set(m); MathTools contains more stable conversion + MathTools.getQuat(m, q1); + +// if (DEBUG) System.out.println("PipingTools.getPipeComponentOrientationQuat() " + dir+ " " + up + " " + right); + + Quat4d q2 = new Quat4d(); + q2.set(new AxisAngle4d(front, angle)); + q1.mul(q2); + return q1; + } + + public Vector3d getDirection() { + return getDirectedControlPointDirection(); + } + + + + + + + + public void insert(PipeControlPoint previous, PipeControlPoint next) { + // inserting an offsetpoint is error, + if (isDualSub()) + throw new RuntimeException(); + // size change control point cannot be inserted this way, because it ends PipeRun + if (isSizeChange()) + throw new RuntimeException(); + PipeRun piperun = previous.getPipeRun(); + // and just to make sure that control point structure is not corrupted + if (getPipeRun() != null) { + if (piperun != getPipeRun() || piperun != next.getPipeRun()) + throw new RuntimeException(); + } else { + piperun.addChild(this); + } + + // insert new BranchControlPoint between straight's control points + PipeControlPoint previousNext = previous.getNext(); + PipeControlPoint previousPrevious = previous.getPrevious(); + + PipeControlPoint offsetCP = null; + if (isOffset()) { + offsetCP = getSubPoint().get(0); + } + if (previousNext != null && previousNext == next) { + if (previous.isDualInline()) { + throw new RuntimeException(); + } + if (next.isDualSub()) { + throw new RuntimeException(); + } + previous.setNext(this); + this.setPrevious(previous); + if (previous.isDualSub()) { + previous.getParentPoint().setNext(this); + } + this.setNext(next); + + if (offsetCP == null) { + next.setPrevious(this); + } else { + next.setPrevious(offsetCP); + offsetCP.setNext(next); + offsetCP.setPrevious(previous); + } + + if (next.isDualInline()) { + next.getSubPoint().get(0).setPrevious(this); + } + } else if (previousPrevious != null && previousPrevious == next) { + // control point were given in reverse order + if (next.isDualInline()) + throw new RuntimeException(); + if (previous.isDualSub()) + throw new RuntimeException(); + + this.setNext(previous); + if (offsetCP == null) { + previous.setNext(this); + } else { + previous.setPrevious(offsetCP); + offsetCP.setNext(previous); + offsetCP.setPrevious(next); + } + if (previous.isDualInline()) { + previous.getSubPoint().get(0).setPrevious(this); + } + this.setPrevious(next); + next.setNext(this); + if (next.isDualSub()) { + next.getParentPoint().setNext(this); + } + + } else { + throw new RuntimeException(); + } + + PipingRules.validate(piperun); + } + + + + public void insert(PipeControlPoint pcp, Direction direction) { + if (isDualSub()) + throw new RuntimeException(); + if (direction == Direction.NEXT) { + // if direction is next, user must have given OffsetPoint + if (pcp.isDualInline()) + throw new RuntimeException(); + // basic next/prev links + pcp.setNext(this); + this.setPrevious(pcp); + // and last take care of sizechange / offset points + if (pcp.isDualSub()) { + pcp.getParentPoint().setNext(this); + } + if (isDualInline()) { + getSubPoint().get(0).setPrevious(this); + } + } else { + // if direction is previous, user must have given sizechange + if (pcp.isDualSub()) + throw new RuntimeException(); + // previous direction is more complicated, since if newCP is SizeChangeControlPoint, + // we must link pcp to newCP's OffsetPoint + PipeControlPoint nocp = null; + if (isDualInline()) { + nocp = getSubPoint().get(0); + nocp.setNext(pcp); + } + if (nocp == null) { + pcp.setPrevious(this); + } else { + pcp.setPrevious(nocp); + } + this.setNext(pcp); + if (pcp.isDualInline()) { + PipeControlPoint ocp = pcp.getSubPoint().get(0); + if (nocp == null) + ocp.setPrevious(this); + else + ocp.setPrevious(nocp); + } + + } + PipingRules.validate(getPipeRun()); + } + + public Vector3d getDirectedControlPointDirection() { + assert (isDirected()); + Vector3d dir = new Vector3d(); + MathTools.rotate(getWorldOrientation(), new Vector3d(1.0, 0.0, 0.0), dir); + dir.normalize(); + return dir; + } + + public Vector3d getPathLegDirection(Direction direction) { + if (direction == Direction.NEXT) { + if (next != null) { + PipeControlPoint pcp = this; + if (pcp.isDualInline()) { + pcp = pcp.getSubPoint().get(0); + } + Vector3d v = new Vector3d(); + v.sub(next.getWorldPosition(),pcp.getWorldPosition()); + return v; + } else { + if (isVariableAngle()) + throw new RuntimeException("Cannot calculate path leg direction for unconnected variable angle control point"); + if (previous == null) { + if (!isDirected()) + throw new RuntimeException("Cannot calculate path leg direction for unconnected control point"); + return getDirectedControlPointDirection(); + + } else { + if (isInline()) { + Vector3d v = new Vector3d(); + v.sub(getWorldPosition(),previous.getWorldPosition()); + return v; + } else if (isDirected()) { + return getDirectedControlPointDirection(); + } else if (isEnd()) { + Vector3d v = new Vector3d(); + v.sub(getWorldPosition(),previous.getWorldPosition()); + return v; + } + throw new RuntimeException("Missing implementation"); + } + } + } else { + if (previous != null) { + PipeControlPoint pcp = this; + if (isDualSub()) + pcp = getParentPoint(); + Vector3d v = new Vector3d(); + v.sub(previous.getWorldPosition(),pcp.getWorldPosition()); + return v; + } else { + if (isVariableAngle()) + throw new RuntimeException("Cannot calculate path leg direction for unconnected variable angle control point"); + if (next == null) { + if (!isDirected()) + throw new RuntimeException("Cannot calculate path leg direction for unconnected control point"); + Vector3d v = getDirectedControlPointDirection(); + v.negate(); + return v; + } else { + if (isInline()) { + Vector3d v = new Vector3d(); + v.sub(getWorldPosition(),next.getWorldPosition()); + return v; + } else if (isDirected()) { + Vector3d v = getDirectedControlPointDirection(); + v.negate(); + return v; + } else if (isEnd()) { + Vector3d v = new Vector3d(); + v.sub(getWorldPosition(),next.getWorldPosition()); + return v; + } + throw new RuntimeException("Missing implementation"); + } + } + } + } + + public void getInlineControlPointEnds(Tuple3d p1, Tuple3d p2) { + assert (isInline()); + + Vector3d pos = getWorldPosition(); + Vector3d dir = getPathLegDirection(Direction.NEXT); + dir.normalize(); + dir.scale(length * 0.5); + p1.set(pos); + p2.set(pos); + p1.sub(dir); + p2.add(dir); + } + + public void getControlPointEnds(Tuple3d p1, Tuple3d p2) { + Vector3d pos = getWorldPosition(); + Vector3d dir1 = getPathLegDirection(Direction.PREVIOUS); + dir1.normalize(); + Vector3d dir2 = getPathLegDirection(Direction.NEXT); + dir2.normalize(); + if (isInline()) { + dir1.scale(length * 0.5); + dir2.scale(length * 0.5); + } else { + dir1.scale(length); + dir2.scale(length); + } + p1.set(pos); + p2.set(pos); + p1.add(dir1); + p2.add(dir2); + } + + public void getInlineControlPointEnds(Tuple3d p1, Tuple3d p2, Vector3d dir) { + assert (isInline()); + + Vector3d pos = getWorldPosition(); + dir.set(getPathLegDirection(Direction.NEXT)); + dir.normalize(); + dir.scale(length * 0.5); + p1.set(pos); + p2.set(pos); + p1.sub(dir); + p2.add(dir); + } + + public void getInlineControlPointEnds(Tuple3d center, Tuple3d p1, Tuple3d p2, Vector3d dir) { + assert (isInline()); + + Vector3d pos = getWorldPosition(); + center.set(pos); + dir.set(getPathLegDirection(Direction.NEXT)); + dir.normalize(); + dir.scale(length * 0.5); + p1.set(pos); + p2.set(pos); + p1.sub(dir); + p2.add(dir); + } + + public double getInlineLength() { + if (type == Type.TURN) + return length; + else if (type == Type.INLINE) + return length * 0.5; + return 0; + } + + public Vector3d getRealPosition(PositionType type) { + Vector3d pos = getWorldPosition(); + switch (type) { + case NEXT: { + Vector3d dir = getPathLegDirection(Direction.NEXT); + double length = getInlineLength(); + dir.normalize(); + dir.scale(length); + pos.add(dir); + break; + } + case PREVIOUS: { + Vector3d dir = getPathLegDirection(Direction.PREVIOUS); + double length = getInlineLength(); + dir.normalize(); + dir.scale(length); + pos.add(dir); + break; + } + case PORT: + // IEntity portDir = pcp.getSingleRelatedObject(ProcessResource.plant3Dresource.HasDirection); + // TODO : how we calculated needed space for a port; does it has an offset from control point's position or not? + break; + case SPLIT: + // do nothing + break; + + } + return pos; + } + + public void getInlineMovement(Tuple3d start, Tuple3d end) { + // FIXME : check type of neighbor components and allow movement on top of variable length components, + // find proper range for movement (pcp's position is not) + PipeControlPoint p = previous.getPrevious(); + PipeControlPoint n = next.getNext(); + start.set(p.getWorldPosition()); + end.set(n.getWorldPosition()); + } + + public PipeControlPoint findNextEnd() { + ArrayList t = new ArrayList(); + return findNextEnd( t); + } + + public PipeControlPoint findPreviousEnd() { + ArrayList t = new ArrayList(); + return findPreviousEnd(t); + } + + public PipeControlPoint findNextEnd(List nextList) { + while (true) { + PipeControlPoint pcp = null; + PipeControlPoint p = null; + if (nextList.size() == 0) + p = this; + + else + p = nextList.get(nextList.size() - 1); + + pcp = p.getNext(); + if (pcp == null) { + pcp = p; + if (nextList.size() > 0) + nextList.remove(nextList.size() - 1); +// if (DEBUG) System.out.println(" " + pcp.getResource() + " not full"); + return pcp; + //break; + } + if (pcp.isPathLegEnd()) { + //if (DEBUG) System.out.println(" " + pcp.getResource()); + return pcp; + } else { + nextList.add(pcp); + // if (DEBUG) System.out.print(" " + pcp.getResource()); + } + } + } + + public PipeControlPoint findPreviousEnd(List prevList) { + while (true) { + PipeControlPoint pcp = null; + PipeControlPoint p = null; + if (prevList.size() == 0) + p = this; + + else + p = prevList.get(prevList.size() - 1); + + pcp = p.getPrevious(); + if (pcp == null) { + pcp = p; + if (prevList.size() > 0) + prevList.remove(prevList.size() - 1); +// if (DEBUG) System.out.println(" " + pcp.getResource() + " not full"); + return pcp; + } + if (pcp.isPathLegEnd()) { +// if (DEBUG) System.out.println(" " + pcp.getResource()); + return pcp; + } else { + prevList.add(pcp); +// if (DEBUG)System.out.print(" " + pcp.getResource()); + } + } + } + + public void _remove() { + if (component == null && next == null && previous == null) + return; + if (isDualInline() || isDualSub()) { + removeDualPoint(); + return; + } + PipeRun pipeRun = getPipeRun(); + if (pipeRun == null) + return; + + PipeControlPoint additionalRemove = null; + if (!PipingRules.isEnabled()) { + setPrevious(null); + setNext(null); + } else { + + PipeControlPoint currentPrev = previous; + PipeControlPoint currentNext = next; + if (currentNext == null && currentPrev == null) { + removeComponent(); + pipeRun.remChild(this); + return; + } + if (currentNext != null && currentPrev != null) { + boolean link = true; + if (currentNext.isBranchEnd()) { + link = false; +// currentNext.setPrevious(null); +// currentNext.setNext(null); + currentNext.remove(); + currentNext = null; + setNext(null); + } + if (currentPrev.isBranchEnd()) { + link = false; +// currentPrev.setPrevious(null); +// currentPrev.setNext(null); + currentPrev.remove(); + currentPrev = null; + setPrevious(null); + } + if (link && currentPrev.isDirected() && currentNext.isDirected()) { + link = false; + } + if (currentNext == null) { + // Nothing to do + } else if (currentNext.isDualInline()) { + PipeControlPoint sccp = currentNext; + PipeControlPoint ocp = sccp.getSubPoint().get(0); + if (ocp == null) { + throw new RuntimeException("Removing PipeControlPoint " + this+ " structure damaged, no offset control point"); + } + if (link) { + sccp.setPrevious(currentPrev); + ocp.setPrevious(currentPrev); + } else { + sccp.setPrevious(null); + ocp.setPrevious(null); + } + setNext(null); + } else if (currentNext.isDualSub()) { + throw new RuntimeException("Removing PipeControlPoint " + this + " structure damaged, next control point is offset control point"); + } else if (currentNext.previous == this) { + if (link) { + currentNext.setPrevious(currentPrev); + } else { + currentNext.setPrevious(null); + } + setNext(null); + } else { + throw new RuntimeException("Removing PipeControlPoint "+ this+ " structure damaged"); + } + if (currentPrev == null) { + // Nothing to do + } else if (currentPrev.isDualInline()) { + throw new RuntimeException("Removing PipeControlPoint " + this + " structure damaged, previous control point is size change control point"); + } else if (currentPrev.isDualSub()) { + PipeControlPoint ocp = currentPrev; + PipeControlPoint sccp = ocp.getParentPoint(); + if (sccp == null) + throw new RuntimeException("Removing PipeControlPoint " + this + " structure damaged, no size change control point"); + if (link) { + ocp.setNext(currentNext); + sccp.setNext(currentNext); + } else { + ocp.setNext(null); + sccp.setNext(null); + } + setPrevious(null); + } else if (currentPrev.next == this) { + if (link) + currentPrev.setNext(currentNext); + else + currentPrev.setNext(null); + + setPrevious(null); + } else { + throw new RuntimeException("Removing PipeControlPoint " + this + " structure damaged"); + } + if (link) { + if (currentNext.isVariableLength() && currentPrev.isVariableLength()) { + // we have to join them into single variable length component. + additionalRemove = currentPrev; + //currentPrev.remove(); + } + } else { + // FIXME : pipe run must be split into two parts, since the control point structure is no more continuous. + } + } else if (next != null) { + if (next.isDualInline()) { + PipeControlPoint sccp = next; + PipeControlPoint ocp = sccp.getSubPoint().get(0); + if (ocp == null) { + throw new RuntimeException("Removing PipeControlPoint " + this+ " structure damaged, no offset control point"); + } + sccp.setPrevious(null); + ocp.setPrevious(null); + } else if (next.isDualSub()) { + throw new RuntimeException("Removing PipeControlPoint " + this + " structure damaged, next control point is offset control point"); + } else if (next.previous == this) { + next.setPrevious(null); + } else { + throw new RuntimeException("Removing PipeControlPoint "+ this+ " structure damaged"); + } + setNext(null); + } else { //(previous != null) + if(previous.isDualInline()) { + throw new RuntimeException("Removing PipeControlPoint " + this + " structure damaged, previous control point is size change control point"); + } else if (previous.isDualSub()) { + PipeControlPoint ocp = previous; + PipeControlPoint sccp = ocp.getParentPoint(); + if (sccp == null) { + throw new RuntimeException("Removing PipeControlPoint " + this + " structure damaged, no size change control point"); + } + ocp.setNext(null); + sccp.setNext(null); + } else if (previous.next == this) { + previous.setNext(null); + } else { + throw new RuntimeException("Removing PipeControlPoint "+ this+ " structure damaged"); + } + setPrevious(null); + } + if (children.size() > 0 ) { + removeSubPoints(); + } else if (parent!= null) { + removeParentPoint(); + } + + } + + removeComponent(); + pipeRun.remChild(this); + checkRemove(pipeRun); + if (PipingRules.isEnabled() && pipeRun.getParent() != null && pipeRun.getControlPoints().size() > 0) + PipingRules.validate(pipeRun); + if (additionalRemove != null) + additionalRemove.remove(); + } + + public void remove() { + PipeControlPoint currentPrev = previous; + PipeControlPoint currentNext = next; + _remove(); + try { + if (currentNext != null) + PipingRules.requestUpdate(currentNext); + if (currentPrev != null) + PipingRules.requestUpdate(currentPrev); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void checkRemove(PipeRun pipeRun) { + Collection points = pipeRun.getControlPoints(); + if (points.size() == 0) { + pipeRun.remove(); + } else if (points.size() == 1) { + PipeControlPoint pcp = points.iterator().next(); + if (pcp.isDeletable()) + pcp._remove(); + } + } + + private void removeDualPoint() { + if (previous != null) + previous.setNext(null); + if (next != null) + next.setPrevious(null); + PipeControlPoint ocp; + PipeControlPoint sccp; + if (isDualInline()) { + sccp = this; + ocp = getSubPoint().get(0); + } else { + ocp = this; + sccp = getParentPoint(); + } + PipeRun p1 = ocp.getPipeRun(); + PipeRun p2 = sccp.getPipeRun(); + + ocp.removeComponent(); + sccp.removeComponent(); + + p1.remChild(ocp); + p2.remChild(sccp); + + ocp.setNext(null); + ocp.setPrevious(null); + sccp.setNext(null); + sccp.setPrevious(null); + + checkRemove(p1); + checkRemove(p2); + } + + private void removeSubPoints() { + for (PipeControlPoint p : children) { + // TODO : this may affect delete routine, since classification of the point changes. + p.parent = null; + p._remove(); + } + children.clear(); + } + + private void removeParentPoint() { + throw new RuntimeException("Child points cannot be removed directly"); + } + + private void removeComponent() { + if (component == null) + return; + PipelineComponent next = component.getNext(); + PipelineComponent prev = component.getNext(); + if (next != null) { + if (next.getNext() == component) + next.setNext(null); + else if (next.getPrevious() == component) + next.setPrevious(null); + } + if (prev != null) { + if (prev.getNext() == component) + prev.setNext(null); + else if (prev.getPrevious() == component) + prev.setPrevious(null); + } + PipelineComponent comp = component; + component = null; + comp.remove(); + } + + @Override + public void setOrientation(Quat4d orientation) { + if (MathTools.equals(orientation, getOrientation())) + return; + super.setOrientation(orientation); + if (getParentPoint() == null && component != null) + component._setWorldOrientation(getWorldOrientation()); + for (PipeControlPoint sub : getSubPoint()) { + sub.setWorldPosition(getWorldPosition()); + sub.setWorldOrientation(getWorldOrientation()); + } + } + + @Override + public void setPosition(Vector3d position) { + if (MathTools.equals(position, getPosition())) + return; + super.setPosition(position); + if (getParentPoint() == null && component != null) + component._setWorldPosition(getWorldPosition()); + for (PipeControlPoint sub : getSubPoint()) { + sub.setWorldPosition(getWorldPosition()); + sub.setWorldOrientation(getWorldOrientation()); + } + } + + + public void _setWorldPosition(Vector3d position) { + Vector3d localPos = getLocalPosition(position); + super.setPosition(localPos); + for (PipeControlPoint sub : getSubPoint()) { + sub.setWorldPosition(getWorldPosition()); + sub.setWorldOrientation(getWorldOrientation()); + } + } + + public void _setWorldOrientation(Quat4d orientation) { + Quat4d localOr = getLocalOrientation(orientation); + super.setOrientation(localOr); + for (PipeControlPoint sub : getSubPoint()) { + sub.setWorldPosition(getWorldPosition()); + sub.setWorldOrientation(getWorldOrientation()); + } + } + + @Override + public String toString() { + return getClass().getName() + "@" + Integer.toHexString(hashCode()); + } + +} diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/controlpoint/PipingRules.java b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/controlpoint/PipingRules.java new file mode 100644 index 00000000..d7c53d4a --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/scenegraph/controlpoint/PipingRules.java @@ -0,0 +1,1651 @@ +package org.simantics.plant3d.scenegraph.controlpoint; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.vecmath.Point3d; +import javax.vecmath.Quat4d; +import javax.vecmath.Vector3d; + +import org.simantics.g3d.math.MathTools; +import org.simantics.plant3d.scenegraph.InlineComponent; +import org.simantics.plant3d.scenegraph.Nozzle; +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.Direction; +import org.simantics.plant3d.utils.ComponentUtils; +import org.simantics.utils.ui.ErrorLogger; + +public class PipingRules { + private static final boolean DEBUG = false; + private static final boolean DUMMY = false; + + private static final double MIN_TURN_ANGLE = 0.01; + + private static final int REMOVE_NONE = 0; + private static final int REMOVE_START = 1; + private static final int REMOVE_END = 2; + private static final int REMOVE_BOTH = 3; + +// private P3DRootNode root; + +// public PipingRules(P3DRootNode root) { +// this.root = root; +// } + + private enum PathLegUpdateType { + NONE, PREV, NEXT, PREV_S, NEXT_S + }; + + private static boolean enabled = true; + private static boolean updating = false; + private static boolean allowInsertRemove = true; + private static boolean triedIR = false; + + + private static List updates = new ArrayList(); + + private static Object mutex = new Object(); + + public static void requestUpdate(PipeControlPoint pcp) { + if (DEBUG) System.out.println("PipingRules request " + pcp); + synchronized (mutex) { + if (!updates.contains(pcp)) + updates.add(pcp); + } + } + + public static synchronized boolean update() throws Exception { + if (updates.size() == 0) + return false; + List temp = new ArrayList(updates.size()); + synchronized(mutex) { + temp.addAll(updates); + updates.clear(); + } + + for (PipeControlPoint pcp : temp) + positionUpdate(pcp); + return true; + } + + public static boolean positionUpdate(PipeControlPoint pcp) throws Exception { + + return positionUpdate(pcp, true); + } + + public static boolean positionUpdate(PipeControlPoint pcp, boolean allowIR) throws Exception { + if (updating || !enabled) + return true; + if (pcp.getPipeRun() == null) + return false; + try { + if (DEBUG) System.out.println("PipingRules " + pcp); + updating = true; + allowInsertRemove = allowIR; + triedIR = false; + validate(pcp.getPipeRun()); + if (pcp.isPathLegEnd()) { + updatePathLegEndControlPoint(pcp); // FXIME: Rules won't work properly, if they are not run twice. + updatePathLegEndControlPoint(pcp); + } else { + updateInlineControlPoint(pcp); + updateInlineControlPoint(pcp); + } + validate(pcp.getPipeRun()); + if (!allowInsertRemove) + return !triedIR; + return true; + } finally { + updating = false; +// System.out.println("PipingRules done " + pcp); + } + } + + public static void setEnabled(boolean enabled) { + PipingRules.enabled = enabled; + if(!enabled) + updates.clear(); + } + + public static boolean isEnabled() { + return enabled; + } + +// private void commit() { +// root.getNodeMap().commit(); +// } + + public static class ExpandIterInfo { + // these two are turn control points + private PipeControlPoint start; + private PipeControlPoint end; + private int type; + + public ExpandIterInfo() { + + } + + public ExpandIterInfo(PipeControlPoint tcp, int type) { + if (type == REMOVE_START) + start = tcp; + else + end = tcp; + this.type = type; + } + + public ExpandIterInfo(PipeControlPoint start, PipeControlPoint end) { + this.start = start; + this.end = end; + this.type = REMOVE_BOTH; + } + + public PipeControlPoint getEnd() { + return end; + } + + public void setEnd(PipeControlPoint end) { + this.end = end; + } + + public PipeControlPoint getStart() { + return start; + } + + public void setStart(PipeControlPoint start) { + this.start = start; + } + + public int getType() { + return type; + } + + public void setType(int type) { + this.type = type; + } + + } + + private static void updatePathLegEndControlPoint(PipeControlPoint pcp) throws Exception { + if (DEBUG) + System.out.println("PipingRules.updatePathLegEndControlPoint() " + pcp); + if (pcp.getNext() != null) { + updatePathLegNext(pcp, pcp, PathLegUpdateType.NEXT_S); + } + if (pcp.getPrevious() != null) { + updatePathLegPrev(pcp, pcp, PathLegUpdateType.PREV_S); + } + + } + + private static void updateInlineControlPoint(PipeControlPoint pcp) throws Exception { + if (DEBUG) + System.out.println("PipingRules.updateInlineControlPoint() " + pcp); + PipeControlPoint start = pcp.findPreviousEnd(); + updatePathLegNext(start, pcp, PathLegUpdateType.NONE); + } + + private static PipeControlPoint insertElbow(PipeControlPoint pcp1, PipeControlPoint pcp2, Vector3d pos) throws Exception{ + if (DEBUG) + System.out.println("PipingRules.insertElbow() " + pcp1 + " " + pcp2 + " " + pos); + if (pcp1.getNext() == pcp2 && pcp2.getPrevious() == pcp1) { + + } else if (pcp1.getNext() == pcp2 && pcp1.isDualInline() && pcp2.getPrevious() == pcp1.getSubPoint().get(0)) { + pcp1 = pcp1.getSubPoint().get(0); + } else if (pcp1.getPrevious() == pcp2 && pcp2.getNext() == pcp1) { + PipeControlPoint t = pcp1; + pcp1 = pcp2; + pcp2 = t; + } else if (pcp2.isDualInline() && pcp1.getPrevious() == pcp2.getSubPoint().get(0) && pcp2.getNext() == pcp1) { + PipeControlPoint t = pcp1; + pcp1 = pcp2.getSubPoint().get(0); + pcp2 = t; + } else { + throw new RuntimeException(); + } + TurnComponent elbow = ComponentUtils.createTurn((P3DRootNode)pcp1.getRootNode()); + PipeControlPoint pcp = elbow.getControlPoint(); + if (pcp1.isDualInline()) + pcp1 = pcp1.getSubPoint().get(0); + String name = pcp1.getPipeRun().getUniqueName("Elbow"); + elbow.setName(name); + pcp1.getPipeRun().addChild(elbow); + + pcp.insert(pcp1, pcp2); + + pcp.setWorldPosition(pos); + validate(pcp.getPipeRun()); + return pcp; + } + + private static PipeControlPoint insertStraight(PipeControlPoint pcp1, PipeControlPoint pcp2, Vector3d pos, double length) throws Exception { + if (DEBUG) + System.out.println("PipingRules.insertStraight() " + pcp1 + " " + pcp2 + " " + pos); + if (pcp1.getNext() == pcp2 && pcp2.getPrevious() == pcp1) { + + } else if (pcp1.getNext() == pcp2 && pcp1.isDualInline() && pcp2.getPrevious() == pcp1.getSubPoint().get(0)) { + pcp1 = pcp1.getSubPoint().get(0); + } else if (pcp1.getPrevious() == pcp2 && pcp2.getNext() == pcp1) { + PipeControlPoint t = pcp1; + pcp1 = pcp2; + pcp2 = t; + } else if (pcp2.isDualInline() && pcp1.getPrevious() == pcp2.getSubPoint().get(0) && pcp2.getNext() == pcp1) { + PipeControlPoint t = pcp1; + pcp1 = pcp2.getSubPoint().get(0); + pcp2 = t; + } else { + throw new RuntimeException(); + } + InlineComponent component = ComponentUtils.createStraight((P3DRootNode)pcp1.getRootNode()); + PipeControlPoint scp = component.getControlPoint(); + if (pcp1.isDualInline()) + pcp1 = pcp1.getSubPoint().get(0); + String name = pcp1.getPipeRun().getUniqueName("Pipe"); + component.setName(name); + pcp1.getPipeRun().addChild(component); + + scp.insert(pcp1, pcp2); + + scp.setWorldPosition(pos); + scp.setLength(length); + validate(scp.getPipeRun()); + return scp; + } + + private static PipeControlPoint insertStraight(PipeControlPoint pcp, Direction direction , Vector3d pos, double length) throws Exception { + if (DEBUG) + System.out.println("PipingRules.insertStraight() " + pcp + " " + direction + " " + pos); + + InlineComponent component = ComponentUtils.createStraight((P3DRootNode)pcp.getRootNode()); + PipeControlPoint scp = component.getControlPoint(); + if (pcp.isDualInline() && direction == Direction.NEXT) + pcp = pcp.getSubPoint().get(0); + String name = pcp.getPipeRun().getUniqueName("Pipe"); + component.setName(name); + pcp.getPipeRun().addChild(component); + + scp.insert(pcp,direction); + + scp.setWorldPosition(pos); + scp.setLength(length); + validate(scp.getPipeRun()); + return scp; + } + + private static void updatePathLegNext(PipeControlPoint start, PipeControlPoint updated, PathLegUpdateType lengthChange) throws Exception { + ArrayList list = new ArrayList(); + PipeControlPoint end = start.findNextEnd(list); + // this is for inline cp that is also path leg end + if (start.equals(updated)) + lengthChange = PathLegUpdateType.NEXT; + else if (end.equals(updated)) + lengthChange = PathLegUpdateType.PREV; + updatePathLegNext(start, list, end, updated, lengthChange); + } + + private static void updatePathLegNext(PipeControlPoint start, ArrayList list, PipeControlPoint end, PipeControlPoint updated, PathLegUpdateType lengthChange) throws Exception { + updatePathLeg(start, list, end, false, 0, new ArrayList(), updated, lengthChange); + } + + private static class UpdateStruct2 { + public PipeControlPoint start; + public Vector3d startPoint; + public ArrayList list; + public PipeControlPoint end; + public Vector3d endPoint; + public Vector3d dir; + public Vector3d offset; + public boolean hasOffsets; + public int iter; + public boolean reversed; + public ArrayList toRemove; + public PipeControlPoint updated; + + public UpdateStruct2(PipeControlPoint start, Vector3d startPoint, ArrayList list, PipeControlPoint end, Vector3d endPoint, Vector3d dir, Vector3d offset, boolean hasOffsets, int iter, boolean reversed, ArrayList toRemove, PipeControlPoint updated) { + if (start == null || end == null) + throw new NullPointerException(); + this.start = start; + this.startPoint = startPoint; + this.list = list; + this.end = end; + this.endPoint = endPoint; + this.dir = dir; + this.offset = offset; + this.hasOffsets = hasOffsets; + this.iter = iter; + this.reversed = reversed; + this.toRemove = toRemove; + this.updated = updated; + + if (!MathTools.isValid(startPoint) || + !MathTools.isValid(endPoint) || + !MathTools.isValid(dir)) { + throw new RuntimeException(); + } + } + + public String toString() { + return start + " " + end+ " " + dir + " " + hasOffsets + " " + offset + " " + iter + " " + toRemove.size(); + } + + } + + private static boolean calculateOffset(Vector3d startPoint, Vector3d endPoint, ArrayList list, Vector3d dir, Vector3d offset) { + boolean hasOffsets = false; + dir.set(startPoint); + dir.sub(endPoint); + if (dir.lengthSquared() > MathTools.NEAR_ZERO) + dir.normalize(); + offset.set(0.0, 0.0, 0.0); + for (PipeControlPoint icp : list) { + if (icp.isOffset()) { + hasOffsets = true; + offset.add(icp.getSizeChangeOffsetVector(dir)); + } else if (icp.isDualSub()) + ErrorLogger.defaultLogError("Updating pipe run, found offset controlpoint " + icp, new Exception("ASSERT!")); + } + return hasOffsets; + } + + /** + * @param start + * starting point of the pipe run + * @param list + * list of inline control points in the pipe run + * @param end + * ending point of the pipe run + * @param reversed + * boolean flag indicating wether start or end control point was + * modified (if true then end point was modified) + * @throws TransactionException + */ + private static void updatePathLeg(PipeControlPoint start, ArrayList list, PipeControlPoint end, boolean reversed, int iter, ArrayList toRemove, PipeControlPoint updated, PathLegUpdateType lengthChange) throws Exception { + if (start == end) + return; + // FIXME: direction is calculated wrong way! + boolean hasOffsets = false; + Vector3d offset = new Vector3d(); + Vector3d startPoint = start.getWorldPosition(); + Vector3d endPoint = end.getWorldPosition(); + Vector3d dir = new Vector3d(); + hasOffsets = calculateOffset(startPoint, endPoint, list, dir, offset); + updatePathLeg(new UpdateStruct2(start, startPoint, list, end, endPoint, dir, offset, hasOffsets, iter, reversed, toRemove, updated), lengthChange); + + } + + private static void updatePathLeg(UpdateStruct2 u, PathLegUpdateType lengthChange) throws Exception { + int directed = 0; + if (u.start.isDirected()) + directed++; + if (u.end.isDirected()) + directed++; + switch (directed) { + case 0: + updateFreePathLeg(u, lengthChange); + break; + case 1: + updateDirectedPathLeg(u, lengthChange); + break; + case 2: + updateDualDirectedPathLeg(u, lengthChange); + break; + } + + } + + private static void updateFreePathLeg(UpdateStruct2 u, PathLegUpdateType lengthChange) throws Exception { + if (DEBUG) + System.out.println("PipingRules.updateFreePipeRun " + u + " " + lengthChange); + checkExpandPathLeg(u, lengthChange); + if (u.start.isInline() || u.end.isInline()) + processPathLeg(u, true, false); + } + + private static void updateInlineControlPoints(UpdateStruct2 u, boolean checkSizes) throws Exception{ + if (DEBUG) + System.out.println("PipingRules.updateInlineControlPoints() " + u); + + if (!u.hasOffsets) { + // FIXME : cache positions + if (!checkSizes) { + Vector3d start = new Vector3d(u.startPoint); + Vector3d end = new Vector3d(u.endPoint); + // create offsets. + MathTools.mad(start, u.dir, 0.1); + MathTools.mad(end, u.dir, -0.1); + for (PipeControlPoint icp : u.list) { + updateInlineControlPoint(icp, start, end, u.dir); + } + return; + } + + ArrayList pathLegPoints = new ArrayList(); + pathLegPoints.add(u.start); + for (PipeControlPoint icp : u.list) { + // updateInlineControlPoint(icp, u.startPoint, + // u.endPoint,u.dir); + updateBranchControlPointBranches(icp); + pathLegPoints.add(icp); + } + pathLegPoints.add(u.end); + + // TODO : values can be cached in the loop + for (int i = 1; i < pathLegPoints.size(); i++) { + PipeControlPoint icp = pathLegPoints.get(i); + + PipeControlPoint prev; + Vector3d prevPos; + prev = pathLegPoints.get(i - 1); + prevPos = prev.getWorldPosition(); + Vector3d currentPos = icp.getWorldPosition(); + + if (icp.isVariableLength()) { + if (i != pathLegPoints.size() - 1) { + PipeControlPoint next; + Vector3d nextPos; + next = pathLegPoints.get(i + 1); + nextPos = next.getWorldPosition(); + Vector3d dir = new Vector3d(nextPos); + dir.sub(prevPos); + double l = dir.lengthSquared(); // distance between + // control points + // (square) + double l2prev = prev.getInlineLength(); // distance + // taken + // by + // components + double l2next = next.getInlineLength(); + double l2 = l2prev + l2next; + double l2s = MathTools.square(l2); + if (l2s < l) { // check if there is enough space for + // variable length component. + // components fit + dir.normalize(); + double length = Math.sqrt(l) - l2; // true length of + // the variable + // length + // component + dir.scale(length * 0.5 + l2prev); // calculate + // center + // position of + // the component + dir.add(prevPos); + icp.setWorldPosition(dir); + icp.setLength(length); + } else { + // components leave no space to the component and it + // must be removed + if (icp.isDeletable()) + icp._remove(); + } + + } else { + // this is variable length component at the end of the + // piperun. + // the problem is that we want to keep unconnected end + // of the component in the same + // place, but center of the component must be moved. + double currentLength = icp.getLength(); + + Vector3d dir = new Vector3d(); + dir.sub(currentPos, prevPos); + + if (currentLength < MathTools.NEAR_ZERO) { + currentLength = (dir.length() - prev.getInlineLength()) * 2.0; + } + + if (dir.lengthSquared() > MathTools.NEAR_ZERO) + dir.normalize(); + Point3d endPos = new Point3d(dir); + endPos.scale(currentLength * 0.5); + endPos.add(currentPos); // this is the free end of the + // component + + double offset = prev.getInlineLength(); + Point3d beginPos = new Point3d(dir); + beginPos.scale(offset); + beginPos.add(prevPos); // this is the connected end of + // the component + + double l = beginPos.distance(endPos); + + if (Double.isNaN(l)) + System.out.println(); + + dir.scale(l * 0.5); + beginPos.add(dir); // center position + + if (DEBUG) + System.out.println("PipingRules.updateInlineControlPoints() setting variable length to " + l); + icp.setLength(l); + + icp.setWorldPosition(new Vector3d(beginPos)); + } + + + } else if (!prev.isVariableLength()) { + // If this and previous control point are not variable + // length pcps, we'll have to check if there is no empty + // space between them. + // I there is, we'll have to create new variable length + // component between them. + Vector3d dir = new Vector3d(currentPos); + dir.sub(prevPos); + double l = dir.lengthSquared(); + double l2prev = prev.getInlineLength(); + double l2next = icp.getInlineLength(); + double l2 = l2prev + l2next; + double l2s = l2 * l2; + if (l > l2s) { + if (allowInsertRemove) { + dir.normalize(); + double length = Math.sqrt(l) - l2; // true length of the + // variable length + // component + dir.scale(length * 0.5 + l2prev); // calculate center + // position of the + // component + dir.add(prevPos); + PipeControlPoint scp = insertStraight(prev, icp, dir, length); + } else { + triedIR = true; + } + } + } + } + } else { + u.endPoint.sub(u.offset); + // FIXME : straights + for (PipeControlPoint icp : u.list) { + updateInlineControlPoint(icp, u.startPoint, u.endPoint, u.dir); + updateBranchControlPointBranches(icp); + + if (icp.isOffset()) { + // TODO : offset vector is already calculated and should be + // cached + u.offset = icp.getSizeChangeOffsetVector(u.dir); + updateOffsetPoint(icp, u.offset); + u.startPoint.add(u.offset); + u.endPoint.add(u.offset); + } + } + } + } + + private static void ppNoOffset(UpdateStruct2 u) throws Exception { + if (DEBUG) + System.out.println("PipingRules.ppNoOffset() " + u); + Vector3d offset = new Vector3d(); + if (u.hasOffsets) { + u.dir.normalize(); + for (PipeControlPoint icp : u.list) { + if (icp.isOffset()) { + offset.add(icp.getSizeChangeOffsetVector(u.dir)); + } else if (icp.isDualSub()) + ErrorLogger.defaultLogError("Updating pipe run, found offset controlpoint " + icp, new Exception("ASSERT!")); + } + } + u.offset = offset; + checkExpandPathLeg(u, PathLegUpdateType.NONE); + } + + private static void ppNoDir(PipeControlPoint start, Vector3d startPoint, ArrayList list, PipeControlPoint end, Vector3d endPoint, boolean hasOffsets, int iter, boolean reversed, ArrayList toRemove, PipeControlPoint updated) throws Exception { + if (DEBUG) + System.out.println("PipingRules.ppNoDir() " + start + " " + end + " " + iter + " " + toRemove.size()); + // FIXME : extra loop (dir should be calculated here) + Vector3d dir = new Vector3d(); + Vector3d offset = new Vector3d(); + hasOffsets = calculateOffset(startPoint, endPoint, list, dir, offset); + ppNoOffset(new UpdateStruct2(start, startPoint, list, end, endPoint, dir, null, hasOffsets, iter, reversed, toRemove, updated)); + } + + private static void checkExpandPathLeg(UpdateStruct2 u, PathLegUpdateType lengthChange) throws Exception { + checkExpandPathLeg(u, lengthChange, false); + } + + private static void checkExpandPathLeg(UpdateStruct2 u, PathLegUpdateType lengthChange, boolean forceUpdate) throws Exception { + if (DEBUG) + System.out.println("PipingRules.checkExpandPathLeg() " + u + " " + lengthChange); + if (lengthChange != PathLegUpdateType.NONE) { + // FIXME : turns cannot be checked before inline cps are updated, + // since their position affects calculation of turns + processPathLeg(u, forceUpdate, false); + int type = checkTurns(u, lengthChange); + if (type == REMOVE_NONE) { + processPathLeg(u, forceUpdate, true); + } else { + expandPathLeg(u, type); + } + } else { + processPathLeg(u, forceUpdate, true); + } + } + + private static void updateDirectedPathLeg(UpdateStruct2 u, PathLegUpdateType lengthChange) throws Exception { + if (DEBUG) + System.out.println("PipingRules.updateDirectedPipeRun() " + u + " " + lengthChange); + PipeControlPoint dcp; + PipeControlPoint other; + boolean canMoveOther = false; + boolean dcpStart = false; + boolean inlineEnd = false; + Vector3d position; + if (u.start.isDirected()) { + dcp = u.start; + other = u.end; + position = u.startPoint; + dcpStart = true; + if (!u.reversed) + canMoveOther = true; + inlineEnd = u.end.isInline(); + + } else { + dcp = u.end; + other = u.start; + position = u.endPoint; + if (u.reversed) + canMoveOther = true; + inlineEnd = u.start.isInline(); + } + + Vector3d directedDirection = dcp.getDirection(); + Point3d directedEndPoint = new Point3d(u.endPoint); + if (u.hasOffsets) + directedEndPoint.add(u.offset); + + double mu[] = new double[2]; + + Vector3d closest; + Vector3d t = new Vector3d(); + + if (dcpStart) { + closest = MathTools.closestPointOnStraight(directedEndPoint, u.startPoint, directedDirection, mu); + t.sub(closest, directedEndPoint); + } else { + closest = MathTools.closestPointOnStraight(u.startPoint, directedEndPoint, directedDirection, mu); + t.sub(closest, u.startPoint); + } + + double distance = t.lengthSquared(); + boolean aligned = (distance < 0.002); + if (aligned) { + checkExpandPathLeg(u, lengthChange, inlineEnd); + + } else { + if (u.iter > 0) { + backIter(u); + } else { + PipeControlPoint nextToMoved; + + if (u.list.size() > 0) + if (dcpStart) + nextToMoved = u.list.get(0); + else + nextToMoved = u.list.get(u.list.size() - 1); + else if (dcpStart) + nextToMoved = u.end; + else + nextToMoved = u.start; + if (other.isVariableAngle()) { + + // TODO calculate needed space from next run end. + if (mu[0] < 1.0) { + if (dcpStart) { + closest.set(u.startPoint); + } else { + closest.set(u.endPoint); + } + closest.add(directedDirection); + } + + if (canMoveOther) { + if (DEBUG) + System.out.println("PipingRules.updateDirectedPipeRun() moved end " + other + " to " + closest); + other.setWorldPosition(closest); + if (dcpStart) { + ppNoOffset(new UpdateStruct2(u.start, u.startPoint, u.list, u.end, new Vector3d(closest), directedDirection, null, u.hasOffsets, u.iter, u.reversed, u.toRemove, u.updated)); + if (u.end.getNext() != null) + updatePathLegNext(u.end, u.updated, PathLegUpdateType.NEXT); + } else { + ppNoOffset(new UpdateStruct2(u.start, new Vector3d(closest), u.list, u.end, u.endPoint, directedDirection, null, u.hasOffsets, u.iter, u.reversed, u.toRemove, u.updated)); + if (u.start.getPrevious() != null) + updatePathLegPrev(u.start, u.updated, PathLegUpdateType.PREV); + } + } else { + // TODO : calculate needed space from next run end. + if (allowInsertRemove) + insertElbowUpdate(u, dcp, nextToMoved, dcpStart, position, directedDirection); + + else + triedIR = true; + } + } else if (other.isNonDirected() && other.getParentPoint() != null) { + // FIXME : this code was for updating branches + Vector3d bintersect = new Vector3d(); + PipeControlPoint bcp = other.getParentPoint(); + if (bcp != null && canMoveOther) { + Point3d bstart = new Point3d(); + Point3d bend = new Point3d(); + Vector3d bdir = new Vector3d(); + bcp.getInlineControlPointEnds(bstart, bend, bdir); + Vector3d nintersect = new Vector3d(); + + MathTools.intersectStraightStraight(position, directedDirection, bend, bdir, nintersect, bintersect, mu); + Vector3d dist = new Vector3d(nintersect); + dist.sub(bintersect); + canMoveOther = mu[1] > 0.0 && mu[1] < 1.0 && dist.lengthSquared() < 0.01; + } else { + // TODO : endControlPoints are undirected: calculcate + // correct position for it + throw new UnsupportedOperationException("not implemented"); + } + if (canMoveOther) { + if (DEBUG) + System.out.println("PipingRules.updateDirectedPipeRun() moved end " + other + " to " + bintersect); + // is required branch position is in possible range + bcp.setWorldPosition(bintersect); + if (dcpStart) { + checkExpandPathLeg(new UpdateStruct2(u.start, u.startPoint, u.list, u.end, new Vector3d(bintersect), directedDirection, u.offset, u.hasOffsets, u.iter, u.reversed, u.toRemove, u.updated), lengthChange); + } else { + checkExpandPathLeg(new UpdateStruct2(u.start, new Vector3d(bintersect), u.list, u.end, u.endPoint, directedDirection, u.offset, u.hasOffsets, u.iter, u.reversed, u.toRemove, u.updated), lengthChange); + } + } else { + // branch cannot be moved into right position, new turn + // / elbow must be inserted + if (allowInsertRemove) + insertElbowUpdate(u, dcp, nextToMoved, dcpStart, position, directedDirection); + else + triedIR = true; + } + + } else { // assume that control point cannot be moved, but can + // be rotated + if (allowInsertRemove) + insertElbowUpdate(u, dcp, nextToMoved, dcpStart, position, directedDirection); + else + triedIR = true; + } + } + } + + + } + + private static void updateDualDirectedPathLeg(UpdateStruct2 u, PathLegUpdateType lengthChange) throws Exception { + if (DEBUG) + System.out.println("PipingRules.updateDualDirectedPipeRun() " + u + " " + lengthChange); + + PipeControlPoint dcp1 = u.start; + PipeControlPoint dcp2 = u.end; + Point3d position1 = new Point3d(u.startPoint); + Point3d position2 = new Point3d(u.endPoint); + Point3d position1offset = new Point3d(position1); + position1offset.sub(u.offset); + Point3d position2offset = new Point3d(position2); + position2offset.add(u.offset); + Vector3d dir1 = dcp1.getDirection(); + Vector3d dir2 = dcp2.getDirection(); + Vector3d p1 = MathTools.closestPointOnStraight(position1offset, position2, dir2); + Vector3d p2 = MathTools.closestPointOnStraight(position2offset, position1, dir1); + double d1 = position1.distance(new Point3d(p1)); + double d2 = position2.distance(new Point3d(p2)); + + boolean aligned = (d1 < 0.01 && d2 < 0.01); + if (aligned) { + processPathLeg(u); + } else { + if (u.iter > 0) { + backIter(u); + } else if (allowInsertRemove){ + PipeControlPoint dcp; + PipeControlPoint next; + if (!u.reversed) { + dcp = dcp1; + if (u.list.size() > 0) + next = u.list.get(0); + else + next = dcp2; + } else { + dcp = dcp2; + if (u.list.size() > 0) + next = u.list.get(u.list.size() - 1); + else + next = dcp1; + } + + p1 = dcp.getWorldPosition(); + // FIXME: calculate position of the elbows properly. + if (!u.reversed) + p1.add(dir1); + else + p1.add(dir2); + + if (!u.reversed) + p2 = MathTools.closestPointOnStraight(new Point3d(p1), position2, dir2); + else + p2 = MathTools.closestPointOnStraight(new Point3d(p1), position1, dir1); + + + PipeControlPoint tcp1 = insertElbow(dcp, next, p1); + PipeControlPoint tcp2 = insertElbow(tcp1, next, p2); + + if (DEBUG) + System.out.println("PipingRules.updateDualDirectedPipeRun() created two turns " + tcp1 + " " + tcp2); + + if (!u.reversed) { + Vector3d dd = new Vector3d(p2); + dd.sub(p1); + dir2.negate(); + updatePathLegNext(u.start, u.updated, PathLegUpdateType.NONE); + updatePathLegNext(tcp1, u.updated, PathLegUpdateType.NONE); + if (!u.reversed) + updatePathLegNext(tcp2, u.updated, PathLegUpdateType.NONE); + else + updatePathLegPrev(tcp2, u.updated, PathLegUpdateType.NONE); + } else { + Vector3d dd = new Vector3d(p1); + dd.sub(p2); + dir2.negate(); + updatePathLegNext(tcp1, u.updated, PathLegUpdateType.NONE); + updatePathLegNext(tcp2, u.updated, PathLegUpdateType.NONE); + if (!u.reversed) + updatePathLegNext(u.start, u.updated, PathLegUpdateType.NONE); + else + updatePathLegPrev(u.start, u.updated, PathLegUpdateType.NONE); + } + } else { + triedIR = true; + } + } + + } + + private static void insertElbowUpdate(UpdateStruct2 u, PipeControlPoint dcp, PipeControlPoint next, boolean dcpStart, Vector3d position, Vector3d directedDirection) throws Exception{ + + Vector3d closest = new Vector3d(position); + closest.add(directedDirection); + PipeControlPoint tcp = null; + if (dcpStart) + tcp = insertElbow(dcp, next, new Vector3d(closest)); + else + tcp = insertElbow(next, dcp, new Vector3d(closest)); + + if (DEBUG) + System.out.println("PipingRules.updateDirectedPipeRun() inserted " + tcp); + + if (dcpStart) { + // update pipe run from new turn to other end + ppNoDir(tcp, new Vector3d(closest), u.list, u.end, u.endPoint, u.hasOffsets, u.iter, u.reversed, u.toRemove, u.updated); + // update pipe run from directed to new turn + processPathLeg(new UpdateStruct2(u.start, u.startPoint, new ArrayList(), tcp, new Vector3d(closest), directedDirection, new Vector3d(), false, 0, false, new ArrayList(), u.updated)); + } else { + // update pipe run from other end to new turn + ppNoDir(u.start, u.startPoint, u.list, tcp, new Vector3d(closest), u.hasOffsets, u.iter, u.reversed, u.toRemove, u.updated); + // update pipe run from new turn to directed + processPathLeg(new UpdateStruct2(tcp, new Vector3d(closest), new ArrayList(), u.end, u.endPoint, directedDirection, new Vector3d(), false, 0, false, new ArrayList(), u.updated)); + } + } + + /** + * Checks if turns can be removed (turn angle near zero) + */ + private static int checkTurns(UpdateStruct2 u, PathLegUpdateType lengthChange) throws Exception { + if (DEBUG) + System.out.println("PipingRules.checkTurns() " + u.start + " " + u.end); + boolean startRemoved = false; + boolean endRemoved = false; + if (u.start.isVariableAngle()) { + // this won't work properly if inline control points are not updated + PipeControlPoint startPrev = u.start.getPrevious(); + if (startPrev != null) { + double a; + if (!u.hasOffsets) { + a = updateTurnControlPointTurn(u.start, startPrev, u.end); + } else { + Vector3d ep = new Vector3d(u.endPoint); + ep.add(u.offset); + a = updateTurnControlPointTurn(u.start, u.startPoint, startPrev.getPosition(), ep); + + } + if (a < MIN_TURN_ANGLE && u.start.isDeletable()) + startRemoved = true; + else if (lengthChange == PathLegUpdateType.PREV || lengthChange == PathLegUpdateType.PREV_S) { + PathLegUpdateType type; + if (lengthChange == PathLegUpdateType.PREV_S) + type = PathLegUpdateType.PREV; + else + type = PathLegUpdateType.NONE; + updatePathLegPrev(u.start, u.start, type); + } + } + } + if (u.end.isVariableAngle()) { + + PipeControlPoint endNext = u.end.getNext(); + if (endNext != null) { + double a; + if (!u.hasOffsets) { + a = updateTurnControlPointTurn(u.end, u.start, endNext); + } else { + Vector3d sp = new Vector3d(u.startPoint); + sp.sub(u.offset); + a = updateTurnControlPointTurn(u.end, u.endPoint, sp, endNext.getPosition()); + } + if (a < MIN_TURN_ANGLE && u.end.isDeletable()) + endRemoved = true; + else if (lengthChange == PathLegUpdateType.NEXT || lengthChange == PathLegUpdateType.NEXT_S) { + PathLegUpdateType type; + if (lengthChange == PathLegUpdateType.NEXT_S) + type = PathLegUpdateType.NEXT; + else + type = PathLegUpdateType.NONE; + updatePathLegNext(u.end, u.end, type); + } + } + } + if (DEBUG) + System.out.println("PipingRules.checkTurns() res " + startRemoved + " " + endRemoved); + if (!startRemoved && !endRemoved) + return REMOVE_NONE; + if (startRemoved && endRemoved) + return REMOVE_BOTH; + if (startRemoved) + return REMOVE_START; + return REMOVE_END; + } + + /** + * Expands piperun search over turns that are going to be removed + * + */ + private static void expandPathLeg(UpdateStruct2 u, int type) throws Exception { + if (DEBUG) + System.out.println("PipingRules.expandPipeline " + u.start + " " + u.end); + ArrayList newList = new ArrayList(); + switch (type) { + case REMOVE_NONE: + throw new RuntimeException("Error in piping rules"); + case REMOVE_START: + u.toRemove.add(new ExpandIterInfo(u.start, REMOVE_START)); + u.start = u.start.findPreviousEnd(); + u.startPoint = u.start.getPosition(); + u.start.findNextEnd(newList); + newList.addAll(u.list); + u.list = newList; + break; + case REMOVE_END: + u.toRemove.add(new ExpandIterInfo(u.end, REMOVE_END)); + u.end = u.end.findNextEnd(newList); + u.endPoint = u.end.getPosition(); + u.list.addAll(newList); + break; + case REMOVE_BOTH: + u.toRemove.add(new ExpandIterInfo(u.start, u.end)); + u.start = u.start.findPreviousEnd(); + u.startPoint = u.start.getPosition(); + u.start.findNextEnd(newList); + newList.addAll(u.list); + u.list = newList; + newList = new ArrayList(); + u.end = u.end.findNextEnd(newList); + u.endPoint = u.end.getPosition(); + u.list.addAll(newList); + break; + default: + throw new RuntimeException("Error in piping rules"); + + } + u.offset = new Vector3d(); + if (u.hasOffsets) { + u.dir.normalize(); + for (PipeControlPoint icp : u.list) { + if (icp.isOffset()) { + u.offset.add(icp.getSizeChangeOffsetVector(u.dir)); + } else if (icp.isDualSub()) + ErrorLogger.defaultLogError("Updating pipe run, found offset controlpoint " + icp, new Exception("ASSERT!")); + } + } + if (DEBUG) + System.out.println("PipingRules.expandPipeline expanded " + u.start + " " + u.end); + u.iter++; + updatePathLeg(u, PathLegUpdateType.NONE); + } + + /** + * reverts one iteration of turn removing back) + */ + private static void backIter(UpdateStruct2 u) throws Exception { + + if (DEBUG) + System.out.println("PipingRules.backIter" + u.start + " " + u.end); + if (u.iter == 0) + throw new RuntimeException("Error in piping rules"); + ExpandIterInfo info = u.toRemove.get(u.toRemove.size() - 1); + u.toRemove.remove(u.toRemove.size() - 1); + if (info.getType() == REMOVE_START || info.getType() == REMOVE_BOTH) { + while (u.list.size() > 0) { + PipeControlPoint icp = u.list.get(0); + if (icp.getPrevious().equals(info.getStart())) + break; + u.list.remove(icp); + } + u.start = info.getStart(); + } + if (info.getType() == REMOVE_END || info.getType() == REMOVE_BOTH) { + while (u.list.size() > 0) { + PipeControlPoint icp = u.list.get(u.list.size() - 1); + if (icp.getNext().equals(info.getEnd())) + break; + u.list.remove(icp); + } + u.end = info.getEnd(); + } + u.offset = new Vector3d(); + if (u.hasOffsets) { + u.dir.normalize(); + for (PipeControlPoint icp : u.list) { + if (icp.isOffset()) { + u.offset.add(icp.getSizeChangeOffsetVector(u.dir)); + } else if (icp.isDualSub()) + ErrorLogger.defaultLogError("Updating pipe run, found offset controlpoint " + icp, new Exception("ASSERT!")); + } + } + processPathLeg(u); + + } + + /** + * Processes pipe run (removes necessary turns and updates run ends) + */ + // private static void processPathLeg(PipeControlPoint start, Point3d + // startPoint,ArrayList list, PipeControlPoint + // end,Point3d endPoint, Vector3d dir,Vector3d offset, boolean + // hasOffsets,int iter, boolean reversed, ArrayList + // toRemove) throws TransactionException { + + private static void processPathLeg(UpdateStruct2 u) throws Exception { + if (DEBUG) + System.out.println("PipingRules.processPathLeg " + u.start + " " + u.end); + processPathLeg(u, true, true); + } + + private static void processPathLeg(UpdateStruct2 u, boolean updateEnds, boolean updateInline) throws Exception { + if (DEBUG) + System.out.println("PipingRules.processPathLeg " + u.start + " " + u.end); + + if (u.toRemove.size() > 0) { + for (ExpandIterInfo info : u.toRemove) { + if (info.getStart() != null) { + info.getStart()._remove(); + } + if (info.getEnd() != null) { + info.getEnd()._remove(); + } + } + // ControlPointTools.removeControlPoint may remove mo0re than one + // CP; + // we must populate inline CP list again. + u.list.clear(); + u.start.findNextEnd( u.list); + } + // FIXME : inline CPs are update twice because their positions must be + // updated before and after ends. + updateInlineControlPoints(u, false); + + if (updateEnds) { + if (u.start.isTurn()) { + updateTurnControlPointTurn(u.start, u.start.getPrevious(), u.start.getNext()); +// updatePathLegPrev(u.start, u.start, PathLegUpdateType.NONE); + } else if (u.start.isEnd()) { + updateEndComponentControlPoint(u.start, u.startPoint, u.endPoint); + } else if (u.start.isInline()) { + updateControlPointOrientation(u.start); + } + if (u.end.isTurn()) { + updateTurnControlPointTurn(u.end, u.end.getPrevious(), u.end.getNext()); +// updatePathLegNext(u.end, u.end, PathLegUpdateType.NONE); + } else if (u.end.isEnd()) { + updateEndComponentControlPoint(u.end, u.startPoint, u.endPoint); + } else if (u.end.isInline()) { + updateControlPointOrientation(u.end); + } + + } else { + if (u.start.isEnd()) { + updateEndComponentControlPoint(u.start, u.startPoint, u.endPoint); + } + if (u.end.isEnd()) { + updateEndComponentControlPoint(u.end, u.startPoint, u.endPoint); + } + } + if (updateInline) + updateInlineControlPoints(u, true); + + } + + /** + * Processes pipe run and recalculates offset + */ + // private static void processPathLeg(PipeControlPoint start, Point3d + // startPoint,ArrayList list, PipeControlPoint + // end,Point3d endPoint, Vector3d dir, boolean hasOffsets,int iter, boolean + // reversed, ArrayList toRemove) throws TransactionException + // { + private static void processPathLegNoOffset(UpdateStruct2 u) throws Exception { + if (DEBUG) + System.out.println("PipingRules.processPathLeg " + u.start + " " + u.end); + Vector3d offset = new Vector3d(); + if (u.hasOffsets) { + u.dir.normalize(); + for (PipeControlPoint icp : u.list) { + if (icp.isOffset()) { + offset.add(icp.getSizeChangeOffsetVector(u.dir)); + } else if (icp.isDualSub()) { + ErrorLogger.defaultLogError("Updating pipe run, found offset controlpoint " + icp, new Exception("ASSERT!")); + } + } + } + processPathLeg(u); + } + + private static void updateOffsetPoint(PipeControlPoint sccp, Vector3d offset) { + Vector3d world = sccp.getWorldPosition(); + world.add(offset); + PipeControlPoint ocp = sccp.getSubPoint().iterator().next(); + ocp.setWorldPosition(world); + } + + private static void updatePathLegPrev(PipeControlPoint start, PipeControlPoint updated, PathLegUpdateType lengthChange) throws Exception { + ArrayList list = new ArrayList(); + PipeControlPoint end = start.findPreviousEnd(list); + updatePathLegPrev(start, list, end, updated, lengthChange); + } + + private static void updatePathLegPrev(PipeControlPoint start, ArrayList list, PipeControlPoint end, PipeControlPoint updated, PathLegUpdateType lengthChange) throws Exception { + // reverses the list + ArrayList nextList = new ArrayList(); + for (PipeControlPoint icp : list) { + if (icp.isDualSub()) { + nextList.add(0, icp.getParentPoint()); + } else { + nextList.add(0, icp); + } + + } + updatePathLeg(end, nextList, start, true, 0, new ArrayList(), updated, lengthChange); + + } + + /** + * Updates InlineControlPoints position when straight pipe's end(s) have + * been changed) + * + * @param pipeline + * @param icp + * @param nextPoint + * @param prevPoint + */ + private static void updateInlineControlPoint(PipeControlPoint icp, Vector3d nextPoint, Vector3d prevPoint, Vector3d dir) { + if (DEBUG) + System.out.println("PipingRules.updateInlineControlPoint() " + icp); + + Vector3d inlinePoint = icp.getWorldPosition(); + if (DEBUG) + System.out.print("InlineControlPoint update " + icp + " " + inlinePoint + " " + prevPoint + " " + nextPoint); + Vector3d newInlinePoint = null; + boolean branchUpdate = false; + PipeControlPoint becp = null; + for (PipeControlPoint pcp : icp.getSubPoint()) + if (pcp.isNonDirected()) { + branchUpdate = true; + becp = pcp; + break; + } + + if (DUMMY || !branchUpdate) { + newInlinePoint = MathTools.closestPointOnEdge(new Vector3d(inlinePoint), new Vector3d(nextPoint), new Vector3d(prevPoint)); + } else { + + // FIXME : can only handle one branch + PipeControlPoint p = null; + if (becp.getNext() != null) { + p = becp.findNextEnd(); + } else if (becp.getPrevious() != null) { + p = becp.findPreviousEnd(); + } + if (p == null) { + newInlinePoint = MathTools.closestPointOnEdge(new Vector3d(inlinePoint), new Vector3d(nextPoint), new Vector3d(prevPoint)); + } else { + Vector3d branchLegEnd = p.getWorldPosition(); + Vector3d dir2 = new Vector3d(inlinePoint); + dir2.sub(branchLegEnd); + Vector3d dir1 = new Vector3d(nextPoint); + dir1.sub(prevPoint); + newInlinePoint = new Vector3d(); + double mu[] = new double[2]; + MathTools.intersectStraightStraight(new Vector3d(prevPoint), dir1, new Vector3d(branchLegEnd), dir2, newInlinePoint, new Vector3d(), mu); + if (DEBUG) + System.out.println(mu[0]); + // FIXME : reserve space + if (mu[0] < 0.0) { + newInlinePoint = new Vector3d(prevPoint); + } else if (mu[0] > 1.0) { + newInlinePoint = new Vector3d(nextPoint); + } + } + } + if (DEBUG) + System.out.println(" " + newInlinePoint); + + icp.setWorldPosition(newInlinePoint); + updateControlPointOrientation(icp); + } + + /** + * Updates InlineControlPoints position when straight pipe's end(s) have + * been changed) + * + * @param pipeline + * @param icp + * @param nextPoint + * @param prevPoint + */ + private static void updateEndComponentControlPoint(PipeControlPoint ecp, Vector3d start, Vector3d end) throws Exception { + if (DEBUG) + System.out.println("PipingRules.updateEndComponentControlPoint() " + ecp); + // PipeControlPoint next = ecp.getNext(); + // PipeControlPoint prev = ecp.getPrevious(); + // if (next != null) { + // end = G3DTools.getPoint(next.getLocalPosition()); + // start = G3DTools.getPoint(ecp.getLocalPosition()); + // } else if (prev != null) { + // end = G3DTools.getPoint(ecp.getLocalPosition()); + // start = G3DTools.getPoint(prev.getLocalPosition()); + // } else { + // // TODO : warning? + // return; + // } + // Vector3d dir = new Vector3d (end); + // dir.sub(start); + // dir.normalize(); + // G3DTools.setTuple(ecp.getDirection(), dir); + if (!ecp.isFixed()) + updateControlPointOrientation(ecp); + + for (PipeControlPoint pcp : ecp.getSubPoint()) { + // TODO update position + updatePathLegEndControlPoint(pcp); + } + } + + private static void updateControlPointOrientation(PipeControlPoint pcp) { + // FIXME : hack to bypass variable length components orientation +// if (pcp.getAtMostOneRelatedObject(ProcessResource.g3dResource.HasWorldOrientation) == null) +// return; +// if (pcp.rotationAngle == null) +// return; + Double angleO = pcp.getRotationAngle(); + double angle = 0.0; + if (angleO != null) + angle = angleO; + + Quat4d q = pcp.getControlPointOrientationQuat(angle); + pcp.setWorldOrientation(q); + } + + /** + * Updates all branches when branch's position has been changed + * + * @param bcp + */ + private static void updateBranchControlPointBranches(PipeControlPoint bcp) throws Exception { + if (DEBUG) + System.out.println("PipingRules.updateBranchControlPointBranches() " + bcp); + if (bcp.isDualInline()) + return; + Collection branches = bcp.getSubPoint(); + if (branches.size() == 0) { + if (DEBUG) + System.out.println("No Branches found"); + return; + } + + for (PipeControlPoint pcp : branches) { + updatePathLegEndControlPoint(pcp); + } + } + + /** + * Recalculates turn control point's internal data (turn angle and offset) + * + * @param tcp + * @param prev + * @param next + */ + private static double updateTurnControlPointTurn(PipeControlPoint tcp, PipeControlPoint prev, PipeControlPoint next) { + if (DEBUG) + System.out.println("PipingTools.updateTurnControlPointTurn()" + tcp); + if (next == null || prev == null) + return Math.PI; // FIXME : argh + Vector3d middlePoint = tcp.getWorldPosition(); + Vector3d nextPoint = next.getWorldPosition(); + Vector3d prevPoint = prev.getWorldPosition(); + return updateTurnControlPointTurn(tcp, middlePoint, prevPoint, nextPoint); + } + + /** + * Recalculates turn control point's internal data (turn angle and offset) + * + * @param tcp + * @param middlePoint + * @param nextPoint + * @param prevPoint + */ + private static double updateTurnControlPointTurn(PipeControlPoint tcp, Vector3d middlePoint, Vector3d prevPoint, Vector3d nextPoint) { + + Vector3d dir1 = new Vector3d(middlePoint); + dir1.sub(prevPoint); + Vector3d dir2 = new Vector3d(nextPoint); + dir2.sub(middlePoint); + if (DEBUG) + System.out.println("PipingTools.updateTurnControlPointTurn " + tcp + " " + prevPoint + " " + middlePoint + " " + nextPoint); + return updateTurnControlPointTurn(tcp, dir1, dir2); + } + + private static double updateTurnControlPointTurn(PipeControlPoint tcp, Vector3d dir1, Vector3d dir2) { + double turnAngle = dir1.angle(dir2); + + double angle = Math.PI - turnAngle; + + Vector3d turnAxis = new Vector3d(); + turnAxis.cross(dir1, dir2); + if (turnAxis.lengthSquared() > MathTools.NEAR_ZERO) { + double elbowRadius = tcp.getPipelineComponent().getPipeRun().getTurnRadius(); + double R = elbowRadius / Math.tan(angle * 0.5); + + turnAxis.normalize(); + tcp.setTurnAngle(turnAngle); + tcp.setLength(R);// setComponentOffsetValue(R); + tcp.setTurnAxis(turnAxis); +// tcp.setPosition(tcp.getPosition()); + } else { + turnAngle = 0.0; + tcp.setTurnAngle(0.0); + tcp.setLength(0.0); + tcp.setTurnAxis(MathTools.Y_AXIS); + } + updateControlPointOrientation(tcp); + if (DEBUG) + System.out.println("PipingTools.updateTurnControlPointTurn " + dir1 + " " + dir2 + " " + turnAngle + " " + turnAxis); + return turnAngle; + } + + public static List getControlPoints(PipeRun pipeRun) { + List list = new ArrayList(); + if (pipeRun.getControlPoints().size() == 0) + return list; + PipeControlPoint pcp = pipeRun.getControlPoints().iterator().next(); + while (pcp.getPrevious() != null) { + PipeControlPoint prev = pcp.getPrevious(); + if (prev.getPipeRun() != pipeRun) + break; + pcp = prev; + } + if (pcp.isDualSub()) { + pcp = pcp.getParentPoint(); + } + list.add(pcp); + while (pcp.getNext() != null) { + pcp = pcp.getNext(); + if (pcp.getPipeRun() != pipeRun) + break; + list.add(pcp); + } + return list; + } + + public static void reverse(PipeRun pipeRun) { + List list = getControlPoints(pipeRun); + if (list.size() <= 1) + return; // nothing to do. + + for (int i = 0 ; i < list.size(); i++) { + boolean first = i == 0; + boolean last = i == list.size() - 1; + PipeControlPoint current = list.get(i); + PipeControlPoint currentSub = null; + if (current.isDualInline()) + currentSub = current.getSubPoint().get(0); + if (first) { + PipeControlPoint next = list.get(i+1); + if (next.isDualInline()) + next = next.getSubPoint().get(0); + current.setNext(null); + current.setPrevious(next); + if (currentSub != null) { + currentSub.setNext(null); + currentSub.setPrevious(next); + } + } else if (last) { + PipeControlPoint prev = list.get(i-1); + + current.setPrevious(null); + current.setNext(prev); + + if (currentSub != null) { + currentSub.setPrevious(null); + currentSub.setNext(prev); + } + } else { + PipeControlPoint prev = list.get(i-1); + PipeControlPoint next = list.get(i+1); + if (next.isDualInline()) + next = next.getSubPoint().get(0); + + + current.setPrevious(next); + current.setNext(prev); + + if (currentSub != null) { + currentSub.setPrevious(next); + currentSub.setNext(prev); + } + + } + } + } + + public static void merge(PipeRun run1, PipeRun r2) { + Map positions = new HashMap(); + Map orientations = new HashMap(); + for (PipeControlPoint pcp : r2.getControlPoints()) { + positions.put(pcp, pcp.getWorldPosition()); + orientations.put(pcp, pcp.getWorldOrientation()); + } + for (PipeControlPoint pcp : r2.getControlPoints()) { + r2.deattachChild(pcp); + run1.addChild(pcp); + PipelineComponent component = pcp.getPipelineComponent(); + if (component != null) { + if (!(component instanceof Nozzle)) { + component.deattach(); + run1.addChild(component); + } else { + Nozzle n = (Nozzle)component; + n.setPipeRun(run1); + } + } + } + r2.remove(); + + } + + public static void validate(PipeRun pipeRun) { + if (pipeRun == null) + return; + Collection pcps = pipeRun.getControlPoints(); + int count = 0; + for (PipeControlPoint pcp : pcps) { + if (pcp.getParentPoint() == null || pcp.getParentPoint().getPipeRun() != pipeRun) + count++; + } + List runPcps = getControlPoints(pipeRun); + if (runPcps.size() != count) { + System.out.println("Run is not connected"); + } + for (PipeControlPoint pcp : pcps) { + if (pcp.getParentPoint() == null) { + PipeControlPoint sub = null; + if (pcp.isDualInline()) + sub = pcp.getSubPoint().get(0); + PipeControlPoint next = pcp.getNext(); + PipeControlPoint prev = pcp.getPrevious(); + if (next != null) { + if (!(next.getPrevious() == pcp || next.getPrevious() == sub)) { + System.out.println("Inconsistency between " + pcp + " -> " +next ); + } + } + if (prev != null) { + PipeControlPoint prevParent = null; + if (prev.isDualSub()) { + prevParent = prev.getParentPoint(); + } else if (prev.isDualInline()) { + System.out.println("Inconsistency between " + pcp + " <-- " +prev ); + } + if (!(prev.getNext() == pcp && (prevParent == null || prevParent.getNext() == pcp))) { + System.out.println("Inconsistency between " + pcp + " <-- " +prev ); + } + } + } + } + } + + public static void splitVariableLengthComponent(PipelineComponent newComponent, InlineComponent splittingComponent, boolean assignPos) throws Exception{ + assert(!splittingComponent.getControlPoint().isFixed()); + assert(!(newComponent instanceof InlineComponent && !newComponent.getControlPoint().isFixed())); + PipeControlPoint newCP = newComponent.getControlPoint(); + PipeControlPoint splittingCP = splittingComponent.getControlPoint(); + PipeControlPoint nextCP = splittingCP.getNext(); + PipeControlPoint prevCP = splittingCP.getPrevious(); + + /* there are many different cases to insert new component when + it splits existing VariableLengthinlineComponent. + + 1. VariableLengthComponet is connected from both sides: + - insert new component between VariableLength component and component connected to it + - insert new VariableLengthComponent between inserted component and component selected in previous step + + 2. VariableLengthComponent is connected from one side + - Use previous case or: + - Insert new component to empty end + - Insert new VariableLength component to inserted components empty end + + 3. VariableLength is not connected to any component. + - Should not be possible, at least in current implementation. + - Could be done using second case + + */ + + if (nextCP == null && prevCP == null) { + // this should not be possible + throw new RuntimeException("VariableLengthComponent " + splittingComponent + " is not connected to anything."); + } + double reservedLength = splittingComponent.getControlPoint().getLength(); + double newLength = newComponent.getControlPoint().getLength(); + + + Point3d next = new Point3d(); + Point3d prev = new Point3d(); + splittingCP.getInlineControlPointEnds(prev, next); + + Vector3d newPos = null; + if (assignPos) { + newPos = new Vector3d(prev); + Vector3d dir = new Vector3d(next); + dir.sub(prev); + dir.scale(0.5); + newPos.add(dir); + newComponent.setWorldPosition(newPos); + } else { + newPos = newComponent.getWorldPosition(); + } + + + + Vector3d dir = new Vector3d(next); + dir.sub(prev); + dir.normalize(); + dir.scale(newLength * 0.5); + Point3d vn = new Point3d(newPos); + Point3d vp = new Point3d(newPos); + vn.add(dir); + vp.sub(dir); + double ln = vn.distance(next); + double lp = vp.distance(prev); + vp.interpolate(prev, 0.5); + vn.interpolate(next, 0.5); + + + PipeControlPoint newVariableLengthCP = null;//insertStraight(pcp1, pcp2, pos, length); + if (nextCP == null) { + newCP.insert(splittingCP, Direction.NEXT); + newVariableLengthCP = insertStraight(newCP, Direction.NEXT, new Vector3d(vn), ln); + splittingCP.setWorldPosition(new Vector3d(vp)); +// ControlPointTools.setWorldPosition(splittingCP, vp); +// splittingCP.setRelatedScalarDouble(ProcessResource.plant3Dresource.HasLength, lp); + } else if (prevCP == null) { + newCP.insert(splittingCP, Direction.PREVIOUS); + newVariableLengthCP = insertStraight(newCP, Direction.PREVIOUS, new Vector3d(vp), lp); + splittingCP.setWorldPosition(new Vector3d(vn)); +// splittingCP.setRelatedScalarDouble(ProcessResource.plant3Dresource.HasLength, ln); + } else { + newCP.insert(splittingCP, nextCP); + newVariableLengthCP = insertStraight(newCP, nextCP, new Vector3d(vn), ln); + splittingCP.setWorldPosition(new Vector3d(vp)); +// splittingCP.setRelatedScalarDouble(ProcessResource.plant3Dresource.HasLength, lp); + } + positionUpdate(newCP); + + } + + public static void addSizeChange(boolean reversed, PipeRun pipeRun, PipeRun other, InlineComponent reducer, PipeControlPoint previous, PipeControlPoint next) { + PipeControlPoint pcp = reducer.getControlPoint(); + PipeControlPoint ocp = pcp.getSubPoint().get(0); + if (!reversed) { + String name = pipeRun.getUniqueName("Reducer"); + reducer.setName(name); + pipeRun.addChild(reducer); + other.addChild(ocp); + reducer.setAlternativePipeRun(other); + + previous.setNext(pcp); + pcp.setPrevious(previous); + ocp.setPrevious(previous); + if (next != null) { + pcp.setNext(next); + ocp.setNext(next); + next.setPrevious(ocp); + } + } else { + String name = other.getUniqueName("Reducer"); + reducer.setName(name); + other.addChild(reducer); + pipeRun.addChild(ocp); + reducer.setAlternativePipeRun(pipeRun); + + if (next != null) { + next.setNext(pcp); + pcp.setPrevious(next); + ocp.setPrevious(next); + } + pcp.setNext(previous); + ocp.setNext(previous); + previous.setPrevious(ocp); + } + } +} diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/utils/ComponentUtils.java b/org.simantics.plant3d/src/org/simantics/plant3d/utils/ComponentUtils.java new file mode 100644 index 00000000..af64f180 --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/utils/ComponentUtils.java @@ -0,0 +1,154 @@ +package org.simantics.plant3d.utils; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +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.exception.DatabaseException; +import org.simantics.layer0.Layer0; +import org.simantics.opencascade.SolidModelProvider; +import org.simantics.plant3d.ontology.Plant3D; +import org.simantics.plant3d.scenegraph.EndComponent; +import org.simantics.plant3d.scenegraph.InlineComponent; +import org.simantics.plant3d.scenegraph.Nozzle; +import org.simantics.plant3d.scenegraph.P3DRootNode; +import org.simantics.plant3d.scenegraph.PipelineComponent; +import org.simantics.plant3d.scenegraph.TurnComponent; + +public class ComponentUtils { + + + private static Map> clazzes = new HashMap>(); + private static Map providers = 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); + + for (String typeURI : types) { + load(graph, typeURI); + } + } + }); + } + + private static SolidModelProvider getProvider(ReadGraph graph, Resource type) throws DatabaseException { + + Layer0 l0 = Layer0.getInstance(graph); + Plant3D p3d = Plant3D.getInstance(graph); + Resource geom = graph.getPossibleObject(type,p3d.hasGeometry); + if (geom == null) { + for (Resource a : graph.getObjects(type, l0.Asserts)) { + if (p3d.hasGeometry.equals(graph.getPossibleObject(a, l0.HasPredicate))) { + geom = graph.getPossibleObject(a, l0.HasObject); + break; + } + } + } + if (geom != null) { + SolidModelProvider provider = graph.adapt(geom, SolidModelProvider.class); + return provider; + } + return null; + } + + private static Class getClazz(ReadGraph graph, Resource type) throws DatabaseException { + Plant3D p3d = Plant3D.getInstance(graph); + if (graph.isInheritedFrom(type, p3d.InlineComponent)) + return InlineComponent.class; + if (graph.isInheritedFrom(type, p3d.TurnComponent)) + return TurnComponent.class; + if (graph.isInheritedFrom(type, p3d.EndComponent)) + return EndComponent.class; + if (graph.isInheritedFrom(type, p3d.Nozzle)) + return Nozzle.class; + return null; + } + + private static void load(ReadGraph graph, String typeURI) throws DatabaseException { + Plant3D p3d = Plant3D.getInstance(graph); + Resource type = graph.getResource(typeURI); + + SolidModelProvider provider = getProvider(graph, type); + if (provider != null || graph.hasStatement(type,p3d.NonVisibleComponent)) { + providers.put(typeURI, provider); + ComponentUtils.clazzes.put(typeURI,getClazz(graph, type)); + return; + } + throw new DatabaseException("Cannot find component for " + typeURI); + } + + private static void load(final String typeURI) throws DatabaseException { + Simantics.getSession().syncRequest(new ReadRequest() { + + @Override + public void run(ReadGraph graph) throws DatabaseException { + load(graph,typeURI); + } + }); + } + + public static PipelineComponent createComponent(P3DRootNode root, String typeURI) throws Exception { + Class type = clazzes.get(typeURI); + SolidModelProvider provider = providers.get(typeURI); + if (type == null || provider == null) { + load(typeURI); + type = clazzes.get(typeURI); + provider = providers.get(typeURI); + } + //PipelineComponent component = type.newInstance(); + PipelineComponent component = null; + if (type == InlineComponent.class) { + component = root.createInline(); + } else if (type == TurnComponent.class) { + component = root.createTurn(); + } else if (type == EndComponent.class) { + component = root.createTurn(); + } else if (type == Nozzle.class) { + component = root.createNozzle(); + } + component.setType(typeURI); + component.setGeometry(provider); + return component; + } + + public static InlineComponent createStraight(P3DRootNode root) throws Exception{ + InlineComponent component = root.createInline(); + component.setType(Plant3D.URIs.Builtin_Straight); + component.setGeometry(providers.get(Plant3D.URIs.Builtin_Straight)); + return component; + } + + public static TurnComponent createTurn(P3DRootNode root) throws Exception { + TurnComponent elbow = root.createTurn(); + elbow.setType(Plant3D.URIs.Builtin_Elbow); + elbow.setGeometry(providers.get(Plant3D.URIs.Builtin_Elbow)); + return elbow; + } + + public static InlineComponent createReducer(P3DRootNode root) throws Exception { + InlineComponent component = root.createInline(); + component.setType(Plant3D.URIs.Builtin_ConcentricReducer); + component.setGeometry(providers.get(Plant3D.URIs.Builtin_ConcentricReducer)); + return component; + } + + public static InlineComponent createBranchSplit(P3DRootNode root) throws Exception { + InlineComponent component = root.createInline(); + component.setType(Plant3D.URIs.Builtin_BranchSplitComponent); + return component; + } +} diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/utils/Item.java b/org.simantics.plant3d/src/org/simantics/plant3d/utils/Item.java new file mode 100644 index 00000000..61ef6c9a --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/utils/Item.java @@ -0,0 +1,79 @@ +package org.simantics.plant3d.utils; + +public class Item { + + public enum Type{EQUIPMENT,INLINE,TURN,END,NOZZLE}; + + private String uri; + private String name; + + private Type type; + private boolean code = false; + private boolean variable = false; + private boolean sizeChange = false; + + + public Item(String type, String name) { + this.uri = type; + this.name = name; + } + + + + public String getUri() { + return uri; + } + + public String getName() { + return name; + } + + public Type getType() { + return type; + } + + public void setType(Type type) { + this.type = type; + } + + public boolean isCode() { + return code; + } + + + + public void setCode(boolean code) { + this.code = code; + } + + public boolean isVariable() { + return variable; + } + + public void setVariable(boolean variable) { + this.variable = variable; + } + + public boolean isSizeChange() { + return sizeChange; + } + + public void setSizeChange(boolean sizeChange) { + this.sizeChange = sizeChange; + } + + + + @Override + public boolean equals(Object obj) { + if (obj.getClass() != getClass()) + return false; + return uri.equals(((Item)obj).uri); + } + + @Override + public int hashCode() { + return uri.hashCode(); + } + +} diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/utils/P3DUtil.java b/org.simantics.plant3d/src/org/simantics/plant3d/utils/P3DUtil.java new file mode 100644 index 00000000..b34f4f07 --- /dev/null +++ b/org.simantics.plant3d/src/org/simantics/plant3d/utils/P3DUtil.java @@ -0,0 +1,162 @@ +package org.simantics.plant3d.utils; + +import java.util.ArrayList; +import java.util.List; + +import org.simantics.Simantics; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.request.Read; +import org.simantics.layer0.Layer0; +import org.simantics.plant3d.ontology.Plant3D; +import org.simantics.plant3d.utils.Item.Type; +import org.simantics.ui.SimanticsUI; + +public class P3DUtil { + + public static List getEquipments() throws DatabaseException { + return Simantics.getSession().syncRequest(new Read>() { + @Override + public List perform(ReadGraph graph) throws DatabaseException { + Plant3D p3d = Plant3D.getInstance(graph); + Resource project = Simantics.getProject().get(); + Resource builtins = graph.getResource(Plant3D.URIs.Builtin); + List actions = getItems(graph, project,p3d.Equipment); + actions.addAll(getItems(graph, builtins,p3d.Equipment)); + return actions; + } + + + }); + } + + public static List getNozzles() throws DatabaseException { + return Simantics.getSession().syncRequest(new Read>() { + @Override + public List perform(ReadGraph graph) throws DatabaseException { + Plant3D p3d = Plant3D.getInstance(graph); + ItemQuery query = new ItemQuery(p3d.Nozzle); + return graph.syncRequest(query); + } + }); + } + + private static class ItemQuery implements Read> { + private Resource type; + public ItemQuery(Resource type) { + this.type = type; + } + + @Override + public List perform(ReadGraph graph) throws DatabaseException { + Resource project = Simantics.getProject().get(); + Resource builtins = graph.getResource(Plant3D.URIs.Builtin); + List actions = getItems(graph, project,type); + actions.addAll(getItems(graph, builtins,type)); + return actions; + } + } + + public static List getEnds() throws DatabaseException { + return Simantics.getSession().syncRequest(new Read>() { + @Override + public List perform(ReadGraph graph) throws DatabaseException { + Plant3D p3d = Plant3D.getInstance(graph); + ItemQuery query = new ItemQuery(p3d.EndComponent); + return graph.syncRequest(query); + } + }); + } + + public static List getTurns() throws DatabaseException { + return Simantics.getSession().syncRequest(new Read>() { + @Override + public List perform(ReadGraph graph) throws DatabaseException { + Plant3D p3d = Plant3D.getInstance(graph); + ItemQuery query = new ItemQuery(p3d.TurnComponent); + return graph.syncRequest(query); + } + }); + } + + public static List getInlines() throws DatabaseException { + return Simantics.getSession().syncRequest(new Read>() { + @Override + public List perform(ReadGraph graph) throws DatabaseException { + Plant3D p3d = Plant3D.getInstance(graph); + ItemQuery query = new ItemQuery(p3d.InlineComponent); + return graph.syncRequest(query); + } + }); + } + + private static List getItems(ReadGraph graph, Resource lib, Resource type) throws DatabaseException{ + Plant3D p3d = Plant3D.getInstance(graph); + Layer0 l0 = Layer0.getInstance(graph); + List result = new ArrayList(); + for (Resource r : graph.getObjects(lib, l0.ConsistsOf)) { + if (graph.isInstanceOf(r, type) ) { + Resource geom = graph.getPossibleObject(r,p3d.hasGeometry); + if (geom != null || graph.hasStatement(r,p3d.NonVisibleComponent)) { + + result.add(createItem(graph, r)); + } + } + if (graph.isInheritedFrom(r, type)) { + boolean asserts = false; + for (Resource a : graph.getObjects(r, l0.Asserts)) { + if (p3d.hasGeometry.equals(graph.getPossibleObject(a, l0.HasPredicate))) { + asserts = true; + break; + } + } + if (asserts) { + result.add(createItem(graph, r)); + } + } + } + return result; + } + + private static Item createItem(ReadGraph graph, Resource r) throws DatabaseException { + Layer0 l0 = Layer0.getInstance(graph); + Plant3D p3d = Plant3D.getInstance(graph); + String name = graph.getRelatedValue(r, l0.HasName); + String uri = graph.getURI(r); + Item item = new Item(uri, name); + if (graph.isInstanceOf(r, p3d.Equipment)) + item.setType(Type.EQUIPMENT); + else if (graph.isInstanceOf(r, p3d.InlineComponent)) + item.setType(Type.INLINE); + else if (graph.isInstanceOf(r, p3d.EndComponent)) + item.setType(Type.END); + else if (graph.isInstanceOf(r, p3d.TurnComponent)) + item.setType(Type.TURN); + else if (graph.isInstanceOf(r, p3d.Nozzle)) + item.setType(Type.NOZZLE); + else + throw new RuntimeException("Cannot detect type for " + r); + + if (graph.hasStatement(r, p3d.CodeComponent)) + item.setCode(true); + if (graph.hasStatement(r, p3d.VariableAngleTurnComponent) || + graph.hasStatement(r, p3d.VariableLengthInlineComponent)) + item.setVariable(true); + if (graph.hasStatement(r, p3d.SizeChangeComponent)) + item.setSizeChange(true); + return item; + } + + public static Resource createModel(WriteGraph graph, String name) throws DatabaseException{ + Layer0 l0 = Layer0.getInstance(graph); + Plant3D p3d = Plant3D.getInstance(graph); + Resource model = graph.newResource(); + graph.claim(model, l0.InstanceOf, p3d.Plant); + graph.claimLiteral(model, l0.HasName, name); + + return model; + } + +}