--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<classpath>\r
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>\r
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>\r
+ <classpathentry kind="src" path="src"/>\r
+ <classpathentry kind="output" path="bin"/>\r
+</classpath>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<projectDescription>\r
+ <name>org.simantics.g3d.csg.ontology</name>\r
+ <comment></comment>\r
+ <projects>\r
+ </projects>\r
+ <buildSpec>\r
+ <buildCommand>\r
+ <name>org.simantics.graph.builder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ <buildCommand>\r
+ <name>org.eclipse.jdt.core.javabuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ <buildCommand>\r
+ <name>org.eclipse.pde.ManifestBuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ <buildCommand>\r
+ <name>org.eclipse.pde.SchemaBuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ </buildSpec>\r
+ <natures>\r
+ <nature>org.eclipse.pde.PluginNature</nature>\r
+ <nature>org.eclipse.jdt.core.javanature</nature>\r
+ <nature>org.simantics.graph.nature</nature>\r
+ </natures>\r
+</projectDescription>\r
--- /dev/null
+#Tue Dec 13 11:35:42 EET 2011\r
+eclipse.preferences.version=1\r
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled\r
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6\r
+org.eclipse.jdt.core.compiler.compliance=1.6\r
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error\r
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error\r
+org.eclipse.jdt.core.compiler.source=1.6\r
--- /dev/null
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: CSG Ontology
+Bundle-SymbolicName: org.simantics.g3d.csg.ontology
+Bundle-Version: 1.0.0.qualifier
+Bundle-Vendor: VTT
+Require-Bundle: org.eclipse.core.runtime,
+ org.simantics.g3d.ontology;bundle-version="1.0.0",
+ org.simantics.layer0;bundle-version="1.0.0",
+ org.simantics.viewpoint.ontology;bundle-version="1.0.0",
+ org.simantics.project.ontology;bundle-version="1.0.0",
+ org.simantics.image2.ontology;bundle-version="1.0.0",
+ org.simantics.action.ontology;bundle-version="1.0.0",
+ org.simantics.selectionview.ontology;bundle-version="1.0.0",
+ org.simantics.simulation.ontology;bundle-version="1.0.0"
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Export-Package: org.simantics.g3d.csg.ontology
--- /dev/null
+source.. = src/\r
+output.. = bin/\r
+bin.includes = META-INF/,\\r
+ .,\\r
+ graph.tg\r
--- /dev/null
+L0 = <http://www.simantics.org/Layer0-1.1>\r
+G3D = <http://www.simantics.org/G3D-0.1>\r
+\r
+CSG = <http://www.simantics.org/CSG-0.1> : L0.Ontology\r
+ @L0.new\r
+ L0.HasResourceClass "org.simantics.g3d.csg.ontology.CSG"\r
+\r
+CSG.Shape <T G3D.Node\r
+CSG.Model <T G3D.RootNode\r
+CSG.Primitive <T CSG.Shape\r
+ @L0.property CSG.HasSizingProperty\r
+\r
+CSG.hasPrimaryShape <R G3D.geometryDefinition\r
+ L0.HasDomain CSG.BooleanOperation\r
+ L0.HasRange CSG.Shape\r
+CSG.hasSecondaryShape <R G3D.geometryDefinition\r
+ L0.HasDomain CSG.BooleanOperation\r
+ L0.HasRange CSG.Shape\r
+CSG.hasChildShape <R G3D.children\r
+ L0.HasDomain CSG.Shape\r
+ L0.HasRange CSG.Shape\r
+CSG.BooleanOperation <T CSG.Shape\r
+ @L0.optionalProperty CSG.hasPrimaryShape\r
+ @L0.property CSG.hasSecondaryShape\r
+CSG.Difference <T CSG.BooleanOperation\r
+CSG.Intersection <T CSG.BooleanOperation\r
+CSG.Union <T CSG.BooleanOperation\r
+\r
+CSG.HasSizingProperty <R G3D.hasNonTransformation \r
+CSG.HasXAxisSize <R CSG.HasSizingProperty : L0.FunctionalRelation\r
+ L0.HasRange L0.Double\r
+CSG.HasYAxisSize <R CSG.HasSizingProperty : L0.FunctionalRelation\r
+ L0.HasRange L0.Double\r
+CSG.HasZAxisSize <R CSG.HasSizingProperty : L0.FunctionalRelation\r
+ L0.HasRange L0.Double\r
+CSG.HasXAxisMinimumSize <R CSG.HasSizingProperty : L0.FunctionalRelation\r
+ L0.HasRange L0.Double\r
+CSG.HasZAxisMinimumSize <R CSG.HasSizingProperty : L0.FunctionalRelation\r
+ L0.HasRange L0.Double\r
+CSG.HasXAxisMaximumSize <R CSG.HasSizingProperty : L0.FunctionalRelation\r
+ L0.HasRange L0.Double\r
+CSG.HasZAxisMaximumSize <R CSG.HasSizingProperty : L0.FunctionalRelation\r
+ L0.HasRange L0.Double\r
+CSG.HasRadius <R CSG.HasSizingProperty : L0.FunctionalRelation\r
+ L0.HasRange L0.Double\r
+CSG.HasMajorRadius <R CSG.HasSizingProperty : L0.FunctionalRelation\r
+ L0.HasRange L0.Double\r
+CSG.HasMinorRadius <R CSG.HasSizingProperty : L0.FunctionalRelation\r
+ L0.HasRange L0.Double\r
+CSG.HasTopRadius <R CSG.HasSizingProperty : L0.FunctionalRelation\r
+ L0.HasRange L0.Double\r
+CSG.HasBottomRadius <R CSG.HasSizingProperty : L0.FunctionalRelation\r
+ L0.HasRange L0.Double\r
+CSG.HasHeight <R CSG.HasSizingProperty : L0.FunctionalRelation\r
+ L0.HasRange L0.Double\r
+CSG.HasCorners <R CSG.HasSizingProperty : L0.FunctionalRelation\r
+ L0.HasRange L0.Integer\r
+CSG.Box <T CSG.Primitive\r
+ @L0.assert CSG.HasXAxisSize 1.0\r
+ @L0.assert CSG.HasYAxisSize 1.0\r
+ @L0.assert CSG.HasZAxisSize 1.0\r
+CSG.Sphere <T CSG.Primitive\r
+ @L0.assert CSG.HasRadius 1.0\r
+CSG.Cone <T CSG.Primitive\r
+ @L0.assert CSG.HasTopRadius 0.5\r
+ @L0.assert CSG.HasBottomRadius 1.0\r
+ @L0.assert CSG.HasHeight 1.0\r
+CSG.Cylinder <T CSG.Primitive\r
+ @L0.assert CSG.HasRadius 1.0\r
+ @L0.assert CSG.HasHeight 1.0\r
+CSG.Barrel <T CSG.Primitive\r
+ @L0.assert CSG.HasMinorRadius 0.9\r
+ @L0.assert CSG.HasMajorRadius 1.0\r
+ @L0.assert CSG.HasHeight 1.0\r
+CSG.EllipticCylinder <T CSG.Primitive\r
+ @L0.assert CSG.HasMinorRadius 0.5\r
+ @L0.assert CSG.HasMajorRadius 1.0\r
+ @L0.assert CSG.HasHeight 1.0\r
+CSG.RegularPrism <T CSG.Primitive\r
+ @L0.assert CSG.HasHeight 1.0\r
+ @L0.assert CSG.HasRadius 1.0\r
+ @L0.assert CSG.HasCorners 3\r
+CSG.Torus <T CSG.Primitive\r
+ @L0.assert CSG.HasMinorRadius 0.5\r
+ @L0.assert CSG.HasMajorRadius 1.0\r
+CSG.RectangularSolid <T CSG.Primitive\r
+ @L0.assert CSG.HasXAxisMinimumSize 0.5\r
+ @L0.assert CSG.HasXAxisMaximumSize 1.0\r
+ @L0.assert CSG.HasYAxisSize 1.0\r
+ @L0.assert CSG.HasZAxisMinimumSize 0.5\r
+ @L0.assert CSG.HasZAxisMaximumSize 1.0\r
--- /dev/null
+L0 = <http://www.simantics.org/Layer0-1.1>\r
+VP = <http://www.simantics.org/Viewpoint-1.2>\r
+CSG = <http://www.simantics.org/CSG-0.1>\r
+PROJ = <http://www.simantics.org/Project-1.2>\r
+SIM = <http://www.simantics.org/Simulation-1.1>\r
+IMAGE = <http://www.simantics.org/Image2-1.2>\r
+ACT = <http://www.simantics.org/Action-1.1>\r
+G3D = <http://www.simantics.org/G3D-0.1>\r
+SEL = <http://www.simantics.org/SelectionView-1.2>\r
+\r
+CBC = CSG.CSGBrowseContext : VP.BrowseContext\r
+ //VP.BrowseContext.IsIncludedIn PROJ.ProjectBrowseContext\r
+ @VP.constantImageRule CSG.Union IMAGES.Union\r
+ @VP.constantImageRule CSG.Difference IMAGES.Difference\r
+ @VP.constantImageRule CSG.Intersection IMAGES.Intersection\r
+ @VP.constantImageRule CSG.Primitive IMAGES.Ruby\r
+ @VP.constantImageRule CSG.Model IMAGES.Ruby\r
+ @VP.relationChildRule CSG.Model G3D.nodes CSG.Shape\r
+ @VP.relationChildRule CSG.Shape G3D.nodes CSG.Shape\r
+ @VP.relationChildRule PROJ.Project L0.ConsistsOf CSG.Model\r
+ \r
+IMAGES = CSG.Images : L0.Library\r
+IMAGES.Union : IMAGE.PngImage\r
+ @L0.loadBytes "images/union.png"\r
+IMAGES.Difference : IMAGE.PngImage\r
+ @L0.loadBytes "images/difference.png"\r
+IMAGES.Intersection : IMAGE.PngImage\r
+ @L0.loadBytes "images/intersection.png"\r
+IMAGES.Ruby : IMAGE.PngImage\r
+ @L0.loadBytes "images/ruby.png"\r
+ \r
+CBC.ShapeTabContribution <T SEL.TypedVariableTabContribution\r
+ SEL.TypedVariableTabContribution.HasType CSG.Shape\r
+ \r
+ \r
+// Labels\r
+CBC.RunLabelRule : VP.LabelRule\r
+CBC\r
+ VP.BrowseContext.HasVisualsContribution _ : VP.VisualsContribution\r
+ VP.VisualsContribution.HasNodeType L0.Entity\r
+ VP.VisualsContribution.HasRule VP.ResourceLabelLabelRule\r
+ VP.VisualsContribution.HasRule VP.ResourceNameModifierRule\r
+ \r
+// Decorations\r
+CBC.ActiveLabelDecorationRule : VP.ConstantLabelDecorationRule\r
+ VP.ConstantLabelDecorationRule.HasFormat "%s [ACTIVE]"\r
+ VP.ConstantLabelDecorationRule.HasStyle "B"
\ No newline at end of file
--- /dev/null
+package org.simantics.g3d.csg.ontology;\r
+\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.request.Read;\r
+import org.simantics.db.Session;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.service.QueryControl;\r
+\r
+public class CSG {\r
+ \r
+ public final Resource Barrel;\r
+ public final Resource BooleanOperation;\r
+ public final Resource Box;\r
+ public final Resource CSGBrowseContext;\r
+ public final Resource CSGBrowseContext_ActiveLabelDecorationRule;\r
+ public final Resource CSGBrowseContext_RunLabelRule;\r
+ public final Resource CSGBrowseContext_ShapeTabContribution;\r
+ public final Resource Cone;\r
+ public final Resource Cylinder;\r
+ public final Resource Difference;\r
+ public final Resource EllipticCylinder;\r
+ public final Resource HasBottomRadius;\r
+ public final Resource HasBottomRadius_Inverse;\r
+ public final Resource HasCorners;\r
+ public final Resource HasCorners_Inverse;\r
+ public final Resource HasHeight;\r
+ public final Resource HasHeight_Inverse;\r
+ public final Resource HasMajorRadius;\r
+ public final Resource HasMajorRadius_Inverse;\r
+ public final Resource HasMinorRadius;\r
+ public final Resource HasMinorRadius_Inverse;\r
+ public final Resource HasRadius;\r
+ public final Resource HasRadius_Inverse;\r
+ public final Resource HasSizingProperty;\r
+ public final Resource HasSizingProperty_Inverse;\r
+ public final Resource HasTopRadius;\r
+ public final Resource HasTopRadius_Inverse;\r
+ public final Resource HasXAxisMaximumSize;\r
+ public final Resource HasXAxisMaximumSize_Inverse;\r
+ public final Resource HasXAxisMinimumSize;\r
+ public final Resource HasXAxisMinimumSize_Inverse;\r
+ public final Resource HasXAxisSize;\r
+ public final Resource HasXAxisSize_Inverse;\r
+ public final Resource HasYAxisSize;\r
+ public final Resource HasYAxisSize_Inverse;\r
+ public final Resource HasZAxisMaximumSize;\r
+ public final Resource HasZAxisMaximumSize_Inverse;\r
+ public final Resource HasZAxisMinimumSize;\r
+ public final Resource HasZAxisMinimumSize_Inverse;\r
+ public final Resource HasZAxisSize;\r
+ public final Resource HasZAxisSize_Inverse;\r
+ public final Resource Images;\r
+ public final Resource Images_Difference;\r
+ public final Resource Images_Intersection;\r
+ public final Resource Images_Ruby;\r
+ public final Resource Images_Union;\r
+ public final Resource Intersection;\r
+ public final Resource Model;\r
+ public final Resource Primitive;\r
+ public final Resource RectangularSolid;\r
+ public final Resource RegularPrism;\r
+ public final Resource Shape;\r
+ public final Resource Sphere;\r
+ public final Resource Torus;\r
+ public final Resource Union;\r
+ public final Resource hasChildShape;\r
+ public final Resource hasChildShape_Inverse;\r
+ public final Resource hasPrimaryShape;\r
+ public final Resource hasPrimaryShape_Inverse;\r
+ public final Resource hasSecondaryShape;\r
+ public final Resource hasSecondaryShape_Inverse;\r
+ \r
+ public static class URIs {\r
+ public static final String Barrel = "http://www.simantics.org/CSG-0.1/Barrel";\r
+ public static final String BooleanOperation = "http://www.simantics.org/CSG-0.1/BooleanOperation";\r
+ public static final String Box = "http://www.simantics.org/CSG-0.1/Box";\r
+ public static final String CSGBrowseContext = "http://www.simantics.org/CSG-0.1/CSGBrowseContext";\r
+ public static final String CSGBrowseContext_ActiveLabelDecorationRule = "http://www.simantics.org/CSG-0.1/CSGBrowseContext/ActiveLabelDecorationRule";\r
+ public static final String CSGBrowseContext_RunLabelRule = "http://www.simantics.org/CSG-0.1/CSGBrowseContext/RunLabelRule";\r
+ public static final String CSGBrowseContext_ShapeTabContribution = "http://www.simantics.org/CSG-0.1/CSGBrowseContext/ShapeTabContribution";\r
+ public static final String Cone = "http://www.simantics.org/CSG-0.1/Cone";\r
+ public static final String Cylinder = "http://www.simantics.org/CSG-0.1/Cylinder";\r
+ public static final String Difference = "http://www.simantics.org/CSG-0.1/Difference";\r
+ public static final String EllipticCylinder = "http://www.simantics.org/CSG-0.1/EllipticCylinder";\r
+ public static final String HasBottomRadius = "http://www.simantics.org/CSG-0.1/HasBottomRadius";\r
+ public static final String HasBottomRadius_Inverse = "http://www.simantics.org/CSG-0.1/HasBottomRadius/Inverse";\r
+ public static final String HasCorners = "http://www.simantics.org/CSG-0.1/HasCorners";\r
+ public static final String HasCorners_Inverse = "http://www.simantics.org/CSG-0.1/HasCorners/Inverse";\r
+ public static final String HasHeight = "http://www.simantics.org/CSG-0.1/HasHeight";\r
+ public static final String HasHeight_Inverse = "http://www.simantics.org/CSG-0.1/HasHeight/Inverse";\r
+ public static final String HasMajorRadius = "http://www.simantics.org/CSG-0.1/HasMajorRadius";\r
+ public static final String HasMajorRadius_Inverse = "http://www.simantics.org/CSG-0.1/HasMajorRadius/Inverse";\r
+ public static final String HasMinorRadius = "http://www.simantics.org/CSG-0.1/HasMinorRadius";\r
+ public static final String HasMinorRadius_Inverse = "http://www.simantics.org/CSG-0.1/HasMinorRadius/Inverse";\r
+ public static final String HasRadius = "http://www.simantics.org/CSG-0.1/HasRadius";\r
+ public static final String HasRadius_Inverse = "http://www.simantics.org/CSG-0.1/HasRadius/Inverse";\r
+ public static final String HasSizingProperty = "http://www.simantics.org/CSG-0.1/HasSizingProperty";\r
+ public static final String HasSizingProperty_Inverse = "http://www.simantics.org/CSG-0.1/HasSizingProperty/Inverse";\r
+ public static final String HasTopRadius = "http://www.simantics.org/CSG-0.1/HasTopRadius";\r
+ public static final String HasTopRadius_Inverse = "http://www.simantics.org/CSG-0.1/HasTopRadius/Inverse";\r
+ public static final String HasXAxisMaximumSize = "http://www.simantics.org/CSG-0.1/HasXAxisMaximumSize";\r
+ public static final String HasXAxisMaximumSize_Inverse = "http://www.simantics.org/CSG-0.1/HasXAxisMaximumSize/Inverse";\r
+ public static final String HasXAxisMinimumSize = "http://www.simantics.org/CSG-0.1/HasXAxisMinimumSize";\r
+ public static final String HasXAxisMinimumSize_Inverse = "http://www.simantics.org/CSG-0.1/HasXAxisMinimumSize/Inverse";\r
+ public static final String HasXAxisSize = "http://www.simantics.org/CSG-0.1/HasXAxisSize";\r
+ public static final String HasXAxisSize_Inverse = "http://www.simantics.org/CSG-0.1/HasXAxisSize/Inverse";\r
+ public static final String HasYAxisSize = "http://www.simantics.org/CSG-0.1/HasYAxisSize";\r
+ public static final String HasYAxisSize_Inverse = "http://www.simantics.org/CSG-0.1/HasYAxisSize/Inverse";\r
+ public static final String HasZAxisMaximumSize = "http://www.simantics.org/CSG-0.1/HasZAxisMaximumSize";\r
+ public static final String HasZAxisMaximumSize_Inverse = "http://www.simantics.org/CSG-0.1/HasZAxisMaximumSize/Inverse";\r
+ public static final String HasZAxisMinimumSize = "http://www.simantics.org/CSG-0.1/HasZAxisMinimumSize";\r
+ public static final String HasZAxisMinimumSize_Inverse = "http://www.simantics.org/CSG-0.1/HasZAxisMinimumSize/Inverse";\r
+ public static final String HasZAxisSize = "http://www.simantics.org/CSG-0.1/HasZAxisSize";\r
+ public static final String HasZAxisSize_Inverse = "http://www.simantics.org/CSG-0.1/HasZAxisSize/Inverse";\r
+ public static final String Images = "http://www.simantics.org/CSG-0.1/Images";\r
+ public static final String Images_Difference = "http://www.simantics.org/CSG-0.1/Images/Difference";\r
+ public static final String Images_Intersection = "http://www.simantics.org/CSG-0.1/Images/Intersection";\r
+ public static final String Images_Ruby = "http://www.simantics.org/CSG-0.1/Images/Ruby";\r
+ public static final String Images_Union = "http://www.simantics.org/CSG-0.1/Images/Union";\r
+ public static final String Intersection = "http://www.simantics.org/CSG-0.1/Intersection";\r
+ public static final String Model = "http://www.simantics.org/CSG-0.1/Model";\r
+ public static final String Primitive = "http://www.simantics.org/CSG-0.1/Primitive";\r
+ public static final String RectangularSolid = "http://www.simantics.org/CSG-0.1/RectangularSolid";\r
+ public static final String RegularPrism = "http://www.simantics.org/CSG-0.1/RegularPrism";\r
+ public static final String Shape = "http://www.simantics.org/CSG-0.1/Shape";\r
+ public static final String Sphere = "http://www.simantics.org/CSG-0.1/Sphere";\r
+ public static final String Torus = "http://www.simantics.org/CSG-0.1/Torus";\r
+ public static final String Union = "http://www.simantics.org/CSG-0.1/Union";\r
+ public static final String hasChildShape = "http://www.simantics.org/CSG-0.1/hasChildShape";\r
+ public static final String hasChildShape_Inverse = "http://www.simantics.org/CSG-0.1/hasChildShape/Inverse";\r
+ public static final String hasPrimaryShape = "http://www.simantics.org/CSG-0.1/hasPrimaryShape";\r
+ public static final String hasPrimaryShape_Inverse = "http://www.simantics.org/CSG-0.1/hasPrimaryShape/Inverse";\r
+ public static final String hasSecondaryShape = "http://www.simantics.org/CSG-0.1/hasSecondaryShape";\r
+ public static final String hasSecondaryShape_Inverse = "http://www.simantics.org/CSG-0.1/hasSecondaryShape/Inverse";\r
+ }\r
+ \r
+ public static Resource getResourceOrNull(ReadGraph graph, String uri) {\r
+ try {\r
+ return graph.getResource(uri);\r
+ } catch(DatabaseException e) {\r
+ System.err.println(e.getMessage());\r
+ return null;\r
+ }\r
+ }\r
+ \r
+ public CSG(ReadGraph graph) {\r
+ Barrel = getResourceOrNull(graph, URIs.Barrel);\r
+ BooleanOperation = getResourceOrNull(graph, URIs.BooleanOperation);\r
+ Box = getResourceOrNull(graph, URIs.Box);\r
+ CSGBrowseContext = getResourceOrNull(graph, URIs.CSGBrowseContext);\r
+ CSGBrowseContext_ActiveLabelDecorationRule = getResourceOrNull(graph, URIs.CSGBrowseContext_ActiveLabelDecorationRule);\r
+ CSGBrowseContext_RunLabelRule = getResourceOrNull(graph, URIs.CSGBrowseContext_RunLabelRule);\r
+ CSGBrowseContext_ShapeTabContribution = getResourceOrNull(graph, URIs.CSGBrowseContext_ShapeTabContribution);\r
+ Cone = getResourceOrNull(graph, URIs.Cone);\r
+ Cylinder = getResourceOrNull(graph, URIs.Cylinder);\r
+ Difference = getResourceOrNull(graph, URIs.Difference);\r
+ EllipticCylinder = getResourceOrNull(graph, URIs.EllipticCylinder);\r
+ HasBottomRadius = getResourceOrNull(graph, URIs.HasBottomRadius);\r
+ HasBottomRadius_Inverse = getResourceOrNull(graph, URIs.HasBottomRadius_Inverse);\r
+ HasCorners = getResourceOrNull(graph, URIs.HasCorners);\r
+ HasCorners_Inverse = getResourceOrNull(graph, URIs.HasCorners_Inverse);\r
+ HasHeight = getResourceOrNull(graph, URIs.HasHeight);\r
+ HasHeight_Inverse = getResourceOrNull(graph, URIs.HasHeight_Inverse);\r
+ HasMajorRadius = getResourceOrNull(graph, URIs.HasMajorRadius);\r
+ HasMajorRadius_Inverse = getResourceOrNull(graph, URIs.HasMajorRadius_Inverse);\r
+ HasMinorRadius = getResourceOrNull(graph, URIs.HasMinorRadius);\r
+ HasMinorRadius_Inverse = getResourceOrNull(graph, URIs.HasMinorRadius_Inverse);\r
+ HasRadius = getResourceOrNull(graph, URIs.HasRadius);\r
+ HasRadius_Inverse = getResourceOrNull(graph, URIs.HasRadius_Inverse);\r
+ HasSizingProperty = getResourceOrNull(graph, URIs.HasSizingProperty);\r
+ HasSizingProperty_Inverse = getResourceOrNull(graph, URIs.HasSizingProperty_Inverse);\r
+ HasTopRadius = getResourceOrNull(graph, URIs.HasTopRadius);\r
+ HasTopRadius_Inverse = getResourceOrNull(graph, URIs.HasTopRadius_Inverse);\r
+ HasXAxisMaximumSize = getResourceOrNull(graph, URIs.HasXAxisMaximumSize);\r
+ HasXAxisMaximumSize_Inverse = getResourceOrNull(graph, URIs.HasXAxisMaximumSize_Inverse);\r
+ HasXAxisMinimumSize = getResourceOrNull(graph, URIs.HasXAxisMinimumSize);\r
+ HasXAxisMinimumSize_Inverse = getResourceOrNull(graph, URIs.HasXAxisMinimumSize_Inverse);\r
+ HasXAxisSize = getResourceOrNull(graph, URIs.HasXAxisSize);\r
+ HasXAxisSize_Inverse = getResourceOrNull(graph, URIs.HasXAxisSize_Inverse);\r
+ HasYAxisSize = getResourceOrNull(graph, URIs.HasYAxisSize);\r
+ HasYAxisSize_Inverse = getResourceOrNull(graph, URIs.HasYAxisSize_Inverse);\r
+ HasZAxisMaximumSize = getResourceOrNull(graph, URIs.HasZAxisMaximumSize);\r
+ HasZAxisMaximumSize_Inverse = getResourceOrNull(graph, URIs.HasZAxisMaximumSize_Inverse);\r
+ HasZAxisMinimumSize = getResourceOrNull(graph, URIs.HasZAxisMinimumSize);\r
+ HasZAxisMinimumSize_Inverse = getResourceOrNull(graph, URIs.HasZAxisMinimumSize_Inverse);\r
+ HasZAxisSize = getResourceOrNull(graph, URIs.HasZAxisSize);\r
+ HasZAxisSize_Inverse = getResourceOrNull(graph, URIs.HasZAxisSize_Inverse);\r
+ Images = getResourceOrNull(graph, URIs.Images);\r
+ Images_Difference = getResourceOrNull(graph, URIs.Images_Difference);\r
+ Images_Intersection = getResourceOrNull(graph, URIs.Images_Intersection);\r
+ Images_Ruby = getResourceOrNull(graph, URIs.Images_Ruby);\r
+ Images_Union = getResourceOrNull(graph, URIs.Images_Union);\r
+ Intersection = getResourceOrNull(graph, URIs.Intersection);\r
+ Model = getResourceOrNull(graph, URIs.Model);\r
+ Primitive = getResourceOrNull(graph, URIs.Primitive);\r
+ RectangularSolid = getResourceOrNull(graph, URIs.RectangularSolid);\r
+ RegularPrism = getResourceOrNull(graph, URIs.RegularPrism);\r
+ Shape = getResourceOrNull(graph, URIs.Shape);\r
+ Sphere = getResourceOrNull(graph, URIs.Sphere);\r
+ Torus = getResourceOrNull(graph, URIs.Torus);\r
+ Union = getResourceOrNull(graph, URIs.Union);\r
+ hasChildShape = getResourceOrNull(graph, URIs.hasChildShape);\r
+ hasChildShape_Inverse = getResourceOrNull(graph, URIs.hasChildShape_Inverse);\r
+ hasPrimaryShape = getResourceOrNull(graph, URIs.hasPrimaryShape);\r
+ hasPrimaryShape_Inverse = getResourceOrNull(graph, URIs.hasPrimaryShape_Inverse);\r
+ hasSecondaryShape = getResourceOrNull(graph, URIs.hasSecondaryShape);\r
+ hasSecondaryShape_Inverse = getResourceOrNull(graph, URIs.hasSecondaryShape_Inverse);\r
+ }\r
+ \r
+ public static CSG getInstance(ReadGraph graph) {\r
+ Session session = graph.getSession();\r
+ CSG ret = session.peekService(CSG.class);\r
+ if(ret == null) {\r
+ QueryControl qc = graph.getService(QueryControl.class);\r
+ ret = new CSG(qc.getIndependentGraph(graph));\r
+ session.registerService(CSG.class, ret);\r
+ }\r
+ return ret;\r
+ }\r
+ \r
+ public static CSG getInstance(Session session) throws DatabaseException {\r
+ CSG ret = session.peekService(CSG.class);\r
+ if(ret == null) {\r
+ ret = session.syncRequest(new Read<CSG>() {\r
+ public CSG perform(ReadGraph graph) throws DatabaseException {\r
+ QueryControl qc = graph.getService(QueryControl.class);\r
+ return new CSG(qc.getIndependentGraph(graph));\r
+ }\r
+ });\r
+ session.registerService(CSG.class, ret);\r
+ }\r
+ return ret;\r
+ }\r
+ \r
+}\r
+\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<classpath>\r
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>\r
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>\r
+ <classpathentry kind="src" path="src"/>\r
+ <classpathentry kind="output" path="bin"/>\r
+</classpath>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<projectDescription>\r
+ <name>org.simantics.g3d.csg</name>\r
+ <comment></comment>\r
+ <projects>\r
+ </projects>\r
+ <buildSpec>\r
+ <buildCommand>\r
+ <name>org.eclipse.jdt.core.javabuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ <buildCommand>\r
+ <name>org.eclipse.pde.ManifestBuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ <buildCommand>\r
+ <name>org.eclipse.pde.SchemaBuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ </buildSpec>\r
+ <natures>\r
+ <nature>org.eclipse.pde.PluginNature</nature>\r
+ <nature>org.eclipse.jdt.core.javanature</nature>\r
+ </natures>\r
+</projectDescription>\r
--- /dev/null
+#Mon Dec 12 16:51:11 EET 2011\r
+eclipse.preferences.version=1\r
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled\r
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6\r
+org.eclipse.jdt.core.compiler.compliance=1.6\r
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error\r
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error\r
+org.eclipse.jdt.core.compiler.source=1.6\r
--- /dev/null
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Csg
+Bundle-SymbolicName: org.simantics.g3d.csg;singleton:=true
+Bundle-Version: 1.0.0.qualifier
+Bundle-Activator: org.simantics.g3d.csg.Activator
+Bundle-Vendor: VTT
+Require-Bundle: org.eclipse.core.runtime,
+ org.simantics.g3d;bundle-version="1.0.0",
+ org.simantics.g3d.ontology;bundle-version="1.0.0",
+ org.simantics.db.layer0;bundle-version="1.1.0",
+ javax.vecmath;bundle-version="1.5.2",
+ org.simantics.opencascade;bundle-version="1.0.0",
+ org.simantics.ui;bundle-version="1.0.0",
+ vtk;bundle-version="1.0.0",
+ org.eclipse.ui,
+ org.simantics.g3d.csg.ontology;bundle-version="1.0.0",
+ org.simantics.selectionview;bundle-version="1.0.0",
+ org.eclipse.ui.views;bundle-version="3.5.1",
+ org.jcae.opencascade;bundle-version="1.0.0",
+ org.simantics.g3d.vtk;bundle-version="1.0.0",
+ org.simantics.browsing.ui.common;bundle-version="1.1.0",
+ org.simantics.objmap2;bundle-version="1.0.0",
+ org.simantics.opencascade.vtk;bundle-version="1.0.0"
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Bundle-ActivationPolicy: lazy
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<adapters>\r
+<target interface="org.simantics.opencascade.SolidModelProvider">\r
+ <type uri="http://www.simantics.org/CSG-0.1/Model"\r
+ class="org.simantics.g3d.csg.adapters.CSGSolidModelAdapter">\r
+ <this />\r
+ </type>\r
+</target>\r
+<target interface="org.simantics.db.layer0.adapter.Remover">\r
+ <type uri="http://www.simantics.org/CSG-0.1/Shape"\r
+ class="org.simantics.g3d.csg.adapters.NodeRemover">\r
+ <this />\r
+ </type>\r
+ </target>\r
+</adapters>
\ No newline at end of file
--- /dev/null
+source.. = src/\r
+output.. = bin/\r
+bin.includes = META-INF/,\\r
+ .,\\r
+ plugin.xml,\\r
+ adapters.xml\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<?eclipse version="3.4"?>\r
+<plugin>\r
+ <extension\r
+ point="org.eclipse.ui.editors">\r
+ <editor\r
+ class="org.simantics.g3d.csg.editor.CSGEditor2"\r
+ default="false"\r
+ icon="platform:/plugin/com.famfamfam.silk/icons/ruby.png"\r
+ id="org.simantics.g3d.csg.editor2"\r
+ name="CSG Editor">\r
+ </editor>\r
+ </extension>\r
+ <extension\r
+ point="org.simantics.ui.resourceEditorAdapter">\r
+ <adapter\r
+ editorId="org.simantics.g3d.csg.editor2"\r
+ image="platform:/plugin/com.famfamfam.silk/icons/ruby.png"\r
+ label="CSG Editor"\r
+ priority="1"\r
+ type_uris="http://www.simantics.org/CSG-0.1/Model">\r
+ </adapter>\r
+ </extension>\r
+ <extension\r
+ point="org.eclipse.ui.exportWizards">\r
+ <category\r
+ id="org.simantics.g3d.csg.category"\r
+ name="CSG Exports">\r
+ </category>\r
+ <wizard\r
+ category="org.simantics.g3d.csg.category"\r
+ class="org.simantics.g3d.csg.wizard.CSGBRepExportWizard"\r
+ id="org.simantics.g3d.csg.brepexportwizard"\r
+ name="CSG BREP Export Wizard">\r
+ </wizard>\r
+ </extension>\r
+\r
+</plugin>\r
--- /dev/null
+package org.simantics.g3d.csg;\r
+\r
+import org.eclipse.ui.plugin.AbstractUIPlugin;\r
+import org.osgi.framework.BundleContext;\r
+\r
+public class Activator extends AbstractUIPlugin {\r
+\r
+ // The plug-in ID\r
+ public static final String PLUGIN_ID = "org.simantics.g3d.csg"; //$NON-NLS-1$\r
+\r
+ // The shared instance\r
+ private static Activator plugin;\r
+ \r
+ /**\r
+ * The constructor\r
+ */\r
+ public Activator() {\r
+ }\r
+\r
+ /*\r
+ * (non-Javadoc)\r
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)\r
+ */\r
+ public void start(BundleContext context) throws Exception {\r
+ super.start(context);\r
+ plugin = this;\r
+ }\r
+\r
+ /*\r
+ * (non-Javadoc)\r
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)\r
+ */\r
+ public void stop(BundleContext context) throws Exception {\r
+ plugin = null;\r
+ super.stop(context);\r
+ }\r
+\r
+ /**\r
+ * Returns the shared instance\r
+ *\r
+ * @return the shared instance\r
+ */\r
+ public static Activator getDefault() {\r
+ return plugin;\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.g3d.csg.actions;\r
+\r
+import java.util.Collection;\r
+import java.util.HashMap;\r
+import java.util.Iterator;\r
+import java.util.Map;\r
+\r
+import javax.vecmath.Quat4d;\r
+import javax.vecmath.Vector3d;\r
+\r
+import org.eclipse.jface.action.Action;\r
+import org.simantics.g3d.csg.scenegraph2.CSGparentNode;\r
+import org.simantics.g3d.csg.scenegraph2.CSGrootNode;\r
+import org.simantics.g3d.csg.scenegraph2.ICSGnode;\r
+import org.simantics.utils.ui.ExceptionUtils;\r
+\r
+public class AddBooleanOpAction2 extends Action {\r
+ CSGrootNode root;\r
+ Class<? extends CSGparentNode> booleanClass;\r
+ Collection<ICSGnode> nodes;\r
+ \r
+ public AddBooleanOpAction2(CSGrootNode root, Class<? extends CSGparentNode> booleanClass, Collection<ICSGnode> nodes) {\r
+ super();\r
+ String name = booleanClass.getSimpleName();\r
+ if (name.endsWith("Node"))\r
+ name = name.substring(0,name.length()-4);\r
+ setText(name);\r
+ this.booleanClass = booleanClass;\r
+ this.nodes = nodes;\r
+ this.root = root;\r
+ if (nodes.size() != 2)\r
+ setEnabled(false);\r
+ for (ICSGnode node : nodes) {\r
+ if (!node.getParent().equals(root))\r
+ setEnabled(false);\r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public void run() {\r
+ try {\r
+ CSGparentNode booleanNode = booleanClass.newInstance();\r
+ Map<ICSGnode,Vector3d> positions = new HashMap<ICSGnode, Vector3d>();\r
+ Map<ICSGnode,Quat4d> orientations = new HashMap<ICSGnode, Quat4d>();\r
+ for (ICSGnode node : nodes) {\r
+ positions.put(node, node.getWorldPosition());\r
+ orientations.put(node, node.getWorldOrientation());\r
+ //root.remChild(node);\r
+ node.deattach();\r
+ }\r
+ Iterator<ICSGnode> iter = nodes.iterator();\r
+ booleanNode.addPrimaryChild(iter.next());\r
+ booleanNode.addSecondaryChild(iter.next());\r
+ \r
+ String name = root.getUniqueName(booleanNode.getClass().getSimpleName());\r
+ booleanNode.setName(name);\r
+ \r
+ root.addChild(booleanNode);\r
+ for (ICSGnode node : nodes) {\r
+ node.setWorldPosition(positions.get(node));\r
+ node.setWorldOrientation(orientations.get(node));\r
+ }\r
+ root.getNodeMap().commit();\r
+ } catch (Exception e) {\r
+ ExceptionUtils.logAndShowError("Cannot create boolean operation.", e);\r
+ }\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.csg.actions;\r
+\r
+import org.eclipse.jface.action.Action;\r
+import org.simantics.g3d.csg.scenegraph2.CSGnode;\r
+import org.simantics.g3d.csg.scenegraph2.CSGrootNode;\r
+import org.simantics.utils.ui.ExceptionUtils;\r
+\r
+public class AddPrimitiveAction2 extends Action {\r
+ \r
+ CSGrootNode root;\r
+ Class<? extends CSGnode> primitiveClass;\r
+ public AddPrimitiveAction2(CSGrootNode root, Class<? extends CSGnode> primitiveClass) {\r
+ super();\r
+ String name = primitiveClass.getSimpleName();\r
+ if (name.endsWith("Node"))\r
+ name = name.substring(0,name.length()-4);\r
+ setText(name);\r
+ this.primitiveClass = primitiveClass;\r
+ this.root = root;\r
+ }\r
+ \r
+ @Override\r
+ public void run() {\r
+ try {\r
+ CSGnode node = primitiveClass.newInstance();\r
+ String name = root.getUniqueName(node.getClass().getSimpleName());\r
+ node.setName(name);\r
+ root.addChild(node);\r
+ root.getNodeMap().commit();\r
+ } catch (Exception e) {\r
+ ExceptionUtils.logAndShowError("Cannot create primitive.", e);\r
+ }\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.csg.actions;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.HashMap;\r
+import java.util.Map;\r
+\r
+import javax.vecmath.Quat4d;\r
+import javax.vecmath.Vector3d;\r
+\r
+import org.eclipse.jface.action.Action;\r
+import org.simantics.g3d.csg.scenegraph2.CSGparentNode;\r
+import org.simantics.g3d.csg.scenegraph2.CSGrootNode;\r
+import org.simantics.g3d.csg.scenegraph2.ICSGnode;\r
+\r
+public class SplitBooleanOpAction2 extends Action {\r
+ private CSGrootNode root;\r
+ private CSGparentNode booleanOp;\r
+ \r
+ public SplitBooleanOpAction2(CSGrootNode root, CSGparentNode booleanOp) {\r
+ super();\r
+ setText("Split");\r
+ this.booleanOp = booleanOp;\r
+ this.root = root;\r
+ }\r
+ \r
+ @Override\r
+ public void run() {\r
+ Collection<ICSGnode> nodes = new ArrayList<ICSGnode>();\r
+ nodes.addAll(booleanOp.getPrimaryChild());\r
+ nodes.addAll(booleanOp.getSecondaryChild());\r
+ Map<ICSGnode,Vector3d> positions = new HashMap<ICSGnode, Vector3d>();\r
+ Map<ICSGnode,Quat4d> orientations = new HashMap<ICSGnode, Quat4d>();\r
+ for (ICSGnode node : nodes) {\r
+ positions.put(node, node.getWorldPosition());\r
+ orientations.put(node, node.getWorldOrientation());\r
+ node.deattach();\r
+ }\r
+ for (ICSGnode node : nodes) {\r
+ root.addChild(node);\r
+ node.setWorldPosition(positions.get(node));\r
+ node.setWorldOrientation(orientations.get(node));\r
+ }\r
+ root.remChild(booleanOp);\r
+ root.getNodeMap().commit();\r
+\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.csg.adapters;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.Collections;\r
+import java.util.List;\r
+\r
+import org.eclipse.core.runtime.IAdaptable;\r
+import org.jcae.opencascade.jni.TopoDS_Shape;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.request.Read;\r
+import org.simantics.g3d.csg.scenegraph2.CSGrootNode;\r
+import org.simantics.g3d.csg.scenegraph2.ICSGnode;\r
+import org.simantics.g3d.csg.scenegraph2.SchemaBuilder;\r
+import org.simantics.objmap.graph.IMapping;\r
+import org.simantics.objmap.graph.Mappings;\r
+import org.simantics.objmap.graph.schema.IMappingSchema;\r
+import org.simantics.objmap.structural.IStructuralObject;\r
+import org.simantics.opencascade.SolidModelProvider;\r
+import org.simantics.ui.SimanticsUI;\r
+\r
+public class CSGSolidModelAdapter implements SolidModelProvider, IAdaptable, IStructuralObject {\r
+ \r
+ private Resource model;\r
+ \r
+ public CSGSolidModelAdapter(Resource model) {\r
+ this.model = model;\r
+ }\r
+ \r
+ @Override\r
+ public Collection<TopoDS_Shape> getModel() throws Exception {\r
+ return SimanticsUI.getSession().syncRequest(new Read<Collection<TopoDS_Shape>>() {\r
+ @Override\r
+ public Collection<TopoDS_Shape> perform(ReadGraph graph)\r
+ throws DatabaseException {\r
+ Collection<TopoDS_Shape> shapes = new ArrayList<TopoDS_Shape>();\r
+ IMappingSchema<Resource,Object> schema = SchemaBuilder.getSchema(graph);\r
+ IMapping<Resource,Object> mapping = Mappings.createWithoutListening(schema);\r
+ CSGrootNode rootNode = (CSGrootNode)mapping.map(graph, model);\r
+ for (ICSGnode node : rootNode.getNodes("child")) {\r
+ TopoDS_Shape shape = node.getGeometry();\r
+ if (shape != null)\r
+ shapes.add(shape);\r
+ }\r
+ // FIXME: clear CSG scene-graph\r
+ return shapes;\r
+ }\r
+ });\r
+ \r
+ }\r
+ \r
+ @SuppressWarnings("rawtypes")\r
+ @Override\r
+ public Object getAdapter(Class adapter) {\r
+ if (Resource.class.equals(adapter))\r
+ return model;\r
+ return null;\r
+ }\r
+ \r
+ @SuppressWarnings("unchecked")\r
+ @Override\r
+ public List<IStructuralObject> getContext() {\r
+ return Collections.EMPTY_LIST;\r
+ }\r
+ \r
+ @Override\r
+ public Resource getType() {\r
+ return null;\r
+ }\r
+ \r
+ @Override\r
+ public void setContext(List<IStructuralObject> object) {\r
+ throw new RuntimeException();\r
+ }\r
+ \r
+ @Override\r
+ public void setType(Resource type) {\r
+ throw new RuntimeException(); \r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.csg.adapters;\r
+\r
+import java.util.Map;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.layer0.adapter.Remover;\r
+\r
+public class NodeRemover implements Remover {\r
+ \r
+ //private Resource node;\r
+ \r
+ public NodeRemover(Resource node) {\r
+ //this.node = node;\r
+ }\r
+ \r
+ @Override\r
+ public String canRemove(ReadGraph graph, Map<Object, Object> aux)\r
+ throws DatabaseException {\r
+ return "Removing scene-graph nodes from model browser is not supported.";\r
+ }\r
+ \r
+ @Override\r
+ public void remove(WriteGraph graph) throws DatabaseException {\r
+ \r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.csg.editor;\r
+\r
+import java.awt.Component;\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.HashSet;\r
+import java.util.List;\r
+import java.util.Set;\r
+\r
+import org.eclipse.jface.action.IMenuListener;\r
+import org.eclipse.jface.action.IMenuManager;\r
+import org.eclipse.jface.action.MenuManager;\r
+import org.eclipse.jface.viewers.ISelectionChangedListener;\r
+import org.eclipse.jface.viewers.SelectionChangedEvent;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.events.DisposeEvent;\r
+import org.eclipse.swt.events.DisposeListener;\r
+import org.eclipse.swt.layout.FillLayout;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Display;\r
+import org.eclipse.swt.widgets.Menu;\r
+import org.eclipse.ui.views.contentoutline.IContentOutlinePage;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.common.request.ReadRequest;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.g3d.csg.actions.AddBooleanOpAction2;\r
+import org.simantics.g3d.csg.actions.AddPrimitiveAction2;\r
+import org.simantics.g3d.csg.actions.SplitBooleanOpAction2;\r
+import org.simantics.g3d.csg.scenegraph2.BarrelNode;\r
+import org.simantics.g3d.csg.scenegraph2.BoxNode;\r
+import org.simantics.g3d.csg.scenegraph2.CSGparentNode;\r
+import org.simantics.g3d.csg.scenegraph2.CSGrootNode;\r
+import org.simantics.g3d.csg.scenegraph2.ConeNode;\r
+import org.simantics.g3d.csg.scenegraph2.CylinderNode;\r
+import org.simantics.g3d.csg.scenegraph2.DifferenceNode;\r
+import org.simantics.g3d.csg.scenegraph2.EllipticCylinderNode;\r
+import org.simantics.g3d.csg.scenegraph2.ICSGnode;\r
+import org.simantics.g3d.csg.scenegraph2.IntersectionNode;\r
+import org.simantics.g3d.csg.scenegraph2.RectangularSolidNode;\r
+import org.simantics.g3d.csg.scenegraph2.RegularPrismNode;\r
+import org.simantics.g3d.csg.scenegraph2.SchemaBuilder;\r
+import org.simantics.g3d.csg.scenegraph2.SphereNode;\r
+import org.simantics.g3d.csg.scenegraph2.TorusNode;\r
+import org.simantics.g3d.csg.scenegraph2.UnionNode;\r
+import org.simantics.g3d.scenegraph.IG3DNode;\r
+import org.simantics.g3d.scenegraph.NodeMap;\r
+import org.simantics.g3d.scenegraph.base.INode;\r
+import org.simantics.g3d.vtk.action.RemoveAction;\r
+import org.simantics.g3d.vtk.action.RotateAction;\r
+import org.simantics.g3d.vtk.action.TranslateAction;\r
+import org.simantics.g3d.vtk.action.vtkCameraAndSelectorAction;\r
+import org.simantics.g3d.vtk.common.HoverHighlighter;\r
+import org.simantics.g3d.vtk.common.InteractiveVtkPanel;\r
+import org.simantics.g3d.vtk.common.NodeSelectionProvider2;\r
+import org.simantics.g3d.vtk.common.SelectionHighlighter;\r
+import org.simantics.g3d.vtk.common.VTKContentOutlinePage;\r
+import org.simantics.g3d.vtk.shape.vtkShape;\r
+import org.simantics.g3d.vtk.utils.vtkPanelUtil;\r
+import org.simantics.objmap.graph.IMapping;\r
+import org.simantics.objmap.graph.Mappings;\r
+import org.simantics.objmap.graph.schema.IMappingSchema;\r
+import org.simantics.selectionview.StandardPropertyPage;\r
+import org.simantics.ui.workbench.IPropertyPage;\r
+import org.simantics.ui.workbench.IResourceEditorInput;\r
+import org.simantics.ui.workbench.ResourceEditorPart;\r
+import org.simantics.utils.threads.AWTThread;\r
+import org.simantics.utils.threads.ThreadUtils;\r
+import org.simantics.utils.ui.ExceptionUtils;\r
+import org.simantics.utils.ui.SWTAWTComponent;\r
+\r
+import vtk.vtkActor;\r
+import vtk.vtkCameraPass;\r
+import vtk.vtkDefaultPass;\r
+import vtk.vtkLightsPass;\r
+import vtk.vtkRenderPassCollection;\r
+import vtk.vtkRenderer;\r
+import vtk.vtkSequencePass;\r
+\r
+public class CSGEditor2 extends ResourceEditorPart {\r
+ private Composite parent;\r
+ private Resource input;\r
+ private InteractiveVtkPanel panel;\r
+ private SWTAWTComponent component;\r
+ \r
+ private CSGrootNode rootNode;\r
+ private IMapping<Resource,Object> mapping;\r
+ \r
+ private NodeSelectionProvider2<Resource,Object> selectionProvider;\r
+ \r
+ private vtkCameraAndSelectorAction cameraAction;\r
+ private TranslateAction translateAction;\r
+ private RotateAction rotateAction;\r
+ private RemoveAction removeAction;\r
+ \r
+ //private ScenegraphOutlinePage outlinePage;\r
+ \r
+ private CSGNodeMap nodeMap;\r
+\r
+\r
+\r
+ @Override\r
+ public void createPartControl(Composite parent) {\r
+ this.parent = parent;\r
+ parent.setLayout (new FillLayout ());\r
+ component = new SWTAWTComponent(parent,SWT.NONE) {\r
+ \r
+ @Override\r
+ protected Component createSwingComponent() {\r
+ if (panel == null) {\r
+ panel = new InteractiveVtkPanel();\r
+ vtkPanelUtil.registerPanel(panel);\r
+ createScene();\r
+ }\r
+ return panel;\r
+ }\r
+ };\r
+\r
+ IResourceEditorInput rei = (IResourceEditorInput)getEditorInput();\r
+ input = rei.getResource();\r
+ \r
+ \r
+ //IActionBars actionBars = getEditorSite().getActionBars();\r
+\r
+ hookContextMenu();\r
+ \r
+ component.syncPopulate();\r
+ \r
+ panel.addMouseListener(new java.awt.event.MouseAdapter() {\r
+ @Override\r
+ public void mouseClicked(final java.awt.event.MouseEvent e) {\r
+ if (e.getButton() == java.awt.event.MouseEvent.BUTTON3) {\r
+ Display.getDefault().asyncExec(new Runnable() {\r
+ public void run() {\r
+ contextMenu.setLocation(e.getXOnScreen(), e.getYOnScreen());\r
+ contextMenu.setVisible(true);\r
+ }\r
+ });\r
+ }\r
+ }\r
+ });\r
+ \r
+\r
+ cameraAction = new vtkCameraAndSelectorAction(panel); \r
+ panel.setDefaultAction(cameraAction);\r
+ panel.useDefaultAction();\r
+ \r
+ try {\r
+ getSession().syncRequest(new ReadRequest() {\r
+ \r
+ @SuppressWarnings({ "rawtypes", "unchecked" })\r
+ @Override\r
+ public void run(ReadGraph graph) throws DatabaseException {\r
+ IMappingSchema schema = SchemaBuilder.getSchema(graph);\r
+ mapping = Mappings.createWithListening(schema);\r
+ rootNode = (CSGrootNode)mapping.map(graph, input);\r
+ nodeMap = new CSGNodeMap(getSession(), mapping, panel,(CSGrootNode)rootNode);\r
+ }\r
+ });\r
+ \r
+ if (rootNode == null)\r
+ throw new RuntimeException("Scenegraph loading failed.");\r
+ populate();\r
+ \r
+ selectionProvider = new NodeSelectionProvider2<Resource,Object>(this,mapping,nodeMap);\r
+\r
+ cameraAction.addSelectionChangedListener(selectionProvider);\r
+\r
+ cameraAction.addHoverChangedListener(new HoverHighlighter(panel,nodeMap));\r
+ selectionProvider.addSelectionChangedListener(new SelectionHighlighter(panel,nodeMap));\r
+ \r
+ getSite().setSelectionProvider(selectionProvider);\r
+ getSite().getPage().addPostSelectionListener(selectionProvider);\r
+ \r
+ //outlinePage = new ScenegraphOutlinePage(rootNode);\r
+ \r
+ \r
+ parent.addDisposeListener(new DisposeListener() {\r
+ \r
+ @Override\r
+ public void widgetDisposed(DisposeEvent e) {\r
+ getSite().getPage().removePostSelectionListener(selectionProvider);\r
+ ThreadUtils.asyncExec(AWTThread.getThreadAccess(), new Runnable() {\r
+ \r
+ @Override\r
+ public void run() {\r
+ nodeMap.delete();\r
+ vtkPanelUtil.unregisterPanel(panel);\r
+\r
+ }\r
+ });\r
+ mapping.dispose();\r
+ component.dispose();\r
+ \r
+ \r
+ }\r
+ });\r
+ } catch (DatabaseException e1) {\r
+ ExceptionUtils.logAndShowError("Cannot open CSG editor",e1);\r
+ return;\r
+ }\r
+ \r
+ translateAction = new TranslateAction(panel,nodeMap);\r
+ rotateAction = new RotateAction(panel,nodeMap);\r
+ removeAction = new RemoveAction(nodeMap) {\r
+ public void setNode(IG3DNode node) {\r
+ super.setNode(node);\r
+ if (node.getParent() instanceof CSGparentNode)\r
+ setEnabled(false);\r
+ \r
+ }\r
+ };\r
+ \r
+ \r
+ }\r
+ \r
+ \r
+\r
+ \r
+ public void populate() {\r
+ ThreadUtils.asyncExec(AWTThread.getThreadAccess(), new Runnable() {\r
+ \r
+ @Override\r
+ public void run() {\r
+ nodeMap.populate();\r
+ }\r
+ });\r
+ \r
+ }\r
+ \r
+ \r
+ \r
+ @Override\r
+ public void setFocus() {\r
+ component.setFocus();\r
+ }\r
+ \r
+ private void createScene() {\r
+ vtkRenderer ren1 = panel.GetRenderer();\r
+ \r
+ boolean multiPass = false;\r
+ if (multiPass) {\r
+ \r
+ vtkLightsPass lightsPass = new vtkLightsPass();\r
+ vtkDefaultPass defaultPass = new vtkDefaultPass();\r
+ \r
+ \r
+ vtkRenderPassCollection passes = new vtkRenderPassCollection();\r
+ passes.AddItem(lightsPass);\r
+ passes.AddItem(defaultPass);\r
+ \r
+ vtkSequencePass seq = new vtkSequencePass();\r
+ seq.SetPasses(passes);\r
+ \r
+ \r
+ \r
+ vtkCameraPass cameraPass = new vtkCameraPass();\r
+ cameraPass.SetDelegatePass(seq);\r
+ \r
+ ren1.SetPass(cameraPass);\r
+ \r
+ }\r
+// ren1.GetRenderWindow().LineSmoothingOn();\r
+// ren1.GetRenderWindow().PointSmoothingOn();\r
+// ren1.GetRenderWindow().PolygonSmoothingOn();\r
+// ren1.GetRenderWindow().SetMultiSamples(2);\r
+\r
+ \r
+\r
+ ren1.SetBackground2(1,1,1); // background color white\r
+ ren1.SetBackground(0.9,0.9,0.9);\r
+ ren1.SetGradientBackground(true);\r
+\r
+ // vtkActor grid = vtkShape.createGridActor(8,1.0,1|2|4);\r
+ vtkActor grid = vtkShape.createGridActor(8,1.0, 2 );\r
+ grid.SetPickable(0);\r
+ ren1.AddActor(grid);\r
+ panel.addDeletable(grid);\r
+ \r
+\r
+ \r
+ }\r
+ \r
+ protected Menu contextMenu;\r
+ \r
+ protected void hookContextMenu() {\r
+ MenuManager menuMgr = new MenuManager("#PopupMenu");\r
+ menuMgr.setRemoveAllWhenShown(true);\r
+ menuMgr.addMenuListener(new IMenuListener() {\r
+ public void menuAboutToShow(IMenuManager manager) {\r
+ final IMenuManager m = manager;\r
+ List<IG3DNode> selected = selectionProvider.getSelectedNodes();\r
+ if (selected.size() == 0) {\r
+ m.add(new AddPrimitiveAction2(rootNode, BarrelNode.class));\r
+ m.add(new AddPrimitiveAction2(rootNode, BoxNode.class));\r
+ m.add(new AddPrimitiveAction2(rootNode, ConeNode.class));\r
+ m.add(new AddPrimitiveAction2(rootNode, CylinderNode.class));\r
+ m.add(new AddPrimitiveAction2(rootNode, EllipticCylinderNode.class));\r
+ m.add(new AddPrimitiveAction2(rootNode, RectangularSolidNode.class));\r
+ m.add(new AddPrimitiveAction2(rootNode, RegularPrismNode.class));\r
+ m.add(new AddPrimitiveAction2(rootNode, SphereNode.class));\r
+ m.add(new AddPrimitiveAction2(rootNode, TorusNode.class));\r
+ } else if (selected.size() == 1) {\r
+ m.add(translateAction);\r
+ m.add(rotateAction);\r
+ m.add(removeAction);\r
+ ICSGnode node = (ICSGnode)selected.get(0);\r
+ translateAction.setNode(node);\r
+ rotateAction.setNode(node);\r
+ removeAction.setNode(node);\r
+ if (node instanceof CSGparentNode) {\r
+ m.add(new SplitBooleanOpAction2(rootNode,(CSGparentNode)node));\r
+ }\r
+ } else if (selected.size() == 2) {\r
+ if (selected.get(0).getParent().equals(rootNode) && selected.get(1).getParent().equals(rootNode)) {\r
+ Collection<ICSGnode> nodes = new ArrayList<ICSGnode>();\r
+ for (IG3DNode n : selected)\r
+ nodes.add((ICSGnode)n);\r
+ m.add(new AddBooleanOpAction2(rootNode, DifferenceNode.class, nodes));\r
+ m.add(new AddBooleanOpAction2(rootNode, IntersectionNode.class, nodes));\r
+ m.add(new AddBooleanOpAction2(rootNode, UnionNode.class, nodes));\r
+ }\r
+ }\r
+// try {\r
+// SimanticsUI.getSession().syncRequest(new ReadRequest() {\r
+// \r
+// @Override\r
+// public void run(ReadGraph graph) throws DatabaseException {\r
+// Layer0 l0 = Layer0.getInstance(graph);\r
+// CSG csg = CSG.getInstance(graph);\r
+// Resource ontology = graph.getResource("http://www.simantics.org/CSG-0.1");\r
+// \r
+// if (selectionProvider.getSelectedResources().size() == 0) {\r
+// List<NamedResource> primitives = new ArrayList<NamedResource>();\r
+// for (Resource r : graph.getObjects(ontology, l0.ConsistsOf)) {\r
+// if (graph.isInheritedFrom(r, csg.Primitive) && !r.equals(csg.Primitive)) {\r
+// primitives.add(new NamedResource((String)graph.getRelatedValue(r, l0.HasName), r));\r
+// }\r
+// }\r
+// \r
+// Collections.sort(primitives);\r
+// for (NamedResource n : primitives) {\r
+// m.add(new AddPrimitiveAction(graph, n.getResource(),input));\r
+// }\r
+// }\r
+// if (selectionProvider.getSelectedResources().size() == 2) {\r
+// List<NamedResource> booleanOps = new ArrayList<NamedResource>();\r
+// for (Resource r : graph.getObjects(ontology, l0.ConsistsOf)) {\r
+// if (graph.isInheritedFrom(r, csg.BooleanOperation) && !r.equals(csg.BooleanOperation)) {\r
+// booleanOps.add(new NamedResource((String)graph.getRelatedValue(r, l0.HasName), r));\r
+// }\r
+// }\r
+// \r
+// Collections.sort(booleanOps);\r
+// for (NamedResource n : booleanOps) {\r
+// m.add(new AddBooleanOpAction(graph, n.getResource(), input, selectionProvider.getSelectedResources()));\r
+// }\r
+// }\r
+// if (selectionProvider.getSelectedResources().size() == 1) {\r
+// m.add(translateAction);\r
+// m.add(rotateAction);\r
+// m.add(removeAction);\r
+// Resource selected = selectionProvider.getSelectedResources().get(0);\r
+// translateAction.setNode((IG3DNode2)mapping.get(selected));\r
+// rotateAction.setNode((IG3DNode2)mapping.get(selected));\r
+// removeAction.setNode((IG3DNode2)mapping.get(selected));\r
+// if (graph.isInstanceOf(selected, csg.BooleanOperation)) {\r
+// m.add(new SplitBooleanOpAction(input,selected));\r
+// }\r
+// \r
+// \r
+// }\r
+// \r
+// }\r
+// });\r
+// } catch (DatabaseException e) {\r
+// // TODO Auto-generated catch block\r
+// e.printStackTrace();\r
+// }\r
+ \r
+ }\r
+ });\r
+\r
+ contextMenu = menuMgr.createContextMenu(parent);\r
+ }\r
+ \r
+ private IContentOutlinePage createOutline() {\r
+ if (rootNode == null || selectionProvider == null)\r
+ return null;\r
+ IContentOutlinePage outlinePage = new VTKContentOutlinePage<Resource,Object>(rootNode, selectionProvider);\r
+ outlinePage.addSelectionChangedListener(new ISelectionChangedListener() {\r
+ \r
+ @Override\r
+ public void selectionChanged(SelectionChangedEvent event) {\r
+ selectionProvider.selectionChanged(event);\r
+ }\r
+ });\r
+ return outlinePage;\r
+ }\r
+\r
+ @SuppressWarnings("rawtypes")\r
+ @Override\r
+ public Object getAdapter(Class adapter) {\r
+ if (IPropertyPage.class.equals(adapter))\r
+ return new StandardPropertyPage(getSite(),getPropertyContexts());\r
+ if (IContentOutlinePage.class.equals(adapter)) {\r
+ return createOutline();\r
+ }\r
+ if (NodeMap.class.equals(adapter)) {\r
+ return nodeMap;\r
+ }\r
+ if (INode.class.equals(adapter)) {\r
+ return rootNode;\r
+ }\r
+ if (IMapping.class.equals(adapter)) {\r
+ return mapping;\r
+ }\r
+ if (InteractiveVtkPanel.class.equals(adapter)) {\r
+ return panel;\r
+ }\r
+ return super.getAdapter(adapter);\r
+ }\r
+ \r
+ public Set<String> getPropertyContexts() {\r
+ Set<String> result = new HashSet<String>();\r
+ result.add("http://www.simantics.org/Project-1.0/ProjectBrowseContext");\r
+ return result;\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.g3d.csg.editor;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.List;\r
+import java.util.Set;\r
+\r
+import org.simantics.db.Session;\r
+import org.simantics.g3d.csg.scenegraph2.CSGrootNode;\r
+import org.simantics.g3d.csg.scenegraph2.ICSGnode;\r
+import org.simantics.g3d.scenegraph.base.ParentNode;\r
+import org.simantics.g3d.vtk.common.AbstractVTKNodeMap;\r
+import org.simantics.g3d.vtk.common.InteractiveVtkPanel;\r
+import org.simantics.objmap.graph.IMapping;\r
+import org.simantics.utils.threads.AWTThread;\r
+\r
+import vtk.vtkProp;\r
+import vtk.vtkProp3D;\r
+import vtk.vtkRenderer;\r
+\r
+public class CSGNodeMap extends AbstractVTKNodeMap<ICSGnode> {\r
+ \r
+\r
+ \r
+ public CSGNodeMap(Session session, IMapping mapping, InteractiveVtkPanel panel, CSGrootNode rootNode) {\r
+ super(session, mapping, panel, rootNode);\r
+ rootNode.setNodeMap(this);\r
+ }\r
+ \r
+\r
+ @SuppressWarnings("unchecked")\r
+ protected void updateActor(ICSGnode node, Set<String> ids) {\r
+ //System.out.println("CSGNodeMap.updateActor " + node);\r
+ if (node.getParent() instanceof ICSGnode) {\r
+ ICSGnode parent = (ICSGnode) node.getParent();\r
+ if (!"child".equals(node.getParentRel())) {\r
+ updateActor(parent,null);\r
+ return;\r
+ }\r
+ }\r
+ \r
+ if (node instanceof ParentNode<?>) {\r
+ ParentNode<ICSGnode> p = (ParentNode<ICSGnode>)node;\r
+ for (ICSGnode n : p.getNodes())\r
+ remActor(n);\r
+ }\r
+ \r
+ remActor(node);\r
+ addActor(node);\r
+\r
+ }\r
+\r
+ @Override\r
+ protected Collection<vtkProp> getActors(ICSGnode node) {\r
+ List<vtkProp> props = new ArrayList<vtkProp>();\r
+ for (vtkProp3D p : ((ICSGnode)node).getActors())\r
+ props.add(p);\r
+ return props;\r
+ }\r
+ \r
+ protected void removeActor(ICSGnode node) {\r
+ //System.out.println("CSGNodeMap.removeActor " + node);\r
+ remActor(node);\r
+ \r
+ if (!"child".equals(node.getParentRel())) {\r
+ if (node.getParent() instanceof ICSGnode)\r
+ updateActor((ICSGnode)node.getParent(),null);\r
+ }\r
+ }\r
+ \r
+ protected void addActor(ICSGnode node) {\r
+ //System.out.println("CSGNodeMap.addActor " + node);\r
+ if (hasActor(node))\r
+ return;\r
+ if (Thread.currentThread() != AWTThread.getThreadAccess().getThread())\r
+ throw new RuntimeException("Illegal thread.");\r
+ \r
+ panel.lock();\r
+ \r
+ node.visualize(panel);\r
+\r
+ for (vtkProp3D act : node.getActors()) {\r
+ nodeToActor.add(node, act);\r
+ actorToNode.put(act, node);\r
+ }\r
+\r
+ panel.unlock();\r
+\r
+ }\r
+ \r
+ \r
+ \r
+ private boolean hasActor(ICSGnode node) {\r
+ List<vtkProp> list = nodeToActor.getValues(node);\r
+ if (list == null || list.size() == 0)\r
+ return false;\r
+ return true;\r
+ }\r
+ \r
+ private void remActor(ICSGnode node) {\r
+ if (Thread.currentThread() != AWTThread.getThreadAccess().getThread())\r
+ throw new RuntimeException("Illegal thread.");\r
+\r
+ List<vtkProp> list = nodeToActor.getValues(node);\r
+ if (list != null) {\r
+ for (vtkProp obj : list) {\r
+ actorToNode.remove(obj); \r
+ }\r
+ nodeToActor.remove(node);\r
+ panel.lock();\r
+ \r
+ node.stopVisualize();\r
+ \r
+ panel.unlock();\r
+ }\r
+ }\r
+ \r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.csg.scenegraph2;\r
+\r
+import org.jcae.opencascade.jni.BRepBuilderAPI_MakeEdge;\r
+import org.jcae.opencascade.jni.BRepBuilderAPI_MakeFace;\r
+import org.jcae.opencascade.jni.BRepBuilderAPI_MakeWire;\r
+import org.jcae.opencascade.jni.BRepPrimAPI_MakeRevol;\r
+import org.jcae.opencascade.jni.GC_MakeArcOfCircle;\r
+import org.jcae.opencascade.jni.GC_MakeSegment;\r
+import org.jcae.opencascade.jni.TopoDS_Edge;\r
+import org.jcae.opencascade.jni.TopoDS_Face;\r
+import org.jcae.opencascade.jni.TopoDS_Shape;\r
+import org.jcae.opencascade.jni.TopoDS_Wire;\r
+import org.simantics.g3d.csg.ontology.CSG;\r
+import org.simantics.g3d.property.annotations.GetPropertyValue;\r
+import org.simantics.g3d.property.annotations.SetPropertyValue;\r
+import org.simantics.objmap.graph.annotations.GraphType;\r
+import org.simantics.objmap.graph.annotations.RelatedGetValue;\r
+import org.simantics.objmap.graph.annotations.RelatedSetValue;\r
+\r
+@GraphType(CSG.URIs.Barrel)\r
+public class BarrelNode extends CSGnode {\r
+\r
+ private double r1 = 1.0;\r
+ private double r2 = 1.1;\r
+ private double h = 1.0;\r
+ \r
+ \r
+\r
+ @RelatedSetValue(CSG.URIs.HasMinorRadius)\r
+ @SetPropertyValue(CSG.URIs.HasMinorRadius)\r
+ public void setR1(double r1) {\r
+ this.r1 = r1;\r
+ firePropertyChanged(CSG.URIs.HasMinorRadius);\r
+ }\r
+ \r
+ @RelatedSetValue(CSG.URIs.HasMajorRadius)\r
+ @SetPropertyValue(CSG.URIs.HasMajorRadius)\r
+ public void setR2(double r2) {\r
+ this.r2 = r2;\r
+ firePropertyChanged(CSG.URIs.HasMajorRadius);\r
+ }\r
+ \r
+ @RelatedSetValue(CSG.URIs.HasHeight)\r
+ @SetPropertyValue(CSG.URIs.HasHeight)\r
+ public void setH(double h) {\r
+ this.h = h;\r
+ firePropertyChanged(CSG.URIs.HasHeight);\r
+ }\r
+ \r
+ @RelatedGetValue(CSG.URIs.HasHeight)\r
+ @GetPropertyValue(value=CSG.URIs.HasHeight, name = "Height")\r
+ public double getH() {\r
+ return h;\r
+ }\r
+ \r
+ @RelatedGetValue(CSG.URIs.HasMinorRadius)\r
+ @GetPropertyValue(value=CSG.URIs.HasMinorRadius, name = "Minor Radius")\r
+ public double getR1() {\r
+ return r1;\r
+ }\r
+ \r
+ @RelatedGetValue(CSG.URIs.HasMajorRadius)\r
+ @GetPropertyValue(value=CSG.URIs.HasMajorRadius, name = "Major Radius")\r
+ public double getR2() {\r
+ return r2;\r
+ }\r
+ \r
+ @Override\r
+ public TopoDS_Shape getBaseGeometry() {\r
+ if (Math.abs(r1 -r2)< MIN_VALUE)\r
+ r2 = r1 + MIN_VALUE;\r
+ double p0[] = new double[]{0.0,-h*0.5,0.0};\r
+ double p1[] = new double[]{0.0,-h*0.5,r1};\r
+ double p2[] = new double[]{0.0, 0.0 ,r2};\r
+ double p3[] = new double[]{0.0, h*0.5,r1};\r
+ double p4[] = new double[]{0.0, h*0.5,0.0};\r
+ GC_MakeArcOfCircle m = new GC_MakeArcOfCircle(p1,p2,p3);\r
+ GC_MakeSegment s1 = new GC_MakeSegment(p0,p1);\r
+ GC_MakeSegment s2 = new GC_MakeSegment(p3,p4);\r
+ \r
+ BRepBuilderAPI_MakeEdge edge = new BRepBuilderAPI_MakeEdge(s1.value());\r
+ TopoDS_Edge e1 = (TopoDS_Edge)edge.shape();\r
+ edge.delete();\r
+ \r
+ edge = new BRepBuilderAPI_MakeEdge(m.value());\r
+ TopoDS_Edge e2 = (TopoDS_Edge)edge.shape();\r
+ edge.delete();\r
+ \r
+ edge = new BRepBuilderAPI_MakeEdge(s2.value());\r
+ TopoDS_Edge e3 = (TopoDS_Edge)edge.shape();\r
+ edge.delete();\r
+ \r
+ BRepBuilderAPI_MakeWire wire = new BRepBuilderAPI_MakeWire(e1,e2,e3);\r
+ TopoDS_Wire w = (TopoDS_Wire)wire.shape();\r
+ wire.delete();\r
+ \r
+ BRepBuilderAPI_MakeFace face = new BRepBuilderAPI_MakeFace(w);\r
+ TopoDS_Face F = (TopoDS_Face) face.shape();\r
+ face.delete();\r
+ \r
+ BRepPrimAPI_MakeRevol revol = new BRepPrimAPI_MakeRevol(F,new double[]{0.0,0.0,0.0,0.0,1.0,0.0}); \r
+ TopoDS_Shape shape = revol.shape();\r
+ revol.delete();\r
+ \r
+ m.delete();\r
+ s1.delete();\r
+ s2.delete();\r
+ e1.delete();\r
+ e2.delete();\r
+ e3.delete();\r
+ w.delete();\r
+ F.delete();\r
+ return shape;\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.csg.scenegraph2;\r
+\r
+import org.jcae.opencascade.jni.TopoDS_Shape;\r
+import org.simantics.g3d.csg.ontology.CSG;\r
+import org.simantics.g3d.property.annotations.GetPropertyValue;\r
+import org.simantics.g3d.property.annotations.SetPropertyValue;\r
+import org.simantics.objmap.graph.annotations.GraphType;\r
+import org.simantics.objmap.graph.annotations.RelatedGetValue;\r
+import org.simantics.objmap.graph.annotations.RelatedSetValue;\r
+import org.simantics.opencascade.OccTriangulator;\r
+\r
+@GraphType(CSG.URIs.Box)\r
+public class BoxNode extends CSGnode {\r
+\r
+ private double sx = 1.0;\r
+ private double sy = 1.0;\r
+ private double sz = 1.0;\r
+ \r
+ public BoxNode() {\r
+ System.out.println();\r
+ }\r
+ \r
+ @RelatedSetValue(CSG.URIs.HasXAxisSize)\r
+ @SetPropertyValue(CSG.URIs.HasXAxisSize)\r
+ public void setSX(double d) {\r
+ this.sx = d;\r
+ firePropertyChanged(CSG.URIs.HasXAxisSize);\r
+ }\r
+ \r
+ @RelatedSetValue(CSG.URIs.HasYAxisSize)\r
+ @SetPropertyValue(CSG.URIs.HasYAxisSize)\r
+ public void setSY(double d) {\r
+ this.sy = d;\r
+ firePropertyChanged(CSG.URIs.HasYAxisSize);\r
+ }\r
+ \r
+ @RelatedSetValue(CSG.URIs.HasZAxisSize)\r
+ @SetPropertyValue(CSG.URIs.HasZAxisSize)\r
+ public void setSZ(double d) {\r
+ this.sz = d;\r
+ firePropertyChanged(CSG.URIs.HasZAxisSize);\r
+ }\r
+ \r
+ @RelatedGetValue(CSG.URIs.HasXAxisSize)\r
+ @GetPropertyValue(value=CSG.URIs.HasXAxisSize, name = "X Size")\r
+ public double getSx() {\r
+ return sx;\r
+ }\r
+ \r
+ @RelatedGetValue(CSG.URIs.HasYAxisSize)\r
+ @GetPropertyValue(value=CSG.URIs.HasYAxisSize, name = "Y Size")\r
+ public double getSy() {\r
+ return sy;\r
+ }\r
+ \r
+ @RelatedGetValue(CSG.URIs.HasZAxisSize)\r
+ @GetPropertyValue(value=CSG.URIs.HasZAxisSize, name = "Z Size")\r
+ public double getSz() {\r
+ return sz;\r
+ }\r
+ \r
+ \r
+ @Override\r
+ public TopoDS_Shape getBaseGeometry() {\r
+ return OccTriangulator.makeBox(-sx * 0.5, -sy * 0.5, -sz * 0.5, sx * 0.5, sy * 0.5, sz * 0.5);\r
+ }\r
+\r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.csg.scenegraph2;\r
+\r
+import java.util.Collection;\r
+import java.util.Collections;\r
+\r
+import javax.vecmath.AxisAngle4d;\r
+import javax.vecmath.Quat4d;\r
+import javax.vecmath.Vector3d;\r
+\r
+import org.jcae.opencascade.jni.TopoDS_Shape;\r
+import org.simantics.g3d.property.annotations.GetPropertyValue;\r
+import org.simantics.g3d.property.annotations.SetPropertyValue;\r
+import org.simantics.g3d.scenegraph.G3DNode;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.objmap.graph.annotations.RelatedGetValue;\r
+import org.simantics.objmap.graph.annotations.RelatedSetValue;\r
+import org.simantics.opencascade.OccTriangulator;\r
+import org.simantics.opencascade.vtk.vtkSolidObject;\r
+import org.simantics.utils.threads.AWTThread;\r
+\r
+import vtk.vtkPanel;\r
+import vtk.vtkProp3D;\r
+import vtk.vtkRenderer;\r
+\r
+public abstract class CSGnode extends G3DNode implements ICSGnode {\r
+\r
+ public static final double MIN_VALUE = 0.001;\r
+ \r
+ private String name;\r
+ \r
+\r
+ @RelatedGetValue(Layer0.URIs.HasName)\r
+ @GetPropertyValue(value = Layer0.URIs.HasName, tabId = "Default", name = "Name")\r
+ public String getName() {\r
+ return name;\r
+ }\r
+ \r
+ @RelatedSetValue(Layer0.URIs.HasName)\r
+ @SetPropertyValue(Layer0.URIs.HasName)\r
+ public void setName(String name) {\r
+ if (name == null)\r
+ return;\r
+ this.name = name;\r
+ firePropertyChanged(Layer0.URIs.HasName);\r
+ }\r
+ \r
+ @Override\r
+ public String toString() {\r
+ return getName();\r
+ }\r
+ \r
+ \r
+ private vtkSolidObject solidObject;\r
+ \r
+ @Override\r
+ public TopoDS_Shape getGeometry() {\r
+ TopoDS_Shape shape = getBaseGeometry();\r
+ if (shape == null)\r
+ return null;\r
+ Quat4d q = getOrientation();\r
+ AxisAngle4d r = new AxisAngle4d();\r
+ r.set(q);\r
+ TopoDS_Shape tshape = OccTriangulator.makeRotation(shape, new double[] { 0.0, 0.0, 0.0, r.x, r.y, r.z }, r.angle);\r
+ shape.delete();\r
+ shape = tshape;\r
+ Vector3d p = getPosition();\r
+ tshape = OccTriangulator.makeTranslation(shape, p.x, p.y, p.z);\r
+ shape.delete();\r
+ return tshape; \r
+ }\r
+ \r
+ public void visualize(vtkPanel panel) {\r
+ if (solidObject != null) {\r
+ solidObject.delete();\r
+ solidObject = null;\r
+ }\r
+ TopoDS_Shape shape = getGeometry();\r
+ if (shape == null)\r
+ return;\r
+ solidObject = new vtkSolidObject(panel, shape);\r
+ solidObject.visualizeSolid(true, false);\r
+ }\r
+ \r
+ @SuppressWarnings("unchecked")\r
+ public Collection<vtkProp3D> getActors() {\r
+ if (solidObject == null)\r
+ return Collections.EMPTY_LIST;\r
+ return solidObject.getActors();\r
+ }\r
+ \r
+ public void stopVisualize() {\r
+ if (solidObject != null) {\r
+ if (Thread.currentThread() == AWTThread.getThreadAccess().getThread())\r
+ solidObject.delete();\r
+ else\r
+ solidObject.dispose();\r
+ solidObject = null;\r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public void cleanup() {\r
+ stopVisualize();\r
+ super.cleanup();\r
+ }\r
+ \r
+ \r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.csg.scenegraph2;\r
+\r
+import java.util.Collection;\r
+import java.util.Collections;\r
+\r
+import javax.vecmath.AxisAngle4d;\r
+import javax.vecmath.Quat4d;\r
+import javax.vecmath.Vector3d;\r
+\r
+import org.jcae.opencascade.jni.TopoDS_Shape;\r
+import org.simantics.g3d.csg.ontology.CSG;\r
+import org.simantics.g3d.math.MathTools;\r
+import org.simantics.g3d.ontology.G3D;\r
+import org.simantics.g3d.property.annotations.GetPropertyValue;\r
+import org.simantics.g3d.property.annotations.PropertyContributor;\r
+import org.simantics.g3d.property.annotations.SetPropertyValue;\r
+import org.simantics.g3d.scenegraph.IG3DNode;\r
+import org.simantics.g3d.scenegraph.base.ParentNode;\r
+import org.simantics.g3d.tools.NodeTools;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.objmap.graph.annotations.RelatedElementsAdd;\r
+import org.simantics.objmap.graph.annotations.RelatedElementsGet;\r
+import org.simantics.objmap.graph.annotations.RelatedElementsRem;\r
+import org.simantics.objmap.graph.annotations.RelatedGetValue;\r
+import org.simantics.objmap.graph.annotations.RelatedSetValue;\r
+import org.simantics.opencascade.OccTriangulator;\r
+import org.simantics.opencascade.vtk.vtkSolidObject;\r
+import org.simantics.utils.threads.AWTThread;\r
+\r
+import vtk.vtkPanel;\r
+import vtk.vtkProp3D;\r
+\r
+@PropertyContributor\r
+public abstract class CSGparentNode extends ParentNode<ICSGnode> implements ICSGnode {\r
+\r
+ private String name;\r
+ \r
+\r
+ @RelatedGetValue(Layer0.URIs.HasName)\r
+ @GetPropertyValue(value = Layer0.URIs.HasName, tabId = "Default", name = "Name")\r
+ public String getName() {\r
+ return name;\r
+ }\r
+ \r
+ @RelatedSetValue(Layer0.URIs.HasName)\r
+ @SetPropertyValue(Layer0.URIs.HasName)\r
+ public void setName(String name) {\r
+ if (name == null)\r
+ return;\r
+ this.name = name;\r
+ firePropertyChanged(Layer0.URIs.HasName);\r
+ }\r
+ \r
+ @Override\r
+ public String toString() {\r
+ return getName();\r
+ }\r
+ \r
+ private Vector3d position = new Vector3d();\r
+ private Quat4d orientation = MathTools.getIdentityQuat();\r
+ \r
+ @Override\r
+ @GetPropertyValue(value = G3D.URIs.hasOrientation, tabId = "Transform", name = "Orientation")\r
+ public Quat4d getOrientation() {\r
+ return orientation;\r
+ }\r
+ \r
+ @RelatedGetValue(G3D.URIs.hasOrientation)\r
+ public double[] getOrientationArr() {\r
+ double arr[] = new double[4];\r
+ orientation.get(arr);\r
+ return arr;\r
+ \r
+ }\r
+ \r
+ @Override\r
+ @GetPropertyValue(value = G3D.URIs.hasPosition, tabId = "Transform", name = "Position")\r
+ public Vector3d getPosition() {\r
+ return position;\r
+ }\r
+ \r
+ @RelatedGetValue(G3D.URIs.hasPosition)\r
+ public double[] getPositionArr() {\r
+ double arr[] = new double[3];\r
+ position.get(arr);\r
+ return arr;\r
+ }\r
+ \r
+ @RelatedElementsAdd(CSG.URIs.hasPrimaryShape)\r
+ public void addPrimaryChild(ICSGnode node) {\r
+ addNode("primary",node);\r
+ }\r
+ \r
+ @RelatedElementsGet(CSG.URIs.hasPrimaryShape)\r
+ public Collection<ICSGnode> getPrimaryChild() {\r
+ return getNodes("primary");\r
+ }\r
+ \r
+ @RelatedElementsRem(CSG.URIs.hasPrimaryShape)\r
+ public void remPrimaryChild(ICSGnode node) {\r
+ removeNode("primary", node);\r
+ }\r
+ \r
+ @RelatedElementsAdd(CSG.URIs.hasSecondaryShape)\r
+ public void addSecondaryChild(ICSGnode node) {\r
+ addNode("secondary",node);\r
+ }\r
+ \r
+ @RelatedElementsGet(CSG.URIs.hasSecondaryShape)\r
+ public Collection<ICSGnode> getSecondaryChild() {\r
+ return getNodes("secondary");\r
+ }\r
+ \r
+ @RelatedElementsRem(CSG.URIs.hasSecondaryShape)\r
+ public void remSecondaryChild(ICSGnode node) {\r
+ removeNode("secondary", node);\r
+ }\r
+ \r
+\r
+ @RelatedElementsAdd(CSG.URIs.hasChildShape)\r
+ public void addChild(ICSGnode node) {\r
+ addNode("child",node);\r
+ }\r
+ \r
+ @RelatedElementsGet(CSG.URIs.hasChildShape)\r
+ public Collection<ICSGnode> getChild() {\r
+ return getNodes("child");\r
+ }\r
+ \r
+ @RelatedElementsRem(CSG.URIs.hasChildShape)\r
+ public void remChild(ICSGnode node) {\r
+ removeNode("child", node);\r
+ }\r
+ \r
+ \r
+ \r
+ protected TopoDS_Shape getPrimary() {\r
+ for (ICSGnode node : getNodes("primary"))\r
+ return node.getGeometry();\r
+ return null;\r
+ }\r
+ \r
+ protected TopoDS_Shape getSecondary() {\r
+ for (ICSGnode node : getNodes("secondary"))\r
+ return node.getGeometry();\r
+ return null;\r
+ }\r
+ \r
+ @Override\r
+ public TopoDS_Shape getGeometry() {\r
+ TopoDS_Shape shape = getBaseGeometry();\r
+ if (shape == null)\r
+ return null;\r
+ Quat4d q = getOrientation();\r
+ AxisAngle4d r = new AxisAngle4d();\r
+ r.set(q);\r
+ TopoDS_Shape tshape = OccTriangulator.makeRotation(shape, new double[] { 0.0, 0.0, 0.0, r.x, r.y, r.z }, r.angle);\r
+ shape.delete();\r
+ shape = tshape;\r
+ Vector3d p = getPosition();\r
+ tshape = OccTriangulator.makeTranslation(shape, p.x, p.y, p.z);\r
+ shape.delete();\r
+ return tshape;\r
+ \r
+ }\r
+ \r
+\r
+ \r
+ @Override\r
+ @SetPropertyValue(G3D.URIs.hasOrientation)\r
+ public void setOrientation(Quat4d orientation) {\r
+ assert(orientation != null);\r
+ this.orientation = orientation;\r
+ \r
+ firePropertyChanged(G3D.URIs.hasOrientation);\r
+ }\r
+ \r
+ @Override\r
+ @SetPropertyValue(G3D.URIs.hasPosition)\r
+ public void setPosition(Vector3d position) {\r
+ assert(position != null);\r
+ this.position = position;\r
+ \r
+ firePropertyChanged(G3D.URIs.hasPosition);\r
+ }\r
+ \r
+ @RelatedSetValue(G3D.URIs.hasOrientation)\r
+ public void setOrientation(double[] arr) {\r
+ if (arr == null)\r
+ return;\r
+ setOrientation(new Quat4d(arr));\r
+ }\r
+ \r
+ @RelatedSetValue(G3D.URIs.hasPosition)\r
+ public void setPosition(double[] arr) {\r
+ if (arr == null)\r
+ return;\r
+ setPosition(new Vector3d(arr));\r
+ }\r
+ \r
+ @Override\r
+ @GetPropertyValue(value = G3D.URIs.hasWorldPosition, tabId = "Transform", name = "World Position")\r
+ public Vector3d getWorldPosition() {\r
+ IG3DNode parent = (IG3DNode) getParent();\r
+ if (parent == null)\r
+ return position;\r
+ return NodeTools.getWorldPosition(parent, new Vector3d(position));\r
+ }\r
+\r
+ public Vector3d getWorldPosition(Vector3d localPosition) {\r
+ return NodeTools.getWorldPosition(this, localPosition);\r
+ }\r
+\r
+ \r
+ @Override\r
+ @GetPropertyValue(value = G3D.URIs.hasWorldOrientation, tabId = "Transform", name = "World Orientation")\r
+ public Quat4d getWorldOrientation() {\r
+ return getWorldOrientation(new Quat4d(orientation));\r
+ }\r
+ \r
+ public Quat4d getWorldOrientation(Quat4d localOrientation) {\r
+ IG3DNode parent = (IG3DNode)getParent();\r
+ if (parent == null)\r
+ return localOrientation;\r
+ return NodeTools.getWorldOrientation(parent, localOrientation);\r
+ }\r
+ \r
+ @Override\r
+ public Vector3d getLocalPosition(Vector3d worldPosition) {\r
+ IG3DNode parent = (IG3DNode)getParent();\r
+ if (parent == null)\r
+ return worldPosition;\r
+ return NodeTools.getLocalPosition(parent,new Vector3d(worldPosition));\r
+ }\r
+ \r
+ @Override\r
+ public Quat4d getLocalOrientation(Quat4d worldOrientation) {\r
+ IG3DNode parent = (IG3DNode)getParent();\r
+ if (parent == null)\r
+ return worldOrientation;\r
+ return NodeTools.getLocalOrientation(parent, new Quat4d(worldOrientation));\r
+ }\r
+ \r
+ @Override\r
+ @SetPropertyValue(G3D.URIs.hasWorldPosition)\r
+ public void setWorldPosition(Vector3d position) {\r
+ Vector3d localPos = getLocalPosition(position);\r
+ setPosition(localPos);\r
+ }\r
+ \r
+ @Override\r
+ @SetPropertyValue(G3D.URIs.hasWorldOrientation)\r
+ public void setWorldOrientation(Quat4d orientation) {\r
+ Quat4d localOr = getLocalOrientation(orientation);\r
+ setOrientation(localOr);\r
+ }\r
+\r
+\r
+ private vtkSolidObject solidObject;\r
+ \r
+ \r
+ public void visualize(vtkPanel panel) {\r
+ if (solidObject != null) {\r
+ solidObject.delete();\r
+ solidObject = null;\r
+ }\r
+ TopoDS_Shape shape = getGeometry();\r
+ if (shape == null)\r
+ return;\r
+ solidObject = new vtkSolidObject(panel, shape);\r
+ solidObject.visualizeSolid(true, false);\r
+ }\r
+ \r
+ @SuppressWarnings("unchecked")\r
+ public Collection<vtkProp3D> getActors() {\r
+ if (solidObject == null)\r
+ return Collections.EMPTY_LIST;\r
+ return solidObject.getActors();\r
+ }\r
+ \r
+ public void stopVisualize() {\r
+ if (solidObject != null) {\r
+ if (Thread.currentThread() == AWTThread.getThreadAccess().getThread())\r
+ solidObject.delete();\r
+ else\r
+ solidObject.dispose();\r
+ solidObject = null;\r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public void cleanup() {\r
+ stopVisualize();\r
+ super.cleanup();\r
+ }\r
+ \r
+ \r
+ @Override\r
+ public void remove() {\r
+ //FIXME: creating boolean shapes (removing nodes from parent and attaching under boolean shape would destroy the existing hierarchy, if default implementation is used.\r
+ super.remove();\r
+ }\r
+\r
+ @Override\r
+ public Object getAdapter(Class adapter) {\r
+ return null;\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.g3d.csg.scenegraph2;\r
+\r
+import java.util.Collection;\r
+import java.util.HashSet;\r
+import java.util.Set;\r
+import java.util.Stack;\r
+\r
+import javax.vecmath.Quat4d;\r
+import javax.vecmath.Vector3d;\r
+\r
+import org.simantics.g3d.csg.editor.CSGNodeMap;\r
+import org.simantics.g3d.csg.ontology.CSG;\r
+import org.simantics.g3d.math.MathTools;\r
+import org.simantics.g3d.scenegraph.IG3DNode;\r
+import org.simantics.g3d.scenegraph.NodeMap;\r
+import org.simantics.g3d.scenegraph.NodeMapProvider;\r
+import org.simantics.g3d.scenegraph.base.NodeException;\r
+import org.simantics.g3d.scenegraph.base.ParentNode;\r
+import org.simantics.objmap.graph.annotations.GraphType;\r
+import org.simantics.objmap.graph.annotations.RelatedElementsAdd;\r
+import org.simantics.objmap.graph.annotations.RelatedElementsGet;\r
+import org.simantics.objmap.graph.annotations.RelatedElementsRem;\r
+\r
+import vtk.vtkProp;\r
+\r
+\r
+@GraphType(CSG.URIs.Model)\r
+public class CSGrootNode extends ParentNode<ICSGnode> implements IG3DNode, NodeMapProvider<vtkProp> {\r
+ \r
+ \r
+ private CSGNodeMap nodeMap;\r
+ \r
+ public void setNodeMap(CSGNodeMap nodeMap) {\r
+ this.nodeMap = nodeMap;\r
+ }\r
+ \r
+ @Override\r
+ public NodeMap<vtkProp> getNodeMap() {\r
+ return nodeMap;\r
+ }\r
+ \r
+ @Override\r
+ public ParentNode<?> getParent() {\r
+ return null;\r
+ }\r
+ \r
+ @Override\r
+ public ParentNode<?> getRootNode() {\r
+ return this;\r
+ }\r
+ \r
+ @RelatedElementsAdd(CSG.URIs.hasChildShape)\r
+ public void addChild(ICSGnode node) {\r
+ addNode("child",node);\r
+ }\r
+ \r
+ @RelatedElementsGet(CSG.URIs.hasChildShape)\r
+ public Collection<ICSGnode> getChild() {\r
+ return getNodes("child");\r
+ }\r
+ \r
+ @RelatedElementsRem(CSG.URIs.hasChildShape)\r
+ public void remChild(ICSGnode node) {\r
+ removeNode("child", node);\r
+ }\r
+ \r
+ public javax.vecmath.Quat4d getOrientation() {\r
+ return MathTools.getIdentityQuat();\r
+ };\r
+ \r
+ @Override\r
+ public Vector3d getPosition() {\r
+ return new Vector3d();\r
+ }\r
+ \r
+ @Override\r
+ public Quat4d getWorldOrientation() {\r
+ return MathTools.getIdentityQuat();\r
+ }\r
+ \r
+ @Override\r
+ public Vector3d getWorldPosition() {\r
+ return new Vector3d();\r
+ }\r
+ \r
+ @Override\r
+ public Quat4d getWorldOrientation(Quat4d localOrientation) {\r
+ return localOrientation;\r
+ }\r
+ \r
+ @Override\r
+ public Vector3d getWorldPosition(Vector3d localPosition) {\r
+ return localPosition;\r
+ }\r
+ \r
+ @Override\r
+ public Quat4d getLocalOrientation(Quat4d worldOrientation) {\r
+ return worldOrientation;\r
+ }\r
+ \r
+ @Override\r
+ public Vector3d getLocalPosition(Vector3d worldPosition) {\r
+ return worldPosition;\r
+ }\r
+ \r
+ @Override\r
+ public void setPosition(Vector3d position) {\r
+ throw new NodeException("Cannot set root node position");\r
+ }\r
+ \r
+ @Override\r
+ public void setOrientation(Quat4d orientation) {\r
+ throw new NodeException("Cannot set root node orientation");\r
+ }\r
+ \r
+ @Override\r
+ public void setWorldOrientation(Quat4d orientation) {\r
+ throw new NodeException("Cannot set root node orientation");\r
+ }\r
+ \r
+ @Override\r
+ public void setWorldPosition(Vector3d position) {\r
+ throw new NodeException("Cannot set root node orientation");\r
+ }\r
+ \r
+ public String getUniqueName(String prefix) {\r
+ Set<String> names = new HashSet<String>();\r
+ Stack<ICSGnode> nodes = new Stack<ICSGnode>();\r
+ nodes.addAll(getChild());\r
+ while (!nodes.isEmpty()) {\r
+ ICSGnode n = nodes.pop();\r
+ names.add(((ICSGnode)n).getName());\r
+ if (n instanceof CSGparentNode) {\r
+ nodes.addAll(((CSGparentNode)n).getChild());\r
+ nodes.addAll(((CSGparentNode)n).getPrimaryChild());\r
+ nodes.addAll(((CSGparentNode)n).getSecondaryChild());\r
+ }\r
+ }\r
+ int i = 1;\r
+ while (true) {\r
+ String genName = prefix + "_" + i;\r
+ if (!names.contains(genName))\r
+ return genName;\r
+ i++;\r
+ }\r
+ }\r
+ \r
+\r
+ @Override\r
+ public Object getAdapter(Class adapter) {\r
+ if (NodeMap.class == adapter)\r
+ return nodeMap;\r
+ return null;\r
+ }\r
+ \r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.csg.scenegraph2;\r
+\r
+import org.jcae.opencascade.jni.TopoDS_Shape;\r
+import org.simantics.g3d.csg.ontology.CSG;\r
+import org.simantics.g3d.property.annotations.GetPropertyValue;\r
+import org.simantics.g3d.property.annotations.SetPropertyValue;\r
+import org.simantics.objmap.graph.annotations.GraphType;\r
+import org.simantics.objmap.graph.annotations.RelatedGetValue;\r
+import org.simantics.objmap.graph.annotations.RelatedSetValue;\r
+import org.simantics.opencascade.OccTriangulator;\r
+\r
+@GraphType(CSG.URIs.Cone)\r
+public class ConeNode extends CSGnode {\r
+\r
+ private double r1 = 1.0;\r
+ private double r2 = 0.5;\r
+ private double h = 1.0;\r
+ \r
+ \r
+ @RelatedSetValue(CSG.URIs.HasBottomRadius)\r
+ @SetPropertyValue(CSG.URIs.HasBottomRadius)\r
+ public void setR1(double r1) {\r
+ this.r1 = r1;\r
+ firePropertyChanged(CSG.URIs.HasBottomRadius);\r
+ }\r
+ \r
+ @RelatedSetValue(CSG.URIs.HasTopRadius)\r
+ @SetPropertyValue(CSG.URIs.HasTopRadius)\r
+ public void setR2(double r2) {\r
+ this.r2 = r2;\r
+ firePropertyChanged(CSG.URIs.HasTopRadius);\r
+ }\r
+ \r
+ @RelatedSetValue(CSG.URIs.HasHeight)\r
+ @SetPropertyValue(CSG.URIs.HasHeight)\r
+ public void setH(double h) {\r
+ this.h = h;\r
+ firePropertyChanged(CSG.URIs.HasHeight);\r
+ }\r
+ \r
+ @RelatedGetValue(CSG.URIs.HasHeight)\r
+ @GetPropertyValue(value=CSG.URIs.HasHeight, name = "Height")\r
+ public double getH() {\r
+ return h;\r
+ }\r
+ \r
+ @RelatedGetValue(CSG.URIs.HasBottomRadius)\r
+ @GetPropertyValue(value=CSG.URIs.HasBottomRadius, name = "Bottom Radius")\r
+ public double getR1() {\r
+ return r1;\r
+ }\r
+ \r
+ @RelatedGetValue(CSG.URIs.HasTopRadius)\r
+ @GetPropertyValue(value=CSG.URIs.HasTopRadius, name = "Top Radius")\r
+ public double getR2() {\r
+ return r2;\r
+ }\r
+ \r
+ @Override\r
+ public TopoDS_Shape getBaseGeometry() {\r
+ if (Math.abs(r1-r2) > MIN_VALUE) {\r
+// if (r1 < MIN_VALUE)\r
+// return null;\r
+ return OccTriangulator.makeCone(new double[] { 0.0, -h * 0.5, 0.0 }, new double[] { 0.0, 1.0, 0.0 }, r1,r2, h);\r
+ } else\r
+ return OccTriangulator.makeCylinder(new double[] { 0.0, -h * 0.5, 0.0 }, new double[] { 0.0, 1.0, 0.0 }, r1, h);\r
+ }\r
+\r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.csg.scenegraph2;\r
+\r
+import org.jcae.opencascade.jni.TopoDS_Shape;\r
+import org.simantics.g3d.csg.ontology.CSG;\r
+import org.simantics.g3d.property.annotations.GetPropertyValue;\r
+import org.simantics.g3d.property.annotations.SetPropertyValue;\r
+import org.simantics.objmap.graph.annotations.GraphType;\r
+import org.simantics.objmap.graph.annotations.RelatedGetValue;\r
+import org.simantics.objmap.graph.annotations.RelatedSetValue;\r
+import org.simantics.opencascade.OccTriangulator;\r
+\r
+@GraphType(CSG.URIs.Cylinder)\r
+public class CylinderNode extends CSGnode {\r
+\r
+ private double r = 1.0;\r
+ private double h = 1.0;\r
+ \r
+ @RelatedSetValue(CSG.URIs.HasRadius)\r
+ @SetPropertyValue(CSG.URIs.HasRadius)\r
+ public void setR(double r) {\r
+ this.r = r;\r
+ firePropertyChanged(CSG.URIs.HasRadius);\r
+ }\r
+\r
+ @RelatedSetValue(CSG.URIs.HasHeight)\r
+ @SetPropertyValue(CSG.URIs.HasHeight)\r
+ public void setH(double h) {\r
+ this.h = h;\r
+ firePropertyChanged(CSG.URIs.HasHeight);\r
+ }\r
+ \r
+ @RelatedGetValue(CSG.URIs.HasHeight)\r
+ @GetPropertyValue(value=CSG.URIs.HasHeight, name = "Height")\r
+ public double getH() {\r
+ return h;\r
+ }\r
+ \r
+ @RelatedGetValue(CSG.URIs.HasRadius)\r
+ @GetPropertyValue(value=CSG.URIs.HasRadius, name = "Radius")\r
+ public double getR() {\r
+ return r;\r
+ }\r
+ \r
+ @Override\r
+ public TopoDS_Shape getBaseGeometry() {\r
+ return OccTriangulator.makeCylinder(new double[] { 0.0, -h * 0.5, 0.0 }, new double[] { 0.0, 1.0, 0.0 }, r, h);\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.csg.scenegraph2;\r
+\r
+import org.jcae.opencascade.jni.TopoDS_Shape;\r
+import org.simantics.g3d.csg.ontology.CSG;\r
+import org.simantics.objmap.graph.annotations.GraphType;\r
+import org.simantics.opencascade.OccTriangulator;\r
+\r
+@GraphType(CSG.URIs.Difference)\r
+public class DifferenceNode extends CSGparentNode {\r
+\r
+ @Override\r
+ public TopoDS_Shape getBaseGeometry() {\r
+ TopoDS_Shape prim = getPrimary();\r
+ TopoDS_Shape sec = getSecondary();\r
+ if (prim != null && sec != null) {\r
+ TopoDS_Shape res = OccTriangulator.makeCut(prim, sec);\r
+ prim.delete();\r
+ sec.delete();\r
+ return res;\r
+ }\r
+ if (prim != null)\r
+ prim.delete();\r
+ if (sec != null)\r
+ sec.delete();\r
+ return null;\r
+ }\r
+\r
+ \r
+}\r
--- /dev/null
+package org.simantics.g3d.csg.scenegraph2;\r
+\r
+import org.jcae.opencascade.jni.TopoDS_Shape;\r
+import org.simantics.g3d.csg.ontology.CSG;\r
+import org.simantics.g3d.property.annotations.GetPropertyValue;\r
+import org.simantics.g3d.property.annotations.SetPropertyValue;\r
+import org.simantics.objmap.graph.annotations.GraphType;\r
+import org.simantics.objmap.graph.annotations.RelatedGetValue;\r
+import org.simantics.objmap.graph.annotations.RelatedSetValue;\r
+import org.simantics.opencascade.OccTriangulator;\r
+\r
+@GraphType(CSG.URIs.EllipticCylinder)\r
+public class EllipticCylinderNode extends CSGnode {\r
+\r
+ private double r1 = 0.5;\r
+ private double r2 = 1.0;\r
+ private double h = 1.0;\r
+ \r
+ @RelatedSetValue(CSG.URIs.HasMinorRadius)\r
+ @SetPropertyValue(CSG.URIs.HasMinorRadius)\r
+ public void setR1(double r1) {\r
+ this.r1 = r1;\r
+ firePropertyChanged(CSG.URIs.HasMinorRadius);\r
+ }\r
+ \r
+ @RelatedSetValue(CSG.URIs.HasMajorRadius)\r
+ @SetPropertyValue(CSG.URIs.HasMajorRadius)\r
+ public void setR2(double r2) {\r
+ this.r2 = r2;\r
+ firePropertyChanged(CSG.URIs.HasMajorRadius);\r
+ }\r
+ \r
+ @RelatedSetValue(CSG.URIs.HasHeight)\r
+ @SetPropertyValue(CSG.URIs.HasHeight)\r
+ public void setH(double h) {\r
+ this.h = h;\r
+ firePropertyChanged(CSG.URIs.HasHeight);\r
+ }\r
+ \r
+ @RelatedGetValue(CSG.URIs.HasHeight)\r
+ @GetPropertyValue(value=CSG.URIs.HasHeight, name = "Height")\r
+ public double getH() {\r
+ return h;\r
+ }\r
+ \r
+ @RelatedGetValue(CSG.URIs.HasMinorRadius)\r
+ @GetPropertyValue(value=CSG.URIs.HasMinorRadius, name = "Minor Radius")\r
+ public double getR1() {\r
+ return r1;\r
+ }\r
+ \r
+ @RelatedGetValue(CSG.URIs.HasMajorRadius)\r
+ @GetPropertyValue(value=CSG.URIs.HasMajorRadius, name = "Major Radius")\r
+ public double getR2() {\r
+ return r2;\r
+ }\r
+ \r
+ @Override\r
+ public TopoDS_Shape getBaseGeometry() {\r
+ return OccTriangulator.makeEllipticCylinder(h, r1, r2);\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.csg.scenegraph2;\r
+\r
+import java.util.Collection;\r
+\r
+import org.jcae.opencascade.jni.TopoDS_Shape;\r
+import org.simantics.g3d.scenegraph.IG3DNode;\r
+\r
+import vtk.vtkPanel;\r
+import vtk.vtkProp3D;\r
+\r
+public interface ICSGnode extends IG3DNode {\r
+ \r
+ \r
+ public String getName();\r
+ public void setName(String name);\r
+ \r
+ public TopoDS_Shape getBaseGeometry();\r
+ \r
+ public TopoDS_Shape getGeometry();\r
+ \r
+ \r
+ public void visualize(vtkPanel panel);\r
+ public void stopVisualize();\r
+ \r
+ public Collection<vtkProp3D> getActors();\r
+ \r
+ public void deattach();\r
+}\r
--- /dev/null
+package org.simantics.g3d.csg.scenegraph2;\r
+\r
+import org.jcae.opencascade.jni.TopoDS_Shape;\r
+import org.simantics.g3d.csg.ontology.CSG;\r
+import org.simantics.objmap.graph.annotations.GraphType;\r
+import org.simantics.opencascade.OccTriangulator;\r
+\r
+@GraphType(CSG.URIs.Intersection)\r
+public class IntersectionNode extends CSGparentNode {\r
+\r
+ @Override\r
+ public TopoDS_Shape getBaseGeometry() {\r
+ TopoDS_Shape prim = getPrimary();\r
+ TopoDS_Shape sec = getSecondary();\r
+ if (prim != null && sec != null) {\r
+ TopoDS_Shape res =OccTriangulator.makeCommon(prim, sec);\r
+ prim.delete();\r
+ sec.delete();\r
+ return res;\r
+ }\r
+ if (prim != null)\r
+ prim.delete();\r
+ if (sec != null)\r
+ sec.delete();\r
+ return null;\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.csg.scenegraph2;\r
+\r
+import org.jcae.opencascade.jni.BRepBuilderAPI_MakeEdge;\r
+import org.jcae.opencascade.jni.BRepBuilderAPI_MakeWire;\r
+import org.jcae.opencascade.jni.BRepOffsetAPI_ThruSections;\r
+import org.jcae.opencascade.jni.TopoDS_Edge;\r
+import org.jcae.opencascade.jni.TopoDS_Shape;\r
+import org.jcae.opencascade.jni.TopoDS_Wire;\r
+import org.simantics.g3d.csg.ontology.CSG;\r
+import org.simantics.g3d.property.annotations.GetPropertyValue;\r
+import org.simantics.g3d.property.annotations.SetPropertyValue;\r
+import org.simantics.objmap.graph.annotations.GraphType;\r
+import org.simantics.objmap.graph.annotations.RelatedGetValue;\r
+import org.simantics.objmap.graph.annotations.RelatedSetValue;\r
+\r
+\r
+@GraphType(CSG.URIs.RectangularSolid)\r
+public class RectangularSolidNode extends CSGnode {\r
+\r
+ double x1 = 0.5;\r
+ double x2 = 1.0;\r
+ double y = 1.0;\r
+ double z1 = 0.5;\r
+ double z2 = 1.0;\r
+ \r
+ \r
+ @RelatedSetValue(CSG.URIs.HasXAxisMinimumSize)\r
+ @SetPropertyValue(CSG.URIs.HasXAxisMinimumSize)\r
+ public void setX1(double d) {\r
+ this.x1 = d;\r
+ firePropertyChanged(CSG.URIs.HasXAxisMinimumSize);\r
+ }\r
+ \r
+ @RelatedSetValue(CSG.URIs.HasXAxisMaximumSize)\r
+ @SetPropertyValue(CSG.URIs.HasXAxisMaximumSize)\r
+ public void setX2(double d) {\r
+ this.x2 = d;\r
+ firePropertyChanged(CSG.URIs.HasXAxisMaximumSize);\r
+ }\r
+ \r
+ @RelatedSetValue(CSG.URIs.HasYAxisSize)\r
+ @SetPropertyValue(CSG.URIs.HasYAxisSize)\r
+ public void setSY(double d) {\r
+ this.y = d;\r
+ firePropertyChanged(CSG.URIs.HasYAxisSize);\r
+ }\r
+ \r
+ @RelatedSetValue(CSG.URIs.HasZAxisMinimumSize)\r
+ @SetPropertyValue(CSG.URIs.HasZAxisMinimumSize)\r
+ public void setZ1(double d) {\r
+ this.z1 = d;\r
+ firePropertyChanged(CSG.URIs.HasZAxisMinimumSize);\r
+ }\r
+ \r
+ @RelatedSetValue(CSG.URIs.HasZAxisMaximumSize)\r
+ @SetPropertyValue(CSG.URIs.HasZAxisMaximumSize)\r
+ public void setZ2(double d) {\r
+ this.z2 = d;\r
+ firePropertyChanged(CSG.URIs.HasZAxisMaximumSize);\r
+ }\r
+ \r
+ @RelatedGetValue(CSG.URIs.HasXAxisMinimumSize)\r
+ @GetPropertyValue(value=CSG.URIs.HasXAxisMinimumSize, name = "X Min Size")\r
+ public double getX1() {\r
+ return x1;\r
+ }\r
+ \r
+ @RelatedGetValue(CSG.URIs.HasXAxisMaximumSize)\r
+ @GetPropertyValue(value=CSG.URIs.HasXAxisMaximumSize, name = "X Max Size")\r
+ public double getX2() {\r
+ return x2;\r
+ }\r
+ \r
+ @RelatedGetValue(CSG.URIs.HasYAxisSize)\r
+ @GetPropertyValue(value=CSG.URIs.HasYAxisSize, name = "Y Size")\r
+ public double getY() {\r
+ return y;\r
+ }\r
+ \r
+ @RelatedGetValue(CSG.URIs.HasZAxisMinimumSize)\r
+ @GetPropertyValue(value=CSG.URIs.HasZAxisMinimumSize, name = "Z Min Size")\r
+ public double getZ1() {\r
+ return z1;\r
+ }\r
+ \r
+ @RelatedGetValue(CSG.URIs.HasZAxisMaximumSize)\r
+ @GetPropertyValue(value=CSG.URIs.HasZAxisMaximumSize, name = "Z Max Size")\r
+ public double getZ2() {\r
+ return z2;\r
+ }\r
+ \r
+ @Override\r
+ public TopoDS_Shape getBaseGeometry() {\r
+ double x1 = this.x1 *0.5;\r
+ double x2 = this.x2 *0.5;\r
+ double z1 = this.z1 *0.5;\r
+ double z2 = this.z2 *0.5;\r
+ double y = this.y * 0.5;\r
+ \r
+ BRepBuilderAPI_MakeWire wire = new BRepBuilderAPI_MakeWire();\r
+ BRepBuilderAPI_MakeEdge edge = new BRepBuilderAPI_MakeEdge(new double[]{x1,-y,z1},new double[]{x1,-y,-z1});\r
+ TopoDS_Edge top_edge = (TopoDS_Edge)edge.shape();\r
+ wire.add(top_edge);\r
+ edge.delete();\r
+ top_edge.delete();\r
+ \r
+ edge = new BRepBuilderAPI_MakeEdge(new double[]{x1,-y,-z1},new double[]{-x1,-y,-z1});\r
+ top_edge = (TopoDS_Edge)edge.shape();\r
+ wire.add(top_edge);\r
+ edge.delete();\r
+ top_edge.delete();\r
+ \r
+ edge = new BRepBuilderAPI_MakeEdge(new double[]{-x1,-y,-z1},new double[]{-x1,-y,z1});\r
+ top_edge = (TopoDS_Edge)edge.shape();\r
+ wire.add(top_edge);\r
+ edge.delete();\r
+ top_edge.delete();\r
+ \r
+ edge = new BRepBuilderAPI_MakeEdge(new double[]{-x1,-y,z1},new double[]{x1,-y,z1});\r
+ top_edge = (TopoDS_Edge)edge.shape();\r
+ wire.add(top_edge);\r
+ edge.delete();\r
+ top_edge.delete();\r
+ \r
+ TopoDS_Wire w1 = (TopoDS_Wire)wire.shape();\r
+ wire.delete();\r
+ wire = new BRepBuilderAPI_MakeWire();\r
+ \r
+ \r
+ edge = new BRepBuilderAPI_MakeEdge(new double[]{x2, y,z2},new double[]{x2, y,-z2});\r
+ top_edge = (TopoDS_Edge)edge.shape();\r
+ wire.add(top_edge);\r
+ edge.delete();\r
+ top_edge.delete();\r
+ \r
+ edge = new BRepBuilderAPI_MakeEdge(new double[]{x2, y,-z2},new double[]{-x2, y,-z2});\r
+ top_edge = (TopoDS_Edge)edge.shape();\r
+ wire.add(top_edge);\r
+ edge.delete();\r
+ top_edge.delete();\r
+ \r
+ edge = new BRepBuilderAPI_MakeEdge(new double[]{-x2, y,-z2},new double[]{-x2, y,z2});\r
+ top_edge = (TopoDS_Edge)edge.shape();\r
+ wire.add(top_edge);\r
+ edge.delete();\r
+ top_edge.delete();\r
+ \r
+ edge = new BRepBuilderAPI_MakeEdge(new double[]{-x2, y,z2},new double[]{x2, y,z2});\r
+ top_edge = (TopoDS_Edge)edge.shape();\r
+ wire.add(top_edge);\r
+ edge.delete();\r
+ top_edge.delete();\r
+ \r
+ TopoDS_Wire w2 = (TopoDS_Wire)wire.shape();\r
+ wire.delete();\r
+ \r
+ BRepOffsetAPI_ThruSections generatorb = new BRepOffsetAPI_ThruSections(true, true);\r
+ generatorb.addWire(w1);\r
+ generatorb.addWire(w2);\r
+ generatorb.build();\r
+ w1.delete();\r
+ w2.delete();\r
+ \r
+ TopoDS_Shape shape = generatorb.shape();\r
+ generatorb.delete();\r
+ \r
+ return shape;\r
+ }\r
+\r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.csg.scenegraph2;\r
+\r
+import org.jcae.opencascade.jni.TopoDS_Shape;\r
+import org.simantics.g3d.csg.ontology.CSG;\r
+import org.simantics.g3d.property.annotations.GetPropertyValue;\r
+import org.simantics.g3d.property.annotations.SetPropertyValue;\r
+import org.simantics.objmap.graph.annotations.GraphType;\r
+import org.simantics.objmap.graph.annotations.RelatedGetValue;\r
+import org.simantics.objmap.graph.annotations.RelatedSetValue;\r
+import org.simantics.opencascade.OccTriangulator;\r
+\r
+@GraphType(CSG.URIs.RegularPrism)\r
+public class RegularPrismNode extends CSGnode {\r
+\r
+ private double r = 1.0;\r
+ private double h = 1.0;\r
+ private int n = 3;\r
+ \r
+ @RelatedSetValue(CSG.URIs.HasRadius)\r
+ @SetPropertyValue(CSG.URIs.HasRadius)\r
+ public void setR(double r) {\r
+ this.r = r;\r
+ firePropertyChanged(CSG.URIs.HasRadius);\r
+ }\r
+\r
+ \r
+ @RelatedSetValue(CSG.URIs.HasHeight)\r
+ @SetPropertyValue(CSG.URIs.HasHeight)\r
+ public void setH(double h) {\r
+ this.h = h;\r
+ firePropertyChanged(CSG.URIs.HasHeight);\r
+ }\r
+ \r
+ @RelatedSetValue(CSG.URIs.HasCorners)\r
+ @SetPropertyValue(CSG.URIs.HasCorners)\r
+ public void setN(int n) {\r
+ if (n < 3)\r
+ n = 3;\r
+ this.n = n;\r
+ firePropertyChanged(CSG.URIs.HasCorners);\r
+ }\r
+ \r
+ @RelatedGetValue(CSG.URIs.HasHeight)\r
+ @GetPropertyValue(value=CSG.URIs.HasHeight, name="Height")\r
+ public double getH() {\r
+ return h;\r
+ }\r
+ \r
+ @RelatedGetValue(CSG.URIs.HasCorners)\r
+ @GetPropertyValue(value=CSG.URIs.HasCorners, name="Corners")\r
+ public int getN() {\r
+ return n;\r
+ }\r
+ \r
+ @RelatedGetValue(CSG.URIs.HasRadius)\r
+ @GetPropertyValue(value=CSG.URIs.HasRadius, name="Radius")\r
+ public double getR() {\r
+ return r;\r
+ }\r
+ \r
+ @Override\r
+ public TopoDS_Shape getBaseGeometry() {\r
+ return OccTriangulator.makeReqularPrism(h, r, n);\r
+ }\r
+\r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.csg.scenegraph2;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.request.Read;\r
+import org.simantics.objmap.graph.schema.IMappingSchema;\r
+import org.simantics.objmap.graph.schema.MappingSchemas;\r
+import org.simantics.objmap.graph.schema.SimpleSchema;\r
+import org.simantics.ui.SimanticsUI;\r
+\r
+public class SchemaBuilder {\r
+ \r
+ public static IMappingSchema<Resource,Object> getSchema() throws DatabaseException{\r
+ return SimanticsUI.getSession().syncRequest(new Read<IMappingSchema<Resource,Object>>() {\r
+ @Override\r
+ public IMappingSchema<Resource,Object> perform(ReadGraph g)\r
+ throws DatabaseException {\r
+ return getSchema(g);\r
+ }\r
+ });\r
+ }\r
+ \r
+ public static IMappingSchema<Resource,Object> getSchema(ReadGraph g) throws DatabaseException{\r
+ try {\r
+ SimpleSchema schema = new SimpleSchema();\r
+ schema.addLinkType(MappingSchemas.fromAnnotations(g, BarrelNode.class));\r
+ schema.addLinkType(MappingSchemas.fromAnnotations(g, BoxNode.class));\r
+ schema.addLinkType(MappingSchemas.fromAnnotations(g, ConeNode.class));\r
+ schema.addLinkType(MappingSchemas.fromAnnotations(g, CylinderNode.class));\r
+ schema.addLinkType(MappingSchemas.fromAnnotations(g, DifferenceNode.class));\r
+ schema.addLinkType(MappingSchemas.fromAnnotations(g, EllipticCylinderNode.class));\r
+ schema.addLinkType(MappingSchemas.fromAnnotations(g, IntersectionNode.class));\r
+ schema.addLinkType(MappingSchemas.fromAnnotations(g, RectangularSolidNode.class));\r
+ schema.addLinkType(MappingSchemas.fromAnnotations(g, RegularPrismNode.class));\r
+ schema.addLinkType(MappingSchemas.fromAnnotations(g, SphereNode.class));\r
+ schema.addLinkType(MappingSchemas.fromAnnotations(g, TorusNode.class));\r
+ schema.addLinkType(MappingSchemas.fromAnnotations(g, UnionNode.class));\r
+ schema.addLinkType(MappingSchemas.fromAnnotations(g, CSGrootNode.class));\r
+ return schema;\r
+ } catch (IllegalAccessException e) {\r
+ throw new DatabaseException(e);\r
+ } catch (InstantiationException e) {\r
+ throw new DatabaseException(e);\r
+ }\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.csg.scenegraph2;\r
+\r
+import org.jcae.opencascade.jni.TopoDS_Shape;\r
+import org.simantics.g3d.csg.ontology.CSG;\r
+import org.simantics.g3d.property.annotations.GetPropertyValue;\r
+import org.simantics.g3d.property.annotations.SetPropertyValue;\r
+import org.simantics.objmap.graph.annotations.GraphType;\r
+import org.simantics.objmap.graph.annotations.RelatedGetValue;\r
+import org.simantics.objmap.graph.annotations.RelatedSetValue;\r
+import org.simantics.opencascade.OccTriangulator;\r
+\r
+@GraphType(CSG.URIs.Sphere)\r
+public class SphereNode extends CSGnode {\r
+\r
+ private double r = 1.0;\r
+ \r
+ @RelatedSetValue(CSG.URIs.HasRadius)\r
+ @SetPropertyValue(CSG.URIs.HasRadius)\r
+ public void setR(double r) {\r
+ this.r = r;\r
+ firePropertyChanged(CSG.URIs.HasRadius);\r
+ }\r
+ \r
+ @RelatedGetValue(CSG.URIs.HasRadius)\r
+ @GetPropertyValue(value=CSG.URIs.HasRadius, name="Radius")\r
+ public double getR() {\r
+ return r;\r
+ }\r
+ \r
+ @Override\r
+ public TopoDS_Shape getBaseGeometry() {\r
+ return OccTriangulator.makeSphere(0, 0, 0, r);\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.csg.scenegraph2;\r
+\r
+import org.jcae.opencascade.jni.TopoDS_Shape;\r
+import org.simantics.g3d.csg.ontology.CSG;\r
+import org.simantics.g3d.property.annotations.GetPropertyValue;\r
+import org.simantics.g3d.property.annotations.SetPropertyValue;\r
+import org.simantics.objmap.graph.annotations.GraphType;\r
+import org.simantics.objmap.graph.annotations.RelatedGetValue;\r
+import org.simantics.objmap.graph.annotations.RelatedSetValue;\r
+import org.simantics.opencascade.OccTriangulator;\r
+\r
+@GraphType(CSG.URIs.Torus)\r
+public class TorusNode extends CSGnode {\r
+\r
+ private double r1 = 1.0;\r
+ private double r2 = 1.0;\r
+ \r
+ \r
+ @RelatedSetValue(CSG.URIs.HasMinorRadius)\r
+ @SetPropertyValue(CSG.URIs.HasMinorRadius)\r
+ public void setR1(double r1) {\r
+ this.r1 = r1;\r
+ firePropertyChanged(CSG.URIs.HasMinorRadius);\r
+ }\r
+ \r
+ @RelatedSetValue(CSG.URIs.HasMajorRadius)\r
+ @SetPropertyValue(CSG.URIs.HasMajorRadius)\r
+ public void setR2(double r2) {\r
+ this.r2 = r2;\r
+ firePropertyChanged(CSG.URIs.HasMajorRadius);\r
+ }\r
+ \r
+ @RelatedGetValue(CSG.URIs.HasMinorRadius)\r
+ @GetPropertyValue(value=CSG.URIs.HasMinorRadius, name="Minor Radius")\r
+ public double getR1() {\r
+ return r1;\r
+ }\r
+ \r
+ @RelatedGetValue(CSG.URIs.HasMajorRadius)\r
+ @GetPropertyValue(value=CSG.URIs.HasMajorRadius, name="Major Radius") \r
+ public double getR2() {\r
+ return r2;\r
+ }\r
+ \r
+ @Override\r
+ public TopoDS_Shape getBaseGeometry() {\r
+ return OccTriangulator.makeTorus(new double[] { 0.0, 0.0, 0.0 }, new double[] { 0.0, 1.0, 0.0 }, r2, r1);\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.csg.scenegraph2;\r
+\r
+import org.jcae.opencascade.jni.TopoDS_Shape;\r
+import org.simantics.g3d.csg.ontology.CSG;\r
+\r
+import org.simantics.objmap.graph.annotations.GraphType;\r
+import org.simantics.opencascade.OccTriangulator;\r
+\r
+@GraphType(CSG.URIs.Union)\r
+public class UnionNode extends CSGparentNode {\r
+\r
+ @Override\r
+ public TopoDS_Shape getBaseGeometry() {\r
+ TopoDS_Shape prim = getPrimary();\r
+ TopoDS_Shape sec = getSecondary();\r
+ if (prim != null && sec != null) {\r
+ TopoDS_Shape res =OccTriangulator.makeFuse(prim, sec);\r
+ prim.delete();\r
+ sec.delete();\r
+ return res;\r
+ }\r
+ if (prim != null)\r
+ prim.delete();\r
+ if (sec != null)\r
+ sec.delete();\r
+ return null;\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.csg.wizard;\r
+\r
+import java.util.Deque;\r
+\r
+import org.eclipse.core.runtime.preferences.InstanceScope;\r
+import org.eclipse.jface.operation.IRunnableWithProgress;\r
+import org.eclipse.jface.preference.IPersistentPreferenceStore;\r
+import org.eclipse.ui.preferences.ScopedPreferenceStore;\r
+import org.simantics.g3d.csg.Activator;\r
+import org.simantics.g3d.wizard.ModelExportWizard;\r
+import org.simantics.g3d.wizard.ModelExportWizardPage;\r
+\r
+public class CSGBRepExportWizard extends ModelExportWizard<CSGExportModel> {\r
+\r
+ public static final String RECENT_CSG_EXPORT_LOCATIONS = "RECENT_CSG_EXPORT_LOCATIONS";\r
+ public static final String CSG_EXPORT_OVERWRITE = "CSG_EXPORT_OVERWRITE";\r
+ \r
+ public CSGBRepExportWizard() {\r
+ setWindowTitle("Export CSG Model to Brep");\r
+ setNeedsProgressMonitor(true);\r
+ }\r
+ \r
+ @Override\r
+ protected CSGExportModel createExportModel(Deque<String> recentExportPaths) {\r
+ return new CSGExportModel(recentExportPaths);\r
+ }\r
+ \r
+ @Override\r
+ protected ModelExportWizardPage<CSGExportModel> createExportPage(CSGExportModel exportModel) {\r
+ return new CSGExportPage(exportModel);\r
+ }\r
+ \r
+ @Override\r
+ protected IRunnableWithProgress createExportRunnable(CSGExportModel exportModel) {\r
+ return new CSGBrepModelExporter(exportModel);\r
+ }\r
+ \r
+ @Override\r
+ protected String getExportLocationId() {\r
+ return RECENT_CSG_EXPORT_LOCATIONS;\r
+ }\r
+ \r
+ @Override\r
+ protected String getExportOverwriteId() {\r
+ return CSG_EXPORT_OVERWRITE;\r
+ }\r
+ \r
+\r
+ @Override\r
+ protected IPersistentPreferenceStore getPreferenceStore() {\r
+ return new ScopedPreferenceStore(InstanceScope.INSTANCE, Activator.PLUGIN_ID);\r
+ }\r
+ \r
+\r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.csg.wizard;\r
+\r
+import java.io.IOException;\r
+import java.lang.reflect.InvocationTargetException;\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import org.eclipse.core.runtime.IProgressMonitor;\r
+import org.eclipse.core.runtime.SubMonitor;\r
+import org.eclipse.jface.operation.IRunnableWithProgress;\r
+import org.jcae.opencascade.jni.TopoDS_Shape;\r
+import org.simantics.Simantics;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.request.Read;\r
+import org.simantics.g3d.csg.scenegraph2.CSGrootNode;\r
+import org.simantics.g3d.csg.scenegraph2.ICSGnode;\r
+import org.simantics.g3d.csg.scenegraph2.SchemaBuilder;\r
+import org.simantics.objmap.graph.IMapping;\r
+import org.simantics.objmap.graph.Mappings;\r
+import org.simantics.objmap.graph.schema.IMappingSchema;\r
+import org.simantics.opencascade.OccTriangulator;\r
+\r
+public class CSGBrepModelExporter implements IRunnableWithProgress {\r
+\r
+ CSGExportModel exportModel;\r
+ public CSGBrepModelExporter(CSGExportModel exportModel) {\r
+ this.exportModel = exportModel;\r
+ }\r
+ \r
+ @Override\r
+ public void run(IProgressMonitor monitor) throws InvocationTargetException,\r
+ InterruptedException {\r
+ SubMonitor progress = SubMonitor.convert(monitor, 50);\r
+ SubMonitor mon = progress.newChild(50, SubMonitor.SUPPRESS_NONE);\r
+ try {\r
+ exportModel(mon);\r
+ } catch (IOException e) {\r
+ mon.setCanceled(true);\r
+ throw new InvocationTargetException(e);\r
+ } catch (DatabaseException e) {\r
+ mon.setCanceled(true);\r
+ throw new InvocationTargetException(e);\r
+ } finally {\r
+ monitor.done();\r
+ }\r
+ \r
+ }\r
+\r
+ void exportModel(SubMonitor mon) throws IOException, DatabaseException {\r
+ int taskSize = 50;\r
+ mon.beginTask("Exporting model...", taskSize);\r
+ mon.setTaskName("Initializing CSG model...");\r
+ \r
+ CSGrootNode rootNode = Simantics.getSessionContext().getSession().syncRequest(new Read<CSGrootNode>() {\r
+ @Override\r
+ public CSGrootNode perform(ReadGraph graph)\r
+ throws DatabaseException {\r
+ IMappingSchema<Resource, Object> schema = SchemaBuilder.getSchema(graph);\r
+ IMapping<Resource, Object> mapping = Mappings.createWithoutListening(schema);\r
+ CSGrootNode rootNode = (CSGrootNode) mapping.map(graph,exportModel.getModel().getResource());\r
+ mapping.dispose();\r
+ return rootNode;\r
+ }\r
+ });\r
+ mon.worked(40);\r
+ \r
+ mon.setTaskName("Creating solid geometry...");\r
+ List<TopoDS_Shape> shapes = new ArrayList<TopoDS_Shape>();\r
+ for (ICSGnode node : rootNode.getChild()) {\r
+ TopoDS_Shape shape = node.getGeometry();\r
+ if (shape != null)\r
+ shapes.add(shape);\r
+ }\r
+ if (shapes.size() == 0) {\r
+ mon.setTaskName("Nothing to export.");\r
+ mon.setCanceled(true);\r
+ return;\r
+ }\r
+ TopoDS_Shape compound = null;\r
+ if (shapes.size() > 1) {\r
+ OccTriangulator.makeCompound(shapes.toArray(new TopoDS_Shape[shapes.size()]));\r
+ for (TopoDS_Shape shape : shapes)\r
+ shape.delete();\r
+ } else {\r
+ compound = shapes.get(0);\r
+ }\r
+ \r
+ mon.worked(50);\r
+ \r
+ mon.setTaskName("Writing file...");\r
+ OccTriangulator.exportBREP(compound, exportModel.getExportLocation().getAbsolutePath());\r
+ compound.delete();\r
+ \r
+ mon.setWorkRemaining(0);\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.g3d.csg.wizard;\r
+\r
+import java.util.Deque;\r
+\r
+import org.simantics.g3d.wizard.IExportModel;\r
+\r
+public class CSGExportModel extends IExportModel{\r
+\r
+ \r
+ \r
+ public CSGExportModel(Deque<String> recentLocations) {\r
+ super();\r
+ setRecentLocations(recentLocations);\r
+ }\r
+ \r
+ @Override\r
+ public boolean usesFile() {\r
+ return true;\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.csg.wizard;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.common.NamedResource;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.g3d.csg.ontology.CSG;\r
+import org.simantics.g3d.wizard.ModelExportWizardPage;\r
+import org.simantics.layer0.Layer0;\r
+\r
+public class CSGExportPage extends ModelExportWizardPage<CSGExportModel> {\r
+ \r
+\r
+ \r
+ public CSGExportPage(CSGExportModel model) {\r
+ super("Export CSG Model","Define Export Location",null,model);\r
+ }\r
+ \r
+ @Override\r
+ public String[] getFilterExtensions() {\r
+ return new String[]{"*.brep"};\r
+ }\r
+ \r
+ @Override\r
+ public String[] getFilterNames() {\r
+ return new String[]{"OpenCASCADE Brep file"};\r
+ }\r
+ \r
+ \r
+ @Override\r
+ protected List<NamedResource> getSupportedModels(ReadGraph graph, Resource project) throws DatabaseException {\r
+ List<NamedResource> models = new ArrayList<NamedResource>();\r
+ Layer0 L0 = Layer0.getInstance(graph);\r
+ CSG csg = CSG.getInstance(graph);\r
+ \r
+ for (Resource r : graph.getObjects(project, L0.ConsistsOf)) {\r
+ if (graph.isInstanceOf(r, csg.Model)) {\r
+ models.add(new NamedResource((String)graph.getRelatedValue(r, L0.HasName), r));\r
+ }\r
+ }\r
+ return models;\r
+ }\r
+ \r
+\r
+ \r
+\r
+\r
+}\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<classpath>\r
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>\r
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>\r
+ <classpathentry kind="src" path="src"/>\r
+ <classpathentry kind="output" path="bin"/>\r
+</classpath>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<projectDescription>\r
+ <name>org.simantics.g3d.ontology</name>\r
+ <comment></comment>\r
+ <projects>\r
+ </projects>\r
+ <buildSpec>\r
+ <buildCommand>\r
+ <name>org.simantics.graph.builder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ <buildCommand>\r
+ <name>org.eclipse.jdt.core.javabuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ <buildCommand>\r
+ <name>org.eclipse.pde.ManifestBuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ <buildCommand>\r
+ <name>org.eclipse.pde.SchemaBuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ </buildSpec>\r
+ <natures>\r
+ <nature>org.eclipse.pde.PluginNature</nature>\r
+ <nature>org.eclipse.jdt.core.javanature</nature>\r
+ <nature>org.simantics.graph.nature</nature>\r
+ </natures>\r
+</projectDescription>\r
--- /dev/null
+#Mon Dec 12 12:36:09 EET 2011\r
+eclipse.preferences.version=1\r
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled\r
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6\r
+org.eclipse.jdt.core.compiler.compliance=1.6\r
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error\r
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error\r
+org.eclipse.jdt.core.compiler.source=1.6\r
--- /dev/null
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: G3D Ontology
+Bundle-SymbolicName: org.simantics.g3d.ontology
+Bundle-Version: 1.0.0.qualifier
+Bundle-Vendor: VTT
+Require-Bundle: org.eclipse.core.runtime,
+ org.simantics.layer0;bundle-version="1.0.0"
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Export-Package: org.simantics.g3d.ontology
--- /dev/null
+source.. = src/\r
+output.. = bin/\r
+bin.includes = META-INF/,\\r
+ .,\\r
+ graph.tg\r
--- /dev/null
+L0 = <http://www.simantics.org/Layer0-1.1>\r
+\r
+G3D = <http://www.simantics.org/G3D-0.1> : L0.Ontology\r
+ @L0.new\r
+ L0.HasResourceClass "org.simantics.g3d.ontology.G3D"\r
+\r
+\r
+G3D.Tuple3D <T L0.Literal\r
+ @L0.assert L0.HasDataType $(Double[3])\r
+ \r
+G3D.Tuple4D <T L0.Literal\r
+ @L0.assert L0.HasDataType $(Double[4])\r
+\r
+\r
+G3D.Position <T G3D.Tuple3D\r
+\r
+G3D.Orientation <T G3D.Tuple4D\r
+\r
+G3D.hasNodeProperty <R L0.HasProperty\r
+\r
+G3D.hasNonTransformation <R G3D.hasNodeProperty\r
+G3D.hasTransformation <R G3D.hasNodeProperty\r
+\r
+\r
+G3D.hasOrientation <R G3D.hasTransformation\r
+ --> G3D.Orientation\r
+ \r
+G3D.hasPosition <R G3D.hasTransformation\r
+ --> G3D.Position\r
+ \r
+G3D.hasWorldOrientation <R G3D.hasTransformation\r
+ --> G3D.Orientation\r
+ @L0.tag L0.Abstract\r
+ \r
+G3D.hasWorldPosition <R G3D.hasTransformation\r
+ --> G3D.Position\r
+ @L0.tag L0.Abstract\r
+\r
+G3D.nodes <R L0.IsComposedOf\r
+ @L0.tag L0.Abstract\r
+ L0.InverseOf G3D.parentNode <R L0.IsWeaklyRelatedTo\r
+ L0.HasDomain G3D.BaseNode\r
+ L0.HasRange G3D.BaseNode\r
+ \r
+G3D.geometryDefinition <R G3D.nodes\r
+ L0.InverseOf G3D.geometryDefinitionOf\r
+\r
+G3D.children <R G3D.nodes\r
+ L0.InverseOf G3D.parent\r
+\r
+G3D.BaseNode <T L0.Entity\r
+ @L0.tag L0.Abstract\r
+ @L0.singleProperty G3D.hasPosition\r
+ @L0.singleProperty G3D.hasOrientation\r
+\r
+G3D.RootNode <T G3D.BaseNode\r
+\r
+G3D.Node <T G3D.BaseNode\r
+\r
+\r
+// Structural modelling\r
+\r
+G3D.publishes <R L0.DomainOf
\ No newline at end of file
--- /dev/null
+package org.simantics.g3d.ontology;\r
+\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.request.Read;\r
+import org.simantics.db.Session;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.service.QueryControl;\r
+\r
+public class G3D {\r
+ \r
+ public final Resource BaseNode;\r
+ public final Resource Node;\r
+ public final Resource Orientation;\r
+ public final Resource Position;\r
+ public final Resource RootNode;\r
+ public final Resource Tuple3D;\r
+ public final Resource Tuple4D;\r
+ public final Resource children;\r
+ public final Resource geometryDefinition;\r
+ public final Resource geometryDefinitionOf;\r
+ public final Resource hasNodeProperty;\r
+ public final Resource hasNodeProperty_Inverse;\r
+ public final Resource hasNonTransformation;\r
+ public final Resource hasNonTransformation_Inverse;\r
+ public final Resource hasOrientation;\r
+ public final Resource hasOrientation_Inverse;\r
+ public final Resource hasPosition;\r
+ public final Resource hasPosition_Inverse;\r
+ public final Resource hasTransformation;\r
+ public final Resource hasTransformation_Inverse;\r
+ public final Resource hasWorldOrientation;\r
+ public final Resource hasWorldOrientation_Inverse;\r
+ public final Resource hasWorldPosition;\r
+ public final Resource hasWorldPosition_Inverse;\r
+ public final Resource nodes;\r
+ public final Resource parent;\r
+ public final Resource parentNode;\r
+ public final Resource publishes;\r
+ public final Resource publishes_Inverse;\r
+ \r
+ public static class URIs {\r
+ public static final String BaseNode = "http://www.simantics.org/G3D-0.1/BaseNode";\r
+ public static final String Node = "http://www.simantics.org/G3D-0.1/Node";\r
+ public static final String Orientation = "http://www.simantics.org/G3D-0.1/Orientation";\r
+ public static final String Position = "http://www.simantics.org/G3D-0.1/Position";\r
+ public static final String RootNode = "http://www.simantics.org/G3D-0.1/RootNode";\r
+ public static final String Tuple3D = "http://www.simantics.org/G3D-0.1/Tuple3D";\r
+ public static final String Tuple4D = "http://www.simantics.org/G3D-0.1/Tuple4D";\r
+ public static final String children = "http://www.simantics.org/G3D-0.1/children";\r
+ public static final String geometryDefinition = "http://www.simantics.org/G3D-0.1/geometryDefinition";\r
+ public static final String geometryDefinitionOf = "http://www.simantics.org/G3D-0.1/geometryDefinitionOf";\r
+ public static final String hasNodeProperty = "http://www.simantics.org/G3D-0.1/hasNodeProperty";\r
+ public static final String hasNodeProperty_Inverse = "http://www.simantics.org/G3D-0.1/hasNodeProperty/Inverse";\r
+ public static final String hasNonTransformation = "http://www.simantics.org/G3D-0.1/hasNonTransformation";\r
+ public static final String hasNonTransformation_Inverse = "http://www.simantics.org/G3D-0.1/hasNonTransformation/Inverse";\r
+ public static final String hasOrientation = "http://www.simantics.org/G3D-0.1/hasOrientation";\r
+ public static final String hasOrientation_Inverse = "http://www.simantics.org/G3D-0.1/hasOrientation/Inverse";\r
+ public static final String hasPosition = "http://www.simantics.org/G3D-0.1/hasPosition";\r
+ public static final String hasPosition_Inverse = "http://www.simantics.org/G3D-0.1/hasPosition/Inverse";\r
+ public static final String hasTransformation = "http://www.simantics.org/G3D-0.1/hasTransformation";\r
+ public static final String hasTransformation_Inverse = "http://www.simantics.org/G3D-0.1/hasTransformation/Inverse";\r
+ public static final String hasWorldOrientation = "http://www.simantics.org/G3D-0.1/hasWorldOrientation";\r
+ public static final String hasWorldOrientation_Inverse = "http://www.simantics.org/G3D-0.1/hasWorldOrientation/Inverse";\r
+ public static final String hasWorldPosition = "http://www.simantics.org/G3D-0.1/hasWorldPosition";\r
+ public static final String hasWorldPosition_Inverse = "http://www.simantics.org/G3D-0.1/hasWorldPosition/Inverse";\r
+ public static final String nodes = "http://www.simantics.org/G3D-0.1/nodes";\r
+ public static final String parent = "http://www.simantics.org/G3D-0.1/parent";\r
+ public static final String parentNode = "http://www.simantics.org/G3D-0.1/parentNode";\r
+ public static final String publishes = "http://www.simantics.org/G3D-0.1/publishes";\r
+ public static final String publishes_Inverse = "http://www.simantics.org/G3D-0.1/publishes/Inverse";\r
+ }\r
+ \r
+ public static Resource getResourceOrNull(ReadGraph graph, String uri) {\r
+ try {\r
+ return graph.getResource(uri);\r
+ } catch(DatabaseException e) {\r
+ System.err.println(e.getMessage());\r
+ return null;\r
+ }\r
+ }\r
+ \r
+ public G3D(ReadGraph graph) {\r
+ BaseNode = getResourceOrNull(graph, URIs.BaseNode);\r
+ Node = getResourceOrNull(graph, URIs.Node);\r
+ Orientation = getResourceOrNull(graph, URIs.Orientation);\r
+ Position = getResourceOrNull(graph, URIs.Position);\r
+ RootNode = getResourceOrNull(graph, URIs.RootNode);\r
+ Tuple3D = getResourceOrNull(graph, URIs.Tuple3D);\r
+ Tuple4D = getResourceOrNull(graph, URIs.Tuple4D);\r
+ children = getResourceOrNull(graph, URIs.children);\r
+ geometryDefinition = getResourceOrNull(graph, URIs.geometryDefinition);\r
+ geometryDefinitionOf = getResourceOrNull(graph, URIs.geometryDefinitionOf);\r
+ hasNodeProperty = getResourceOrNull(graph, URIs.hasNodeProperty);\r
+ hasNodeProperty_Inverse = getResourceOrNull(graph, URIs.hasNodeProperty_Inverse);\r
+ hasNonTransformation = getResourceOrNull(graph, URIs.hasNonTransformation);\r
+ hasNonTransformation_Inverse = getResourceOrNull(graph, URIs.hasNonTransformation_Inverse);\r
+ hasOrientation = getResourceOrNull(graph, URIs.hasOrientation);\r
+ hasOrientation_Inverse = getResourceOrNull(graph, URIs.hasOrientation_Inverse);\r
+ hasPosition = getResourceOrNull(graph, URIs.hasPosition);\r
+ hasPosition_Inverse = getResourceOrNull(graph, URIs.hasPosition_Inverse);\r
+ hasTransformation = getResourceOrNull(graph, URIs.hasTransformation);\r
+ hasTransformation_Inverse = getResourceOrNull(graph, URIs.hasTransformation_Inverse);\r
+ hasWorldOrientation = getResourceOrNull(graph, URIs.hasWorldOrientation);\r
+ hasWorldOrientation_Inverse = getResourceOrNull(graph, URIs.hasWorldOrientation_Inverse);\r
+ hasWorldPosition = getResourceOrNull(graph, URIs.hasWorldPosition);\r
+ hasWorldPosition_Inverse = getResourceOrNull(graph, URIs.hasWorldPosition_Inverse);\r
+ nodes = getResourceOrNull(graph, URIs.nodes);\r
+ parent = getResourceOrNull(graph, URIs.parent);\r
+ parentNode = getResourceOrNull(graph, URIs.parentNode);\r
+ publishes = getResourceOrNull(graph, URIs.publishes);\r
+ publishes_Inverse = getResourceOrNull(graph, URIs.publishes_Inverse);\r
+ }\r
+ \r
+ public static G3D getInstance(ReadGraph graph) {\r
+ Session session = graph.getSession();\r
+ G3D ret = session.peekService(G3D.class);\r
+ if(ret == null) {\r
+ QueryControl qc = graph.getService(QueryControl.class);\r
+ ret = new G3D(qc.getIndependentGraph(graph));\r
+ session.registerService(G3D.class, ret);\r
+ }\r
+ return ret;\r
+ }\r
+ \r
+ public static G3D getInstance(Session session) throws DatabaseException {\r
+ G3D ret = session.peekService(G3D.class);\r
+ if(ret == null) {\r
+ ret = session.syncRequest(new Read<G3D>() {\r
+ public G3D perform(ReadGraph graph) throws DatabaseException {\r
+ QueryControl qc = graph.getService(QueryControl.class);\r
+ return new G3D(qc.getIndependentGraph(graph));\r
+ }\r
+ });\r
+ session.registerService(G3D.class, ret);\r
+ }\r
+ return ret;\r
+ }\r
+ \r
+}\r
+\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<classpath>\r
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>\r
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>\r
+ <classpathentry kind="src" path="src"/>\r
+ <classpathentry kind="output" path="bin"/>\r
+</classpath>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<projectDescription>\r
+ <name>org.simantics.g3d.vtk</name>\r
+ <comment></comment>\r
+ <projects>\r
+ </projects>\r
+ <buildSpec>\r
+ <buildCommand>\r
+ <name>org.eclipse.jdt.core.javabuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ <buildCommand>\r
+ <name>org.eclipse.pde.ManifestBuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ <buildCommand>\r
+ <name>org.eclipse.pde.SchemaBuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ </buildSpec>\r
+ <natures>\r
+ <nature>org.eclipse.pde.PluginNature</nature>\r
+ <nature>org.eclipse.jdt.core.javanature</nature>\r
+ </natures>\r
+</projectDescription>\r
--- /dev/null
+#Thu Mar 29 15:34:08 EEST 2012\r
+eclipse.preferences.version=1\r
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled\r
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6\r
+org.eclipse.jdt.core.compiler.compliance=1.6\r
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error\r
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error\r
+org.eclipse.jdt.core.compiler.source=1.6\r
--- /dev/null
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: G3D Vtk integration
+Bundle-SymbolicName: org.simantics.g3d.vtk;singleton:=true
+Bundle-Version: 1.0.0.qualifier
+Bundle-Activator: org.simantics.g3d.vtk.Activator
+Bundle-Vendor: VTT
+Require-Bundle: org.eclipse.core.runtime,
+ javax.vecmath;bundle-version="1.5.2",
+ org.simantics.g3d;bundle-version="1.0.0",
+ org.eclipse.ui;bundle-version="3.6.2",
+ org.simantics.db;bundle-version="1.1.0",
+ org.simantics.selectionview;bundle-version="1.0.0",
+ org.simantics.db.management;bundle-version="1.1.0",
+ org.eclipse.ui.views;bundle-version="3.5.1",
+ org.simantics.objmap2;bundle-version="1.0.0",
+ org.simantics.db.common;bundle-version="1.1.0",
+ org.simantics.g3d.ontology;bundle-version="1.0.0",
+ vtk;bundle-version="5.10.0",
+ org.simantics.utils.ui;bundle-version="1.1.0"
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Bundle-ActivationPolicy: lazy
+Export-Package: org.simantics.g3d.vtk.action,
+ org.simantics.g3d.vtk.common,
+ org.simantics.g3d.vtk.gizmo,
+ org.simantics.g3d.vtk.handlers,
+ org.simantics.g3d.vtk.property,
+ org.simantics.g3d.vtk.shape,
+ org.simantics.g3d.vtk.utils
--- /dev/null
+source.. = src/\r
+output.. = bin/\r
+bin.includes = META-INF/,\\r
+ .,\\r
+ plugin.xml\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<?eclipse version="3.4"?>\r
+<plugin>\r
+ <extension\r
+ point="org.eclipse.ui.preferencePages">\r
+ <page\r
+ class="org.simantics.g3d.vtk.preferences.VTKPreferencePage"\r
+ id="org.simantics.g3d.vtk.preferences.VTKPreferencePage"\r
+ name="VTK Preferences">\r
+ </page>\r
+ </extension>\r
+ <extension\r
+ point="org.eclipse.core.runtime.preferences">\r
+ <initializer\r
+ class="org.simantics.g3d.vtk.preferences.PreferenceInitializer">\r
+ </initializer>\r
+ </extension>\r
+ <extension\r
+ point="org.eclipse.ui.commands">\r
+ </extension>\r
+\r
+</plugin>\r
--- /dev/null
+package org.simantics.g3d.vtk;\r
+\r
+import org.eclipse.ui.plugin.AbstractUIPlugin;\r
+import org.osgi.framework.BundleContext;\r
+\r
+public class Activator extends AbstractUIPlugin {\r
+\r
+ public static final String PLUGIN_ID = "org.simantics.g3d.vtk"; //$NON-NLS-1$\r
+ \r
+ private static Activator plugin;\r
+ \r
+ \r
+ /*\r
+ * (non-Javadoc)\r
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)\r
+ */\r
+ public void start(BundleContext context) throws Exception {\r
+ super.start(context);\r
+ plugin = this;\r
+ }\r
+\r
+ /*\r
+ * (non-Javadoc)\r
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)\r
+ */\r
+ public void stop(BundleContext context) throws Exception {\r
+ plugin = null;\r
+ super.stop(context);\r
+ }\r
+\r
+ /**\r
+ * Returns the shared instance\r
+ *\r
+ * @return the shared instance\r
+ */\r
+ public static Activator getDefault() {\r
+ return plugin;\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.vtk.action;\r
+\r
+import org.eclipse.jface.action.Action;\r
+import org.simantics.g3d.scenegraph.IG3DNode;\r
+import org.simantics.g3d.scenegraph.structural.IStructuralNode;\r
+import org.simantics.g3d.vtk.Activator;\r
+import org.simantics.g3d.vtk.common.VTKNodeMap;\r
+\r
+public class RemoveAction extends Action {\r
+\r
+ private VTKNodeMap nodeMap;\r
+ protected IG3DNode node;\r
+ \r
+ public RemoveAction(VTKNodeMap nodeMap) {\r
+ setText("Remove");\r
+ setImageDescriptor(Activator.imageDescriptorFromPlugin("com.famfamfam.silk", "icons/delete.png"));\r
+ this.nodeMap = nodeMap;\r
+ }\r
+ \r
+ public void setNode(IG3DNode node) {\r
+ this.node = node;\r
+ setEnabled(isRemovable(node));\r
+ }\r
+ \r
+ public boolean isRemovable(IG3DNode node) {\r
+ if ((node instanceof IStructuralNode) && ((IStructuralNode)node).isPartOfInstantiatedModel() && !((IStructuralNode)node).isInstantiatedModelRoot())\r
+ return false;\r
+ return true;\r
+ }\r
+ \r
+ @Override\r
+ public void run() {\r
+ \r
+ doRemove(node);\r
+ nodeMap.commit();\r
+ node = null;\r
+ }\r
+ \r
+ protected void doRemove(IG3DNode node) {\r
+ node.remove();\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.g3d.vtk.action;\r
+\r
+import java.awt.Cursor;\r
+import java.awt.event.KeyEvent;\r
+import java.awt.event.MouseEvent;\r
+\r
+import javax.vecmath.AxisAngle4d;\r
+import javax.vecmath.Point3d;\r
+import javax.vecmath.Quat4d;\r
+import javax.vecmath.Vector3d;\r
+\r
+import org.simantics.g3d.math.EulerTools;\r
+import org.simantics.g3d.math.MathTools;\r
+import org.simantics.g3d.math.Ray;\r
+import org.simantics.g3d.math.EulerTools.Order;\r
+import org.simantics.g3d.preferences.PreferenceConstants;\r
+import org.simantics.g3d.scenegraph.IG3DNode;\r
+import org.simantics.g3d.scenegraph.structural.IStructuralNode;\r
+import org.simantics.g3d.vtk.Activator;\r
+import org.simantics.g3d.vtk.common.InteractiveVtkPanel;\r
+import org.simantics.g3d.vtk.common.VTKNodeMap;\r
+import org.simantics.g3d.vtk.gizmo.RotateAxisGizmo;\r
+import org.simantics.g3d.vtk.utils.vtkUtil;\r
+import org.simantics.utils.threads.AWTThread;\r
+import org.simantics.utils.threads.ThreadUtils;\r
+\r
+import vtk.vtkProp;\r
+/**\r
+ * FIXME: complete rewrite.\r
+ * \r
+ * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
+ *\r
+ */\r
+public class RotateAction extends vtkAction{\r
+ \r
+ public static final int X = 0;\r
+ public static final int Y = 1;\r
+ public static final int Z = 2;\r
+ public static final int P = 3;\r
+\r
+ private VTKNodeMap nodeMap;\r
+ //private TranslateGizmo gizmo = new TranslateGizmo();\r
+ private RotateAxisGizmo gizmo = new RotateAxisGizmo();\r
+ private IG3DNode node;\r
+ \r
+ \r
+ \r
+ private Cursor activeCursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);\r
+ private Cursor dragCursor = Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR);\r
+ \r
+ \r
+ int stepMethod = 1;\r
+ Order order = Order.YXZ;\r
+ \r
+ private int steps; \r
+ private double angles[];\r
+ \r
+ int index = P;\r
+ boolean valid = false;\r
+ private boolean worldCoord = true;\r
+ //private AxisAngle4d aa = null;\r
+ private Quat4d parentWorldOrientation = null;\r
+ \r
+ //AxisAngle4d rotation = new AxisAngle4d();\r
+ Quat4d worldOrientation = new Quat4d();\r
+ \r
+ public void setNode(IG3DNode node) {\r
+ this.node = node;\r
+ if ((node instanceof IStructuralNode) && ((IStructuralNode)node).isPartOfInstantiatedModel() && !((IStructuralNode)node).isInstantiatedModelRoot()) {\r
+ setEnabled(false);\r
+ } else {\r
+ setEnabled(true);\r
+ }\r
+ \r
+ String set = org.simantics.g3d.Activator.getDefault().getPreferenceStore().getString(PreferenceConstants.ORIENTATION_PRESENTATION);\r
+ if (set.equals("aa")) {\r
+ stepMethod = 0;\r
+ } else if (set.equals("euler")){\r
+ stepMethod = 1;\r
+ String eulerOrder = org.simantics.g3d.Activator.getDefault().getPreferenceStore().getString(PreferenceConstants.EULER_ANGLE_ORDER);\r
+ try {\r
+ order = Order.valueOf(eulerOrder);\r
+ } catch (Exception e) {\r
+ order = Order.YXZ;\r
+ }\r
+ } else {\r
+ stepMethod = 2;\r
+ }\r
+ }\r
+ \r
+ public IG3DNode getNode() {\r
+ return node;\r
+ }\r
+ \r
+ public RotateAction(InteractiveVtkPanel panel, VTKNodeMap nodeMap) {\r
+ super(panel);\r
+ setImageDescriptor(Activator.imageDescriptorFromPlugin("com.famfamfam.silk", "icons/arrow_rotate_clockwise.png"));\r
+ setText("Rotate");\r
+ this.nodeMap = nodeMap;\r
+ \r
+ \r
+ steps = 36;\r
+ angles = new double[steps+1];\r
+ for (int i = 0; i < angles.length; i++) {\r
+ angles[i] = - Math.PI + (Math.PI * i * 2.0 / steps);\r
+ }\r
+ }\r
+ \r
+ public void attach() {\r
+ if (node == null)\r
+ return;\r
+ \r
+ super.attach();\r
+ ThreadUtils.asyncExec(AWTThread.getThreadAccess(), new Runnable() {\r
+ public void run() {\r
+ attachUI();\r
+ update();\r
+ }\r
+ });\r
+ \r
+ \r
+ \r
+ }\r
+ \r
+ public void deattach() {\r
+ \r
+ node = null;\r
+ nodeMap.commit();\r
+ deattachUI();\r
+ super.deattach();\r
+ panel.repaint();\r
+ }\r
+ \r
+ private void attachUI() {\r
+ panel.setCursor(activeCursor);\r
+ gizmo.attach(panel.GetRenderer());\r
+ }\r
+ \r
+ private void deattachUI() {\r
+ panel.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));\r
+ gizmo.deattach();\r
+ }\r
+ \r
+ @Override\r
+ public void keyPressed(KeyEvent e) {\r
+ if (e.getKeyCode() == KeyEvent.VK_ESCAPE)\r
+ panel.useDefaultAction();\r
+ if (valid)\r
+ return;\r
+ if (e.getKeyCode() == KeyEvent.VK_X) {\r
+ if (index != X)\r
+ index = X;\r
+ else\r
+ index = P;\r
+ }\r
+ if (e.getKeyCode() == KeyEvent.VK_Y) {\r
+ if (index != Y)\r
+ index = Y;\r
+ else\r
+ index = P;\r
+ }\r
+ if (e.getKeyCode() == KeyEvent.VK_Z) {\r
+ if (index != Z)\r
+ index = Z;\r
+ else\r
+ index = P;\r
+ }\r
+ if (e.getKeyCode() == KeyEvent.VK_G) {\r
+ worldCoord = !worldCoord;\r
+ }\r
+ gizmo.setType(index);\r
+ panel.repaint();\r
+ }\r
+ \r
+ @Override\r
+ public void keyReleased(KeyEvent e) {\r
+ \r
+ }\r
+ \r
+ \r
+ \r
+ @Override\r
+ public void mouseClicked(MouseEvent e) {\r
+ if (e.getClickCount() > 1) {\r
+ if (isOverNode(e)) {\r
+ return;\r
+ }\r
+ panel.useDefaultAction();\r
+ //if(!gizmo.isPartOf(actor))\r
+ // panel.useDefaultAction();\r
+ \r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public void mouseEntered(MouseEvent e) {\r
+ \r
+ }\r
+ \r
+ @Override\r
+ public void mouseExited(MouseEvent e) {\r
+ \r
+ }\r
+ \r
+ \r
+\r
+ \r
+ \r
+ public void setWorldCoord(boolean b) {\r
+ if (worldCoord == b)\r
+ return;\r
+ worldCoord = b;\r
+ update();\r
+ \r
+ }\r
+ \r
+ \r
+ private void update() {\r
+ Vector3d nodePos = node.getWorldPosition();\r
+ System.out.println(nodePos);\r
+ gizmo.setPosition(nodePos);\r
+ if (worldCoord) {\r
+ gizmo.setRotation(new AxisAngle4d());\r
+ parentWorldOrientation = null;\r
+ } else {\r
+ AxisAngle4d aa = new AxisAngle4d();\r
+ parentWorldOrientation = ((IG3DNode)node.getParent()).getWorldOrientation();\r
+ aa.set(parentWorldOrientation);\r
+ gizmo.setRotation(aa);\r
+ }\r
+\r
+ Point3d camPos = new Point3d(panel.GetRenderer().GetActiveCamera().GetPosition());\r
+ Vector3d p = new Vector3d(nodePos);\r
+ p.sub(camPos);\r
+ \r
+ if (parentWorldOrientation != null) {\r
+ Quat4d qi = new Quat4d(parentWorldOrientation);\r
+ qi.inverse();\r
+ MathTools.rotate(parentWorldOrientation, p, p);\r
+ }\r
+ if (panel.GetRenderer().GetActiveCamera().GetParallelProjection() == 0) {\r
+ double distance = p.length();\r
+ p.negate();\r
+ double fov = panel.GetRenderer().GetActiveCamera().GetViewAngle();\r
+ float s = (float) (Math.sin(fov) * distance * 0.1); \r
+\r
+ Vector3d scale = new Vector3d(1., 1., 1.);\r
+ \r
+// if (p.x > 0.f)\r
+// scale.x = -1.;\r
+// if (p.y > 0.f)\r
+// scale.y = -1.;\r
+// if (p.z > 0.f)\r
+// scale.z = -1.;\r
+ scale.scale(s);\r
+ gizmo.setScale(scale);\r
+ \r
+ } else {\r
+ Vector3d scale = new Vector3d(1.f, 1.f, 1.f);\r
+ double s = panel.GetRenderer().GetActiveCamera().GetParallelScale() / 5.;\r
+// if (p.x > 0.f)\r
+// scale.x = -1.;\r
+// if (p.y > 0.f)\r
+// scale.y = -1.;\r
+// if (p.z > 0.f)\r
+// scale.z = -1.;\r
+ scale.scale(s);\r
+ gizmo.setScale(scale);\r
+ }\r
+ \r
+ panel.Render();\r
+ }\r
+ \r
+ private boolean isOverNode(MouseEvent e) {\r
+ vtkProp picked[] = panel.pick(e.getX(), e.getY());\r
+ if (picked !=null) {\r
+ for (int i = 0; i < picked.length; i++) {\r
+ if (node.equals(nodeMap.getNode(picked[i])))\r
+ return true;\r
+ }\r
+ }\r
+ return false;\r
+ }\r
+ \r
+\r
+ \r
+ @Override\r
+ public void mousePressed(MouseEvent e) {\r
+ if (e.getButton() == MouseEvent.BUTTON1) {\r
+ \r
+ \r
+ if (isOverNode(e)) {\r
+ valid = true;\r
+ if ((e.getModifiers() & MouseEvent.CTRL_MASK) > 0) {\r
+ useStep = true;\r
+ } else {\r
+ useStep = false;\r
+ }\r
+ worldOrientation = node.getWorldOrientation();\r
+ doChanges(true, e.getX(), e.getY());\r
+ \r
+ panel.setCursor(dragCursor);\r
+ } else {\r
+ valid = false;\r
+ panel.getDefaultAction().mousePressed(e);\r
+ panel.setCursor(activeCursor);\r
+ }\r
+ } else {\r
+ panel.getDefaultAction().mousePressed(e);\r
+ }\r
+ }\r
+ \r
+ \r
+ \r
+ @Override\r
+ public void mouseReleased(MouseEvent e) {\r
+ if (e.getButton() == MouseEvent.BUTTON1) {\r
+ valid = false;\r
+ worldOrientation = null;\r
+ panel.setCursor(activeCursor);\r
+ } else {\r
+ panel.getDefaultAction().mouseReleased(e);\r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public void mouseDragged(MouseEvent e) {\r
+ if ((e.getModifiersEx() & MouseEvent.BUTTON1_DOWN_MASK) > 0 && valid) { \r
+ if ((e.getModifiers() & MouseEvent.CTRL_MASK) > 0) {\r
+ useStep = true;\r
+ } else {\r
+ useStep = false;\r
+ }\r
+ doChanges(false, e.getX(), e.getY());\r
+ \r
+ //nodeMap.modified(node);\r
+ update();\r
+ } else {\r
+ panel.getDefaultAction().mouseDragged(e);\r
+ update();\r
+ }\r
+ }\r
+ \r
+ Vector3d axis = null;\r
+ \r
+ @Override\r
+ public void keyTyped(KeyEvent e) {\r
+ if (e.getKeyCode() == KeyEvent.VK_LEFT) {\r
+ inputType = InputType.KEY;\r
+ axis = new Vector3d(0.0,1.0,0.0);\r
+ } else if (e.getKeyCode() == KeyEvent.VK_RIGHT) {\r
+ inputType = InputType.KEY;\r
+ axis = new Vector3d(0.0,-1.0,0.0);\r
+ } else if (e.getKeyCode() ==KeyEvent.VK_UP) {\r
+ inputType = InputType.KEY;\r
+ axis = new Vector3d(1.0,0.0,0.0);\r
+ } else if (e.getKeyCode() == KeyEvent.VK_DOWN) {\r
+ inputType = InputType.KEY;\r
+ axis = new Vector3d(-1.0,0.0,0.0);\r
+ } \r
+ }\r
+ \r
+ public void doChanges(boolean pressed, int x, int y) {\r
+ Ray ray = vtkUtil.createMouseRay(panel.GetRenderer(),x, y);\r
+ Vector3d p = node.getWorldPosition();\r
+ \r
+ if (pressed) {\r
+ Vector3d axis = getRotationAxis();\r
+ if (axis != null) {\r
+ if (!worldCoord) {\r
+ MathTools.rotate(parentWorldOrientation, axis, axis);\r
+ }\r
+\r
+ \r
+ double s[] = new double[2];\r
+ Vector3d i2 = new Vector3d();\r
+ \r
+ boolean intersect = MathTools.intersectStraightPlane(ray.pos, ray.dir, p, axis, i2, s);\r
+ double dot = Math.abs(ray.dir.dot(axis));\r
+ if (intersect && dot > 0.4)\r
+ inputType = InputType.INTERSECT;\r
+ else\r
+ inputType = InputType.NONINTERSECT;\r
+ \r
+ \r
+ if (inputType == InputType.INTERSECT) {\r
+ // picking ray and plane defined by gizmo's center point and\r
+ // rotation axis can intersect\r
+ // vector from center point to intersection point\r
+ i2.sub(p);\r
+ // creating vectors i and j that are lying on the plane and\r
+ // are perpendicular\r
+ // vectors are used to calculate polar coordinate for\r
+ // intersection point\r
+ j.set(i2);\r
+ i.cross(j, axis);\r
+ System.out.println("I,J " + i + " " + j);\r
+ double angleI = i2.angle(i);\r
+ double angleJ = i2.angle(j);\r
+ prevAngle = Math.atan2(Math.cos(angleJ), Math.cos(angleI));\r
+ } else {\r
+ // picking ray and plane defined by gizmo's center point and\r
+ // rotation axis are parallel,\r
+ // so we'll use cross product of rotation axis and picking\r
+ // ray to detect amount of rotation\r
+ i.cross(ray.dir, axis);\r
+ MathTools.intersectStraightStraight(ray.pos, ray.dir, p, i, new Vector3d(), new Vector3d(), s);\r
+ prevS = s[1];\r
+ }\r
+ }\r
+ \r
+ \r
+ }\r
+\r
+ if (inputType != InputType.KEY)\r
+ axis = getRotationAxis();\r
+ if (axis == null) {\r
+ return; \r
+ }\r
+ Vector3d taxis = null;\r
+ if (!worldCoord) {\r
+ taxis = new Vector3d(axis);\r
+ MathTools.rotate(parentWorldOrientation, axis, axis);\r
+ }\r
+ System.out.println(inputType);\r
+ if (inputType == InputType.INTERSECT) {\r
+\r
+ double s[] = new double[2];\r
+ Vector3d i2 = new Vector3d();\r
+ MathTools.intersectStraightPlane(ray.pos, ray.dir, p, axis, i2, s);\r
+ i2.sub(p);\r
+ double angleI = i2.angle(i);\r
+ double angleJ = i2.angle(j);\r
+ double angle = Math.atan2(Math.cos(angleJ), Math.cos(angleI));\r
+ System.out.println("Angle " + angle + " i " + angleI + " j " + angleJ + " prev " + prevAngle);\r
+ if(!worldCoord)\r
+ axis = taxis;\r
+ if (useStep) {\r
+\r
+ //setOrientation(MathTools.getQuat(rotation));\r
+ AxisAngle4d rot = new AxisAngle4d(axis,angle-prevAngle);\r
+ Quat4d qrot = new Quat4d();\r
+ MathTools.getQuat(rot, qrot);\r
+ //prevAngle = angle;\r
+ qrot.mulInverse(worldOrientation);\r
+ \r
+ \r
+ if (stepMethod == 0) {\r
+ rot.set(qrot);\r
+ rot.angle = roundAngle(rot.angle);\r
+ //qrot.set(rot);\r
+ MathTools.getQuat(rot,qrot);\r
+ setOrientation(qrot);\r
+ } else if (stepMethod == 1){\r
+ \r
+ //Vector3d euler = MathTools.getEuler(qrot);\r
+ Vector3d euler = EulerTools.getEulerFromQuat(order, qrot);\r
+ euler.x = roundAngle(euler.x);\r
+ euler.y = roundAngle(euler.y);\r
+ euler.z = roundAngle(euler.z);\r
+ //Quat4d q = MathTools.getQuat(euler);\r
+ Quat4d q = EulerTools.getQuatFromEuler(order, euler);\r
+ setOrientation(q);\r
+ System.out.println(" (" + MathTools.radToDeg(euler.x) + " " + MathTools.radToDeg(euler.y) + " " + MathTools.radToDeg(euler.z) + ") " + qrot + " "+ q);\r
+ } else {\r
+ setOrientation(qrot);\r
+ }\r
+ \r
+ } else {\r
+ if (worldCoord) {\r
+ //G3DTools.multiplyOrientation(mo.getG3DNode(graph).getWorldOrientation(), new AxisAngle4d(axis,angle-prevAngle));\r
+ AxisAngle4d aa = MathTools.getAxisAngle(node.getWorldOrientation());\r
+ AxisAngle4d rot = new AxisAngle4d(axis,angle-prevAngle);\r
+ MathTools.multiplyOrientation(aa, rot);\r
+ setWorldOrientation(MathTools.getQuat(rot));\r
+ } else {\r
+ AxisAngle4d aa = MathTools.getAxisAngle(node.getOrientation());\r
+ AxisAngle4d rot = new AxisAngle4d(axis,angle-prevAngle);\r
+ MathTools.multiplyOrientation(aa, rot);\r
+ setOrientation(MathTools.getQuat(rot));\r
+ //G3DTools.multiplyOrientation(mo.getG3DNode(graph).getLocalOrientation(), new AxisAngle4d(axis,angle-prevAngle));\r
+ }\r
+ prevAngle = angle;\r
+ }\r
+ \r
+ } else if (inputType == InputType.NONINTERSECT){\r
+\r
+ double s[] = new double[2];\r
+ MathTools.intersectStraightStraight(ray.pos, ray.dir, p, i, new Vector3d(), new Vector3d(), s);\r
+ if(!worldCoord)\r
+ axis = taxis;\r
+ if (useStep) {\r
+ //setOrientation(MathTools.getQuat(rotation));\r
+ AxisAngle4d rot = new AxisAngle4d(axis,s[1] - prevS);\r
+ \r
+ Quat4d qrot = new Quat4d();\r
+ //qrot.set(rot);\r
+ MathTools.getQuat(rot, qrot);\r
+ //prevAngle = angle;\r
+ qrot.mulInverse(worldOrientation);\r
+ \r
+ \r
+ if (stepMethod == 0) {\r
+ rot.set(qrot);\r
+ rot.angle = roundAngle(rot.angle);\r
+ //qrot.set(rot);\r
+ MathTools.getQuat(rot,qrot);\r
+ setOrientation(qrot);\r
+ } else if (stepMethod == 1){\r
+ \r
+ //Vector3d euler = MathTools.getEuler(qrot);\r
+ Vector3d euler = EulerTools.getEulerFromQuat(order, qrot);\r
+ euler.x = roundAngle(euler.x);\r
+ euler.y = roundAngle(euler.y);\r
+ euler.z = roundAngle(euler.z);\r
+ //Quat4d q = MathTools.getQuat(euler);\r
+ Quat4d q = EulerTools.getQuatFromEuler(order, euler);\r
+ setOrientation(q);\r
+ System.out.println(" (" + MathTools.radToDeg(euler.x) + " " + MathTools.radToDeg(euler.y) + " " + MathTools.radToDeg(euler.z) + ") " + qrot + " "+ q);\r
+ } else {\r
+ setOrientation(qrot);\r
+ }\r
+ prevS = s[1];\r
+ \r
+// G3DTools.setOrientation(mo.getG3DNode(graph).getLocalOrientation(), rotations.get(mo));\r
+// G3DTools.multiplyOrientation(mo.getG3DNode(graph).getWorldOrientation(), new AxisAngle4d(axis,s[1] - prevS));\r
+// AxisAngle4d aa = G3DTools.getOrientation(mo.getG3DNode(graph).getLocalOrientation());\r
+// rotations.put(mo, aa);\r
+// Vector3d euler = MathTools.getEuler(aa);\r
+// euler.x = roundAngle(euler.x);\r
+// euler.y = roundAngle(euler.y);\r
+// euler.z = roundAngle(euler.z);\r
+// aa = MathTools.getFromEuler2(euler);\r
+// prevS = s[1];\r
+// G3DTools.setOrientation(mo.getG3DNode(graph).getLocalOrientation(), aa);\r
+// Vector3d e = MathTools.getEuler(G3DTools.getOrientation(mo.getG3DNode(graph).getLocalOrientation()));\r
+// e.scale(180.0/Math.PI);\r
+// text += G3DTools.getOrientation(mo.getG3DNode(graph).getLocalOrientation()) + " " + e + " ";\r
+ \r
+ \r
+ } else {\r
+ if (worldCoord) {\r
+ AxisAngle4d aa = MathTools.getAxisAngle(node.getWorldOrientation());\r
+ AxisAngle4d rot = new AxisAngle4d(axis,s[1] - prevS);\r
+ MathTools.multiplyOrientation(aa, rot);\r
+ setWorldOrientation(MathTools.getQuat(rot));\r
+ //G3DTools.multiplyOrientation(mo.getG3DNode(graph).getWorldOrientation(), new AxisAngle4d(axis,s[1] - prevS));\r
+ } else {\r
+ AxisAngle4d aa = MathTools.getAxisAngle(node.getOrientation());\r
+ AxisAngle4d rot = new AxisAngle4d(axis,s[1] - prevS);\r
+ MathTools.multiplyOrientation(aa, rot);\r
+ setOrientation(MathTools.getQuat(rot));\r
+ //G3DTools.multiplyOrientation(mo.getG3DNode(graph).getLocalOrientation(), new AxisAngle4d(axis,s[1] - prevS));\r
+ }\r
+ //text += G3DTools.getOrientation(mo.getG3DNode(graph).getLocalOrientation()) + " " + MathTools.getEuler(G3DTools.getOrientation(mo.getG3DNode(graph).getLocalOrientation())) + " ";\r
+ prevS = s[1];\r
+ \r
+ }\r
+ \r
+ } else {\r
+ if (worldCoord) {\r
+ AxisAngle4d aa = MathTools.getAxisAngle(node.getWorldOrientation());\r
+ AxisAngle4d rot = new AxisAngle4d(axis,Math.PI * 0.5);\r
+ MathTools.multiplyOrientation(aa, rot);\r
+ setWorldOrientation(MathTools.getQuat(rot));\r
+ //G3DTools.multiplyOrientation(mo.getG3DNode(graph).getWorldOrientation(), new AxisAngle4d(axis,Math.PI * 0.5));\r
+ } else {\r
+ AxisAngle4d aa = MathTools.getAxisAngle(node.getOrientation());\r
+ AxisAngle4d rot = new AxisAngle4d(axis,Math.PI * 0.5);\r
+ MathTools.multiplyOrientation(aa, rot);\r
+ setOrientation(MathTools.getQuat(rot));\r
+ //G3DTools.multiplyOrientation(mo.getG3DNode(graph).getLocalOrientation(), new AxisAngle4d(axis,Math.PI * 0.5));\r
+ }\r
+ // text += G3DTools.getOrientation(mo.getG3DNode(graph).getLocalOrientation()) + " " + MathTools.getEuler(G3DTools.getOrientation(mo.getG3DNode(graph).getLocalOrientation())) + " ";\r
+ \r
+ }\r
+ //setInfoText(text);\r
+ \r
+ }\r
+ \r
+ protected void setOrientation(Quat4d q) {\r
+ node.setOrientation(q);\r
+ }\r
+ \r
+ protected void setWorldOrientation(Quat4d q) {\r
+ node.setWorldOrientation(q);\r
+ }\r
+ \r
+ @Override\r
+ public void mouseMoved(MouseEvent e) {\r
+ panel.getDefaultAction().mouseMoved(e);\r
+ }\r
+ \r
+ private Vector3d getRotationAxis() {\r
+ switch (index) {\r
+ case X:\r
+ return new Vector3d(1.0, 0.0, 0.0);\r
+ case Y:\r
+ return new Vector3d(0.0, 1.0, 0.0);\r
+ case Z:\r
+ return new Vector3d(0.0, 0.0, 1.0);\r
+ case P:\r
+ Vector3d axis = new Vector3d(panel.GetRenderer().GetActiveCamera()\r
+ .GetDirectionOfProjection());\r
+ axis.normalize();\r
+ return axis;\r
+ default:\r
+ return null;\r
+ }\r
+ }\r
+ \r
+ private double prevS = 0.0;\r
+ \r
+ private Vector3d i = new Vector3d();\r
+ private Vector3d j = new Vector3d();\r
+ private double prevAngle = 0;\r
+\r
+ enum InputType{INTERSECT,NONINTERSECT,KEY,NONE};\r
+ InputType inputType;\r
+ private boolean useStep = false;\r
+ \r
+ \r
+ \r
+ private double roundAngle(double angle) {\r
+ while (angle < - Math.PI)\r
+ angle += Math.PI*2.0;\r
+ while (angle > Math.PI)\r
+ angle -= Math.PI*2.0;\r
+ \r
+ \r
+ int index = 0;\r
+ while (angle > angles[index])\r
+ index++;\r
+ if (index == 0) {\r
+ angle = angles[0];\r
+ } else {\r
+ double d = angle - angles[index - 1];\r
+ double d2 = angles[index] - angle;\r
+ if (d < d2)\r
+ angle = angles[index - 1];\r
+ else\r
+ angle = angles[index];\r
+ }\r
+ return angle;\r
+ }\r
+ \r
+}\r
--- /dev/null
+package org.simantics.g3d.vtk.action;\r
+\r
+import java.awt.Cursor;\r
+import java.awt.event.KeyEvent;\r
+import java.awt.event.MouseEvent;\r
+import java.math.BigDecimal;\r
+\r
+import javax.vecmath.AxisAngle4d;\r
+import javax.vecmath.Point3d;\r
+import javax.vecmath.Quat4d;\r
+import javax.vecmath.Vector3d;\r
+\r
+import org.simantics.g3d.math.MathTools;\r
+import org.simantics.g3d.math.Ray;\r
+import org.simantics.g3d.scenegraph.IG3DNode;\r
+import org.simantics.g3d.scenegraph.structural.IStructuralNode;\r
+import org.simantics.g3d.vtk.Activator;\r
+import org.simantics.g3d.vtk.common.InteractiveVtkPanel;\r
+import org.simantics.g3d.vtk.common.VTKNodeMap;\r
+import org.simantics.g3d.vtk.gizmo.TranslateAxisGizmo;\r
+import org.simantics.g3d.vtk.utils.vtkUtil;\r
+import org.simantics.utils.threads.AWTThread;\r
+import org.simantics.utils.threads.ThreadUtils;\r
+\r
+import vtk.vtkProp;\r
+\r
+public class TranslateAction extends vtkAction{\r
+ \r
+ public static final int X = 0;\r
+ public static final int Y = 1;\r
+ public static final int Z = 2;\r
+ public static final int XY = 3;\r
+ public static final int XZ = 4;\r
+ public static final int YZ = 5;\r
+ public static final int P = 6;\r
+\r
+ private VTKNodeMap nodeMap;\r
+ //private TranslateGizmo gizmo = new TranslateGizmo();\r
+ private TranslateAxisGizmo gizmo = new TranslateAxisGizmo();\r
+ private IG3DNode node;\r
+ \r
+ \r
+ \r
+ private Cursor activeCursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);\r
+ private Cursor dragCursor = Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR);\r
+ \r
+ public void setNode(IG3DNode node) {\r
+ this.node = node;\r
+ if ((node instanceof IStructuralNode) && ((IStructuralNode)node).isPartOfInstantiatedModel() && !((IStructuralNode)node).isInstantiatedModelRoot()) {\r
+ setEnabled(false);\r
+ } else {\r
+ setEnabled(true);\r
+ }\r
+ }\r
+ \r
+ public IG3DNode getNode() {\r
+ return node;\r
+ }\r
+ \r
+ public TranslateAction(InteractiveVtkPanel panel, VTKNodeMap nodeMap) {\r
+ super(panel);\r
+ setImageDescriptor(Activator.imageDescriptorFromPlugin("com.famfamfam.silk", "icons/arrow_out.png"));\r
+ setText("Translate");\r
+ this.nodeMap = nodeMap;\r
+ }\r
+ \r
+ public void attach() {\r
+ if (node == null)\r
+ return;\r
+ \r
+ super.attach();\r
+ ThreadUtils.asyncExec(AWTThread.getThreadAccess(), new Runnable() {\r
+ public void run() {\r
+ attachUI();\r
+ update();\r
+ }\r
+ });\r
+ \r
+ \r
+ \r
+ }\r
+ \r
+ public void deattach() {\r
+ \r
+ node = null;\r
+ nodeMap.commit();\r
+ deattachUI();\r
+ super.deattach();\r
+ panel.repaint();\r
+ }\r
+ \r
+ private void attachUI() {\r
+ panel.setCursor(activeCursor);\r
+ gizmo.attach(panel.GetRenderer());\r
+ }\r
+ \r
+ private void deattachUI() {\r
+ panel.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));\r
+ gizmo.deattach();\r
+ }\r
+ \r
+ @Override\r
+ public void keyPressed(KeyEvent e) {\r
+ if (e.getKeyCode() == KeyEvent.VK_ESCAPE)\r
+ panel.useDefaultAction();\r
+ if (valid)\r
+ return;\r
+ if (e.getKeyCode() == KeyEvent.VK_X) {\r
+ if (index != X)\r
+ index = X;\r
+ else\r
+ index = P;\r
+ }\r
+ if (e.getKeyCode() == KeyEvent.VK_Y) {\r
+ if (index != Y)\r
+ index = Y;\r
+ else\r
+ index = P;\r
+ }\r
+ if (e.getKeyCode() == KeyEvent.VK_Z) {\r
+ if (index != Z)\r
+ index = Z;\r
+ else\r
+ index = P;\r
+ }\r
+ if (e.getKeyCode() == KeyEvent.VK_G) {\r
+ worldCoord = !worldCoord;\r
+ }\r
+ gizmo.setType(index);\r
+ \r
+ update();\r
+ //panel.repaint();\r
+ }\r
+ \r
+ @Override\r
+ public void keyReleased(KeyEvent e) {\r
+ \r
+ }\r
+ \r
+ @Override\r
+ public void keyTyped(KeyEvent e) {\r
+ \r
+ }\r
+ \r
+ @Override\r
+ public void mouseClicked(MouseEvent e) {\r
+ if (e.getClickCount() > 1) {\r
+ if (isOverNode(e)) {\r
+ return;\r
+ } else {\r
+ panel.useDefaultAction();\r
+ }\r
+ //if(!gizmo.isPartOf(actor))\r
+ // panel.useDefaultAction();\r
+ \r
+ }\r
+ }\r
+ \r
+ private boolean isOverNode(MouseEvent e) {\r
+ vtkProp picked[] = panel.pick(e.getX(), e.getY());\r
+ if (picked !=null) {\r
+ for (int i = 0; i < picked.length; i++) {\r
+ if (node.equals(nodeMap.getNode(picked[i])))\r
+ return true;\r
+ }\r
+ }\r
+ return false;\r
+ }\r
+ \r
+ @Override\r
+ public void mouseEntered(MouseEvent e) {\r
+ \r
+ }\r
+ \r
+ @Override\r
+ public void mouseExited(MouseEvent e) {\r
+ \r
+ }\r
+ \r
+ int index = P;\r
+ boolean valid = false;\r
+ private boolean worldCoord = true;\r
+ private AxisAngle4d aa = null;\r
+ private Quat4d q = null;\r
+ \r
+ \r
+ public void setWorldCoord(boolean b) {\r
+ if (worldCoord == b)\r
+ return;\r
+ worldCoord = b;\r
+ update();\r
+ \r
+ }\r
+ \r
+ \r
+ private void update() {\r
+ if (node == null)\r
+ return;\r
+ if (worldCoord) {\r
+ gizmo.setRotation(new AxisAngle4d());\r
+ aa = null;\r
+ q = null;\r
+ } else {\r
+ aa = new AxisAngle4d();\r
+ aa.set(((IG3DNode)node.getParent()).getWorldOrientation());\r
+ gizmo.setRotation(aa);\r
+ q = new Quat4d();\r
+ MathTools.getQuat(aa, q);\r
+ }\r
+ \r
+ Vector3d nodePos = node.getWorldPosition();\r
+ //System.out.println(nodePos);\r
+ gizmo.setPosition(nodePos);\r
+\r
+ \r
+ Point3d camPos = new Point3d(panel.GetRenderer().GetActiveCamera().GetPosition());\r
+ Vector3d p = new Vector3d(nodePos);\r
+ p.sub(camPos);\r
+ \r
+ if (q != null) {\r
+ Quat4d qi = new Quat4d(q);\r
+ qi.inverse();\r
+ MathTools.rotate(q, p, p);\r
+ }\r
+ if (panel.GetRenderer().GetActiveCamera().GetParallelProjection() == 0) {\r
+ double distance = p.length();\r
+ p.negate();\r
+ double fov = panel.GetRenderer().GetActiveCamera().GetViewAngle();\r
+ float s = (float) (Math.sin(fov) * distance * 0.1); \r
+\r
+ Vector3d scale = new Vector3d(1., 1., 1.);\r
+ \r
+// if (p.x > 0.f)\r
+// scale.x = -1.;\r
+// if (p.y > 0.f)\r
+// scale.y = -1.;\r
+// if (p.z > 0.f)\r
+// scale.z = -1.;\r
+ scale.scale(s);\r
+ gizmo.setScale(scale);\r
+ \r
+ } else {\r
+ Vector3d scale = new Vector3d(1.f, 1.f, 1.f);\r
+ double s = panel.GetRenderer().GetActiveCamera().GetParallelScale() / 5.;\r
+// if (p.x > 0.f)\r
+// scale.x = -1.;\r
+// if (p.y > 0.f)\r
+// scale.y = -1.;\r
+// if (p.z > 0.f)\r
+// scale.z = -1.;\r
+ scale.scale(s);\r
+ gizmo.setScale(scale);\r
+ }\r
+ \r
+ //panel.Render();\r
+ panel.repaint();\r
+ }\r
+ \r
+ Vector3d prevTranslate = null;\r
+ \r
+ @Override\r
+ public void mousePressed(MouseEvent e) {\r
+ if (e.getButton() == MouseEvent.BUTTON1) {\r
+\r
+ if (isOverNode(e)) {\r
+ prevTranslate = getTranslate(e.getX(), e.getY());\r
+ valid = true;\r
+ panel.setCursor(dragCursor);\r
+ } else {\r
+ valid = false;\r
+ panel.getDefaultAction().mousePressed(e);\r
+ panel.setCursor(activeCursor);\r
+ }\r
+ } else {\r
+ panel.getDefaultAction().mousePressed(e);\r
+ }\r
+ //index = gizmo.getTranslateAxis(actor);\r
+ //if (index == -1) {\r
+ // valid = false;\r
+ // panel.getDefaultAction().mousePressed(e);\r
+ // return;\r
+ //}\r
+ //valid = true; \r
+ //prevTranslate = getTranslate(e.getX(), e.getY());\r
+ //System.out.println("start translate " + prevTranslate);\r
+ }\r
+ \r
+ \r
+ \r
+ @Override\r
+ public void mouseReleased(MouseEvent e) {\r
+ if (e.getButton() == MouseEvent.BUTTON1) {\r
+ valid = false;\r
+ prevTranslate = null;\r
+ panel.setCursor(activeCursor);\r
+ } else {\r
+ panel.getDefaultAction().mouseReleased(e);\r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public void mouseDragged(MouseEvent e) {\r
+ if ((e.getModifiersEx() & MouseEvent.BUTTON1_DOWN_MASK) > 0 && valid) { \r
+ \r
+ Vector3d translate = getTranslate(e.getX(), e.getY(), prevTranslate);\r
+ //System.out.println("translate " + translate);\r
+ if (translate == null)\r
+ return;\r
+ boolean step = ((e.getModifiers() & MouseEvent.CTRL_MASK) > 0);\r
+ if (worldCoord) {\r
+ Vector3d pos = new Vector3d(node.getWorldPosition());\r
+ pos.add(translate);\r
+ pos = constaints(pos, step);\r
+ setWorldPos(pos);\r
+ } else {\r
+ Vector3d pos = new Vector3d(node.getPosition());\r
+ pos.add(translate);\r
+ pos = constaints(pos, step);\r
+ setPos(pos);\r
+ }\r
+ //mapping.rangeModified(node);\r
+ \r
+ //nodeMap.modified(node);\r
+ update();\r
+ } else {\r
+ panel.getDefaultAction().mouseDragged(e);\r
+ update();\r
+ }\r
+ }\r
+ \r
+ protected void setPos(Vector3d pos) {\r
+ node.setPosition(pos);\r
+ }\r
+ \r
+ protected void setWorldPos(Vector3d pos) {\r
+ node.setWorldPosition(pos);\r
+ }\r
+ \r
+ private double istep = 10.0;\r
+ private int decimals = 2;\r
+ \r
+ private Vector3d constaints(Vector3d p, boolean step) {\r
+ if(!step)\r
+ return p;\r
+ switch (index) {\r
+ case X:\r
+ p.x = Math.round(istep * p.x) / istep;\r
+ BigDecimal bx = new BigDecimal(p.x);\r
+ bx.setScale(decimals, BigDecimal.ROUND_HALF_UP);\r
+ p.x = bx.doubleValue();\r
+ break;\r
+ case Y:\r
+ p.y = Math.round(istep * p.y) / istep;\r
+ BigDecimal by = new BigDecimal(p.y);\r
+ by.setScale(decimals, BigDecimal.ROUND_HALF_UP);\r
+ p.y = by.doubleValue();\r
+ break;\r
+ \r
+ case Z:\r
+ p.z = Math.round(istep * p.z) / istep;\r
+ BigDecimal bz = new BigDecimal(p.z);\r
+ bz.setScale(decimals, BigDecimal.ROUND_HALF_UP);\r
+ p.z = bz.doubleValue();\r
+ break;\r
+ }\r
+ return p;\r
+ }\r
+ \r
+ @Override\r
+ public void mouseMoved(MouseEvent e) {\r
+ panel.getDefaultAction().mouseMoved(e);\r
+ }\r
+ \r
+ Vector3d getTranslate(double x, double y) {\r
+ return getTranslate(x, y, new Vector3d());\r
+ }\r
+ \r
+ Vector3d getTranslate(double x, double y, Vector3d offset) {\r
+ Vector3d translate = new Vector3d();\r
+ \r
+ Ray ray = vtkUtil.createMouseRay(panel.GetRenderer(),x, y);\r
+ \r
+ Vector3d p = node.getWorldPosition();\r
+ Vector3d dir = null;\r
+ \r
+ switch (index) {\r
+ case P:\r
+ Vector3d normal = new Vector3d(panel.GetRenderer().GetActiveCamera().GetDirectionOfProjection());\r
+ if (!worldCoord) {\r
+ MathTools.rotate(q, normal, normal);\r
+ }\r
+ normal.normalize();\r
+ double s[] = new double[1];\r
+ Vector3d r = new Vector3d();\r
+ if (MathTools.intersectStraightPlane(ray.pos, ray.dir, p, normal, r)) {\r
+ r.sub(p);\r
+ translate.x = r.x;\r
+ translate.y = r.y;\r
+ translate.z = r.z;\r
+ }\r
+ break;\r
+\r
+ case X :\r
+ dir = new Vector3d(1.0,0.0,0.0);\r
+ if(!worldCoord)\r
+ MathTools.rotate(q, dir, dir);\r
+ Vector3d i1 = new Vector3d();\r
+ Vector3d i2 = new Vector3d();\r
+ s = new double[2];\r
+ MathTools.intersectStraightStraight( p, dir,ray.pos, ray.dir, i2, i1,s);\r
+ translate.x = s[0];\r
+ \r
+ break;\r
+ case Y :\r
+ dir = new Vector3d(0.0,1.0,0.0);\r
+ if(!worldCoord)\r
+ MathTools.rotate(q, dir, dir);\r
+ i1 = new Vector3d();\r
+ i2 = new Vector3d();\r
+ s = new double[2];\r
+ MathTools.intersectStraightStraight( p, dir,ray.pos, ray.dir, i2, i1,s);\r
+ translate.y = s[0];\r
+ break;\r
+ case Z :\r
+ dir = new Vector3d(0.0,0.0,1.0);\r
+ if(!worldCoord)\r
+ MathTools.rotate(q, dir, dir);\r
+ i1 = new Vector3d();\r
+ i2 = new Vector3d();\r
+ s = new double[2];\r
+ MathTools.intersectStraightStraight( p, dir,ray.pos, ray.dir, i2, i1,s);\r
+ translate.z = s[0];\r
+ break;\r
+ case XY :\r
+ normal = new Vector3d(0.0,0.0,1.0);\r
+ if(!worldCoord)\r
+ MathTools.rotate(q, normal, normal);\r
+ r = new Vector3d();\r
+ if (MathTools.intersectStraightPlane(ray.pos, ray.dir, p, normal, r)) {\r
+ r.sub(p);\r
+ translate.x = r.x;\r
+ translate.y = r.y;\r
+ }\r
+ break;\r
+ case XZ :\r
+ normal = new Vector3d(0.0,1.0,0.0);\r
+ if(!worldCoord)\r
+ MathTools.rotate(q, normal, normal);\r
+ r = new Vector3d();\r
+ if (MathTools.intersectStraightPlane(ray.pos, ray.dir, p, normal, r)) {\r
+ r.sub(p);\r
+ translate.x = r.x;\r
+ translate.z = r.z;\r
+ }\r
+ break;\r
+ case YZ :\r
+ normal = new Vector3d(1.0,0.0,0.0);\r
+ if(!worldCoord)\r
+ MathTools.rotate(q, normal, normal);\r
+ r = new Vector3d();\r
+ if (MathTools.intersectStraightPlane(ray.pos, ray.dir, p, normal, r)) {\r
+ r.sub(p);\r
+ translate.y = r.y;\r
+ translate.z = r.z;\r
+ }\r
+ break;\r
+ default :\r
+ \r
+ return null;\r
+ }\r
+ translate.sub(offset);\r
+ return translate;\r
+ }\r
+ \r
+}\r
--- /dev/null
+package org.simantics.g3d.vtk.action;\r
+\r
+import java.awt.event.KeyEvent;\r
+import java.awt.event.KeyListener;\r
+import java.awt.event.MouseEvent;\r
+import java.awt.event.MouseListener;\r
+import java.awt.event.MouseMotionListener;\r
+\r
+import org.eclipse.jface.action.Action;\r
+import org.simantics.g3d.vtk.common.InteractiveVtkPanel;\r
+\r
+public abstract class vtkAction extends Action implements KeyListener, MouseListener, MouseMotionListener {\r
+\r
+ protected InteractiveVtkPanel panel;\r
+ \r
+ public vtkAction(InteractiveVtkPanel panel) {\r
+ this.panel = panel;\r
+ }\r
+ \r
+ @Override\r
+ public void run() {\r
+ panel.setActiveAction(this);\r
+ }\r
+ \r
+ \r
+ public void attach() {\r
+\r
+ panel.addKeyListener(this);\r
+ panel.addMouseListener(this);\r
+ panel.addMouseMotionListener(this);\r
+\r
+ }\r
+ \r
+ public void deattach() {\r
+ panel.removeKeyListener(this);\r
+ panel.removeMouseListener(this);\r
+ panel.removeMouseMotionListener(this);\r
+ }\r
+ \r
+ @Override\r
+ public void keyPressed(KeyEvent e) {\r
+ \r
+ }\r
+ \r
+ @Override\r
+ public void keyReleased(KeyEvent e) {\r
+ \r
+ }\r
+ \r
+ @Override\r
+ public void keyTyped(KeyEvent e) {\r
+ \r
+ }\r
+ \r
+ public void mouseClicked(java.awt.event.MouseEvent e) {\r
+ \r
+ };\r
+ \r
+ @Override\r
+ public void mouseDragged(MouseEvent e) {\r
+ \r
+ }\r
+ \r
+ @Override\r
+ public void mouseEntered(MouseEvent e) {\r
+ \r
+ }\r
+ \r
+ @Override\r
+ public void mouseExited(MouseEvent e) {\r
+ \r
+ }\r
+ \r
+ @Override\r
+ public void mouseMoved(MouseEvent e) {\r
+ \r
+ }\r
+ \r
+ @Override\r
+ public void mousePressed(MouseEvent e) {\r
+ \r
+ }\r
+ \r
+ @Override\r
+ public void mouseReleased(MouseEvent e) {\r
+ \r
+ }\r
+}\r
--- /dev/null
+package org.simantics.g3d.vtk.action;\r
+\r
+import java.awt.event.InputEvent;\r
+import java.awt.event.MouseEvent;\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.HashSet;\r
+import java.util.List;\r
+import java.util.Set;\r
+\r
+import org.eclipse.jface.viewers.ISelection;\r
+import org.eclipse.jface.viewers.ISelectionChangedListener;\r
+import org.eclipse.jface.viewers.ISelectionProvider;\r
+import org.eclipse.jface.viewers.SelectionChangedEvent;\r
+import org.eclipse.jface.viewers.StructuredSelection;\r
+import org.eclipse.swt.widgets.Display;\r
+import org.simantics.g3d.tools.AdaptationUtils;\r
+import org.simantics.g3d.vtk.common.InteractiveVtkPanel;\r
+\r
+import vtk.vtkActor;\r
+import vtk.vtkCamera;\r
+import vtk.vtkProp;\r
+import vtk.vtkRenderWindow;\r
+import vtk.vtkRenderer;\r
+\r
+public class vtkCameraAndSelectorAction extends vtkAction implements ISelectionProvider {\r
+ \r
+ protected vtkRenderer ren;\r
+ protected int lastX;\r
+ protected int lastY;\r
+ protected vtkRenderWindow rw;\r
+ protected vtkCamera cam;\r
+ protected int InteractionMode = 1;\r
+ \r
+ public vtkCameraAndSelectorAction(InteractiveVtkPanel panel) {\r
+ super(panel);\r
+ this.ren = panel.GetRenderer();\r
+ this.rw = panel.GetRenderWindow();\r
+ this.cam = ren.GetActiveCamera();\r
+ }\r
+ \r
+ public void Lock() {\r
+ panel.lock();\r
+ }\r
+ \r
+ public void UnLock() {\r
+ panel.unlock();\r
+ }\r
+ \r
+ public void InteractionModeRotate()\r
+ {\r
+ this.InteractionMode = 1;\r
+ }\r
+ \r
+ public void InteractionModeTranslate()\r
+ {\r
+ this.InteractionMode = 2;\r
+ }\r
+ \r
+ public void InteractionModeZoom()\r
+ {\r
+ this.InteractionMode = 3;\r
+ }\r
+ \r
+ public void resetCameraClippingRange() {\r
+ Lock();\r
+ ren.ResetCameraClippingRange();\r
+ UnLock();\r
+ }\r
+\r
+ public void resetCamera() {\r
+ Lock();\r
+ ren.ResetCamera();\r
+ UnLock();\r
+ }\r
+ \r
+ public void mousePressed(MouseEvent e)\r
+ {\r
+ \r
+ if (ren.VisibleActorCount() == 0) return;\r
+ rw.SetDesiredUpdateRate(5.0);\r
+ lastX = e.getX();\r
+ lastY = e.getY();\r
+ if ((e.getModifiers()==InputEvent.BUTTON2_MASK) ||\r
+ (e.getModifiers()==(InputEvent.BUTTON1_MASK | InputEvent.SHIFT_MASK)))\r
+ {\r
+ InteractionModeTranslate();\r
+ }\r
+ else if (e.getModifiers()==InputEvent.BUTTON3_MASK)\r
+ {\r
+ InteractionModeZoom();\r
+ }\r
+ else \r
+ {\r
+ InteractionModeRotate();\r
+ }\r
+ }\r
+ \r
+ public void mouseReleased(MouseEvent e)\r
+ {\r
+ rw.SetDesiredUpdateRate(0.01);\r
+ }\r
+ \r
+\r
+ \r
+ public void mouseDragged(MouseEvent e)\r
+ {\r
+ if (ren.VisibleActorCount() == 0) return;\r
+ int x = e.getX();\r
+ int y = e.getY();\r
+ // rotate\r
+ if (this.InteractionMode == 1)\r
+ {\r
+ cam.Azimuth(lastX - x);\r
+ cam.Elevation(y - lastY);\r
+ cam.OrthogonalizeViewUp();\r
+ resetCameraClippingRange();\r
+ panel.UpdateLight();\r
+ }\r
+ // translate\r
+ if (this.InteractionMode == 2)\r
+ {\r
+ double FPoint[];\r
+ double PPoint[];\r
+ double APoint[] = new double[3];\r
+ double RPoint[];\r
+ double focalDepth;\r
+ \r
+ // get the current focal point and position\r
+ FPoint = cam.GetFocalPoint();\r
+ PPoint = cam.GetPosition();\r
+ \r
+ // calculate the focal depth since we'll be using it a lot\r
+ ren.SetWorldPoint(FPoint[0],FPoint[1],FPoint[2],1.0);\r
+ ren.WorldToDisplay();\r
+ focalDepth = ren.GetDisplayPoint()[2];\r
+ \r
+ APoint[0] = rw.GetSize()[0]/2.0 + (x - lastX);\r
+ APoint[1] = rw.GetSize()[1]/2.0 - (y - lastY);\r
+ APoint[2] = focalDepth;\r
+ ren.SetDisplayPoint(APoint);\r
+ ren.DisplayToWorld();\r
+ RPoint = ren.GetWorldPoint();\r
+ if (RPoint[3] != 0.0)\r
+ {\r
+ RPoint[0] = RPoint[0]/RPoint[3];\r
+ RPoint[1] = RPoint[1]/RPoint[3];\r
+ RPoint[2] = RPoint[2]/RPoint[3];\r
+ }\r
+ \r
+ /*\r
+ * Compute a translation vector, moving everything 1/2 \r
+ * the distance to the cursor. (Arbitrary scale factor)\r
+ */\r
+ cam.SetFocalPoint(\r
+ (FPoint[0]-RPoint[0])/2.0 + FPoint[0],\r
+ (FPoint[1]-RPoint[1])/2.0 + FPoint[1],\r
+ (FPoint[2]-RPoint[2])/2.0 + FPoint[2]);\r
+ cam.SetPosition(\r
+ (FPoint[0]-RPoint[0])/2.0 + PPoint[0],\r
+ (FPoint[1]-RPoint[1])/2.0 + PPoint[1],\r
+ (FPoint[2]-RPoint[2])/2.0 + PPoint[2]);\r
+ resetCameraClippingRange();\r
+ }\r
+ // zoom\r
+ if (this.InteractionMode == 3)\r
+ {\r
+ double zoomFactor;\r
+ //double clippingRange[];\r
+ \r
+ zoomFactor = Math.pow(1.02,(y - lastY));\r
+ if (cam.GetParallelProjection() == 1)\r
+ {\r
+ cam.SetParallelScale(cam.GetParallelScale()/zoomFactor);\r
+ }\r
+ else\r
+ {\r
+ cam.Dolly(zoomFactor);\r
+ resetCameraClippingRange();\r
+ }\r
+ }\r
+ lastX = x;\r
+ lastY = y;\r
+ panel.Render();\r
+ }\r
+\r
+ \r
+ private List<vtkProp> selectActors = new ArrayList<vtkProp>();\r
+ private List<vtkProp> hoverActor = new ArrayList<vtkProp>();\r
+ \r
+ @Override\r
+ public void mouseClicked(MouseEvent e) {\r
+ if (!panel.isFocusOwner())\r
+ return;\r
+ if (e.getButton() != MouseEvent.BUTTON1)\r
+ return;\r
+ vtkProp spick[] = panel.pick(e.getX(), e.getY());\r
+ if (spick != null && spick.length > 0) {\r
+ for (vtkProp selectActor : spick) {\r
+ if (!e.isControlDown()) {\r
+ selectActors.clear();\r
+ selectActors.add(selectActor);\r
+ } else {\r
+ if (selectActors.contains(selectActor))\r
+ selectActors.remove(selectActor);\r
+ else\r
+ selectActors.add(selectActor);\r
+ }\r
+ }\r
+ fireSelectionChanged();\r
+ } else if (!e.isControlDown()) {\r
+ selectActors.clear();\r
+ fireSelectionChanged();\r
+ }\r
+ \r
+// if (e.getClickCount() > 1)\r
+// updatePickRay(e.getX(), e.getY());\r
+ \r
+ }\r
+ \r
+// private void updatePickRay(double x , double y) {\r
+// Ray ray = vtkUtil.createMouseRay(panel.GetRenderer(), x, y);\r
+// \r
+// \r
+// System.out.println(ray.pos + " " + ray.dir);\r
+// vtkPoints linePoints = new vtkPoints();\r
+// linePoints.InsertPoint(0,ray.pos.x, ray.pos.y, ray.pos.z);\r
+// linePoints.InsertPoint(1, ray.pos.x + ray.dir.x, ray.pos.y + ray.dir.y, ray.pos.z + ray.dir.z);\r
+// vtkLine aLine = new vtkLine();\r
+// aLine.GetPointIds().SetId(0, 0);\r
+// aLine.GetPointIds().SetId(1, 1);\r
+// vtkUnstructuredGrid aLineGrid = new vtkUnstructuredGrid();\r
+// aLineGrid.Allocate(1, 1);\r
+// aLineGrid.InsertNextCell(aLine.GetCellType(), aLine.GetPointIds());\r
+// aLineGrid.SetPoints(linePoints);\r
+// vtkDataSetMapper aLineMapper = new vtkDataSetMapper();\r
+// aLineMapper.SetInput(aLineGrid);\r
+// vtkActor aLineActor = new vtkActor();\r
+// aLineActor.SetMapper(aLineMapper);\r
+// aLineActor.GetProperty().SetDiffuseColor(.2, 1, 1);\r
+// \r
+// if (rayActor != null) {\r
+// panel.GetRenderer().RemoveActor(rayActor);\r
+// rayActor.Delete();\r
+// }\r
+// rayActor = aLineActor;\r
+// panel.GetRenderer().AddActor(rayActor);\r
+// \r
+// linePoints.Delete();\r
+// aLine.Delete();\r
+// aLineGrid.Delete();\r
+// aLineMapper.Delete();\r
+// panel.repaint();\r
+// }\r
+// \r
+// private vtkActor rayActor;\r
+ \r
+ @Override\r
+ public void mouseMoved(MouseEvent e) {\r
+ lastX = e.getX();\r
+ lastY = e.getY();\r
+ \r
+ if (!panel.isFocusOwner())\r
+ return;\r
+ List<vtkProp> prevHover = new ArrayList<vtkProp>();\r
+ prevHover.addAll(hoverActor);\r
+ hoverActor.clear();\r
+ vtkProp pick[] = panel.pick(e.getX(),e.getY());\r
+ if (pick != null) {\r
+ for (vtkProp p : pick)\r
+ hoverActor.add(p);\r
+ }\r
+ \r
+ if (!prevHover.containsAll(hoverActor) || !hoverActor.containsAll(prevHover)) {\r
+ fireHoverChanged();\r
+ }\r
+ }\r
+ \r
+ public List<vtkProp> getSelectActor() {\r
+ return selectActors;\r
+ }\r
+ \r
+ public List<vtkProp> getHoverActor() {\r
+ return hoverActor;\r
+ }\r
+ \r
+ private List<ISelectionChangedListener> selectionListeners = new ArrayList<ISelectionChangedListener>();\r
+ \r
+ @Override\r
+ public void addSelectionChangedListener(ISelectionChangedListener listener) {\r
+ selectionListeners.add(listener);\r
+ }\r
+ \r
+ @Override\r
+ public ISelection getSelection() {\r
+ return new StructuredSelection(selectActors);\r
+ }\r
+ \r
+ @Override\r
+ public void removeSelectionChangedListener(\r
+ ISelectionChangedListener listener) {\r
+ selectionListeners.remove(listener);\r
+ }\r
+ \r
+ @Override\r
+ public void setSelection(ISelection selection) {\r
+ setSelection(selection, false);\r
+\r
+ }\r
+ \r
+ public void setSelection(ISelection selection, boolean fire) {\r
+ Collection<vtkProp> selectedProps = AdaptationUtils.adaptToCollection(selection, vtkProp.class);\r
+ \r
+ selectActors.clear();\r
+ selectActors.addAll(selectedProps);\r
+ if (fire)\r
+ fireSelectionChanged();\r
+ }\r
+ \r
+ private void fireSelectionChanged() {\r
+ Display.getDefault().asyncExec(new Runnable() {\r
+ @Override\r
+ public void run() {\r
+ \r
+ SelectionChangedEvent evt = new SelectionChangedEvent(vtkCameraAndSelectorAction.this, new StructuredSelection(selectActors));\r
+ for (ISelectionChangedListener l :selectionListeners) {\r
+ l.selectionChanged(evt);\r
+ }\r
+ \r
+ }\r
+ });\r
+ }\r
+ \r
+ \r
+ private List<ISelectionChangedListener> hoverListeners = new ArrayList<ISelectionChangedListener>();\r
+ \r
+ \r
+ public void addHoverChangedListener(ISelectionChangedListener listener) {\r
+ hoverListeners.add(listener);\r
+ }\r
+ \r
+ \r
+ public ISelection getHoverSelection() {\r
+ return new StructuredSelection(hoverActor);\r
+ }\r
+ \r
+ public void removeHoverChangedListener(\r
+ ISelectionChangedListener listener) {\r
+ hoverListeners.remove(listener);\r
+ }\r
+\r
+ private void fireHoverChanged() {\r
+ Display.getDefault().asyncExec(new Runnable() {\r
+ @Override\r
+ public void run() {\r
+ StructuredSelection sel = null;\r
+ if (hoverActor == null)\r
+ sel = new StructuredSelection();\r
+ else\r
+ sel = new StructuredSelection(hoverActor);\r
+ SelectionChangedEvent evt = new SelectionChangedEvent(vtkCameraAndSelectorAction.this, sel);\r
+ for (ISelectionChangedListener l :hoverListeners) {\r
+ l.selectionChanged(evt);\r
+ }\r
+ \r
+ }\r
+ });\r
+ }\r
+ \r
+ \r
+}\r
--- /dev/null
+package org.simantics.g3d.vtk.common;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.HashMap;\r
+import java.util.HashSet;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.Set;\r
+import java.util.Stack;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.Session;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.request.ReadRequest;\r
+import org.simantics.db.common.request.WriteRequest;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.g3d.ontology.G3D;\r
+import org.simantics.g3d.scenegraph.IG3DNode;\r
+import org.simantics.g3d.scenegraph.RenderListener;\r
+import org.simantics.g3d.scenegraph.base.INode;\r
+import org.simantics.g3d.scenegraph.base.NodeListener;\r
+import org.simantics.g3d.scenegraph.base.ParentNode;\r
+import org.simantics.objmap.graph.IMapping;\r
+import org.simantics.objmap.graph.IMappingListener;\r
+import org.simantics.utils.datastructures.Callback;\r
+import org.simantics.utils.datastructures.MapList;\r
+import org.simantics.utils.datastructures.MapSet;\r
+import org.simantics.utils.datastructures.Pair;\r
+import org.simantics.utils.ui.ExceptionUtils;\r
+\r
+import vtk.vtkProp;\r
+\r
+public abstract class AbstractVTKNodeMap<E extends INode> implements VTKNodeMap, IMappingListener, RenderListener, NodeListener{\r
+\r
+ private static final boolean DEBUG = false;\r
+ \r
+ protected Session session;\r
+ protected IMapping<Object,E> mapping;\r
+ protected InteractiveVtkPanel panel;\r
+ \r
+ protected MapList<E, vtkProp> nodeToActor = new MapList<E, vtkProp>();\r
+ protected Map<vtkProp,E> actorToNode = new HashMap<vtkProp, E>();\r
+\r
+ protected ParentNode<E> rootNode;\r
+ \r
+ public AbstractVTKNodeMap(Session session, IMapping<Object,E> mapping, InteractiveVtkPanel panel, ParentNode<E> rootNode) {\r
+ this.session = session;\r
+ this.mapping = mapping;\r
+ this.panel = panel;\r
+ this.rootNode = rootNode;\r
+ panel.addListener(this);\r
+ mapping.addMappingListener(this);\r
+ rootNode.addListener(this);\r
+ }\r
+ \r
+ \r
+ protected abstract void addActor(E node);\r
+ protected abstract void removeActor(E node);\r
+ protected abstract void updateActor(E node,Set<String> ids);\r
+ \r
+ public void repaint() {\r
+ panel.repaint();\r
+ }\r
+ \r
+ public void populate() {\r
+ for (E node : rootNode.getNodes()) {\r
+ receiveAdd(node, node.getParentRel(),true);\r
+ }\r
+ repaint();\r
+ }\r
+ \r
+ @Override\r
+ public INode getNode(vtkProp prop) {\r
+ return actorToNode.get(prop);\r
+ }\r
+ \r
+ @SuppressWarnings("unchecked")\r
+ @Override\r
+ public Collection<vtkProp> getRenderObjects(INode node) {\r
+ return nodeToActor.getValues((E)node);\r
+ }\r
+ \r
+ @SuppressWarnings("unchecked")\r
+ @Override\r
+ public ParentNode<IG3DNode> getRootNode() {\r
+ return (ParentNode<IG3DNode>)rootNode;\r
+ }\r
+ \r
+ \r
+ \r
+ @Override\r
+ public boolean isChangeTracking() {\r
+ return changeTracking;\r
+ }\r
+ \r
+ @Override\r
+ public void setChangeTracking(boolean enabled) {\r
+ changeTracking = enabled;\r
+ }\r
+ \r
+ private boolean changeTracking = true;\r
+ \r
+ protected Object syncMutex = new Object(); \r
+ \r
+\r
+ private List<Pair<E,String>> added = new ArrayList<Pair<E,String>>();\r
+ private List<Pair<E,String>> removed = new ArrayList<Pair<E,String>>();\r
+ //private List<Pair<E,String>> updated = new ArrayList<Pair<E,String>>();\r
+ private MapSet<E, String> updated = new MapSet.Hash<E, String>();\r
+\r
+ private boolean rangeModified = false;\r
+ \r
+ @SuppressWarnings("unchecked")\r
+ @Override\r
+ public void updateRenderObjectsFor(INode node) {\r
+ List<vtkProp> toDelete = new ArrayList<vtkProp>();\r
+ for (vtkProp prop : nodeToActor.getValues((E)node)) {\r
+ if (prop.GetVTKId() != 0) {\r
+ panel.GetRenderer().RemoveActor(prop);\r
+ //prop.Delete();\r
+ toDelete.add(prop);\r
+ }\r
+ actorToNode.remove(prop);\r
+ }\r
+ nodeToActor.remove((E)node);\r
+ Collection<vtkProp> coll = getActors((E)node);\r
+ if (coll == null)\r
+ return;\r
+ for (vtkProp prop : coll) {\r
+ nodeToActor.add((E)node,prop);\r
+ actorToNode.put(prop, (E)node);\r
+ toDelete.remove(prop);\r
+ }\r
+ for (vtkProp p : toDelete)\r
+ p.Delete();\r
+ }\r
+ \r
+ protected abstract Collection<vtkProp> getActors(E node);\r
+ \r
+ @SuppressWarnings("unchecked")\r
+ private void receiveAdd(E node, String id, boolean db) {\r
+ if (DEBUG) System.out.println("receiveAdd " + node + " " + id + " " + db);\r
+ synchronized (syncMutex) {\r
+ for (Pair<E, String> n : added) {\r
+ if (n.first.equals(node))\r
+ return;\r
+ }\r
+ if (changeTracking) {\r
+ mapping.rangeModified((E)node.getParent());\r
+ }\r
+ added.add(new Pair<E, String>(node, id));\r
+ rangeModified = true;\r
+ }\r
+ panel.repaint();\r
+ }\r
+ \r
+ @SuppressWarnings("unchecked")\r
+ private void receiveRemove(E node, String id, boolean db) {\r
+ if (DEBUG) System.out.println("receiveRemove " + node + " " + id + " " + db);\r
+ synchronized (syncMutex) {\r
+ for (Pair<E, String> n : removed) {\r
+ if (n.first.equals(node))\r
+ return;\r
+ }\r
+ if (changeTracking && !db)\r
+ mapping.rangeModified((E)node.getParent());\r
+ removed.add(new Pair<E, String>(node, id));\r
+ rangeModified = true;\r
+ }\r
+ panel.repaint();\r
+ }\r
+ \r
+ @SuppressWarnings("unchecked")\r
+ private void receiveUpdate(E node, String id, boolean db) {\r
+ if (DEBUG) System.out.println("receiveUpdate " + node + " " + id + " " + db);\r
+ synchronized (syncMutex) {\r
+// for (Pair<E, String> n : updated) {\r
+// if (n.first.equals(node))\r
+// return;\r
+// }\r
+ if (changeTracking && !db)\r
+ mapping.rangeModified(node);\r
+ //updated.add(new Pair<E, String>(node, id));\r
+ updated.add(node, id);\r
+ rangeModified = true;\r
+ }\r
+ panel.repaint();\r
+ }\r
+ \r
+ private boolean graphUpdates = false;\r
+ private Set<E> graphModified = new HashSet<E>();\r
+ \r
+ private boolean requestCommit = false;\r
+ \r
+ @Override\r
+ public void commit() {\r
+ requestCommit = true;\r
+ }\r
+ \r
+ protected void doCommit() {\r
+ session.asyncRequest(new WriteRequest() {\r
+ \r
+ @Override\r
+ public void perform(WriteGraph graph) throws DatabaseException {\r
+ commit(graph);\r
+ }\r
+ \r
+ }, new Callback<DatabaseException>() {\r
+ \r
+ @Override\r
+ public void run(DatabaseException parameter) {\r
+ if (parameter != null)\r
+ ExceptionUtils.logAndShowError("Cannot commit editor changes", parameter);\r
+ }\r
+ });\r
+ }\r
+ \r
+ protected void commit(WriteGraph graph) throws DatabaseException {\r
+ synchronized(syncMutex) {\r
+ if (DEBUG) System.out.println("Commit");\r
+ graphUpdates = true;\r
+ mapping.updateDomain(graph);\r
+ graphUpdates = false;\r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public void domainModified() {\r
+ if (graphUpdates)\r
+ return;\r
+ if (DEBUG)System.out.println("domainModified");\r
+ session.asyncRequest(new ReadRequest() {\r
+ \r
+ @SuppressWarnings("unchecked")\r
+ @Override\r
+ public void run(ReadGraph graph) throws DatabaseException {\r
+ update(graph);\r
+ }\r
+ });\r
+ \r
+ }\r
+ \r
+ protected void update(ReadGraph graph) throws DatabaseException {\r
+ synchronized (syncMutex) {\r
+ graphUpdates = true;\r
+ for (Object domainObject : mapping.getDomainModified()) {\r
+ E rangeObject = mapping.get(domainObject);\r
+ if (rangeObject != null)\r
+ graphModified.add(rangeObject);\r
+ }\r
+ mapping.updateRange(graph);\r
+ graphModified.clear();\r
+ graphUpdates = false;\r
+ }\r
+ \r
+ if (mapping.isRangeModified())\r
+ commit();\r
+ }\r
+ \r
+ @Override\r
+ public void rangeModified() {\r
+ //System.out.println("rangeModified");\r
+\r
+ }\r
+ \r
+ @Override\r
+ public void postRender() {\r
+ // Commit changes if\r
+ // 1. Commit has been requested\r
+ // 2. There are no pending changes that should be processed in preRender() \r
+ if (requestCommit && !rangeModified) { // FIXME : not thread safe.\r
+ requestCommit = false;\r
+ doCommit();\r
+ }\r
+ }\r
+ \r
+ List<Pair<E, String>> rem = new ArrayList<Pair<E,String>>();\r
+ List<Pair<E, String>> add = new ArrayList<Pair<E,String>>();\r
+ MapSet<E, String> mod = new MapSet.Hash<E, String>();\r
+ Set<E> propagation = new HashSet<E>();\r
+ Stack<E> stack = new Stack<E>();\r
+ \r
+ \r
+ @Override\r
+ public synchronized void preRender() {\r
+ updateCycle();\r
+ }\r
+ \r
+ @SuppressWarnings("unchecked")\r
+ protected void updateCycle() {\r
+ rem.clear();\r
+ add.clear();\r
+ mod.clear();\r
+ propagation.clear();\r
+ \r
+ synchronized (syncMutex) {\r
+ rem.addAll(removed);\r
+ add.addAll(added);\r
+ for (E e : updated.getKeys()) {\r
+ for (String s : updated.getValues(e)) {\r
+ mod.add(e, s);\r
+ }\r
+ }\r
+ \r
+ removed.clear();\r
+ added.clear();\r
+ updated.clear();\r
+ }\r
+ \r
+ for (Pair<E, String> n : rem) {\r
+ stopListening(n.first);\r
+ removeActor(n.first);\r
+ \r
+ }\r
+ \r
+ for (Pair<E, String> n : add) {\r
+ addActor(n.first);\r
+ listen(n.first);\r
+ }\r
+ \r
+ for (E e : mod.getKeys()) {\r
+ Set<String> ids = mod.getValues(e);\r
+ if (ids.contains(G3D.URIs.hasPosition) || ids.contains(G3D.URIs.hasOrientation)) {\r
+ if (!propagation.contains(e))\r
+ propagation.add(e);\r
+ }\r
+ }\r
+\r
+ if (propagation.size() > 0) {\r
+ stack.clear();\r
+ stack.addAll(propagation);\r
+ propagation.clear();\r
+ while (!stack.isEmpty()) {\r
+ E node = stack.pop();\r
+ if (propagation.contains(node))\r
+ continue;\r
+ propagation.add(node);\r
+ for (NodeListener l : node.getListeners()) {\r
+ if (l == this) {\r
+ //changeTracking = false;\r
+ //l.propertyChanged(node, G3D.URIs.hasPosition);\r
+ //changeTracking = true;\r
+ } else {\r
+ l.propertyChanged(node, G3D.URIs.hasWorldPosition);\r
+ }\r
+ }\r
+ if (node instanceof ParentNode) {\r
+ stack.addAll(((ParentNode<E>)node).getNodes());\r
+ }\r
+ }\r
+ }\r
+ \r
+// synchronized (syncMutex) {\r
+// rem.addAll(removed);\r
+// add.addAll(added);\r
+// //mod.addAll(updated);\r
+// for (E e : updated.getKeys()) {\r
+// for (String s : updated.getValues(e))\r
+// mod.add(e, s);\r
+// }\r
+// \r
+// removed.clear();\r
+// added.clear();\r
+// updated.clear();\r
+// }\r
+ \r
+ for (E e : mod.getKeys()) {\r
+ Set<String> ids = mod.getValues(e);\r
+ updateActor(e,ids);\r
+ }\r
+ \r
+ \r
+ for (Pair<E, String> n : rem) {\r
+ for (NodeListener l : nodeListeners)\r
+ l.nodeRemoved(null, n.first, n.second);\r
+ }\r
+ for (Pair<E, String> n : add) {\r
+ for (NodeListener l : nodeListeners)\r
+ l.nodeAdded(n.first.getParent(), n.first, n.second);\r
+ }\r
+// for (Pair<E, String> n : mod) {\r
+// for (NodeListener l : nodeListeners)\r
+// l.propertyChanged(n.first, n.second);\r
+// }\r
+ for (E e : mod.getKeys()) {\r
+ for (NodeListener l : nodeListeners)\r
+ for (String s : mod.getValues(e))\r
+ l.propertyChanged(e, s);\r
+ }\r
+ synchronized (syncMutex) {\r
+ if (added.isEmpty() && removed.isEmpty() && updated.getKeys().size() == 0)\r
+ rangeModified = false;\r
+ }\r
+ }\r
+ \r
+ @SuppressWarnings("unchecked")\r
+ private void listen(INode node) {\r
+ node.addListener(this);\r
+ if (node instanceof ParentNode<?>) {\r
+ ParentNode<INode> parentNode = (ParentNode<INode>)node;\r
+ for (INode n : parentNode.getNodes())\r
+ listen(n);\r
+ }\r
+ }\r
+ \r
+ private void stopListening(INode node) {\r
+ node.removeListener(this);\r
+ if (node instanceof ParentNode<?>) {\r
+ @SuppressWarnings("unchecked")\r
+ ParentNode<INode> parentNode = (ParentNode<INode>)node;\r
+ for (INode n : parentNode.getNodes())\r
+ stopListening(n);\r
+ }\r
+ }\r
+ \r
+ @SuppressWarnings("unchecked")\r
+ @Override\r
+ public void propertyChanged(INode node, String id) {\r
+ //receiveUpdate((E)node, id, graphUpdates);\r
+ receiveUpdate((E)node, id, graphModified.contains(node));\r
+ \r
+ }\r
+ \r
+ @SuppressWarnings("unchecked")\r
+ @Override\r
+ public <T extends INode> void nodeAdded(ParentNode<T> node, INode child,\r
+ String rel) {\r
+ if (DEBUG) System.out.println("Node added " + child + " parent " + node);\r
+ //receiveAdd((E)child, rel ,graphUpdates);\r
+ receiveAdd((E)child, rel ,graphModified.contains(node));\r
+ \r
+ }\r
+ \r
+ @SuppressWarnings("unchecked")\r
+ @Override\r
+ public <T extends INode> void nodeRemoved(ParentNode<T> node, INode child,\r
+ String rel) {\r
+ if (DEBUG) System.out.println("Node removed " + child + " parent " + node);\r
+ //receiveRemove((E)child, rel, graphUpdates);\r
+ receiveRemove((E)child, rel, graphModified.contains(node));\r
+ \r
+ //FIXME : sometimes removed structural models cause ObjMap to add their children again.\r
+ // removing the listener here prevents corruption of visual model, but better fix is needed.\r
+ stopListening(child);\r
+ }\r
+ \r
+ @Override\r
+ public void delete() {\r
+ changeTracking = false;\r
+ panel.removeListener(this);\r
+ mapping.removeMappingListener(this);\r
+\r
+ List<E> nodes = new ArrayList<E>(nodeToActor.getKeySize());\r
+ nodes.addAll(nodeToActor.getKeys());\r
+ for (E node : nodes) {\r
+ node.removeListener(this);\r
+ removeActor(node);\r
+ node.cleanup();\r
+ }\r
+ for (vtkProp prop : actorToNode.keySet()) {\r
+ if (prop.GetVTKId() != 0) \r
+ prop.Delete();\r
+ }\r
+ actorToNode.clear();\r
+ nodeToActor.clear();\r
+ \r
+ }\r
+ \r
+ \r
+ private List<NodeListener> nodeListeners = new ArrayList<NodeListener>();\r
+ @Override\r
+ public void addListener(NodeListener listener) {\r
+ nodeListeners.add(listener);\r
+ \r
+ }\r
+ \r
+ @Override\r
+ public void removeListener(NodeListener listener) {\r
+ nodeListeners.remove(listener);\r
+ \r
+ }\r
+ \r
+ public IMapping<Object,E> getMapping() {\r
+ return mapping;\r
+ }\r
+ \r
+ \r
+}\r
--- /dev/null
+package org.simantics.g3d.vtk.common;\r
+\r
+import org.simantics.g3d.scenegraph.NodeHighlighter.HighlightEventType;\r
+\r
+import vtk.vtkProp;\r
+\r
+public interface ActorHighlighter {\r
+\r
+ public void highlightActor(vtkProp prop, HighlightEventType type);\r
+}\r
--- /dev/null
+package org.simantics.g3d.vtk.common;\r
+\r
+import org.eclipse.jface.viewers.ISelection;\r
+import org.simantics.g3d.scenegraph.IG3DNode;\r
+import org.simantics.g3d.scenegraph.NodeHighlighter;\r
+import org.simantics.g3d.scenegraph.NodeHighlighter.HighlightEventType;\r
+\r
+import vtk.vtkPanel;\r
+\r
+public class HoverHighlighter extends SelectionHighlighter {\r
+\r
+\r
+ public HoverHighlighter(vtkPanel panel, VTKNodeMap nodeMap) {\r
+ super(panel, nodeMap);\r
+ \r
+ }\r
+ \r
+ protected void highlight(ISelection s) {\r
+ highlight(s, HighlightEventType.Hover, HighlightEventType.ClearHover);\r
+ }\r
+ \r
+ protected void hilight(IG3DNode node, HighlightEventType type) {\r
+ if (node instanceof NodeHighlighter) {\r
+ ((NodeHighlighter)node).highlight(type);\r
+ return;\r
+ }\r
+ if (type == HighlightEventType.Hover) {\r
+ setSelectedColor(node);\r
+ } else if (type == HighlightEventType.ClearHover) {\r
+ setDefaultColor(node);\r
+ }\r
+ }\r
+\r
+ protected void setDefaultColor(IG3DNode node) {\r
+ double color[] = new double[]{0,0,0};\r
+ setColor(node, true, color);\r
+ }\r
+ \r
+ protected void setSelectedColor(IG3DNode node) {\r
+ double color[] = new double[]{1,0,1};\r
+ setColor(node, true, color);\r
+ }\r
+ \r
+}\r
--- /dev/null
+package org.simantics.g3d.vtk.common;\r
+\r
+import java.awt.event.KeyEvent;\r
+import java.awt.event.MouseEvent;\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import org.simantics.g3d.scenegraph.RenderListener;\r
+import org.simantics.g3d.vtk.action.vtkAction;\r
+\r
+import vtk.vtkAbstractPicker;\r
+import vtk.vtkAreaPicker;\r
+import vtk.vtkAssemblyNode;\r
+import vtk.vtkAssemblyPath;\r
+import vtk.vtkCellPicker;\r
+import vtk.vtkGenericRenderWindowInteractor;\r
+import vtk.vtkInteractorStyleTrackballCamera;\r
+import vtk.vtkObjectBase;\r
+import vtk.vtkPanel;\r
+import vtk.vtkPointPicker;\r
+import vtk.vtkProp;\r
+import vtk.vtkProp3DCollection;\r
+import vtk.vtkPropCollection;\r
+import vtk.vtkPropPicker;\r
+import vtk.vtkScenePicker;\r
+\r
+public class InteractiveVtkPanel extends vtkPanel {\r
+ \r
+ protected vtkGenericRenderWindowInteractor iren;\r
+ \r
+\r
+ public vtkGenericRenderWindowInteractor getRenderWindowInteractor() {\r
+ return this.iren;\r
+ }\r
+ private static final long serialVersionUID = 2815073937537950615L;\r
+ \r
+ \r
+ public InteractiveVtkPanel() {\r
+ super();\r
+ iren = new vtkGenericRenderWindowInteractor();\r
+ iren.SetRenderWindow(rw);\r
+ iren.TimerEventResetsTimerOff();\r
+ iren.SetSize(200, 200);\r
+ iren.ConfigureEvent();\r
+ vtkInteractorStyleTrackballCamera style = new vtkInteractorStyleTrackballCamera();\r
+ iren.SetInteractorStyle(style);\r
+ addDeletable(style);\r
+ addDeletable(iren);\r
+ }\r
+ \r
+ @Override\r
+ public void mouseClicked(MouseEvent e) {\r
+\r
+ }\r
+ \r
+ @Override\r
+ public void mouseMoved(MouseEvent e) {\r
+\r
+ }\r
+ \r
+ @Override\r
+ public void mouseEntered(MouseEvent e) {\r
+ super.mouseEntered(e);\r
+ }\r
+ \r
+ @Override\r
+ public void mouseExited(MouseEvent e) {\r
+ \r
+ }\r
+ \r
+ @Override\r
+ public void mousePressed(MouseEvent e) {\r
+ \r
+ }\r
+ \r
+ @Override\r
+ public void mouseDragged(MouseEvent e) {\r
+ \r
+ }\r
+ \r
+ @Override\r
+ public void mouseReleased(MouseEvent e) {\r
+ \r
+ }\r
+ \r
+ @Override\r
+ public void keyPressed(KeyEvent e) {\r
+\r
+ }\r
+ \r
+ @Override\r
+ public void keyTyped(KeyEvent e) {\r
+ \r
+ }\r
+ \r
+ public void setSize(int x, int y) {\r
+ if (windowset == 1) {\r
+ Lock();\r
+ rw.SetSize(x, y);\r
+ iren.SetSize(x, y);\r
+ iren.ConfigureEvent();\r
+ UnLock();\r
+ }\r
+ }\r
+\r
+ private vtkScenePicker scenePicker;\r
+ \r
+ int pickType = 4;\r
+ \r
+ public int getPickType() {\r
+ return pickType;\r
+ }\r
+ \r
+ public void setPickType(int pickType) {\r
+ this.pickType = pickType;\r
+ }\r
+ \r
+ public vtkProp[] pick(int x, int y) {\r
+ \r
+ \r
+// vtkPicker picker = new vtkPicker();\r
+// vtkAbstractPicker picker = new vtkAbstractPicker();\r
+// picker.Pick(x, rw.GetSize()[1] - y, ren);\r
+// // see page 60 of VTK user's guide\r
+//\r
+ if (pickType == 0) {\r
+ \r
+ vtkPropPicker picker = new vtkPropPicker();\r
+ Lock();\r
+ picker.PickProp(x, rw.GetSize()[1] - y, ren);\r
+ \r
+ UnLock();\r
+ \r
+ vtkAssemblyPath apath = picker.GetPath();\r
+ return processPick(picker, apath);\r
+ \r
+ } else if (pickType == 1) {\r
+ if (scenePicker == null) {\r
+ scenePicker = new vtkScenePicker();\r
+ scenePicker.SetRenderer(ren);\r
+ scenePicker.EnableVertexPickingOn();\r
+ \r
+ }\r
+ Lock();\r
+\r
+ vtkAssemblyPath apath = ren.PickProp(x, rw.GetSize()[1] - y);\r
+ //int vertexId = scenePicker.GetVertexId(new int[]{x, rw.GetSize()[1] - y});\r
+ \r
+ UnLock();\r
+ \r
+ if (apath != null) {\r
+ apath.InitTraversal();\r
+// System.out.println("Pick, actors " + apath.GetNumberOfItems() );\r
+// for (int i = 0; i < apath.GetNumberOfItems(); i++) {\r
+// vtkAssemblyNode node = apath.GetNextNode();\r
+// vtkProp test = (vtkProp) node.GetViewProp();\r
+// System.out.println(test.GetClassName());\r
+// }\r
+ \r
+ vtkAssemblyNode node = apath.GetLastNode();\r
+ vtkProp test = (vtkProp) node.GetViewProp();\r
+ apath.Delete();\r
+ node.Delete();\r
+ return new vtkProp[]{test};\r
+ \r
+ }\r
+ \r
+ } else if (pickType == 2) {\r
+ vtkPointPicker picker = new vtkPointPicker();\r
+ picker.SetTolerance(2.0/(double)rw.GetSize()[0]);\r
+ Lock();\r
+ picker.Pick(new double[]{x, rw.GetSize()[1] - y,0}, ren);\r
+ UnLock();\r
+ \r
+ vtkAssemblyPath apath = picker.GetPath();\r
+ return processPick(picker, apath);\r
+ } else if (pickType == 3) {\r
+ vtkAreaPicker picker = new vtkAreaPicker();\r
+ Lock();\r
+ picker.Pick(new double[]{x, rw.GetSize()[1] - y,0}, ren);\r
+ //picker.AreaPick(x-1, rw.GetSize()[1] - y-1,x+1,rw.GetSize()[1] - y+1, ren);\r
+ UnLock();\r
+ vtkAssemblyPath apath = picker.GetPath();\r
+ return processPick(picker, apath);\r
+ } else if (pickType == 4) {\r
+ vtkCellPicker picker = new vtkCellPicker();\r
+ picker.SetTolerance(2.0/(double)rw.GetSize()[0]);\r
+ Lock();\r
+ picker.Pick(new double[]{x, rw.GetSize()[1] - y,0}, ren);\r
+ UnLock(); \r
+ vtkAssemblyPath apath = picker.GetPath();\r
+ return processPick(picker, apath);\r
+ }\r
+\r
+ return null;\r
+ }\r
+ \r
+ public vtkProp[] pick2(int x, int y) {\r
+ \r
+ \r
+// vtkPicker picker = new vtkPicker();\r
+// vtkAbstractPicker picker = new vtkAbstractPicker();\r
+// picker.Pick(x, rw.GetSize()[1] - y, ren);\r
+// // see page 60 of VTK user's guide\r
+//\r
+ if (pickType == 0) {\r
+ \r
+ vtkPropPicker picker = new vtkPropPicker();\r
+ Lock();\r
+ picker.PickProp(x, rw.GetSize()[1] - y, ren);\r
+ \r
+ UnLock();\r
+ vtkPropCollection coll = picker.GetPickList();\r
+ return processPick(picker, coll);\r
+ \r
+ } else if (pickType == 1) {\r
+ if (scenePicker == null) {\r
+ scenePicker = new vtkScenePicker();\r
+ scenePicker.SetRenderer(ren);\r
+ scenePicker.EnableVertexPickingOn();\r
+ \r
+ }\r
+ Lock();\r
+\r
+ \r
+ vtkAssemblyPath apath = ren.PickProp(x, rw.GetSize()[1] - y);\r
+ \r
+ UnLock();\r
+ \r
+ if (apath != null) {\r
+ apath.InitTraversal();\r
+\r
+ \r
+ vtkAssemblyNode node = apath.GetLastNode();\r
+ vtkProp test = (vtkProp) node.GetViewProp();\r
+ apath.Delete();\r
+ node.Delete();\r
+ return new vtkProp[]{test};\r
+ \r
+ }\r
+ \r
+ } else if (pickType == 2) {\r
+ vtkPointPicker picker = new vtkPointPicker();\r
+ picker.SetTolerance(2.0/(double)rw.GetSize()[0]);\r
+ Lock();\r
+ picker.Pick(new double[]{x, rw.GetSize()[1] - y,0}, ren);\r
+ UnLock();\r
+ vtkProp3DCollection coll = picker.GetProp3Ds();\r
+ return processPick(picker, coll);\r
+ } else if (pickType == 3) {\r
+ vtkAreaPicker picker = new vtkAreaPicker();\r
+ Lock();\r
+ picker.Pick(new double[]{x, rw.GetSize()[1] - y,0}, ren);\r
+ //picker.AreaPick(x-1, rw.GetSize()[1] - y-1,x+1,rw.GetSize()[1] - y+1, ren);\r
+ UnLock();\r
+ vtkProp3DCollection coll = picker.GetProp3Ds();\r
+ return processPick(picker, coll);\r
+ } else if (pickType == 4) {\r
+ vtkCellPicker picker = new vtkCellPicker();\r
+ picker.SetTolerance(2.0/(double)rw.GetSize()[0]);\r
+ Lock();\r
+ picker.Pick(new double[]{x, rw.GetSize()[1] - y,0}, ren);\r
+ UnLock(); \r
+ vtkProp3DCollection coll = picker.GetProp3Ds();\r
+ return processPick(picker, coll);\r
+ }\r
+\r
+ return null;\r
+ }\r
+ \r
+ private vtkProp[] processPick(vtkAbstractPicker picker, vtkAssemblyPath apath) {\r
+// double[] pickPos = picker.GetPickPosition();\r
+ picker.Delete();\r
+ if (apath != null) {\r
+ apath.InitTraversal();\r
+ vtkProp result[] = new vtkProp[apath.GetNumberOfItems()];\r
+ for (int i = apath.GetNumberOfItems()-1; i >= 0; i--) {\r
+ vtkAssemblyNode node = apath.GetNextNode();\r
+ vtkProp test = (vtkProp) node.GetViewProp();\r
+// System.out.println("Picked: " + test.GetClassName() + " " + test.GetVTKId());\r
+ result[i] = test;\r
+ node.Delete();\r
+ }\r
+ apath.Delete();\r
+ return result;\r
+\r
+ }\r
+ return null;\r
+ }\r
+ \r
+ private vtkProp[] processPick(vtkAbstractPicker picker, vtkPropCollection coll) {\r
+// double[] pickPos = picker.GetPickPosition();\r
+ picker.Delete();\r
+ if (coll != null) {\r
+ coll.InitTraversal();\r
+ vtkProp result[] = new vtkProp[coll.GetNumberOfItems()];\r
+ for (int i = coll.GetNumberOfItems()-1; i >= 0; i--) {\r
+ vtkProp test = coll.GetNextProp();\r
+ \r
+// System.out.println("Picked: " + test.GetClassName() + " " + test.GetVTKId());\r
+ result[i] = test;\r
+ \r
+ }\r
+ coll.Delete();\r
+ return result;\r
+\r
+ }\r
+ return null;\r
+ }\r
+ \r
+ \r
+ private vtkAction defaultAction;\r
+ private vtkAction currentAction;\r
+ \r
+ public void setActiveAction(vtkAction action) {\r
+ if (action.equals(currentAction))\r
+ return;\r
+ if (currentAction != null)\r
+ currentAction.deattach();\r
+ currentAction = action;\r
+ if (action != null)\r
+ action.attach();\r
+ }\r
+ \r
+ public void setDefaultAction(vtkAction defaultAction) {\r
+ this.defaultAction = defaultAction;\r
+ }\r
+ \r
+ public void useDefaultAction() {\r
+ setActiveAction(defaultAction);\r
+ }\r
+ \r
+ public vtkAction getDefaultAction() {\r
+ return defaultAction;\r
+ }\r
+ \r
+ \r
+ @Override\r
+ public synchronized void Render() {\r
+ //System.out.println("Render " + rendering);\r
+ if (rendering)\r
+ return;\r
+ \r
+ firePreRender();\r
+ super.Render();\r
+ firePostRender();\r
+ }\r
+ \r
+ \r
+ public void addListener(RenderListener l) {\r
+ listeners.add(l);\r
+ }\r
+ \r
+ public void removeListener(RenderListener l) {\r
+ listeners.remove(l);\r
+ }\r
+ \r
+ private List<RenderListener> listeners = new ArrayList<RenderListener>();\r
+ \r
+ List<RenderListener> list = new ArrayList<RenderListener>();\r
+ \r
+ private void firePreRender() {\r
+ if (listeners.size() > 0) {\r
+ list.addAll(listeners);\r
+ for (RenderListener l : list)\r
+ l.preRender();\r
+ list.clear();\r
+ }\r
+ }\r
+ \r
+ private void firePostRender() {\r
+ if (listeners.size() > 0) {\r
+ list.addAll(listeners);\r
+ for (RenderListener l : list)\r
+ l.postRender();\r
+ list.clear();\r
+ }\r
+ }\r
+\r
+ \r
+ private List<vtkObjectBase> deletable = new ArrayList<vtkObjectBase>();\r
+ \r
+ public void addDeletable(vtkObjectBase o) {\r
+ deletable.add(o);\r
+ }\r
+ \r
+ public void removeDeletable (vtkObjectBase o) {\r
+ deletable.remove(o);\r
+ }\r
+ \r
+ @Override\r
+ public void Delete() {\r
+ for (vtkObjectBase o : deletable) {\r
+ if (o.GetVTKId() != 0) {\r
+ o.Delete();\r
+ }\r
+ }\r
+ deletable.clear();\r
+ \r
+ super.Delete();\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.g3d.vtk.common;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.List;\r
+\r
+import org.eclipse.jface.viewers.ISelection;\r
+import org.eclipse.jface.viewers.ISelectionChangedListener;\r
+import org.eclipse.jface.viewers.ISelectionProvider;\r
+import org.eclipse.jface.viewers.SelectionChangedEvent;\r
+import org.eclipse.jface.viewers.StructuredSelection;\r
+import org.eclipse.ui.IEditorPart;\r
+import org.eclipse.ui.ISelectionListener;\r
+import org.eclipse.ui.IWorkbenchPart;\r
+import org.simantics.db.Resource;\r
+import org.simantics.g3d.scenegraph.IG3DNode;\r
+import org.simantics.g3d.scenegraph.base.INode;\r
+import org.simantics.g3d.tools.AdaptationUtils;\r
+import org.simantics.objmap.graph.IMapping;\r
+import org.simantics.objmap.structural.StructuralResource;\r
+\r
+import vtk.vtkProp;\r
+\r
+public class NodeSelectionProvider2<DBObject,JavaObject> implements ISelectionProvider, ISelectionChangedListener, ISelectionListener{\r
+ private ISelection selection = new StructuredSelection();\r
+ private List<ISelectionChangedListener> listeners = new ArrayList<ISelectionChangedListener>();\r
+ \r
+ List<IG3DNode> selectedNodes = new ArrayList<IG3DNode>(); // selection is ordered\r
+ //List<Resource> selectedResources = new ArrayList<Resource>();\r
+ List<VTKSelectionItem<DBObject>> selectedItems = new ArrayList<VTKSelectionItem<DBObject>>();\r
+ \r
+ IEditorPart part;\r
+ IMapping<DBObject,JavaObject> mapping;\r
+ VTKNodeMap nodeMap;\r
+ \r
+ public NodeSelectionProvider2(IEditorPart part, IMapping<DBObject,JavaObject> mapping, VTKNodeMap nodeMap) {\r
+ this.part = part;\r
+ this.mapping = mapping;\r
+ this.nodeMap = nodeMap;\r
+ }\r
+ \r
+ @Override\r
+ public void addSelectionChangedListener(\r
+ ISelectionChangedListener listener) {\r
+ listeners.add(listener);\r
+ }\r
+ \r
+ @Override\r
+ public void removeSelectionChangedListener(\r
+ ISelectionChangedListener listener) {\r
+ listeners.remove(listener);\r
+ }\r
+ \r
+ @Override\r
+ public ISelection getSelection() {\r
+ return selection;\r
+ }\r
+ \r
+ @Override\r
+ public void setSelection(ISelection selection) {\r
+ \r
+ }\r
+ \r
+ // events coming from vtk \r
+ @Override\r
+ public void selectionChanged(SelectionChangedEvent event) {\r
+ ISelection s = event.getSelection();\r
+ \r
+ processSelection(s);\r
+ fireSelectionChanged(event.getSource());\r
+ }\r
+ \r
+ @SuppressWarnings("unchecked")\r
+ private void processSelection(ISelection s) {\r
+ selectedNodes.clear();\r
+ selectedItems.clear();\r
+ \r
+ Collection<vtkProp> selectedActors = AdaptationUtils.adaptToCollection(s, vtkProp.class);\r
+ if (selectedActors.size() > 0) {\r
+ for (vtkProp a : selectedActors) {\r
+ IG3DNode node = (IG3DNode)nodeMap.getNode((vtkProp)a);\r
+ if (node == null)\r
+ continue;\r
+ if (!selectedNodes.contains(node))\r
+ selectedNodes.add(node);\r
+ DBObject r = mapping.inverseGet((JavaObject)node);\r
+ selectedItems.add(new VTKSelectionItem<DBObject>(a, node,r));\r
+ }\r
+ } else {\r
+ Collection<IG3DNode> selectedNds = AdaptationUtils.adaptToCollection(s, IG3DNode.class);\r
+ for (INode node : selectedNds) {\r
+ if (!selectedNodes.contains(node))\r
+ selectedNodes.add((IG3DNode)node);\r
+ DBObject r = mapping.inverseGet((JavaObject)node);\r
+ selectedItems.add(new VTKSelectionItem<DBObject>(null, (IG3DNode)node,r));\r
+ }\r
+ }\r
+ \r
+ \r
+ selection = new StructuredSelection(selectedItems);\r
+ }\r
+ \r
+ private void fireSelectionChanged(Object source) {\r
+ SelectionChangedEvent evt = new SelectionChangedEvent((ISelectionProvider)source, selection);\r
+ for (ISelectionChangedListener l : listeners) {\r
+ l.selectionChanged(evt);\r
+ }\r
+ }\r
+ \r
+ \r
+ \r
+ // events coming from workbench\r
+ @Override\r
+ public void selectionChanged(IWorkbenchPart part, ISelection selection) {\r
+ if (part == this.part)\r
+ return;\r
+ processSelection(selection);\r
+ \r
+ }\r
+ \r
+ public List<IG3DNode> getSelectedNodes() {\r
+ return selectedNodes;\r
+ }\r
+ \r
+ @SuppressWarnings("unchecked")\r
+ public List<DBObject> getSelectedResources() {\r
+ \r
+ List<DBObject> list = new ArrayList<DBObject>();\r
+ for (VTKSelectionItem<DBObject> i : selectedItems) {\r
+ DBObject r = (DBObject)i.getAdapter(Resource.class);\r
+ if (r == null)\r
+ r = (DBObject)i.getAdapter(StructuralResource.class);\r
+ if (r == null)\r
+ continue;\r
+ if (!list.contains(r))\r
+ list.add(r);\r
+ }\r
+ return list;\r
+ }\r
+ \r
+ protected INode getNode(DBObject r) {\r
+ return (INode)mapping.get(r);\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.g3d.vtk.common;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.List;\r
+\r
+import org.eclipse.jface.viewers.ISelection;\r
+import org.eclipse.jface.viewers.ISelectionChangedListener;\r
+import org.eclipse.jface.viewers.SelectionChangedEvent;\r
+import org.simantics.g3d.scenegraph.IG3DNode;\r
+import org.simantics.g3d.scenegraph.NodeHighlighter;\r
+import org.simantics.g3d.scenegraph.NodeHighlighter.HighlightEventType;\r
+import org.simantics.g3d.scenegraph.NodeHighlighter.HighlightObjectType;\r
+import org.simantics.g3d.scenegraph.base.INode;\r
+import org.simantics.g3d.tools.AdaptationUtils;\r
+import org.simantics.utils.threads.AWTThread;\r
+import org.simantics.utils.threads.ThreadUtils;\r
+\r
+import vtk.vtkActor;\r
+import vtk.vtkAlgorithm;\r
+import vtk.vtkAlgorithmOutput;\r
+import vtk.vtkFeatureEdges;\r
+import vtk.vtkMapper;\r
+import vtk.vtkPanel;\r
+import vtk.vtkProp;\r
+import vtk.vtkProperty;\r
+\r
+public class SelectionHighlighter implements ISelectionChangedListener{\r
+\r
+ \r
+ \r
+ vtkPanel panel;\r
+ VTKNodeMap nodeMap;\r
+ \r
+ List<IG3DNode> selectedNodes = new ArrayList<IG3DNode>();\r
+ List<vtkActor> selectedActors = new ArrayList<vtkActor>();\r
+ \r
+ HighlightObjectType type = HighlightObjectType.Node;\r
+ \r
+ public SelectionHighlighter(vtkPanel panel, VTKNodeMap nodeMap) {\r
+ this.panel = panel;\r
+ this.nodeMap = nodeMap;\r
+ }\r
+ \r
+ @Override\r
+ public void selectionChanged(SelectionChangedEvent event) {\r
+ final ISelection s = event.getSelection();\r
+ \r
+ if (Thread.currentThread().equals(AWTThread.getThreadAccess().getThread()))\r
+ highlight(s);\r
+ else {\r
+ ThreadUtils.asyncExec(AWTThread.getThreadAccess(), new Runnable() {\r
+ @Override\r
+ public void run() {\r
+ highlight(s);\r
+ //System.out.println(this.getClass().getName() + " highlight ");\r
+ panel.Render();\r
+ //panel.repaint();\r
+ }\r
+ });\r
+ }\r
+ \r
+ }\r
+ \r
+ protected void hilight(IG3DNode node, HighlightEventType type) {\r
+ if (node instanceof NodeHighlighter) {\r
+ ((NodeHighlighter)node).highlight(type);\r
+ return;\r
+ }\r
+ if (type == HighlightEventType.Selection) {\r
+ setSelectedColor(node); \r
+ } else if (type == HighlightEventType.ClearSelection) {\r
+ setDefaultColor(node);\r
+ }\r
+ }\r
+ \r
+ protected void hilight(vtkActor actor, HighlightEventType type) {\r
+ if (type == HighlightEventType.Selection) {\r
+ setColor(actor,false,new double[]{1,0,0});\r
+ setColor(actor,true,new double[]{1,0,1});\r
+ } else if (type == HighlightEventType.ClearSelection) {\r
+ setColor(actor,false,new double[]{1,1,0});\r
+ setColor(actor,true,new double[]{0,0,0});\r
+ }\r
+ }\r
+ \r
+ protected void highlight(ISelection s) {\r
+ highlight(s, HighlightEventType.Selection, HighlightEventType.ClearSelection);\r
+ }\r
+ \r
+ protected void highlight(ISelection s, HighlightEventType apply, HighlightEventType clear) {\r
+ \r
+ boolean changed = false;\r
+ if (type == HighlightObjectType.Node) {\r
+ Collection<IG3DNode> currentSelectedNodes = AdaptationUtils.adaptToCollection(s,IG3DNode.class);//getSelectedNodes(currentSelectedActors);\r
+ if (currentSelectedNodes.size() == 0) {\r
+ Collection<vtkProp> currentSelectedActors = AdaptationUtils.adaptToCollection(s, vtkProp.class);\r
+ currentSelectedNodes = getSelectedNodes(currentSelectedActors);\r
+ }\r
+ for (IG3DNode node : selectedNodes) {\r
+ if (!currentSelectedNodes.contains(node)) {\r
+ hilight(node, clear);\r
+ changed = true;\r
+ }\r
+ }\r
+ for (IG3DNode node : currentSelectedNodes) {\r
+ if (!selectedNodes.contains(node)) {\r
+ hilight(node, apply);\r
+ changed = true;\r
+ }\r
+ }\r
+ selectedNodes.clear();\r
+ selectedNodes.addAll(currentSelectedNodes);\r
+ //selectedNodes = currentSelectedNodes;\r
+ \r
+ } else {\r
+ \r
+ Collection<vtkActor> currentSelectedActors = AdaptationUtils.adaptToCollection(s, vtkActor.class);\r
+ \r
+ for (vtkActor act : selectedActors) {\r
+ if (!currentSelectedActors.contains(act)) {\r
+ hilight(act,clear);\r
+ changed = true;\r
+ }\r
+ }\r
+ for (vtkActor act : currentSelectedActors) {\r
+ if (!selectedActors.contains(act)) {\r
+ hilight(act,apply);\r
+ changed = true;\r
+ }\r
+ }\r
+ selectedActors.clear();\r
+ selectedActors.addAll(currentSelectedActors);\r
+ }\r
+ if (changed) {\r
+ panel.repaint();\r
+ }\r
+ }\r
+ \r
+ protected List<IG3DNode> getSelectedNodes(Collection<vtkProp> selectedActors) {\r
+ List<IG3DNode> currentSelectedNodes = new ArrayList<IG3DNode>();\r
+ \r
+ for (vtkProp a : selectedActors) {\r
+ INode node = nodeMap.getNode((vtkProp)a);\r
+ if (node == null || !(node instanceof IG3DNode))\r
+ continue;\r
+ if (!currentSelectedNodes.contains(node))\r
+ currentSelectedNodes.add((IG3DNode)node);\r
+ }\r
+ return currentSelectedNodes;\r
+ }\r
+ \r
+ protected void setDefaultColor(IG3DNode node) {\r
+ double color[] = new double[]{1,1,0};\r
+ setColor(node, false, color);\r
+ }\r
+ \r
+ protected void setSelectedColor(IG3DNode node) {\r
+ double color[] = new double[]{1,0,0};\r
+ setColor(node, false, color);\r
+ }\r
+ \r
+ \r
+ protected void setColor(IG3DNode node, boolean edge, double color[]) {\r
+ for (vtkProp prop : nodeMap.getRenderObjects(node)) {\r
+ if (prop instanceof vtkActor) {\r
+ vtkActor act = (vtkActor)prop;\r
+ setColor(act, edge, color);\r
+ }\r
+ }\r
+ }\r
+ \r
+ protected void setColor(vtkActor act, boolean edge, double color[]) {\r
+ \r
+ vtkMapper mapper = act.GetMapper();\r
+ vtkAlgorithmOutput out = mapper.GetInputConnection(0, 0);\r
+ vtkAlgorithm producer = out.GetProducer();\r
+ boolean isEdge = (producer instanceof vtkFeatureEdges);\r
+ producer.Delete();\r
+ if (isEdge == edge) {\r
+ vtkProperty property = act.GetProperty();\r
+ property.SetColor(color);\r
+ property.Delete();\r
+ }\r
+ out.Delete();\r
+ mapper.Delete();\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.g3d.vtk.common;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.List;\r
+\r
+import org.eclipse.jface.viewers.ISelection;\r
+import org.eclipse.jface.viewers.ISelectionChangedListener;\r
+import org.eclipse.jface.viewers.SelectionChangedEvent;\r
+import org.eclipse.jface.viewers.StructuredSelection;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.simantics.g3d.scenegraph.IG3DNode;\r
+import org.simantics.g3d.scenegraph.base.INode;\r
+import org.simantics.g3d.scenegraph.base.ParentNode;\r
+import org.simantics.g3d.tools.AdaptationUtils;\r
+import org.simantics.g3d.ui.ScenegraphOutlinePage;\r
+\r
+public class VTKContentOutlinePage<DBObject,JavaObject> extends ScenegraphOutlinePage{\r
+ private NodeSelectionProvider2<DBObject,JavaObject> provider;\r
+ \r
+ public VTKContentOutlinePage(ParentNode<? extends INode> rootNode, NodeSelectionProvider2<DBObject,JavaObject> provider) {\r
+ super(rootNode);\r
+ this.provider = provider;\r
+ }\r
+ \r
+ private boolean outsideSelection = false;\r
+ \r
+ @Override\r
+ public void createControl(Composite parent) {\r
+\r
+ super.createControl(parent);\r
+\r
+ provider.addSelectionChangedListener(new ISelectionChangedListener() {\r
+ \r
+ @Override\r
+ public void selectionChanged(SelectionChangedEvent event) {\r
+ Object source = event.getSource();\r
+ if (source == VTKContentOutlinePage.this)\r
+ return;\r
+ ISelection s = event.getSelection();\r
+ Collection<INode> nodes = AdaptationUtils.adaptToCollection(s, INode.class);\r
+ outsideSelection = true;\r
+ getTreeViewer().setSelection(new StructuredSelection(nodes.toArray()),true);\r
+ outsideSelection = false;\r
+ \r
+ }\r
+ });\r
+ }\r
+ \r
+ List<INode> selectedNodes = new ArrayList<INode>();\r
+ \r
+ @SuppressWarnings("unchecked")\r
+ @Override\r
+ protected void fireSelectionChanged(ISelection selection) {\r
+ if (outsideSelection)\r
+ return;\r
+ // TreeViewer provides selected object in tree order, not in selected order.\r
+ Collection<INode> selectedUnsortedNodes = AdaptationUtils.adaptToCollection(selection, INode.class);\r
+ List<INode> toRemove = new ArrayList<INode>();\r
+ for (INode node : selectedNodes) {\r
+ if (!selectedUnsortedNodes.contains(node))\r
+ toRemove.add(node);\r
+ }\r
+ for (INode node : toRemove)\r
+ selectedNodes.remove(node);\r
+ for (INode node : selectedUnsortedNodes) {\r
+ if (!selectedNodes.contains(node))\r
+ selectedNodes.add(node);\r
+ }\r
+ \r
+ List<VTKSelectionItem<DBObject>> selectedItems = new ArrayList<VTKSelectionItem<DBObject>>();\r
+ for (INode node : selectedNodes) {\r
+ DBObject r = provider.mapping.inverseGet((JavaObject)node);\r
+ selectedItems.add(new VTKSelectionItem<DBObject>(null, (IG3DNode)node, r));\r
+ }\r
+ \r
+ super.fireSelectionChanged(new StructuredSelection(selectedItems));\r
+ }\r
+ \r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.vtk.common;\r
+\r
+import org.simantics.g3d.scenegraph.NodeMap;\r
+\r
+import vtk.vtkProp;\r
+\r
+public interface VTKNodeMap extends NodeMap<vtkProp>{\r
+\r
+ \r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.vtk.common;\r
+\r
+import org.eclipse.core.runtime.IAdaptable;\r
+import org.simantics.db.Resource;\r
+import org.simantics.g3d.scenegraph.IG3DNode;\r
+import org.simantics.g3d.scenegraph.base.INode;\r
+import org.simantics.objmap.structural.StructuralResource;\r
+\r
+import vtk.vtkProp;\r
+\r
+public class VTKSelectionItem<DBObject> implements IAdaptable{\r
+\r
+ private vtkProp prop;\r
+ private IG3DNode node;\r
+ private DBObject resource;\r
+\r
+ //private VTKpropSet actors;\r
+ \r
+ \r
+ public VTKSelectionItem(vtkProp prop, IG3DNode node, DBObject res) {\r
+ this.prop = prop;\r
+ this.node = node;\r
+ this.resource = res;\r
+ }\r
+ \r
+// public VTKSelectionItem(Resource res, Collection<vtkProp> actors) {\r
+// this.resource = res;\r
+// this.actors = new VTKpropSet();\r
+// this.actors.addAll(actors);\r
+// }\r
+// \r
+// public VTKSelectionItem(Resource res, vtkProp... actors) {\r
+// this.resource = res;\r
+// this.actors = new VTKpropSet();\r
+// for (vtkProp a : actors)\r
+// this.actors.add(a);\r
+// }\r
+\r
+ @SuppressWarnings("rawtypes")\r
+ @Override\r
+ public Object getAdapter(Class adapter) {\r
+ if (adapter == Resource.class)\r
+ if (resource instanceof Resource)\r
+ return resource;\r
+ else\r
+ return null;\r
+ if (adapter == StructuralResource.class)\r
+ if (resource instanceof StructuralResource)\r
+ return resource;\r
+ else\r
+ return null;\r
+ if (adapter == vtkProp.class)\r
+ return prop;\r
+ if (adapter == IG3DNode.class)\r
+ return node;\r
+ if (adapter == INode.class)\r
+ return node;\r
+ return null;\r
+ }\r
+ \r
+// @SuppressWarnings("rawtypes")\r
+// @Override\r
+// public Object getAdapter(Class adapter) {\r
+// if (adapter == Resource.class)\r
+// return resource;\r
+// if (adapter == VTKpropSet.class)\r
+// return actors;\r
+// return null;\r
+// }\r
+ \r
+// public Resource getResource() {\r
+// return resource;\r
+// }\r
+// \r
+// public VTKpropSet getActors() {\r
+// return actors;\r
+// }\r
+ \r
+ @SuppressWarnings("rawtypes")\r
+ @Override\r
+ public boolean equals(Object obj) {\r
+ if (obj == null)\r
+ return false;\r
+ if (obj.getClass() != this.getClass())\r
+ return false;\r
+ VTKSelectionItem other = (VTKSelectionItem)obj;\r
+ if (prop != null)\r
+ return prop.equals(other.prop);\r
+ if (node != null)\r
+ return node.equals(other.node);\r
+ return resource.equals(other.resource);\r
+ //return resource.equals(other.resource);\r
+ \r
+ }\r
+}\r
--- /dev/null
+package org.simantics.g3d.vtk.gizmo;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.List;\r
+\r
+import javax.vecmath.Point3d;\r
+\r
+import org.simantics.g3d.vtk.action.RotateAction;\r
+import org.simantics.g3d.vtk.shape.vtkShape;\r
+\r
+import vtk.vtkActor;\r
+import vtk.vtkProp;\r
+\r
+public class RotateAxisGizmo extends vtkGizmo{\r
+ \r
+ private List<vtkProp> parts = new ArrayList<vtkProp>();\r
+ int type = -1;\r
+\r
+ \r
+ @Override\r
+ public Collection<vtkProp> getGizmo() {\r
+ for (vtkProp p : parts)\r
+ p.Delete();\r
+ parts.clear();\r
+ double l = 100;\r
+ double w = 3;\r
+ switch (type) {\r
+ case RotateAction.X:{\r
+ vtkActor lineActorX = vtkShape.createLineActor(new Point3d(-l,0,0), new Point3d(l,0,0));\r
+ lineActorX.GetProperty().SetColor(1, 0, 0);\r
+ lineActorX.GetProperty().SetLineWidth(w);\r
+ lineActorX.GetProperty().Delete();\r
+ parts.add(lineActorX);\r
+ break;\r
+ }\r
+ case RotateAction.Y: {\r
+ vtkActor lineActorY = vtkShape.createLineActor(new Point3d(0,-l,0), new Point3d(0,l,0));\r
+ lineActorY.GetProperty().SetColor(0, 1, 0);\r
+ lineActorY.GetProperty().SetLineWidth(w);\r
+ lineActorY.GetProperty().Delete();\r
+ parts.add(lineActorY);\r
+ break;\r
+ }\r
+ case RotateAction.Z: {\r
+ vtkActor lineActorZ = vtkShape.createLineActor(new Point3d(0,0,-l), new Point3d(0,0,l));\r
+ lineActorZ.GetProperty().SetColor(0, 0, 1);\r
+ lineActorZ.GetProperty().SetLineWidth(w);\r
+ lineActorZ.GetProperty().Delete();\r
+ parts.add(lineActorZ);\r
+ break;\r
+ }\r
+ default: {\r
+ \r
+ }\r
+ }\r
+ return parts;\r
+ }\r
+ \r
+ public void setType(int type) {\r
+ if (this.type == type)\r
+ return;\r
+ this.type = type;\r
+ deattachActors();\r
+ attachActors();\r
+ }\r
+ \r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.vtk.gizmo;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.List;\r
+\r
+import javax.vecmath.Point3d;\r
+\r
+import org.simantics.g3d.vtk.action.TranslateAction;\r
+import org.simantics.g3d.vtk.shape.vtkShape;\r
+\r
+import vtk.vtkActor;\r
+import vtk.vtkProp;\r
+\r
+public class TranslateAxisGizmo extends vtkGizmo{\r
+ \r
+ private List<vtkProp> parts = new ArrayList<vtkProp>();\r
+ int type = -1;\r
+\r
+ \r
+ @Override\r
+ public Collection<vtkProp> getGizmo() {\r
+ for (vtkProp p : parts)\r
+ p.Delete();\r
+ parts.clear();\r
+ double l = 100;\r
+ double w = 3;\r
+ switch (type) {\r
+ case TranslateAction.X:{\r
+ vtkActor lineActorX = vtkShape.createLineActor(new Point3d(-l,0,0), new Point3d(l,0,0));\r
+ lineActorX.GetProperty().SetColor(1, 0, 0);\r
+ lineActorX.GetProperty().SetLineWidth(w);\r
+ lineActorX.GetProperty().Delete();\r
+ parts.add(lineActorX);\r
+ break;\r
+ }\r
+ case TranslateAction.Y: {\r
+ vtkActor lineActorY = vtkShape.createLineActor(new Point3d(0,-l,0), new Point3d(0,l,0));\r
+ lineActorY.GetProperty().SetColor(0, 1, 0);\r
+ lineActorY.GetProperty().SetLineWidth(w);\r
+ lineActorY.GetProperty().Delete();\r
+ parts.add(lineActorY);\r
+ break;\r
+ }\r
+ case TranslateAction.Z: {\r
+ vtkActor lineActorZ = vtkShape.createLineActor(new Point3d(0,0,-l), new Point3d(0,0,l));\r
+ lineActorZ.GetProperty().SetColor(0, 0, 1);\r
+ lineActorZ.GetProperty().SetLineWidth(w);\r
+ lineActorZ.GetProperty().Delete();\r
+ parts.add(lineActorZ);\r
+ break;\r
+ }\r
+ case TranslateAction.XY: {\r
+ vtkActor lineActorX = vtkShape.createLineActor(new Point3d(-l,0,0), new Point3d(l,0,0));\r
+ lineActorX.GetProperty().SetColor(1, 0, 0);\r
+ lineActorX.GetProperty().SetLineWidth(w);\r
+ lineActorX.GetProperty().Delete();\r
+ parts.add(lineActorX);\r
+ vtkActor lineActorY = vtkShape.createLineActor(new Point3d(0,-l,0), new Point3d(0,l,0));\r
+ lineActorY.GetProperty().SetColor(0, 1, 0);\r
+ lineActorY.GetProperty().SetLineWidth(w);\r
+ lineActorY.GetProperty().Delete();\r
+ parts.add(lineActorY);\r
+ break;\r
+ }\r
+ case TranslateAction.XZ: {\r
+ vtkActor lineActorX = vtkShape.createLineActor(new Point3d(-l,0,0), new Point3d(l,0,0));\r
+ lineActorX.GetProperty().SetColor(1, 0, 0);\r
+ lineActorX.GetProperty().Delete();\r
+ parts.add(lineActorX);\r
+ vtkActor lineActorZ = vtkShape.createLineActor(new Point3d(0,0,-l), new Point3d(0,0,l));\r
+ lineActorZ.GetProperty().SetColor(0, 0, 1);\r
+ lineActorZ.GetProperty().Delete();\r
+ parts.add(lineActorZ);\r
+ break;\r
+ }\r
+ case TranslateAction.YZ: {\r
+ vtkActor lineActorY = vtkShape.createLineActor(new Point3d(0,-l,0), new Point3d(0,l,0));\r
+ lineActorY.GetProperty().SetColor(0, 1, 0);\r
+ lineActorY.GetProperty().SetLineWidth(w);\r
+ lineActorY.GetProperty().Delete();\r
+ parts.add(lineActorY);\r
+ vtkActor lineActorZ = vtkShape.createLineActor(new Point3d(0,0,-l), new Point3d(0,0,l));\r
+ lineActorZ.GetProperty().SetColor(0, 0, 1);\r
+ lineActorZ.GetProperty().SetLineWidth(w);\r
+ lineActorZ.GetProperty().Delete();\r
+ parts.add(lineActorZ);\r
+ break;\r
+ }\r
+ default: {\r
+ \r
+ }\r
+ }\r
+ return parts;\r
+ }\r
+ \r
+ public void setType(int type) {\r
+ if (this.type == type)\r
+ return;\r
+ this.type = type;\r
+ if (getRenderer() != null) {\r
+ deattachActors();\r
+ attachActors();\r
+ }\r
+ }\r
+ \r
+ \r
+}\r
--- /dev/null
+package org.simantics.g3d.vtk.gizmo;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.List;\r
+\r
+import vtk.vtkActor;\r
+import vtk.vtkDataSetMapper;\r
+import vtk.vtkPoints;\r
+import vtk.vtkPolyData;\r
+import vtk.vtkProp;\r
+import vtk.vtkTriangle;\r
+\r
+public class TranslateGizmo extends vtkGizmo {\r
+ \r
+ \r
+ \r
+ private List<vtkProp> parts;\r
+ \r
+ @Override\r
+ public Collection<vtkProp> getGizmo() {\r
+ if (parts == null) {\r
+ parts = new ArrayList<vtkProp>();\r
+ \r
+ \r
+ float size = 2.f; \r
+ float sizeD2 = 1.f;\r
+ float offset = 0.2f;\r
+ \r
+ double[] colorX = new double[]{0.5,0.0,0.0};\r
+ double[] colorY = new double[]{0.0,0.5,0.0};\r
+ double[] colorZ = new double[]{0.0,0.0,0.5};\r
+ \r
+ double[] colorXY = add(colorX, colorY);\r
+ double[] colorXZ = add(colorX, colorZ);\r
+ double[] colorYZ = add(colorY, colorZ);\r
+ double[] colorP = add(colorX,colorY,colorZ);\r
+ \r
+ vtkActor actorX = new vtkActor();\r
+ vtkActor actorY = new vtkActor();\r
+ vtkActor actorZ = new vtkActor();\r
+ vtkActor actorXY = new vtkActor();\r
+ vtkActor actorXZ = new vtkActor();\r
+ vtkActor actorYZ = new vtkActor();\r
+ vtkActor actorP = new vtkActor();\r
+ \r
+ actorX.GetProperty().SetColor(colorX);\r
+ actorY.GetProperty().SetColor(colorY);\r
+ actorZ.GetProperty().SetColor(colorZ);\r
+ actorXY.GetProperty().SetColor(colorXY);\r
+ actorXZ.GetProperty().SetColor(colorXZ);\r
+ actorYZ.GetProperty().SetColor(colorYZ);\r
+ actorP.GetProperty().SetColor(colorP);\r
+ \r
+ actorX.GetProperty().SetOpacity(0.5);\r
+ actorY.GetProperty().SetOpacity(0.5);\r
+ actorZ.GetProperty().SetOpacity(0.5);\r
+ actorXY.GetProperty().SetOpacity(0.5);\r
+ actorXZ.GetProperty().SetOpacity(0.5);\r
+ actorYZ.GetProperty().SetOpacity(0.5);\r
+ actorP.GetProperty().SetOpacity(0.5);\r
+ \r
+ actorX.GetProperty().BackfaceCullingOff();\r
+ actorY.GetProperty().BackfaceCullingOff();\r
+ actorZ.GetProperty().BackfaceCullingOff();\r
+ actorXY.GetProperty().BackfaceCullingOff();\r
+ actorXZ.GetProperty().BackfaceCullingOff();\r
+ actorYZ.GetProperty().BackfaceCullingOff();\r
+ actorP.GetProperty().BackfaceCullingOff();\r
+ \r
+ actorX.SetPickable(1);\r
+ actorY.SetPickable(1);\r
+ actorZ.SetPickable(1);\r
+ actorXY.SetPickable(1);\r
+ actorXZ.SetPickable(1);\r
+ actorYZ.SetPickable(1);\r
+ actorP.SetPickable(1);\r
+ \r
+ \r
+ actorX.GetProperty().LightingOff();\r
+ actorY.GetProperty().LightingOff();\r
+ actorZ.GetProperty().LightingOff();\r
+ actorXY.GetProperty().LightingOff();\r
+ actorXZ.GetProperty().LightingOff();\r
+ actorYZ.GetProperty().LightingOff();\r
+ actorP.GetProperty().LightingOff();\r
+ \r
+\r
+ vtkTriangle triangle = new vtkTriangle();\r
+ \r
+ // X\r
+ vtkPolyData actorXData = new vtkPolyData();\r
+ actorXData.Allocate(6, 6);\r
+ \r
+ triangle.GetPointIds().SetId(0, 0);\r
+ triangle.GetPointIds().SetId(1, 1);\r
+ triangle.GetPointIds().SetId(2, 3);\r
+ actorXData.InsertNextCell(triangle.GetCellType(), triangle.GetPointIds());\r
+ triangle.GetPointIds().SetId(0, 1);\r
+ triangle.GetPointIds().SetId(1, 2);\r
+ triangle.GetPointIds().SetId(2, 3);\r
+ actorXData.InsertNextCell(triangle.GetCellType(), triangle.GetPointIds());\r
+ triangle.GetPointIds().SetId(0, 0);\r
+ triangle.GetPointIds().SetId(1, 3);\r
+ triangle.GetPointIds().SetId(2, 5);\r
+ actorXData.InsertNextCell(triangle.GetCellType(), triangle.GetPointIds());\r
+ triangle.GetPointIds().SetId(0, 3);\r
+ triangle.GetPointIds().SetId(1, 4);\r
+ triangle.GetPointIds().SetId(2, 5);\r
+ actorXData.InsertNextCell(triangle.GetCellType(), triangle.GetPointIds());\r
+ \r
+ vtkPoints partPoints = new vtkPoints();\r
+ partPoints.InsertPoint(0, new double[]{size,0.,0.});\r
+ partPoints.InsertPoint(1, new double[]{size-offset,offset,0.});\r
+ partPoints.InsertPoint(2, new double[]{sizeD2-offset,offset,0.});\r
+ partPoints.InsertPoint(3, new double[]{sizeD2,0.,0.});\r
+ partPoints.InsertPoint(4, new double[]{sizeD2-offset,0.,offset});\r
+ partPoints.InsertPoint(5, new double[]{size-offset,0.,offset});\r
+ actorXData.SetPoints(partPoints);\r
+ partPoints.Delete();\r
+ \r
+ // Y\r
+ vtkPolyData actorYData = new vtkPolyData();\r
+ actorYData.Allocate(6, 6);\r
+ \r
+ triangle.GetPointIds().SetId(0, 0);\r
+ triangle.GetPointIds().SetId(1, 1);\r
+ triangle.GetPointIds().SetId(2, 3);\r
+ actorYData.InsertNextCell(triangle.GetCellType(), triangle.GetPointIds());\r
+ triangle.GetPointIds().SetId(0, 1);\r
+ triangle.GetPointIds().SetId(1, 2);\r
+ triangle.GetPointIds().SetId(2, 3);\r
+ actorYData.InsertNextCell(triangle.GetCellType(), triangle.GetPointIds());\r
+ triangle.GetPointIds().SetId(0, 0);\r
+ triangle.GetPointIds().SetId(1, 3);\r
+ triangle.GetPointIds().SetId(2, 5);\r
+ actorYData.InsertNextCell(triangle.GetCellType(), triangle.GetPointIds());\r
+ triangle.GetPointIds().SetId(0, 3);\r
+ triangle.GetPointIds().SetId(1, 4);\r
+ triangle.GetPointIds().SetId(2, 5);\r
+ actorYData.InsertNextCell(triangle.GetCellType(), triangle.GetPointIds());\r
+ \r
+ partPoints = new vtkPoints();\r
+ partPoints.InsertPoint(0, new double[]{0., size, 0.});\r
+ partPoints.InsertPoint(1, new double[]{offset, size - offset, 0.});\r
+ partPoints.InsertPoint(2, new double[]{offset, sizeD2 - offset, 0.});\r
+ partPoints.InsertPoint(3, new double[]{0., sizeD2, 0.});\r
+ partPoints.InsertPoint(4, new double[]{0., sizeD2 - offset, offset});\r
+ partPoints.InsertPoint(5, new double[]{0., size - offset, offset});\r
+ actorYData.SetPoints(partPoints);\r
+ partPoints.Delete();\r
+ \r
+ // Z\r
+ vtkPolyData actorZData = new vtkPolyData();\r
+ actorZData.Allocate(6, 6);\r
+ \r
+ triangle.GetPointIds().SetId(0, 0);\r
+ triangle.GetPointIds().SetId(1, 1);\r
+ triangle.GetPointIds().SetId(2, 3);\r
+ actorZData.InsertNextCell(triangle.GetCellType(), triangle.GetPointIds());\r
+ triangle.GetPointIds().SetId(0, 1);\r
+ triangle.GetPointIds().SetId(1, 2);\r
+ triangle.GetPointIds().SetId(2, 3);\r
+ actorZData.InsertNextCell(triangle.GetCellType(), triangle.GetPointIds());\r
+ triangle.GetPointIds().SetId(0, 0);\r
+ triangle.GetPointIds().SetId(1, 3);\r
+ triangle.GetPointIds().SetId(2, 5);\r
+ actorZData.InsertNextCell(triangle.GetCellType(), triangle.GetPointIds());\r
+ triangle.GetPointIds().SetId(0, 3);\r
+ triangle.GetPointIds().SetId(1, 4);\r
+ triangle.GetPointIds().SetId(2, 5);\r
+ actorZData.InsertNextCell(triangle.GetCellType(), triangle.GetPointIds());\r
+ \r
+ partPoints = new vtkPoints();\r
+ partPoints.InsertPoint(0, new double[]{0., 0.,size});\r
+ partPoints.InsertPoint(1, new double[]{offset, 0., size - offset});\r
+ partPoints.InsertPoint(2, new double[]{offset, 0., sizeD2 - offset});\r
+ partPoints.InsertPoint(3, new double[]{0., 0., sizeD2});\r
+ partPoints.InsertPoint(4, new double[]{0., offset, sizeD2 - offset});\r
+ partPoints.InsertPoint(5, new double[]{0., offset, size - offset});\r
+ actorZData.SetPoints(partPoints);\r
+ partPoints.Delete();\r
+ \r
+ // XY\r
+ vtkPolyData actorXYData = new vtkPolyData();\r
+ actorXYData.Allocate(4, 4);\r
+ \r
+ triangle.GetPointIds().SetId(0, 2);\r
+ triangle.GetPointIds().SetId(1, 1);\r
+ triangle.GetPointIds().SetId(2, 3);\r
+ actorXYData.InsertNextCell(triangle.GetCellType(), triangle.GetPointIds());\r
+ triangle.GetPointIds().SetId(0, 0);\r
+ triangle.GetPointIds().SetId(1, 1);\r
+ triangle.GetPointIds().SetId(2, 3);\r
+ actorXYData.InsertNextCell(triangle.GetCellType(), triangle.GetPointIds());\r
+ \r
+ partPoints = new vtkPoints();\r
+ partPoints.InsertPoint(0, new double[]{offset, size-offset, 0.f});\r
+ partPoints.InsertPoint(1, new double[]{offset, sizeD2 - offset, 0.f});\r
+ partPoints.InsertPoint(2, new double[]{sizeD2 - offset, offset, 0.f});\r
+ partPoints.InsertPoint(3, new double[]{size-offset, offset, 0.f});\r
+ actorXYData.SetPoints(partPoints);\r
+ partPoints.Delete();\r
+ \r
+ // XZ\r
+ vtkPolyData actorXZData = new vtkPolyData();\r
+ actorXZData.Allocate(4, 4);\r
+ \r
+ triangle.GetPointIds().SetId(0, 2);\r
+ triangle.GetPointIds().SetId(1, 1);\r
+ triangle.GetPointIds().SetId(2, 3);\r
+ actorXZData.InsertNextCell(triangle.GetCellType(), triangle.GetPointIds());\r
+ triangle.GetPointIds().SetId(0, 0);\r
+ triangle.GetPointIds().SetId(1, 1);\r
+ triangle.GetPointIds().SetId(2, 3);\r
+ actorXZData.InsertNextCell(triangle.GetCellType(), triangle.GetPointIds());\r
+ \r
+ partPoints = new vtkPoints();\r
+ partPoints.InsertPoint(0, new double[]{offset, 0.f, size-offset});\r
+ partPoints.InsertPoint(1, new double[]{offset, 0.f, sizeD2 - offset});\r
+ partPoints.InsertPoint(2, new double[]{sizeD2 - offset, 0.f, offset});\r
+ partPoints.InsertPoint(3, new double[]{size-offset, 0.f, offset});\r
+ actorXZData.SetPoints(partPoints);\r
+ partPoints.Delete();\r
+ \r
+ // YZ\r
+ vtkPolyData actorYZData = new vtkPolyData();\r
+ actorYZData.Allocate(4, 4);\r
+ \r
+ triangle.GetPointIds().SetId(0, 2);\r
+ triangle.GetPointIds().SetId(1, 1);\r
+ triangle.GetPointIds().SetId(2, 3);\r
+ actorYZData.InsertNextCell(triangle.GetCellType(), triangle.GetPointIds());\r
+ triangle.GetPointIds().SetId(0, 0);\r
+ triangle.GetPointIds().SetId(1, 1);\r
+ triangle.GetPointIds().SetId(2, 3);\r
+ actorYZData.InsertNextCell(triangle.GetCellType(), triangle.GetPointIds());\r
+ \r
+ partPoints = new vtkPoints();\r
+ partPoints.InsertPoint(0, new double[]{0.f,offset, size-offset});\r
+ partPoints.InsertPoint(1, new double[]{0.f,offset, sizeD2 - offset});\r
+ partPoints.InsertPoint(2, new double[]{0.f,sizeD2 - offset, offset});\r
+ partPoints.InsertPoint(3, new double[]{0.f,size-offset, offset});\r
+ \r
+ actorYZData.SetPoints(partPoints);\r
+ partPoints.Delete();\r
+ \r
+ vtkPolyData actorPData = new vtkPolyData();\r
+ actorPData.Allocate(10, 10);\r
+ \r
+ triangle.GetPointIds().SetId(0, 0);\r
+ triangle.GetPointIds().SetId(1, 1);\r
+ triangle.GetPointIds().SetId(2, 2);\r
+ actorPData.InsertNextCell(triangle.GetCellType(), triangle.GetPointIds());\r
+ triangle.GetPointIds().SetId(0, 0);\r
+ triangle.GetPointIds().SetId(1, 2);\r
+ triangle.GetPointIds().SetId(2, 3);\r
+ actorPData.InsertNextCell(triangle.GetCellType(), triangle.GetPointIds());\r
+ triangle.GetPointIds().SetId(0, 0);\r
+ triangle.GetPointIds().SetId(1, 3);\r
+ triangle.GetPointIds().SetId(2, 4);\r
+ actorPData.InsertNextCell(triangle.GetCellType(), triangle.GetPointIds());\r
+ triangle.GetPointIds().SetId(0, 0);\r
+ triangle.GetPointIds().SetId(1, 4);\r
+ triangle.GetPointIds().SetId(2, 5);\r
+ actorPData.InsertNextCell(triangle.GetCellType(), triangle.GetPointIds());\r
+ triangle.GetPointIds().SetId(0, 0);\r
+ triangle.GetPointIds().SetId(1, 5);\r
+ triangle.GetPointIds().SetId(2, 6);\r
+ actorPData.InsertNextCell(triangle.GetCellType(), triangle.GetPointIds());\r
+ triangle.GetPointIds().SetId(0, 0);\r
+ triangle.GetPointIds().SetId(1, 6);\r
+ triangle.GetPointIds().SetId(2, 7);\r
+ actorPData.InsertNextCell(triangle.GetCellType(), triangle.GetPointIds());\r
+ triangle.GetPointIds().SetId(0, 0);\r
+ triangle.GetPointIds().SetId(1, 7);\r
+ triangle.GetPointIds().SetId(2, 8);\r
+ actorPData.InsertNextCell(triangle.GetCellType(), triangle.GetPointIds());\r
+ triangle.GetPointIds().SetId(0, 0);\r
+ triangle.GetPointIds().SetId(1, 8);\r
+ triangle.GetPointIds().SetId(2, 9);\r
+ actorPData.InsertNextCell(triangle.GetCellType(), triangle.GetPointIds());\r
+ triangle.GetPointIds().SetId(0, 0);\r
+ triangle.GetPointIds().SetId(1, 9);\r
+ triangle.GetPointIds().SetId(2, 1);\r
+ actorPData.InsertNextCell(triangle.GetCellType(), triangle.GetPointIds());\r
+ \r
+ partPoints = new vtkPoints();\r
+ partPoints.InsertPoint(0, new double[]{0.f, 0.f, 0.f});\r
+ partPoints.InsertPoint(1, new double[]{sizeD2, 0.f, 0.f});\r
+ partPoints.InsertPoint(2, new double[]{sizeD2 - offset, offset, 0.f});\r
+ partPoints.InsertPoint(3, new double[]{offset, sizeD2 - offset, 0.f});\r
+ partPoints.InsertPoint(4, new double[]{0.f, sizeD2, 0.f});\r
+ partPoints.InsertPoint(5, new double[]{0.f, sizeD2 - offset, offset});\r
+ partPoints.InsertPoint(6, new double[]{0.f, offset, sizeD2-offset});\r
+ partPoints.InsertPoint(7, new double[]{0.f, 0.f, sizeD2});\r
+ partPoints.InsertPoint(8, new double[]{offset, 0.f, sizeD2-offset});\r
+ partPoints.InsertPoint(9, new double[]{sizeD2-offset, 0.f, offset});\r
+ actorPData.SetPoints(partPoints);\r
+ partPoints.Delete();\r
+ \r
+ \r
+ vtkDataSetMapper partMapper = new vtkDataSetMapper();\r
+ partMapper.SetInput(actorXData);\r
+ partMapper.ScalarVisibilityOn();\r
+ actorX.SetMapper(partMapper);\r
+ partMapper.Delete();\r
+ \r
+ partMapper = new vtkDataSetMapper();\r
+ partMapper.SetInput(actorYData);\r
+ partMapper.ScalarVisibilityOn();\r
+ actorY.SetMapper(partMapper);\r
+ partMapper.Delete();\r
+ \r
+ partMapper = new vtkDataSetMapper();\r
+ partMapper.SetInput(actorZData);\r
+ partMapper.ScalarVisibilityOn();\r
+ actorZ.SetMapper(partMapper);\r
+ partMapper.Delete();\r
+ \r
+ partMapper = new vtkDataSetMapper();\r
+ partMapper.SetInput(actorXYData);\r
+ partMapper.ScalarVisibilityOn();\r
+ actorXY.SetMapper(partMapper);\r
+ partMapper.Delete();\r
+ \r
+ partMapper = new vtkDataSetMapper();\r
+ partMapper.SetInput(actorXZData);\r
+ partMapper.ScalarVisibilityOn();\r
+ actorXZ.SetMapper(partMapper);\r
+ partMapper.Delete();\r
+ \r
+ partMapper = new vtkDataSetMapper();\r
+ partMapper.SetInput(actorYZData);\r
+ partMapper.ScalarVisibilityOn();\r
+ actorYZ.SetMapper(partMapper);\r
+ partMapper.Delete();\r
+ \r
+ partMapper = new vtkDataSetMapper();\r
+ partMapper.SetInput(actorPData);\r
+ partMapper.ScalarVisibilityOn();\r
+ actorP.SetMapper(partMapper);\r
+ partMapper.Delete();\r
+ \r
+ \r
+ actorXData.Delete();\r
+ actorYData.Delete();\r
+ actorZData.Delete();\r
+ actorXYData.Delete();\r
+ actorXZData.Delete();\r
+ actorYZData.Delete();\r
+ actorPData.Delete();\r
+ \r
+ parts.add(actorX);\r
+ parts.add(actorY);\r
+ parts.add(actorZ);\r
+ parts.add(actorXY);\r
+ parts.add(actorXZ);\r
+ parts.add(actorYZ);\r
+ parts.add(actorP);\r
+ }\r
+ return parts;\r
+ }\r
+ \r
+ public int getTranslateAxis(vtkActor actor) {\r
+ if (actor == null)\r
+ return -1;\r
+ return parts.indexOf(actor);\r
+ }\r
+ \r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.vtk.gizmo;\r
+\r
+import java.util.Collection;\r
+\r
+import javax.vecmath.AxisAngle4d;\r
+import javax.vecmath.Tuple3d;\r
+import javax.vecmath.Vector3d;\r
+\r
+import org.simantics.g3d.gizmo.Gizmo;\r
+import org.simantics.g3d.math.MathTools;\r
+\r
+import vtk.vtkProp;\r
+import vtk.vtkProp3D;\r
+import vtk.vtkRenderer;\r
+\r
+public abstract class vtkGizmo implements Gizmo<vtkProp> {\r
+\r
+ private vtkRenderer ren1;\r
+ private Collection<vtkProp> gizmo;\r
+ \r
+ private Tuple3d position;\r
+ private AxisAngle4d orientation;\r
+ private Tuple3d scale;\r
+ \r
+ @Override\r
+ public void attach(Object renderingPart) {\r
+ if (ren1 != null)\r
+ throw new RuntimeException("Gizmo is attached");\r
+ ren1 = (vtkRenderer)renderingPart;\r
+ attachActors();\r
+ }\r
+ \r
+ @Override\r
+ public void deattach() {\r
+ if (ren1 == null)\r
+ throw new RuntimeException("Gizmo is not attached");\r
+ deattachActors();\r
+ ren1 = null;\r
+ }\r
+ \r
+ public boolean isAttached() {\r
+ return (ren1 != null);\r
+ }\r
+ \r
+ protected void attachActors() {\r
+ gizmo = getGizmo();\r
+ for (vtkProp p : gizmo) {\r
+ ren1.AddActor(p);\r
+ }\r
+ if (position != null)\r
+ setPosition(position);\r
+ if (orientation != null)\r
+ setRotation(orientation);\r
+ if (scale != null)\r
+ setScale(scale);\r
+ }\r
+ \r
+ protected void deattachActors() {\r
+ for (vtkProp p : gizmo) {\r
+ ren1.RemoveActor(p);\r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public boolean isPartOf(vtkProp pickedObject) {\r
+ for (vtkProp prop : gizmo) {\r
+ if (prop.equals(pickedObject))\r
+ return true;\r
+ }\r
+ return false;\r
+ }\r
+ \r
+ public void setPosition(Tuple3d position) {\r
+ this.position = position;\r
+ for (vtkProp p : gizmo) {\r
+ ((vtkProp3D)p).SetPosition(position.x, position.y, position.z);\r
+ }\r
+ }\r
+ \r
+ public void setRotation(AxisAngle4d q) {\r
+ this.orientation = q;\r
+ for (vtkProp p : gizmo) {\r
+ ((vtkProp3D)p).SetOrientation(0,0,0);\r
+ ((vtkProp3D)p).RotateWXYZ(MathTools.radToDeg(q.angle), q.x, q.y, q.z);\r
+ }\r
+ }\r
+ \r
+ \r
+ public void setScale(Tuple3d s) {\r
+ this.scale = s;\r
+ for (vtkProp p : gizmo) {\r
+ ((vtkProp3D)p).SetScale(s.x, s.y, s.z);\r
+ }\r
+ }\r
+ \r
+ public void setScale(double s) {\r
+ this.scale = new Vector3d(s,s,s);\r
+ for (vtkProp p : gizmo) {\r
+ ((vtkProp3D)p).SetScale(s, s, s);\r
+ }\r
+ }\r
+ \r
+ public abstract Collection<vtkProp> getGizmo();\r
+ \r
+// public double[] add(double[] color1, double[] color2) {\r
+// double[] result = new double[]{color1[0]+color2[0],color1[1],+color2[1],color1[2]+color2[2]};\r
+// return result;\r
+// }\r
+// \r
+// public double[] add(double[] color1, double[] color2, double[] color3) {\r
+// double[] result = new double[]{color1[0]+color2[0]+color3[0],color1[1],+color2[1]+color3[1],color1[2]+color2[2]+color3[2]};\r
+// return result;\r
+// }\r
+ \r
+ public double[] add(double[]... color) {\r
+ double result[] = new double[]{0,0,0};\r
+ for (double c[] : color) {\r
+ for (int i = 0; i < 3; i++)\r
+ result[i] += c[i];\r
+ }\r
+ \r
+ return result;\r
+ }\r
+ \r
+ \r
+ public vtkRenderer getRenderer() {\r
+ return ren1;\r
+ }\r
+ \r
+ \r
+ \r
+}\r
--- /dev/null
+package org.simantics.g3d.vtk.handlers;\r
+\r
+import java.util.HashMap;\r
+import java.util.Map;\r
+\r
+import javax.vecmath.Vector3d;\r
+\r
+import org.eclipse.core.commands.AbstractHandler;\r
+import org.eclipse.core.commands.ExecutionEvent;\r
+import org.eclipse.core.commands.ExecutionException;\r
+import org.eclipse.ui.IWorkbenchPart;\r
+import org.eclipse.ui.handlers.HandlerUtil;\r
+import org.simantics.g3d.vtk.common.InteractiveVtkPanel;\r
+import org.simantics.utils.threads.AWTThread;\r
+import org.simantics.utils.threads.ThreadUtils;\r
+\r
+public class CameraPositionHandler extends AbstractHandler {\r
+\r
+ \r
+ private Map<InteractiveVtkPanel,Vector3d> cameraPos = new HashMap<InteractiveVtkPanel, Vector3d>();\r
+ \r
+ @Override\r
+ public Object execute(ExecutionEvent event) throws ExecutionException {\r
+ \r
+ final IWorkbenchPart ap = HandlerUtil.getActiveEditor(event);\r
+ final InteractiveVtkPanel panel = (InteractiveVtkPanel)ap.getAdapter(InteractiveVtkPanel.class);\r
+ \r
+ String param = event.getParameter("org.simantics.g3d.viewDirection");\r
+ String vals[] = param.split(",");\r
+ final Vector3d direction = new Vector3d(Double.parseDouble(vals[0]),Double.parseDouble(vals[1]),Double.parseDouble(vals[2]));\r
+\r
+ \r
+ ThreadUtils.asyncExec(AWTThread.getThreadAccess(), new Runnable() {\r
+ \r
+ @Override\r
+ public void run() {\r
+\r
+ Vector3d focal = new Vector3d(panel.GetRenderer().GetActiveCamera().GetFocalPoint());\r
+ Vector3d pos = new Vector3d(panel.GetRenderer().GetActiveCamera().GetPosition());\r
+ cameraPos.put(panel, pos);\r
+ Vector3d dir = new Vector3d(pos);\r
+ dir.sub(focal);\r
+ double distance = dir.length();\r
+ \r
+ dir.set(direction);\r
+ dir.scale(distance);\r
+ dir.add(focal);\r
+ panel.GetRenderer().GetActiveCamera().SetPosition(dir.x, dir.y, dir.z);\r
+ if (Math.abs(direction.dot(new Vector3d(0,1,0))) < 0.95)\r
+ panel.GetRenderer().GetActiveCamera().SetViewUp(0, 1, 0);\r
+ else\r
+ panel.GetRenderer().GetActiveCamera().SetViewUp(1, 0, 0);\r
+ \r
+ panel.GetRenderer().ResetCameraClippingRange();\r
+ \r
+ panel.UpdateLight();\r
+ panel.repaint();\r
+ }\r
+ });\r
+ \r
+ return null;\r
+ \r
+ }\r
+ \r
+ \r
+}\r
--- /dev/null
+package org.simantics.g3d.vtk.handlers;\r
+\r
+import java.util.HashMap;\r
+import java.util.Map;\r
+\r
+import javax.vecmath.Vector3d;\r
+\r
+import org.eclipse.core.commands.AbstractHandler;\r
+import org.eclipse.core.commands.Command;\r
+import org.eclipse.core.commands.ExecutionEvent;\r
+import org.eclipse.core.commands.ExecutionException;\r
+import org.eclipse.ui.IWorkbenchPart;\r
+import org.eclipse.ui.handlers.HandlerUtil;\r
+import org.simantics.g3d.vtk.common.InteractiveVtkPanel;\r
+import org.simantics.utils.threads.AWTThread;\r
+import org.simantics.utils.threads.ThreadUtils;\r
+\r
+public class ParallelPerspectiveHandler extends AbstractHandler {\r
+\r
+ \r
+ private Map<InteractiveVtkPanel,Vector3d> cameraPos = new HashMap<InteractiveVtkPanel, Vector3d>();\r
+ \r
+ @Override\r
+ public Object execute(ExecutionEvent event) throws ExecutionException {\r
+ Command command = event.getCommand();\r
+ boolean oldValue = HandlerUtil.toggleCommandState(command);\r
+ final boolean activate = !oldValue;\r
+ \r
+ final IWorkbenchPart ap = HandlerUtil.getActiveEditor(event);\r
+ final InteractiveVtkPanel panel = (InteractiveVtkPanel)ap.getAdapter(InteractiveVtkPanel.class);\r
+ \r
+ ThreadUtils.asyncExec(AWTThread.getThreadAccess(), new Runnable() {\r
+ \r
+ @Override\r
+ public void run() {\r
+ if (activate){\r
+ Vector3d focal = new Vector3d(panel.GetRenderer().GetActiveCamera().GetFocalPoint());\r
+ Vector3d pos = new Vector3d(panel.GetRenderer().GetActiveCamera().GetPosition());\r
+ cameraPos.put(panel, pos);\r
+ Vector3d dir = new Vector3d(pos);\r
+ dir.sub(focal);\r
+ dir.normalize();\r
+ dir.scale(100);\r
+ dir.add(focal);\r
+ panel.GetRenderer().GetActiveCamera().SetPosition(dir.x, dir.y, dir.z);\r
+ \r
+ \r
+ panel.GetRenderer().GetActiveCamera().SetParallelProjection(1);\r
+ panel.GetRenderer().ResetCameraClippingRange();\r
+ } else {\r
+ panel.GetRenderer().GetActiveCamera().SetParallelProjection(0);\r
+ Vector3d pos = cameraPos.get(panel);\r
+ if (pos != null) {\r
+ panel.GetRenderer().GetActiveCamera().SetPosition(pos.x, pos.y, pos.z);\r
+ }\r
+ panel.GetRenderer().ResetCameraClippingRange();\r
+ \r
+ }\r
+ panel.UpdateLight();\r
+ panel.repaint();\r
+\r
+ }\r
+ });\r
+ \r
+ return null;\r
+ \r
+ }\r
+ \r
+ \r
+ \r
+}\r
--- /dev/null
+package org.simantics.g3d.vtk.preferences;\r
+\r
+public enum CloseMethod {\r
+ ON_CLOSE,\r
+ ON_LAST_CLOSE,\r
+ NO_CLOSE\r
+}\r
--- /dev/null
+package org.simantics.g3d.vtk.preferences;
+
+/**
+ * Constant definitions for plug-in preferences
+ */
+public class PreferenceConstants {
+
+ public static final String CLOSE_METHOD = "closeMethod";
+
+}
--- /dev/null
+package org.simantics.g3d.vtk.preferences;
+
+import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer;
+import org.eclipse.jface.preference.IPreferenceStore;
+
+import org.simantics.g3d.vtk.Activator;
+
+/**
+ * Class used to initialize default preference values.
+ */
+public class PreferenceInitializer extends AbstractPreferenceInitializer {
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer#initializeDefaultPreferences()
+ */
+ public void initializeDefaultPreferences() {
+ IPreferenceStore store = Activator.getDefault().getPreferenceStore();
+ store.setDefault(PreferenceConstants.CLOSE_METHOD, CloseMethod.ON_LAST_CLOSE.toString());
+ }
+
+}
--- /dev/null
+package org.simantics.g3d.vtk.preferences;
+
+import org.eclipse.jface.preference.*;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+import org.eclipse.ui.IWorkbench;
+import org.simantics.g3d.vtk.Activator;
+
+/**
+ * This class represents a preference page that
+ * is contributed to the Preferences dialog. By
+ * subclassing <samp>FieldEditorPreferencePage</samp>, we
+ * can use the field support built into JFace that allows
+ * us to create a page that is small and knows how to
+ * save, restore and apply itself.
+ * <p>
+ * This page is used to modify preferences only. They
+ * are stored in the preference store that belongs to
+ * the main plug-in class. That way, preferences can
+ * be accessed directly via the preference store.
+ */
+
+public class VTKPreferencePage
+ extends FieldEditorPreferencePage
+ implements IWorkbenchPreferencePage {
+
+ public VTKPreferencePage() {
+ super(GRID);
+ setPreferenceStore(Activator.getDefault().getPreferenceStore());
+ setDescription("VTK Preferences (DEBUG)");
+ }
+
+ /**
+ * Creates the field editors. Field editors are abstractions of
+ * the common GUI blocks needed to manipulate various types
+ * of preferences. Each field editor knows how to save and
+ * restore itself.
+ */
+ public void createFieldEditors() {
+ addField(new RadioGroupFieldEditor(
+ PreferenceConstants.CLOSE_METHOD,
+ "When to close VTK",
+ 1,
+ new String[][] { { "On &Editor Close", CloseMethod.ON_CLOSE.toString() },
+ { "On &Last Editor Close", CloseMethod.ON_LAST_CLOSE.toString() },
+ { "&Closing Disabled", CloseMethod.NO_CLOSE.toString() }
+ }, getFieldEditorParent()));
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench)
+ */
+ public void init(IWorkbench workbench) {
+ }
+
+}
\ No newline at end of file
--- /dev/null
+package org.simantics.g3d.vtk.property;\r
+\r
+import org.eclipse.jface.viewers.ISelection;\r
+import org.eclipse.jface.viewers.ISelectionProvider;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.layout.FillLayout;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Control;\r
+import org.eclipse.swt.widgets.Display;\r
+import org.eclipse.swt.widgets.Text;\r
+import org.eclipse.ui.IWorkbenchSite;\r
+import org.simantics.db.management.ISessionContext;\r
+import org.simantics.selectionview.IPropertyTab;\r
+import org.simantics.selectionview.PropertyTabContributor;\r
+import org.simantics.utils.threads.AWTThread;\r
+import org.simantics.utils.threads.ThreadUtils;\r
+\r
+import vtk.vtkActor;\r
+import vtk.vtkAlgorithm;\r
+import vtk.vtkAlgorithmOutput;\r
+import vtk.vtkMapper;\r
+import vtk.vtkProp;\r
+\r
+public class VTKPropertyTabContributor implements PropertyTabContributor{\r
+ \r
+ public org.simantics.selectionview.IPropertyTab create(Composite parent, IWorkbenchSite site, ISessionContext context, Object input) {\r
+ IPropertyTab tab = new VTKPropertyTab((vtkProp)input);\r
+ tab.createControl(parent, context);\r
+ return tab;\r
+ };\r
+ \r
+ \r
+ public class VTKPropertyTab implements IPropertyTab {\r
+ private Composite composite;\r
+ private Text text;\r
+ private vtkProp prop;\r
+ \r
+ public VTKPropertyTab(vtkProp prop) {\r
+ this.prop = prop;\r
+ }\r
+ \r
+ @Override\r
+ public void createControl(Composite parent, ISessionContext context) {\r
+ \r
+ composite = new Composite(parent, SWT.NONE);\r
+ composite.setLayout(new FillLayout());\r
+ text = new Text(composite, SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL | SWT.READ_ONLY);\r
+ ThreadUtils.asyncExec(AWTThread.getThreadAccess(), new Runnable() {\r
+ \r
+ @Override\r
+ public void run() {\r
+ String string = "";\r
+ if (prop instanceof vtkActor) {\r
+ vtkActor act = (vtkActor)prop;\r
+ vtkMapper mapper = act.GetMapper();\r
+ vtkAlgorithmOutput out = mapper.GetInputConnection(0, 0);\r
+ vtkAlgorithm producer = out.GetProducer();\r
+ string += producer.GetClassName() +"\n";\r
+ out.Delete();\r
+ mapper.Delete();\r
+ producer.Delete();\r
+ }\r
+ string += prop.Print();\r
+ final String s = string;\r
+ Display.getDefault().asyncExec(new Runnable() {\r
+ @Override\r
+ public void run() {\r
+ if (!text.isDisposed())\r
+ text.setText(s);\r
+ }\r
+ });\r
+ }\r
+ });;\r
+ \r
+ \r
+ }\r
+ \r
+ @Override\r
+ public void requestFocus() {\r
+ composite.setFocus();\r
+ }\r
+ \r
+ @Override\r
+ public void dispose() {\r
+ composite.dispose();\r
+ }\r
+ \r
+ @Override\r
+ public boolean isDisposed() {\r
+ return composite.isDisposed();\r
+ }\r
+ \r
+ @Override\r
+ public Control getControl() {\r
+ return composite;\r
+ }\r
+ \r
+ @Override\r
+ public void setInput(ISessionContext context, ISelection selection,\r
+ boolean force) {\r
+ \r
+ }\r
+ \r
+ @Override\r
+ public ISelectionProvider getSelectionProvider() {\r
+ return null;\r
+ }\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.vtk.shape;\r
+\r
+import javax.vecmath.AxisAngle4d;\r
+import javax.vecmath.Matrix4d;\r
+import javax.vecmath.Point3d;\r
+import javax.vecmath.Vector3d;\r
+\r
+import org.simantics.g3d.math.MathTools;\r
+import org.simantics.utils.threads.AWTThread;\r
+import org.simantics.utils.threads.ThreadUtils;\r
+\r
+import vtk.vtkActor;\r
+import vtk.vtkAssembly;\r
+import vtk.vtkConeSource;\r
+import vtk.vtkLineSource;\r
+import vtk.vtkLinearTransform;\r
+import vtk.vtkMatrix4x4;\r
+import vtk.vtkPolyDataMapper;\r
+import vtk.vtkProp3D;\r
+import vtk.vtkRenderer;\r
+import vtk.vtkTextActor;\r
+import vtk.vtkTubeFilter;\r
+\r
+public class DualHeadArrowActor extends vtkAssembly implements IvtkVisualObject{\r
+\r
+ private vtkRenderer ren;\r
+ private Vector3d axisDir = new Vector3d(1,0,0);\r
+ private vtkTextActor tactor;\r
+ private vtkActor tubeActor;\r
+ private vtkActor coneActor;\r
+ private vtkActor coneActor2;\r
+ private boolean rendered = false;\r
+\r
+ public DualHeadArrowActor(vtkRenderer _ren, String label) {\r
+ super();\r
+ ren = _ren;\r
+ createAxis(label);\r
+ }\r
+ \r
+ public DualHeadArrowActor(vtkRenderer _ren, String label, Vector3d dir) {\r
+ super();\r
+ ren = _ren;\r
+ this.axisDir = dir;\r
+ if (dir.lengthSquared() < MathTools.NEAR_ZERO)\r
+ throw new IllegalArgumentException("Direction vector length must mer larger than zero");\r
+ createAxis(label);\r
+ }\r
+\r
+ public void createAxis(String label) {\r
+ double coneScale = 0.3 * axisDir.length();\r
+ Vector3d coneOffset = new Vector3d(axisDir);\r
+ coneOffset.normalize();\r
+ coneOffset.scale(coneScale*0.5);\r
+ \r
+ vtkLineSource line = new vtkLineSource();\r
+ //line.SetPoint1(0.0,0.0,0.0);\r
+ line.SetPoint1(coneOffset.x,coneOffset.y,coneOffset.z);\r
+ line.SetPoint2(axisDir.x-coneOffset.x,axisDir.y-coneOffset.y,axisDir.z-coneOffset.z);\r
+ \r
+ tactor = new vtkTextActor();\r
+ \r
+ tactor.SetInput(label);\r
+ \r
+ tactor.SetTextScaleModeToNone();\r
+ tactor.GetTextProperty().SetColor(0.0, 0.0, 0.0);\r
+ tactor.GetTextProperty().ShadowOff();\r
+ tactor.GetTextProperty().ItalicOff();\r
+ tactor.GetTextProperty().BoldOff();\r
+ \r
+ tactor.GetTextProperty().Delete();\r
+ \r
+ tactor.SetMaximumLineHeight(0.25);\r
+ \r
+ tactor.SetPickable(0);\r
+ \r
+ vtkTubeFilter tube = new vtkTubeFilter();\r
+ tube.SetInput(line.GetOutput());\r
+ tube.SetRadius(0.05 * axisDir.length());\r
+ tube.SetNumberOfSides(8);\r
+\r
+ vtkPolyDataMapper tubeMapper = new vtkPolyDataMapper();\r
+ tubeMapper.SetInput(tube.GetOutput());\r
+\r
+ tubeActor = new vtkActor();\r
+ tubeActor.SetMapper(tubeMapper);\r
+ tubeActor.PickableOff();\r
+\r
+ int coneRes = 12;\r
+ \r
+\r
+ \r
+ \r
+ // --- x-Cone\r
+ vtkConeSource cone = new vtkConeSource();\r
+ cone.SetResolution(coneRes);\r
+ vtkPolyDataMapper coneMapper = new vtkPolyDataMapper();\r
+ coneMapper.SetInput(cone.GetOutput());\r
+ coneActor = new vtkActor();\r
+ coneActor.SetMapper(coneMapper);\r
+ coneActor.GetProperty().SetColor(1, 0, 0);\r
+ coneActor.SetScale(coneScale, coneScale, coneScale);\r
+ coneActor.SetPosition(axisDir.x-coneOffset.x,axisDir.y-coneOffset.y,axisDir.z-coneOffset.z);\r
+ coneActor.SetPickable(0);\r
+ \r
+ AxisAngle4d aa = MathTools.createRotation(new Vector3d(1,0,0), axisDir);\r
+ if (aa != null)\r
+ coneActor.RotateWXYZ(MathTools.radToDeg(aa.angle), aa.x, aa.y, aa.z);\r
+ \r
+ \r
+ coneActor2 = new vtkActor();\r
+ coneActor2.SetMapper(coneMapper);\r
+ coneActor2.GetProperty().SetColor(1, 0, 0);\r
+ coneActor2.SetScale(coneScale, coneScale, coneScale);\r
+ coneActor2.SetPosition(coneOffset.x,coneOffset.y,coneOffset.z);\r
+ coneActor2.SetPickable(0);\r
+ \r
+ aa = MathTools.createRotation(new Vector3d(-1,0,0), axisDir);\r
+ if (aa != null)\r
+ coneActor2.RotateWXYZ(MathTools.radToDeg(aa.angle), aa.x, aa.y, aa.z);\r
+ \r
+ this.AddPart(tubeActor);\r
+ this.AddPart(coneActor);\r
+ this.AddPart(coneActor2);\r
+ \r
+ tube.GetOutput().Delete();\r
+ cone.GetOutput().Delete();\r
+ line.GetOutput().Delete();\r
+ \r
+ tubeMapper.Delete();\r
+ tube.Delete();\r
+ cone.Delete();\r
+ line.Delete();\r
+\r
+ coneMapper.Delete();\r
+ \r
+ coneActor.GetProperty().Delete();\r
+ coneActor2.GetProperty().Delete();\r
+ }\r
+ \r
+ public void addToRenderer() {\r
+ if (rendered)\r
+ return;\r
+ rendered = true;\r
+ \r
+ ren.AddActor2D(tactor);\r
+ \r
+ ren.AddActor(this);\r
+ }\r
+ \r
+ public void removeFromRenderer() {\r
+ if (!rendered)\r
+ return;\r
+ rendered = false;\r
+ ren.RemoveActor2D(tactor);\r
+ ren.RemoveActor(this);\r
+ }\r
+ \r
+ public boolean isRendered() {\r
+ return rendered;\r
+ }\r
+\r
+ public void setAxesVisibility(boolean ison) {\r
+ this.SetVisibility(ison ? 1 : 0);\r
+ tactor.SetVisibility(ison ? 1 : 0);\r
+ }\r
+ \r
+ public void setLabelVisibility(boolean ison) {\r
+ tactor.SetVisibility(ison ? 1 : 0);\r
+ }\r
+ \r
+ double mat[] = new double[16];\r
+ Matrix4d m = new Matrix4d();\r
+ private void updateTextLoc() {\r
+ tactor.GetPositionCoordinate().SetCoordinateSystemToWorld();\r
+ \r
+ \r
+ GetMatrix(mat);\r
+ MathTools.set(m,mat);\r
+ Point3d p = new Point3d(axisDir.x*0.5, axisDir.y*0.5,axisDir.z*0.5);\r
+ m.transform(p);\r
+ tactor.GetPositionCoordinate().SetValue(p.x, p.y, p.z);\r
+ \r
+ tactor.GetPositionCoordinate().Delete();\r
+ }\r
+ \r
+ @Override\r
+ public void SetPickable(int id0) {\r
+ super.SetPickable(id0);\r
+ tubeActor.SetPickable(id0);\r
+ coneActor.SetPickable(id0);\r
+ coneActor2.SetPickable(id0);\r
+ }\r
+ \r
+ @Override\r
+ public void SetOrientation(double id0, double id1, double id2) {\r
+ super.SetOrientation(id0, id1, id2);\r
+ updateTextLoc();\r
+ }\r
+ \r
+ @Override\r
+ public void RotateWXYZ(double id0, double id1, double id2, double id3) {\r
+ super.RotateWXYZ(id0, id1, id2, id3);\r
+ updateTextLoc();\r
+ }\r
+ \r
+ @Override\r
+ public void SetPosition(double[] id0) {\r
+ super.SetPosition(id0);\r
+ updateTextLoc();\r
+ }\r
+ \r
+ @Override\r
+ public void SetPosition(double id0, double id1, double id2) {\r
+ super.SetPosition(id0, id1, id2);\r
+ updateTextLoc();\r
+ }\r
+ \r
+ @Override\r
+ public void SetOrientation(double[] id0) {\r
+ super.SetOrientation(id0);\r
+ updateTextLoc();\r
+ }\r
+ \r
+ @Override\r
+ public void SetScale(double id0) {\r
+ super.SetScale(id0);\r
+ updateTextLoc();\r
+ }\r
+ \r
+ @Override\r
+ public void SetScale(double id0, double id1, double id2) {\r
+ super.SetScale(id0, id1, id2);\r
+ updateTextLoc();\r
+ }\r
+ \r
+ @Override\r
+ public void SetScale(double[] id0) {\r
+ super.SetScale(id0);\r
+ updateTextLoc();\r
+ }\r
+ \r
+ public void SetColor(double r, double g, double b) {\r
+ coneActor.GetProperty().SetColor(r, g, b);\r
+ coneActor2.GetProperty().SetColor(r, g, b);\r
+ tubeActor.GetProperty().SetColor(r, g, b);\r
+ coneActor.GetProperty().Delete();\r
+ coneActor2.GetProperty().Delete();\r
+ tubeActor.GetProperty().Delete();\r
+ }\r
+ \r
+ public void SetTextColor(double r, double g, double b) {\r
+ tactor.GetTextProperty().SetColor(r, g, b);\r
+ tactor.GetTextProperty().Delete();\r
+ }\r
+ \r
+ @Override\r
+ public void SetUserMatrix(vtkMatrix4x4 id0) {\r
+ super.SetUserMatrix(id0);\r
+ updateTextLoc();\r
+ }\r
+ \r
+ @Override\r
+ public void SetUserTransform(vtkLinearTransform id0) {\r
+ super.SetUserTransform(id0);\r
+ updateTextLoc();\r
+ }\r
+ \r
+ @Override\r
+ public void Delete() {\r
+ ren.RemoveActor(tactor);\r
+ ren.RemoveActor(tubeActor);\r
+ ren.RemoveActor(coneActor);\r
+ ren.RemoveActor(coneActor2);\r
+ tactor.Delete();\r
+ tubeActor.Delete();\r
+ coneActor.Delete();\r
+ coneActor2.Delete();\r
+ super.Delete();\r
+ }\r
+\r
+ public void dispose() {\r
+ ThreadUtils.asyncExec(AWTThread.getThreadAccess(), new Runnable() {\r
+ \r
+ @Override\r
+ public void run() {\r
+ removeFromRenderer();\r
+ Delete();\r
+ }\r
+ });\r
+ }\r
+ \r
+ @Override\r
+ public vtkProp3D getVtkProp() {\r
+ return this;\r
+ }\r
+ \r
+}\r
--- /dev/null
+package org.simantics.g3d.vtk.shape;\r
+\r
+import vtk.vtkProp3D;\r
+\r
+public interface IvtkVisualObject {\r
+\r
+ \r
+ public void addToRenderer() ;\r
+ public void removeFromRenderer();\r
+ public boolean isRendered();\r
+ public vtkProp3D getVtkProp();\r
+}\r
--- /dev/null
+package org.simantics.g3d.vtk.shape;\r
+\r
+import javax.vecmath.Vector3d;\r
+\r
+import org.simantics.g3d.shape.Color4d;\r
+import org.simantics.g3d.shape.Mesh;\r
+\r
+import vtk.vtkActor;\r
+import vtk.vtkDataSetMapper;\r
+import vtk.vtkIdList;\r
+import vtk.vtkPoints;\r
+import vtk.vtkPolyData;\r
+import vtk.vtkPolyDataMapper;\r
+import vtk.vtkPolyDataNormals;\r
+import vtk.vtkTriangle;\r
+import vtk.vtkUnsignedCharArray;\r
+\r
+public class MeshActor extends vtkActor {\r
+ \r
+ public void setMesh(Mesh mesh) {\r
+ \r
+ vtkPolyDataMapper mapper = new vtkPolyDataMapper();\r
+ \r
+ vtkPolyData polyData = new vtkPolyData();\r
+ polyData.Allocate(mesh.getIndices().size()/3, mesh.getIndices().size()/3);\r
+ \r
+ vtkTriangle triangle = new vtkTriangle();\r
+ vtkIdList list = triangle.GetPointIds();\r
+ for (int i = 0; i < mesh.getIndices().size(); i+=3) {\r
+ list.SetId(0, mesh.getIndices().get(i));\r
+ list.SetId(1, mesh.getIndices().get(i+1));\r
+ list.SetId(2, mesh.getIndices().get(i+2));\r
+ polyData.InsertNextCell(triangle.GetCellType(), list);\r
+ }\r
+ list.Delete();\r
+ triangle.Delete();\r
+ \r
+ \r
+ vtkPoints points = new vtkPoints();\r
+ for (int i = 0; i < mesh.getVertices().size(); i++) {\r
+ Vector3d p = mesh.getVertices().get(i);\r
+ points.InsertPoint(i, p.x, p.y, p.z);\r
+ }\r
+ \r
+ polyData.SetPoints(points);\r
+ points.Delete();\r
+ \r
+ if (mesh.getColors() != null) {\r
+ vtkUnsignedCharArray colors = new vtkUnsignedCharArray();\r
+ colors.SetName("Colors");\r
+ colors.SetNumberOfComponents(3);\r
+ colors.SetNumberOfTuples(mesh.getColors().size());\r
+ for (int i = 0; i < mesh.getColors().size(); i++) {\r
+ Color4d c = mesh.getColors().get(i);\r
+ colors.InsertTuple3(i, 255.0* c.x, 255.0 * c.y, 255.0 * c.z);\r
+ }\r
+ polyData.GetPointData().AddArray(colors);\r
+ colors.Delete();\r
+ \r
+ }\r
+ \r
+ boolean computeNormals = true;\r
+ if (computeNormals) {\r
+ vtkPolyDataNormals normals = new vtkPolyDataNormals();\r
+ normals.SetInput(polyData);\r
+ mapper.SetInputConnection(normals.GetOutputPort());\r
+ normals.GetOutputPort().Delete();\r
+ normals.Delete();\r
+ } else {\r
+ mapper.SetInput(polyData);\r
+ }\r
+ \r
+ if (mesh.getColors() != null) {\r
+ mapper.ScalarVisibilityOn();\r
+ mapper.SetScalarModeToUsePointFieldData();\r
+ mapper.SelectColorArray("Colors");\r
+ }\r
+ \r
+ SetMapper(mapper);\r
+ mapper.Delete();\r
+ polyData.GetPointData().Delete();\r
+ polyData.Delete();\r
+ \r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.vtk.shape;\r
+\r
+import javax.vecmath.Matrix4d;\r
+import javax.vecmath.Point3d;\r
+\r
+import org.simantics.g3d.math.MathTools;\r
+import org.simantics.utils.threads.AWTThread;\r
+import org.simantics.utils.threads.ThreadUtils;\r
+\r
+import vtk.vtkActor;\r
+import vtk.vtkAssembly;\r
+import vtk.vtkAxes;\r
+import vtk.vtkConeSource;\r
+import vtk.vtkLinearTransform;\r
+import vtk.vtkMatrix4x4;\r
+import vtk.vtkPolyDataMapper;\r
+import vtk.vtkProp3D;\r
+import vtk.vtkRenderer;\r
+import vtk.vtkTextActor;\r
+import vtk.vtkTubeFilter;\r
+\r
+public class axesActor extends vtkAssembly implements IvtkVisualObject{\r
+\r
+ private vtkRenderer ren;\r
+ private double axisLength = 0.8;\r
+ private vtkTextActor xactor, yactor, zactor;\r
+ private vtkActor tubeActor;\r
+ private vtkActor xconeActor;\r
+ private vtkActor yconeActor;\r
+ private vtkActor zconeActor;\r
+ private boolean rendered = false;\r
+\r
+ public axesActor(vtkRenderer _ren) {\r
+ super();\r
+ ren = _ren;\r
+ createAxes();\r
+ }\r
+ \r
+ public axesActor(vtkRenderer _ren, double axisLength) {\r
+ super();\r
+ ren = _ren;\r
+ this.axisLength = axisLength;\r
+ createAxes();\r
+ }\r
+\r
+ public void createAxes() {\r
+ vtkAxes axes = new vtkAxes();\r
+ axes.SetOrigin(0, 0, 0);\r
+ axes.SetScaleFactor(axisLength);\r
+\r
+ xactor = new vtkTextActor();\r
+ yactor = new vtkTextActor();\r
+ zactor = new vtkTextActor();\r
+\r
+ xactor.SetInput("X");\r
+ yactor.SetInput("Y");\r
+ zactor.SetInput("Z");\r
+\r
+// xactor.SetTextScaleModeToViewport();\r
+// yactor.SetTextScaleModeToViewport();\r
+// zactor.SetTextScaleModeToViewport();\r
+ xactor.SetTextScaleModeToNone();\r
+ yactor.SetTextScaleModeToNone();\r
+ zactor.SetTextScaleModeToNone();\r
+ \r
+ xactor.GetTextProperty().SetColor(0.0, 0.0, 0.0);\r
+ xactor.GetTextProperty().ShadowOff();\r
+ xactor.GetTextProperty().ItalicOff();\r
+ xactor.GetTextProperty().BoldOff();\r
+\r
+ yactor.GetTextProperty().SetColor(0.0, 0.0, 0.0);\r
+ yactor.GetTextProperty().ShadowOff();\r
+ yactor.GetTextProperty().ItalicOff();\r
+ yactor.GetTextProperty().BoldOff();\r
+\r
+ zactor.GetTextProperty().SetColor(0.0, 0.0, 0.0);\r
+ zactor.GetTextProperty().ShadowOff();\r
+ zactor.GetTextProperty().ItalicOff();\r
+ zactor.GetTextProperty().BoldOff();\r
+ \r
+ xactor.GetTextProperty().Delete();\r
+ yactor.GetTextProperty().Delete();\r
+ zactor.GetTextProperty().Delete();\r
+\r
+ xactor.SetMaximumLineHeight(0.25);\r
+ yactor.SetMaximumLineHeight(0.25);\r
+ zactor.SetMaximumLineHeight(0.25);\r
+ \r
+ xactor.SetPickable(0);\r
+ yactor.SetPickable(0);\r
+ zactor.SetPickable(0);\r
+\r
+ vtkTubeFilter tube = new vtkTubeFilter();\r
+ tube.SetInput(axes.GetOutput());\r
+ tube.SetRadius(0.05 * axisLength);\r
+ tube.SetNumberOfSides(8);\r
+\r
+ vtkPolyDataMapper tubeMapper = new vtkPolyDataMapper();\r
+ tubeMapper.SetInput(tube.GetOutput());\r
+\r
+ tubeActor = new vtkActor();\r
+ tubeActor.SetMapper(tubeMapper);\r
+ tubeActor.PickableOff();\r
+\r
+ int coneRes = 12;\r
+ double coneScale = 0.3 * axisLength;\r
+\r
+ // --- x-Cone\r
+ vtkConeSource xcone = new vtkConeSource();\r
+ xcone.SetResolution(coneRes);\r
+ vtkPolyDataMapper xconeMapper = new vtkPolyDataMapper();\r
+ xconeMapper.SetInput(xcone.GetOutput());\r
+ xconeActor = new vtkActor();\r
+ xconeActor.SetMapper(xconeMapper);\r
+ xconeActor.GetProperty().SetColor(1, 0, 0);\r
+ xconeActor.SetScale(coneScale, coneScale, coneScale);\r
+ xconeActor.SetPosition(axisLength, 0.0, 0.0);\r
+ xconeActor.SetPickable(0);\r
+\r
+ // --- y-Cone\r
+ vtkConeSource ycone = new vtkConeSource();\r
+ ycone.SetResolution(coneRes);\r
+ vtkPolyDataMapper yconeMapper = new vtkPolyDataMapper();\r
+ yconeMapper.SetInput(ycone.GetOutput());\r
+ yconeActor = new vtkActor();\r
+ yconeActor.SetMapper(yconeMapper);\r
+ yconeActor.GetProperty().SetColor(1, 1, 0);\r
+ yconeActor.RotateZ(90);\r
+ yconeActor.SetScale(coneScale, coneScale, coneScale);\r
+ yconeActor.SetPosition(0.0, axisLength, 0.0);\r
+ yconeActor.SetPickable(0);\r
+\r
+ // --- z-Cone\r
+ vtkConeSource zcone = new vtkConeSource();\r
+ zcone.SetResolution(coneRes);\r
+ vtkPolyDataMapper zconeMapper = new vtkPolyDataMapper();\r
+ zconeMapper.SetInput(zcone.GetOutput());\r
+ zconeActor = new vtkActor();\r
+ zconeActor.SetMapper(zconeMapper);\r
+ zconeActor.GetProperty().SetColor(0, 1, 0);\r
+ zconeActor.RotateY(-90);\r
+ zconeActor.SetScale(coneScale, coneScale, coneScale);\r
+ zconeActor.SetPosition(0.0, 0.0, axisLength);\r
+ zconeActor.SetPickable(0);\r
+\r
+ \r
+ this.AddPart(tubeActor);\r
+ this.AddPart(xconeActor);\r
+ this.AddPart(yconeActor);\r
+ this.AddPart(zconeActor);\r
+ \r
+ tube.GetOutput().Delete();\r
+ xcone.GetOutput().Delete();\r
+ ycone.GetOutput().Delete();\r
+ zcone.GetOutput().Delete();\r
+ axes.GetOutput().Delete();\r
+ axes.Delete();\r
+ tubeMapper.Delete();\r
+ tube.Delete();\r
+ xcone.Delete();\r
+ ycone.Delete();\r
+ zcone.Delete();\r
+ xconeMapper.Delete();\r
+ yconeMapper.Delete();\r
+ zconeMapper.Delete();\r
+ \r
+ xconeActor.GetProperty().Delete();\r
+ yconeActor.GetProperty().Delete();\r
+ zconeActor.GetProperty().Delete();\r
+ }\r
+ \r
+ public void addToRenderer() {\r
+ if (rendered)\r
+ return;\r
+ rendered = true;\r
+ \r
+ ren.AddActor2D(xactor);\r
+ ren.AddActor2D(yactor);\r
+ ren.AddActor2D(zactor);\r
+ \r
+ \r
+ ren.AddActor(this);\r
+ }\r
+ \r
+ public void removeFromRenderer() {\r
+ if (!rendered)\r
+ return;\r
+ rendered = false;\r
+ ren.RemoveActor2D(xactor);\r
+ ren.RemoveActor2D(yactor);\r
+ ren.RemoveActor2D(zactor);\r
+ ren.RemoveActor(this);\r
+ }\r
+ \r
+ public boolean isRendered() {\r
+ return rendered;\r
+ }\r
+\r
+ public void setAxesVisibility(boolean ison) {\r
+ this.SetVisibility(ison ? 1 : 0);\r
+ xactor.SetVisibility(ison ? 1 : 0);\r
+ yactor.SetVisibility(ison ? 1 : 0);\r
+ zactor.SetVisibility(ison ? 1 : 0);\r
+ }\r
+ \r
+ private boolean labelVisible = true;\r
+ \r
+ public void setLabelVisibility(boolean ison) {\r
+ xactor.SetVisibility(ison ? 1 : 0);\r
+ yactor.SetVisibility(ison ? 1 : 0);\r
+ zactor.SetVisibility(ison ? 1 : 0);\r
+ labelVisible = ison;\r
+ if (labelVisible)\r
+ updateTextLoc();\r
+ }\r
+ \r
+ Matrix4d m = new Matrix4d();\r
+ double mat[] = new double[16];\r
+ Point3d x = new Point3d();\r
+ Point3d y = new Point3d();\r
+ Point3d z = new Point3d();\r
+ \r
+ private void updateTextLoc() {\r
+ if (!labelVisible)\r
+ return;\r
+ xactor.GetPositionCoordinate().SetCoordinateSystemToWorld();\r
+ yactor.GetPositionCoordinate().SetCoordinateSystemToWorld();\r
+ zactor.GetPositionCoordinate().SetCoordinateSystemToWorld();\r
+ \r
+ GetMatrix(mat);\r
+ MathTools.set(m, mat);\r
+ x.set(axisLength, 0,0);\r
+ y.set(0,axisLength, 0);\r
+ z.set(0,0,axisLength);\r
+ \r
+ m.transform(x);\r
+ m.transform(y);\r
+ m.transform(z);\r
+ xactor.GetPositionCoordinate().SetValue(x.x, x.y, x.z);\r
+ yactor.GetPositionCoordinate().SetValue(y.x, y.y, y.z);\r
+ zactor.GetPositionCoordinate().SetValue(z.x, z.y, z.z);\r
+ \r
+ xactor.GetPositionCoordinate().Delete();\r
+ yactor.GetPositionCoordinate().Delete();\r
+ zactor.GetPositionCoordinate().Delete();\r
+ }\r
+ \r
+ @Override\r
+ public void SetPickable(int id0) {\r
+ super.SetPickable(id0);\r
+ tubeActor.SetPickable(id0);\r
+ xconeActor.SetPickable(id0);\r
+ yconeActor.SetPickable(id0);\r
+ zconeActor.SetPickable(id0);\r
+\r
+ }\r
+ \r
+ @Override\r
+ public void SetOrientation(double id0, double id1, double id2) {\r
+ super.SetOrientation(id0, id1, id2);\r
+ updateTextLoc();\r
+ }\r
+ \r
+ @Override\r
+ public void RotateWXYZ(double id0, double id1, double id2, double id3) {\r
+ super.RotateWXYZ(id0, id1, id2, id3);\r
+ updateTextLoc();\r
+ }\r
+ \r
+ @Override\r
+ public void SetPosition(double[] id0) {\r
+ super.SetPosition(id0);\r
+ updateTextLoc();\r
+ }\r
+ \r
+ @Override\r
+ public void SetPosition(double id0, double id1, double id2) {\r
+ super.SetPosition(id0, id1, id2);\r
+ updateTextLoc();\r
+ }\r
+ \r
+ @Override\r
+ public void SetOrientation(double[] id0) {\r
+ super.SetOrientation(id0);\r
+ updateTextLoc();\r
+ }\r
+ \r
+ @Override\r
+ public void SetScale(double id0) {\r
+ super.SetScale(id0);\r
+ updateTextLoc();\r
+ }\r
+ \r
+ @Override\r
+ public void SetScale(double id0, double id1, double id2) {\r
+ super.SetScale(id0, id1, id2);\r
+ updateTextLoc();\r
+ }\r
+ \r
+ @Override\r
+ public void SetScale(double[] id0) {\r
+ super.SetScale(id0);\r
+ updateTextLoc();\r
+ }\r
+ \r
+ @Override\r
+ public void SetUserMatrix(vtkMatrix4x4 id0) {\r
+ super.SetUserMatrix(id0);\r
+ updateTextLoc();\r
+ }\r
+ \r
+ @Override\r
+ public void SetUserTransform(vtkLinearTransform id0) {\r
+ super.SetUserTransform(id0);\r
+ updateTextLoc();\r
+ }\r
+ \r
+ @Override\r
+ public void Delete() {\r
+ ren.RemoveActor(xactor);\r
+ ren.RemoveActor(yactor);\r
+ ren.RemoveActor(zactor);\r
+ ren.RemoveActor(tubeActor);\r
+ ren.RemoveActor(xconeActor);\r
+ ren.RemoveActor(yconeActor);\r
+ ren.RemoveActor(xconeActor);\r
+ xactor.Delete();\r
+ yactor.Delete();\r
+ zactor.Delete();\r
+ tubeActor.Delete();\r
+ xconeActor.Delete();\r
+ yconeActor.Delete();\r
+ zconeActor.Delete();\r
+ super.Delete();\r
+ }\r
+\r
+ public void dispose() {\r
+ ThreadUtils.asyncExec(AWTThread.getThreadAccess(), new Runnable() {\r
+ \r
+ @Override\r
+ public void run() {\r
+ removeFromRenderer();\r
+ Delete();\r
+ }\r
+ });\r
+ }\r
+ \r
+ @Override\r
+ public vtkProp3D getVtkProp() {\r
+ return this;\r
+ }\r
+ \r
+}\r
--- /dev/null
+package org.simantics.g3d.vtk.shape;\r
+\r
+import javax.vecmath.Matrix4d;\r
+import javax.vecmath.Point3d;\r
+\r
+import org.simantics.g3d.math.MathTools;\r
+import org.simantics.utils.threads.AWTThread;\r
+import org.simantics.utils.threads.ThreadUtils;\r
+\r
+import vtk.vtkActor;\r
+import vtk.vtkAssembly;\r
+import vtk.vtkAxes;\r
+import vtk.vtkConeSource;\r
+import vtk.vtkLinearTransform;\r
+import vtk.vtkMatrix4x4;\r
+import vtk.vtkPolyDataMapper;\r
+import vtk.vtkProp3D;\r
+import vtk.vtkRenderer;\r
+import vtk.vtkSphereSource;\r
+import vtk.vtkTextActor;\r
+import vtk.vtkTubeFilter;\r
+\r
+public class axesSphereActor extends vtkAssembly implements IvtkVisualObject{\r
+\r
+ private vtkRenderer ren;\r
+ private double axisLength = 0.8;\r
+ private vtkTextActor xactor, yactor, zactor;\r
+ private vtkActor tubeActor;\r
+ private vtkActor xconeActor;\r
+ private vtkActor yconeActor;\r
+ private vtkActor zconeActor;\r
+ private vtkActor oBallActor;\r
+ private boolean rendered = false;\r
+\r
+ public axesSphereActor(vtkRenderer _ren) {\r
+ super();\r
+ ren = _ren;\r
+ createAxes();\r
+ }\r
+ \r
+ public axesSphereActor(vtkRenderer _ren, double axisLength) {\r
+ super();\r
+ ren = _ren;\r
+ this.axisLength = axisLength;\r
+ createAxes();\r
+ }\r
+\r
+ public void createAxes() {\r
+ vtkAxes axes = new vtkAxes();\r
+ axes.SetOrigin(0, 0, 0);\r
+ axes.SetScaleFactor(axisLength);\r
+\r
+\r
+\r
+ vtkTubeFilter tube = new vtkTubeFilter();\r
+ tube.SetInput(axes.GetOutput());\r
+ tube.SetRadius(0.05 * axisLength);\r
+ tube.SetNumberOfSides(8);\r
+\r
+ vtkPolyDataMapper tubeMapper = new vtkPolyDataMapper();\r
+ tubeMapper.SetInput(tube.GetOutput());\r
+\r
+ tubeActor = new vtkActor();\r
+ tubeActor.SetMapper(tubeMapper);\r
+ tubeActor.PickableOff();\r
+\r
+ int coneRes = 12;\r
+ double coneScale = 0.3 * axisLength;\r
+\r
+ // --- x-Cone\r
+ vtkConeSource xcone = new vtkConeSource();\r
+ xcone.SetResolution(coneRes);\r
+ vtkPolyDataMapper xconeMapper = new vtkPolyDataMapper();\r
+ xconeMapper.SetInput(xcone.GetOutput());\r
+ xconeActor = new vtkActor();\r
+ xconeActor.SetMapper(xconeMapper);\r
+ xconeActor.GetProperty().SetColor(1, 0, 0);\r
+ xconeActor.SetScale(coneScale, coneScale, coneScale);\r
+ xconeActor.SetPosition(axisLength, 0.0, 0.0);\r
+ xconeActor.SetPickable(0);\r
+\r
+ // --- y-Cone\r
+ vtkConeSource ycone = new vtkConeSource();\r
+ ycone.SetResolution(coneRes);\r
+ vtkPolyDataMapper yconeMapper = new vtkPolyDataMapper();\r
+ yconeMapper.SetInput(ycone.GetOutput());\r
+ yconeActor = new vtkActor();\r
+ yconeActor.SetMapper(yconeMapper);\r
+ yconeActor.GetProperty().SetColor(1, 1, 0);\r
+ yconeActor.RotateZ(90);\r
+ yconeActor.SetScale(coneScale, coneScale, coneScale);\r
+ yconeActor.SetPosition(0.0, axisLength, 0.0);\r
+ yconeActor.SetPickable(0);\r
+\r
+ // --- z-Cone\r
+ vtkConeSource zcone = new vtkConeSource();\r
+ zcone.SetResolution(coneRes);\r
+ vtkPolyDataMapper zconeMapper = new vtkPolyDataMapper();\r
+ zconeMapper.SetInput(zcone.GetOutput());\r
+ zconeActor = new vtkActor();\r
+ zconeActor.SetMapper(zconeMapper);\r
+ zconeActor.GetProperty().SetColor(0, 1, 0);\r
+ zconeActor.RotateY(-90);\r
+ zconeActor.SetScale(coneScale, coneScale, coneScale);\r
+ zconeActor.SetPosition(0.0, 0.0, axisLength);\r
+ zconeActor.SetPickable(0);\r
+\r
+ vtkSphereSource ball = new vtkSphereSource();\r
+ ball.SetRadius(axisLength * 0.3);\r
+ ball.SetPhiResolution(6);\r
+ ball.SetThetaResolution(8);\r
+ vtkPolyDataMapper ballMapper = new vtkPolyDataMapper();\r
+ ballMapper.SetInput(ball.GetOutput());\r
+ oBallActor = new vtkActor();\r
+ oBallActor.SetMapper(ballMapper);\r
+ oBallActor.GetProperty().SetColor(0, 0, 1);\r
+ oBallActor.SetPickable(0);\r
+ \r
+ \r
+ this.AddPart(tubeActor);\r
+ this.AddPart(xconeActor);\r
+ this.AddPart(yconeActor);\r
+ this.AddPart(zconeActor);\r
+ this.AddPart(oBallActor);\r
+ \r
+ tube.GetOutput().Delete();\r
+ xcone.GetOutput().Delete();\r
+ ycone.GetOutput().Delete();\r
+ zcone.GetOutput().Delete();\r
+ axes.GetOutput().Delete();\r
+ ball.GetOutput().Delete();\r
+ axes.Delete();\r
+ tube.Delete();\r
+ xcone.Delete();\r
+ ycone.Delete();\r
+ zcone.Delete();\r
+ ball.Delete();\r
+ tubeMapper.Delete();\r
+ xconeMapper.Delete();\r
+ yconeMapper.Delete();\r
+ zconeMapper.Delete();\r
+ ballMapper.Delete();\r
+ \r
+ xconeActor.GetProperty().Delete();\r
+ yconeActor.GetProperty().Delete();\r
+ zconeActor.GetProperty().Delete();\r
+ oBallActor.GetProperty().Delete();\r
+ \r
+ \r
+ xactor = new vtkTextActor();\r
+ yactor = new vtkTextActor();\r
+ zactor = new vtkTextActor();\r
+\r
+ xactor.SetInput("X");\r
+ yactor.SetInput("Y");\r
+ zactor.SetInput("Z");\r
+\r
+// xactor.SetTextScaleModeToViewport();\r
+// yactor.SetTextScaleModeToViewport();\r
+// zactor.SetTextScaleModeToViewport();\r
+ xactor.SetTextScaleModeToNone();\r
+ yactor.SetTextScaleModeToNone();\r
+ zactor.SetTextScaleModeToNone();\r
+ \r
+ xactor.GetTextProperty().SetColor(0.0, 0.0, 0.0);\r
+ xactor.GetTextProperty().ShadowOff();\r
+ xactor.GetTextProperty().ItalicOff();\r
+ xactor.GetTextProperty().BoldOff();\r
+\r
+ yactor.GetTextProperty().SetColor(0.0, 0.0, 0.0);\r
+ yactor.GetTextProperty().ShadowOff();\r
+ yactor.GetTextProperty().ItalicOff();\r
+ yactor.GetTextProperty().BoldOff();\r
+\r
+ zactor.GetTextProperty().SetColor(0.0, 0.0, 0.0);\r
+ zactor.GetTextProperty().ShadowOff();\r
+ zactor.GetTextProperty().ItalicOff();\r
+ zactor.GetTextProperty().BoldOff();\r
+ \r
+ xactor.GetTextProperty().Delete();\r
+ yactor.GetTextProperty().Delete();\r
+ zactor.GetTextProperty().Delete();\r
+\r
+ xactor.SetMaximumLineHeight(0.25);\r
+ yactor.SetMaximumLineHeight(0.25);\r
+ zactor.SetMaximumLineHeight(0.25);\r
+ \r
+ xactor.SetPickable(0);\r
+ yactor.SetPickable(0);\r
+ zactor.SetPickable(0);\r
+ }\r
+ \r
+ public void addToRenderer() {\r
+ if (rendered)\r
+ return;\r
+ rendered = true;\r
+ \r
+ ren.AddActor2D(xactor);\r
+ ren.AddActor2D(yactor);\r
+ ren.AddActor2D(zactor);\r
+ \r
+ \r
+ ren.AddActor(this);\r
+ }\r
+ \r
+ public void removeFromRenderer() {\r
+ if (!rendered)\r
+ return;\r
+ rendered = false;\r
+ ren.RemoveActor2D(xactor);\r
+ ren.RemoveActor2D(yactor);\r
+ ren.RemoveActor2D(zactor);\r
+ ren.RemoveActor(this);\r
+ }\r
+ \r
+ public boolean isRendered() {\r
+ return rendered;\r
+ }\r
+\r
+ public void setAxesVisibility(boolean ison) {\r
+ this.SetVisibility(ison ? 1 : 0);\r
+ xactor.SetVisibility(ison ? 1 : 0);\r
+ yactor.SetVisibility(ison ? 1 : 0);\r
+ zactor.SetVisibility(ison ? 1 : 0);\r
+ }\r
+ \r
+ private boolean labelVisible = true;\r
+ public void setLabelVisibility(boolean ison) {\r
+ xactor.SetVisibility(ison ? 1 : 0);\r
+ yactor.SetVisibility(ison ? 1 : 0);\r
+ zactor.SetVisibility(ison ? 1 : 0);\r
+ labelVisible = ison;\r
+ if (labelVisible)\r
+ updateTextLoc();\r
+ }\r
+ \r
+ Matrix4d m = new Matrix4d();\r
+ double mat[] = new double[16];\r
+ Point3d x = new Point3d();\r
+ Point3d y = new Point3d();\r
+ Point3d z = new Point3d();\r
+ \r
+ private void updateTextLoc() {\r
+ if (!labelVisible)\r
+ return;\r
+ xactor.GetPositionCoordinate().SetCoordinateSystemToWorld();\r
+ yactor.GetPositionCoordinate().SetCoordinateSystemToWorld();\r
+ zactor.GetPositionCoordinate().SetCoordinateSystemToWorld();\r
+\r
+ GetMatrix(mat);\r
+ MathTools.set(m, mat);\r
+ x.set(axisLength, 0,0);\r
+ y.set(0,axisLength, 0);\r
+ z.set(0,0,axisLength);\r
+ \r
+ m.transform(x);\r
+ m.transform(y);\r
+ m.transform(z);\r
+ xactor.GetPositionCoordinate().SetValue(x.x, x.y, x.z);\r
+ yactor.GetPositionCoordinate().SetValue(y.x, y.y, y.z);\r
+ zactor.GetPositionCoordinate().SetValue(z.x, z.y, z.z);\r
+ \r
+ xactor.GetPositionCoordinate().Delete();\r
+ yactor.GetPositionCoordinate().Delete();\r
+ zactor.GetPositionCoordinate().Delete();\r
+ }\r
+ \r
+ @Override\r
+ public void SetPickable(int id0) {\r
+ super.SetPickable(id0);\r
+ tubeActor.SetPickable(id0);\r
+ xconeActor.SetPickable(id0);\r
+ yconeActor.SetPickable(id0);\r
+ zconeActor.SetPickable(id0);\r
+ oBallActor.SetPickable(id0);\r
+\r
+ }\r
+ \r
+ @Override\r
+ public void SetOrientation(double id0, double id1, double id2) {\r
+ super.SetOrientation(id0, id1, id2);\r
+ updateTextLoc();\r
+ }\r
+ \r
+ @Override\r
+ public void RotateWXYZ(double id0, double id1, double id2, double id3) {\r
+ super.RotateWXYZ(id0, id1, id2, id3);\r
+ updateTextLoc();\r
+ }\r
+ \r
+ @Override\r
+ public void SetPosition(double[] id0) {\r
+ super.SetPosition(id0);\r
+ updateTextLoc();\r
+ }\r
+ \r
+ @Override\r
+ public void SetPosition(double id0, double id1, double id2) {\r
+ super.SetPosition(id0, id1, id2);\r
+ updateTextLoc();\r
+ }\r
+ \r
+ @Override\r
+ public void SetOrientation(double[] id0) {\r
+ super.SetOrientation(id0);\r
+ updateTextLoc();\r
+ }\r
+ \r
+ @Override\r
+ public void SetScale(double id0) {\r
+ super.SetScale(id0);\r
+ updateTextLoc();\r
+ }\r
+ \r
+ @Override\r
+ public void SetScale(double id0, double id1, double id2) {\r
+ super.SetScale(id0, id1, id2);\r
+ updateTextLoc();\r
+ }\r
+ \r
+ @Override\r
+ public void SetScale(double[] id0) {\r
+ super.SetScale(id0);\r
+ updateTextLoc();\r
+ }\r
+ \r
+ @Override\r
+ public void SetUserMatrix(vtkMatrix4x4 id0) {\r
+ super.SetUserMatrix(id0);\r
+ updateTextLoc();\r
+ }\r
+ \r
+ @Override\r
+ public void SetUserTransform(vtkLinearTransform id0) {\r
+ super.SetUserTransform(id0);\r
+ updateTextLoc();\r
+ }\r
+ \r
+ @Override\r
+ public void Delete() {\r
+ ren.RemoveActor(xactor);\r
+ ren.RemoveActor(yactor);\r
+ ren.RemoveActor(zactor);\r
+ ren.RemoveActor(tubeActor);\r
+ ren.RemoveActor(xconeActor);\r
+ ren.RemoveActor(yconeActor);\r
+ ren.RemoveActor(xconeActor);\r
+ xactor.Delete();\r
+ yactor.Delete();\r
+ zactor.Delete();\r
+ tubeActor.Delete();\r
+ xconeActor.Delete();\r
+ yconeActor.Delete();\r
+ zconeActor.Delete();\r
+ super.Delete();\r
+ }\r
+\r
+ public void dispose() {\r
+ ThreadUtils.asyncExec(AWTThread.getThreadAccess(), new Runnable() {\r
+ \r
+ @Override\r
+ public void run() {\r
+ removeFromRenderer();\r
+ Delete();\r
+ }\r
+ });\r
+ }\r
+ \r
+ @Override\r
+ public vtkProp3D getVtkProp() {\r
+ return this;\r
+ }\r
+ \r
+}\r
--- /dev/null
+package org.simantics.g3d.vtk.shape;\r
+\r
+import javax.vecmath.AxisAngle4d;\r
+import javax.vecmath.Matrix4d;\r
+import javax.vecmath.Point3d;\r
+import javax.vecmath.Vector3d;\r
+\r
+import org.simantics.g3d.math.MathTools;\r
+import org.simantics.g3d.shape.Color4d;\r
+import org.simantics.g3d.shape.Cone;\r
+import org.simantics.g3d.shape.Cylinder;\r
+import org.simantics.g3d.shape.Mesh;\r
+import org.simantics.g3d.shape.Sphere;\r
+\r
+import vtk.vtkLinearTransform;\r
+import vtk.vtkMatrix4x4;\r
+import vtk.vtkRenderer;\r
+import vtk.vtkTextActor;\r
+\r
+public class axesSphereActor2 extends MeshActor{\r
+ \r
+ private double axisLength;\r
+ private vtkRenderer ren;\r
+ private vtkTextActor xactor, yactor, zactor;\r
+ \r
+ public axesSphereActor2(vtkRenderer ren, double size) {\r
+ int res = 16;\r
+ axisLength = size;\r
+ this.ren = ren;\r
+ Mesh cone_x = Cone.create(size*0.3, res);\r
+ Mesh cone_y = Cone.create(size*0.3, res);\r
+ Mesh cone_z = Cone.create(size*0.3, res);\r
+ cone_x.rotate(MathTools.getQuat(new AxisAngle4d(0,0,-1,Math.PI*0.5)));\r
+ cone_z.rotate(MathTools.getQuat(new AxisAngle4d(1,0,0,Math.PI*0.5)));\r
+ cone_x.translate(new Vector3d(size,0,0));\r
+ cone_y.translate(new Vector3d(0,size,0));\r
+ cone_z.translate(new Vector3d(0,0,size));\r
+ \r
+ Mesh tube_x = Cylinder.create(MathTools.ORIGIN, new Vector3d(size,0,0), size*0.1, res);\r
+ Mesh tube_y = Cylinder.create(MathTools.ORIGIN, new Vector3d(0,size,0), size*0.1, res);\r
+ Mesh tube_z = Cylinder.create(MathTools.ORIGIN, new Vector3d(0,0,size), size*0.1, res);\r
+ \r
+ Mesh sphere = Sphere.create(size*0.3, res, res*2/3);\r
+ \r
+ Color4d x_col = new Color4d(1,0,0,1);\r
+ Color4d y_col = new Color4d(1,1,0,1);\r
+ Color4d z_col = new Color4d(0,1,0,1);\r
+ Color4d o_col = new Color4d(0,0,1,1);\r
+ \r
+ cone_x.setColor(x_col);\r
+ tube_x.setColor(x_col);\r
+ cone_y.setColor(y_col);\r
+ tube_y.setColor(y_col);\r
+ cone_z.setColor(z_col);\r
+ tube_z.setColor(z_col);\r
+ sphere.setColor(o_col);\r
+ \r
+ sphere.add(cone_x);\r
+ sphere.add(tube_x);\r
+ sphere.add(cone_y);\r
+ sphere.add(tube_y);\r
+ sphere.add(cone_z);\r
+ sphere.add(tube_z);\r
+ \r
+ setMesh(sphere);\r
+ \r
+ \r
+ \r
+ xactor = new vtkTextActor();\r
+ yactor = new vtkTextActor();\r
+ zactor = new vtkTextActor();\r
+\r
+ xactor.SetInput("X");\r
+ yactor.SetInput("Y");\r
+ zactor.SetInput("Z");\r
+ \r
+ xactor.SetTextScaleModeToNone();\r
+ yactor.SetTextScaleModeToNone();\r
+ zactor.SetTextScaleModeToNone();\r
+ \r
+ xactor.GetTextProperty().SetColor(0.0, 0.0, 0.0);\r
+ xactor.GetTextProperty().ShadowOff();\r
+ xactor.GetTextProperty().ItalicOff();\r
+ xactor.GetTextProperty().BoldOff();\r
+\r
+ yactor.GetTextProperty().SetColor(0.0, 0.0, 0.0);\r
+ yactor.GetTextProperty().ShadowOff();\r
+ yactor.GetTextProperty().ItalicOff();\r
+ yactor.GetTextProperty().BoldOff();\r
+\r
+ zactor.GetTextProperty().SetColor(0.0, 0.0, 0.0);\r
+ zactor.GetTextProperty().ShadowOff();\r
+ zactor.GetTextProperty().ItalicOff();\r
+ zactor.GetTextProperty().BoldOff();\r
+ \r
+ xactor.GetTextProperty().Delete();\r
+ yactor.GetTextProperty().Delete();\r
+ zactor.GetTextProperty().Delete();\r
+\r
+ xactor.SetMaximumLineHeight(0.25);\r
+ yactor.SetMaximumLineHeight(0.25);\r
+ zactor.SetMaximumLineHeight(0.25);\r
+ \r
+ xactor.SetPickable(0);\r
+ yactor.SetPickable(0);\r
+ zactor.SetPickable(0);\r
+ }\r
+ \r
+ private boolean labelVisible = false;\r
+ public void setLabelVisibility(boolean ison) {\r
+ if (ison == labelVisible)\r
+ return;\r
+ labelVisible = ison;\r
+ if (labelVisible) {\r
+ ren.AddActor2D(xactor);\r
+ ren.AddActor2D(yactor);\r
+ ren.AddActor2D(zactor);\r
+ updateTextLoc();\r
+ } else {\r
+ ren.RemoveActor2D(xactor);\r
+ ren.RemoveActor2D(yactor);\r
+ ren.RemoveActor2D(zactor);\r
+ }\r
+ \r
+ }\r
+ \r
+ Matrix4d m = new Matrix4d();\r
+ double mat[] = new double[16];\r
+ Point3d x = new Point3d();\r
+ Point3d y = new Point3d();\r
+ Point3d z = new Point3d();\r
+ \r
+ private void updateTextLoc() {\r
+ if (!labelVisible)\r
+ return;\r
+ xactor.GetPositionCoordinate().SetCoordinateSystemToWorld();\r
+ yactor.GetPositionCoordinate().SetCoordinateSystemToWorld();\r
+ zactor.GetPositionCoordinate().SetCoordinateSystemToWorld();\r
+\r
+ GetMatrix(mat);\r
+ MathTools.set(m, mat);\r
+ x.set(axisLength, 0,0);\r
+ y.set(0,axisLength, 0);\r
+ z.set(0,0,axisLength);\r
+ \r
+ m.transform(x);\r
+ m.transform(y);\r
+ m.transform(z);\r
+ xactor.GetPositionCoordinate().SetValue(x.x, x.y, x.z);\r
+ yactor.GetPositionCoordinate().SetValue(y.x, y.y, y.z);\r
+ zactor.GetPositionCoordinate().SetValue(z.x, z.y, z.z);\r
+ \r
+ xactor.GetPositionCoordinate().Delete();\r
+ yactor.GetPositionCoordinate().Delete();\r
+ zactor.GetPositionCoordinate().Delete();\r
+ }\r
+ \r
+ @Override\r
+ public void SetOrientation(double id0, double id1, double id2) {\r
+ super.SetOrientation(id0, id1, id2);\r
+ updateTextLoc();\r
+ }\r
+ \r
+ @Override\r
+ public void RotateWXYZ(double id0, double id1, double id2, double id3) {\r
+ super.RotateWXYZ(id0, id1, id2, id3);\r
+ updateTextLoc();\r
+ }\r
+ \r
+ @Override\r
+ public void SetPosition(double[] id0) {\r
+ super.SetPosition(id0);\r
+ updateTextLoc();\r
+ }\r
+ \r
+ @Override\r
+ public void SetPosition(double id0, double id1, double id2) {\r
+ super.SetPosition(id0, id1, id2);\r
+ updateTextLoc();\r
+ }\r
+ \r
+ @Override\r
+ public void SetOrientation(double[] id0) {\r
+ super.SetOrientation(id0);\r
+ updateTextLoc();\r
+ }\r
+ \r
+ @Override\r
+ public void SetScale(double id0) {\r
+ super.SetScale(id0);\r
+ updateTextLoc();\r
+ }\r
+ \r
+ @Override\r
+ public void SetScale(double id0, double id1, double id2) {\r
+ super.SetScale(id0, id1, id2);\r
+ updateTextLoc();\r
+ }\r
+ \r
+ @Override\r
+ public void SetScale(double[] id0) {\r
+ super.SetScale(id0);\r
+ updateTextLoc();\r
+ }\r
+ \r
+ @Override\r
+ public void SetUserMatrix(vtkMatrix4x4 id0) {\r
+ super.SetUserMatrix(id0);\r
+ updateTextLoc();\r
+ }\r
+ \r
+ @Override\r
+ public void SetUserTransform(vtkLinearTransform id0) {\r
+ super.SetUserTransform(id0);\r
+ updateTextLoc();\r
+ }\r
+ \r
+ @Override\r
+ public void Delete() {\r
+ ren.RemoveActor(xactor);\r
+ ren.RemoveActor(yactor);\r
+ ren.RemoveActor(zactor);\r
+ xactor.Delete();\r
+ yactor.Delete();\r
+ zactor.Delete();\r
+ super.Delete();\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.g3d.vtk.shape;\r
+\r
+import javax.vecmath.AxisAngle4d;\r
+import javax.vecmath.Matrix4d;\r
+import javax.vecmath.Point3d;\r
+import javax.vecmath.Vector3d;\r
+\r
+import org.simantics.g3d.math.MathTools;\r
+import org.simantics.utils.threads.AWTThread;\r
+import org.simantics.utils.threads.ThreadUtils;\r
+\r
+import vtk.vtkActor;\r
+import vtk.vtkAssembly;\r
+import vtk.vtkConeSource;\r
+import vtk.vtkLineSource;\r
+import vtk.vtkLinearTransform;\r
+import vtk.vtkMatrix4x4;\r
+import vtk.vtkPolyDataMapper;\r
+import vtk.vtkProp3D;\r
+import vtk.vtkRenderer;\r
+import vtk.vtkTextActor;\r
+import vtk.vtkTubeFilter;\r
+\r
+public class axisActor extends vtkAssembly implements IvtkVisualObject{\r
+\r
+ private vtkRenderer ren;\r
+ private Vector3d axisDir = new Vector3d(1,0,0);\r
+ private vtkTextActor tactor;\r
+ private vtkActor tubeActor;\r
+ private vtkActor coneActor;\r
+ private boolean rendered = false;\r
+\r
+ public axisActor(vtkRenderer _ren, String label) {\r
+ super();\r
+ ren = _ren;\r
+ createAxis(label);\r
+ }\r
+ \r
+ public axisActor(vtkRenderer _ren, String label, Vector3d dir) {\r
+ super();\r
+ ren = _ren;\r
+ this.axisDir = dir;\r
+ createAxis(label);\r
+ }\r
+\r
+ public void createAxis(String label) {\r
+ vtkLineSource line = new vtkLineSource();\r
+ line.SetPoint1(0.0,0.0,0.0);\r
+ line.SetPoint2(axisDir.x,axisDir.y,axisDir.z);\r
+ \r
+ tactor = new vtkTextActor();\r
+ \r
+ tactor.SetInput(label);\r
+ \r
+ tactor.SetTextScaleModeToNone();\r
+ tactor.GetTextProperty().SetColor(0.0, 0.0, 0.0);\r
+ tactor.GetTextProperty().ShadowOff();\r
+ tactor.GetTextProperty().ItalicOff();\r
+ tactor.GetTextProperty().BoldOff();\r
+ \r
+ tactor.GetTextProperty().Delete();\r
+ \r
+ tactor.SetMaximumLineHeight(0.25);\r
+ \r
+ tactor.SetPickable(0);\r
+ \r
+ vtkTubeFilter tube = new vtkTubeFilter();\r
+ tube.SetInput(line.GetOutput());\r
+ tube.SetRadius(0.05 * axisDir.length());\r
+ tube.SetNumberOfSides(8);\r
+\r
+ vtkPolyDataMapper tubeMapper = new vtkPolyDataMapper();\r
+ tubeMapper.SetInput(tube.GetOutput());\r
+\r
+ tubeActor = new vtkActor();\r
+ tubeActor.SetMapper(tubeMapper);\r
+ tubeActor.PickableOff();\r
+\r
+ int coneRes = 12;\r
+ double coneScale = 0.3 * axisDir.length();\r
+\r
+ // --- x-Cone\r
+ vtkConeSource cone = new vtkConeSource();\r
+ cone.SetResolution(coneRes);\r
+ vtkPolyDataMapper coneMapper = new vtkPolyDataMapper();\r
+ coneMapper.SetInput(cone.GetOutput());\r
+ coneActor = new vtkActor();\r
+ coneActor.SetMapper(coneMapper);\r
+ coneActor.GetProperty().SetColor(1, 0, 0);\r
+ coneActor.SetScale(coneScale, coneScale, coneScale);\r
+ coneActor.SetPosition(axisDir.x,axisDir.y,axisDir.z);\r
+ coneActor.SetPickable(0);\r
+ \r
+ AxisAngle4d aa = MathTools.createRotation(new Vector3d(1,0,0), new Vector3d(axisDir));\r
+ if (aa != null)\r
+ coneActor.RotateWXYZ(MathTools.radToDeg(aa.angle), aa.x, aa.y, aa.z);\r
+ \r
+ this.AddPart(tubeActor);\r
+ this.AddPart(coneActor);\r
+ \r
+ tube.GetOutput().Delete();\r
+ cone.GetOutput().Delete();\r
+ line.GetOutput().Delete();\r
+ \r
+ tubeMapper.Delete();\r
+ tube.Delete();\r
+ cone.Delete();\r
+ line.Delete();\r
+\r
+ coneMapper.Delete();\r
+ \r
+ coneActor.GetProperty().Delete();\r
+ }\r
+ \r
+ public void addToRenderer() {\r
+ if (rendered)\r
+ return;\r
+ rendered = true;\r
+ \r
+ ren.AddActor2D(tactor);\r
+ \r
+ ren.AddActor(this);\r
+ }\r
+ \r
+ public void removeFromRenderer() {\r
+ if (!rendered)\r
+ return;\r
+ rendered = false;\r
+ ren.RemoveActor2D(tactor);\r
+ ren.RemoveActor(this);\r
+ }\r
+ \r
+ public boolean isRendered() {\r
+ return rendered;\r
+ }\r
+\r
+ public void setAxesVisibility(boolean ison) {\r
+ this.SetVisibility(ison ? 1 : 0);\r
+ tactor.SetVisibility(ison ? 1 : 0);\r
+ }\r
+ \r
+ public void setLabelVisibility(boolean ison) {\r
+ tactor.SetVisibility(ison ? 1 : 0);\r
+ }\r
+ \r
+ double mat[] = new double[16];\r
+ Matrix4d m = new Matrix4d();\r
+ Point3d p = new Point3d();\r
+ private void updateTextLoc() {\r
+ tactor.GetPositionCoordinate().SetCoordinateSystemToWorld();\r
+ \r
+ \r
+ GetMatrix(mat);\r
+ MathTools.set(m, mat);\r
+ p.set(axisDir.x, axisDir.y,axisDir.z);\r
+ m.transform(p);\r
+ tactor.GetPositionCoordinate().SetValue(p.x, p.y, p.z);\r
+ \r
+ tactor.GetPositionCoordinate().Delete();\r
+ }\r
+ \r
+ @Override\r
+ public void SetPickable(int id0) {\r
+ super.SetPickable(id0);\r
+ tubeActor.SetPickable(id0);\r
+ coneActor.SetPickable(id0);\r
+ }\r
+ \r
+ @Override\r
+ public void SetOrientation(double id0, double id1, double id2) {\r
+ super.SetOrientation(id0, id1, id2);\r
+ updateTextLoc();\r
+ }\r
+ \r
+ @Override\r
+ public void RotateWXYZ(double id0, double id1, double id2, double id3) {\r
+ super.RotateWXYZ(id0, id1, id2, id3);\r
+ updateTextLoc();\r
+ }\r
+ \r
+ @Override\r
+ public void SetPosition(double[] id0) {\r
+ super.SetPosition(id0);\r
+ updateTextLoc();\r
+ }\r
+ \r
+ @Override\r
+ public void SetPosition(double id0, double id1, double id2) {\r
+ super.SetPosition(id0, id1, id2);\r
+ updateTextLoc();\r
+ }\r
+ \r
+ @Override\r
+ public void SetOrientation(double[] id0) {\r
+ super.SetOrientation(id0);\r
+ updateTextLoc();\r
+ }\r
+ \r
+ @Override\r
+ public void SetScale(double id0) {\r
+ super.SetScale(id0);\r
+ updateTextLoc();\r
+ }\r
+ \r
+ @Override\r
+ public void SetScale(double id0, double id1, double id2) {\r
+ super.SetScale(id0, id1, id2);\r
+ updateTextLoc();\r
+ }\r
+ \r
+ @Override\r
+ public void SetScale(double[] id0) {\r
+ super.SetScale(id0);\r
+ updateTextLoc();\r
+ }\r
+ \r
+ public void SetColor(double r, double g, double b) {\r
+ coneActor.GetProperty().SetColor(r, g, b);\r
+ tubeActor.GetProperty().SetColor(r, g, b);\r
+ coneActor.GetProperty().Delete();\r
+ tubeActor.GetProperty().Delete();\r
+ }\r
+ \r
+ public void SetTextColor(double r, double g, double b) {\r
+ tactor.GetTextProperty().SetColor(r, g, b);\r
+ tactor.GetTextProperty().Delete();\r
+ }\r
+ \r
+ @Override\r
+ public void SetUserMatrix(vtkMatrix4x4 id0) {\r
+ super.SetUserMatrix(id0);\r
+ updateTextLoc();\r
+ }\r
+ \r
+ @Override\r
+ public void SetUserTransform(vtkLinearTransform id0) {\r
+ super.SetUserTransform(id0);\r
+ updateTextLoc();\r
+ }\r
+ \r
+ @Override\r
+ public void Delete() {\r
+ ren.RemoveActor(tactor);\r
+ ren.RemoveActor(tubeActor);\r
+ ren.RemoveActor(coneActor);\r
+ tactor.Delete();\r
+ tubeActor.Delete();\r
+ coneActor.Delete();\r
+ super.Delete();\r
+ }\r
+\r
+ public void dispose() {\r
+ ThreadUtils.asyncExec(AWTThread.getThreadAccess(), new Runnable() {\r
+ \r
+ @Override\r
+ public void run() {\r
+ removeFromRenderer();\r
+ Delete();\r
+ }\r
+ });\r
+ }\r
+ \r
+ @Override\r
+ public vtkProp3D getVtkProp() {\r
+ return this;\r
+ }\r
+ \r
+}\r
--- /dev/null
+package org.simantics.g3d.vtk.shape;\r
+\r
+import javax.vecmath.Tuple3d;\r
+\r
+import vtk.vtkActor;\r
+import vtk.vtkDataSetMapper;\r
+import vtk.vtkLine;\r
+import vtk.vtkPoints;\r
+import vtk.vtkPolyLine;\r
+import vtk.vtkUnstructuredGrid;\r
+\r
+public class vtkShape {\r
+ \r
+ /**\r
+ * Creates a grid shaped actor.\r
+ * \r
+ * @param size number of grid lines\r
+ * @param space distance between grid lines\r
+ * @param axes bitmask of axes: 1:x, 2:y, 4:z\r
+ * @return vtkActor representing a grid.\r
+ */\r
+ public static vtkActor createGridActor(int size, double space, int axes) {\r
+ int gridCount = 0;\r
+ if ((axes & 0x1) > 0) {\r
+ gridCount++;\r
+ }\r
+ if ((axes & 0x2) > 0) {\r
+ gridCount++;\r
+ }\r
+ if ((axes & 0x4) > 0) {\r
+ gridCount++;\r
+ }\r
+ int pointCount = (size+1) * 2 * 2 * gridCount;\r
+ vtkPoints linePoints = new vtkPoints();\r
+ linePoints.SetNumberOfPoints(pointCount);\r
+ \r
+ \r
+ double max = space * (double)size * 0.5;\r
+ double min = -max;\r
+ int base = 0;\r
+ if ((axes & 0x1) > 0) {\r
+ for (int i = 0; i <= size; i++) {\r
+ double s = min + ((double)i) * space;\r
+ linePoints.InsertPoint(base + i*2 ,0.0, s, min);\r
+ linePoints.InsertPoint(base + i*2+1,0.0, s, max);\r
+ i++;\r
+ if (i > size)\r
+ break;\r
+ s = min + ((double)i) * space;\r
+ linePoints.InsertPoint(base + i*2 ,0.0, s, max);\r
+ linePoints.InsertPoint(base + i*2+1,0.0, s, min);\r
+ }\r
+ base += (size+1)*2;\r
+ for (int i = 0; i <= size; i++) {\r
+ double s = min + ((double)i) * space;\r
+ linePoints.InsertPoint(base + i*2 , 0.0, max, s);\r
+ linePoints.InsertPoint(base + i*2+1, 0.0, min, s);\r
+ i++;\r
+ if (i > size)\r
+ break;\r
+ s = min + ((double)i) * space;\r
+ linePoints.InsertPoint(base + i*2 , 0.0, min, s);\r
+ linePoints.InsertPoint(base + i*2+1, 0.0, max, s);\r
+ }\r
+ base += (size+1)*2;\r
+ } \r
+ if ((axes & 0x4) > 0) {\r
+ for (int i = 0; i <= size; i++) {\r
+ double s = min + ((double)i) * space;\r
+ linePoints.InsertPoint(base + i*2 ,s, min, 0.0);\r
+ linePoints.InsertPoint(base + i*2+1,s, max, 0.0);\r
+ i++;\r
+ if (i > size)\r
+ break;\r
+ s = min + ((double)i) * space;\r
+ linePoints.InsertPoint(base + i*2 ,s, max, 0.0);\r
+ linePoints.InsertPoint(base + i*2+1,s, min, 0.0);\r
+ }\r
+ base += (size+1)*2;\r
+ for (int i = 0; i <= size; i++) {\r
+ double s = min + ((double)i) * space;\r
+ linePoints.InsertPoint(base + i*2 ,max, s, 0.0);\r
+ linePoints.InsertPoint(base + i*2+1,min, s, 0.0);\r
+ i++;\r
+ if (i > size)\r
+ break;\r
+ s = min + ((double)i) * space;\r
+ linePoints.InsertPoint(base + i*2 ,min, s, 0.0);\r
+ linePoints.InsertPoint(base + i*2+1,max, s, 0.0);\r
+ }\r
+ base += (size+1)*2;\r
+ } \r
+ if ((axes & 0x2) > 0) {\r
+ for (int i = 0; i <= size; i++) {\r
+ double s = min + ((double)i) * space;\r
+ linePoints.InsertPoint(base + i*2 ,s, 0.0, min);\r
+ linePoints.InsertPoint(base + i*2+1,s, 0.0, max);\r
+ i++;\r
+ if (i > size)\r
+ break;\r
+ s = min + ((double)i) * space;\r
+ linePoints.InsertPoint(base + i*2 ,s, 0.0, max);\r
+ linePoints.InsertPoint(base + i*2+1,s, 0.0, min);\r
+ }\r
+ base += (size+1)*2;\r
+ for (int i = 0; i <= size; i++) {\r
+ double s = min + ((double)i) * space;\r
+ linePoints.InsertPoint(base + i*2 ,max, 0.0, s);\r
+ linePoints.InsertPoint(base + i*2+1,min, 0.0, s);\r
+ i++;\r
+ if (i > size)\r
+ break;\r
+ s = min + ((double)i) * space;\r
+ linePoints.InsertPoint(base + i*2 ,min, 0.0, s);\r
+ linePoints.InsertPoint(base + i*2+1,max, 0.0, s);\r
+ }\r
+ base += (size+1)*2;\r
+ }\r
+ \r
+ \r
+ //vtkLine aLine = new vtkLine();\r
+ vtkPolyLine aLine = new vtkPolyLine();\r
+ aLine.GetPointIds().SetNumberOfIds(pointCount);\r
+ for (int i = 0; i < pointCount; i++) {\r
+ aLine.GetPointIds().SetId(i, i);\r
+ }\r
+ \r
+ \r
+ vtkUnstructuredGrid aLineGrid = new vtkUnstructuredGrid();\r
+ aLineGrid.Allocate(pointCount, pointCount);\r
+ aLineGrid.InsertNextCell(aLine.GetCellType(), aLine.GetPointIds());\r
+ aLineGrid.SetPoints(linePoints);\r
+ vtkDataSetMapper aLineMapper = new vtkDataSetMapper();\r
+ aLineMapper.SetInput(aLineGrid);\r
+ vtkActor aLineActor = new vtkActor();\r
+ aLineActor.SetMapper(aLineMapper);\r
+ \r
+ linePoints.Delete();\r
+ aLine.GetPointIds().Delete();\r
+ aLine.Delete();\r
+ aLineGrid.Delete();\r
+ aLineMapper.Delete();\r
+ \r
+ aLineActor.GetProperty().SetColor(0, 0, 0);\r
+ aLineActor.GetProperty().Delete();\r
+ \r
+ return aLineActor;\r
+ }\r
+ \r
+ /**\r
+ * Creates a line.\r
+ * \r
+ * @param p1\r
+ * @param p2\r
+ * @return\r
+ */\r
+ public static vtkActor createLineActor(Tuple3d p1, Tuple3d p2) {\r
+ vtkPoints linePoints = new vtkPoints();\r
+ linePoints.SetNumberOfPoints(2);\r
+ linePoints.InsertPoint(0,p1.x, p1.y, p1.z);\r
+ linePoints.InsertPoint(1,p2.x, p2.y, p2.z);\r
+ vtkLine aLine = new vtkLine();\r
+ aLine.GetPointIds().SetId(0, 0);\r
+ aLine.GetPointIds().SetId(1, 1);\r
+ vtkUnstructuredGrid aLineGrid = new vtkUnstructuredGrid();\r
+ aLineGrid.Allocate(1, 1);\r
+ aLineGrid.InsertNextCell(aLine.GetCellType(), aLine.GetPointIds());\r
+ aLineGrid.SetPoints(linePoints);\r
+ vtkDataSetMapper aLineMapper = new vtkDataSetMapper();\r
+ aLineMapper.SetInput(aLineGrid);\r
+ vtkActor aLineActor = new vtkActor();\r
+ aLineActor.SetMapper(aLineMapper);\r
+ //aLineActor.GetProperty().SetDiffuseColor(.2, 1, 1);\r
+ \r
+ linePoints.Delete();\r
+ aLine.GetPointIds().Delete();\r
+ aLine.Delete();\r
+ aLineGrid.Delete();\r
+ aLineMapper.Delete();\r
+ \r
+ return aLineActor;\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.vtk.utils;\r
+\r
+import javax.vecmath.AxisAngle4d;\r
+import javax.vecmath.Vector3d;\r
+\r
+import org.simantics.g3d.math.MathTools;\r
+import org.simantics.g3d.vtk.shape.IvtkVisualObject;\r
+\r
+import vtk.vtkActor;\r
+import vtk.vtkCamera;\r
+import vtk.vtkContourFilter;\r
+import vtk.vtkDataObject;\r
+import vtk.vtkOutlineFilter;\r
+import vtk.vtkOutlineSource;\r
+import vtk.vtkPolyData;\r
+import vtk.vtkPolyDataMapper;\r
+import vtk.vtkPolyDataSilhouette;\r
+import vtk.vtkProp3D;\r
+import vtk.vtkRenderWindow;\r
+import vtk.vtkRenderer;\r
+import vtk.vtkTransform;\r
+import vtk.vtkTransformPolyDataFilter;\r
+import vtk.vtkWindowToImageFilter;\r
+\r
+public class vtkEffect {\r
+\r
+ private static vtkRenderer tmpRenderer;\r
+ \r
+ public static vtkRenderer getRenderer() {\r
+ if (tmpRenderer == null)\r
+ tmpRenderer = new vtkRenderer();\r
+ return tmpRenderer;\r
+ }\r
+ public static vtkActor createContour(vtkProp3D tmpProp) {\r
+ \r
+ vtkRenderer tmpRenderer = getRenderer();\r
+ tmpRenderer.SetBackground(1,1,1);\r
+ \r
+ \r
+ if (tmpProp instanceof IvtkVisualObject) {\r
+ ((IvtkVisualObject)tmpProp).addToRenderer();\r
+ } else {\r
+ tmpRenderer.AddActor(tmpProp);\r
+ }\r
+ \r
+ if (tmpProp instanceof vtkActor) {\r
+ ((vtkActor)tmpProp).GetProperty().SetColor(0, 0, 0);\r
+ }\r
+ \r
+ \r
+ double bounds_data[] = tmpProp.GetBounds();\r
+ double center_data[] = tmpProp.GetCenter();\r
+ \r
+ tmpRenderer.ResetCamera();\r
+ tmpRenderer.GetActiveCamera().SetParallelProjection(1);\r
+ \r
+ vtkRenderWindow tmpRenderWindow = new vtkRenderWindow();\r
+ tmpRenderWindow.SetOffScreenRendering(1);\r
+ tmpRenderWindow.AddRenderer(tmpRenderer);\r
+ tmpRenderWindow.Render();\r
+ \r
+ vtkWindowToImageFilter windowToImageFilter = new vtkWindowToImageFilter();\r
+ windowToImageFilter.SetInput(tmpRenderWindow);\r
+ windowToImageFilter.SetMagnification(2);\r
+ windowToImageFilter.Update();\r
+ \r
+ vtkContourFilter contourFilter = new vtkContourFilter();\r
+ contourFilter.SetInputConnection(windowToImageFilter.GetOutputPort());\r
+ \r
+ contourFilter.SetValue(0, 255);\r
+ contourFilter.Update();\r
+ \r
+ vtkPolyData contour = contourFilter.GetOutput();\r
+ \r
+ double bounds_contour[] = new double[6]; \r
+ double center_contour[] = new double[3];\r
+ double trans_x=0., trans_y=0., trans_z=0., ratio_x=0., ratio_y=0.;\r
+ contour.GetBounds(bounds_contour);\r
+ \r
+ ratio_x = (bounds_data[1]-bounds_data[0])/(bounds_contour[1]-bounds_contour[0]);\r
+ ratio_y = (bounds_data[3]-bounds_data[2])/(bounds_contour[3]-bounds_contour[2]);\r
+ \r
+ vtkTransform transform1 = new vtkTransform();\r
+ transform1.Scale(ratio_x,ratio_y,1);\r
+ \r
+ vtkTransformPolyDataFilter tFilter1 = new vtkTransformPolyDataFilter();\r
+ tFilter1.SetInput(contour);\r
+ tFilter1.SetTransform(transform1);\r
+ tFilter1.Update();\r
+ \r
+ contour = tFilter1.GetOutput();\r
+ \r
+ contour.GetCenter(center_contour);\r
+ trans_x = center_data[0]-center_contour[0];\r
+ trans_y = center_data[1]-center_contour[1];\r
+ trans_z = center_data[2]-center_contour[2];\r
+\r
+ vtkTransform transform2 = new vtkTransform();\r
+ transform2.Translate( trans_x, trans_y, trans_z);\r
+ \r
+ vtkTransformPolyDataFilter tFilter2 = new vtkTransformPolyDataFilter();\r
+ tFilter2.SetInput(contour);\r
+ tFilter2.SetTransform(transform2);\r
+ tFilter2.Update();\r
+ \r
+ contour = tFilter2.GetOutput();\r
+ \r
+ vtkPolyDataMapper mapper = new vtkPolyDataMapper();\r
+ mapper.SetInput(contour);\r
+ \r
+ \r
+ vtkActor actor =new vtkActor();\r
+ actor.SetMapper(mapper);\r
+ actor.GetProperty().SetLineWidth(2.);\r
+ \r
+ tmpRenderer.RemoveActor(tmpProp);\r
+ \r
+ tFilter1.Delete();\r
+ tFilter2.Delete();\r
+ contour.Delete();\r
+ contourFilter.Delete();\r
+ mapper.Delete();\r
+ tmpRenderWindow.Delete();\r
+ transform1.Delete();\r
+ transform2.Delete();\r
+ windowToImageFilter.Delete();\r
+ \r
+ return actor;\r
+ }\r
+ \r
+ public static vtkActor createContour(vtkProp3D tmpProp, vtkRenderer ren) {\r
+ \r
+ vtkRenderer tmpRenderer = getRenderer();\r
+ tmpRenderer.SetBackground(1,1,1);\r
+ \r
+ \r
+ if (tmpProp instanceof IvtkVisualObject) {\r
+ ((IvtkVisualObject)tmpProp).addToRenderer();\r
+ } else {\r
+ tmpRenderer.AddActor(tmpProp);\r
+ }\r
+ \r
+ if (tmpProp instanceof vtkActor) {\r
+ ((vtkActor)tmpProp).GetProperty().SetColor(0, 0, 0);\r
+ }\r
+ \r
+ \r
+ //double bounds_data[] = tmpProp.GetBounds();\r
+ double center_data[] = tmpProp.GetCenter();\r
+ \r
+ tmpRenderer.ResetCamera();\r
+ \r
+ vtkCamera camera = ren.GetActiveCamera();\r
+ \r
+ vtkCamera tmpCamera = tmpRenderer.GetActiveCamera(); \r
+ tmpCamera.SetParallelProjection(camera.GetParallelProjection());\r
+ \r
+ \r
+ Vector3d pos = new Vector3d(camera.GetPosition());\r
+ Vector3d foc = new Vector3d(camera.GetFocalPoint());\r
+ Vector3d dir = new Vector3d();\r
+ dir.sub(pos,foc);\r
+ double l = dir.length();\r
+// dir.scale(1.0/l);\r
+// \r
+// \r
+//\r
+// \r
+// dir.scale(2.0);\r
+// Vector3d tmpFoc = new Vector3d(tmpCamera.GetFocalPoint());\r
+// tmpFoc.add(dir);\r
+// tmpCamera.SetPosition(tmpFoc.x,tmpFoc.y,tmpFoc.z);\r
+// tmpCamera.SetRoll(camera.GetRoll());\r
+ \r
+ tmpCamera.DeepCopy(camera);\r
+ //tmpCamera.SetModelTransformMatrix(camera.GetModelTransformMatrix());\r
+ tmpCamera.UpdateViewport(tmpRenderer);\r
+ \r
+ vtkRenderWindow tmpRenderWindow = new vtkRenderWindow();\r
+ tmpRenderWindow.SetOffScreenRendering(1);\r
+ tmpRenderWindow.AddRenderer(tmpRenderer);\r
+ tmpRenderWindow.Render();\r
+ \r
+ vtkWindowToImageFilter windowToImageFilter = new vtkWindowToImageFilter();\r
+ windowToImageFilter.SetInput(tmpRenderWindow);\r
+ windowToImageFilter.SetMagnification(2);\r
+ windowToImageFilter.Update();\r
+ \r
+ vtkContourFilter contourFilter = new vtkContourFilter();\r
+ contourFilter.SetInputConnection(windowToImageFilter.GetOutputPort());\r
+ \r
+ contourFilter.SetValue(0, 255);\r
+ contourFilter.Update();\r
+ \r
+ vtkPolyData contour = contourFilter.GetOutput();\r
+ \r
+ \r
+ double or[] = camera.GetOrientationWXYZ();\r
+ AxisAngle4d aa = new AxisAngle4d();\r
+ aa.angle = -MathTools.degToRad(or[0]);\r
+ aa.x = or[1];\r
+ aa.y = or[2];\r
+ aa.z = or[3];\r
+ \r
+ vtkTransform transform0 = new vtkTransform();\r
+ transform0.RotateWXYZ(MathTools.radToDeg(aa.angle), aa.x, aa.y, aa.z);\r
+ \r
+ vtkTransformPolyDataFilter tFilter0 = new vtkTransformPolyDataFilter();\r
+ tFilter0.SetInput(contour);\r
+ tFilter0.SetTransform(transform0);\r
+ tFilter0.Update();\r
+ \r
+ contour.Delete();\r
+ contour = tFilter0.GetOutput();\r
+ \r
+ double bounds_contour[] = new double[6]; \r
+ \r
+ double trans_x=0., trans_y=0., trans_z=0., ratio_x=0.002, ratio_y=0.002, ratio_z=0.002;\r
+ contour.GetBounds(bounds_contour);\r
+// \r
+// ratio_x = (bounds_data[1]-bounds_data[0])/(bounds_contour[1]-bounds_contour[0]);\r
+// ratio_y = (bounds_data[3]-bounds_data[2])/(bounds_contour[3]-bounds_contour[2]);\r
+// ratio_z = (bounds_data[5]-bounds_data[4])/(bounds_contour[5]-bounds_contour[4]);\r
+ ratio_x = l*0.0008;\r
+ ratio_y = l*0.0008;\r
+ ratio_z = l*0.0008;\r
+ \r
+ \r
+ System.out.println(ratio_x + " " + ratio_y);\r
+ \r
+ \r
+// \r
+ vtkTransform transform1 = new vtkTransform();\r
+ transform1.Scale(ratio_x,ratio_y,ratio_z);\r
+ \r
+ vtkTransformPolyDataFilter tFilter1 = new vtkTransformPolyDataFilter();\r
+ tFilter1.SetInput(contour);\r
+ tFilter1.SetTransform(transform1);\r
+ tFilter1.Update();\r
+ \r
+ contour.Delete();\r
+ contour = tFilter1.GetOutput();\r
+ \r
+ double center_contour[] = new double[3];\r
+ contour.GetCenter(center_contour);\r
+ trans_x = center_data[0]-center_contour[0];\r
+ trans_y = center_data[1]-center_contour[1];\r
+ trans_z = center_data[2]-center_contour[2];\r
+// \r
+ System.out.println(trans_x + " " + trans_y + " " + trans_z);\r
+//\r
+ vtkTransform transform2 = new vtkTransform();\r
+ transform2.Translate( trans_x, trans_y, trans_z);\r
+ \r
+ vtkTransformPolyDataFilter tFilter2 = new vtkTransformPolyDataFilter();\r
+ tFilter2.SetInput(contour);\r
+ tFilter2.SetTransform(transform2);\r
+ tFilter2.Update();\r
+ \r
+ contour.Delete();\r
+ contour = tFilter2.GetOutput();\r
+ \r
+ vtkPolyDataMapper mapper = new vtkPolyDataMapper();\r
+ mapper.SetInput(contour);\r
+ \r
+ \r
+ vtkActor actor =new vtkActor();\r
+ actor.SetMapper(mapper);\r
+ actor.GetProperty().SetLineWidth(2.);\r
+ actor.GetProperty().SetColor(0,0,1);\r
+ actor.GetProperty().Delete();\r
+ \r
+ tmpRenderer.RemoveActor(tmpProp);\r
+ \r
+ tFilter0.Delete();\r
+ tFilter1.Delete();\r
+ tFilter2.Delete();\r
+ contour.Delete();\r
+ contourFilter.Delete();\r
+ mapper.Delete();\r
+ tmpRenderWindow.Delete();\r
+ transform0.Delete();\r
+ transform1.Delete();\r
+ transform2.Delete();\r
+ windowToImageFilter.GetOutputPort().Delete();\r
+ windowToImageFilter.Delete();\r
+ \r
+ ren.AddActor(actor);\r
+ \r
+// vtkMatrix4x4 m = camera.GetModelTransformMatrix();\r
+// m.Invert();\r
+// actor.SetUserMatrix(m);\r
+ //m.Delete();\r
+ //actor.SetPosition(trans_x,trans_y, trans_z);\r
+ //actor.RotateWXYZ(MathTools.radToDeg(aa.angle), aa.x, aa.y, aa.z);\r
+ //\r
+ return actor;\r
+ }\r
+ \r
+ public static vtkActor createSilhouette(vtkRenderer ren, vtkDataObject data) {\r
+ \r
+ \r
+ vtkPolyDataSilhouette silhouette = new vtkPolyDataSilhouette();\r
+ \r
+ silhouette.SetInput(data);\r
+ silhouette.SetCamera(ren.GetActiveCamera());\r
+ silhouette.SetEnableFeatureAngle(0);\r
+ vtkPolyDataMapper mapper = new vtkPolyDataMapper();\r
+ \r
+ mapper.SetInputConnection(silhouette.GetOutputPort());\r
+ \r
+ vtkActor actor = new vtkActor();\r
+ actor.SetMapper(mapper);\r
+ \r
+ silhouette.GetOutputPort().Delete();\r
+ silhouette.Delete();\r
+ mapper.Delete();\r
+ \r
+ return actor;\r
+ }\r
+ \r
+ public static vtkActor createOutline(vtkDataObject data) {\r
+ vtkOutlineFilter filter = new vtkOutlineFilter();\r
+ filter.SetInput(data);\r
+ vtkPolyDataMapper mapper = new vtkPolyDataMapper();\r
+ mapper.SetInputConnection(filter.GetOutputPort());\r
+ \r
+ vtkActor actor = new vtkActor();\r
+ actor.SetMapper(mapper);\r
+ \r
+ filter.GetOutputPort().Delete();\r
+ filter.Delete();\r
+ mapper.Delete();\r
+ \r
+ return actor;\r
+ }\r
+ \r
+ public static vtkActor createOutline(vtkProp3D prop) {\r
+\r
+ double bounds[] = prop.GetBounds();\r
+\r
+ vtkOutlineSource source = new vtkOutlineSource();\r
+ source.SetBounds(bounds);\r
+ \r
+ vtkOutlineFilter filter = new vtkOutlineFilter();\r
+ filter.SetInput(source.GetOutput());\r
+ vtkPolyDataMapper mapper = new vtkPolyDataMapper();\r
+ mapper.SetInputConnection(filter.GetOutputPort());\r
+ \r
+ vtkActor actor = new vtkActor();\r
+ actor.SetMapper(mapper);\r
+ \r
+ source.GetOutput().Delete();\r
+ source.Delete();\r
+ filter.GetOutputPort().Delete();\r
+ filter.Delete();\r
+ mapper.Delete();\r
+ \r
+ actor.SetPickable(0);\r
+ return actor;\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.g3d.vtk.utils;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import org.simantics.g3d.vtk.Activator;\r
+import org.simantics.g3d.vtk.preferences.CloseMethod;\r
+import org.simantics.g3d.vtk.preferences.PreferenceConstants;\r
+import org.simantics.utils.threads.AWTThread;\r
+\r
+import vtk.vtkCamera;\r
+import vtk.vtkObject;\r
+import vtk.vtkPanel;\r
+import vtk.vtkReferenceInformation;\r
+import vtk.vtkRenderWindow;\r
+import vtk.vtkRenderer;\r
+\r
+public class vtkPanelUtil {\r
+ \r
+ private static List<vtkPanel> activePanels = new ArrayList<vtkPanel>();\r
+ private static List<vtkPanel> waitingToDeletePanels = new ArrayList<vtkPanel>();\r
+ \r
+ public static void registerPanel(vtkPanel panel) {\r
+ activePanels.add(panel);\r
+ }\r
+ \r
+ public static void unregisterPanel(vtkPanel panel) {\r
+ assert (Thread.currentThread() == AWTThread.getThreadAccess().getThread());\r
+ if (!activePanels.remove(panel))\r
+ return;\r
+ CloseMethod method = getCloseMethod();\r
+ if (method == CloseMethod.ON_LAST_CLOSE) {\r
+ waitingToDeletePanels.add(panel);\r
+ \r
+ if (activePanels.size() == 0) {\r
+ cleanup();\r
+ }\r
+ } else if (method == CloseMethod.ON_CLOSE) {\r
+ dPanel(panel);\r
+ vtkGC();\r
+ } else if (method == CloseMethod.NO_CLOSE) {\r
+ waitingToDeletePanels.add(panel); \r
+ }\r
+ }\r
+ \r
+ public static CloseMethod getCloseMethod() {\r
+ return CloseMethod.valueOf(Activator.getDefault().getPreferenceStore().getString(PreferenceConstants.CLOSE_METHOD));\r
+ }\r
+ \r
+ private static void cleanup() {\r
+ \r
+ for (vtkPanel p : waitingToDeletePanels) {\r
+ dPanel(p);\r
+ }\r
+ waitingToDeletePanels.clear();\r
+ vtkGC();\r
+ }\r
+ \r
+ private static void vtkGC() {\r
+ vtkReferenceInformation info = vtkObject.JAVA_OBJECT_MANAGER.gc(true);\r
+ System.out.println("Referenced objects when closing editor: " + info.getTotalNumberOfObjects() + "\n");\r
+ System.out.println(info.listRemovedReferenceToString());\r
+ System.out.println(info.listKeptReferenceToString());\r
+ }\r
+\r
+ \r
+ private static void dPanel(vtkPanel panel) {\r
+ panel.lock();\r
+ vtkCamera camera = panel.GetRenderer().GetActiveCamera();\r
+ vtkRenderer ren = panel.GetRenderer();\r
+ vtkRenderWindow win = panel.GetRenderWindow();\r
+ win.SetForceMakeCurrent();\r
+ panel.Delete();\r
+ panel = null;\r
+ camera.Delete();\r
+ ren.Delete();\r
+ win.Delete();\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.g3d.vtk.utils;\r
+\r
+import java.util.Collection;\r
+\r
+import javax.vecmath.AxisAngle4d;\r
+import javax.vecmath.Matrix4d;\r
+import javax.vecmath.Point2d;\r
+import javax.vecmath.Point3d;\r
+import javax.vecmath.Quat4d;\r
+import javax.vecmath.Tuple3d;\r
+import javax.vecmath.Vector3d;\r
+\r
+import org.simantics.g3d.math.MathTools;\r
+import org.simantics.g3d.math.Ray;\r
+\r
+import vtk.vtkMatrix4x4;\r
+import vtk.vtkProp3D;\r
+import vtk.vtkRenderer;\r
+\r
+public class vtkUtil {\r
+\r
+ public static Ray createMouseRay(vtkRenderer ren1, double x, double y) {\r
+ Point2d screenPos = new Point2d(x,y);\r
+ Point3d worldCoords = getWorldCoordinates(ren1, screenPos, 0);\r
+ Point3d worldCoords2 = getWorldCoordinates(ren1, screenPos, 1);\r
+ Vector3d dir = new Vector3d(worldCoords2);\r
+ dir.sub(worldCoords);\r
+ return new Ray(worldCoords, dir);\r
+ }\r
+ \r
+ public static Point3d getWorldCoordinates(vtkRenderer ren1, Point2d screenPosition, double zPos) {\r
+ \r
+ ren1.SetDisplayPoint(screenPosition.x, ren1.GetSize()[1]-screenPosition.y, zPos);\r
+ ren1.DisplayToWorld();\r
+ double world[] = ren1.GetWorldPoint(); \r
+\r
+ return new Point3d(world);\r
+ \r
+ }\r
+ \r
+ public static Point2d getScreenCoordinates(vtkRenderer ren1, Tuple3d worldPos) {\r
+ ren1.SetWorldPoint(worldPos.x, worldPos.y, worldPos.z, 0.0);\r
+ ren1.WorldToDisplay();\r
+ double screen[] = ren1.GetDisplayPoint();\r
+ \r
+ return new Point2d(screen);\r
+ \r
+ }\r
+\r
+ public static Matrix4d getMatrix(vtkMatrix4x4 ptm) {\r
+ Matrix4d mat = new Matrix4d();\r
+ for (int i = 0; i < 4; i++) {\r
+ for (int j = 0; j < 4; j++) {\r
+ mat.setElement(i, j, ptm.GetElement(i, j));\r
+ }\r
+ }\r
+\r
+ return mat;\r
+ }\r
+ \r
+ public static vtkMatrix4x4 getMatrix(Matrix4d m) {\r
+ vtkMatrix4x4 mat= new vtkMatrix4x4();\r
+ for (int i = 0; i < 4; i++) {\r
+ for (int j = 0; j < 4; j++) {\r
+ mat.SetElement(i, j, m.getElement(i, j));\r
+ }\r
+ }\r
+ return mat;\r
+ }\r
+ \r
+ public static void updateTransform(Collection<vtkProp3D> props, Vector3d pos, Quat4d q) {\r
+ AxisAngle4d aa = new AxisAngle4d();\r
+ aa.set(q);\r
+ updateTransform(props, pos, aa);\r
+ }\r
+ \r
+ public static void updateTransform(vtkProp3D actor, double pos[], AxisAngle4d aa) {\r
+ actor.SetOrientation(0, 0, 0);\r
+ actor.RotateWXYZ(MathTools.radToDeg(aa.angle), aa.x, aa.y, aa.z);\r
+ actor.SetPosition(pos);\r
+ }\r
+ \r
+ public static void updateTransform(vtkProp3D actor, AxisAngle4d aa) {\r
+ actor.SetOrientation(0, 0, 0);\r
+ actor.RotateWXYZ(MathTools.radToDeg(aa.angle), aa.x, aa.y, aa.z);\r
+ }\r
+ \r
+ \r
+ public static void updateTransform(Collection<vtkProp3D> props, Vector3d pos, AxisAngle4d aa) {\r
+ for (vtkProp3D actor : props) {\r
+ actor.SetOrientation(0, 0, 0);\r
+ actor.RotateWXYZ(MathTools.radToDeg(aa.angle), aa.x, aa.y, aa.z);\r
+ actor.SetPosition(pos.x, pos.y, pos.z);\r
+ }\r
+ }\r
+ \r
+ public static void updateTransform(Collection<vtkProp3D> props, Vector3d pos, AxisAngle4d aa, double scale) {\r
+ for (vtkProp3D actor : props) {\r
+ actor.SetOrientation(0, 0, 0);\r
+ actor.RotateWXYZ(MathTools.radToDeg(aa.angle), aa.x, aa.y, aa.z);\r
+ actor.SetScale(scale);\r
+ actor.SetPosition(pos.x,pos.y,pos.z);\r
+ }\r
+ }\r
+ \r
+ public static void updateTransform(vtkProp3D actor, Vector3d pos, AxisAngle4d aa, double scale) {\r
+ actor.SetOrientation(0, 0, 0);\r
+ actor.RotateWXYZ(MathTools.radToDeg(aa.angle), aa.x, aa.y, aa.z);\r
+ actor.SetScale(scale);\r
+ actor.SetPosition(pos.x,pos.y,pos.z);\r
+ }\r
+ \r
+ public static void updateTransform(vtkProp3D actor, Vector3d pos, AxisAngle4d aa, double scalex, double scaley, double scalez) {\r
+ actor.SetOrientation(0, 0, 0);\r
+ actor.RotateWXYZ(MathTools.radToDeg(aa.angle), aa.x, aa.y, aa.z);\r
+ actor.SetScale(scalex,scaley, scalez);\r
+ actor.SetPosition(pos.x,pos.y,pos.z);\r
+ }\r
+}\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<classpath>\r
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>\r
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>\r
+ <classpathentry excluding="org/simantics/g3d/objmap/" kind="src" path="src"/>\r
+ <classpathentry kind="output" path="bin"/>\r
+</classpath>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<projectDescription>\r
+ <name>org.simantics.g3d</name>\r
+ <comment></comment>\r
+ <projects>\r
+ </projects>\r
+ <buildSpec>\r
+ <buildCommand>\r
+ <name>org.eclipse.jdt.core.javabuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ <buildCommand>\r
+ <name>org.eclipse.pde.ManifestBuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ <buildCommand>\r
+ <name>org.eclipse.pde.SchemaBuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ </buildSpec>\r
+ <natures>\r
+ <nature>org.eclipse.pde.PluginNature</nature>\r
+ <nature>org.eclipse.jdt.core.javanature</nature>\r
+ </natures>\r
+</projectDescription>\r
--- /dev/null
+#Mon Dec 12 12:35:07 EET 2011\r
+eclipse.preferences.version=1\r
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled\r
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6\r
+org.eclipse.jdt.core.compiler.compliance=1.6\r
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error\r
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error\r
+org.eclipse.jdt.core.compiler.source=1.6\r
--- /dev/null
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: G3D
+Bundle-SymbolicName: org.simantics.g3d;singleton:=true
+Bundle-Version: 1.0.0.qualifier
+Bundle-Activator: org.simantics.g3d.Activator
+Bundle-Vendor: VTT
+Require-Bundle: org.eclipse.core.runtime,
+ javax.vecmath;bundle-version="1.5.2",
+ org.simantics.g3d.ontology;bundle-version="1.0.0",
+ org.simantics.db.layer0;bundle-version="1.1.0",
+ org.eclipse.jface;bundle-version="3.6.2",
+ org.eclipse.ui;bundle-version="3.6.2",
+ org.eclipse.ui.views;bundle-version="3.5.1",
+ org.simantics.browsing.ui.swt;bundle-version="1.1.0",
+ org.simantics.db.management;bundle-version="1.1.0",
+ org.simantics.selectionview;bundle-version="1.0.0",
+ gnu.trove2;bundle-version="2.0.4",
+ org.simantics.objmap2;bundle-version="1.0.0",
+ org.eclipse.nebula.widgets.tablecombo;bundle-version="1.0.0",
+ org.simantics.ui;bundle-version="1.0.0"
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Bundle-ActivationPolicy: lazy
+Export-Package: org.simantics.g3d,
+ org.simantics.g3d.gizmo,
+ org.simantics.g3d.math,
+ org.simantics.g3d.preferences,
+ org.simantics.g3d.property,
+ org.simantics.g3d.property.annotations,
+ org.simantics.g3d.scenegraph,
+ org.simantics.g3d.scenegraph.base,
+ org.simantics.g3d.scenegraph.structural,
+ org.simantics.g3d.shape,
+ org.simantics.g3d.toolbar,
+ org.simantics.g3d.tools,
+ org.simantics.g3d.ui,
+ org.simantics.g3d.wizard
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<adapters>\r
+ \r
+</adapters>
\ No newline at end of file
--- /dev/null
+source.. = src/\r
+output.. = bin/\r
+bin.includes = META-INF/,\\r
+ .,\\r
+ plugin.xml\r
--- /dev/null
+=Introduction=\r
+Simantics 3D framework (G3D) provides a set of tools for developing 3D modelling environment on top of Simantics.\r
+\r
+The framework is rendering library neutral. Currently supported are:\r
+* [http://www.vtk.org|VTK]\r
+* [http://www.jmonkeyengine.org|jMonkeyEngine]
\ No newline at end of file
--- /dev/null
+@media screen {\r
+ body { width: 780px; }\r
+}\r
+\r
+@media print {\r
+ html { font-size: 10pt; }\r
+}\r
--- /dev/null
+\r
+ /* following font face declarations need to be removed for DBCS */\r
+ body, h1, h2, h3, h4, h5, h6, p, table, td, caption, th, ul, ol, dl, li, dd, dt {font-family: Arial, Helvetica, sans-serif; color: #000000 }\r
+ pre, code, tt { font-family: "Courier New", Courier, monospace;}\r
+ /* end font face declarations */\r
+\r
+ body { font-size: 83%; background: #FFFFFF; margin-bottom: 1em }\r
+ h1 { font-size: 180%; margin-top: 5px; margin-bottom: 1px } \r
+ h2 { font-size: 140%; margin-top: 25px; margin-bottom: 3px }\r
+ h3 { font-size: 110%; margin-top: 20px; margin-bottom: 3px }\r
+ h4 { font-size: 100%; margin-top: 20px; margin-bottom: 3px; font-style: italic }\r
+ p { margin-top: 10px; margin-bottom: 10px }\r
+ pre { font-size: 93%; margin-left: 6; color: #4444CC }\r
+ img.border { border:1px dashed }\r
+ pre.solid { border:1px solid #333; background: #eee; padding: 3px; margin: 3px; }\r
+ pre.dotted { font-size: 93%; margin-left: 6; padding: 1em;border: 1px dashed #2f6fab;color: black;background-color: #f9f9f9;line-height: 1.1em; }\r
+ code, tt { font-size: 93%; } \r
+ table { font-size: 100% } /* needed for quirks mode */\r
+ a:link { color: #0000FF }\r
+ a:hover { color: #000080 }\r
+ a:visited { text-decoration: underline }\r
+ \r
+ \r
+ ul { margin-top: 4px; margin-bottom: 4px; list-style-image: url("arrow.png"); margin-left: 25px; }\r
+ li { margin-left: 0; margin-bottom: 4px; padding: 0; /* margin between bullet and content */ } \r
+ ol { margin-top: 10px; margin-bottom: 10px; }\r
+ \r
+ \r
+ dl { margin-top: 10px; margin-bottom: 10px; }\r
+ dt { margin-top: 5px; margin-bottom: 5px; font-weight: bold; }\r
+ dd { margin-top: 5px; margin-bottom: 5px; }\r
+ strong { font-weight: bold}\r
+ em { font-style: italic}\r
+ var { font-style: italic}\r
+ div.revision { border-left-style: solid; border-left-width: thin; \r
+ border-left-color: #7B68EE; padding-left:5 }\r
+ th { font-weight: bold }\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<toc label="Simantics 3D framework guide">\r
+ <topic href="introduction.mediawiki" label="Introduction">\r
+ </topic>\r
+</toc>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<?eclipse version="3.4"?>\r
+<plugin>\r
+ <extension-point id="toolbarCommand" name="toolbarCommand" schema="schema/toolbarCommand.exsd"/>\r
+ <extension\r
+ point="org.eclipse.ui.views">\r
+ <view\r
+ allowMultiple="false"\r
+ category="org.simantics.debug.ui"\r
+ class="org.simantics.g3d.ui.SceneGraphDebugger"\r
+ icon="platform:/plugin/com.famfamfam.silk/icons/car.png"\r
+ id="org.simantics.g3d.debug"\r
+ name="Scene-graph Debugger"\r
+ restorable="true">\r
+ </view>\r
+ </extension>\r
+ <extension\r
+ point="org.eclipse.ui.preferencePages">\r
+ <page\r
+ class="org.simantics.g3d.preferences.G3DPreferencePage"\r
+ id="org.simantics.g3d.preferences.G3DPreferencePage"\r
+ name="3D Modelling Preferences">\r
+ </page>\r
+ </extension>\r
+ <extension\r
+ point="org.eclipse.core.runtime.preferences">\r
+ <initializer\r
+ class="org.simantics.g3d.preferences.PreferenceInitializer">\r
+ </initializer>\r
+ </extension>\r
+ <extension\r
+ point="org.eclipse.ui.commands">\r
+ <category\r
+ id="org.simantics.g3d.category"\r
+ name="3D Modelling Commands">\r
+ </category>\r
+ <command\r
+ categoryId="org.simantics.g3d.category"\r
+ id="org.simantics.g3d.parallelperspective"\r
+ name="Parallel perspective">\r
+ <state\r
+ id="org.eclipse.ui.commands.toggleState">\r
+ <class\r
+ class="org.eclipse.ui.handlers.RegistryToggleState">\r
+ <parameter\r
+ name="persisted"\r
+ value="false">\r
+ </parameter>\r
+ <parameter\r
+ name="default"\r
+ value="false">\r
+ </parameter>\r
+ </class>\r
+ </state>\r
+ </command>\r
+ <command\r
+ categoryId="org.simantics.g3d.category"\r
+ id="org.simantics.g3d.viewdir"\r
+ name="View Dir">\r
+ <commandParameter\r
+ id="org.simantics.g3d.viewDirection"\r
+ name="direction"\r
+ optional="true">\r
+ </commandParameter>\r
+ </command>\r
+ </extension>\r
+\r
+</plugin>\r
--- /dev/null
+<?xml version='1.0' encoding='UTF-8'?>\r
+<!-- Schema file written by PDE -->\r
+<schema targetNamespace="org.simantics.g3d" xmlns="http://www.w3.org/2001/XMLSchema">\r
+<annotation>\r
+ <appinfo>\r
+ <meta.schema plugin="org.simantics.g3d" id="toolbarCommand" name="toolbarCommand"/>\r
+ </appinfo>\r
+ <documentation>\r
+ [Enter description of this extension point.]\r
+ </documentation>\r
+ </annotation>\r
+\r
+ <element name="extension">\r
+ <annotation>\r
+ <appinfo>\r
+ <meta.element />\r
+ </appinfo>\r
+ </annotation>\r
+ <complexType>\r
+ <sequence>\r
+ <element ref="command" minOccurs="0" maxOccurs="unbounded"/>\r
+ </sequence>\r
+ <attribute name="point" type="string" use="required">\r
+ <annotation>\r
+ <documentation>\r
+ \r
+ </documentation>\r
+ </annotation>\r
+ </attribute>\r
+ <attribute name="id" type="string">\r
+ <annotation>\r
+ <documentation>\r
+ \r
+ </documentation>\r
+ </annotation>\r
+ </attribute>\r
+ <attribute name="name" type="string">\r
+ <annotation>\r
+ <documentation>\r
+ \r
+ </documentation>\r
+ <appinfo>\r
+ <meta.attribute translatable="true"/>\r
+ </appinfo>\r
+ </annotation>\r
+ </attribute>\r
+ </complexType>\r
+ </element>\r
+\r
+ <element name="command">\r
+ <complexType>\r
+ <attribute name="commandId" type="string" use="required">\r
+ <annotation>\r
+ <documentation>\r
+ \r
+ </documentation>\r
+ </annotation>\r
+ </attribute>\r
+ <attribute name="toolbarId" type="string" use="required">\r
+ <annotation>\r
+ <documentation>\r
+ \r
+ </documentation>\r
+ </annotation>\r
+ </attribute>\r
+ <attribute name="name" type="string" use="required">\r
+ <annotation>\r
+ <documentation>\r
+ \r
+ </documentation>\r
+ </annotation>\r
+ </attribute>\r
+ <attribute name="type" use="required">\r
+ <annotation>\r
+ <documentation>\r
+ \r
+ </documentation>\r
+ </annotation>\r
+ <simpleType>\r
+ <restriction base="string">\r
+ <enumeration value="push">\r
+ </enumeration>\r
+ <enumeration value="toggle">\r
+ </enumeration>\r
+ <enumeration value="radio">\r
+ </enumeration>\r
+ <enumeration value="combo">\r
+ </enumeration>\r
+ </restriction>\r
+ </simpleType>\r
+ </attribute>\r
+ <attribute name="value" type="string">\r
+ <annotation>\r
+ <documentation>\r
+ Used with radio buttons.\r
+ </documentation>\r
+ </annotation>\r
+ </attribute>\r
+ <attribute name="image" type="string">\r
+ <annotation>\r
+ <documentation>\r
+ \r
+ </documentation>\r
+ <appinfo>\r
+ <meta.attribute kind="resource"/>\r
+ </appinfo>\r
+ </annotation>\r
+ </attribute>\r
+ </complexType>\r
+ </element>\r
+\r
+ <annotation>\r
+ <appinfo>\r
+ <meta.section type="since"/>\r
+ </appinfo>\r
+ <documentation>\r
+ [Enter the first release in which this extension point appears.]\r
+ </documentation>\r
+ </annotation>\r
+\r
+ <annotation>\r
+ <appinfo>\r
+ <meta.section type="examples"/>\r
+ </appinfo>\r
+ <documentation>\r
+ [Enter extension point usage example here.]\r
+ </documentation>\r
+ </annotation>\r
+\r
+ <annotation>\r
+ <appinfo>\r
+ <meta.section type="apiinfo"/>\r
+ </appinfo>\r
+ <documentation>\r
+ [Enter API information here.]\r
+ </documentation>\r
+ </annotation>\r
+\r
+ <annotation>\r
+ <appinfo>\r
+ <meta.section type="implementation"/>\r
+ </appinfo>\r
+ <documentation>\r
+ [Enter information about supplied implementation of this extension point.]\r
+ </documentation>\r
+ </annotation>\r
+\r
+\r
+</schema>\r
--- /dev/null
+package org.simantics.g3d;\r
+\r
+import org.eclipse.ui.plugin.AbstractUIPlugin;\r
+import org.osgi.framework.BundleContext;\r
+\r
+public class Activator extends AbstractUIPlugin {\r
+\r
+ // The plug-in ID\r
+ public static final String PLUGIN_ID = "org.simantics.g3d"; //$NON-NLS-1$\r
+\r
+ // The shared instance\r
+ private static Activator plugin;\r
+ \r
+ /**\r
+ * The constructor\r
+ */\r
+ public Activator() {\r
+ }\r
+\r
+ /*\r
+ * (non-Javadoc)\r
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)\r
+ */\r
+ public void start(BundleContext context) throws Exception {\r
+ super.start(context);\r
+ plugin = this;\r
+ }\r
+\r
+ /*\r
+ * (non-Javadoc)\r
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)\r
+ */\r
+ public void stop(BundleContext context) throws Exception {\r
+ plugin = null;\r
+ super.stop(context);\r
+ }\r
+\r
+ /**\r
+ * Returns the shared instance\r
+ *\r
+ * @return the shared instance\r
+ */\r
+ public static Activator getDefault() {\r
+ return plugin;\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.adapters;\r
+\r
+import java.util.Map;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.layer0.adapter.Remover;\r
+\r
+public class NodeRemover implements Remover {\r
+ \r
+ //private Resource node;\r
+ \r
+ public NodeRemover(Resource node) {\r
+ //this.node = node;\r
+ }\r
+ \r
+ @Override\r
+ public String canRemove(ReadGraph graph, Map<Object, Object> aux)\r
+ throws DatabaseException {\r
+ return "Removing scene-graph nodes from model browser is not supported.";\r
+ }\r
+ \r
+ @Override\r
+ public void remove(WriteGraph graph) throws DatabaseException {\r
+ \r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.gizmo;\r
+\r
+import javax.vecmath.AxisAngle4d;\r
+import javax.vecmath.Tuple3d;\r
+\r
+public interface Gizmo<T> {\r
+ \r
+ \r
+ public boolean isPartOf(T pickedObject);\r
+ \r
+ \r
+ public void attach(Object renderingPart);\r
+ public void deattach();\r
+ \r
+ public void setPosition(Tuple3d position);\r
+ public void setRotation(AxisAngle4d q);\r
+}\r
--- /dev/null
+package org.simantics.g3d.math;\r
+\r
+import javax.vecmath.AxisAngle4d;\r
+import javax.vecmath.Quat4d;\r
+import javax.vecmath.Vector3d;\r
+\r
+public class EulerTools {\r
+\r
+ public enum Order {\r
+ XYX, XYZ, XZX, XZY, YXY, YXZ, YZX, YZY, ZXY, ZXZ, ZYX, ZYZ\r
+ };\r
+\r
+ public static Quat4d getQuatFromEuler(Order order, Vector3d a) {\r
+ return getQuatFromEuler(order, a.x, a.y, a.z);\r
+ }\r
+ \r
+ public static Quat4d getQuatFromEuler(Order order, double a1, double a2, double a3) {\r
+ Quat4d q1 = new Quat4d();\r
+ Quat4d q2 = new Quat4d();\r
+ Quat4d q3 = new Quat4d();\r
+ switch (order) {\r
+ case XYX:\r
+ q1.set(new AxisAngle4d(1.0, 0.0, 0.0, a1));\r
+ q2.set(new AxisAngle4d(0.0, 1.0, 0.0, a2));\r
+ q3.set(new AxisAngle4d(1.0, 0.0, 0.0, a3));\r
+ break;\r
+ case XYZ:\r
+ q1.set(new AxisAngle4d(1.0, 0.0, 0.0, a1));\r
+ q2.set(new AxisAngle4d(0.0, 1.0, 0.0, a2));\r
+ q3.set(new AxisAngle4d(0.0, 0.0, 1.0, a3));\r
+ break;\r
+ case XZX:\r
+ q1.set(new AxisAngle4d(1.0, 0.0, 0.0, a1));\r
+ q2.set(new AxisAngle4d(0.0, 0.0, 1.0, a2));\r
+ q3.set(new AxisAngle4d(1.0, 0.0, 0.0, a3));\r
+ break;\r
+ case XZY:\r
+ q1.set(new AxisAngle4d(1.0, 0.0, 0.0, a1));\r
+ q2.set(new AxisAngle4d(0.0, 0.0, 1.0, a2));\r
+ q3.set(new AxisAngle4d(0.0, 1.0, 0.0, a3));\r
+ break;\r
+ case YXY:\r
+ q1.set(new AxisAngle4d(0.0, 1.0, 0.0, a1));\r
+ q2.set(new AxisAngle4d(1.0, 0.0, 0.0, a2));\r
+ q3.set(new AxisAngle4d(0.0, 1.0, 0.0, a3));\r
+ break;\r
+ case YXZ:\r
+ q1.set(new AxisAngle4d(0.0, 1.0, 0.0, a1));\r
+ q2.set(new AxisAngle4d(1.0, 0.0, 0.0, a2));\r
+ q3.set(new AxisAngle4d(0.0, 0.0, 1.0, a3));\r
+ break;\r
+ case YZX:\r
+ q1.set(new AxisAngle4d(0.0, 1.0, 0.0, a1));\r
+ q2.set(new AxisAngle4d(0.0, 0.0, 1.0, a2));\r
+ q3.set(new AxisAngle4d(1.0, 0.0, 0.0, a3));\r
+ break;\r
+ case YZY:\r
+ q1.set(new AxisAngle4d(0.0, 1.0, 0.0, a1));\r
+ q2.set(new AxisAngle4d(0.0, 0.0, 1.0, a2));\r
+ q3.set(new AxisAngle4d(0.0, 1.0, 0.0, a3));\r
+ break;\r
+ case ZXY:\r
+ q1.set(new AxisAngle4d(0.0, 0.0, 1.0, a1));\r
+ q2.set(new AxisAngle4d(1.0, 0.0, 0.0, a2));\r
+ q3.set(new AxisAngle4d(0.0, 1.0, 0.0, a3));\r
+ break;\r
+ case ZXZ:\r
+ q1.set(new AxisAngle4d(0.0, 0.0, 1.0, a1));\r
+ q2.set(new AxisAngle4d(1.0, 0.0, 0.0, a2));\r
+ q3.set(new AxisAngle4d(0.0, 0.0, 1.0, a3));\r
+ break;\r
+ case ZYX:\r
+ q1.set(new AxisAngle4d(0.0, 0.0, 1.0, a1));\r
+ q2.set(new AxisAngle4d(0.0, 1.0, 0.0, a2));\r
+ q3.set(new AxisAngle4d(1.0, 0.0, 0.0, a3));\r
+ break;\r
+ case ZYZ:\r
+ q1.set(new AxisAngle4d(0.0, 0.0, 1.0, a1));\r
+ q2.set(new AxisAngle4d(0.0, 1.0, 0.0, a2));\r
+ q3.set(new AxisAngle4d(0.0, 0.0, 1.0, a3));\r
+ break;\r
+ }\r
+ q1.mul(q2);\r
+ q1.mul(q3);\r
+ return q1;\r
+ }\r
+ \r
+ /**\r
+ * See http://noelhughes.net/uploads/quat_2_euler_paper_ver3.pdf\r
+ * @param order\r
+ * @param q\r
+ * @return\r
+ */\r
+ public static Vector3d getEulerFromQuat(Order order, Quat4d q) {\r
+ Vector3d euler = new Vector3d();\r
+ \r
+// Vector3d v1 = new Vector3d();\r
+// Vector3d v2 = new Vector3d();\r
+ Vector3d v3 = new Vector3d();\r
+ Vector3d v3n = new Vector3d();\r
+ \r
+ switch (order) {\r
+ case XYX:\r
+// v1.x = 1.0;\r
+// v2.y = 1.0;\r
+ v3.x = 1.0;\r
+ v3n.y = 1.0;\r
+ break;\r
+ case XYZ:\r
+// v1.x = 1.0;\r
+// v2.y = 1.0;\r
+ v3.z = 1.0;\r
+ v3n.x = 1.0;\r
+ break;\r
+ case XZX:\r
+// v1.x = 1.0;\r
+// v2.z = 1.0;\r
+ v3.x = 1.0;\r
+ v3n.y = 1.0;\r
+ break;\r
+ case XZY:\r
+// v1.x = 1.0;\r
+// v2.z = 1.0;\r
+ v3.y = 1.0;\r
+ v3n.z = 1.0;\r
+ break;\r
+ case YXY:\r
+// v1.y = 1.0;\r
+// v2.x = 1.0;\r
+ v3.y = 1.0;\r
+ v3n.z = 1.0;\r
+ break;\r
+ case YXZ:\r
+// v1.y = 1.0;\r
+// v2.x = 1.0;\r
+ v3.z = 1.0;\r
+ v3n.x = 1.0;\r
+ break;\r
+ case YZX:\r
+// v1.y = 1.0;\r
+// v2.z = 1.0;\r
+ v3.x = 1.0;\r
+ v3n.y = 1.0;\r
+ break;\r
+ case YZY:\r
+// v1.y = 1.0;\r
+// v2.z = 1.0;\r
+ v3.y = 1.0;\r
+ v3n.z = 1.0;\r
+ break;\r
+ case ZXY:\r
+// v1.z = 1.0;\r
+// v2.x = 1.0;\r
+ v3.y = 1.0;\r
+ v3n.z = 1.0;\r
+ break;\r
+ case ZXZ:\r
+// v1.z = 1.0;\r
+// v2.x = 1.0;\r
+ v3.z = 1.0;\r
+ v3n.x = 1.0;\r
+ break;\r
+ case ZYX:\r
+// v1.z = 1.0;\r
+// v2.y = 1.0;\r
+ v3.x = 1.0;\r
+ v3n.y = 1.0;\r
+ break;\r
+ case ZYZ:\r
+// v1.z = 1.0;\r
+// v2.y = 1.0;\r
+ v3.z = 1.0;\r
+ v3n.x = 1.0;\r
+ break;\r
+ }\r
+ Vector3d v3r = new Vector3d();\r
+ MathTools.rotate(q, v3, v3r);\r
+ v3r.normalize();\r
+ \r
+ switch (order) {\r
+\r
+ case XZX:\r
+ euler.x = Math.atan2(v3r.z, v3r.y);\r
+ euler.y = Math.acos(v3r.x);\r
+ break;\r
+ case YXY:\r
+ euler.x = Math.atan2(v3r.x, v3r.z);\r
+ euler.y = Math.acos(v3r.y);\r
+ break;\r
+ case ZYZ:\r
+ euler.x = Math.atan2(v3r.y, v3r.x);\r
+ euler.y = Math.acos(v3r.z);\r
+ break;\r
+ \r
+ case XZY:\r
+ euler.x = Math.atan2(v3r.z, v3r.y);\r
+ euler.y = -Math.asin(v3r.x);\r
+ break;\r
+ case YXZ:\r
+ euler.x = Math.atan2(v3r.x, v3r.z);\r
+ euler.y = -Math.asin(v3r.y);\r
+ break;\r
+ case ZYX:\r
+ euler.x = Math.atan2(v3r.y, v3r.x);\r
+ euler.y = -Math.asin(v3r.z);\r
+ break;\r
+ \r
+ case XYX:\r
+ euler.x = Math.atan2(v3r.y, -v3r.z);\r
+ //euler.x = Math.atan2(v3r.y, -v3r.x);\r
+ euler.y = Math.acos(v3r.x);\r
+ break;\r
+ case YZY:\r
+ euler.x = Math.atan2(v3r.z, -v3r.x);\r
+ //euler.x = Math.atan2(v3r.z, -v3r.y);\r
+ euler.y = Math.acos(v3r.y);\r
+ break;\r
+ case ZXZ:\r
+ euler.x = Math.atan2(v3r.x, -v3r.y);\r
+ //euler.x = Math.atan2(v3r.x, -v3r.z);\r
+ euler.y = Math.acos(v3r.z);\r
+ break;\r
+ \r
+ case XYZ:\r
+ euler.x = Math.atan2(-v3r.y, v3r.z);\r
+ euler.y = Math.asin(v3r.x);\r
+ break;\r
+ case YZX:\r
+ euler.x = Math.atan2(-v3r.z, v3r.x);\r
+ euler.y = Math.asin(v3r.y);\r
+ break;\r
+ case ZXY:\r
+ euler.x = Math.atan2(-v3r.x, v3r.y);\r
+ euler.y = Math.asin(v3r.z);\r
+ break;\r
+ }\r
+ \r
+ Quat4d q1 = new Quat4d();\r
+ q1.w = Math.cos(euler.x*0.5);\r
+ Quat4d q2 = new Quat4d();\r
+ q2.w = Math.cos(euler.y*0.5);\r
+ \r
+ switch (order) {\r
+ case XYX:\r
+ case XYZ:\r
+ case XZX:\r
+ case XZY:\r
+ q1.x = Math.sin(euler.x*0.5);\r
+ break;\r
+ case YXY:\r
+ case YXZ:\r
+ case YZX:\r
+ case YZY:\r
+ q1.y = Math.sin(euler.x*0.5);\r
+ break;\r
+ case ZXY:\r
+ case ZXZ:\r
+ case ZYX:\r
+ case ZYZ:\r
+ q1.z = Math.sin(euler.x*0.5);\r
+ break;\r
+ }\r
+ \r
+ switch (order) {\r
+ case YXY:\r
+ case YXZ:\r
+ case ZXY:\r
+ case ZXZ:\r
+ q2.x = Math.sin(euler.y*0.5);\r
+ break;\r
+ case XYX:\r
+ case XYZ:\r
+ case ZYX:\r
+ case ZYZ:\r
+ q2.y = Math.sin(euler.y*0.5);\r
+ break;\r
+ case XZX:\r
+ case XZY:\r
+ case YZX:\r
+ case YZY:\r
+ q2.z = Math.sin(euler.y*0.5);\r
+ break;\r
+ }\r
+ \r
+ Quat4d q12 = new Quat4d();\r
+ q12.mul(q1, q2);\r
+ \r
+ Vector3d v3n12 = new Vector3d();\r
+ Vector3d v3ng = new Vector3d();\r
+ MathTools.rotate(q12, v3n, v3n12);\r
+ MathTools.rotate(q, v3n, v3ng);\r
+ \r
+ double dot = v3n12.dot(v3ng);\r
+ dot = MathTools.clamp(-1.0, 1.0, dot);\r
+ euler.z = Math.abs(Math.acos(dot));\r
+ Vector3d vc = new Vector3d();\r
+ vc.cross(v3n12, v3ng);\r
+ euler.z *= Math.signum(vc.dot(v3r));\r
+ \r
+ return euler;\r
+ }\r
+\r
+ \r
+ public static void main(String args[]) {\r
+ \r
+ boolean all = false;\r
+ boolean allOrder = false;\r
+ if (all) {\r
+ testAll();\r
+ } else if (allOrder) {\r
+ test(Order.YXZ);\r
+ } else {\r
+ //test(Order.ZXY,30,60,45);\r
+ //test(Order.YXZ,30,0,0);\r
+ //test(Order.YXZ,30,90,60);\r
+ test(Order.YXZ,300,240,360);\r
+ }\r
+ }\r
+ \r
+ private static void testAll() {\r
+ double start = 0.0;\r
+ double end = 90.0;\r
+ double step = 30.0;\r
+ for (double a1 = start; a1 <= end; a1+= step) {\r
+ double r1 = MathTools.degToRad(a1);\r
+ for (double a2 = start; a2 <= end; a2+= step) {\r
+ double r2 = MathTools.degToRad(a2);\r
+ for (double a3 = start; a3 <= end; a3+= step) {\r
+ double r3 = MathTools.degToRad(a3);\r
+ for (Order order : Order.values()) {\r
+ Quat4d q = EulerTools.getQuatFromEuler(order, r1, r2, r3);\r
+ Vector3d a = EulerTools.getEulerFromQuat(order, q);\r
+ Quat4d q2 = EulerTools.getQuatFromEuler(order, a.x,a.y,a.z);\r
+ a.x = MathTools.radToDeg(a.x);\r
+ a.y = MathTools.radToDeg(a.y);\r
+ a.z = MathTools.radToDeg(a.z);\r
+ System.out.println(toString(a1) +" " + toString(a2) + " " + toString(a3) + " " + order + "\t" + toString(a) + "\t" + toString(q) + "\t" + toString(q2));\r
+ }\r
+ } \r
+ } \r
+ }\r
+ }\r
+ \r
+ private static void test(Order order) {\r
+ double start = 0.0;\r
+ double end = 360.0;\r
+ double step = 30.0;\r
+ for (double a1 = start; a1 <= end; a1+= step) {\r
+ double r1 = MathTools.degToRad(a1);\r
+ for (double a2 = start; a2 <= end; a2+= step) {\r
+ double r2 = MathTools.degToRad(a2);\r
+ for (double a3 = start; a3 <= end; a3+= step) {\r
+ double r3 = MathTools.degToRad(a3);\r
+ \r
+ Quat4d q = EulerTools.getQuatFromEuler(order, r1, r2, r3);\r
+ Vector3d a = EulerTools.getEulerFromQuat(order, q);\r
+ Quat4d q2 = EulerTools.getQuatFromEuler(order, a.x,a.y,a.z);\r
+ a.x = MathTools.radToDeg(a.x);\r
+ a.y = MathTools.radToDeg(a.y);\r
+ a.z = MathTools.radToDeg(a.z);\r
+ \r
+ System.out.println(toString(a1) +" " + toString(a2) + " " + toString(a3) + " " + order + "\t" + toString(a) + "\t" + toString(q) + "\t" + toString(q2));\r
+ } \r
+ } \r
+ }\r
+ }\r
+ \r
+ private static String toString(double d) {\r
+ return String.format("%1$6.2f", d);\r
+ }\r
+ \r
+ private static String toString(Vector3d v) {\r
+ return "("+toString(v.x) +", "+ toString(v.y) + ", " + toString(v.z) +")";\r
+ }\r
+ \r
+ private static String toString(Quat4d v) {\r
+ return "("+toString(v.x) +", "+ toString(v.y) + ", " + toString(v.z) + ", " + toString(v.w) +")";\r
+ }\r
+ \r
+ private static void test(Order order, double deg1, double deg2, double deg3) {\r
+ double r1 = MathTools.degToRad(deg1);\r
+ double r2 = MathTools.degToRad(deg2);\r
+ double r3 = MathTools.degToRad(deg3);\r
+ \r
+ Quat4d q = EulerTools.getQuatFromEuler(order, r1, r2, r3);\r
+ Vector3d a = EulerTools.getEulerFromQuat(order, q);\r
+ Quat4d q2 = EulerTools.getQuatFromEuler(order, a.x,a.y,a.z);\r
+ a.x = MathTools.radToDeg(a.x);\r
+ a.y = MathTools.radToDeg(a.y);\r
+ a.z = MathTools.radToDeg(a.z);\r
+ System.out.println(toString(deg1) +" " + toString(deg2) + " " + toString(deg3) + " " + order + "\t" + toString(a) + "\t" + toString(q) + "\t" + toString(q2));\r
+\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.g3d.math;\r
+\r
+import javax.vecmath.AxisAngle4d;\r
+import javax.vecmath.Matrix3d;\r
+import javax.vecmath.Matrix4d;\r
+import javax.vecmath.Quat4d;\r
+import javax.vecmath.Tuple3d;\r
+import javax.vecmath.Tuple4d;\r
+import javax.vecmath.Vector2f;\r
+import javax.vecmath.Vector3d;\r
+\r
+import org.simantics.g3d.math.EulerTools.Order;\r
+\r
+\r
+/**\r
+ * Some useful geometry related math functions. Beware, methods may modify their input parameters!\r
+ * \r
+ * @author Marko Luukkainen\r
+ *\r
+ */\r
+public class MathTools {\r
+ \r
+ public static double NEAR_ZERO = 0.0000001;\r
+ public static double NEAR_HALF = 0.4999999;\r
+ \r
+ public static final Vector3d Z_AXIS = new Vector3d(0.0,0.0,1.0);\r
+ public static final Vector3d Y_AXIS = new Vector3d(0.0,1.0,0.0);\r
+ public static final Vector3d X_AXIS = new Vector3d(1.0,0.0,0.0);\r
+ public static final Vector3d ORIGIN = new Vector3d(0.0,0.0,0.0);\r
+ \r
+ final static double EPS = 1.0e-12;\r
+ \r
+ \r
+ public static boolean equals(double d1, double d2) {\r
+ return Math.abs(d1-d2) < EPS;\r
+ }\r
+ \r
+ public static boolean equals(Tuple3d p1, Tuple3d p2) {\r
+ return distanceSquared(p1, p2) < NEAR_ZERO;\r
+ }\r
+ \r
+ public static boolean equals(Tuple4d p1, Tuple4d p2) {\r
+ return distanceSquared(p1, p2) < NEAR_ZERO;\r
+ }\r
+ \r
+ public static double distance(Tuple3d p1, Tuple3d p2) {\r
+ double dx, dy, dz;\r
+\r
+ dx = p2.x - p1.x;\r
+ dy = p2.y - p1.y;\r
+ dz = p2.z - p1.z;\r
+ return Math.sqrt(dx*dx+dy*dy+dz*dz);\r
+ }\r
+ \r
+ public static double distance(Tuple4d p1, Tuple4d p2) {\r
+ double dx, dy, dz, dw;\r
+\r
+ dx = p2.x - p1.x;\r
+ dy = p2.y - p1.y;\r
+ dz = p2.z - p1.z;\r
+ dw = p2.w - p1.w;\r
+ return Math.sqrt(dx*dx+dy*dy+dz*dz+dw*dw);\r
+ }\r
+ \r
+ public static double distanceSquared(Tuple3d p1, Tuple3d p2) {\r
+ double dx, dy, dz;\r
+\r
+ dx = p2.x - p1.x;\r
+ dy = p2.y - p1.y;\r
+ dz = p2.z - p1.z;\r
+ return dx*dx+dy*dy+dz*dz;\r
+ }\r
+ \r
+ public static double distanceSquared(Tuple4d p1, Tuple4d p2) {\r
+ double dx, dy, dz, dw;\r
+\r
+ dx = p2.x - p1.x;\r
+ dy = p2.y - p1.y;\r
+ dz = p2.z - p1.z;\r
+ dw = p2.w - p1.w;\r
+ return dx*dx+dy*dy+dz*dz+dw*dw;\r
+ }\r
+ \r
+ public static boolean isValid(Tuple3d t) {\r
+ return !(Double.isInfinite(t.x) || Double.isNaN(t.x) ||\r
+ Double.isInfinite(t.y) || Double.isNaN(t.y) ||\r
+ Double.isInfinite(t.z) || Double.isNaN(t.z));\r
+ }\r
+ \r
+ public static Vector3d closestPointOnEdge(Vector3d point, Vector3d edgePoint1, Vector3d edgePoint2) {\r
+ point.sub(edgePoint1);\r
+ Vector3d v = new Vector3d(edgePoint2);\r
+ v.sub(edgePoint1);\r
+ double t = v.dot(point);\r
+ t /= v.lengthSquared();\r
+ if (t <= 0.0f)\r
+ return edgePoint1;\r
+ if (t >= 1.0f)\r
+ return edgePoint2;\r
+ v.scale(t);\r
+ v.add(edgePoint1);\r
+ return v; \r
+ }\r
+ \r
+ public static Vector3d closestPointOnStraight(Tuple3d point, Tuple3d straightPoint, Vector3d straightDir) {\r
+ Vector3d v = new Vector3d(point);\r
+ v.sub(straightPoint);\r
+ double t = straightDir.dot(v);\r
+ t /= straightDir.lengthSquared();\r
+ v.set(straightDir);\r
+ v.scale(t);\r
+ v.add(straightPoint);\r
+ return v; \r
+ }\r
+ \r
+ public static Vector3d closestPointOnStraight(Tuple3d point, Tuple3d straightPoint, Vector3d straightDir, double u[]) {\r
+ Vector3d v = new Vector3d(point);\r
+ v.sub(straightPoint);\r
+ u[0] = straightDir.dot(v);\r
+ u[0] /= straightDir.lengthSquared();\r
+ v.set(straightDir);\r
+ v.scale(u[0]);\r
+ v.add(straightPoint);\r
+ return v; \r
+ }\r
+ \r
+ public static double distanceFromPlane(Vector3d point, Vector3d planeNormal, Tuple3d planePoint) {\r
+ point.sub(planePoint);\r
+ \r
+ return planeNormal.dot(point);\r
+ }\r
+ \r
+ public static double distanceFromPlane(Vector3d point, Vector3d planeNormal, float d) {\r
+ return (planeNormal.dot(point) + d);\r
+ }\r
+ \r
+ public static boolean intersectStraightPlane(Tuple3d linePoint, Vector3d lineDir, Tuple3d planePoint, Vector3d planeNormal, Tuple3d intersectPoint) {\r
+ intersectPoint.set(planePoint);\r
+ intersectPoint.sub(linePoint);\r
+ double u = planeNormal.dot(new Vector3d(intersectPoint));\r
+ double v = planeNormal.dot(lineDir);\r
+ if (Math.abs(v) < NEAR_ZERO)\r
+ return false;\r
+ u /= v;\r
+ intersectPoint.set(lineDir);\r
+ intersectPoint.scale(u);\r
+ intersectPoint.add(linePoint);\r
+ return true;\r
+ }\r
+ \r
+ public static boolean intersectStraightPlane(Tuple3d linePoint, Vector3d lineDir, Tuple3d planePoint, Vector3d planeNormal, Vector3d intersectPoint, double[] u) {\r
+ intersectPoint.set(planePoint);\r
+ intersectPoint.sub(linePoint);\r
+ u[0] = planeNormal.dot(intersectPoint);\r
+ double v = planeNormal.dot(lineDir);\r
+ if (Math.abs(v) < NEAR_ZERO)\r
+ return false;\r
+ u[0] /= v;\r
+ intersectPoint.set(lineDir);\r
+ intersectPoint.scale(u[0]);\r
+ intersectPoint.add(linePoint);\r
+ return true;\r
+ }\r
+ \r
+ public static boolean intersectLineLine(Tuple3d l1_start,Tuple3d l1_end,Tuple3d l2_start,Tuple3d l2_end,Tuple3d l1_pos, Tuple3d l2_pos) {\r
+ Vector3d p13 = new Vector3d();\r
+ Vector3d p43 = new Vector3d();\r
+ Vector3d p21 = new Vector3d();\r
+ double d1343,d4321,d1321,d4343,d2121;\r
+ double numer,denom;\r
+ p13.sub(l1_start, l2_start);\r
+ p43.sub(l2_end,l2_start);\r
+ if (Math.abs(p43.x) < NEAR_ZERO && Math.abs(p43.y) < NEAR_ZERO && Math.abs(p43.z) < NEAR_ZERO)\r
+ return false;\r
+ p21.sub(l1_end,l1_start);\r
+ if (Math.abs(p21.x) < NEAR_ZERO && Math.abs(p21.y) < NEAR_ZERO && Math.abs(p21.z) < NEAR_ZERO)\r
+ return false;\r
+\r
+ d1343 = p13.dot(p43);\r
+ d4321 = p43.dot(p21);\r
+ d1321 = p13.dot(p21);\r
+ d4343 = p43.lengthSquared();\r
+ d2121 = p21.lengthSquared();\r
+\r
+ denom = d2121 * d4343 - d4321 * d4321;\r
+ if (Math.abs(denom) < NEAR_ZERO)\r
+ return false;\r
+ numer = d1343 * d4321 - d1321 * d4343;\r
+\r
+ double mua = numer / denom;\r
+ double mub = (d1343 + d4321 * mua) / d4343;\r
+ \r
+ l1_pos.x = l1_start.x + mua * p21.x;\r
+ l1_pos.y = l1_start.y + mua * p21.y;\r
+ l1_pos.z = l1_start.z + mua * p21.z;\r
+ l2_pos.x = l2_start.x + mub * p43.x;\r
+ l2_pos.y = l2_start.y + mub * p43.y;\r
+ l2_pos.z = l2_start.z + mub * p43.z;\r
+\r
+ return true;\r
+ }\r
+ \r
+ public static boolean intersectStraightStraight(Tuple3d p1,Vector3d p21,Tuple3d p3,Vector3d p43,Tuple3d pa,Tuple3d pb) {\r
+ Vector3d p13 = new Vector3d();\r
+\r
+ double d1343,d4321,d1321,d4343,d2121;\r
+ double numer,denom;\r
+ \r
+ p13.sub(p1, p3);\r
+ if (Math.abs(p43.x) < NEAR_ZERO && Math.abs(p43.y) < NEAR_ZERO && Math.abs(p43.z) < NEAR_ZERO)\r
+ return false;\r
+ if (Math.abs(p21.x) < NEAR_ZERO && Math.abs(p21.y) < NEAR_ZERO && Math.abs(p21.z) < NEAR_ZERO)\r
+ return false;\r
+\r
+ d1343 = p13.dot(p43);\r
+ d4321 = p43.dot(p21);\r
+ d1321 = p13.dot(p21);\r
+ d4343 = p43.lengthSquared();\r
+ d2121 = p21.lengthSquared();\r
+\r
+ denom = d2121 * d4343 - d4321 * d4321;\r
+ if (Math.abs(denom) < NEAR_ZERO)\r
+ return false;\r
+ numer = d1343 * d4321 - d1321 * d4343;\r
+\r
+ double mua = numer / denom;\r
+ double mub = (d1343 + d4321 * mua) / d4343;\r
+\r
+ pa.x = p1.x + mua * p21.x;\r
+ pa.y = p1.y + mua * p21.y;\r
+ pa.z = p1.z + mua * p21.z;\r
+ pb.x = p3.x + mub * p43.x;\r
+ pb.y = p3.y + mub * p43.y;\r
+ pb.z = p3.z + mub * p43.z;\r
+\r
+ return true;\r
+ }\r
+ \r
+ /**\r
+ * Calculate the line segment PaPb that is the shortest route between\r
+ * two lines P1P2 and P3P4. Calculate also the values of mua and mub where\r
+ * Pa = P1 + mua (P2 - P1)\r
+ * Pb = P3 + mub (P4 - P3)\r
+ * @param p1\r
+ * @param p21\r
+ * @param p3\r
+ * @param p43\r
+ * @param pa\r
+ * @param pb\r
+ * @param mu\r
+ * @return\r
+ */\r
+ public static boolean intersectStraightStraight(Tuple3d p1,Vector3d p21,Tuple3d p3,Vector3d p43,Tuple3d pa,Tuple3d pb, double mu[]) {\r
+ Vector3d p13 = new Vector3d();\r
+\r
+ double d1343,d4321,d1321,d4343,d2121;\r
+ double numer,denom;\r
+ double EPS = 0.001;\r
+ p13.sub(p1, p3);\r
+ if (Math.abs(p43.x) < EPS && Math.abs(p43.y) < EPS && Math.abs(p43.z) < EPS)\r
+ return false;\r
+ if (Math.abs(p21.x) < EPS && Math.abs(p21.y) < EPS && Math.abs(p21.z) < EPS)\r
+ return false;\r
+\r
+ d1343 = p13.dot(p43);\r
+ d4321 = p43.dot(p21);\r
+ d1321 = p13.dot(p21);\r
+ d4343 = p43.lengthSquared();\r
+ d2121 = p21.lengthSquared();\r
+\r
+ denom = d2121 * d4343 - d4321 * d4321;\r
+ if (Math.abs(denom) < EPS)\r
+ return false;\r
+ numer = d1343 * d4321 - d1321 * d4343;\r
+\r
+ mu[0] = numer / denom;\r
+ mu[1] = (d1343 + d4321 * mu[0]) / d4343;\r
+\r
+ pa.x = p1.x + mu[0] * p21.x;\r
+ pa.y = p1.y + mu[0] * p21.y;\r
+ pa.z = p1.z + mu[0] * p21.z;\r
+ pb.x = p3.x + mu[1] * p43.x;\r
+ pb.y = p3.y + mu[1] * p43.y;\r
+ pb.z = p3.z + mu[1] * p43.z;\r
+\r
+ return true;\r
+ }\r
+ \r
+ \r
+ \r
+ public static void rotate(Quat4d q, Tuple3d in, Tuple3d out) {\r
+ // p' = q * p * q'\r
+ double tw = - q.x*in.x - q.y*in.y - q.z*in.z;\r
+ double tx = q.w*in.x + q.y*in.z - q.z*in.y;\r
+ double ty = q.w*in.y - q.x*in.z + q.z*in.x;\r
+ double tz = q.w*in.z + q.x*in.y - q.y*in.x ;\r
+ \r
+ //temp * q' -> x = -x, y = -y z = -z\r
+ //out.w = tw*q.w + tx*q.x + ty*q.y + tz*q.z;\r
+ out.x = -tw*q.x + tx*q.w - ty*q.z + tz*q.y;\r
+ out.y = -tw*q.y + tx*q.z + ty*q.w - tz*q.x;\r
+ out.z = -tw*q.z - tx*q.y + ty*q.x + tz*q.w; \r
+ }\r
+ \r
+ public static void getMatrix(Quat4d quat, Matrix3d m) {\r
+ m.m00 = 1.0f - 2.0 * (quat.y * quat.y + quat.z * quat.z);\r
+ m.m01 = 2.0 * (quat.x * quat.y + quat.w * quat.z);\r
+ m.m02 = 2.0 * (quat.x * quat.z - quat.w * quat.y);\r
+ m.m10 = 2.0 * (quat.x * quat.y - quat.w * quat.z);\r
+ m.m11 = 1.0 - 2.0f * (quat.x * quat.x + quat.z * quat.z);\r
+ m.m12 = 2.0 * (quat.y * quat.z + quat.w * quat.x);\r
+ m.m20 = 2.0 * (quat.x * quat.z + quat.w * quat.y);\r
+ m.m21 = 2.0 * (quat.y * quat.z - quat.w * quat.x);\r
+ m.m22 = 1.0 - 2.0f * (quat.x * quat.x + quat.y * quat.y);\r
+\r
+ }\r
+ \r
+ \r
+ private static double q[] = new double[3];\r
+ private static int nxt[] = { 1, 2, 0 };\r
+ /**\r
+ * Converts Matrix to Quaternion\r
+ * \r
+ * Note: non-thread safe.\r
+ * \r
+ * @param mat\r
+ * @param quat\r
+ */\r
+ public static void getQuat(Matrix3d mat, Quat4d quat) {\r
+ double tr = mat.m00 + mat.m11 + mat.m22;\r
+ if (tr > 0.0) {\r
+ double s = Math.sqrt(tr + 1.0);\r
+ quat.w = 0.5 * s;\r
+ s = 0.5 / s;\r
+ quat.x = (mat.m21 - mat.m12) * s;\r
+ quat.y = (mat.m02 - mat.m20) * s;\r
+ quat.z = (mat.m10 - mat.m01) * s;\r
+ } else {\r
+ int i = 0, j, k;\r
+ if (mat.m11 > mat.m00)\r
+ i = 1;\r
+ if (mat.m22 > mat.getElement(i, i))\r
+ i = 2;\r
+ \r
+\r
+ j = nxt[i];\r
+ k = nxt[j];\r
+\r
+ double s = Math.sqrt((mat.getElement(i, i) - (mat.getElement(j, j) + mat.getElement(k, k))) + 1.0);\r
+\r
+ q[i] = s * 0.5;\r
+\r
+ if (Math.abs(s) > 0.001)\r
+ s = 0.5 / s;\r
+\r
+ quat.w = (mat.getElement(k, j) - mat.getElement(j, k)) * s;\r
+ q[j] = (mat.getElement(j, i) + mat.getElement(i, j)) * s;\r
+ q[k] = (mat.getElement(k, i) + mat.getElement(i, k)) * s;\r
+\r
+ quat.x = q[0];\r
+ quat.y = q[1];\r
+ quat.z = q[2];\r
+ }\r
+ }\r
+ \r
+ public static Quat4d getQuat(Matrix3d mat) {\r
+ Quat4d q = new Quat4d();\r
+ getQuat(mat, q);\r
+ return q;\r
+ }\r
+ \r
+ public static AxisAngle4d getFromPseudoEuler(Vector3d euler) {\r
+ AxisAngle4d aa = new AxisAngle4d();\r
+ aa.angle = euler.length();\r
+ Vector3d normal = new Vector3d(euler);\r
+ if (aa.angle > NEAR_ZERO) {\r
+ normal.normalize();\r
+ aa.x = normal.x;\r
+ aa.y = normal.y;\r
+ aa.z = normal.z;\r
+ } else {\r
+ aa.x = 1.0;\r
+ aa.y = 0.0;\r
+ aa.z = 0.0;\r
+ }\r
+ \r
+ return aa;\r
+ }\r
+ \r
+ public static Vector3d getPseudoEuler(AxisAngle4d aa) {\r
+ Vector3d euler = new Vector3d(aa.x,aa.y,aa.z);\r
+ euler.scale(aa.angle);\r
+ return euler;\r
+ }\r
+ \r
+ \r
+ public static void getQuat(Vector3d euler, Quat4d quat) {\r
+ Quat4d q = EulerTools.getQuatFromEuler(Order.YXZ, euler.y,euler.x,euler.z);\r
+ quat.set(q);\r
+ // http://en.wikipedia.org/wiki/Rotation_formalisms_in_three_dimensions#Conversion_formulae_between_formalisms\r
+ // Using the x-convention, the 3-1-3 Euler angles phi, theta and psi (around the Z, X and again the Z-axis) \r
+// quat.x = -Math.cos((euler.x - euler.z)*0.5)*Math.sin(euler.y*0.5);\r
+// quat.y = -Math.sin((euler.x - euler.z)*0.5)*Math.sin(euler.y*0.5);\r
+// quat.z = -Math.sin((euler.x + euler.z)*0.5)*Math.cos(euler.y*0.5);\r
+// quat.w = Math.sin((euler.x + euler.z)*0.5)*Math.cos(euler.y*0.5);\r
+ \r
+ // http://www.euclideanspace.com/maths/geometry/rotations/conversions/eulerToQuaternion/index.htm\r
+ // Y, Z, X order\r
+// double c1 = Math.cos(euler.y*0.5);\r
+// double s1 = Math.sin(euler.y*0.5);\r
+// double c2 = Math.cos(euler.z*0.5);\r
+// double s2 = Math.sin(euler.z*0.5);\r
+// double c3 = Math.cos(euler.x*0.5);\r
+// double s3 = Math.sin(euler.x*0.5);\r
+// double c1c2 = c1*c2;\r
+// double s1s2 = s1*s2;\r
+// quat.w =c1c2*c3 - s1s2*s3;\r
+// quat.x =c1c2*s3 + s1s2*c3;\r
+// quat.y =s1*c2*c3 + c1*s2*s3;\r
+// quat.z =c1*s2*c3 - s1*c2*s3;\r
+\r
+// Quat4d q2 = EulerTools.getQuatFromEuler(Order.YZX, euler.y,euler.z,euler.x);\r
+// System.out.println("Q " + quat + " Q2 " + q2);\r
+// double c1 = Math.cos(euler.y);\r
+// double s1 = Math.sin(euler.y);\r
+// double c2 = Math.cos(euler.z);\r
+// double s2 = Math.sin(euler.z);\r
+// double c3 = Math.cos(euler.x);\r
+// double s3 = Math.sin(euler.x);\r
+// quat.w = Math.sqrt(1.0 + c1 * c2 + c1*c3 - s1 * s2 * s3 + c2*c3) / 2.0;\r
+// double w4 = (4.0 * quat.w);\r
+// quat.x = (c2 * s3 + c1 * s3 + s1 * s2 * c3) / w4 ;\r
+// quat.y = (s1 * c2 + s1 * c3 + c1 * s2 * s3) / w4 ;\r
+// quat.z = (-s1 * s3 + c1 * s2 * c3 +s2) / w4 ;\r
+ }\r
+ \r
+ \r
+ \r
+ \r
+ public static void getEuler(Quat4d quat,Vector3d euler) {\r
+ Vector3d e = EulerTools.getEulerFromQuat(Order.YXZ, quat);\r
+ euler.x = e.y;\r
+ euler.y = e.x;\r
+ euler.z = e.z;\r
+ \r
+ // http://en.wikipedia.org/wiki/Rotation_formalisms_in_three_dimensions#Conversion_formulae_between_formalisms\r
+// euler.x = Math.atan2(quat.x * quat.z + quat.y* quat.w, quat.y*quat.z - quat.x * quat.w);\r
+// euler.y = Math.acos(-square(quat.x) - square(quat.y) + square(quat.z) + square(quat.w));\r
+// euler.z = -Math.atan2(quat.x * quat.z - quat.y* quat.w, quat.y*quat.z + quat.x * quat.w);\r
+ \r
+ // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/index.htm\r
+ // Y, Z, X order\r
+// double test = quat.x * quat.y + quat.z * quat.w;\r
+// if (test > NEAR_HALF) {\r
+// euler.y = 2.0 * Math.atan2(quat.x,quat.w);\r
+// euler.z = Math.PI * 0.5;\r
+// euler.x = 0.0;\r
+// } else if (test < -NEAR_HALF) {\r
+// euler.y = -2.0 * Math.atan2(quat.x,quat.w);\r
+// euler.z = -Math.PI * 0.5;\r
+// euler.x = 0.0;\r
+// } else {\r
+// double sqx = square(quat.x);\r
+// double sqy = square(quat.y);\r
+// double sqz = square(quat.z);\r
+// euler.y = Math.atan2(2.0*(quat.y*quat.w-quat.x*quat.z), 1.0 - 2.0*(sqy-sqz));\r
+// euler.z = Math.asin(2.0*test);\r
+// euler.x = Math.atan2(2.0*(quat.x*quat.w-quat.y*quat.z), 1.0 - 2.0*(sqx-sqz));\r
+// System.out.println(euler + " " + EulerTools.getEulerFromQuat(Order.YXZ, quat) + " " + quat);\r
+// }\r
+// double sqw = quat.w*quat.w;\r
+// double sqx = quat.x*quat.x;\r
+// double sqy = quat.y*quat.y;\r
+// double sqz = quat.z*quat.z;\r
+// double unit = sqx + sqy + sqz + sqw; // if normalised is one, otherwise is correction factor\r
+// double test = quat.x*quat.y + quat.z*quat.w;\r
+// if (test > 0.499*unit) { // singularity at north pole\r
+// euler.y = 2 * Math.atan2(quat.x,quat.w);\r
+// euler.z = Math.PI/2;\r
+// euler.x = 0;\r
+// return;\r
+// }\r
+// if (test < -0.499*unit) { // singularity at south pole\r
+// euler.y = -2 * Math.atan2(quat.x,quat.w);\r
+// euler.z = -Math.PI/2;\r
+// euler.x = 0;\r
+// return;\r
+// }\r
+// euler.y = Math.atan2(2*quat.y*quat.w-2*quat.x*quat.z , sqx - sqy - sqz + sqw);\r
+// euler.z = Math.asin(2*test/unit);\r
+// euler.x = Math.atan2(2*quat.x*quat.w-2*quat.y*quat.z , -sqx + sqy - sqz + sqw);\r
+ }\r
+ \r
+ public static Quat4d getQuat(Vector3d euler) {\r
+ Quat4d q = new Quat4d();\r
+ getQuat(euler,q);\r
+ return q;\r
+ }\r
+ \r
+ \r
+ public static Vector3d getEuler(Quat4d quat) {\r
+ Vector3d v = new Vector3d();\r
+ getEuler(quat, v);\r
+ return v;\r
+ }\r
+ \r
+ public static Quat4d getQuat(AxisAngle4d aa) {\r
+ Quat4d q = new Quat4d();\r
+ getQuat(aa, q);\r
+ return q;\r
+ }\r
+ \r
+ public static AxisAngle4d getAxisAngle(Quat4d q) {\r
+ AxisAngle4d aa = new AxisAngle4d();\r
+ aa.set(q);\r
+ return aa;\r
+ }\r
+ \r
+ public static Quat4d getIdentityQuat() {\r
+ return new Quat4d(0, 0, 0, 1);\r
+ }\r
+ \r
+ public static void getQuat(AxisAngle4d aa, Quat4d q) {\r
+ double mag,amag;\r
+ // Quat = cos(theta/2) + sin(theta/2)(roation_axis) \r
+ \r
+ amag = Math.sqrt( aa.x*aa.x + aa.y*aa.y + aa.z*aa.z);\r
+ if( amag < NEAR_ZERO ) {\r
+ q.w = 1.0;\r
+ q.x = 0.0;\r
+ q.y = 0.0;\r
+ q.z = 0.0;\r
+ } else { \r
+ amag = 1.0/amag; \r
+ double a2 = aa.angle * 0.5;\r
+ mag = Math.sin(a2);\r
+ q.w = Math.cos(a2);\r
+ q.x = aa.x*amag*mag;\r
+ q.y = aa.y*amag*mag;\r
+ q.z = aa.z*amag*mag;\r
+ }\r
+ }\r
+ \r
+ \r
+ /*\r
+ * Cohen-Sutherland\r
+ */\r
+ \r
+ private static final int IN = 0;\r
+ private static final int LEFT = 1;\r
+ private static final int RIGHT = 2;\r
+ private static final int BOTTOM = 4;\r
+ private static final int TOP = 8;\r
+ \r
+ \r
+ private static int bitcode(Vector2f p1, Vector2f min, Vector2f max) {\r
+ int code = IN;\r
+ if (p1.x < min.x)\r
+ code |= LEFT;\r
+ else if (p1.x > max.x)\r
+ code |= RIGHT;\r
+ if (p1.y < min.y)\r
+ code |= BOTTOM;\r
+ else if (p1.y > max.y)\r
+ code |= TOP;\r
+ return code;\r
+ }\r
+ \r
+ public static boolean clipLineRectangle(Vector2f p1,Vector2f p2, Vector2f min, Vector2f max, Vector2f r1, Vector2f r2) {\r
+ while (true) {\r
+ int o1 = bitcode(p1, min, max);\r
+ int o2 = bitcode(p2, min, max);\r
+ int and = o1 & o2;\r
+ int or = o1 | o2;\r
+ if (and != IN) {\r
+ return false;\r
+ }\r
+ if (or == IN) {\r
+ r1.set(p1);\r
+ r2.set(p2);\r
+ return true;\r
+ }\r
+ if (o1 == IN) {\r
+ Vector2f t = p1;\r
+ p1 = p2;\r
+ p2 = t;\r
+ int t2 = o1;\r
+ o1 = o2;\r
+ o2 = t2;\r
+ }\r
+ if ((o1 & TOP) != IN) {\r
+ float t = (max.y - p1.y) / (p2.y - p1.y);\r
+ p1.x += t * (p2.x - p1.x);\r
+ p1.y = max.y;\r
+ } else if ((o1 & BOTTOM) != IN) {\r
+ float t = (min.y - p1.y) / (p2.y - p1.y);\r
+ p1.x += t * (p2.x - p1.x);\r
+ p1.y = min.y;\r
+ } else if ((o1 & LEFT) != IN) {\r
+ float t = (min.x - p1.x) / (p2.x - p1.x);\r
+ p1.y += t * (p2.y - p1.y);\r
+ p1.x = min.x;\r
+ } else if ((o1 & RIGHT) != IN) {\r
+ float t = (max.x - p1.x) / (p2.x - p1.x);\r
+ p1.y += t * (p2.y - p1.y);\r
+ p1.x = max.x;\r
+ } else {\r
+ throw new RuntimeException("Error in clipping code");\r
+ }\r
+ }\r
+ \r
+ }\r
+ \r
+ public static double square(double d) {\r
+ return d * d;\r
+ }\r
+ \r
+ \r
+ public static void multiplyOrientation(AxisAngle4d aa, AxisAngle4d rot) {\r
+ Quat4d q1 = new Quat4d();\r
+ getQuat(aa, q1);\r
+ Quat4d q2 = new Quat4d();\r
+ getQuat(rot, q2);\r
+ q2.mul(q1);\r
+ rot.set(q2);\r
+ }\r
+ \r
+ public static double radToDeg(double rad) {\r
+ return (rad / Math.PI) * 180.0;\r
+ }\r
+ \r
+ public static double degToRad(double deg) {\r
+ return (deg / 180.0) * Math.PI;\r
+ }\r
+ \r
+ public static double clamp(double min, double max,double v) {\r
+ if (v < min)\r
+ return min;\r
+ if (v > max)\r
+ return max;\r
+ return v;\r
+ }\r
+ \r
+ public static AxisAngle4d createRotation(Vector3d original, Vector3d rotated) { \r
+ AxisAngle4d result = new AxisAngle4d();\r
+ if (createRotation(original, rotated, result))\r
+ return result;\r
+ return null;\r
+ }\r
+ \r
+ \r
+ public static void setIdentity(Quat4d q) {\r
+ q.w = 1.0;\r
+ q.x = 0.0;\r
+ q.y = 0.0;\r
+ q.z = 0.0;\r
+ }\r
+ \r
+ public static void setIdentity(AxisAngle4d aa) {\r
+ aa.angle = 0.0;\r
+ aa.x = 0.0;\r
+ aa.y = 1.0;\r
+ aa.z = 0.0;\r
+ }\r
+ \r
+ public static void set(Matrix3d mat, double m00, double m01, double m02,\r
+ double m10, double m11, double m12, double m20, double m21,\r
+ double m22) {\r
+ mat.m00 = m00;\r
+ mat.m01 = m01;\r
+ mat.m02 = m02;\r
+\r
+ mat.m10 = m10;\r
+ mat.m11 = m11;\r
+ mat.m12 = m12;\r
+\r
+ mat.m20 = m20;\r
+ mat.m21 = m21;\r
+ mat.m22 = m22;\r
+ }\r
+ \r
+ public static void set(Matrix4d mat, double[] v) {\r
+ mat.m00 = v[0];\r
+ mat.m01 = v[1];\r
+ mat.m02 = v[2];\r
+ mat.m03 = v[3];\r
+\r
+ mat.m10 = v[4];\r
+ mat.m11 = v[5];\r
+ mat.m12 = v[6];\r
+ mat.m13 = v[7];\r
+\r
+ mat.m20 = v[8];\r
+ mat.m21 = v[9];\r
+ mat.m22 = v[10];\r
+ mat.m23 = v[11];\r
+\r
+ mat.m30 = v[12];\r
+ mat.m31 = v[13];\r
+ mat.m32 = v[14];\r
+ mat.m33 = v[15];\r
+\r
+ }\r
+ \r
+ public static boolean createRotation(Vector3d original, Vector3d rotated, AxisAngle4d result) {\r
+ \r
+ if (rotated.lengthSquared() > 0.01)\r
+ rotated.normalize();\r
+ else\r
+ return false;\r
+ double d = original.dot(rotated);\r
+ if (d > 0.9999) {\r
+ // original and rotated are parallel, pointing at the same direction\r
+ result.angle = 0.0;\r
+ result.x = 0.0;\r
+ result.y = 1.0;\r
+ result.z = 0.0;\r
+ } else if (d < -0.9999) {\r
+ // original and rotated are parallel, pointing at the opposite direction \r
+ Vector3d a = Z_AXIS;\r
+ if (Math.abs(a.dot(original)) > 0.8 )\r
+ a = Y_AXIS;\r
+ result.set(a, Math.PI);\r
+ } else {\r
+ double angle = original.angle(rotated);\r
+ Vector3d axis = new Vector3d();\r
+ axis.cross(original, rotated);\r
+ result.set(axis,angle);\r
+ }\r
+ return true;\r
+ }\r
+ \r
+ public static boolean createRotation(Vector3d original, Vector3d rotated, Quat4d result) {\r
+ \r
+ if (rotated.lengthSquared() > 0.01)\r
+ rotated.normalize();\r
+ else\r
+ return false;\r
+ double d = original.dot(rotated);\r
+ if (d > 0.9999) {\r
+ // original and rotated are parallel, pointing at the same direction\r
+ result.w = 1.0;\r
+ result.x = 0.0;\r
+ result.y = 0.0;\r
+ result.z = 0.0;\r
+ } else if (d < -0.9999) {\r
+ // original and rotated are parallel, pointing at the opposite direction \r
+ Vector3d a = Z_AXIS;\r
+ if (Math.abs(a.dot(original)) > 0.8 )\r
+ a = Y_AXIS;\r
+ getQuat(a, Math.PI, result);\r
+ \r
+ } else {\r
+ double angle = original.angle(rotated);\r
+ Vector3d axis = new Vector3d();\r
+ axis.cross(original, rotated);\r
+ getQuat(axis, angle, result);\r
+ }\r
+ return true;\r
+ }\r
+ \r
+ public static void getQuat(Vector3d axis, double angle, Quat4d q)\r
+ {\r
+ double mag,amag;\r
+ // Quat = cos(theta/2) + sin(theta/2)(roation_axis) \r
+ \r
+ amag = Math.sqrt( axis.x*axis.x + axis.y*axis.y + axis.z*axis.z);\r
+ if( amag < EPS ) {\r
+ q.w = 1.0;\r
+ q.x = 0.0;\r
+ q.y = 0.0;\r
+ q.z = 0.0;\r
+ } else { \r
+ amag = 1.0/amag; \r
+ double a2 = angle*0.5;\r
+ mag = Math.sin(a2);\r
+ q.w = Math.cos(a2);\r
+ q.x = axis.x*amag*mag;\r
+ q.y = axis.y*amag*mag;\r
+ q.z = axis.z*amag*mag;\r
+ }\r
+ \r
+ }\r
+ \r
+ /**\r
+ * Linear interpolation of quaternions. Result IS set to q1.\r
+ * @param q1\r
+ * @param q2\r
+ * @param alpha\r
+ */\r
+ public static void lip(Quat4d q1, Quat4d q2, double alpha) {\r
+ double s1 = 1.0 - alpha;\r
+ double s2 = alpha;\r
+ q1.scale(s1);\r
+ mad(q1,q2,s2);\r
+ q1.normalize();\r
+ }\r
+ \r
+ public static double dot(Quat4d q1, Quat4d q2) {\r
+ return q1.x * q2.x + q1.y * q2.y + q1.z * q2.z + q1.w * q2.w;\r
+ }\r
+ \r
+ public static void mad(Tuple3d q1, Tuple3d q2, double s2) {\r
+ q1.x += q2.x * s2;\r
+ q1.y += q2.y * s2;\r
+ q1.z += q2.z * s2;\r
+ }\r
+ \r
+ public static void mad(Quat4d q1, Quat4d q2, double s2) {\r
+ q1.x += q2.x * s2;\r
+ q1.y += q2.y * s2;\r
+ q1.z += q2.z * s2;\r
+ q1.w += q2.w * s2;\r
+ }\r
+ \r
+ /**\r
+ * Slerp\r
+ * \r
+ * Sets results to q1. Modifies q2.\r
+ * \r
+ * @param q1\r
+ * @param q2\r
+ * @param alpha\r
+ */\r
+ public static void sip(Quat4d q1, Quat4d q2, double alpha) {\r
+ double cosom = dot(q1,q2);\r
+ if (cosom < 0.0) {\r
+ cosom = -cosom;\r
+ q2.negate();\r
+ }\r
+ \r
+ if (cosom > 0.9999) {\r
+ q2.sub(q1);\r
+ q2.scale(alpha);\r
+ q1.add(q2);\r
+ q1.normalize();\r
+ return;\r
+ }\r
+ double theta_0 = Math.acos(cosom);\r
+ double theta = theta_0 * alpha;\r
+ Quat4d t = new Quat4d(q1);\r
+ t.scale(-cosom);\r
+ t.add(q2);\r
+ t.normalize();\r
+ t.scale(Math.sin(theta));\r
+ q1.scale(Math.cos(theta));\r
+ q1.add(t);\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.g3d.math;\r
+\r
+import javax.vecmath.Point3d;\r
+import javax.vecmath.Vector3d;\r
+\r
+public class Ray {\r
+ public Point3d pos;\r
+ public Vector3d dir;\r
+ \r
+ public Ray(Point3d pos, Vector3d dir) {\r
+ this.pos = pos;\r
+ this.dir = dir;\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.objmap.annotations;\r
+\r
+import java.lang.annotation.Annotation;\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.ANNOTATION_TYPE)\r
+public @interface HasCollectionAdder {\r
+ Class<? extends Annotation> value();\r
+}\r
--- /dev/null
+package org.simantics.g3d.objmap.annotations;\r
+\r
+import java.lang.annotation.Annotation;\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.ANNOTATION_TYPE)\r
+public @interface HasCollectionRemover {\r
+ Class<? extends Annotation> value();\r
+}\r
--- /dev/null
+package org.simantics.g3d.objmap.annotations;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+import org.simantics.g3d.objmap.rules.factory.ICollectionRuleFactory;\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.ANNOTATION_TYPE) \r
+public @interface HasCollectionRuleFactory {\r
+ Class<? extends ICollectionRuleFactory> value();\r
+}\r
--- /dev/null
+package org.simantics.g3d.objmap.annotations;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+import org.simantics.g3d.objmap.rules.factory.IGetSetRuleFactory;\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.ANNOTATION_TYPE) \r
+public @interface HasGetSetRuleFactory {\r
+ Class<? extends IGetSetRuleFactory> value();\r
+}\r
--- /dev/null
+package org.simantics.g3d.objmap.annotations;\r
+\r
+import java.lang.annotation.Annotation;\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.ANNOTATION_TYPE)\r
+public @interface HasSetter {\r
+ Class<? extends Annotation> value();\r
+}\r
--- /dev/null
+package org.simantics.g3d.objmap.annotations;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.METHOD)\r
+public @interface RelatedElementsAdd {\r
+ String value();\r
+}\r
--- /dev/null
+package org.simantics.g3d.objmap.annotations;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+import org.simantics.g3d.objmap.annotations.factories.RelatedElementsRuleFactory;\r
+\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.METHOD)\r
+@HasCollectionRuleFactory(RelatedElementsRuleFactory.class)\r
+@HasCollectionAdder(RelatedElementsAdd.class)\r
+@HasCollectionRemover(RelatedElementsRem.class)\r
+public @interface RelatedElementsGet {\r
+ String value();\r
+}\r
--- /dev/null
+package org.simantics.g3d.objmap.annotations;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.METHOD)\r
+public @interface RelatedElementsRem {\r
+ String value();\r
+}\r
--- /dev/null
+package org.simantics.g3d.objmap.annotations;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+import org.simantics.g3d.objmap.annotations.factories.RelatedGetSetObjRuleFactory;\r
+\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.METHOD)\r
+@HasGetSetRuleFactory(RelatedGetSetObjRuleFactory.class)\r
+@HasSetter(RelatedSetObj.class)\r
+public @interface RelatedGetObj {\r
+ String value();\r
+}\r
--- /dev/null
+package org.simantics.g3d.objmap.annotations;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+import org.simantics.g3d.objmap.annotations.factories.RelatedGetSetValueRuleFactory;\r
+import org.simantics.objmap.rules.adapters.IdentityAdapter;\r
+import org.simantics.objmap.rules.adapters.ValueAdapter;\r
+\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.METHOD)\r
+@HasGetSetRuleFactory(RelatedGetSetValueRuleFactory.class)\r
+@HasSetter(RelatedSetValue.class)\r
+public @interface RelatedGetValue {\r
+ String value();\r
+ Class<? extends ValueAdapter> adapter() default IdentityAdapter.class;\r
+}\r
--- /dev/null
+package org.simantics.g3d.objmap.annotations;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.METHOD)\r
+public @interface RelatedSetObj {\r
+ String value();\r
+}\r
--- /dev/null
+package org.simantics.g3d.objmap.annotations;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.METHOD)\r
+public @interface RelatedSetValue {\r
+ String value();\r
+}\r
--- /dev/null
+package org.simantics.g3d.objmap.annotations.factories;\r
+\r
+import java.lang.annotation.Annotation;\r
+import java.lang.reflect.Method;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.g3d.objmap.annotations.RelatedElementsAdd;\r
+import org.simantics.g3d.objmap.annotations.RelatedElementsGet;\r
+import org.simantics.g3d.objmap.annotations.RelatedElementsRem;\r
+import org.simantics.g3d.objmap.rules.factory.ICollectionRuleFactory;\r
+import org.simantics.g3d.objmap.rules.range.CollectionAccessor;\r
+import org.simantics.objmap.IMappingRule;\r
+import org.simantics.objmap.rules.MappedElementsRule;\r
+import org.simantics.objmap.rules.domain.RelatedObjectsAccessor;\r
+\r
+public class RelatedElementsRuleFactory implements ICollectionRuleFactory {\r
+ \r
+ @Override\r
+ public IMappingRule create(ReadGraph g, Annotation annotation,\r
+ Method getter, Method adder, Method remover)\r
+ throws DatabaseException {\r
+ RelatedElementsGet getterAnn = (RelatedElementsGet)annotation;\r
+ return new MappedElementsRule(new RelatedObjectsAccessor(g.getResource(getterAnn.value()),true),\r
+ new CollectionAccessor<Object>(getter, adder, remover));\r
+ }\r
+ \r
+ @Override\r
+ public boolean isAdder(Annotation getterAnnotation, Annotation annotation) {\r
+ RelatedElementsGet getterAnn = (RelatedElementsGet)getterAnnotation;\r
+ RelatedElementsAdd adderAnn = (RelatedElementsAdd)annotation;\r
+ return getterAnn.value().equals(adderAnn.value());\r
+ }\r
+ \r
+ @Override\r
+ public boolean isRemover(Annotation getterAnnotation, Annotation annotation) {\r
+ RelatedElementsGet getterAnn = (RelatedElementsGet)getterAnnotation;\r
+ RelatedElementsRem adderAnn = (RelatedElementsRem)annotation;\r
+ return getterAnn.value().equals(adderAnn.value());\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.objmap.annotations.factories;\r
+\r
+import java.lang.annotation.Annotation;\r
+import java.lang.reflect.Method;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.g3d.objmap.annotations.RelatedGetObj;\r
+import org.simantics.g3d.objmap.annotations.RelatedGetValue;\r
+import org.simantics.g3d.objmap.annotations.RelatedSetObj;\r
+import org.simantics.g3d.objmap.annotations.RelatedSetValue;\r
+import org.simantics.g3d.objmap.rules.factory.IGetSetRuleFactory;\r
+import org.simantics.g3d.objmap.rules.range.GetSetObjectAccessor;\r
+import org.simantics.objmap.IMappingRule;\r
+import org.simantics.objmap.rules.MappedElementRule;\r
+import org.simantics.objmap.rules.domain.RelatedObjectAccessor;\r
+\r
+/**\r
+ * Rule factory for mapped object using Getter/Setter-methods.\r
+ * \r
+ * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
+ *\r
+ */\r
+public class RelatedGetSetObjRuleFactory implements IGetSetRuleFactory {\r
+ \r
+ @Override\r
+ public IMappingRule create(ReadGraph g, Annotation annotation,\r
+ Method getter, Method setter)\r
+ throws DatabaseException {\r
+ RelatedGetObj getterAnn = (RelatedGetObj)annotation;\r
+ return new MappedElementRule(new RelatedObjectAccessor(g.getResource(getterAnn.value())),\r
+ new GetSetObjectAccessor<Object>(getter, setter));\r
+ }\r
+ \r
+ @Override\r
+ public boolean isSetter(Annotation getterAnnotation, Annotation annotation) {\r
+ RelatedGetObj getterAnn = (RelatedGetObj)getterAnnotation;\r
+ RelatedSetObj setterAnn = (RelatedSetObj)annotation;\r
+ return getterAnn.value().equals(setterAnn.value());\r
+ }\r
+ \r
+ \r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.objmap.annotations.factories;\r
+\r
+import java.lang.annotation.Annotation;\r
+import java.lang.reflect.Method;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.g3d.objmap.annotations.RelatedGetValue;\r
+import org.simantics.g3d.objmap.annotations.RelatedSetValue;\r
+import org.simantics.g3d.objmap.rules.factory.IGetSetRuleFactory;\r
+import org.simantics.g3d.objmap.rules.range.GetSetValueAccessor;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.objmap.IMappingRule;\r
+import org.simantics.objmap.rules.ValueRule;\r
+import org.simantics.objmap.rules.adapters.IdentityAdapter;\r
+import org.simantics.objmap.rules.adapters.ValueAdapter;\r
+import org.simantics.objmap.rules.domain.RelatedValueAccessor;\r
+import org.simantics.objmap.rules.range.AdaptedRangeAccessor;\r
+import org.simantics.objmap.rules.range.IRangeAccessor;\r
+\r
+/**\r
+ * Rule factory for mapped value using Getter/Setter-methods.\r
+ * \r
+ * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
+ *\r
+ */\r
+public class RelatedGetSetValueRuleFactory implements IGetSetRuleFactory {\r
+ \r
+ @Override\r
+ public IMappingRule create(ReadGraph g, Annotation annotation,\r
+ Method getter, Method setter)\r
+ throws DatabaseException {\r
+ RelatedGetValue getterAnn = (RelatedGetValue)annotation;\r
+ \r
+ Class<? extends ValueAdapter> adapterClass = getterAnn.adapter();\r
+ IRangeAccessor<Object> rangeAccessor = new GetSetValueAccessor<Object>(getter, setter);\r
+ Resource valueType;\r
+ if (adapterClass == IdentityAdapter.class) {\r
+ valueType = dataTypeOfClass(g, getter.getReturnType());\r
+ } else {\r
+ try{\r
+ ValueAdapter adapter = adapterClass.newInstance();\r
+ rangeAccessor = new AdaptedRangeAccessor(rangeAccessor, adapter);\r
+ valueType = adapter.rangeTypeToDomainType(g, getter.getReturnType());\r
+ } catch (InstantiationException e) {\r
+ throw new RuntimeException(e);\r
+ } catch (IllegalAccessException e) {\r
+ throw new RuntimeException(e);\r
+ }\r
+ }\r
+ return new ValueRule(new RelatedValueAccessor(g.getResource(getterAnn.value()), valueType),\r
+ rangeAccessor);\r
+ }\r
+ \r
+ @Override\r
+ public boolean isSetter(Annotation getterAnnotation, Annotation annotation) {\r
+ RelatedGetValue getterAnn = (RelatedGetValue)getterAnnotation;\r
+ RelatedSetValue setterAnn = (RelatedSetValue)annotation;\r
+ return getterAnn.value().equals(setterAnn.value());\r
+ }\r
+ \r
+ public static Resource dataTypeOfClass(ReadGraph g, Class<?> clazz) {\r
+ Layer0 b = Layer0.getInstance(g);\r
+ if(clazz.equals(Double.class) || clazz.equals(double.class))\r
+ return b.Double;\r
+ else if(clazz.equals(String.class))\r
+ return b.String;\r
+ else if(clazz.equals(Integer.class) || clazz.equals(int.class))\r
+ return b.Integer;\r
+ else if(clazz.equals(Float.class) || clazz.equals(float.class))\r
+ return b.Float;\r
+ else if(clazz.equals(Boolean.class) || clazz.equals(boolean.class))\r
+ return b.Boolean;\r
+ else if(clazz.equals(Long.class) || clazz.equals(long.class))\r
+ return b.Long;\r
+ else if(clazz.equals(Byte.class) || clazz.equals(byte.class))\r
+ return b.Byte;\r
+ \r
+ else if(clazz.equals(double[].class))\r
+ return b.DoubleArray;\r
+ else if(clazz.equals(int[].class))\r
+ return b.IntegerArray;\r
+ else if(clazz.equals(byte[].class))\r
+ return b.ByteArray;\r
+ else if(clazz.equals(float[].class))\r
+ return b.FloatArray;\r
+ else if(clazz.equals(boolean[].class))\r
+ return b.BooleanArray;\r
+ else if(clazz.equals(String[].class))\r
+ return b.StringArray;\r
+ else if(clazz.equals(long[].class))\r
+ return b.LongArray;\r
+ else {\r
+ System.out.println("Couldn't find a data type for " + clazz);\r
+ return null;\r
+ }\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.objmap.rules.factory;\r
+\r
+import java.lang.annotation.Annotation;\r
+import java.lang.reflect.Method;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.objmap.IMappingRule;\r
+\r
+public interface ICollectionRuleFactory {\r
+ IMappingRule create(ReadGraph g, Annotation annotation, Method getter, Method adder, Method remover) throws DatabaseException;\r
+ boolean isAdder(Annotation getterAnnotation, Annotation annotation);\r
+ boolean isRemover(Annotation getterAnnotation, Annotation annotation);\r
+}\r
--- /dev/null
+package org.simantics.g3d.objmap.rules.factory;\r
+\r
+import java.lang.annotation.Annotation;\r
+import java.lang.reflect.Method;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.objmap.IMappingRule;\r
+\r
+public interface IGetSetRuleFactory {\r
+ IMappingRule create(ReadGraph g, Annotation annotation, Method getter, Method setter) throws DatabaseException;\r
+ boolean isSetter(Annotation getterAnnotation, Annotation annotation);\r
+}\r
--- /dev/null
+package org.simantics.g3d.objmap.rules.range;\r
+\r
+import java.lang.reflect.InvocationTargetException;\r
+import java.lang.reflect.Method;\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+\r
+import org.simantics.objmap.MappingException;\r
+import org.simantics.objmap.rules.range.IRangeAccessor;\r
+\r
+/**\r
+ * Accessor for mapped collections. \r
+ * Uses three methods:\r
+ * - Getter: returns the collection.\r
+ * - Adder: adds one item into the collection.\r
+ * - Remover: removes one item from the collection. \r
+ * \r
+ * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
+ *\r
+ * @param <T>\r
+ */\r
+public class CollectionAccessor<T> implements IRangeAccessor<Collection<T>> {\r
+ \r
+ private Method getter;\r
+ private Method adder;\r
+ private Method remover;\r
+ \r
+ public CollectionAccessor(Method getter, Method adder, Method remover) {\r
+ this.getter = getter;\r
+ this.adder = adder;\r
+ this.remover = remover;\r
+ }\r
+ \r
+ @SuppressWarnings("unchecked")\r
+ public java.util.Collection<T> get(Object element) throws org.simantics.objmap.MappingException {\r
+ try {\r
+ return (Collection<T>) getter.invoke(element);\r
+ } catch (IllegalArgumentException e) {\r
+ throw new MappingException(e);\r
+ } catch (IllegalAccessException e) {\r
+ throw new MappingException(e);\r
+ } catch (InvocationTargetException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ };\r
+\r
+ @Override\r
+ public boolean set(Object element, Collection<T> value)\r
+ throws MappingException {\r
+ java.util.Collection<T> current = get(element);\r
+ Collection<T> adding = new ArrayList<T>();\r
+ Collection<T> removing = new ArrayList<T>();\r
+ for (T e : current) {\r
+ if (!value.contains(e))\r
+ removing.add(e);\r
+ }\r
+ for (T e : value) {\r
+ if (!current.contains(e))\r
+ adding.add(e);\r
+ }\r
+ \r
+ try {\r
+ for (T e : removing) {\r
+ remover.invoke(element, e);\r
+ }\r
+ \r
+ for (T e : adding) {\r
+ adder.invoke(element, e);\r
+ }\r
+ } catch (IllegalArgumentException e) {\r
+ throw new MappingException(e);\r
+ } catch (IllegalAccessException e) {\r
+ throw new MappingException(e);\r
+ } catch (InvocationTargetException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ return true;\r
+ \r
+ }\r
+}\r
--- /dev/null
+package org.simantics.g3d.objmap.rules.range;\r
+\r
+import java.lang.reflect.InvocationTargetException;\r
+import java.lang.reflect.Method;\r
+\r
+import org.simantics.objmap.MappingException;\r
+import org.simantics.objmap.rules.range.IRangeAccessor;\r
+\r
+/**\r
+ * Accessor for mapped objects. Uses two methods:\r
+ * - Getter: returns the current object.\r
+ * - Setter: sets the current object. The object may be null.\r
+ * \r
+ * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
+ *\r
+ * @param <T>\r
+ */\r
+public class GetSetObjectAccessor<T> implements IRangeAccessor<T> {\r
+ \r
+ private Method getter;\r
+ private Method setter;\r
+ \r
+ \r
+ public GetSetObjectAccessor(Method getter, Method setter) {\r
+ this.getter = getter;\r
+ this.setter = setter;\r
+ \r
+ }\r
+ \r
+ @SuppressWarnings("unchecked")\r
+ public T get(Object element) throws org.simantics.objmap.MappingException {\r
+ try {\r
+ return (T) getter.invoke(element);\r
+ } catch (IllegalArgumentException e) {\r
+ throw new MappingException(e);\r
+ } catch (IllegalAccessException e) {\r
+ throw new MappingException(e);\r
+ } catch (InvocationTargetException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ };\r
+\r
+ @Override\r
+ public boolean set(Object element, T value)\r
+ throws MappingException { \r
+ try {\r
+ setter.invoke(element, value);\r
+ } catch (IllegalArgumentException e) {\r
+ throw new MappingException(e);\r
+ } catch (IllegalAccessException e) {\r
+ throw new MappingException(e);\r
+ } catch (InvocationTargetException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ return true;\r
+ \r
+ }\r
+}\r
--- /dev/null
+package org.simantics.g3d.objmap.rules.range;\r
+\r
+import java.lang.reflect.InvocationTargetException;\r
+import java.lang.reflect.Method;\r
+\r
+import org.simantics.objmap.MappingException;\r
+import org.simantics.objmap.rules.range.IRangeAccessor;\r
+\r
+/**\r
+ * Accessor for mapped value. Uses two methods:\r
+ * - Getter: returns the current value.\r
+ * - Setter: sets the current value. The value may be null. (if setter parameter is primitive, null value is not mapped).\r
+ * \r
+ * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
+ *\r
+ * @param <T>\r
+ */\r
+public class GetSetValueAccessor<T> implements IRangeAccessor<T> {\r
+ \r
+ private Method getter;\r
+ private Method setter;\r
+ private boolean primitive;\r
+ \r
+ public GetSetValueAccessor(Method getter, Method setter) {\r
+ this.getter = getter;\r
+ this.setter = setter;\r
+ this.primitive = setter.getParameterTypes()[0].isPrimitive();\r
+ }\r
+ \r
+ @SuppressWarnings("unchecked")\r
+ public T get(Object element) throws org.simantics.objmap.MappingException {\r
+ try {\r
+ return (T) getter.invoke(element);\r
+ } catch (IllegalArgumentException e) {\r
+ throw new MappingException(e);\r
+ } catch (IllegalAccessException e) {\r
+ throw new MappingException(e);\r
+ } catch (InvocationTargetException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ };\r
+\r
+ @Override\r
+ public boolean set(Object element, T value)\r
+ throws MappingException {\r
+ if (value == null && primitive)\r
+ return false;\r
+ if (equal(get(element),value))\r
+ return false;\r
+ try {\r
+ setter.invoke(element, value);\r
+ } catch (IllegalArgumentException e) {\r
+ throw new MappingException(e);\r
+ } catch (IllegalAccessException e) {\r
+ throw new MappingException(e);\r
+ } catch (InvocationTargetException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ return true;\r
+ \r
+ }\r
+ \r
+ private boolean equal(Object v1, Object v2) {\r
+ if (v1 == null) {\r
+ if (v2 == null)\r
+ return true;\r
+ return false;\r
+ } else if (v2 == null) {\r
+ return false;\r
+ }\r
+ return v1.equals(v2);\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.g3d.objmap.schema;\r
+\r
+//import org.apache.log4j.Logger;\r
+import org.eclipse.core.runtime.IAdaptable;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.objmap.IFunction;\r
+import org.simantics.objmap.ILinkType;\r
+import org.simantics.objmap.MappingException;\r
+\r
+/**\r
+ * A link type that is associated with adaptable resource (ReadGraph.getAdapter(Resource,Class)). \r
+ * The adapted object must implement IAdaptable interface for returning the original Resource. \r
+ * \r
+ * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
+ *\r
+ */\r
+public class AdaptedLinkType implements ILinkType {\r
+\r
+ \r
+ //static Logger LOGGER = Logger.getLogger("org.simantics.objmap");\r
+ \r
+ Resource domainType;\r
+ Class<?> rangeType;\r
+ \r
+ \r
+ public AdaptedLinkType(Resource domainType, Class<?> rangeType) {\r
+ this.domainType = domainType;\r
+ this.rangeType = rangeType;\r
+ }\r
+ \r
+ @Override\r
+ public Resource createDomainElement(WriteGraph g, Object rangeElement)\r
+ throws MappingException {\r
+ try {\r
+ IAdaptable adaptable = (IAdaptable)rangeElement;\r
+ Resource res = (Resource)adaptable.getAdapter(Resource.class);\r
+ if (res == null)\r
+ throw new NullPointerException();\r
+ return res;\r
+ } catch (Exception e) {\r
+ throw new MappingException("Adapted object must implement IAdaptable interface to return the source Resource.", e);\r
+ }\r
+ \r
+ }\r
+ \r
+ @Override\r
+ public Object createRangeElement(ReadGraph g, Resource domainElement)\r
+ throws MappingException {\r
+ try {\r
+ return g.adapt(domainElement, rangeType);\r
+ } catch (DatabaseException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public boolean updateDomain(WriteGraph g, IFunction<Object, Resource> map,\r
+ Resource domainElement, Object rangeElement)\r
+ throws MappingException {\r
+ return false;\r
+ }\r
+ @Override\r
+ public boolean updateRange(ReadGraph g, IFunction<Resource, Object> map,\r
+ Resource domainElement, Object rangeElement)\r
+ throws MappingException {\r
+ return false;\r
+ }\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.g3d.objmap.schema;\r
+\r
+import gnu.trove.THashMap;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.common.utils.NameUtils;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.objmap.ILinkType;\r
+import org.simantics.objmap.IMappingSchema;\r
+import org.simantics.objmap.MappingException;\r
+import org.simantics.objmap.schema.SimpleLinkType;\r
+\r
+/**\r
+ * \r
+ */\r
+public class DefaultSchema implements IMappingSchema {\r
+\r
+ THashMap<Resource, ILinkType> domainLinkTypes = \r
+ new THashMap<Resource, ILinkType>();\r
+ THashMap<Class<?>, ILinkType> rangeLinkTypes = \r
+ new THashMap<Class<?>, ILinkType>();\r
+ \r
+ public void addLinkType(SimpleLinkType linkType) {\r
+ domainLinkTypes.put(linkType.domainType, linkType);\r
+ rangeLinkTypes.put(linkType.rangeType, linkType);\r
+ }\r
+ \r
+ public void addLinkType(AdaptedLinkType linkType) {\r
+ domainLinkTypes.put(linkType.domainType, linkType);\r
+ rangeLinkTypes.put(linkType.rangeType, linkType);\r
+ }\r
+ \r
+ @Override\r
+ public ILinkType linkTypeOfDomainElement(ReadGraph g, Resource element) throws MappingException { \r
+ try {\r
+ \r
+ for(Resource type : g.getTypes(element)) {\r
+\r
+ ILinkType linkType = domainLinkTypes.get(type);\r
+ if(linkType != null) return linkType;\r
+ \r
+ }\r
+ \r
+ throw new MappingException("Didn't find a link type for " +\r
+ NameUtils.getSafeName(g, element) + ".");\r
+ \r
+ } catch (DatabaseException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public ILinkType linkTypeOfRangeElement(Object element) throws MappingException {\r
+ ILinkType type = rangeLinkTypes.get(element.getClass());\r
+ if(type == null) {\r
+ for (Class<?> clazz : element.getClass().getInterfaces()) {\r
+ type = rangeLinkTypes.get(clazz);\r
+ if (type != null)\r
+ return type;\r
+ \r
+ }\r
+ throw new MappingException("Didn't find a link type for " + element + ".");\r
+ }\r
+ return type;\r
+ }\r
+\r
+ \r
+ public ILinkType linkTypeOfDomainType(ReadGraph g, Resource type) { \r
+ return domainLinkTypes.get(type);\r
+ }\r
+ \r
+ public ILinkType linkTypeOfRangeType(Class<?> clazz) {\r
+ ILinkType type = rangeLinkTypes.get(clazz);\r
+ if(type == null) {\r
+ for (Class<?> c : clazz.getInterfaces()) {\r
+ type = rangeLinkTypes.get(clazz);\r
+ if (type != null)\r
+ return type;\r
+ \r
+ }\r
+ }\r
+ return null;\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.g3d.objmap.schema;\r
+\r
+import java.lang.annotation.Annotation;\r
+import java.lang.reflect.Field;\r
+import java.lang.reflect.Method;\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.g3d.objmap.annotations.HasCollectionAdder;\r
+import org.simantics.g3d.objmap.annotations.HasCollectionRemover;\r
+import org.simantics.g3d.objmap.annotations.HasCollectionRuleFactory;\r
+import org.simantics.g3d.objmap.annotations.HasGetSetRuleFactory;\r
+import org.simantics.g3d.objmap.annotations.HasSetter;\r
+import org.simantics.g3d.objmap.rules.factory.ICollectionRuleFactory;\r
+import org.simantics.g3d.objmap.rules.factory.IGetSetRuleFactory;\r
+import org.simantics.objmap.ILinkType;\r
+import org.simantics.objmap.IMappingRule;\r
+import org.simantics.objmap.annotations.GraphType;\r
+import org.simantics.objmap.annotations.RelatedValue;\r
+import org.simantics.objmap.annotations.meta.HasClassRuleFactory;\r
+import org.simantics.objmap.annotations.meta.HasFieldRuleFactory;\r
+import org.simantics.objmap.annotations.meta.HasMethodRuleFactory;\r
+import org.simantics.objmap.schema.SimpleLinkType;\r
+\r
+public class MappingSchemas {\r
+ /**\r
+ * Creates a new SimpleLinkType based on the annotations in the given class.\r
+ * @throws IllegalAccessException \r
+ * @throws InstantiationException \r
+ * @see GraphType\r
+ * @see RelatedValue\r
+ */\r
+ public static SimpleLinkType fromAnnotations(ReadGraph g, Class<?> clazz) throws DatabaseException, InstantiationException, IllegalAccessException {\r
+ GraphType graphType = clazz.getAnnotation(GraphType.class);\r
+ \r
+ ArrayList<IMappingRule> rules = new ArrayList<IMappingRule>();\r
+ collectRulesFromAnnotations(g, clazz, rules);\r
+ \r
+ return new SimpleLinkType(\r
+ g.getResource(graphType.value()), \r
+ clazz, rules); \r
+ }\r
+ \r
+ public static void collectRulesFromAnnotations(ReadGraph g, Class<?> clazz, Collection<IMappingRule> rules) throws DatabaseException, InstantiationException, IllegalAccessException {\r
+ Class<?> superclass = clazz.getSuperclass();\r
+ if(superclass != null)\r
+ collectRulesFromAnnotations(g, superclass, rules);\r
+ \r
+ for(Annotation annotation : clazz.getAnnotations()) {\r
+ HasClassRuleFactory factory = \r
+ annotation.annotationType().getAnnotation(HasClassRuleFactory.class);\r
+ if(factory != null) {\r
+ rules.add(factory.value().newInstance()\r
+ .create(g, annotation, clazz));\r
+ }\r
+ }\r
+\r
+ for(Field f : clazz.getDeclaredFields()) {\r
+ f.setAccessible(true);\r
+\r
+ for(Annotation annotation : f.getAnnotations()) {\r
+ HasFieldRuleFactory factory = \r
+ annotation.annotationType().getAnnotation(HasFieldRuleFactory.class);\r
+ if(factory != null) {\r
+ rules.add(factory.value().newInstance()\r
+ .create(g, annotation, f));\r
+ }\r
+ }\r
+ }\r
+\r
+ for(Method m : clazz.getDeclaredMethods()) {\r
+ m.setAccessible(true);\r
+\r
+ for(Annotation annotation : m.getAnnotations()) {\r
+ HasMethodRuleFactory factory = \r
+ annotation.annotationType().getAnnotation(HasMethodRuleFactory.class);\r
+ if(factory != null) {\r
+ rules.add(factory.value().newInstance().create(g, annotation, m));\r
+ }\r
+ }\r
+ }\r
+ \r
+ for (Method m : clazz.getDeclaredMethods()) {\r
+ m.setAccessible(true);\r
+ for (Annotation annotation : m.getAnnotations()) {\r
+ Class<? extends Annotation> annotationType = annotation.annotationType();\r
+ HasGetSetRuleFactory factory = \r
+ annotationType.getAnnotation(HasGetSetRuleFactory.class);\r
+ if (factory != null) {\r
+ \r
+ HasSetter setterAnnType = annotationType.getAnnotation(HasSetter.class);\r
+ \r
+ Class<? extends Annotation> setterAnn = setterAnnType.value();\r
+ \r
+ IGetSetRuleFactory ruleFactory = factory.value().newInstance();\r
+ \r
+ Method getter = m;\r
+ Method setter = null;\r
+ \r
+ for (Method m2 : clazz.getDeclaredMethods()) {\r
+ Annotation set = m2.getAnnotation(setterAnn);\r
+ if (set != null && ruleFactory.isSetter(annotation, set))\r
+ setter = m2;\r
+ }\r
+\r
+ rules.add(ruleFactory.create(g, annotation, getter, setter));\r
+ }\r
+ \r
+ }\r
+ }\r
+ \r
+ for (Method m : clazz.getDeclaredMethods()) {\r
+ m.setAccessible(true);\r
+ for (Annotation annotation : m.getAnnotations()) {\r
+ Class<? extends Annotation> annotationType = annotation.annotationType();\r
+ HasCollectionRuleFactory factory = \r
+ annotationType.getAnnotation(HasCollectionRuleFactory.class);\r
+ if (factory != null) {\r
+ \r
+ HasCollectionAdder adderAnnType = annotationType.getAnnotation(HasCollectionAdder.class);\r
+ HasCollectionRemover removerAnnType = annotationType.getAnnotation(HasCollectionRemover.class);\r
+ \r
+ Class<? extends Annotation> adderAnn = adderAnnType.value();\r
+ Class<? extends Annotation> removerAnn = removerAnnType.value();\r
+ \r
+ ICollectionRuleFactory ruleFactory = factory.value().newInstance();\r
+ \r
+ Method getter = m;\r
+ Method adder = null;\r
+ Method remover = null;\r
+ \r
+ for (Method m2 : clazz.getDeclaredMethods()) {\r
+ Annotation add = m2.getAnnotation(adderAnn);\r
+ Annotation rem = m2.getAnnotation(removerAnn);\r
+ if (add != null && ruleFactory.isAdder(annotation, add))\r
+ adder = m2;\r
+ if (rem != null && ruleFactory.isRemover(annotation, rem))\r
+ remover = m2;\r
+ }\r
+ \r
+ \r
+ \r
+ rules.add(ruleFactory.create(g, annotation, getter,adder,remover));\r
+ }\r
+ \r
+ }\r
+ }\r
+ }\r
+ \r
+ /**\r
+ * Creates a new SimpleLinkType based on the annotations in the given class.\r
+ * @throws IllegalAccessException \r
+ * @throws InstantiationException \r
+ * @see GraphType\r
+ * @see RelatedValue\r
+ */\r
+ public static AdaptedLinkType fromAdaptable(ReadGraph g, String type, Class<?> clazz) throws DatabaseException, InstantiationException, IllegalAccessException {\r
+ \r
+ \r
+ return new AdaptedLinkType(g.getResource(type), clazz); \r
+ }\r
+ \r
+ \r
+}\r
--- /dev/null
+package org.simantics.g3d.preferences;
+
+import org.eclipse.jface.preference.*;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+import org.eclipse.ui.IWorkbench;
+import org.simantics.g3d.Activator;
+import org.simantics.g3d.math.EulerTools.Order;
+
+/**
+ * This class represents a preference page that
+ * is contributed to the Preferences dialog. By
+ * subclassing <samp>FieldEditorPreferencePage</samp>, we
+ * can use the field support built into JFace that allows
+ * us to create a page that is small and knows how to
+ * save, restore and apply itself.
+ * <p>
+ * This page is used to modify preferences only. They
+ * are stored in the preference store that belongs to
+ * the main plug-in class. That way, preferences can
+ * be accessed directly via the preference store.
+ */
+
+public class G3DPreferencePage
+ extends FieldEditorPreferencePage
+ implements IWorkbenchPreferencePage {
+
+ public G3DPreferencePage() {
+ super(GRID);
+ setPreferenceStore(Activator.getDefault().getPreferenceStore());
+ setDescription("3D modelling prederences");
+ }
+
+ /**
+ * Creates the field editors. Field editors are abstractions of
+ * the common GUI blocks needed to manipulate various types
+ * of preferences. Each field editor knows how to save and
+ * restore itself.
+ */
+ public void createFieldEditors() {
+ addField(new RadioGroupFieldEditor(
+ PreferenceConstants.ORIENTATION_PRESENTATION,
+ "OrientationPresentation", 1,
+ new String[][] { { "&Quaternion", "quat" },
+ { "&Axis-Angle", "aa" },{ "&Euler", "euler" } }, getFieldEditorParent()));
+ String[][] eulerOrders = new String[Order.values().length][2];
+ for (int i = 0; i < Order.values().length; i++) {
+ eulerOrders[i][0] = Order.values()[i].toString();
+ eulerOrders[i][1] = Order.values()[i].name();
+ }
+ addField(new RadioGroupFieldEditor(
+ PreferenceConstants.EULER_ANGLE_ORDER,
+ "Euler Angle Order", 1,
+ eulerOrders, getFieldEditorParent()));
+// addField(new DirectoryFieldEditor(PreferenceConstants.P_PATH,
+// "&Directory preference:", getFieldEditorParent()));
+// addField(
+// new BooleanFieldEditor(
+// PreferenceConstants.P_BOOLEAN,
+// "&An example of a boolean preference",
+// getFieldEditorParent()));
+//
+// addField(new RadioGroupFieldEditor(
+// PreferenceConstants.P_CHOICE,
+// "An example of a multiple-choice preference",
+// 1,
+// new String[][] { { "&Choice 1", "choice1" }, {
+// "C&hoice 2", "choice2" }
+// }, getFieldEditorParent()));
+// addField(
+// new StringFieldEditor(PreferenceConstants.P_STRING, "A &text preference:", getFieldEditorParent()));
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench)
+ */
+ public void init(IWorkbench workbench) {
+ }
+
+}
\ No newline at end of file
--- /dev/null
+package org.simantics.g3d.preferences;
+
+/**
+ * Constant definitions for plug-in preferences
+ */
+public class PreferenceConstants {
+
+ public static final String ORIENTATION_PRESENTATION = "orientationPresentationPreference";
+ public static final String EULER_ANGLE_ORDER = "eulerAngleOrderPreference";
+
+// public static final String P_PATH = "pathPreference";
+//
+// public static final String P_BOOLEAN = "booleanPreference";
+//
+// public static final String P_CHOICE = "choicePreference";
+//
+// public static final String P_STRING = "stringPreference";
+
+}
--- /dev/null
+package org.simantics.g3d.preferences;
+
+import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer;
+import org.eclipse.jface.preference.IPreferenceStore;
+
+import org.simantics.g3d.Activator;
+import org.simantics.g3d.math.EulerTools.Order;
+
+/**
+ * Class used to initialize default preference values.
+ */
+public class PreferenceInitializer extends AbstractPreferenceInitializer {
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer#initializeDefaultPreferences()
+ */
+ public void initializeDefaultPreferences() {
+ IPreferenceStore store = Activator.getDefault().getPreferenceStore();
+ store.setDefault(PreferenceConstants.ORIENTATION_PRESENTATION, "aa");
+ store.setDefault(PreferenceConstants.EULER_ANGLE_ORDER, Order.YXZ.toString());
+// store.setDefault(PreferenceConstants.P_BOOLEAN, true);
+// store.setDefault(PreferenceConstants.P_CHOICE, "choice2");
+// store.setDefault(PreferenceConstants.P_STRING,"Default value");
+ }
+
+}
--- /dev/null
+package org.simantics.g3d.property;\r
+\r
+import java.lang.annotation.Annotation;\r
+import java.lang.reflect.Field;\r
+import java.lang.reflect.InvocationTargetException;\r
+import java.lang.reflect.Method;\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.Collections;\r
+import java.util.HashMap;\r
+import java.util.HashSet;\r
+import java.util.LinkedHashMap;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.Set;\r
+\r
+import org.eclipse.jface.layout.GridDataFactory;\r
+import org.eclipse.jface.viewers.AbstractTableViewer;\r
+import org.eclipse.jface.viewers.CellEditor;\r
+import org.eclipse.jface.viewers.CellEditor.LayoutData;\r
+import org.eclipse.jface.viewers.CellLabelProvider;\r
+import org.eclipse.jface.viewers.CellNavigationStrategy;\r
+import org.eclipse.jface.viewers.ColumnViewer;\r
+import org.eclipse.jface.viewers.ColumnViewerEditor;\r
+import org.eclipse.jface.viewers.ColumnViewerEditorActivationEvent;\r
+import org.eclipse.jface.viewers.ColumnViewerEditorActivationListener;\r
+import org.eclipse.jface.viewers.ColumnViewerEditorActivationStrategy;\r
+import org.eclipse.jface.viewers.ColumnViewerEditorDeactivationEvent;\r
+import org.eclipse.jface.viewers.EditingSupport;\r
+import org.eclipse.jface.viewers.FocusCellOwnerDrawHighlighter;\r
+import org.eclipse.jface.viewers.ISelection;\r
+import org.eclipse.jface.viewers.ISelectionChangedListener;\r
+import org.eclipse.jface.viewers.ISelectionProvider;\r
+import org.eclipse.jface.viewers.IStructuredContentProvider;\r
+import org.eclipse.jface.viewers.SelectionChangedEvent;\r
+import org.eclipse.jface.viewers.StructuredSelection;\r
+import org.eclipse.jface.viewers.TableViewer;\r
+import org.eclipse.jface.viewers.TableViewerColumn;\r
+import org.eclipse.jface.viewers.TableViewerFocusCellManager;\r
+import org.eclipse.jface.viewers.TextCellEditor;\r
+import org.eclipse.jface.viewers.Viewer;\r
+import org.eclipse.jface.viewers.ViewerCell;\r
+import org.eclipse.jface.viewers.ViewerColumn;\r
+import org.eclipse.jface.viewers.ViewerRow;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.custom.TableEditor;\r
+import org.eclipse.swt.events.TraverseEvent;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Control;\r
+import org.eclipse.swt.widgets.Display;\r
+import org.eclipse.swt.widgets.Event;\r
+import org.eclipse.swt.widgets.Item;\r
+import org.eclipse.swt.widgets.TableColumn;\r
+import org.eclipse.swt.widgets.TableItem;\r
+import org.eclipse.ui.IWorkbenchSite;\r
+import org.simantics.db.management.ISessionContext;\r
+import org.simantics.g3d.property.annotations.CompoundGetPropertyValue;\r
+import org.simantics.g3d.property.annotations.CompoundSetPropertyValue;\r
+import org.simantics.g3d.property.annotations.GetPropertyValue;\r
+import org.simantics.g3d.property.annotations.PropertyTabBlacklist;\r
+import org.simantics.g3d.property.annotations.SetPropertyValue;\r
+import org.simantics.g3d.scenegraph.IG3DNode;\r
+import org.simantics.g3d.scenegraph.NodeMap;\r
+import org.simantics.g3d.scenegraph.NodeMapProvider;\r
+import org.simantics.g3d.scenegraph.base.INode;\r
+import org.simantics.g3d.scenegraph.base.NodeListener;\r
+import org.simantics.g3d.scenegraph.base.ParentNode;\r
+import org.simantics.g3d.scenegraph.structural.IStructuralNode;\r
+import org.simantics.g3d.tools.AdaptationUtils;\r
+import org.simantics.selectionview.IPropertyTab;\r
+import org.simantics.selectionview.IPropertyTab2;\r
+import org.simantics.utils.datastructures.Callback;\r
+import org.simantics.utils.datastructures.MapList;\r
+\r
+public class AnnotatedPropertyTabContributorFactory implements PropertyTabContributorFactory {\r
+\r
+ private static final boolean DEBUG = false;\r
+ \r
+ @SuppressWarnings("unchecked")\r
+ @Override\r
+ public List<PropertyTabContributor> getContributors(Object input) {\r
+ Map<String,IPropertyItem> items = new LinkedHashMap<String, IPropertyItem>();\r
+ List<String> blacklist = new ArrayList<String>();\r
+ try {\r
+ collectItems(input.getClass(), items);\r
+ collectBlacklist(input.getClass(), blacklist);\r
+ } catch (InstantiationException e) {\r
+ // TODO Auto-generated catch block\r
+ e.printStackTrace();\r
+ } catch (IllegalAccessException e) {\r
+ // TODO Auto-generated catch block\r
+ e.printStackTrace();\r
+ }\r
+ \r
+ if (items.size() == 0)\r
+ return Collections.EMPTY_LIST;\r
+ \r
+ MapList<String, IPropertyItem> tabMap = new MapList<String, IPropertyItem>();\r
+ List<String> tabs = new ArrayList<String>();\r
+ for (String id : items.keySet()) {\r
+ IPropertyItem item = items.get(id);\r
+ tabMap.add(item.getTabId(), item);\r
+ if (!tabs.contains(item.getTabId())) {\r
+ tabs.add(item.getTabId());\r
+ //System.out.println(item.tabId + " " + item.name + " " + item.id);\r
+ }\r
+ }\r
+ for (String s : blacklist) {\r
+ tabs.remove(s);\r
+ }\r
+ \r
+ List<PropertyTabContributor> contributors = new ArrayList<PropertyTabContributor>(tabs.size());\r
+ for (String tabId : tabs) {\r
+ contributors.add(new AnnotatedPropertyTabContributor(tabId, tabMap.getValues(tabId)));\r
+ }\r
+ \r
+ return contributors;\r
+ }\r
+ \r
+ \r
+ private static void collectItems(Class<?> clazz, Map<String, IPropertyItem> items) throws InstantiationException, IllegalAccessException {\r
+ Class<?> superclass = clazz.getSuperclass();\r
+ if(superclass != null)\r
+ collectItems(superclass, items);\r
+ \r
+ for (Method m : clazz.getDeclaredMethods()) {\r
+ m.setAccessible(true);\r
+ for (Annotation annotation : m.getAnnotations()) {\r
+ if (annotation.annotationType().equals(GetPropertyValue.class)) {\r
+ GetPropertyValue get = (GetPropertyValue)annotation;\r
+ PropertyItem item = (PropertyItem)items.get(get.value());\r
+ if (item == null) {\r
+ item = new PropertyItem(get.value());\r
+ items.put(item.id, item);\r
+ }\r
+\r
+ item.getter = m;\r
+ item.manipulatorClass = get.manipulator().newInstance().get(m,null);\r
+\r
+ item.tabId = get.tabId();\r
+\r
+ item.name = get.name();\r
+ \r
+ \r
+ } else if (annotation.annotationType().equals(SetPropertyValue.class)) {\r
+ SetPropertyValue set = (SetPropertyValue)annotation;\r
+ PropertyItem item = (PropertyItem)items.get(set.value());\r
+ if (item == null) {\r
+ item = new PropertyItem(set.value());\r
+ items.put(item.id, item);\r
+ }\r
+ \r
+ item.setter = m;\r
+ } else if (annotation.annotationType().equals(CompoundGetPropertyValue.class)) {\r
+ CompoundGetPropertyValue get = (CompoundGetPropertyValue)annotation;\r
+ CompoundPropertyItem item = (CompoundPropertyItem)items.get(get.value());\r
+ if (item == null) {\r
+ item = new CompoundPropertyItem(get.value());\r
+ items.put(item.id, item);\r
+ }\r
+\r
+ item.getter = m;\r
+ item.manipulatorFactory = get.manipulator().newInstance();\r
+\r
+ item.tabId = get.tabId();\r
+\r
+ item.name = get.name();\r
+ } else if (annotation.annotationType().equals(CompoundSetPropertyValue.class)) {\r
+ CompoundSetPropertyValue set = (CompoundSetPropertyValue)annotation;\r
+ CompoundPropertyItem item = (CompoundPropertyItem)items.get(set.value());\r
+ if (item == null) {\r
+ item = new CompoundPropertyItem(set.value());\r
+ items.put(item.id, item);\r
+ }\r
+ \r
+ item.setter = m;\r
+ }\r
+ }\r
+ }\r
+ \r
+ \r
+ }\r
+ \r
+ private static void collectBlacklist(Class<?> clazz, List<String> blacklist) throws InstantiationException, IllegalAccessException {\r
+ Class<?> superclass = clazz.getSuperclass();\r
+ if(superclass != null)\r
+ collectBlacklist(superclass, blacklist);\r
+ \r
+ PropertyTabBlacklist ann = clazz.getAnnotation(PropertyTabBlacklist.class);\r
+ if (ann == null)\r
+ return;\r
+ String s = ann.value();\r
+ if (s == null)\r
+ return;\r
+ if (s.length() == 0)\r
+ return;\r
+ for (String item : s.split(";")) {\r
+ blacklist.add(item);\r
+ }\r
+ \r
+ \r
+ }\r
+ \r
+ private static Map<PropertyItem, PropertyManipulator> createManipulators(CompoundPropertyItem item, Object obj) {\r
+ try {\r
+ \r
+ Map<String,Object> map = (Map<String, Object>)item.getter.invoke(obj);\r
+ Map<PropertyItem, PropertyManipulator> result = new HashMap<AnnotatedPropertyTabContributorFactory.PropertyItem, PropertyManipulator>();\r
+ for (String key : map.keySet()) {\r
+ MethodWithMapValueProvider provider = new MethodWithMapValueProvider(item.getter, item.setter, key);\r
+ Class<? extends PropertyManipulator> clazz = item.manipulatorFactory.get(null,map.get(key));\r
+ PropertyManipulator manipulator = clazz.getConstructor(ValueProvider.class,Object.class).newInstance(provider,obj);\r
+ PropertyItem i = new PropertyItem(item.id+"."+key);\r
+ i.getter = item.getter;\r
+ i.setter = item.setter;\r
+ i.name = key;\r
+ i.tabId = item.tabId;\r
+ result.put(i,manipulator);\r
+ }\r
+ return result;\r
+ } catch (Exception e) {\r
+ e.printStackTrace();\r
+ return Collections.EMPTY_MAP;\r
+ } \r
+ \r
+ }\r
+ \r
+ private static PropertyManipulator createManipulator(PropertyItem item, Object obj) {\r
+ try {\r
+ MethodValueProvider provider = new MethodValueProvider(item.getter, item.setter);\r
+ PropertyManipulator manipulator = item.manipulatorClass.getConstructor(ValueProvider.class,Object.class).newInstance(provider,obj);\r
+ return manipulator;\r
+ } catch (Exception e) {\r
+ e.printStackTrace();\r
+ return null;\r
+ } \r
+ }\r
+ \r
+ private static interface IPropertyItem {\r
+ public String getTabId();\r
+ }\r
+ \r
+ private static class PropertyItem implements IPropertyItem{\r
+ private String id;\r
+ private String name;\r
+ private String tabId;\r
+ private Method getter;\r
+ private Method setter;\r
+ private Class<? extends PropertyManipulator> manipulatorClass;\r
+ \r
+ \r
+ public PropertyItem(String id) {\r
+ if (id == null)\r
+ throw new NullPointerException();\r
+ this.id = id;\r
+ }\r
+ \r
+ @Override\r
+ public int hashCode() {\r
+ return id.hashCode();\r
+ }\r
+ \r
+ @Override\r
+ public String getTabId() {\r
+ return tabId;\r
+ }\r
+ }\r
+ \r
+ private static class CompoundPropertyItem implements IPropertyItem{\r
+ private String id;\r
+ private String name;\r
+ private String tabId;\r
+ private Method getter;\r
+ private Method setter;\r
+ private PropertyManipulatorFactory manipulatorFactory;\r
+ \r
+ \r
+ public CompoundPropertyItem(String id) {\r
+ if (id == null)\r
+ throw new NullPointerException();\r
+ this.id = id;\r
+ }\r
+ \r
+ @Override\r
+ public int hashCode() {\r
+ return id.hashCode();\r
+ }\r
+ \r
+ @Override\r
+ public String getTabId() {\r
+ return tabId;\r
+ }\r
+ }\r
+ \r
+ private static class AnnotatedPropertyTabContributor implements PropertyTabContributor {\r
+ private String id; \r
+ List<IPropertyItem> items;\r
+ \r
+ public AnnotatedPropertyTabContributor(String id, List<IPropertyItem> items) {\r
+ if (id == null)\r
+ throw new NullPointerException();\r
+ this.id = id;\r
+ this.items = items;\r
+ }\r
+ \r
+ @Override\r
+ public IPropertyTab create(Composite parent, IWorkbenchSite site,\r
+ ISessionContext context, Object input) {\r
+ AnnotatedPropertyTab tab = new AnnotatedPropertyTab(id, items);\r
+ tab.createControl(parent, context);\r
+ return tab;\r
+ }\r
+ \r
+ @Override\r
+ public String getId() {\r
+ return id;\r
+ }\r
+ \r
+ }\r
+ \r
+ private static class AnnotatedPropertyTab implements IPropertyTab2, NodeListener {\r
+ //private String id; \r
+ List<IPropertyItem> contibutedItems;\r
+ List<PropertyItem> resolvedItems = new ArrayList<PropertyItem>();\r
+ private Map<PropertyItem,PropertyManipulator> manipulators = new HashMap<PropertyItem, PropertyManipulator>();\r
+ \r
+ private TableViewer viewer;\r
+ \r
+ private IG3DNode node;\r
+ private NodeMap<?> nodeMap;\r
+ \r
+ private List<TableViewerColumn> valueColumns = new ArrayList<TableViewerColumn>();\r
+ \r
+ public AnnotatedPropertyTab(String id, List<IPropertyItem> items) {\r
+ //this.id = id;\r
+ this.contibutedItems = items;\r
+ \r
+ \r
+ }\r
+ \r
+ @Override\r
+ public void createControl(Composite parent, ISessionContext context) {\r
+ //parent.setLayout(new FillLayout());\r
+ viewer = new TableViewer(parent, SWT.FULL_SELECTION | SWT.SINGLE);\r
+ \r
+ GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(true, true).applyTo(viewer.getTable());\r
+ \r
+ //viewer.setLabelProvider(new AnnotatedTableLabelProvider(object))\r
+ \r
+ viewer.setContentProvider(new PropertyItemContentsProvider());\r
+ \r
+ TableViewerColumn name = new TableViewerColumn(viewer, SWT.LEFT);\r
+ //TableViewerColumn value = new TableViewerColumn(viewer, SWT.LEFT);\r
+ name.setLabelProvider(new PropertyItemNameProvider());\r
+ //value.setLabelProvider(new PropertyValueLabelProvider(null));\r
+ name.getColumn().setText("Property");\r
+ //value.getColumn().setText("Value");\r
+ name.getColumn().setWidth(200);\r
+ //value.getColumn().setWidth(200);\r
+ name.getViewer().addSelectionChangedListener(new ISelectionChangedListener() {\r
+ \r
+ @Override\r
+ public void selectionChanged(SelectionChangedEvent event) {\r
+ PropertyItem item = AdaptationUtils.adaptToSingle(event.getSelection(),PropertyItem.class);\r
+ if (item != null) {\r
+ PropertyManipulator manipulator = manipulators.get(item);//createManipulator(item, null);\r
+ for (int i = 0; i < valueColumns.size(); i++) {\r
+ TableViewerColumn c = valueColumns.get(i);\r
+ if (i < manipulator.getValueCount()) {\r
+ c.getColumn().setText(manipulator.getDescription(i));\r
+ } else {\r
+ c.getColumn().setText("");\r
+ }\r
+ }\r
+ }\r
+ \r
+ }\r
+ });\r
+ \r
+ int valueCount = 0;\r
+ for (IPropertyItem item : contibutedItems) {\r
+ if (item instanceof PropertyItem) {\r
+ PropertyManipulator manipulator = createManipulator((PropertyItem)item, null);\r
+ if (manipulator == null)\r
+ continue;\r
+ if (valueCount < manipulator.getValueCount())\r
+ valueCount = manipulator.getValueCount();\r
+ } else if (item instanceof CompoundPropertyItem) {\r
+ if (valueCount < 1)\r
+ valueCount = 1;\r
+ }\r
+ }\r
+ for (int i = 0; i < valueCount; i++) {\r
+ TableViewerColumn value = new TableViewerColumn(viewer, SWT.LEFT);\r
+ //value.getColumn().setText("Value " + (i+1));\r
+ value.getColumn().setText("");\r
+ value.getColumn().setWidth(200);\r
+ valueColumns.add(value);\r
+ //value.setEditingSupport(new )\r
+ }\r
+ viewer.getTable().setHeaderVisible(true);\r
+ viewer.getTable().setLinesVisible(true);\r
+ viewer.addSelectionChangedListener(new ISelectionChangedListener() {\r
+ \r
+ @Override\r
+ public void selectionChanged(SelectionChangedEvent event) {\r
+ PropertyItem item = AdaptationUtils.adaptToSingle(event.getSelection(), PropertyItem.class);\r
+ selectedItem = item;\r
+ if (!manipulators.get(selectedItem).getEditMode())\r
+ manipulators.get(selectedItem).setEditMode(true);\r
+ \r
+\r
+ for (IPropertyItem i : delayedUpdate) {\r
+ if (!i.equals(selectedItem)) {\r
+ manipulators.get(i).setEditMode(false);\r
+ viewer.update(i,null);\r
+ }\r
+ }\r
+ if (delayedUpdate.contains(selectedItem)) {\r
+ delayedUpdate.clear();\r
+ delayedUpdate.add(selectedItem);\r
+ } else {\r
+ delayedUpdate.clear();\r
+ }\r
+ }\r
+ });\r
+ \r
+ CellNavigationStrategy nStrategy = new CellNavigationStrategy() {\r
+ private ViewerCell internalFindSelectedCell(\r
+ ColumnViewer viewer, ViewerCell currentSelectedCell,\r
+ Event event) {\r
+ switch (event.keyCode) {\r
+ case SWT.ARROW_UP:\r
+ if (currentSelectedCell != null) {\r
+ return getNeighbor(currentSelectedCell,\r
+ ViewerCell.ABOVE, false);\r
+ }\r
+ break;\r
+ case SWT.ARROW_DOWN:\r
+ if (currentSelectedCell != null) {\r
+ return getNeighbor(currentSelectedCell,\r
+ ViewerCell.BELOW, false);\r
+ }\r
+ break;\r
+ case SWT.ARROW_LEFT:\r
+ if (currentSelectedCell != null) {\r
+ return getNeighbor(currentSelectedCell,\r
+ ViewerCell.LEFT, true);\r
+ }\r
+ break;\r
+ case SWT.ARROW_RIGHT:\r
+ if (currentSelectedCell != null) {\r
+ return getNeighbor(currentSelectedCell,\r
+ ViewerCell.RIGHT, true);\r
+ }\r
+ break;\r
+ }\r
+ return null;\r
+ }\r
+ \r
+ public ViewerCell findSelectedCell(ColumnViewer viewer,\r
+ ViewerCell currentSelectedCell, Event event) {\r
+ ViewerCell cell = internalFindSelectedCell(viewer,\r
+ currentSelectedCell, event);\r
+ if (cell != null) {\r
+ TableColumn t = AnnotatedPropertyTab.this.viewer.getTable().getColumn(\r
+ cell.getColumnIndex());\r
+ AnnotatedPropertyTab.this.viewer.getTable().showColumn(t);\r
+ }\r
+ return cell;\r
+ }\r
+ };\r
+ \r
+ TableViewerFocusCellManager focusCellManager = new TableViewerFocusCellManager(\r
+ viewer, new FocusCellOwnerDrawHighlighter(viewer));\r
+ try {\r
+ Field f = focusCellManager.getClass().getSuperclass()\r
+ .getDeclaredField("navigationStrategy");\r
+ f.setAccessible(true);\r
+ f.set(focusCellManager, nStrategy);\r
+ } catch (SecurityException e) {\r
+ e.printStackTrace();\r
+ } catch (NoSuchFieldException e) {\r
+ e.printStackTrace();\r
+ } catch (IllegalArgumentException e) {\r
+ e.printStackTrace();\r
+ } catch (IllegalAccessException e) {\r
+ e.printStackTrace();\r
+ }\r
+ ColumnViewerEditorActivationStrategy actSupport = new ColumnViewerEditorActivationStrategy(\r
+ viewer) {\r
+ protected boolean isEditorActivationEvent(\r
+ ColumnViewerEditorActivationEvent event) {\r
+ return event.eventType == ColumnViewerEditorActivationEvent.TRAVERSAL\r
+ || event.eventType == ColumnViewerEditorActivationEvent.MOUSE_DOUBLE_CLICK_SELECTION\r
+ || (event.eventType == ColumnViewerEditorActivationEvent.KEY_PRESSED && event.keyCode == SWT.CR)\r
+ || event.eventType == ColumnViewerEditorActivationEvent.PROGRAMMATIC;\r
+ }\r
+ };\r
+ TableViewerEditor.create(viewer, focusCellManager, actSupport,\r
+ ColumnViewerEditor.TABBING_HORIZONTAL\r
+ | ColumnViewerEditor.TABBING_MOVE_TO_ROW_NEIGHBOR\r
+ | ColumnViewerEditor.TABBING_VERTICAL\r
+ | ColumnViewerEditor.KEYBOARD_ACTIVATION);\r
+ viewer.getColumnViewerEditor().addEditorActivationListener(\r
+ new ColumnViewerEditorActivationListener() {\r
+ public void afterEditorActivated(\r
+ ColumnViewerEditorActivationEvent event) {\r
+ }\r
+\r
+ public void afterEditorDeactivated(\r
+ ColumnViewerEditorDeactivationEvent event) {\r
+ }\r
+\r
+ public void beforeEditorActivated(\r
+ ColumnViewerEditorActivationEvent event) {\r
+ ViewerCell cell = (ViewerCell) event.getSource();\r
+ viewer.getTable().showColumn(\r
+ viewer.getTable().getColumn(cell.getColumnIndex()));\r
+ }\r
+\r
+ public void beforeEditorDeactivated(\r
+ ColumnViewerEditorDeactivationEvent event) {\r
+ }\r
+ });\r
+ }\r
+ \r
+ \r
+ \r
+ \r
+ private IPropertyItem selectedItem = null;\r
+ private Set<IPropertyItem> delayedUpdate = new HashSet<IPropertyItem>();\r
+ \r
+ \r
+ @Override\r
+ public void setInput(ISessionContext context, ISelection selection,\r
+ boolean force) {\r
+ Collection<IG3DNode> nodes = AdaptationUtils.adaptToCollection(selection, IG3DNode.class);\r
+ if (nodes.size() != 1) {\r
+ if (node != null) {\r
+ node.removeListener(this);\r
+ node = null;\r
+ }\r
+ return;\r
+ }\r
+ IG3DNode n = nodes.iterator().next();\r
+ if (node != null) {\r
+ if (!node.equals(n)) {\r
+ node.removeListener(this);\r
+ setInput(n);\r
+ }\r
+ } else {\r
+ setInput(n);\r
+ }\r
+ }\r
+ \r
+ \r
+ \r
+ private void setInput(IG3DNode node) {\r
+ this.node = node;\r
+ this.node.addListener(this);\r
+ // resolve nodemap\r
+ IG3DNode n = node;\r
+ while (true) {\r
+ if (n == null) {\r
+ nodeMap = null;\r
+ break;\r
+ }\r
+ if (n instanceof NodeMapProvider<?>) {\r
+ nodeMap = ((NodeMapProvider<?>) n).getNodeMap();\r
+ if (nodeMap != null)\r
+ break;\r
+ }\r
+ n = (IG3DNode)n.getParent();\r
+ }\r
+ boolean readOnly = (node instanceof IStructuralNode && ((IStructuralNode)node).isPartOfInstantiatedModel() && !((IStructuralNode)node).isInstantiatedModelRoot());\r
+ // create label providers\r
+ PropertyValueLabelProvider2 p = new PropertyValueLabelProvider2(this);\r
+ int index = 0;\r
+ for (TableViewerColumn c : valueColumns) {\r
+ c.setLabelProvider(p);\r
+ if (!readOnly) {\r
+ PropertyEditingSupport support = new PropertyEditingSupport(this, viewer, index++, nodeMap);\r
+ c.setEditingSupport(support);\r
+ }\r
+ }\r
+ resolvedItems.clear();\r
+ manipulators.clear();\r
+ for (IPropertyItem item : contibutedItems) {\r
+ if (item instanceof PropertyItem) {\r
+ resolvedItems.add((PropertyItem)item);\r
+ manipulators.put((PropertyItem)item, createManipulator((PropertyItem)item, node));\r
+ }\r
+ else {\r
+ CompoundPropertyItem compound = (CompoundPropertyItem)item;\r
+ Map<PropertyItem, PropertyManipulator> manipulators = createManipulators(compound, node);\r
+ for (PropertyItem i : manipulators.keySet()) {\r
+ resolvedItems.add(i);\r
+ this.manipulators.put(i, manipulators.get(i));\r
+ }\r
+ }\r
+ }\r
+ \r
+ viewer.getTable().setEnabled(!readOnly);\r
+ viewer.setInput(resolvedItems);\r
+ }\r
+ \r
+ @Override\r
+ public void requestFocus() {\r
+ viewer.getTable().forceFocus();\r
+ }\r
+ \r
+ @Override\r
+ public void dispose() {\r
+ if (node != null) {\r
+ node.removeListener(this);\r
+ node = null;\r
+ }\r
+ \r
+ }\r
+ \r
+ @Override\r
+ public Control getControl() {\r
+ return viewer.getTable();\r
+ }\r
+ \r
+ @Override\r
+ public ISelectionProvider getSelectionProvider() {\r
+ return null;\r
+ }\r
+ \r
+ @Override\r
+ public boolean isDisposed() {\r
+ return viewer.getTable().isDisposed();\r
+ }\r
+ \r
+ @Override\r
+ public <T extends INode> void nodeAdded(ParentNode<T> node,\r
+ INode child, String rel) {\r
+ \r
+ }\r
+ \r
+ @Override\r
+ public <T extends INode> void nodeRemoved(ParentNode<T> node,\r
+ INode child, String rel) {\r
+ \r
+ }\r
+ \r
+ @Override\r
+ public void propertyChanged(INode node, final String id) {\r
+// for (final PropertyItem item : items) {\r
+// if (item.id.equals(id)) {\r
+// Display.getDefault().asyncExec(new Runnable() {\r
+// \r
+// @Override\r
+// public void run() {\r
+// viewer.update(item, null);\r
+// \r
+// }\r
+// });\r
+// }\r
+// }\r
+ if (Thread.currentThread() == Display.getDefault().getThread()) {\r
+ if (DEBUG)System.out.println("Viewer refresh " + id);\r
+ for (PropertyItem item : resolvedItems)\r
+ if (!item.equals(selectedItem))\r
+ viewer.refresh(item);\r
+ if (selectedItem != null)\r
+ delayedUpdate.add(selectedItem);\r
+ } else if (!editing){\r
+ // running delayed refresh when a cell editor is active would cancel cell editing.\r
+ Display.getDefault().asyncExec(new Runnable() {\r
+ @Override\r
+ public void run() {\r
+ if (viewer.getTable().isDisposed()) {\r
+ if (AnnotatedPropertyTab.this.node != null)\r
+ AnnotatedPropertyTab.this.node.removeListener(AnnotatedPropertyTab.this);\r
+ return;\r
+ }\r
+ if (DEBUG) System.out.println("Viewer threaded refresh " + id);\r
+ for (PropertyItem item : resolvedItems)\r
+ if (!item.equals(selectedItem))\r
+ viewer.refresh(item);\r
+ if (selectedItem != null)\r
+ delayedUpdate.add(selectedItem);\r
+ \r
+ }\r
+ });\r
+ } else {\r
+ for (PropertyItem item : resolvedItems) {\r
+ delayedUpdate.add(item);\r
+ }\r
+ }\r
+ \r
+ }\r
+ \r
+\r
+ \r
+ \r
+ \r
+ @Override\r
+ public void updatePartName(Callback<String> updateCallback) {\r
+ if (node != null)\r
+ updateCallback.run(node.toString()); \r
+ \r
+ }\r
+ \r
+ public PropertyManipulator getManipulator(PropertyItem item) {\r
+ return manipulators.get(item);\r
+ }\r
+ \r
+ private boolean editing = false;\r
+ \r
+ public void setEditing(boolean editing) {\r
+ this.editing = editing;\r
+ }\r
+ }\r
+ \r
+ \r
+ \r
+ private static class PropertyEditingSupport extends EditingSupport {\r
+ AnnotatedPropertyTab tab;\r
+ int index;\r
+ NodeMap<?> nodeMap;\r
+ TableViewer viewer;\r
+ CellEditor editor;\r
+\r
+ public PropertyEditingSupport(AnnotatedPropertyTab tab, TableViewer viewer, int index, NodeMap<?> nodeMap) {\r
+ super(viewer);\r
+ this.tab = tab;\r
+ this.index = index;\r
+ this.viewer = viewer;\r
+ this.nodeMap = nodeMap;\r
+ }\r
+ \r
+ @Override\r
+ protected boolean canEdit(Object element) {\r
+ PropertyItem item = (PropertyItem)element;\r
+ if (tab.getManipulator(item).getValueCount() <= index)\r
+ return false;\r
+ return (item.setter != null);\r
+ }\r
+ \r
+ @Override\r
+ protected CellEditor getCellEditor(Object element) {\r
+ \r
+ if (tab.getManipulator((PropertyItem)element).getValueCount() <= index)\r
+ return null;\r
+ if (editor == null)\r
+ editor = new TextCellEditor(viewer.getTable(),SWT.NONE) {\r
+ @Override\r
+ public void activate() {\r
+ tab.setEditing(true);\r
+ }\r
+ \r
+ @Override\r
+ public void deactivate() {\r
+ super.deactivate();\r
+ tab.setEditing(false);\r
+ }\r
+ };\r
+ if (DEBUG)System.err.println("CELL EDITOR: " + element);\r
+ return editor;\r
+ }\r
+ \r
+ @Override\r
+ protected Object getValue(Object element) {\r
+ PropertyItem item = (PropertyItem)element;\r
+ PropertyManipulator manipulator = tab.getManipulator(item);//createManipulator(item, obj);\r
+ if (manipulator.getValueCount() <= index)\r
+ return null;\r
+ Object value = manipulator.getValue(index);\r
+ return value;\r
+ }\r
+ \r
+ @Override\r
+ protected void setValue(Object element, Object value) {\r
+ \r
+ PropertyItem item = (PropertyItem)element;\r
+ PropertyManipulator manipulator = tab.getManipulator(item);//createManipulator(item, obj);\r
+ if (manipulator.getValueCount() <= index)\r
+ throw new IllegalAccessError("Editing value in index " + index + " is not allowed.");\r
+ if (DEBUG)System.err.println("CELL SET VALUE: " + element + " " + value);\r
+ manipulator.setValue((String)value,index);\r
+ viewer.refresh(item);\r
+ nodeMap.commit();\r
+ \r
+ }\r
+ \r
+ \r
+\r
+ }\r
+ \r
+ private static class PropertyItemNameProvider extends CellLabelProvider {\r
+\r
+ \r
+ @Override\r
+ public void update(ViewerCell cell) {\r
+ PropertyItem item = (PropertyItem)cell.getElement();\r
+\r
+ if (item.name.length() > 0)\r
+ cell.setText(item.name);\r
+ else\r
+ cell.setText(item.id);\r
+ \r
+ \r
+ }\r
+ }\r
+ \r
+ private static class PropertyValueLabelProvider2 extends CellLabelProvider {\r
+ AnnotatedPropertyTab tab;\r
+ //private Object object;\r
+ \r
+ public PropertyValueLabelProvider2(AnnotatedPropertyTab tab) {\r
+ this.tab = tab;\r
+ }\r
+ \r
+ @Override\r
+ public void update(ViewerCell cell) {\r
+ PropertyItem item = (PropertyItem)cell.getElement();\r
+ int index = cell.getColumnIndex() -1;\r
+ PropertyManipulator manipulator = tab.getManipulator(item);//createManipulator(item, object);\r
+ if (manipulator.getValueCount() <= index)\r
+ return;\r
+ cell.setText(manipulator.getValue(index));\r
+ }\r
+ }\r
+ \r
+ private static class PropertyItemContentsProvider implements IStructuredContentProvider {\r
+ @SuppressWarnings("unchecked")\r
+ @Override\r
+ public Object[] getElements(Object inputElement) {\r
+ List<PropertyItem> items = (List<PropertyItem>)inputElement;\r
+ return items.toArray();\r
+ }\r
+ \r
+ @Override\r
+ public void dispose() {\r
+ \r
+ }\r
+ \r
+ @Override\r
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {\r
+ \r
+ }\r
+ }\r
+ \r
+ \r
+ \r
+ private static ViewerCell getNeighbor(ViewerCell currentCell,\r
+ int directionMask, boolean sameLevel) {\r
+ ViewerRow row;\r
+ if ((directionMask & ViewerCell.ABOVE) == ViewerCell.ABOVE) {\r
+ row = currentCell.getViewerRow().getNeighbor(ViewerRow.ABOVE,\r
+ sameLevel);\r
+ } else if ((directionMask & ViewerCell.BELOW) == ViewerCell.BELOW) {\r
+ row = currentCell.getViewerRow().getNeighbor(ViewerRow.BELOW,\r
+ sameLevel);\r
+ } else {\r
+ row = currentCell.getViewerRow();\r
+ }\r
+ if (row != null) {\r
+ int columnIndex;\r
+ columnIndex = getVisualIndex(row, currentCell.getColumnIndex());\r
+ int modifier = 0;\r
+ if ((directionMask & ViewerCell.LEFT) == ViewerCell.LEFT) {\r
+ modifier = -1;\r
+ } else if ((directionMask & ViewerCell.RIGHT) == ViewerCell.RIGHT) {\r
+ modifier = 1;\r
+ }\r
+ columnIndex += modifier;\r
+ if (columnIndex >= 0 && columnIndex < row.getColumnCount()) {\r
+ ViewerCell cell = getCellAtVisualIndex(row, columnIndex);\r
+ if (cell != null) {\r
+ while (cell != null\r
+ && columnIndex < row.getColumnCount() - 1\r
+ && columnIndex > 0) {\r
+ if (isVisible(cell)) {\r
+ break;\r
+ }\r
+ columnIndex += modifier;\r
+ cell = getCellAtVisualIndex(row, columnIndex);\r
+ if (cell == null) {\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ return cell;\r
+ }\r
+ }\r
+ return null;\r
+ }\r
+ \r
+ \r
+ \r
+ public static class TableViewerEditor extends ColumnViewerEditor {\r
+ /**\r
+ * This viewer's table editor.\r
+ */\r
+ private TableEditor tableEditor;\r
+ private TableViewerFocusCellManager focusCellManager;\r
+ private int feature;\r
+\r
+ /**\r
+ * @param viewer\r
+ * the viewer the editor is attached to\r
+ * @param focusCellManager\r
+ * the cell focus manager if one used or <code>null</code>\r
+ * @param editorActivationStrategy\r
+ * the strategy used to decide about the editor activation\r
+ * @param feature\r
+ * the feature mask\r
+ */\r
+ TableViewerEditor(TableViewer viewer,\r
+ TableViewerFocusCellManager focusCellManager,\r
+ ColumnViewerEditorActivationStrategy editorActivationStrategy,\r
+ int feature) {\r
+ super(viewer, editorActivationStrategy, feature);\r
+ this.feature = feature;\r
+ tableEditor = new TableEditor(viewer.getTable());\r
+ this.focusCellManager = focusCellManager;\r
+ }\r
+\r
+ /**\r
+ * Create a customized editor with focusable cells\r
+ * \r
+ * @param viewer\r
+ * the viewer the editor is created for\r
+ * @param focusCellManager\r
+ * the cell focus manager if one needed else\r
+ * <code>null</code>\r
+ * @param editorActivationStrategy\r
+ * activation strategy to control if an editor activated\r
+ * @param feature\r
+ * bit mask controlling the editor\r
+ * <ul>\r
+ * <li>{@link ColumnViewerEditor#DEFAULT}</li>\r
+ * <li>{@link ColumnViewerEditor#TABBING_CYCLE_IN_ROW}</li>\r
+ * <li>{@link ColumnViewerEditor#TABBING_HORIZONTAL}</li>\r
+ * <li>\r
+ * {@link ColumnViewerEditor#TABBING_MOVE_TO_ROW_NEIGHBOR}</li>\r
+ * <li>{@link ColumnViewerEditor#TABBING_VERTICAL}</li>\r
+ * </ul>\r
+ * @see #create(TableViewer, ColumnViewerEditorActivationStrategy, int)\r
+ */\r
+ public static void create(TableViewer viewer,\r
+ TableViewerFocusCellManager focusCellManager,\r
+ ColumnViewerEditorActivationStrategy editorActivationStrategy,\r
+ int feature) {\r
+ TableViewerEditor editor = new TableViewerEditor(viewer,\r
+ focusCellManager, editorActivationStrategy, feature);\r
+ viewer.setColumnViewerEditor(editor);\r
+ if (focusCellManager != null) {\r
+ try {\r
+ Method m = focusCellManager.getClass().getSuperclass()\r
+ .getDeclaredMethod("init", null);\r
+ m.setAccessible(true);\r
+ m.invoke(focusCellManager, null);\r
+ } catch (SecurityException e) {\r
+ e.printStackTrace();\r
+ } catch (IllegalArgumentException e) {\r
+ e.printStackTrace();\r
+ } catch (IllegalAccessException e) {\r
+ e.printStackTrace();\r
+ } catch (NoSuchMethodException e) {\r
+ e.printStackTrace();\r
+ } catch (InvocationTargetException e) {\r
+ e.printStackTrace();\r
+ }\r
+ // focusCellManager.init();\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Create a customized editor whose activation process is customized\r
+ * \r
+ * @param viewer\r
+ * the viewer the editor is created for\r
+ * @param editorActivationStrategy\r
+ * activation strategy to control if an editor activated\r
+ * @param feature\r
+ * bit mask controlling the editor\r
+ * <ul>\r
+ * <li>{@link ColumnViewerEditor#DEFAULT}</li>\r
+ * <li>{@link ColumnViewerEditor#TABBING_CYCLE_IN_ROW}</li>\r
+ * <li>{@link ColumnViewerEditor#TABBING_HORIZONTAL}</li>\r
+ * <li>\r
+ * {@link ColumnViewerEditor#TABBING_MOVE_TO_ROW_NEIGHBOR}</li>\r
+ * <li>{@link ColumnViewerEditor#TABBING_VERTICAL}</li>\r
+ * </ul>\r
+ */\r
+ public static void create(TableViewer viewer,\r
+ ColumnViewerEditorActivationStrategy editorActivationStrategy,\r
+ int feature) {\r
+ create(viewer, null, editorActivationStrategy, feature);\r
+ }\r
+\r
+ protected void setEditor(Control w, Item item, int columnNumber) {\r
+ tableEditor.setEditor(w, (TableItem) item, columnNumber);\r
+ }\r
+\r
+ protected void setLayoutData(LayoutData layoutData) {\r
+ tableEditor.grabHorizontal = layoutData.grabHorizontal;\r
+ tableEditor.horizontalAlignment = layoutData.horizontalAlignment;\r
+ tableEditor.minimumWidth = layoutData.minimumWidth;\r
+ }\r
+\r
+ public ViewerCell getFocusCell() {\r
+ if (focusCellManager != null) {\r
+ return focusCellManager.getFocusCell();\r
+ }\r
+ return super.getFocusCell();\r
+ }\r
+\r
+ protected void updateFocusCell(ViewerCell focusCell,\r
+ ColumnViewerEditorActivationEvent event) {\r
+ // Update the focus cell when we activated the editor with these 2\r
+ // events\r
+ if (event.eventType == ColumnViewerEditorActivationEvent.PROGRAMMATIC\r
+ || event.eventType == ColumnViewerEditorActivationEvent.TRAVERSAL) {\r
+ if (focusCellManager != null) {\r
+ try {\r
+ if (DEBUG)System.err.println("FOCUS CELL: " + focusCell);\r
+ \r
+ Method m = AbstractTableViewer.class.getDeclaredMethod(\r
+ "getSelectionFromWidget", null);\r
+ m.setAccessible(true);\r
+ List l = (List) m.invoke(getViewer(), null);\r
+ if (focusCellManager != null) {\r
+ m = focusCellManager\r
+ .getClass()\r
+ .getSuperclass()\r
+ .getDeclaredMethod("setFocusCell",\r
+ new Class[] { ViewerCell.class });\r
+ m.setAccessible(true);\r
+ m.invoke(focusCellManager,\r
+ new Object[] { focusCell });\r
+ }\r
+ if (!l.contains(focusCell.getElement())) {\r
+ getViewer().setSelection(\r
+ new StructuredSelection(focusCell\r
+ .getElement()));\r
+ }\r
+ } catch (SecurityException e) {\r
+ e.printStackTrace();\r
+ } catch (IllegalArgumentException e) {\r
+ e.printStackTrace();\r
+ } catch (IllegalAccessException e) {\r
+ e.printStackTrace();\r
+ } catch (NoSuchMethodException e) {\r
+ e.printStackTrace();\r
+ } catch (InvocationTargetException e) {\r
+ e.printStackTrace();\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ protected void processTraverseEvent(int columnIndex, ViewerRow row,\r
+ TraverseEvent event) {\r
+ ViewerCell cell2edit = null;\r
+ if (event.detail == SWT.TRAVERSE_TAB_PREVIOUS) {\r
+ event.doit = false;\r
+ if ((event.stateMask & SWT.CTRL) == SWT.CTRL\r
+ && (feature & TABBING_VERTICAL) == TABBING_VERTICAL) {\r
+ cell2edit = searchCellAboveBelow(row, getViewer(),\r
+ columnIndex, true);\r
+ } else if ((feature & TABBING_HORIZONTAL) == TABBING_HORIZONTAL) {\r
+ cell2edit = searchPreviousCell(row,\r
+ row.getCell(columnIndex), row.getCell(columnIndex),\r
+ getViewer());\r
+ }\r
+ } else if (event.detail == SWT.TRAVERSE_TAB_NEXT) {\r
+ event.doit = false;\r
+ if ((event.stateMask & SWT.CTRL) == SWT.CTRL\r
+ && (feature & TABBING_VERTICAL) == TABBING_VERTICAL) {\r
+ cell2edit = searchCellAboveBelow(row, getViewer(),\r
+ columnIndex, false);\r
+ } else if ((feature & TABBING_HORIZONTAL) == TABBING_HORIZONTAL) {\r
+ cell2edit = searchNextCell(row, row.getCell(columnIndex),\r
+ row.getCell(columnIndex), getViewer());\r
+ }\r
+ }\r
+ if (DEBUG) System.err.println("NEXT CELL: " + cell2edit);\r
+ if (cell2edit != null) {\r
+ getViewer().getControl().setRedraw(false);\r
+ ColumnViewerEditorActivationEvent acEvent = new ColumnViewerEditorActivationEvent(\r
+ cell2edit, event);\r
+ try {\r
+ Method m = ColumnViewer.class\r
+ .getDeclaredMethod(\r
+ "triggerEditorActivationEvent",\r
+ new Class[] { ColumnViewerEditorActivationEvent.class });\r
+ m.setAccessible(true);\r
+ m.invoke(getViewer(), new Object[] { acEvent });\r
+ } catch (SecurityException e) {\r
+ e.printStackTrace();\r
+ } catch (NoSuchMethodException e) {\r
+ e.printStackTrace();\r
+ } catch (IllegalArgumentException e) {\r
+ e.printStackTrace();\r
+ } catch (IllegalAccessException e) {\r
+ e.printStackTrace();\r
+ } catch (InvocationTargetException e) {\r
+ e.printStackTrace();\r
+ }\r
+ getViewer().getControl().setRedraw(true);\r
+ }\r
+ }\r
+\r
+ private ViewerCell searchCellAboveBelow(ViewerRow row,\r
+ ColumnViewer viewer, int columnIndex, boolean above) {\r
+ ViewerCell rv = null;\r
+ ViewerRow newRow = null;\r
+ if (above) {\r
+ newRow = row.getNeighbor(ViewerRow.ABOVE, false);\r
+ } else {\r
+ newRow = row.getNeighbor(ViewerRow.BELOW, false);\r
+ }\r
+ try {\r
+ if (newRow != null) {\r
+ Method m = ColumnViewer.class.getDeclaredMethod(\r
+ "getViewerColumn", new Class[] { int.class });\r
+ m.setAccessible(true);\r
+ ViewerColumn column = (ViewerColumn) m.invoke(viewer,\r
+ new Object[] { new Integer(columnIndex) });\r
+ m = ViewerColumn.class.getDeclaredMethod(\r
+ "getEditingSupport", null);\r
+ m.setAccessible(true);\r
+ EditingSupport es = (EditingSupport) m.invoke(column, null);\r
+ if (column != null && es != null) {\r
+ m = EditingSupport.class.getDeclaredMethod("canEdit",\r
+ new Class[] { Object.class });\r
+ m.setAccessible(true);\r
+ Boolean b = (Boolean) m.invoke(es,\r
+ new Object[] { newRow.getItem().getData() });\r
+ if (b.booleanValue()) {\r
+ rv = newRow.getCell(columnIndex);\r
+ }\r
+ } else {\r
+ rv = searchCellAboveBelow(newRow, viewer, columnIndex,\r
+ above);\r
+ }\r
+ }\r
+ } catch (Exception e) {\r
+ e.printStackTrace();\r
+ }\r
+ return rv;\r
+ }\r
+\r
+ private ViewerCell searchPreviousCell(ViewerRow row,\r
+ ViewerCell currentCell, ViewerCell originalCell,\r
+ ColumnViewer viewer) {\r
+ ViewerCell rv = null;\r
+ ViewerCell previousCell;\r
+ if (currentCell != null) {\r
+ previousCell = getNeighbor(currentCell, ViewerCell.LEFT, true);\r
+ } else {\r
+ if (row.getColumnCount() != 0) {\r
+ previousCell = row.getCell(getCreationIndex(row,\r
+ row.getColumnCount() - 1));\r
+ } else {\r
+ previousCell = row.getCell(0);\r
+ }\r
+ }\r
+ // No endless loop\r
+ if (originalCell.equals(previousCell)) {\r
+ return null;\r
+ }\r
+ if (previousCell != null) {\r
+ if (isCellEditable(viewer, previousCell)) {\r
+ rv = previousCell;\r
+ } else {\r
+ rv = searchPreviousCell(row, previousCell, originalCell,\r
+ viewer);\r
+ }\r
+ } else {\r
+ if ((feature & TABBING_CYCLE_IN_ROW) == TABBING_CYCLE_IN_ROW) {\r
+ rv = searchPreviousCell(row, null, originalCell, viewer);\r
+ } else if ((feature & TABBING_MOVE_TO_ROW_NEIGHBOR) == TABBING_MOVE_TO_ROW_NEIGHBOR) {\r
+ ViewerRow rowAbove = row\r
+ .getNeighbor(ViewerRow.ABOVE, false);\r
+ if (rowAbove != null) {\r
+ rv = searchPreviousCell(rowAbove, null, originalCell,\r
+ viewer);\r
+ }\r
+ }\r
+ }\r
+ return rv;\r
+ }\r
+\r
+ private ViewerCell searchNextCell(ViewerRow row,\r
+ ViewerCell currentCell, ViewerCell originalCell,\r
+ ColumnViewer viewer) {\r
+ ViewerCell rv = null;\r
+ ViewerCell nextCell;\r
+ if (currentCell != null) {\r
+ nextCell = getNeighbor(currentCell, ViewerCell.RIGHT, true);\r
+ } else {\r
+ nextCell = row.getCell(getCreationIndex(row, 0));\r
+ }\r
+ // No endless loop\r
+ if (originalCell.equals(nextCell)) {\r
+ return null;\r
+ }\r
+ if (nextCell != null) {\r
+ if (isCellEditable(viewer, nextCell)) {\r
+ rv = nextCell;\r
+ } else {\r
+ rv = searchNextCell(row, nextCell, originalCell, viewer);\r
+ }\r
+ } else {\r
+ if ((feature & TABBING_CYCLE_IN_ROW) == TABBING_CYCLE_IN_ROW) {\r
+ rv = searchNextCell(row, null, originalCell, viewer);\r
+ } else if ((feature & TABBING_MOVE_TO_ROW_NEIGHBOR) == TABBING_MOVE_TO_ROW_NEIGHBOR) {\r
+ ViewerRow rowBelow = row\r
+ .getNeighbor(ViewerRow.BELOW, false);\r
+ if (rowBelow != null) {\r
+ rv = searchNextCell(rowBelow, null, originalCell,\r
+ viewer);\r
+ }\r
+ }\r
+ }\r
+ return rv;\r
+ }\r
+\r
+ private boolean isCellEditable(ColumnViewer viewer, ViewerCell cell) {\r
+ try {\r
+ Method m = ColumnViewer.class.getDeclaredMethod(\r
+ "getViewerColumn", new Class[] { int.class });\r
+ m.setAccessible(true);\r
+ ViewerColumn column = (ViewerColumn) m.invoke(viewer,\r
+ new Object[] { new Integer(cell.getColumnIndex()) });\r
+ m = ViewerColumn.class.getDeclaredMethod("getEditingSupport",\r
+ null);\r
+ m.setAccessible(true);\r
+ EditingSupport es = (EditingSupport) m.invoke(column, null);\r
+ if (column != null && es != null) {\r
+ m = EditingSupport.class.getDeclaredMethod("canEdit",\r
+ new Class[] { Object.class });\r
+ m.setAccessible(true);\r
+ // return true;\r
+ Boolean b = (Boolean) m.invoke(es,\r
+ new Object[] { cell.getElement() });\r
+ return b.booleanValue();\r
+ }\r
+ } catch (Exception e) {\r
+ e.printStackTrace();\r
+ }\r
+ return false;\r
+ }\r
+ }\r
+ \r
+ // Reimplementation of ViewerCell-Methods\r
+ private static int getVisualIndex(ViewerRow row, int creationIndex) {\r
+ TableItem item = (TableItem) row.getItem();\r
+ int[] order = item.getParent().getColumnOrder();\r
+ for (int i = 0; i < order.length; i++) {\r
+ if (order[i] == creationIndex) {\r
+ return i;\r
+ }\r
+ }\r
+ return creationIndex;\r
+ }\r
+ \r
+ private static int getCreationIndex(ViewerRow row, int visualIndex) {\r
+ TableItem item = (TableItem) row.getItem();\r
+ if (item != null && !item.isDisposed() /*\r
+ * && hasColumns() &&\r
+ * isValidOrderIndex\r
+ * (visualIndex)\r
+ */) {\r
+ return item.getParent().getColumnOrder()[visualIndex];\r
+ }\r
+ return visualIndex;\r
+ }\r
+ \r
+ private static ViewerCell getCellAtVisualIndex(ViewerRow row,\r
+ int visualIndex) {\r
+ return getCell(row, getCreationIndex(row, visualIndex));\r
+ }\r
+\r
+ private static boolean isVisible(ViewerCell cell) {\r
+ return getWidth(cell) > 0;\r
+ }\r
+\r
+ private static int getWidth(ViewerCell cell) {\r
+ TableItem item = (TableItem) cell.getViewerRow().getItem();\r
+ return item.getParent().getColumn(cell.getColumnIndex()).getWidth();\r
+ }\r
+\r
+ private static ViewerCell getCell(ViewerRow row, int index) {\r
+ return row.getCell(index);\r
+ }\r
+ \r
+ \r
+}\r
--- /dev/null
+package org.simantics.g3d.property;\r
+\r
+\r
+public class BooleanPropertyManipulator implements PropertyManipulator {\r
+ \r
+ ValueProvider provider;\r
+ Object input;\r
+ \r
+ boolean editMode;\r
+ String editValue = null;\r
+ \r
+ public BooleanPropertyManipulator(ValueProvider provider, Object input) {\r
+ this.provider = provider;\r
+ this.input = input;\r
+ }\r
+ \r
+ @Override\r
+ public int getValueCount() {\r
+ return 1;\r
+ }\r
+ \r
+ @Override\r
+ public String getDescription(int i) {\r
+ if (i == 0)\r
+ return "Value";\r
+ return null;\r
+ }\r
+ \r
+ @Override\r
+ public String getValue(int i) {\r
+ if (editMode)\r
+ return editValue;\r
+ try {\r
+ return provider.getValue(input).toString();\r
+ } catch (Exception e) {\r
+ return null;\r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public String setValue(String value, int i) {\r
+ try {\r
+ editValue = value;\r
+ provider.setValue(input, Boolean.parseBoolean(value));\r
+ } catch (Exception e) {\r
+ return e.getMessage();\r
+ }\r
+ return null;\r
+ }\r
+ \r
+ @Override\r
+ public boolean getEditMode() {\r
+ return editMode;\r
+ }\r
+ \r
+ @Override\r
+ public void setEditMode(boolean b) {\r
+ editMode = b;\r
+ if (editMode) {\r
+ try {\r
+ editValue = provider.getValue(input).toString();\r
+ } catch (Exception e) {\r
+ \r
+ }\r
+ }\r
+ \r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.property;\r
+\r
+import java.lang.reflect.Method;\r
+\r
+import javax.vecmath.Quat4d;\r
+import javax.vecmath.Vector3d;\r
+\r
+public class DefaultPropertyManipulatorFactory implements PropertyManipulatorFactory {\r
+ \r
+ @Override\r
+ public Class<? extends PropertyManipulator> get(Method get, Object value) {\r
+ Class<?> returnValue = null;\r
+ if (get != null)\r
+ returnValue = get.getReturnType();\r
+ else\r
+ returnValue = value.getClass();\r
+ if (Double.class.equals(returnValue))\r
+ return DoublePropertyManipulator.class;\r
+ if (Vector3d.class.equals(returnValue))\r
+ return VectorPropertyManipulator.class;\r
+ if (Quat4d.class.equals(returnValue))\r
+ return QuatPropertyManipulator.class;\r
+ if (String.class.equals(returnValue))\r
+ return StringPropertyManipulator.class;\r
+ if (Integer.class.equals(returnValue))\r
+ return IntegerPropertyManipulator.class;\r
+ if (Boolean.class.equals(returnValue))\r
+ return BooleanPropertyManipulator.class;\r
+ if(double.class.equals(returnValue)) \r
+ return DoublePropertyManipulator.class;\r
+ if(int.class.equals(returnValue))\r
+ return IntegerPropertyManipulator.class;\r
+ if(boolean.class.equals(returnValue))\r
+ return BooleanPropertyManipulator.class;\r
+ throw new RuntimeException("Cannot handle value " + returnValue.getName() + " for method " + get);\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.property;\r
+\r
+import java.lang.reflect.Method;\r
+\r
+public class DoublePropertyManipulator implements PropertyManipulator {\r
+ \r
+ ValueProvider provider;\r
+ Object input;\r
+ \r
+ boolean editMode;\r
+ String editValue = null;\r
+ \r
+ public DoublePropertyManipulator(ValueProvider provider, Object input) {\r
+ this.provider = provider;\r
+ this.input = input;\r
+ }\r
+ \r
+ @Override\r
+ public int getValueCount() {\r
+ return 1;\r
+ }\r
+ \r
+ @Override\r
+ public String getDescription(int i) {\r
+ if (i == 0)\r
+ return "Value";\r
+ return null;\r
+ }\r
+ \r
+ @Override\r
+ public String getValue(int i) {\r
+ if (editMode)\r
+ return editValue;\r
+ try {\r
+ return provider.getValue(input).toString();\r
+ } catch (Exception e) {\r
+ return null;\r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public String setValue(String value, int i) {\r
+ try {\r
+ editValue = value;\r
+ provider.setValue(input, Double.parseDouble(value));\r
+ } catch (Exception e) {\r
+ return e.getMessage();\r
+ }\r
+ return null;\r
+ }\r
+\r
+ @Override\r
+ public boolean getEditMode() {\r
+ return editMode;\r
+ }\r
+ \r
+ @Override\r
+ public void setEditMode(boolean b) {\r
+ editMode = b;\r
+ if (editMode) {\r
+ try {\r
+ editValue = provider.getValue(input).toString();\r
+ } catch (Exception e) {\r
+ \r
+ }\r
+ }\r
+ \r
+ }\r
+}\r
--- /dev/null
+package org.simantics.g3d.property;\r
+\r
+\r
+public class IntegerPropertyManipulator implements PropertyManipulator {\r
+ \r
+ ValueProvider provider;\r
+ Object input;\r
+ \r
+ boolean editMode;\r
+ String editValue = null;\r
+ \r
+ public IntegerPropertyManipulator(ValueProvider provider, Object input) {\r
+ this.provider = provider;\r
+ this.input = input;\r
+ }\r
+ \r
+ @Override\r
+ public int getValueCount() {\r
+ return 1;\r
+ }\r
+ \r
+ @Override\r
+ public String getDescription(int i) {\r
+ if (i == 0)\r
+ return "Value";\r
+ return null;\r
+ }\r
+ \r
+ @Override\r
+ public String getValue(int i) {\r
+ if (editMode)\r
+ return editValue;\r
+ try {\r
+ return provider.getValue(input).toString();\r
+ } catch (Exception e) {\r
+ return null;\r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public String setValue(String value, int i) {\r
+ try {\r
+ editValue = value;\r
+ provider.setValue(input, Integer.parseInt(value));\r
+ } catch (Exception e) {\r
+ return e.getMessage();\r
+ }\r
+ return null;\r
+ }\r
+ \r
+ @Override\r
+ public boolean getEditMode() {\r
+ return editMode;\r
+ }\r
+ \r
+ @Override\r
+ public void setEditMode(boolean b) {\r
+ editMode = b;\r
+ if (editMode) {\r
+ try {\r
+ editValue = provider.getValue(input).toString();\r
+ } catch (Exception e) {\r
+ \r
+ }\r
+ }\r
+ \r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.property;\r
+\r
+import java.lang.reflect.Method;\r
+\r
+public class MethodValueProvider implements ValueProvider {\r
+\r
+ Method getter; \r
+ Method setter;\r
+ \r
+ public MethodValueProvider(Method getter, Method setter) {\r
+ this.getter = getter;\r
+ this.setter = setter;\r
+ }\r
+ \r
+ @Override\r
+ public Object getValue(Object obj) throws Exception{\r
+ return getter.invoke(obj);\r
+ }\r
+ @Override\r
+ public void setValue(Object obj, Object value) throws Exception {\r
+ setter.invoke(obj,value);\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.g3d.property;\r
+\r
+import java.lang.reflect.Method;\r
+import java.util.HashMap;\r
+import java.util.Map;\r
+\r
+public class MethodWithMapValueProvider implements ValueProvider {\r
+\r
+ Method getter; \r
+ Method setter;\r
+ String key;\r
+ \r
+ public MethodWithMapValueProvider(Method getter, Method setter, String key) {\r
+ this.getter = getter;\r
+ this.setter = setter;\r
+ this.key = key;\r
+ }\r
+ \r
+ @Override\r
+ public Object getValue(Object obj) throws Exception{\r
+ Map<String,Object> map = (Map<String, Object>)getter.invoke(obj);\r
+ return map.get(key);\r
+ }\r
+ @Override\r
+ public void setValue(Object obj, Object value) throws Exception {\r
+ Map<String,Object> map = new HashMap<String, Object>();\r
+ map.putAll((Map<String, Object>)getter.invoke(obj));\r
+ map.put(key, value);\r
+ setter.invoke(obj,map);\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.g3d.property;\r
+\r
+/**\r
+ * Interfaces for manipulating properties.\r
+ * \r
+ * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
+ *\r
+ */\r
+public interface PropertyManipulator {\r
+ \r
+ /**\r
+ * Returns number of individual values.\r
+ * @return\r
+ */\r
+ int getValueCount();\r
+ \r
+ /**\r
+ * Returns value at given index.\r
+ * @param i\r
+ * @return\r
+ */\r
+ String getValue(int i);\r
+ \r
+ /**\r
+ * Sets value at given index.\r
+ * @param i\r
+ * @return\r
+ */\r
+ String setValue(String value, int i);\r
+ \r
+ /**\r
+ * Returns description of a value at given index. The description is shown in the table header.\r
+ * @param i\r
+ * @return\r
+ */\r
+ String getDescription(int i);\r
+ \r
+ /**\r
+ * Gets edit mode status.\r
+ * @return\r
+ */\r
+ boolean getEditMode();\r
+ \r
+ /**\r
+ * Sets edit mode status.\r
+ * @param b\r
+ */\r
+ void setEditMode(boolean b);\r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.property;\r
+\r
+import java.lang.reflect.Method;\r
+\r
+public interface PropertyManipulatorFactory {\r
+ \r
+ public Class<? extends PropertyManipulator> get(Method get, Object value);\r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.property;\r
+\r
+public interface PropertyTabContributor extends org.simantics.selectionview.PropertyTabContributor{\r
+\r
+ public String getId();\r
+}\r
--- /dev/null
+package org.simantics.g3d.property;\r
+\r
+import java.util.List;\r
+\r
+\r
+public interface PropertyTabContributorFactory {\r
+\r
+ \r
+ public List<PropertyTabContributor> getContributors(Object input);\r
+}\r
--- /dev/null
+package org.simantics.g3d.property;\r
+\r
+import java.util.Collections;\r
+import java.util.List;\r
+\r
+import org.simantics.g3d.property.annotations.PropertyContributor;\r
+\r
+public class PropertyTabUtil {\r
+ \r
+ \r
+ @SuppressWarnings("unchecked")\r
+ public static List<PropertyTabContributor> getContributors(Object input) {\r
+ PropertyTabContributorFactory factory = resolveFactory(input.getClass());\r
+ if (factory == null)\r
+ return Collections.EMPTY_LIST;\r
+ return factory.getContributors(input);\r
+ }\r
+ \r
+ private static PropertyTabContributorFactory resolveFactory(Class<?> clazz) {\r
+ PropertyContributor contributor = clazz.getAnnotation(PropertyContributor.class);\r
+ if (contributor != null)\r
+ try {\r
+ return contributor.value().newInstance();\r
+ } catch (InstantiationException e) {\r
+ e.printStackTrace();\r
+ } catch (IllegalAccessException e) {\r
+ e.printStackTrace();\r
+ }\r
+ Class<?> superClass = clazz.getSuperclass();\r
+ if (superClass != null)\r
+ return resolveFactory(superClass);\r
+ return null;\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.property;\r
+\r
+import javax.vecmath.AxisAngle4d;\r
+import javax.vecmath.Quat4d;\r
+import javax.vecmath.Vector3d;\r
+\r
+import org.simantics.g3d.Activator;\r
+import org.simantics.g3d.math.EulerTools;\r
+import org.simantics.g3d.math.EulerTools.Order;\r
+import org.simantics.g3d.math.MathTools;\r
+import org.simantics.g3d.preferences.PreferenceConstants;\r
+\r
+public class QuatPropertyManipulator implements PropertyManipulator {\r
+ \r
+ ValueProvider provider;\r
+ protected Object input;\r
+ \r
+ enum EditType {QUATERNION,AXIS_ANGLE,EULER};\r
+ \r
+ EditType type = EditType.QUATERNION;\r
+ Order order;\r
+ \r
+ boolean editMode;\r
+ Object editValue = null;\r
+ \r
+ public QuatPropertyManipulator(ValueProvider provider, Object input) {\r
+ this.provider = provider;\r
+ this.input = input;\r
+ \r
+ String set = Activator.getDefault().getPreferenceStore().getString(PreferenceConstants.ORIENTATION_PRESENTATION);\r
+ if ("quat".equals(set)) {\r
+ type = EditType.QUATERNION;\r
+ } else if ("aa".equals(set)) {\r
+ type = EditType.AXIS_ANGLE;\r
+ } else if ("euler".equals(set)) {\r
+ type = EditType.EULER;\r
+ String eulerOrder = Activator.getDefault().getPreferenceStore().getString(PreferenceConstants.EULER_ANGLE_ORDER);\r
+ order = Order.valueOf(eulerOrder);\r
+ if (order == null)\r
+ order = Order.YXZ;\r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public String getDescription(int i) {\r
+ switch (type) {\r
+ case QUATERNION:\r
+ if (i == 0)\r
+ return "X";\r
+ if (i == 1)\r
+ return "Y";\r
+ if (i == 2)\r
+ return "Z";\r
+ if (i == 3)\r
+ return "W";\r
+ break;\r
+ case AXIS_ANGLE:\r
+ if (i == 0)\r
+ return "X";\r
+ if (i == 1)\r
+ return "Y";\r
+ if (i == 2)\r
+ return "Z";\r
+ if (i == 3)\r
+ return "Angle";\r
+ break;\r
+ case EULER:\r
+ if (i > 3)\r
+ return null;\r
+ return order.toString().substring(i, i+1);\r
+ default:\r
+ break;\r
+ }\r
+ return null;\r
+ }\r
+ \r
+ @Override\r
+ public int getValueCount() {\r
+ switch (type) {\r
+ case QUATERNION:\r
+ return 4;\r
+ case AXIS_ANGLE:\r
+ return 4;\r
+ case EULER:\r
+ return 3;\r
+ default:\r
+ break;\r
+ }\r
+ return 0;\r
+ }\r
+ \r
+ @Override\r
+ public String getValue(int i) {\r
+ try {\r
+ Quat4d q = (Quat4d) provider.getValue(input);\r
+ double d = 0;\r
+ switch (type) {\r
+ case QUATERNION:\r
+ if (editMode)\r
+ q = (Quat4d)editValue;\r
+ else\r
+ q = new Quat4d(q);\r
+ \r
+ if (i == 0)\r
+ d = q.x;\r
+ if (i == 1)\r
+ d = q.y;\r
+ if (i == 2)\r
+ d = q.z;\r
+ if (i == 3)\r
+ d = q.w;\r
+ break;\r
+ \r
+ case AXIS_ANGLE: {\r
+ AxisAngle4d aa;\r
+ if (editMode)\r
+ aa = (AxisAngle4d)editValue;\r
+ else {\r
+ aa = new AxisAngle4d();\r
+ aa.set(q);\r
+ }\r
+ if (i == 0)\r
+ d = aa.x;\r
+ if (i == 1)\r
+ d = aa.y;\r
+ if (i == 2)\r
+ d = aa.z;\r
+ if (i == 3)\r
+ d = MathTools.radToDeg(aa.angle);\r
+ break;\r
+ }\r
+ case EULER: {\r
+ Vector3d aa;\r
+ if (editMode)\r
+ aa = (Vector3d)editValue;\r
+ else\r
+ aa = EulerTools.getEulerFromQuat(order, q);//MathTools.getEuler(q);\r
+ if (i == 0)\r
+ d = aa.x;\r
+ if (i == 1)\r
+ d = aa.y;\r
+ if (i == 2)\r
+ d = aa.z;\r
+ d = MathTools.radToDeg(d);\r
+ }\r
+\r
+ default:\r
+ break;\r
+ }\r
+ return Double.toString(d);\r
+ } catch (Exception e) {\r
+ return null;\r
+ }\r
+ }\r
+ \r
+ \r
+ \r
+ @Override\r
+ public String setValue(String value, int i) {\r
+ try {\r
+ Double d = Double.parseDouble(value);\r
+ Quat4d q = (Quat4d) provider.getValue(input);\r
+ switch (type) {\r
+ case QUATERNION:\r
+ if (editMode)\r
+ q = (Quat4d)editValue;\r
+ else\r
+ q = new Quat4d(q);\r
+ \r
+ if (i == 0)\r
+ q.x = d;\r
+ if (i == 1)\r
+ q.y = d;\r
+ if (i == 2)\r
+ q.z = d;\r
+ if (i == 3)\r
+ q.w = d;\r
+ break;\r
+ case AXIS_ANGLE: {\r
+ AxisAngle4d aa;\r
+ if (editMode)\r
+ aa = (AxisAngle4d) editValue;\r
+ else {\r
+ aa = new AxisAngle4d();\r
+ aa.set(q);\r
+ }\r
+ if (i == 0)\r
+ aa.x = d;\r
+ if (i == 1)\r
+ aa.y = d;\r
+ if (i == 2)\r
+ aa.z = d;\r
+ if (i == 3)\r
+ aa.angle = MathTools.degToRad(d);\r
+ q = new Quat4d();\r
+ MathTools.getQuat(aa,q);\r
+ break;\r
+ }\r
+ case EULER: {\r
+ Vector3d e;\r
+ if (editMode)\r
+ e = (Vector3d)editValue;\r
+ else \r
+ e = EulerTools.getEulerFromQuat(order, q);//MathTools.getEuler(q);\r
+ d = MathTools.degToRad(d);\r
+ if (i == 0)\r
+ e.x = d;\r
+ if (i == 1)\r
+ e.y = d;\r
+ if (i == 2)\r
+ e.z = d;\r
+ q = EulerTools.getQuatFromEuler(order, e);//MathTools.getQuat(e);\r
+ }\r
+ default:\r
+ break;\r
+ }\r
+ q.normalize();\r
+ setValue(q);\r
+ } catch (Exception e) {\r
+ return e.getMessage();\r
+ }\r
+ return null;\r
+ }\r
+ \r
+ protected void setValue(Quat4d q) throws Exception {\r
+ provider.setValue(input, q);\r
+ }\r
+ \r
+ private void storeEditValue() {\r
+ try {\r
+ Quat4d q = (Quat4d) provider.getValue(input);\r
+ switch (type) {\r
+ case QUATERNION:\r
+ editValue = q;\r
+ break;\r
+ case AXIS_ANGLE:\r
+ AxisAngle4d aa = new AxisAngle4d();\r
+ aa.set(q);\r
+ editValue = aa;\r
+ break;\r
+ case EULER:\r
+ Vector3d e = EulerTools.getEulerFromQuat(order, q);\r
+ editValue = e;\r
+ break;\r
+ }\r
+ } catch (Exception e) {\r
+ \r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public boolean getEditMode() {\r
+ return editMode;\r
+ }\r
+ \r
+ @Override\r
+ public void setEditMode(boolean b) {\r
+ editMode = b;\r
+ if (editMode) {\r
+ storeEditValue();\r
+ }\r
+ \r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.property;\r
+\r
+import java.lang.reflect.Method;\r
+\r
+public class StringPropertyManipulator implements PropertyManipulator {\r
+ \r
+ ValueProvider provider;\r
+ Object input;\r
+ \r
+ boolean editMode;\r
+ String editValue = null;\r
+ \r
+ public StringPropertyManipulator(ValueProvider provider, Object input) {\r
+ this.provider = provider;\r
+ this.input = input;\r
+ }\r
+ \r
+ @Override\r
+ public int getValueCount() {\r
+ return 1;\r
+ }\r
+ \r
+ @Override\r
+ public String getDescription(int i) {\r
+ if (i == 0)\r
+ return "Value";\r
+ return null;\r
+ }\r
+ \r
+ @Override\r
+ public String getValue(int i) {\r
+ if (editMode)\r
+ return editValue;\r
+ try {\r
+ return provider.getValue(input).toString();\r
+ } catch (Exception e) {\r
+ return null;\r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public String setValue(String value, int i) {\r
+ try {\r
+ editValue = value;\r
+ provider.setValue(input, value);\r
+ } catch (Exception e) {\r
+ return e.getMessage();\r
+ }\r
+ return null;\r
+ }\r
+\r
+ @Override\r
+ public boolean getEditMode() {\r
+ return editMode;\r
+ }\r
+ \r
+ @Override\r
+ public void setEditMode(boolean b) {\r
+ editMode = b;\r
+ if (editMode) {\r
+ try {\r
+ editValue = provider.getValue(input).toString();\r
+ } catch (Exception e) {\r
+ \r
+ }\r
+ }\r
+ \r
+ }\r
+}\r
--- /dev/null
+package org.simantics.g3d.property;\r
+\r
+public interface ValueProvider {\r
+ \r
+ \r
+ Object getValue(Object obj) throws Exception;\r
+ void setValue(Object obj, Object value) throws Exception;\r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.property;\r
+\r
+import java.lang.reflect.InvocationTargetException;\r
+import java.lang.reflect.Method;\r
+\r
+import javax.vecmath.Vector3d;\r
+\r
+public class VectorPropertyManipulator implements PropertyManipulator {\r
+ \r
+ ValueProvider provider;\r
+ protected Object input;\r
+ \r
+ boolean editMode;\r
+ Vector3d editValue = null;\r
+ \r
+ public VectorPropertyManipulator(ValueProvider provider, Object input) {\r
+ this.provider = provider;\r
+ this.input = input;\r
+ }\r
+ \r
+ @Override\r
+ public int getValueCount() {\r
+ return 3;\r
+ }\r
+ \r
+ @Override\r
+ public String getDescription(int i) {\r
+ if (i == 0)\r
+ return "X";\r
+ if (i == 1)\r
+ return "Y";\r
+ if (i == 2)\r
+ return "Z";\r
+ return null;\r
+ }\r
+ \r
+ @Override\r
+ public String getValue(int i) {\r
+ try {\r
+ Vector3d v = _getValue();\r
+ if (v == null)\r
+ return null;\r
+ if (i == 0)\r
+ return Double.toString(v.x);\r
+ if (i == 1)\r
+ return Double.toString(v.y);\r
+ if (i == 2)\r
+ return Double.toString(v.z);\r
+ return null;\r
+ } catch (Exception e) {\r
+ return null;\r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public String setValue(String value, int i) {\r
+ try {\r
+ Double d = Double.parseDouble(value);\r
+ Vector3d v = _getValue();\r
+ v = new Vector3d(v.x, v.y, v.z);\r
+ if (i == 0)\r
+ v.x = d;\r
+ if (i == 1)\r
+ v.y = d;\r
+ if (i == 2)\r
+ v.z = d;\r
+ editValue = v;\r
+ setValue(v);\r
+ } catch (Exception e) {\r
+ return e.getMessage();\r
+ }\r
+ return null;\r
+ }\r
+ \r
+ protected void setValue(Vector3d v) throws Exception {\r
+ provider.setValue(input, v);\r
+ }\r
+ \r
+ private Vector3d _getValue() throws Exception{\r
+ if (editMode)\r
+ return editValue;\r
+ return (Vector3d) provider.getValue(input);\r
+ }\r
+ \r
+ @Override\r
+ public boolean getEditMode() {\r
+ return editMode;\r
+ }\r
+ \r
+ @Override\r
+ public void setEditMode(boolean b) {\r
+ editMode = b;\r
+ if (editMode) {\r
+ try {\r
+ editValue = (Vector3d) provider.getValue(input);\r
+ } catch (Exception e) {\r
+ \r
+ }\r
+ }\r
+ \r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.property.annotations;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+import org.simantics.g3d.property.DefaultPropertyManipulatorFactory;\r
+import org.simantics.g3d.property.PropertyManipulatorFactory;\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.METHOD)\r
+public @interface CompoundGetPropertyValue {\r
+ String value();\r
+ String name() default "";\r
+ String tabId() default "Default";\r
+ Class<? extends PropertyManipulatorFactory> manipulator() default DefaultPropertyManipulatorFactory.class; \r
+}\r
--- /dev/null
+package org.simantics.g3d.property.annotations;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.METHOD) \r
+public @interface CompoundSetPropertyValue {\r
+ String value();\r
+}\r
--- /dev/null
+package org.simantics.g3d.property.annotations;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+import org.simantics.g3d.property.DefaultPropertyManipulatorFactory;\r
+import org.simantics.g3d.property.PropertyManipulatorFactory;\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.METHOD)\r
+public @interface GetPropertyValue {\r
+ String value();\r
+ String name() default "";\r
+ String tabId() default "Default";\r
+ Class<? extends PropertyManipulatorFactory> manipulator() default DefaultPropertyManipulatorFactory.class; \r
+}\r
--- /dev/null
+package org.simantics.g3d.property.annotations;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+import org.simantics.g3d.property.AnnotatedPropertyTabContributorFactory;\r
+import org.simantics.g3d.property.PropertyTabContributorFactory;\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.TYPE) \r
+public @interface PropertyContributor {\r
+ Class<? extends PropertyTabContributorFactory> value() default AnnotatedPropertyTabContributorFactory.class;\r
+}\r
--- /dev/null
+package org.simantics.g3d.property.annotations;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.TYPE) \r
+public @interface PropertyTabBlacklist {\r
+ String value() default "";\r
+}\r
--- /dev/null
+package org.simantics.g3d.property.annotations;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.METHOD) \r
+public @interface SetPropertyValue {\r
+ String value();\r
+}\r
--- /dev/null
+package org.simantics.g3d.scenegraph;\r
+\r
+import javax.vecmath.Quat4d;\r
+import javax.vecmath.Vector3d;\r
+\r
+import org.simantics.g3d.ontology.G3D;\r
+import org.simantics.g3d.property.annotations.GetPropertyValue;\r
+import org.simantics.g3d.property.annotations.PropertyContributor;\r
+import org.simantics.g3d.property.annotations.SetPropertyValue;\r
+import org.simantics.g3d.scenegraph.base.INode;\r
+import org.simantics.g3d.scenegraph.base.Node;\r
+import org.simantics.g3d.tools.NodeTools;\r
+import org.simantics.objmap.graph.annotations.RelatedGetValue;\r
+import org.simantics.objmap.graph.annotations.RelatedSetValue;\r
+\r
+\r
+@PropertyContributor\r
+public class G3DNode extends Node implements IG3DNode {\r
+ \r
+ private Vector3d position = new Vector3d();\r
+ private Quat4d orientation = new Quat4d(0,0,0,1);\r
+ \r
+ @Override\r
+ @GetPropertyValue(value = G3D.URIs.hasOrientation, tabId = "Transform", name = "Orientation")\r
+ public Quat4d getOrientation() {\r
+ return orientation;\r
+ }\r
+ \r
+ @RelatedGetValue(G3D.URIs.hasOrientation)\r
+ public double[] getOrientationArr() {\r
+ double arr[] = new double[4];\r
+ orientation.get(arr);\r
+ return arr;\r
+ \r
+ }\r
+ \r
+ @Override\r
+ @GetPropertyValue(value = G3D.URIs.hasPosition, tabId = "Transform", name = "Position")\r
+ public Vector3d getPosition() {\r
+ return position;\r
+ }\r
+ \r
+ @RelatedGetValue(G3D.URIs.hasPosition)\r
+ public double[] getPositionArr() {\r
+ double arr[] = new double[3];\r
+ position.get(arr);\r
+ return arr;\r
+ }\r
+ \r
+ @Override\r
+ @SetPropertyValue(G3D.URIs.hasOrientation)\r
+ public void setOrientation(Quat4d orientation) {\r
+ assert(orientation != null);\r
+ this.orientation = orientation;\r
+ \r
+ firePropertyChanged(G3D.URIs.hasOrientation);\r
+ }\r
+ \r
+ @RelatedSetValue(G3D.URIs.hasOrientation)\r
+ public void setOrientation(double[] arr) {\r
+ if (arr == null)\r
+ return;\r
+ setOrientation(new Quat4d(arr));\r
+ }\r
+ \r
+ @Override\r
+ @SetPropertyValue(G3D.URIs.hasPosition)\r
+ public void setPosition(Vector3d position) {\r
+ assert(position != null);\r
+ this.position = position;\r
+ \r
+ firePropertyChanged(G3D.URIs.hasPosition);\r
+ }\r
+ \r
+ @RelatedSetValue(G3D.URIs.hasPosition)\r
+ public void setPosition(double[] arr) {\r
+ if (arr == null)\r
+ return;\r
+ setPosition(new Vector3d(arr));\r
+ }\r
+ \r
+ @Override\r
+ @GetPropertyValue(value = G3D.URIs.hasWorldPosition, tabId = "Transform", name = "World Position")\r
+ public Vector3d getWorldPosition() {\r
+ IG3DNode parent = (IG3DNode)getParent();\r
+ if (parent == null)\r
+ return position;\r
+ return NodeTools.getWorldPosition(parent, new Vector3d(position));\r
+ }\r
+ \r
+ \r
+ public Vector3d getWorldPosition(Vector3d localPosition) {\r
+ return NodeTools.getWorldPosition(this,localPosition);\r
+ }\r
+\r
+ \r
+ @Override\r
+ @GetPropertyValue(value = G3D.URIs.hasWorldOrientation, tabId = "Transform", name = "World Orientation")\r
+ public Quat4d getWorldOrientation() {\r
+ return getWorldOrientation(new Quat4d(orientation));\r
+ }\r
+ \r
+ public Quat4d getWorldOrientation(Quat4d localOrientation) {\r
+ IG3DNode parent = (IG3DNode)getParent();\r
+ if (parent == null)\r
+ return localOrientation;\r
+ return NodeTools.getWorldOrientation(parent, localOrientation);\r
+ }\r
+ \r
+ @Override\r
+ public Vector3d getLocalPosition(Vector3d worldPosition) {\r
+ IG3DNode parent = (IG3DNode)getParent();\r
+ if (parent == null)\r
+ return worldPosition;\r
+ return NodeTools.getLocalPosition(parent,new Vector3d(worldPosition));\r
+ }\r
+ \r
+ @Override\r
+ public Quat4d getLocalOrientation(Quat4d worldOrientation) {\r
+ IG3DNode parent = (IG3DNode)getParent();\r
+ if (parent == null)\r
+ return worldOrientation;\r
+ return NodeTools.getLocalOrientation(parent, new Quat4d(worldOrientation));\r
+ }\r
+ \r
+ @Override\r
+ @SetPropertyValue(G3D.URIs.hasWorldPosition)\r
+ public void setWorldPosition(Vector3d position) {\r
+ Vector3d localPos = getLocalPosition(position);\r
+ setPosition(localPos);\r
+ }\r
+ \r
+ @Override\r
+ @SetPropertyValue(G3D.URIs.hasWorldOrientation)\r
+ public void setWorldOrientation(Quat4d orientation) {\r
+ Quat4d localOr = getLocalOrientation(orientation);\r
+ setOrientation(localOr);\r
+ }\r
+ \r
+ @Override\r
+ public Object getAdapter(Class adapter) {\r
+ if (INode.class == adapter)\r
+ return this;\r
+ if (IG3DNode.class == adapter)\r
+ return this;\r
+ return null;\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.scenegraph;\r
+\r
+import javax.vecmath.Quat4d;\r
+import javax.vecmath.Vector3d;\r
+\r
+import org.simantics.g3d.math.MathTools;\r
+import org.simantics.g3d.ontology.G3D;\r
+import org.simantics.g3d.property.annotations.GetPropertyValue;\r
+import org.simantics.g3d.property.annotations.SetPropertyValue;\r
+import org.simantics.g3d.scenegraph.base.ParentNode;\r
+import org.simantics.g3d.tools.NodeTools;\r
+import org.simantics.objmap.graph.annotations.RelatedGetValue;\r
+import org.simantics.objmap.graph.annotations.RelatedSetValue;\r
+\r
+\r
+public class G3DparentNode<T extends IG3DNode> extends ParentNode<T> implements IG3DNode{\r
+ private Vector3d position = new Vector3d();\r
+ private Quat4d orientation = MathTools.getIdentityQuat();\r
+ \r
+ \r
+ @Override\r
+ @GetPropertyValue(value = G3D.URIs.hasOrientation, tabId = "Transform", name = "Orientation")\r
+ public Quat4d getOrientation() {\r
+ return orientation;\r
+ }\r
+ \r
+ @RelatedGetValue(G3D.URIs.hasOrientation)\r
+ public double[] getOrientationArr() {\r
+ double arr[] = new double[4];\r
+ orientation.get(arr);\r
+ return arr;\r
+ \r
+ }\r
+ \r
+ @Override\r
+ @GetPropertyValue(value = G3D.URIs.hasPosition, tabId = "Transform", name = "Position")\r
+ public Vector3d getPosition() {\r
+ return position;\r
+ }\r
+ \r
+ @RelatedGetValue(G3D.URIs.hasPosition)\r
+ public double[] getPositionArr() {\r
+ double arr[] = new double[3];\r
+ position.get(arr);\r
+ return arr;\r
+ }\r
+ \r
+ @Override\r
+ @SetPropertyValue(G3D.URIs.hasOrientation)\r
+ public void setOrientation(Quat4d orientation) {\r
+ assert(orientation != null);\r
+ this.orientation = orientation;\r
+ }\r
+ \r
+ @Override\r
+ @SetPropertyValue(G3D.URIs.hasPosition)\r
+ public void setPosition(Vector3d position) {\r
+ assert(position != null);\r
+ this.position = position;\r
+ }\r
+ \r
+ @RelatedSetValue(G3D.URIs.hasOrientation)\r
+ public void setOrientation(double[] arr) {\r
+ if (arr == null)\r
+ return;\r
+ setOrientation(new Quat4d(arr));\r
+ }\r
+ \r
+ @RelatedSetValue(G3D.URIs.hasPosition)\r
+ public void setPosition(double[] arr) {\r
+ if (arr == null)\r
+ return;\r
+ setPosition(new Vector3d(arr));\r
+ }\r
+ \r
+ @Override\r
+ @GetPropertyValue(value = G3D.URIs.hasWorldPosition, tabId = "Transform", name = "World Position")\r
+ public Vector3d getWorldPosition() {\r
+ IG3DNode parent = (IG3DNode)getParent();\r
+ if (parent == null)\r
+ return position;\r
+ return NodeTools.getWorldPosition(parent, new Vector3d(position));\r
+ }\r
+ \r
+ \r
+ public Vector3d getWorldPosition(Vector3d localPosition) {\r
+ return NodeTools.getWorldPosition(this,localPosition);\r
+ }\r
+\r
+ \r
+ @Override\r
+ @GetPropertyValue(value = G3D.URIs.hasWorldOrientation, tabId = "Transform", name = "World Orientation")\r
+ public Quat4d getWorldOrientation() {\r
+ return getWorldOrientation(new Quat4d(orientation));\r
+ }\r
+ \r
+ public Quat4d getWorldOrientation(Quat4d localOrientation) {\r
+ IG3DNode parent = (IG3DNode)getParent();\r
+ if (parent == null)\r
+ return localOrientation;\r
+ return NodeTools.getWorldOrientation(parent, localOrientation);\r
+ }\r
+ \r
+ @Override\r
+ public Vector3d getLocalPosition(Vector3d worldPosition) {\r
+ IG3DNode parent = (IG3DNode)getParent();\r
+ if (parent == null)\r
+ return worldPosition;\r
+ return NodeTools.getLocalPosition(parent,new Vector3d(worldPosition));\r
+ }\r
+ \r
+ @Override\r
+ public Quat4d getLocalOrientation(Quat4d worldOrientation) {\r
+ IG3DNode parent = (IG3DNode)getParent();\r
+ if (parent == null)\r
+ return worldOrientation;\r
+ return NodeTools.getLocalOrientation(parent, new Quat4d(worldOrientation));\r
+ }\r
+ \r
+ @Override\r
+ @SetPropertyValue(G3D.URIs.hasWorldPosition)\r
+ public void setWorldPosition(Vector3d position) {\r
+ Vector3d localPos = getLocalPosition(position);\r
+ setPosition(localPos);\r
+ }\r
+ \r
+ @Override\r
+ @SetPropertyValue(G3D.URIs.hasWorldOrientation)\r
+ public void setWorldOrientation(Quat4d orientation) {\r
+ Quat4d localOr = getLocalOrientation(orientation);\r
+ setOrientation(localOr);\r
+ }\r
+ \r
+ @Override\r
+ public Object getAdapter(Class adapter) {\r
+ return null;\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.g3d.scenegraph;\r
+\r
+import javax.vecmath.Quat4d;\r
+import javax.vecmath.Vector3d;\r
+\r
+import org.eclipse.core.runtime.IAdaptable;\r
+import org.simantics.g3d.scenegraph.base.INode;\r
+\r
+\r
+public interface IG3DNode extends INode, IAdaptable {\r
+\r
+ \r
+ \r
+ public Vector3d getPosition();\r
+ public void setPosition(Vector3d position);\r
+ \r
+ public Quat4d getOrientation();\r
+ public void setOrientation(Quat4d orientation);\r
+ \r
+ public Vector3d getWorldPosition();\r
+ public Quat4d getWorldOrientation();\r
+ \r
+ public Vector3d getWorldPosition(Vector3d localPosition);\r
+ public Quat4d getWorldOrientation(Quat4d localOrientation);\r
+ \r
+ \r
+ public Vector3d getLocalPosition(Vector3d worldPosition);\r
+ public Quat4d getLocalOrientation(Quat4d worldOrientation);\r
+ \r
+ public void setWorldPosition(Vector3d position);\r
+ public void setWorldOrientation(Quat4d orientation);\r
+ \r
+ \r
+ \r
+}\r
--- /dev/null
+package org.simantics.g3d.scenegraph;\r
+\r
+\r
+public interface NodeHighlighter {\r
+ \r
+ public static enum HighlightObjectType{Actor, Node};\r
+ public static enum HighlightEventType{Selection, Hover, ClearSelection, ClearHover};\r
+\r
+ public void highlight(HighlightEventType type);\r
+}\r
--- /dev/null
+package org.simantics.g3d.scenegraph;\r
+\r
+import java.util.Collection;\r
+\r
+import org.simantics.g3d.scenegraph.base.INode;\r
+import org.simantics.g3d.scenegraph.base.NodeListener;\r
+import org.simantics.g3d.scenegraph.base.ParentNode;\r
+\r
+public interface NodeMap<T> {\r
+\r
+ public Collection<T> getRenderObjects(INode node);\r
+ \r
+ public void updateRenderObjectsFor(INode node);\r
+ \r
+ public INode getNode(T t);\r
+ \r
+ public ParentNode<IG3DNode> getRootNode();\r
+ \r
+ /**\r
+ * Commit changes to the database.\r
+ */\r
+ public void commit();\r
+ \r
+ \r
+ /**\r
+ * Deletes (Disposes) the map. \r
+ */\r
+ public void delete();\r
+ \r
+ \r
+ /**\r
+ * Track changes that are going to be committed into the database.\r
+ * \r
+ * Disabling change tracking causes commit() to do nothing. \r
+ * @param enabled\r
+ */\r
+ public void setChangeTracking(boolean enabled);\r
+ public boolean isChangeTracking();\r
+ \r
+ \r
+ /**\r
+ * Add listener for all scene-graph events.\r
+ * @param listener\r
+ */\r
+ public void addListener(NodeListener listener);\r
+ \r
+ public void removeListener(NodeListener listener);\r
+}\r
--- /dev/null
+package org.simantics.g3d.scenegraph;\r
+\r
+public interface NodeMapProvider<T> {\r
+\r
+ public NodeMap<T> getNodeMap();\r
+}\r
--- /dev/null
+package org.simantics.g3d.scenegraph;\r
+\r
+public interface RenderListener {\r
+ public void preRender();\r
+ public void postRender();\r
+}\r
--- /dev/null
+package org.simantics.g3d.scenegraph.base;\r
+\r
+import java.util.List;\r
+\r
+\r
+\r
+\r
+\r
+public interface INode {\r
+ \r
+ /**\r
+ * \r
+ * @return unique node identifier\r
+ */\r
+ public Long getId();\r
+\r
+ /**\r
+ * @return root node of the scene graph or <code>null</code> if this node is\r
+ * not part of a properly rooted scene graph hierarchy\r
+ */\r
+ public ParentNode<?> getRootNode();\r
+\r
+ /**\r
+ * @return Parent node reference or <code>null</code> if not set\r
+ */\r
+ public ParentNode<?> getParent();\r
+ \r
+ public String getParentRel();\r
+ /**\r
+ * Set parent node. This method is for scene graph internal use only and\r
+ * should not be called outside the scene graph structure. This method\r
+ * simply sets the parent node parent field, and does not affect on parent\r
+ * node (i.e., should be called only from parent node).\r
+ */\r
+ public void setParent(ParentNode<?> parent, String name);\r
+\r
+ /**\r
+ * Perform cleanup for this node and for the child nodes. Any resources\r
+ * (including child nodes) related to this node are unusable after this\r
+ * operation. This method is for scene graph internal use only, thus should\r
+ * not be called outside the scene graph structure.\r
+ */\r
+ public void cleanup();\r
+ /**\r
+ * Remove this node and its children from the scene graph.\r
+ */\r
+ public void remove();\r
+\r
+ \r
+ public void addListener(NodeListener listener);\r
+ public void removeListener(NodeListener listener);\r
+ \r
+ public List<NodeListener> getListeners();\r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.scenegraph.base;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+\r
+public abstract class Node implements INode {\r
+ public transient static long IDCOUNTER = 1;\r
+ protected transient ParentNode<?> parent = null;\r
+ protected transient String parentName = null; \r
+ protected Long id = IDCOUNTER++;\r
+ \r
+\r
+ public Long getId() {\r
+ return id;\r
+ }\r
+\r
+\r
+ public ParentNode<?> getParent() {\r
+ return parent;\r
+ }\r
+\r
+ \r
+ @Override\r
+ public String getParentRel() {\r
+ return parentName;\r
+ }\r
+ \r
+ public void setParent(ParentNode<?> parent, String name) {\r
+ this.parent = parent;\r
+ this.parentName = name;\r
+ }\r
+ \r
+ public ParentNode<?> getRootNode() {\r
+ return parent != null ? parent.getRootNode() : null;\r
+ }\r
+ \r
+ public void remove() {\r
+ if (parent != null) {\r
+ parent.removeNode(parentName, this);\r
+ }\r
+ }\r
+ \r
+ public void deattach() {\r
+ if (parent != null) {\r
+ parent.deattachNode(parentName, this);\r
+ }\r
+ }\r
+ \r
+ public void init() {\r
+ }\r
+ \r
+ public void cleanup() {\r
+ if (parent != null) {\r
+ parent.removeNode(parentName, this);\r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public String toString() {\r
+ return getClass().getSimpleName();\r
+ }\r
+ \r
+ protected List<NodeListener> listeners = new ArrayList<NodeListener>();\r
+ \r
+ @Override\r
+ public void addListener(NodeListener listener) {\r
+ if (!listeners.contains(listener))\r
+ listeners.add(listener);\r
+ }\r
+ \r
+ @Override\r
+ public void removeListener(NodeListener listener) {\r
+ listeners.remove(listener);\r
+ }\r
+ \r
+ @Override\r
+ public List<NodeListener> getListeners() {\r
+ return listeners;\r
+ }\r
+ \r
+ protected void firePropertyChanged(String id) {\r
+ for (NodeListener listener : listeners) {\r
+ listener.propertyChanged(this, id);\r
+ }\r
+ }\r
+ \r
+}\r
--- /dev/null
+package org.simantics.g3d.scenegraph.base;\r
+\r
+public class NodeException extends RuntimeException{\r
+\r
+ private static final long serialVersionUID = -6067907301659268L;\r
+\r
+ public NodeException(String message) {\r
+ super(message);\r
+ }\r
+\r
+ public NodeException(String message, Exception e) {\r
+ super(message,e);\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.g3d.scenegraph.base;\r
+\r
+\r
+public interface NodeListener {\r
+\r
+ /**\r
+ * Event occurring when a node's property is changed\r
+ * @param node\r
+ * @param child\r
+ * @param rel\r
+ */\r
+ public void propertyChanged(INode node, String id);\r
+ \r
+ /**\r
+ * Event occurring when a new node is added to the scene-graph\r
+ * @param node\r
+ * @param child\r
+ * @param rel\r
+ */\r
+ public <T extends INode> void nodeAdded(ParentNode<T> node, INode child, String rel);\r
+ \r
+ /**\r
+ * Event occurring when a node is removed from the scene-graph\r
+ * @param nodeThe node, which contained the removed node.\r
+ * @param child The removed node.\r
+ * @param rel \r
+ */\r
+ public <T extends INode> void nodeRemoved(ParentNode<T> node, INode child, String rel);\r
+}\r
--- /dev/null
+package org.simantics.g3d.scenegraph.base;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.List;\r
+\r
+import org.simantics.utils.datastructures.MapList;\r
+\r
+public abstract class ParentNode<T extends INode> extends Node {\r
+\r
+ private MapList<String, T> children = new MapList<String, T>();\r
+\r
+ public synchronized void addNode(String relName, T child) {\r
+ if (child.getParent() != null)\r
+ child.getParent().removeNode(child.getParentRel(), child);\r
+\r
+ child.setParent(this, relName);\r
+ children.add(relName, (T) child);\r
+\r
+ childrenChanged();\r
+ fireNodeAdded(child, relName);\r
+ }\r
+\r
+ /**\r
+ * Removes child node and it's hierarchy.\r
+ * @param relName\r
+ * @param child\r
+ * @return\r
+ */\r
+ @SuppressWarnings("unchecked")\r
+ public synchronized final boolean removeNode(String relName, INode child) {\r
+ if (children.remove(relName, (T) child)) {\r
+ fireNodeRemoved(child, relName);\r
+ child.remove();\r
+ child.setParent(null, null);\r
+ return true;\r
+ }\r
+ return false;\r
+ }\r
+ \r
+ /**\r
+ * Removes child node. The child nodes hierarchy is left intact.\r
+ * @param relName\r
+ * @param child\r
+ * @return\r
+ */\r
+ @SuppressWarnings("unchecked")\r
+ public synchronized final boolean deattachNode(String relName, INode child) {\r
+ if (children.remove(relName, (T) child)) {\r
+ fireNodeRemoved(child, relName);\r
+ child.setParent(null, null);\r
+ return true;\r
+ }\r
+ return false;\r
+ }\r
+ \r
+ public synchronized final boolean removeNodes(String relName) {\r
+ List<T> nodes = children.getValues(relName);\r
+ for (T child : nodes) {\r
+ if (children.remove(relName, (T) child)) {\r
+ fireNodeRemoved(child, relName);\r
+ child.remove();\r
+ child.setParent(null, null);\r
+ \r
+ }\r
+ }\r
+ return nodes.size() > 0;\r
+ }\r
+\r
+ public synchronized final void removeNodes() {\r
+ synchronized (children) {\r
+ boolean changed = false;\r
+ for (String key : children.getKeys()) {\r
+ for (T child : children.getValues(key)) {\r
+ if (child != null) {\r
+ changed = true;\r
+ if (child instanceof ParentNode<?>) {\r
+ ((ParentNode<?>) child).removeNodes();\r
+ }\r
+ child.cleanup();\r
+ child.setParent(null, null);\r
+ // if (propertyChangeListener != null) {\r
+ // propertyChangeListener.propertyChange(new\r
+ // PropertyChangeEvent(this,\r
+ // "children["+child.getId()+"]", child.getClass(),\r
+ // NULL)); // "children" is a special field name\r
+ // }\r
+ }\r
+ }\r
+ }\r
+ children.clear();\r
+ if (changed)\r
+ childrenChanged();\r
+ }\r
+ }\r
+\r
+ public synchronized List<T> getNodes(String rel) {\r
+ return children.getValues(rel);\r
+ }\r
+\r
+ public synchronized List<T> getNodes() {\r
+ List<T> result = new ArrayList<T>();\r
+ for (String s : children.getKeys())\r
+ result.addAll(children.getValues(s));\r
+ return result;\r
+ }\r
+\r
+ protected void childrenChanged() {\r
+ }\r
+\r
+\r
+ @Override\r
+ public void remove() {\r
+ synchronized (children) {\r
+ List<T> toRemove = new ArrayList<T>();\r
+ \r
+ for (String key : children.getKeys()) {\r
+ \r
+ for (T child : children.getValues(key)) {\r
+ if (child != null) {\r
+ toRemove.add(child);\r
+ }\r
+ }\r
+ }\r
+\r
+ for (T n : toRemove) {\r
+ n.remove();\r
+ }\r
+ \r
+ children.clear();\r
+ if (toRemove.size() > 0)\r
+ childrenChanged();\r
+ super.remove();\r
+ \r
+ }\r
+ }\r
+ \r
+ \r
+ \r
+ \r
+ protected void fireNodeAdded(INode node, String rel) {\r
+ for (NodeListener listener : listeners) {\r
+ listener.nodeAdded(this, node, rel);\r
+ }\r
+ }\r
+ \r
+ protected void fireNodeRemoved(INode node, String rel) {\r
+ for (NodeListener listener : listeners) {\r
+ listener.nodeRemoved(this, node, rel);\r
+ }\r
+ }\r
+ \r
+}\r
--- /dev/null
+package org.simantics.g3d.scenegraph.structural;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.Collections;\r
+import java.util.List;\r
+\r
+import org.simantics.g3d.ontology.G3D;\r
+import org.simantics.g3d.property.annotations.GetPropertyValue;\r
+import org.simantics.g3d.property.annotations.SetPropertyValue;\r
+import org.simantics.g3d.scenegraph.base.Node;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.objmap.graph.annotations.RelatedGetValue;\r
+import org.simantics.objmap.graph.annotations.RelatedSetValue;\r
+import org.simantics.objmap.structural.IStructuralObject;\r
+import org.simantics.utils.datastructures.MapList;\r
+\r
+public abstract class ComponentNode<T extends Connection, T2 extends IComponentNode> extends Node implements IComponentNode<T, T2>{\r
+\r
+ \r
+ private String name;\r
+ \r
+\r
+ @RelatedGetValue(Layer0.URIs.HasName)\r
+ @GetPropertyValue(value = Layer0.URIs.HasName, tabId = "Default", name = "Name")\r
+ public String getName() {\r
+ return name;\r
+ }\r
+ \r
+ @RelatedSetValue(Layer0.URIs.HasName)\r
+ @SetPropertyValue(Layer0.URIs.HasName)\r
+ public void setName(String name) {\r
+ if (name == null)\r
+ return;\r
+ this.name = name;\r
+ firePropertyChanged(Layer0.URIs.HasName);\r
+ }\r
+ \r
+ @Override\r
+ public String toString() {\r
+ return getName();\r
+ }\r
+ \r
+ public boolean isPartOfInstantiatedModel() {\r
+ return ctx.size() > 0;\r
+ }\r
+ \r
+ public boolean isExposed() {\r
+ if (ctx.size() == 0)\r
+ return true;\r
+ return getPublishedBy().contains(ctx.get(0));\r
+ }\r
+ \r
+ @Override\r
+ public boolean isInstantiatedModelRoot() {\r
+ return ctx.size() == 1 && this.equals(ctx.get(0));\r
+ }\r
+ \r
+ @Override\r
+ public boolean isPublishable() {\r
+ return !isPartOfInstantiatedModel();\r
+ }\r
+ \r
+ private List<IStructuralObject> ctx = new ArrayList<IStructuralObject>(1);\r
+ @Override\r
+ public List<IStructuralObject> getContext() {\r
+ return ctx;\r
+ }\r
+ \r
+ @Override\r
+ public void setContext(List<IStructuralObject> object) {\r
+ ctx = object;\r
+ }\r
+ \r
+ private List<IStructuralNode> publisher = new ArrayList<IStructuralNode>(1);\r
+ \r
+ \r
+ \r
+ protected abstract boolean isValidConnectionId(String id);\r
+ \r
+ @Override\r
+ public void connectionChanged(T c, T2 node, boolean add) {\r
+ \r
+ }\r
+ \r
+ @Override\r
+ public void addPublishedBy(IStructuralNode node) {\r
+ publisher.add(node);\r
+ firePropertyChanged(G3D.URIs.publishes);\r
+ }\r
+ \r
+ @Override\r
+ public Collection<IStructuralNode> getPublishedBy() {\r
+ return publisher;\r
+ }\r
+ \r
+ @Override\r
+ public void removePublishedBy(IStructuralNode node) {\r
+ if (publisher.remove(node))\r
+ firePropertyChanged(G3D.URIs.publishes);\r
+ }\r
+ \r
+ \r
+ @Override\r
+ public List<T> getConnections(String id) {\r
+ List<T> list = new ArrayList<T>();\r
+ list.addAll(connections.getValues(id));\r
+ list.addAll(connections.getValues(id+"/str"));\r
+ return list;\r
+ } \r
+ \r
+ public List<T2> getAllConnectedNodes() {\r
+ List<T2> list = new ArrayList<T2>();\r
+ for (T c : getAllConnections()) {\r
+ T2 node = (T2)c.getOther(this);\r
+ if (node != null)\r
+ list.add(node);\r
+ }\r
+ return list;\r
+ }\r
+ \r
+ \r
+ @Override\r
+ public void addConnection(String id, T c) {\r
+ assert(isValidConnectionId(id));\r
+ if (!isPartOfInstantiatedModel())\r
+ _addConnection(id, c);\r
+ else\r
+ _addConnection(id+"/str", c);\r
+ }\r
+ \r
+ @Override\r
+ public void removeConnection(String id, T c) {\r
+ assert(isValidConnectionId(id));\r
+ if (!isPartOfInstantiatedModel())\r
+ _removeConnection(id, c);\r
+ else\r
+ _removeConnection(id+"/str", c);\r
+ }\r
+ \r
+ @Override\r
+ public void removeConnection(String id) {\r
+ assert(isValidConnectionId(id));\r
+ if (!isPartOfInstantiatedModel())\r
+ _removeConnection(id);\r
+ else\r
+ _removeConnection(id+"/str");\r
+ }\r
+ \r
+ private MapList<String, T> connections = new MapList<String, T>();\r
+ \r
+ \r
+ protected void _addConnection(String id, T c) {\r
+ connections.add(id, c);\r
+ c.addConnect(this);\r
+ firePropertyChanged(id);\r
+ }\r
+ \r
+ protected void _addStrConnection(String id, T c) {\r
+ _addConnection(id+"/str", c);\r
+ }\r
+ \r
+ protected MapList<String, T> _getConnections() {\r
+ return connections;\r
+ }\r
+ \r
+ protected List<T> _getConnections(String id) {\r
+ return connections.getValues(id);\r
+ }\r
+ \r
+ protected List<T> _getStrConnections(String id) {\r
+ return _getConnections(id+"/str");\r
+ }\r
+ \r
+ protected void _removeConnection(String id, T c) {\r
+ if (connections.remove(id, c)) {\r
+ c.remove();\r
+ firePropertyChanged(id);\r
+ }\r
+ }\r
+ \r
+ protected void _removeConnection(String id) {\r
+ List<T> conns = new ArrayList<T>();\r
+ conns.addAll(_getConnections(id));\r
+ for (T c : conns) {\r
+ _removeConnection(id, c);\r
+ }\r
+ }\r
+ \r
+ protected void _removeStrConnection(String id, T c) {\r
+ _removeConnection(id+"/str", c);\r
+ }\r
+ \r
+ public List<T> getAllConnections() {\r
+ List<T> list = new ArrayList<T>();\r
+ List<String> keys = new ArrayList<String>();\r
+ keys.addAll(connections.getKeys());\r
+ Collections.sort(keys);\r
+ for (String s : keys)\r
+ list.addAll(connections.getValues(s));\r
+ return list;\r
+ }\r
+ \r
+ public void removeConnection(T c) {\r
+ String keys[] = connections.getKeys(new String[connections.getKeySize()]);\r
+ for (String s : keys) {\r
+ if (connections.contains(s, c))\r
+ _removeConnection(s, c);\r
+ }\r
+ }\r
+ \r
+ public List<T2> getConnectedNodes(String id) {\r
+ List<T2> list = new ArrayList<T2>();\r
+ for (T c : getConnections(id)) {\r
+ T2 node = (T2)c.getOther(this);\r
+ if (node != null)\r
+ list.add(node);\r
+ }\r
+ return list;\r
+ }\r
+ \r
+ @Override\r
+ public String getConnectionId(T c) {\r
+ for (String s : connections.getKeys()) {\r
+ if (connections.contains(s, c)) {\r
+ if (!s.endsWith("/str"))\r
+ return s;\r
+ return s.substring(0, s.length()-4);\r
+ }\r
+ }\r
+ return null;\r
+ }\r
+ \r
+ @Override\r
+ public Collection<String> getConnectionIds(T2 node) {\r
+ Collection<String> ids = new ArrayList<String>();\r
+ for (String s : connections.getKeys()) {\r
+ for (T c : connections.getValues(s)) {\r
+ if (node.equals(c.getOther(this))) {\r
+ if (!s.endsWith("/str"))\r
+ ids.add(s);\r
+ else\r
+ ids.add(s.substring(0, s.length()-4));\r
+ }\r
+ }\r
+ }\r
+ return ids;\r
+ }\r
+ \r
+ @Override\r
+ public void remove() {\r
+ List<T> connections = getAllConnections();\r
+ for (T c : connections) {\r
+ removeConnection(c);\r
+ }\r
+ super.remove();\r
+ \r
+ }\r
+}\r
--- /dev/null
+package org.simantics.g3d.scenegraph.structural;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.List;\r
+\r
+import org.simantics.db.Resource;\r
+import org.simantics.objmap.structural.IStructuralObject;\r
+\r
+@SuppressWarnings("rawtypes")\r
+public abstract class Connection <T extends IComponentNode> implements IStructuralObject{\r
+\r
+ \r
+ private List<T> connects = new ArrayList<T>();\r
+ \r
+ \r
+ public void addConnect(T node) {\r
+ if (!connects.contains(node))\r
+ connects.add(node);\r
+ fireChanged(node,true);\r
+ }\r
+ \r
+ protected void fireChanged(T node, boolean add){\r
+ for (IComponentNode n : connects) {\r
+ n.connectionChanged(this,node,add);\r
+ }\r
+ }\r
+ \r
+ public Collection<T> getConnected() {\r
+ return connects;\r
+ }\r
+ \r
+ public void removeConnect(T node) {\r
+ connects.remove(node);\r
+ fireChanged(node,false);\r
+ }\r
+ \r
+ public void remove() {\r
+ List<T> toRemove = new ArrayList<T>(connects.size());\r
+ toRemove.addAll(connects);\r
+ for (IComponentNode node : toRemove) {\r
+ node.removeConnection(this);\r
+ }\r
+ }\r
+ \r
+ public T getOther(T node) {\r
+ if (connects.size() != 2) \r
+ return null;\r
+ if (connects.get(0).equals(node))\r
+ return connects.get(1);\r
+ else if (connects.get(1).equals(node))\r
+ return connects.get(0);\r
+ return null;\r
+ }\r
+ \r
+ @Override\r
+ public void setType(Resource type) {\r
+ \r
+ }\r
+ \r
+ @Override\r
+ public Resource getType() {\r
+ return null;\r
+ }\r
+ \r
+ private List<IStructuralObject> ctx = new ArrayList<IStructuralObject>(1);\r
+ @Override\r
+ public List<IStructuralObject> getContext() {\r
+ return ctx;\r
+ }\r
+ \r
+ @Override\r
+ public void setContext(List<IStructuralObject> object) {\r
+ ctx = object;\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.g3d.scenegraph.structural;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.Collections;\r
+import java.util.List;\r
+\r
+import org.simantics.g3d.ontology.G3D;\r
+import org.simantics.g3d.property.annotations.GetPropertyValue;\r
+import org.simantics.g3d.property.annotations.SetPropertyValue;\r
+import org.simantics.g3d.scenegraph.G3DNode;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.objmap.graph.annotations.RelatedGetValue;\r
+import org.simantics.objmap.graph.annotations.RelatedSetValue;\r
+import org.simantics.objmap.structural.IStructuralObject;\r
+import org.simantics.utils.datastructures.MapList;\r
+\r
+public abstract class G3DComponentNode<T extends Connection, T2 extends IComponentNode> extends G3DNode implements IComponentNode<T, T2>{\r
+\r
+ \r
+ private String name;\r
+ \r
+\r
+ @RelatedGetValue(Layer0.URIs.HasName)\r
+ @GetPropertyValue(value = Layer0.URIs.HasName, tabId = "Default", name = "Name")\r
+ public String getName() {\r
+ return name;\r
+ }\r
+ \r
+ @RelatedSetValue(Layer0.URIs.HasName)\r
+ @SetPropertyValue(Layer0.URIs.HasName)\r
+ public void setName(String name) {\r
+ if (name == null)\r
+ return;\r
+ this.name = name;\r
+ firePropertyChanged(Layer0.URIs.HasName);\r
+ }\r
+ \r
+ @Override\r
+ public String toString() {\r
+ return getName();\r
+ }\r
+ \r
+ public boolean isPartOfInstantiatedModel() {\r
+ return ctx.size() > 0;\r
+ }\r
+ \r
+ public boolean isExposed() {\r
+ if (ctx.size() == 0)\r
+ return true;\r
+ return getPublishedBy().contains(ctx.get(0));\r
+ }\r
+ \r
+ @Override\r
+ public boolean isInstantiatedModelRoot() {\r
+ return ctx.size() == 1 && this.equals(ctx.get(0));\r
+ }\r
+ \r
+ @Override\r
+ public boolean isPublishable() {\r
+ return !isPartOfInstantiatedModel();\r
+ }\r
+ \r
+ private List<IStructuralObject> ctx = new ArrayList<IStructuralObject>(1);\r
+ @Override\r
+ public List<IStructuralObject> getContext() {\r
+ return ctx;\r
+ }\r
+ \r
+ @Override\r
+ public void setContext(List<IStructuralObject> object) {\r
+ ctx = object;\r
+ }\r
+ \r
+ private List<IStructuralNode> publisher = new ArrayList<IStructuralNode>(1);\r
+ \r
+ \r
+ \r
+ protected abstract boolean isValidConnectionId(String id);\r
+ \r
+ @Override\r
+ public void connectionChanged(T c, T2 node, boolean add) {\r
+ \r
+ }\r
+ \r
+ @Override\r
+ public void addPublishedBy(IStructuralNode node) {\r
+ publisher.add(node);\r
+ firePropertyChanged(G3D.URIs.publishes);\r
+ }\r
+ \r
+ @Override\r
+ public Collection<IStructuralNode> getPublishedBy() {\r
+ return publisher;\r
+ }\r
+ \r
+ @Override\r
+ public void removePublishedBy(IStructuralNode node) {\r
+ if (publisher.remove(node))\r
+ firePropertyChanged(G3D.URIs.publishes);\r
+ }\r
+ \r
+ \r
+ @Override\r
+ public List<T> getConnections(String id) {\r
+ List<T> list = new ArrayList<T>();\r
+ list.addAll(connections.getValues(id));\r
+ list.addAll(connections.getValues(id+"/str"));\r
+ return list;\r
+ } \r
+ \r
+ public List<T2> getAllConnectedNodes() {\r
+ List<T2> list = new ArrayList<T2>();\r
+ for (T c : getAllConnections()) {\r
+ T2 node = (T2)c.getOther(this);\r
+ if (node != null)\r
+ list.add(node);\r
+ }\r
+ return list;\r
+ }\r
+ \r
+ \r
+ @Override\r
+ public void addConnection(String id, T c) {\r
+ assert(isValidConnectionId(id));\r
+ if (!isPartOfInstantiatedModel())\r
+ _addConnection(id, c);\r
+ else\r
+ _addConnection(id+"/str", c);\r
+ }\r
+ \r
+ @Override\r
+ public void removeConnection(String id, T c) {\r
+ assert(isValidConnectionId(id));\r
+ if (!isPartOfInstantiatedModel())\r
+ _removeConnection(id, c);\r
+ else\r
+ _removeConnection(id+"/str", c);\r
+ }\r
+ \r
+ @Override\r
+ public void removeConnection(String id) {\r
+ assert(isValidConnectionId(id));\r
+ if (!isPartOfInstantiatedModel())\r
+ _removeConnection(id);\r
+ else\r
+ _removeConnection(id+"/str");\r
+ }\r
+ \r
+ private MapList<String, T> connections = new MapList<String, T>();\r
+ \r
+ \r
+ protected void _addConnection(String id, T c) {\r
+ connections.add(id, c);\r
+ c.addConnect(this);\r
+ firePropertyChanged(id);\r
+ }\r
+ \r
+ protected void _addStrConnection(String id, T c) {\r
+ _addConnection(id+"/str", c);\r
+ }\r
+ \r
+ protected MapList<String, T> _getConnections() {\r
+ return connections;\r
+ }\r
+ \r
+ protected List<T> _getConnections(String id) {\r
+ return connections.getValues(id);\r
+ }\r
+ \r
+ protected List<T> _getStrConnections(String id) {\r
+ return _getConnections(id+"/str");\r
+ }\r
+ \r
+ protected void _removeConnection(String id, T c) {\r
+ if (connections.remove(id, c)) {\r
+ c.remove();\r
+ firePropertyChanged(id);\r
+ }\r
+ }\r
+ \r
+ protected void _removeConnection(String id) {\r
+ List<T> conns = new ArrayList<T>();\r
+ conns.addAll(_getConnections(id));\r
+ for (T c : conns) {\r
+ _removeConnection(id, c);\r
+ }\r
+ }\r
+ \r
+ protected void _removeStrConnection(String id, T c) {\r
+ _removeConnection(id+"/str", c);\r
+ }\r
+ \r
+ public List<T> getAllConnections() {\r
+ List<T> list = new ArrayList<T>();\r
+ List<String> keys = new ArrayList<String>();\r
+ keys.addAll(connections.getKeys());\r
+ Collections.sort(keys);\r
+ for (String s : keys)\r
+ list.addAll(connections.getValues(s));\r
+ return list;\r
+ }\r
+ \r
+ public void removeConnection(T c) {\r
+ String keys[] = connections.getKeys(new String[connections.getKeySize()]);\r
+ for (String s : keys) {\r
+ if (connections.contains(s, c))\r
+ _removeConnection(s, c);\r
+ }\r
+ }\r
+ \r
+ public List<T2> getConnectedNodes(String id) {\r
+ List<T2> list = new ArrayList<T2>();\r
+ for (T c : getConnections(id)) {\r
+ T2 node = (T2)c.getOther(this);\r
+ if (node != null)\r
+ list.add(node);\r
+ }\r
+ return list;\r
+ }\r
+ \r
+ @Override\r
+ public String getConnectionId(T c) {\r
+ for (String s : connections.getKeys()) {\r
+ if (connections.contains(s, c)) {\r
+ if (!s.endsWith("/str"))\r
+ return s;\r
+ return s.substring(0, s.length()-4);\r
+ }\r
+ }\r
+ return null;\r
+ }\r
+ \r
+ @Override\r
+ public Collection<String> getConnectionIds(T2 node) {\r
+ Collection<String> ids = new ArrayList<String>();\r
+ for (String s : connections.getKeys()) {\r
+ for (T c : connections.getValues(s)) {\r
+ if (node.equals(c.getOther(this))) {\r
+ if (!s.endsWith("/str"))\r
+ ids.add(s);\r
+ else\r
+ ids.add(s.substring(0, s.length()-4));\r
+ }\r
+ }\r
+ }\r
+ return ids;\r
+ }\r
+ \r
+ @Override\r
+ public void remove() {\r
+ List<T> connections = getAllConnections();\r
+ for (T c : connections) {\r
+ removeConnection(c);\r
+ }\r
+ super.remove();\r
+ \r
+ }\r
+}\r
--- /dev/null
+package org.simantics.g3d.scenegraph.structural;\r
+\r
+import java.util.Collection;\r
+\r
+import javax.vecmath.Quat4d;\r
+import javax.vecmath.Vector3d;\r
+\r
+import org.simantics.g3d.math.MathTools;\r
+import org.simantics.g3d.ontology.G3D;\r
+import org.simantics.g3d.property.annotations.GetPropertyValue;\r
+import org.simantics.g3d.property.annotations.SetPropertyValue;\r
+import org.simantics.g3d.scenegraph.IG3DNode;\r
+import org.simantics.g3d.scenegraph.base.INode;\r
+import org.simantics.g3d.scenegraph.base.NodeException;\r
+import org.simantics.g3d.tools.NodeTools;\r
+import org.simantics.objmap.graph.annotations.RelatedGetValue;\r
+import org.simantics.objmap.graph.annotations.RelatedSetValue;\r
+\r
+public abstract class G3DStructuralParentNode<T extends IStructuralNode> extends StructuralParentNode<T> implements IG3DNode{\r
+ private Vector3d position = new Vector3d();\r
+ private Quat4d orientation = MathTools.getIdentityQuat();\r
+ \r
+\r
+ @GetPropertyValue(value = G3D.URIs.hasOrientation, tabId = "Transform", name = "Orientation")\r
+ public Quat4d getOrientation() {\r
+ if (getParent() == null)\r
+ return MathTools.getIdentityQuat();\r
+ return orientation;\r
+ };\r
+ \r
+ @Override\r
+ @GetPropertyValue(value = G3D.URIs.hasPosition, tabId = "Transform", name = "Position")\r
+ public Vector3d getPosition() {\r
+ if (getParent() == null)\r
+ return MathTools.ORIGIN;\r
+ return position;\r
+ }\r
+ \r
+ @Override\r
+ @GetPropertyValue(value = G3D.URIs.hasWorldOrientation, tabId = "Transform", name = "World Orientation")\r
+ public Quat4d getWorldOrientation() {\r
+ if (getParent() == null)\r
+ return MathTools.getIdentityQuat();\r
+ return getWorldOrientation(orientation);\r
+ }\r
+ \r
+ @Override\r
+ @GetPropertyValue(value = G3D.URIs.hasWorldPosition, tabId = "Transform", name = "World Position")\r
+ public Vector3d getWorldPosition() {\r
+ IG3DNode parent = (IG3DNode)getParent();\r
+ if (parent == null)\r
+ return MathTools.ORIGIN;\r
+ return NodeTools.getWorldPosition(parent, new Vector3d(position));\r
+ }\r
+ \r
+ @Override\r
+ public Quat4d getWorldOrientation(Quat4d localOrientation) {\r
+ IG3DNode parent = (IG3DNode)getParent();\r
+ if (parent == null)\r
+ return localOrientation;\r
+ return NodeTools.getWorldOrientation(parent, localOrientation);\r
+ }\r
+ \r
+ \r
+ public Vector3d getWorldPosition(Vector3d localPosition) {\r
+ return NodeTools.getWorldPosition(this,localPosition);\r
+ }\r
+ \r
+ @Override\r
+ public Quat4d getLocalOrientation(Quat4d worldOrientation) {\r
+ IG3DNode parent = (IG3DNode)getParent();\r
+ if (parent == null)\r
+ return worldOrientation;\r
+ return NodeTools.getLocalOrientation(parent, new Quat4d(worldOrientation));\r
+ }\r
+ \r
+ @Override\r
+ public Vector3d getLocalPosition(Vector3d worldPosition) {\r
+ IG3DNode parent = (IG3DNode)getParent();\r
+ if (parent == null)\r
+ return worldPosition;\r
+ return NodeTools.getLocalPosition(parent,new Vector3d(worldPosition));\r
+ }\r
+ \r
+ @Override\r
+ @SetPropertyValue(G3D.URIs.hasPosition)\r
+ public void setPosition(Vector3d position) {\r
+ this.position = position;\r
+ firePropertyChanged(G3D.URIs.hasPosition);\r
+ }\r
+ \r
+ @Override\r
+ @SetPropertyValue(G3D.URIs.hasOrientation)\r
+ public void setOrientation(Quat4d orientation) {\r
+ this.orientation = orientation;\r
+ firePropertyChanged(G3D.URIs.hasOrientation);\r
+ }\r
+ \r
+ @Override\r
+ @SetPropertyValue(G3D.URIs.hasWorldOrientation)\r
+ public void setWorldOrientation(Quat4d orientation) {\r
+ if (getParent() == null)\r
+ throw new NodeException("Cannot set root node orientation");\r
+ Quat4d localOr = getLocalOrientation(orientation);\r
+ setOrientation(localOr);\r
+ }\r
+ \r
+ @Override\r
+ @SetPropertyValue(G3D.URIs.hasWorldPosition)\r
+ public void setWorldPosition(Vector3d position) {\r
+ if (getParent() == null)\r
+ throw new NodeException("Cannot set root node position");\r
+ Vector3d localPos = getLocalPosition(position);\r
+ setPosition(localPos);\r
+ }\r
+ \r
+ \r
+ \r
+ @RelatedGetValue(G3D.URIs.hasOrientation)\r
+ public double[] getOrientationArr() {\r
+ double arr[] = new double[4];\r
+ orientation.get(arr);\r
+ return arr;\r
+ \r
+ }\r
+ \r
+ @RelatedGetValue(G3D.URIs.hasPosition)\r
+ public double[] getPositionArr() {\r
+ double arr[] = new double[3];\r
+ position.get(arr);\r
+ return arr;\r
+ }\r
+ \r
+ @RelatedSetValue(G3D.URIs.hasOrientation)\r
+ public void setOrientation(double[] arr) {\r
+ if (arr == null)\r
+ return;\r
+ setOrientation(new Quat4d(arr));\r
+ }\r
+ \r
+ @RelatedSetValue(G3D.URIs.hasPosition)\r
+ public void setPosition(double[] arr) {\r
+ if (arr == null)\r
+ return;\r
+ setPosition(new Vector3d(arr));\r
+ }\r
+ \r
+ \r
+ protected void _addStrNode(String id, T child) {\r
+ addNode(id+"/str", child);\r
+ }\r
+ \r
+ protected boolean _removeStrNode(String id, T child) {\r
+ return removeNode(id+"/str", child);\r
+ }\r
+ \r
+ protected Collection<T> _getStrNodes(String id) {\r
+ return getNodes(id+"/str");\r
+ }\r
+ \r
+ public Object getAdapter(Class adapter) {\r
+ if (INode.class == adapter)\r
+ return this;\r
+ if (IG3DNode.class == adapter)\r
+ return this;\r
+ return null;\r
+ }\r
+ \r
+ \r
+ \r
+}\r
--- /dev/null
+package org.simantics.g3d.scenegraph.structural;\r
+\r
+import java.util.Collection;\r
+import java.util.List;\r
+\r
+\r
+@SuppressWarnings("rawtypes")\r
+public interface IComponentNode<T extends Connection, T2 extends IComponentNode> extends IStructuralNode{\r
+ \r
+ public List<T> getAllConnections();\r
+ //public void addConnection(Connection c);\r
+ public void removeConnection(T c);\r
+ public void connectionChanged(T c, T2 node, boolean add);\r
+\r
+ public List<T> getConnections(String id);\r
+ public void addConnection(String id,T c);\r
+ public void removeConnection(String id,T c);\r
+ public void removeConnection(String id);\r
+ \r
+ public String getConnectionId(T c);\r
+ public Collection<String> getConnectionIds(T2 node);\r
+ public List<T2> getAllConnectedNodes();\r
+ public List<T2> getConnectedNodes(String id);\r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.scenegraph.structural;\r
+\r
+import java.util.Collection;\r
+\r
+import org.simantics.g3d.scenegraph.base.INode;\r
+import org.simantics.objmap.structural.IStructuralObject;\r
+\r
+public interface IStructuralNode extends INode, IStructuralObject {\r
+ \r
+ public String getName();\r
+ \r
+ public boolean isPartOfInstantiatedModel();\r
+ public boolean isExposed();\r
+ public boolean isInstantiatedModelRoot();\r
+ public boolean isPublishable();\r
+ \r
+\r
+\r
+ public Collection<IStructuralNode> getPublishedBy();\r
+ public void addPublishedBy(IStructuralNode node);\r
+ public void removePublishedBy(IStructuralNode node);\r
+}\r
--- /dev/null
+package org.simantics.g3d.scenegraph.structural;\r
+\r
+import java.util.Collection;\r
+\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.objmap.graph.annotations.RelatedElementsAdd;\r
+import org.simantics.objmap.graph.annotations.RelatedElementsGet;\r
+import org.simantics.objmap.graph.annotations.RelatedElementsRem;\r
+import org.simantics.objmap.structural.annotations.TypeRelatedElementsAdd;\r
+import org.simantics.objmap.structural.annotations.TypeRelatedElementsGet;\r
+import org.simantics.objmap.structural.annotations.TypeRelatedElementsRem;\r
+\r
+public interface IStructuralRootNode extends IStructuralNode {\r
+ \r
+ @RelatedElementsAdd(Layer0.URIs.ConsistsOf)\r
+ public void addComponent(IStructuralNode node);\r
+ @RelatedElementsGet(Layer0.URIs.ConsistsOf)\r
+ public Collection<IStructuralNode> getComponent();\r
+ @RelatedElementsRem(Layer0.URIs.ConsistsOf)\r
+ public void removeComponent(IStructuralNode node);\r
+ \r
+ @TypeRelatedElementsAdd(Layer0.URIs.ConsistsOf)\r
+ public void addTypeComponent(IStructuralNode node);\r
+ @TypeRelatedElementsGet(Layer0.URIs.ConsistsOf)\r
+ public Collection<IStructuralNode> getTypeComponent();\r
+ @TypeRelatedElementsRem(Layer0.URIs.ConsistsOf)\r
+ public void removeTypeComponent(IStructuralNode node);\r
+ \r
+ @RelatedElementsAdd(Layer0.URIs.DomainOf)\r
+ public void addPublished(IStructuralNode node);\r
+ @RelatedElementsGet(Layer0.URIs.DomainOf)\r
+ public Collection<IStructuralNode> getPublished();\r
+ @RelatedElementsRem(Layer0.URIs.DomainOf)\r
+ public void removePublished(IStructuralNode node);\r
+ \r
+ @TypeRelatedElementsAdd(Layer0.URIs.DomainOf)\r
+ public void addTypePublished(IStructuralNode node);\r
+ @TypeRelatedElementsGet(Layer0.URIs.DomainOf)\r
+ public Collection<IStructuralNode> getTypePublished();\r
+ @TypeRelatedElementsRem(Layer0.URIs.DomainOf)\r
+ public void removeTypePublished(IStructuralNode node);\r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.scenegraph.structural;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.List;\r
+\r
+import org.simantics.g3d.ontology.G3D;\r
+import org.simantics.g3d.property.annotations.GetPropertyValue;\r
+import org.simantics.g3d.property.annotations.SetPropertyValue;\r
+import org.simantics.g3d.scenegraph.base.ParentNode;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.objmap.graph.annotations.RelatedGetValue;\r
+import org.simantics.objmap.graph.annotations.RelatedSetValue;\r
+import org.simantics.objmap.structural.IStructuralObject;\r
+\r
+public abstract class StructuralParentNode<T extends IStructuralNode> extends ParentNode<T> implements IStructuralNode{\r
+\r
+ private String name;\r
+ \r
+\r
+ @RelatedGetValue(Layer0.URIs.HasName)\r
+ @GetPropertyValue(value = Layer0.URIs.HasName, tabId = "Default", name = "Name")\r
+ public String getName() {\r
+ return name;\r
+ }\r
+ \r
+ @RelatedSetValue(Layer0.URIs.HasName)\r
+ @SetPropertyValue(Layer0.URIs.HasName)\r
+ public void setName(String name) {\r
+ if (name == null)\r
+ return;\r
+ this.name = name;\r
+ firePropertyChanged(Layer0.URIs.HasName);\r
+ }\r
+ \r
+ @Override\r
+ public String toString() {\r
+ return getName();\r
+ }\r
+ \r
+ public boolean isPartOfInstantiatedModel() {\r
+ return ctx.size() > 0;\r
+ }\r
+ \r
+ public boolean isExposed() {\r
+ if (ctx.size() == 0)\r
+ return true;\r
+ return getPublishedBy().contains(ctx.get(0));\r
+ }\r
+ \r
+ @Override\r
+ public boolean isInstantiatedModelRoot() {\r
+ return ctx.size() == 1 && this.equals(ctx.get(0));\r
+ }\r
+ \r
+ @Override\r
+ public boolean isPublishable() {\r
+ return !isPartOfInstantiatedModel();\r
+ }\r
+ \r
+ private List<IStructuralObject> ctx = new ArrayList<IStructuralObject>(1);\r
+ @Override\r
+ public List<IStructuralObject> getContext() {\r
+ return ctx;\r
+ }\r
+ \r
+ @Override\r
+ public void setContext(List<IStructuralObject> object) {\r
+ ctx = object;\r
+ }\r
+ \r
+ private List<IStructuralNode> publisher = new ArrayList<IStructuralNode>(1);\r
+ \r
+ @Override\r
+ public void addPublishedBy(IStructuralNode node) {\r
+ publisher.add(node);\r
+ firePropertyChanged(G3D.URIs.publishes);\r
+ }\r
+ \r
+ @Override\r
+ public Collection<IStructuralNode> getPublishedBy() {\r
+ return publisher;\r
+ }\r
+ \r
+ @Override\r
+ public void removePublishedBy(IStructuralNode node) {\r
+ if (publisher.remove(node))\r
+ firePropertyChanged(G3D.URIs.publishes);\r
+ }\r
+ \r
+ @Override\r
+ public void remove() {\r
+ IStructuralRootNode root = (IStructuralRootNode)getRootNode();\r
+ if (root.getPublished().contains(this))\r
+ root.removePublished(this);\r
+ \r
+ super.remove();\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.g3d.shape;\r
+\r
+import javax.vecmath.Tuple4d;\r
+import javax.vecmath.Tuple4f;\r
+\r
+public class Color4d extends Tuple4d{\r
+\r
+ private static final long serialVersionUID = -4217159803441535837L;\r
+\r
+ public Color4d() {\r
+ super();\r
+ }\r
+\r
+ public Color4d(double x, double y, double z, double w) {\r
+ super(x, y, z, w);\r
+ }\r
+\r
+ public Color4d(double[] t) {\r
+ super(t);\r
+ }\r
+\r
+ public Color4d(Tuple4d t1) {\r
+ super(t1);\r
+ }\r
+\r
+ public Color4d(Tuple4f t1) {\r
+ super(t1);\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.shape;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import javax.vecmath.AxisAngle4d;\r
+import javax.vecmath.Vector3d;\r
+\r
+import org.simantics.g3d.math.MathTools;\r
+\r
+public class Cone {\r
+\r
+ public static Mesh create(double radius, int s) {\r
+ if (s < 3 || radius < MathTools.NEAR_ZERO)\r
+ throw new IllegalArgumentException();\r
+ List<Vector3d> vertices = new ArrayList<Vector3d>(s+2);\r
+ List<Vector3d> normals = new ArrayList<Vector3d>(vertices.size());\r
+ List<Integer> indices = new ArrayList<Integer>();\r
+ \r
+ vertices.add(new Vector3d(0.0,0.0,0.0));\r
+ normals.add(new Vector3d(0.0,-1.0,0.0));\r
+ vertices.add(new Vector3d(0.0,radius*2.0,0.0));\r
+ normals.add(new Vector3d(0.0,1.0,0.0));\r
+ \r
+ Vector3d v = new Vector3d(radius,0,0);\r
+ for (int i = 0; i < s; i++) {\r
+ AxisAngle4d aa = new AxisAngle4d(0,1,0,((double)i/(double)s)*Math.PI * 2);\r
+ Vector3d t = new Vector3d();\r
+ MathTools.rotate(MathTools.getQuat(aa), v, t);\r
+ vertices.add(t);\r
+ Vector3d n = new Vector3d(t);\r
+ n.normalize();\r
+ normals.add(n);\r
+ }\r
+ \r
+ for (int i = 0; i < s; i++) {\r
+ indices.add(0);\r
+ \r
+ if (i < s - 1)\r
+ indices.add(i + 3);\r
+ else\r
+ indices.add(2);\r
+ indices.add(i + 2);\r
+ }\r
+ \r
+ for (int i = 0; i < s; i++) {\r
+ indices.add(1);\r
+ indices.add(i + 2);\r
+ if (i < s - 1)\r
+ indices.add(i + 3);\r
+ else\r
+ indices.add(2);\r
+ \r
+ }\r
+ return new Mesh(vertices,normals,indices);\r
+ \r
+ }\r
+ \r
+ public static void main(String arg[]) {\r
+ Mesh s1 = create(1.0, 3);\r
+ Mesh s2 = create(1.0, 4);\r
+ System.out.println("debug " + s1 + "\n" + s2);\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.g3d.shape;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import javax.vecmath.Vector3d;\r
+\r
+public class Cylinder {\r
+ \r
+ public static Mesh create(Vector3d start, Vector3d dir, double r, int s) {\r
+ Tube tube = new Tube();\r
+ tube.setResolution(s);\r
+ tube.setRadius(r);\r
+ List<Vector3d> vertices = new ArrayList<Vector3d>();\r
+ vertices.add(start);\r
+ Vector3d t = new Vector3d(start);\r
+ t.add(dir);\r
+ vertices.add(dir);\r
+ tube.setVertices(vertices);\r
+ return tube.create();\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.shape;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import javax.vecmath.Quat4d;\r
+import javax.vecmath.Vector3d;\r
+\r
+import org.simantics.g3d.math.MathTools;\r
+\r
+public class Mesh {\r
+ private List<Vector3d> vertices;\r
+ private List<Vector3d> normals;\r
+ private List<Color4d> colors;\r
+ private List<Integer> indices;\r
+ \r
+ \r
+ public Mesh(List<Vector3d> vertices, List<Vector3d> normals,\r
+ List<Color4d> colors, List<Integer> indices) {\r
+ this.vertices = vertices;\r
+ this.normals = normals;\r
+ this.colors = colors;\r
+ this.indices = indices;\r
+ }\r
+ \r
+ public Mesh(List<Vector3d> vertices, List<Vector3d> normals, List<Integer> indices) {\r
+ this.vertices = vertices;\r
+ this.normals = normals;\r
+ this.indices = indices;\r
+ }\r
+ \r
+ public Mesh(List<Vector3d> vertices, List<Integer> indices) {\r
+ this.vertices = vertices;\r
+ this.indices = indices;\r
+ }\r
+\r
+ public List<Vector3d> getVertices() {\r
+ return vertices;\r
+ }\r
+ \r
+ public List<Vector3d> getNormals() {\r
+ return normals;\r
+ }\r
+ \r
+ public List<Integer> getIndices() {\r
+ return indices;\r
+ }\r
+ \r
+ public List<Color4d> getColors() {\r
+ return colors;\r
+ }\r
+ \r
+ public void createNormals() {\r
+ normals = new ArrayList<Vector3d>(vertices.size());\r
+ for (int i = 0; i < vertices.size(); i++) {\r
+ normals.add(new Vector3d());\r
+ }\r
+ Vector3d v1 = new Vector3d();\r
+ Vector3d v2 = new Vector3d();\r
+ Vector3d v3 = new Vector3d();\r
+ Vector3d t1 = new Vector3d();\r
+ Vector3d t2 = new Vector3d();\r
+ Vector3d n = new Vector3d();\r
+ for (int i = 0; i < indices.size(); i+=3) {\r
+ v1.set(vertices.get(i));\r
+ v2.set(vertices.get(i+1));\r
+ v3.set(vertices.get(i+2));\r
+ t1.sub(v3,v1);\r
+ t2.sub(v2,v1);\r
+ n.cross(t2, t1);\r
+ normals.get(i).add(n);\r
+ normals.get(i+1).add(n);\r
+ normals.get(i+2).add(n);\r
+ }\r
+ for (int i = 0; i < normals.size(); i++) {\r
+ normals.get(i).normalize();\r
+ }\r
+ }\r
+ \r
+ public void translate(Vector3d v) {\r
+ for (int i = 0; i < vertices.size(); i++) {\r
+ vertices.get(i).add(v);\r
+ }\r
+ }\r
+ \r
+ public void rotate(Quat4d q) {\r
+ Vector3d t = new Vector3d();\r
+ for (int i = 0; i < vertices.size(); i++) {\r
+ MathTools.rotate(q, vertices.get(i), t);\r
+ vertices.get(i).set(t);\r
+ }\r
+ \r
+ if (normals != null) {\r
+ for (int i = 0; i < normals.size(); i++) {\r
+ MathTools.rotate(q, normals.get(i), t);\r
+ t.normalize();\r
+ normals.get(i).set(t);\r
+ } \r
+ }\r
+ }\r
+ \r
+ public void setColor(Color4d color) {\r
+ colors = new ArrayList<Color4d>(vertices.size());\r
+ for (int i = 0; i < vertices.size(); i++) {\r
+ colors.add(color);\r
+ }\r
+ }\r
+ \r
+ public void add(Mesh mesh) {\r
+ int vindex = vertices.size();\r
+ int triIndex = indices.size();\r
+ vertices.addAll(mesh.getVertices());\r
+ indices.addAll(mesh.indices);\r
+ for (int i = triIndex; i < indices.size(); i++) {\r
+ indices.set(i, indices.get(i)+vindex);\r
+ }\r
+ if (normals != null) {\r
+ boolean hasNormals = true;\r
+ if (mesh.getNormals() == null) {\r
+ mesh.createNormals();\r
+ hasNormals = false;\r
+ }\r
+ normals.addAll(mesh.getNormals());\r
+ if (!hasNormals)\r
+ mesh.normals = null;\r
+ }\r
+ if (colors != null) {\r
+ if (mesh.getColors() != null) {\r
+ colors.addAll(mesh.getColors());\r
+ } else {\r
+ for (int i = 0; i < mesh.getVertices().size(); i++) {\r
+ colors.add(new Color4d(1,1,1,0));\r
+ }\r
+ }\r
+ }\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.g3d.shape;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import javax.vecmath.AxisAngle4d;\r
+import javax.vecmath.Vector3d;\r
+\r
+import org.simantics.g3d.math.MathTools;\r
+\r
+public class Sphere {\r
+\r
+ public static Mesh create(double radius, int s, int p) {\r
+ if (s < 3 || p < 3 || radius < MathTools.NEAR_ZERO)\r
+ throw new IllegalArgumentException();\r
+ List<Vector3d> vertices = new ArrayList<Vector3d>((s-2)*p + 2);\r
+ List<Vector3d> normals = new ArrayList<Vector3d>(vertices.size());\r
+ List<Integer> indices = new ArrayList<Integer>(((s-3)*p*2 + p * 2)*3);\r
+ Vector3d v = new Vector3d(0.0,-radius,0.0);\r
+ Vector3d vp = new Vector3d();\r
+ for (int ip = 0; ip < p; ip++) {\r
+ if (ip == 0) {\r
+ vertices.add(new Vector3d(0.0,-radius,0.0));\r
+ } else if (ip == p - 1) {\r
+ vertices.add(new Vector3d(0.0, radius,0.0));\r
+ int off = 1 + (ip-2)*s;\r
+ for (int is = 0; is < s; is++) {\r
+ indices.add(vertices.size() - 1);\r
+ indices.add(is+off);\r
+ if (is < s -1)\r
+ indices.add(is+off+1);\r
+ else\r
+ indices.add(off);\r
+ \r
+ \r
+ }\r
+ } else {\r
+ AxisAngle4d aa = new AxisAngle4d(1, 0, 0, ((double)ip/(double)(p-1))*Math.PI);\r
+ MathTools.rotate(MathTools.getQuat(aa), v, vp);\r
+ for (int is = 0; is < s; is++) {\r
+ aa = new AxisAngle4d(0, 1, 0, ((double)is/(double)s)*Math.PI*2);\r
+ Vector3d vs = new Vector3d();\r
+ MathTools.rotate(MathTools.getQuat(aa), vp, vs);\r
+ vertices.add(vs);\r
+ }\r
+ if (ip == 1) {\r
+ for (int is = 0; is < s; is++) {\r
+ indices.add(0);\r
+ if (is < s -1)\r
+ indices.add(is+2);\r
+ else\r
+ indices.add(1);\r
+ indices.add(is+1);\r
+ }\r
+ } else {\r
+ int off = 1 + (ip-1)*s;\r
+ for (int is = 0; is < s-1; is++) {\r
+ indices.add(off + is - s);\r
+ indices.add(off + is+1);\r
+ indices.add(off + is);\r
+ \r
+ \r
+ indices.add(off + is - s);\r
+ indices.add(off + is + 1 - s);\r
+ indices.add(off + is + 1);\r
+ \r
+ }\r
+ indices.add(off - 1);\r
+ indices.add(off);\r
+ indices.add(off + s - 1);\r
+ \r
+ indices.add(off -1);\r
+ indices.add(off - s);\r
+ indices.add(off);\r
+ \r
+ }\r
+ }\r
+ }\r
+ for (int i = 0; i < vertices.size(); i++) {\r
+ Vector3d n = new Vector3d(vertices.get(i));\r
+ n.normalize();\r
+ normals.add(n);\r
+ }\r
+ \r
+ return new Mesh(vertices,normals,indices);\r
+ \r
+ }\r
+ \r
+ public static void main(String arg[]) {\r
+ Mesh s1 = create(1.0, 3, 3);\r
+ Mesh s2 = create(1.0, 4, 4);\r
+ System.out.println("debug " + s1 + " " + s2);\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.g3d.shape;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import javax.vecmath.AxisAngle4d;\r
+import javax.vecmath.Vector3d;\r
+\r
+import org.simantics.g3d.math.MathTools;\r
+\r
+\r
+public class Tube {\r
+ List<Vector3d> vertices;\r
+ List<Color4d> colors;\r
+ List<Double> radiis;\r
+ Double radius = 1.0;\r
+ int resolution = 8;\r
+ \r
+ \r
+ public void setResolution(int resolution) {\r
+ if (resolution > 2)\r
+ this.resolution = resolution;\r
+ }\r
+ \r
+ public void setVertices(List<Vector3d> vertices) {\r
+ this.vertices = vertices;\r
+ }\r
+\r
+ public void setColors(List<Color4d> colors) {\r
+ this.colors = colors;\r
+ }\r
+ \r
+ public void setRadiis(List<Double> radiis) {\r
+ this.radiis = radiis;\r
+ }\r
+ \r
+ public void setRadius(Double radius) {\r
+ this.radius = radius;\r
+ }\r
+ \r
+ \r
+ \r
+ public Mesh create() {\r
+ if (vertices.size() < 2 )\r
+ throw new IllegalArgumentException("Tube must have at least two vertices");\r
+ \r
+ Vector3d t = new Vector3d();\r
+ \r
+ for (int i = 0; i < vertices.size() - 1; i++) {\r
+ t.set(vertices.get(i+1));\r
+ t.sub(vertices.get(i));\r
+ if (t.lengthSquared() < 0.0001)\r
+ throw new IllegalArgumentException("vertices at index " + i + " are too close to each other");\r
+ }\r
+ \r
+ List<Vector3d> points = new ArrayList<Vector3d>(vertices.size()*resolution);\r
+ List<Vector3d> normals = new ArrayList<Vector3d>(vertices.size()*resolution);\r
+ \r
+ for (int i = 0; i < vertices.size(); i++) {\r
+ createCircle(i,points,normals);\r
+ }\r
+ \r
+ int index[] = new int[(vertices.size()-1)*resolution*6];\r
+ \r
+ createIndices(index);\r
+ List<Integer> indices = new ArrayList<Integer>();\r
+ for (int i = 0; i < index.length; i++) {\r
+ indices.add(index[i]);\r
+ }\r
+ \r
+ \r
+ \r
+ vertices.clear();\r
+ if (colors != null)\r
+ colors.clear();\r
+ if (radiis != null)\r
+ radiis.clear();\r
+ \r
+ return new Mesh(points, normals, indices);\r
+ \r
+ }\r
+ \r
+ private void createCircle(int i, List<Vector3d> points, List<Vector3d> normals) {\r
+ final Vector3d up = new Vector3d(0,1,0);\r
+ final Vector3d up2 = new Vector3d(0,0,1);\r
+ Vector3d p = vertices.get(i);\r
+ Vector3d t = getTangent(i);\r
+ Vector3d n = new Vector3d();\r
+ if (up.dot(t) < 0.99) {\r
+ n.cross(up, t);\r
+ } else {\r
+ n.cross(up2, t);\r
+ }\r
+ n.normalize();\r
+ if (radiis != null) {\r
+ n.scale(radiis.get(i));\r
+ } else {\r
+ n.scale(radius);\r
+ }\r
+ \r
+ for (int index = 0; index < resolution; index ++) {\r
+ Vector3d v;\r
+ if (index == 0) {\r
+ v = new Vector3d(n);\r
+ \r
+ } else {\r
+ AxisAngle4d aa = new AxisAngle4d(t, (Math.PI * 2 * (double)index)/(double)resolution);\r
+ v = new Vector3d();\r
+ MathTools.rotate(MathTools.getQuat(aa), n, v);\r
+ }\r
+ //int vIndex = (i*resolution + index)*3;\r
+ Vector3d pt = new Vector3d(p);\r
+ pt.add(v);\r
+ //points.set(vIndex, pt);\r
+ points.add(pt);\r
+ v.normalize();\r
+ //normals.set(vIndex, v);\r
+ normals.add(v);\r
+ }\r
+ }\r
+ \r
+ private Vector3d getTangent(int i) {\r
+ Vector3d p,n;\r
+ if (i == 0) {\r
+ p = vertices.get(0);\r
+ n = vertices.get(1);\r
+ } else if (i == vertices.size() - 1) {\r
+ p = vertices.get(i-1);\r
+ n = vertices.get(i);\r
+ } else {\r
+ p = vertices.get(i-1);\r
+ n = vertices.get(i+1);\r
+ }\r
+ n = new Vector3d(n);\r
+ n.sub(p);\r
+ n.normalize();\r
+ return n;\r
+ }\r
+ \r
+ private void createIndices(int index[]) {\r
+ for (int c = 0; c < vertices.size() - 1; c++) {\r
+ for (int s = 0; s < resolution; s++) {\r
+ int ii = (c * resolution + s) * 6;\r
+ int iv = c*resolution + s;\r
+ \r
+ /*\r
+ iv+1 ---- iv + resolution + 1\r
+ | /|\r
+ |/ |\r
+ iv ---- iv + resolution \r
+ */\r
+ if (s < resolution - 1) {\r
+ index[ii+2] = iv;\r
+ index[ii+1] = iv+resolution;\r
+ index[ii+0] = iv+resolution+1;\r
+ \r
+ index[ii+5] = iv;\r
+ index[ii+4] = iv+resolution+1;\r
+ index[ii+3] = iv+1;\r
+ } else {\r
+ index[ii+2] = iv;\r
+ index[ii+1] = iv+resolution;\r
+ index[ii+0] = iv+1;\r
+ \r
+ index[ii+5] = iv;\r
+ index[ii+4] = iv+1;\r
+ index[ii+3] = iv+1-resolution;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.toolbar;\r
+\r
+import java.util.HashMap;\r
+import java.util.Map;\r
+\r
+import org.eclipse.core.commands.Command;\r
+import org.eclipse.core.commands.State;\r
+import org.eclipse.ui.IWorkbenchPart;\r
+import org.eclipse.ui.PlatformUI;\r
+import org.eclipse.ui.commands.ICommandService;\r
+import org.eclipse.ui.handlers.IHandlerService;\r
+import org.eclipse.ui.handlers.RadioState;\r
+import org.eclipse.ui.handlers.RegistryToggleState;\r
+\r
+/**\r
+ * Registry for storing command states separately for each IEditorPart\r
+ * \r
+ * TODO : how to change toggle/radios state from editor?\r
+ * TODO : how to update visible buttons (ToolbarContributor)\r
+ * \r
+ * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
+ *\r
+ */\r
+public class CommandStateRegistry {\r
+\r
+ \r
+ private static CommandStateRegistry instance;\r
+ \r
+ \r
+ public static CommandStateRegistry getInstance() {\r
+ if (instance == null)\r
+ instance = new CommandStateRegistry();\r
+ return instance;\r
+ }\r
+ \r
+ \r
+ \r
+ private Map<IWorkbenchPart,Map<String,Boolean>> toggleStates = new HashMap<IWorkbenchPart, Map<String,Boolean>>();\r
+ private Map<String,Boolean> defaultToggleStates = new HashMap<String, Boolean>();\r
+ \r
+ private Map<String,String> defaultRadioStates = new HashMap<String, String>();\r
+ private Map<IWorkbenchPart,Map<String,String>> radioStates = new HashMap<IWorkbenchPart, Map<String,String>>();\r
+\r
+ private ICommandService service;\r
+ private IHandlerService handlerService;\r
+ \r
+ private CommandStateRegistry() {\r
+ service = (ICommandService) PlatformUI.getWorkbench().getService(ICommandService.class);\r
+ handlerService = (IHandlerService) PlatformUI.getWorkbench().getService(IHandlerService.class);\r
+ }\r
+ \r
+ /**\r
+ * Stores default state for a command.\r
+ * \r
+ * Note: uses current state as default. \r
+ * \r
+ * @param commandId\r
+ */\r
+ public void storeDefaultState(String commandId) {\r
+ Command command = service.getCommand(commandId);\r
+ State toggleState = command.getState(RegistryToggleState.STATE_ID);\r
+ State radioState = command.getState(RadioState.STATE_ID);\r
+ if (toggleState != null) {\r
+ if (!defaultToggleStates.containsKey(commandId))\r
+ defaultToggleStates.put(commandId, getToggleState(command));\r
+ } else if (radioState != null) {\r
+ String value = (String) radioState.getValue();\r
+ if (!defaultRadioStates.containsKey(commandId))\r
+ defaultRadioStates.put(commandId, value);\r
+ } else {\r
+ throw new IllegalArgumentException("Command " + commandId + " does not have a state");\r
+ }\r
+ }\r
+ /**\r
+ * Stores toggle state of a command.\r
+ * @param part\r
+ * @param commandId\r
+ * @param checked\r
+ */\r
+ public void setEditorState(IWorkbenchPart part, String commandId, boolean checked) {\r
+ Map<String,Boolean> editorStates = toggleStates.get(part);\r
+ if (editorStates == null) {\r
+ editorStates = new HashMap<String, Boolean>();\r
+ toggleStates.put(part, editorStates);\r
+ }\r
+ editorStates.put(commandId, checked);\r
+ }\r
+ \r
+ /**\r
+ * Stores radio state of a command.\r
+ * @param part\r
+ * @param commandId\r
+ * @param value\r
+ */\r
+ public void setEditorState(IWorkbenchPart part, String commandId, String value) {\r
+ Map<String,String> editorStates = radioStates.get(part);\r
+ if (editorStates == null) {\r
+ editorStates = new HashMap<String, String>();\r
+ radioStates.put(part, editorStates);\r
+ }\r
+ editorStates.put(commandId, value);\r
+ }\r
+ \r
+ public Map<String, Boolean> getDefaultToggleStates() {\r
+ return defaultToggleStates;\r
+ }\r
+ \r
+ public Map<String, String> getDefaultRadioStates() {\r
+ return defaultRadioStates;\r
+ }\r
+ \r
+ public Map<String, Boolean> getEditorToggleStates(IWorkbenchPart part) {\r
+ return toggleStates.get(part);\r
+ }\r
+ \r
+ public Map<String, String> getEditorRadioStates(IWorkbenchPart part) {\r
+ return radioStates.get(part);\r
+ }\r
+ \r
+ public Boolean getToggleState(IWorkbenchPart part, String commandId) {\r
+ if (part == null)\r
+ return defaultToggleStates.get(commandId);\r
+ Map<String,Boolean> editorStates = toggleStates.get(part);\r
+ if (editorStates == null) {\r
+ return defaultToggleStates.get(commandId);\r
+ }\r
+ return editorStates.get(commandId);\r
+ }\r
+ \r
+ public String getRadioState(IWorkbenchPart part, String commandId) {\r
+ if (part == null)\r
+ return defaultRadioStates.get(commandId);\r
+ Map<String,String> editorStates = radioStates.get(part);\r
+ if (editorStates == null) {\r
+ return defaultRadioStates.get(commandId);\r
+ }\r
+ return editorStates.get(commandId);\r
+ }\r
+ \r
+ public void clearStates(IWorkbenchPart part) {\r
+ toggleStates.remove(part);\r
+ radioStates.remove(part);\r
+ }\r
+ \r
+ private boolean getToggleState(Command command) {\r
+ State toggleState = command.getState(RegistryToggleState.STATE_ID);\r
+ return (Boolean)toggleState.getValue();\r
+ }\r
+ \r
+ \r
+}\r
--- /dev/null
+package org.simantics.g3d.toolbar;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collections;\r
+import java.util.List;\r
+\r
+import org.eclipse.core.runtime.IConfigurationElement;\r
+import org.eclipse.core.runtime.IExtension;\r
+import org.eclipse.core.runtime.IExtensionPoint;\r
+import org.eclipse.core.runtime.Platform;\r
+import org.eclipse.core.runtime.dynamichelpers.ExtensionTracker;\r
+import org.eclipse.core.runtime.dynamichelpers.IExtensionChangeHandler;\r
+import org.eclipse.core.runtime.dynamichelpers.IExtensionTracker;\r
+import org.eclipse.core.runtime.dynamichelpers.IFilter;\r
+import org.simantics.g3d.Activator;\r
+\r
+\r
+\r
+\r
+\r
+public class ToolBarCommandRegistry implements IExtensionChangeHandler {\r
+ private final static String NAMESPACE = Activator.PLUGIN_ID;\r
+\r
+ private final static String EP_NAME = "toolbarCommand";\r
+ \r
+ private ExtensionTracker tracker;\r
+ \r
+ private List<ToolbarCommandExtension> extensions = new ArrayList<ToolbarCommandExtension>();\r
+ \r
+ \r
+ private static ToolBarCommandRegistry INSTANCE;\r
+ \r
+ public static synchronized ToolBarCommandRegistry getInstance() {\r
+ if (INSTANCE == null)\r
+ INSTANCE = new ToolBarCommandRegistry();\r
+ return INSTANCE;\r
+ }\r
+ \r
+ public static synchronized void dispose() {\r
+ if (INSTANCE != null) {\r
+ INSTANCE.close();\r
+ INSTANCE = null;\r
+ } \r
+ }\r
+ \r
+ public ToolBarCommandRegistry() {\r
+ tracker = new ExtensionTracker();\r
+ \r
+ IExtensionPoint ep = Platform.getExtensionRegistry().getExtensionPoint(NAMESPACE,EP_NAME);\r
+ loadExtensions(ep.getConfigurationElements());\r
+ \r
+ IFilter filter = ExtensionTracker.createExtensionPointFilter(ep);\r
+ tracker.registerHandler(this, filter);\r
+ }\r
+ \r
+ private void close() {\r
+ tracker.close();\r
+ tracker = null;\r
+ extensions.clear();\r
+ }\r
+ \r
+ public synchronized List<ToolbarCommandExtension> getExtensions() {\r
+ return Collections.unmodifiableList(extensions);\r
+ }\r
+ \r
+ private synchronized void loadExtensions(IConfigurationElement[] elements) {\r
+ for (IConfigurationElement el : elements) {\r
+ String commandId = el.getAttribute("commandId");\r
+ \r
+ ToolbarCommandExtension ext = new ToolbarCommandExtension(commandId);\r
+ ext.toolbarId = el.getAttribute("toolbarId");\r
+ ext.image = el.getAttribute("image");\r
+ ext.name = el.getAttribute("name");\r
+ ext.type = el.getAttribute("type");\r
+ ext.value = el.getAttribute("value");\r
+ ext.contributorId = el.getContributor().getName();\r
+ tracker.registerObject(el.getDeclaringExtension(), ext, IExtensionTracker.REF_STRONG);\r
+ extensions.add(ext);\r
+ \r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public void addExtension(IExtensionTracker tracker, IExtension extension) {\r
+ loadExtensions(extension.getConfigurationElements());\r
+ }\r
+ \r
+ @Override\r
+ public synchronized void removeExtension(IExtension extension, Object[] objects) {\r
+ for (Object o : objects) {\r
+ ToolbarCommandExtension ext = (ToolbarCommandExtension) o;\r
+ tracker.unregisterObject(extension, ext);\r
+ extensions.remove(ext);\r
+ }\r
+ }\r
+ \r
+ public synchronized List<ToolbarCommandExtension> getExtensions(String toolbarId) {\r
+ List<ToolbarCommandExtension> list = new ArrayList<ToolbarCommandExtension>();\r
+ for (ToolbarCommandExtension ext : extensions)\r
+ if (ext.toolbarId.equals(toolbarId))\r
+ list.add(ext);\r
+ return list;\r
+ \r
+ }\r
+ \r
+ public class ToolbarCommandExtension {\r
+ public String commandId;\r
+ public String toolbarId;\r
+ public String name;\r
+ public String type;\r
+ public String value;\r
+ public String image;\r
+ public String contributorId;\r
+ public ToolbarCommandExtension(String commandId) {\r
+ super();\r
+ this.commandId = commandId;\r
+ }\r
+ \r
+ @Override\r
+ public String toString() {\r
+ return "ToolbarCommandExtension, commandId= " + commandId + " toolbarId= " + toolbarId + " type= " + type + " value= " + value + " contributor= " + contributorId;\r
+ }\r
+ }\r
+ \r
+ \r
+}\r
--- /dev/null
+package org.simantics.g3d.toolbar;\r
+\r
+import java.util.ArrayList;\r
+import java.util.HashMap;\r
+import java.util.HashSet;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.Set;\r
+\r
+import org.eclipse.core.commands.Command;\r
+import org.eclipse.core.commands.CommandEvent;\r
+import org.eclipse.core.commands.ExecutionException;\r
+import org.eclipse.core.commands.ICommandListener;\r
+import org.eclipse.core.commands.State;\r
+import org.eclipse.jface.action.Action;\r
+import org.eclipse.jface.action.ActionContributionItem;\r
+import org.eclipse.jface.action.IContributionItem;\r
+import org.eclipse.jface.action.ICoolBarManager;\r
+import org.eclipse.jface.action.IToolBarManager;\r
+import org.eclipse.jface.action.ToolBarContributionItem;\r
+import org.eclipse.jface.resource.ImageDescriptor;\r
+import org.eclipse.nebula.widgets.tablecombo.TableCombo;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.events.SelectionEvent;\r
+import org.eclipse.swt.events.SelectionListener;\r
+import org.eclipse.swt.layout.GridData;\r
+import org.eclipse.swt.layout.GridLayout;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Control;\r
+import org.eclipse.swt.widgets.TableItem;\r
+import org.eclipse.ui.IEditorPart;\r
+import org.eclipse.ui.IPartListener;\r
+import org.eclipse.ui.IWorkbenchPart;\r
+import org.eclipse.ui.PlatformUI;\r
+import org.eclipse.ui.commands.ICommandService;\r
+import org.eclipse.ui.handlers.HandlerUtil;\r
+import org.eclipse.ui.handlers.IHandlerService;\r
+import org.eclipse.ui.handlers.RadioState;\r
+import org.eclipse.ui.handlers.RegistryToggleState;\r
+import org.eclipse.ui.menus.WorkbenchWindowControlContribution;\r
+import org.eclipse.ui.part.EditorActionBarContributor;\r
+import org.simantics.db.common.utils.ErrorLogger;\r
+import org.simantics.g3d.Activator;\r
+import org.simantics.g3d.toolbar.ToolBarCommandRegistry.ToolbarCommandExtension;\r
+import org.simantics.utils.datastructures.MapList;\r
+\r
+\r
+/**\r
+ * EditorBarContributor, which tracks toggle states separately for each command.\r
+ * \r
+ * @see org.simantics.g3d.toolbarCommand Extension Point\r
+ * \r
+ * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
+ * \r
+ * \r
+ * \r
+ * TODO : test radio buttons.\r
+ * TODO : configuring the position of buttons. \r
+ *\r
+ */\r
+public abstract class ToolbarContributor extends EditorActionBarContributor implements ICommandListener, IPartListener {\r
+\r
+ private static final String PLATFORM = "platform:/plugin/";\r
+ \r
+ private IEditorPart activePart;\r
+ private Set<IEditorPart> parts = new HashSet<IEditorPart>();\r
+ IToolBarManager mgr;\r
+ \r
+ \r
+ ICommandService service;\r
+ IHandlerService handlerService;\r
+ List<IContributionItem> items = new ArrayList<IContributionItem>();\r
+ MapList<String, CommandAction> actions = new MapList<String, ToolbarContributor.CommandAction>();\r
+ \r
+ CommandStateRegistry stateRegistry;\r
+ \r
+ private Map<String,ComboContribution> menus = new HashMap<String, ComboContribution>();\r
+ \r
+ public ToolbarContributor() {\r
+ service = (ICommandService) PlatformUI.getWorkbench().getService(ICommandService.class); \r
+ handlerService = (IHandlerService) PlatformUI.getWorkbench().getService(IHandlerService.class);\r
+ stateRegistry = CommandStateRegistry.getInstance();\r
+ }\r
+ \r
+ public abstract String getToolbarId();\r
+ \r
+ public void contributeToCoolBar(ICoolBarManager coolBarManager) {\r
+ IContributionItem toolBar = coolBarManager.find(getToolbarId());\r
+ if (toolBar instanceof ToolBarContributionItem)\r
+ mgr = ((ToolBarContributionItem) toolBar).getToolBarManager();\r
+ if (mgr == null)\r
+ return;\r
+ \r
+ createCommands();\r
+ \r
+ mgr.markDirty();\r
+ \r
+ }\r
+ \r
+ private void createCommands() {\r
+ for (ToolbarCommandExtension ext : ToolBarCommandRegistry.getInstance().getExtensions(getToolbarId())) {\r
+ addCommand(ext);\r
+ }\r
+ }\r
+ \r
+ private void addCommand(ToolbarCommandExtension ext) {\r
+ String commandId = ext.commandId;\r
+ Command command = service.getCommand(commandId);\r
+ \r
+ String type = ext.type;\r
+ \r
+ State toggleState = command.getState(RegistryToggleState.STATE_ID);\r
+ State radioState = command.getState(RadioState.STATE_ID);\r
+ \r
+ String name = ext.name;\r
+ \r
+ \r
+ ImageDescriptor image = getImage(ext);\r
+ \r
+ CommandAction a = null;\r
+ if (type.equals("toggle") && toggleState != null) {\r
+ a = new CommandCheckboxAction(command,name,image);\r
+\r
+ stateRegistry.storeDefaultState(commandId);\r
+ } else if (radioState != null && ext.value != null) {\r
+ stateRegistry.storeDefaultState(commandId);\r
+ if (type.equals("radio")) {\r
+ a = new CommandRadioAction(command,name,ext.value,image);\r
+ } else if (type.equals("combo")) {\r
+ a = new CommandRadioAction(command,name,ext.value,image);\r
+ ComboContribution combo = menus.get(commandId);\r
+ if (combo == null) {\r
+ combo = new ComboContribution();\r
+ menus.put(commandId, combo);\r
+ items.add(combo);\r
+ mgr.add(combo);\r
+ a.getCommand().addCommandListener(this);\r
+ }\r
+ actions.add(commandId,a);\r
+ combo.addAction(a);\r
+ return;\r
+ }\r
+ } else if (type.equals("push")) {\r
+ a = new CommandPushAction(command,name,image);\r
+ } else {\r
+ ErrorLogger.defaultLogError(ext + " is not valid.");\r
+ return;\r
+ }\r
+ a.getCommand().addCommandListener(this);\r
+ IContributionItem item = new ActionContributionItem(a);\r
+ actions.add(commandId,a);\r
+ items.add(item);\r
+ mgr.add(item);\r
+ }\r
+ \r
+ private ImageDescriptor getImage(ToolbarCommandExtension ext) {\r
+ ImageDescriptor image = null;\r
+ if (ext.image != null) {\r
+ String plugin = null;\r
+ String file = null;\r
+ if (ext.image.startsWith(PLATFORM)) {\r
+ String s = ext.image.substring(PLATFORM.length());\r
+ int i = s.indexOf("/");\r
+ plugin = s.substring(0,i);\r
+ file = s.substring(i+1);\r
+ } else {\r
+ plugin = ext.contributorId;\r
+ file = ext.image;\r
+ }\r
+ image = Activator.imageDescriptorFromPlugin(plugin, file);\r
+ }\r
+ return image;\r
+ }\r
+ \r
+\r
+ \r
+ @Override\r
+ public void commandChanged(CommandEvent commandEvent) {\r
+ if (commandEvent.isHandledChanged()||commandEvent.isEnabledChanged()) {\r
+ Command command = commandEvent.getCommand();\r
+ String commandId = command.getId();\r
+ for (CommandAction a : actions.getValues(commandId)) {\r
+ a.setEnabled(command.isHandled() && command.isEnabled());\r
+ }\r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public void setActiveEditor(IEditorPart targetEditor) {\r
+ if (targetEditor == activePart)\r
+ return;\r
+ setContext(targetEditor);\r
+ }\r
+ \r
+ private void setContext(IEditorPart part) {\r
+ this.activePart = part;\r
+ if (!parts.contains(activePart)) {\r
+ activePart.getSite().getPage().addPartListener(this);\r
+ }\r
+ if (part != null) {\r
+ for (String commandId : actions.getKeys()) {\r
+ for (CommandAction a : actions.getValues(commandId)) {\r
+ a.setEnabled(true);\r
+ }\r
+ }\r
+ updateActionBars(part);\r
+ } else {\r
+ for (String commandId : actions.getKeys()) {\r
+ for (CommandAction a : actions.getValues(commandId)) {\r
+ a.setEnabled(false);\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ private void updateActionBars(IEditorPart part) {\r
+ restoreActionStates();\r
+ part.getEditorSite().getActionBars().updateActionBars();\r
+ }\r
+ \r
+ @Override\r
+ public void dispose() {\r
+ if (mgr != null) {\r
+ for (IContributionItem item : items) {\r
+ mgr.remove(item);\r
+ item.dispose();\r
+ }\r
+ mgr.markDirty();\r
+ mgr.update(true);\r
+ if (activePart != null) {\r
+ activePart.getEditorSite().getActionBars().updateActionBars();\r
+ }\r
+ \r
+ for (String commandId : actions.getKeys()) {\r
+ for (CommandAction a : actions.getValues(commandId)) {\r
+ a.getCommand().removeCommandListener(this);\r
+ }\r
+ }\r
+ actions.clear();\r
+ }\r
+ \r
+ super.dispose();\r
+ activePart = null;\r
+ }\r
+ \r
+\r
+ private void storeRadioActionState(CommandRadioAction action, boolean checked) {\r
+ if (activePart == null)\r
+ return;\r
+ stateRegistry.setEditorState(activePart, action.getCommandId(), action.getValue());\r
+ }\r
+ \r
+ private void storeToggleActionState(CommandAction action, boolean checked) {\r
+ if (activePart == null)\r
+ return;\r
+ stateRegistry.setEditorState(activePart, action.getCommandId(), checked);\r
+ }\r
+ \r
+ private void restoreActionStates() {\r
+ if (activePart == null)\r
+ return;\r
+ // toggles\r
+ Map<String,Boolean> defaultToggleStates = stateRegistry.getDefaultToggleStates();\r
+ for (String commandId : defaultToggleStates.keySet()) {\r
+ for (CommandAction a : actions.getValues(commandId)) {\r
+ a.setChecked(defaultToggleStates.get(commandId));\r
+ }\r
+ }\r
+ Map<String,Boolean> editorStates = stateRegistry.getEditorToggleStates(activePart);//toggleStates.get(activePart);\r
+ if (editorStates != null) {\r
+ for (String commandId : editorStates.keySet()) {\r
+ for (CommandAction a : actions.getValues(commandId)) {\r
+ a.setChecked(editorStates.get(commandId));\r
+ }\r
+ }\r
+ }\r
+ // radios\r
+ Map<String,String> defaultRadioStates = stateRegistry.getDefaultRadioStates();\r
+ for (String commandId : defaultRadioStates.keySet()) {\r
+ String defaultValue = defaultRadioStates.get(commandId);\r
+ for (CommandAction a : actions.getValues(commandId)) {\r
+ CommandRadioAction r = (CommandRadioAction)a;\r
+ r.setChecked(r.getValue().equals(defaultValue));\r
+ }\r
+ }\r
+ \r
+ Map<String,String> editorRadioStates = stateRegistry.getEditorRadioStates(activePart);//radioStates.get(activePart);\r
+ if (editorRadioStates != null) {\r
+ for (String commandId : editorRadioStates.keySet()) {\r
+ String defaultValue = editorRadioStates.get(commandId);\r
+ for (CommandAction a : actions.getValues(commandId)) {\r
+ CommandRadioAction r = (CommandRadioAction)a;\r
+ r.setChecked(r.getValue().equals(defaultValue));\r
+ }\r
+ }\r
+ }\r
+ \r
+ for (ComboContribution c : menus.values()) {\r
+ c.updateSelection();\r
+ }\r
+ \r
+\r
+ }\r
+ \r
+ @Override\r
+ public void partActivated(IWorkbenchPart part) {\r
+\r
+ }\r
+ \r
+ @Override\r
+ public void partBroughtToTop(IWorkbenchPart part) {\r
+ \r
+ }\r
+ \r
+ @Override\r
+ public void partClosed(IWorkbenchPart part) {\r
+ parts.remove(part);\r
+ stateRegistry.clearStates(part);\r
+ part.getSite().getPage().removePartListener(this);\r
+ }\r
+ \r
+ @Override\r
+ public void partDeactivated(IWorkbenchPart part) {\r
+ \r
+ }\r
+ \r
+ @Override\r
+ public void partOpened(IWorkbenchPart part) {\r
+ \r
+ }\r
+ \r
+ private boolean getToggleState(Command command) {\r
+ State toggleState = command.getState(RegistryToggleState.STATE_ID);\r
+ return (Boolean)toggleState.getValue();\r
+ }\r
+ \r
+ private abstract class CommandAction extends Action {\r
+ private Command command;\r
+ \r
+ public CommandAction(Command command, String name, ImageDescriptor image, int style) {\r
+ super(name,style);\r
+ this.command = command;\r
+ if (image != null)\r
+ setImageDescriptor(image);\r
+ }\r
+ \r
+ @Override\r
+ public void run() {\r
+ try {\r
+ handlerService.executeCommand(command.getId(), null);\r
+ } catch (Exception e) {\r
+ e.printStackTrace();\r
+ }\r
+ }\r
+ \r
+ public Command getCommand() {\r
+ return command;\r
+ }\r
+ \r
+ public String getCommandId() {\r
+ return command.getId();\r
+ }\r
+ }\r
+ \r
+ private class CommandCheckboxAction extends CommandAction {\r
+ \r
+ public CommandCheckboxAction(Command command, String name, ImageDescriptor image) {\r
+ super(command,name,image,Action.AS_CHECK_BOX);\r
+ \r
+ }\r
+ \r
+ @Override\r
+ public void run() {\r
+ boolean checked = isChecked(); \r
+ storeToggleActionState(this, checked);\r
+ try {\r
+ if (checked == getToggleState(getCommand()))\r
+ HandlerUtil.toggleCommandState(getCommand());\r
+ } catch (ExecutionException e) {\r
+ e.printStackTrace();\r
+ }\r
+ super.run();\r
+ }\r
+ \r
+ }\r
+ \r
+ private class CommandRadioAction extends CommandAction {\r
+\r
+ private String value;\r
+ \r
+ public CommandRadioAction(Command command, String name, String value, ImageDescriptor image) {\r
+ super(command,name,image,Action.AS_RADIO_BUTTON);\r
+ this.value = value;\r
+ }\r
+ \r
+ @Override\r
+ public void run() {\r
+ boolean checked = isChecked(); \r
+ storeRadioActionState(this, checked);\r
+ try {\r
+ HandlerUtil.updateRadioState(getCommand(), value);\r
+ } catch (ExecutionException e) {\r
+ e.printStackTrace();\r
+ return;\r
+ }\r
+ super.run();\r
+ }\r
+ \r
+ public String getValue() {\r
+ return value;\r
+ }\r
+ \r
+ }\r
+\r
+ private class CommandPushAction extends CommandAction {\r
+ \r
+ public CommandPushAction(Command command, String name, ImageDescriptor image) {\r
+ super(command,name,image,Action.AS_PUSH_BUTTON);\r
+ }\r
+\r
+ }\r
+ \r
+ private class ComboContribution extends WorkbenchWindowControlContribution {\r
+ private TableCombo combo;\r
+ \r
+ private List<Action> actions = new ArrayList<Action>();\r
+ \r
+ @Override\r
+ protected Control createControl(Composite parent) {\r
+ Composite container = new Composite(parent, SWT.NONE);\r
+ GridLayout glContainer = new GridLayout(1, false);\r
+ glContainer.marginTop = 0;\r
+ glContainer.marginHeight = 0;\r
+ glContainer.marginWidth = 0;\r
+ container.setLayout(glContainer);\r
+ GridData glReader = new GridData(SWT.FILL, SWT.FILL, false, false, 1, 1);\r
+ combo = new TableCombo(container, SWT.BORDER | SWT.READ_ONLY);\r
+ combo.setLayoutData(glReader);\r
+\r
+ for (Action a : actions) {\r
+ TableItem item = new TableItem(combo.getTable(), SWT.NONE);\r
+ item.setText(a.getText());\r
+ if (a.getImageDescriptor() != null)\r
+ item.setImage(a.getImageDescriptor().createImage());\r
+ }\r
+ \r
+ combo.addSelectionListener(new SelectionListener() {\r
+ \r
+ @Override\r
+ public void widgetSelected(SelectionEvent e) {\r
+ int index = combo.getSelectionIndex();\r
+ if (index == -1)\r
+ return;\r
+ actions.get(index).run();\r
+ }\r
+ \r
+ @Override\r
+ public void widgetDefaultSelected(SelectionEvent e) {\r
+ \r
+ }\r
+ });\r
+ updateSelection();\r
+ return container;\r
+ }\r
+ \r
+ public void addAction(Action a) {\r
+ actions.add(a);\r
+ }\r
+ \r
+ void updateSelection() {\r
+ if (combo == null)\r
+ return;\r
+ for (int i = 0; i < actions.size(); i++) {\r
+ if (actions.get(i).isChecked()) {\r
+ combo.select(i);\r
+ return;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ \r
+}\r
--- /dev/null
+package org.simantics.g3d.tools;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.Collections;\r
+\r
+import org.eclipse.core.runtime.IAdaptable;\r
+import org.eclipse.jface.viewers.IStructuredSelection;\r
+import org.simantics.utils.Container;\r
+\r
+/**\r
+ * @author Antti Villberg\r
+ * @author Marko Luukkainen\r
+ * \r
+ * TODO: merge to os.ui.utils.\r
+ */\r
+public class AdaptationUtils {\r
+ /**\r
+ * \r
+ * @param o\r
+ * @param clazz\r
+ * @return object of given class or null\r
+ */\r
+ @SuppressWarnings("unchecked")\r
+ public static <T> T adaptToSingle(Object o, Class<T> clazz) {\r
+ if (o instanceof IStructuredSelection) {\r
+ IStructuredSelection iss = (IStructuredSelection) o;\r
+ if (iss.size() != 1)\r
+ return null;\r
+ Object element = iss.getFirstElement();\r
+ return adaptToSingle(element, clazz);\r
+ } else if (o instanceof Collection<?>) {\r
+ Collection<?> c = (Collection<?>) o;\r
+ if (c.size() != 1)\r
+ return null;\r
+ Object element = c.iterator().next();\r
+ return adaptToSingle(element, clazz);\r
+ } else if (o instanceof IAdaptable) {\r
+ IAdaptable a = (IAdaptable) o;\r
+ return (T)a.getAdapter(clazz);\r
+ } else if (clazz.isInstance(o)) {\r
+ return (T)o;\r
+ } else if (o instanceof Container<?>) {\r
+ Object obj = ((Container<?>) o).get();\r
+ if (obj == o)\r
+ return null;\r
+ return adaptToSingle(obj, clazz);\r
+ }\r
+ return null;\r
+ }\r
+ /**\r
+ * \r
+ * @param o\r
+ * @param clazz\r
+ * @return collection of objects of given class. \r
+ */\r
+ @SuppressWarnings("unchecked")\r
+ public static <T> Collection<T> adaptToCollection(Object o, Class<T> clazz) {\r
+ if (clazz.isInstance(o)) {\r
+ return Collections.singletonList((T)o);\r
+ } else if (o instanceof IStructuredSelection) {\r
+ IStructuredSelection iss = (IStructuredSelection) o;\r
+ return adaptToCollection(iss.toArray(), clazz);\r
+ } else if (o instanceof Collection<?>) {\r
+ Collection<?> c = (Collection<?>) o;\r
+ return adaptToCollection(c.toArray(), clazz);\r
+ } else if (o instanceof IAdaptable) {\r
+ IAdaptable a = (IAdaptable) o;\r
+ return Collections.singletonList((T)a.getAdapter(clazz));\r
+ } else if (o instanceof Container<?>) {\r
+ Object obj = ((Container<?>) o).get();\r
+ if (obj == o)\r
+ return Collections.EMPTY_LIST;\r
+ return adaptToCollection(obj, clazz);\r
+ }\r
+ return Collections.EMPTY_LIST;\r
+ }\r
+ \r
+ public static <T> Collection<T> adaptToCollection(Object arr[], Class<T> clazz) {\r
+ Collection<T> result = new ArrayList<T>();\r
+ for (Object o : arr) {\r
+ Collection<T> tColl = adaptToCollection(o, clazz); \r
+ for (T t : tColl)\r
+ if (t != null && !result.contains(t))\r
+ result.add(t);\r
+ }\r
+ return result;\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.g3d.tools;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import javax.vecmath.Point3d;\r
+import javax.vecmath.Vector3d;\r
+\r
+public class Constraint {\r
+ \r
+ public Constraint() {\r
+ points = new ArrayList<Point3d>();\r
+ dirs = new ArrayList<Vector3d>();\r
+ }\r
+ \r
+ public List<Point3d> points;\r
+ public List<Vector3d> dirs;\r
+\r
+}\r
+\r
--- /dev/null
+package org.simantics.g3d.tools;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import javax.vecmath.Point3d;\r
+import javax.vecmath.Vector3d;\r
+\r
+import org.simantics.g3d.math.MathTools;\r
+import org.simantics.g3d.scenegraph.IG3DNode;\r
+import org.simantics.g3d.shape.Color4d;\r
+\r
+public abstract class ConstraintDetector {\r
+ \r
+ private static final int X = 0;\r
+ private static final int Y = 1;\r
+ private static final int Z = 2;\r
+ \r
+ \r
+// private ThreeDimensionalEditorBase editor;\r
+ //private G3DNode constraintReference = null;\r
+ private IG3DNode constraintReference = null;\r
+ private ArrayList<Point3d> constraintPoints = new ArrayList<Point3d>();\r
+ private ArrayList<Vector3d> constraintDirections = new ArrayList<Vector3d>();\r
+// private MaterialState ms;\r
+ \r
+ private Color4d xColor = new Color4d(1.f,0.f,0.f,1.f);\r
+ private Color4d yColor = new Color4d(0.f,1.f,0.f,1.f);\r
+ private Color4d zColor = new Color4d(0.f,0.f,1.f,1.f);\r
+ \r
+ \r
+// public ConstraintDetector(ThreeDimensionalEditorBase editor) {\r
+// this.editor = editor;\r
+// ms = editor.getRenderingComponent().getDisplaySystem().getRenderer().createMaterialState();\r
+// ms.setEmissive(new ColorRGBA(1.f,1.f,1.f,1.f));\r
+// ms.setColorMaterial(MaterialState.CM_EMISSIVE);\r
+// }\r
+ \r
+\r
+ public void clearConstraints() {\r
+ //System.out.println("ConstraintDetector.clearConstraints()");\r
+ constraintPoints.clear();\r
+ constraintDirections.clear();\r
+ }\r
+ \r
+ private void updateConstraints() {\r
+ clearConstraints();\r
+ if (constraintReference == null)\r
+ return;\r
+ Constraint c = (Constraint)constraintReference.getAdapter(Constraint.class);\r
+ if (c == null)\r
+ return;\r
+ constraintPoints.addAll(c.points);\r
+ constraintDirections.addAll(c.dirs);\r
+ }\r
+ \r
+ \r
+ public ArrayList<Point3d> getConstraintPoints() {\r
+ return constraintPoints;\r
+ }\r
+ \r
+ public ArrayList<Vector3d> getConstraintDirections() {\r
+ return constraintDirections;\r
+ }\r
+\r
+ public void updateConstraintReference(IG3DNode node) {\r
+ if (constraintReference != null && !constraintReference.equals(node)) {\r
+ constraintReference = node;\r
+ updateConstraints();\r
+ } else if (node != null){\r
+ constraintReference = node;\r
+ updateConstraints();\r
+ }\r
+ \r
+ }\r
+ \r
+ public void addContraintPoint(Point3d p) {\r
+ //System.out.println("ConstraintDetector.addConstraintPoint() " + p);\r
+ constraintPoints.add(p);\r
+ }\r
+ \r
+ public void addContraintDirection(Vector3d v) {\r
+ //System.out.println("ConstraintDetector.addConstraintDirection() " + v);\r
+ constraintDirections.add(v);\r
+ }\r
+ \r
+ private double snapAngle = 0.1;\r
+ private String snapString = "";\r
+\r
+// private ArrayList<Geometry> constraintHighlights = new ArrayList<Geometry>();\r
+ \r
+ public Point3d getSnappedPoint(Vector3d pickPoint, Vector3d pickDir, Vector3d requestedPoint) {\r
+ \r
+ \r
+ Vector3d snappedPoint = new Vector3d();\r
+ Vector3d t = new Vector3d();\r
+ Point3d currentPoint = null;\r
+ // TODO : snap to closest angle\r
+ for (Vector3d constraintDir : constraintDirections) {\r
+ \r
+ MathTools.intersectStraightStraight(pickPoint,pickDir, requestedPoint, constraintDir, t, snappedPoint);\r
+ t.sub(snappedPoint);\r
+ if (t.lengthSquared() < snapAngle) {\r
+ \r
+ snapString += "Angle snap ";\r
+ currentPoint = new Point3d(snappedPoint);\r
+ break;\r
+ }\r
+ }\r
+ if (currentPoint != null) {\r
+ Vector3d dir = new Vector3d(currentPoint);\r
+ dir.sub(requestedPoint);\r
+ Point3d p = getPointSnap(requestedPoint, dir);\r
+ if (p != null)\r
+ currentPoint = p;\r
+ } else {\r
+ List<Double> distances = new ArrayList<Double>();\r
+ List<Point3d> snapPoints = new ArrayList<Point3d>();\r
+ List<String> snapStrings = new ArrayList<String>();\r
+ List<Color4d> snapColors = new ArrayList<Color4d>();\r
+ for (Point3d constraintPoint : constraintPoints) {\r
+ distances.clear();\r
+ snapPoints.clear();\r
+ snapStrings.clear();\r
+ MathTools.intersectStraightStraight(new Vector3d(constraintPoint), new Vector3d(1.0, 0.0, 0.0),\r
+ pickPoint, pickDir, snappedPoint, t);\r
+ t.sub(snappedPoint);\r
+ double distance = t.lengthSquared();\r
+ if (distance < snapAngle) {\r
+ distances.add(distance);\r
+ snapPoints.add(new Point3d(snappedPoint));\r
+ snapStrings.add("Point x-snap ");\r
+ snapColors.add(xColor);\r
+ }\r
+ MathTools.intersectStraightStraight(new Vector3d(constraintPoint), new Vector3d(0.0, 1.0, 0.0),\r
+ pickPoint, pickDir, snappedPoint, t);\r
+ t.sub(snappedPoint);\r
+ distance = t.lengthSquared();\r
+ if (distance < snapAngle) {\r
+ distances.add(distance);\r
+ snapPoints.add(new Point3d(snappedPoint));\r
+ snapStrings.add("Point y-snap ");\r
+ snapColors.add(yColor);\r
+ }\r
+ MathTools.intersectStraightStraight(new Vector3d(constraintPoint), new Vector3d(0.0, 0.0, 1.0),\r
+ pickPoint, pickDir, snappedPoint, t);\r
+ t.sub(snappedPoint);\r
+ distance = t.lengthSquared();\r
+ if (distance < snapAngle) {\r
+ distances.add(distance);\r
+ snapPoints.add(new Point3d(snappedPoint));\r
+ snapStrings.add("Point z-snap ");\r
+ snapColors.add(zColor);\r
+ \r
+ }\r
+ if (distances.size() > 0) {\r
+ if (distances.size() > 1) {\r
+ // more than one axes snape\r
+ Vector3d ref = MathTools.closestPointOnStraight(constraintPoint, new Point3d(pickPoint), pickDir);\r
+ ref.sub(constraintPoint);\r
+ distance = ref.lengthSquared();\r
+ if (distance < snapAngle) {\r
+ // we are close enought to point, so we'll just snap there\r
+ currentPoint = new Point3d(constraintPoint);\r
+ snapString += "Point snap ";\r
+ } else {\r
+ // select the closest of axes snap to\r
+ int min = 0;\r
+ for (int i = 1; i < distances.size(); i++) {\r
+ if (distances.get(i) < distances.get(min))\r
+ min = i;\r
+ }\r
+ currentPoint = snapPoints.get(min);\r
+ addConstrainLineHighlight(currentPoint, constraintPoint,snapColors.get(min));\r
+ snapString += snapStrings.get(min);\r
+ }\r
+ } else {\r
+ // only one of the axes snaps\r
+ currentPoint = snapPoints.get(0);\r
+ addConstrainLineHighlight(currentPoint, constraintPoint,snapColors.get(0));\r
+ snapString += snapStrings.get(0);\r
+ }\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ return currentPoint;\r
+\r
+ }\r
+ \r
+ public abstract void clearConstraintHighlights();\r
+ protected abstract void addConstrainLineHighlight(Point3d p1, Point3d p2, Color4d color);\r
+ protected abstract void addConstrainPlaneHighlight(Point3d p1, Point3d p2, int axis);\r
+ \r
+// public void clearConstraintHighlights() {\r
+// snapString = "";\r
+//\r
+// for (Geometry s : constraintHighlights)\r
+// s.removeFromParent();\r
+// \r
+// constraintHighlights.clear();\r
+// }\r
+// \r
+// private void addConstrainLineHighlight(Point3d p1, Point3d p2, Color4d color) {\r
+//\r
+// float coord[] = new float[6];\r
+// ColorRGBA colors[] = new ColorRGBA[2];\r
+// colors[0] = color;\r
+// colors[1] = color;\r
+// coord[0] = (float)p1.x;\r
+// coord[1] = (float)p1.y;\r
+// coord[2] = (float)p1.z;\r
+// coord[3] = (float)p2.x;\r
+// coord[4] = (float)p2.y;\r
+// coord[5] = (float)p2.z;\r
+// Line shape = new Line("",BufferUtils.createFloatBuffer(coord),null,BufferUtils.createFloatBuffer(colors),null);\r
+// editor.getRenderingComponent().getNoShadowRoot().attachChild(shape);\r
+// shape.setRenderState(ms);\r
+// constraintHighlights.add(shape);\r
+// }\r
+// \r
+// private void addConstrainPlaneHighlight(Point3d p1, Point3d p2, int axis) {\r
+//\r
+// float coord[] = new float[9];\r
+// ColorRGBA colors[] = new ColorRGBA[3];\r
+// coord[0] = (float)p1.x;\r
+// coord[1] = (float)p1.y;\r
+// coord[2] = (float)p1.z;\r
+// switch (axis) {\r
+// case X:\r
+// coord[3] = (float)p1.x;\r
+// coord[4] = (float)p1.y;\r
+// coord[5] = (float)p2.z;\r
+// colors[0] = colors[1] = colors[2] = xColor;\r
+// break;\r
+// case Y:\r
+// coord[3] = (float)p1.x;\r
+// coord[4] = (float)p1.y;\r
+// coord[5] = (float)p2.z;\r
+// colors[0] = colors[1] = colors[2] = yColor;\r
+// break;\r
+// case Z:\r
+// coord[3] = (float)p1.x;\r
+// coord[4] = (float)p2.y;\r
+// coord[5] = (float)p2.z;\r
+// colors[0] = colors[1] = colors[2] = zColor;\r
+// break;\r
+// \r
+// }\r
+// coord[6] = (float)p2.x;\r
+// coord[7] = (float)p2.y;\r
+// coord[8] = (float)p2.z;\r
+// Line shape = new Line("",BufferUtils.createFloatBuffer(coord),null,BufferUtils.createFloatBuffer(colors),null);\r
+// shape.setMode(Line.CONNECTED);\r
+// editor.getRenderingComponent().getNoShadowRoot().attachChild(shape);\r
+// shape.setRenderState(ms);\r
+// constraintHighlights.add(shape);\r
+// }\r
+ \r
+ /**\r
+ * Snaps position to axis-aligned planes defined by constraint points\r
+ * Form of position is p+v, meaning that the position that is snapped is requestedPoint + requestedDir\r
+ * @param requestedPoint one part of the position to be snapped\r
+ * @param requestedDir second part of the position to be snapped and direction that the position is allowed to move\r
+ * @return\r
+ */\r
+ public Point3d getPointSnap(Vector3d requestedPoint, Vector3d requestedDir) {\r
+ \r
+ Vector3d snappedPoint = new Vector3d();\r
+ Point3d currentPoint = null;\r
+ double u[] = new double[1];\r
+ List<Point3d> p1s = new ArrayList<Point3d>();\r
+ List<Point3d> p2s = new ArrayList<Point3d>();\r
+ List<Integer> axes = new ArrayList<Integer>();\r
+ \r
+ for (Point3d constraintPoint : constraintPoints) {\r
+ boolean snap = false;\r
+ \r
+ if (MathTools.intersectStraightPlane(requestedPoint, requestedDir, new Vector3d(constraintPoint), getAxialVector(X), snappedPoint,u) && Math.abs(1.0 - u[0]) < snapAngle) {\r
+ currentPoint = new Point3d(snappedPoint);\r
+ //snapString += "Point/Plane x-snap ";\r
+ snap = true;\r
+ //addConstrainPlaneHighlight(constraintPoint, currentPoint,X);\r
+ p1s.add(constraintPoint);\r
+ p2s.add(currentPoint);\r
+ axes.add(X);\r
+ }\r
+ \r
+ if (MathTools.intersectStraightPlane(requestedPoint, requestedDir, new Vector3d(constraintPoint), getAxialVector(Y), snappedPoint,u) && Math.abs(1.0 - u[0]) < snapAngle) {\r
+ currentPoint = new Point3d(snappedPoint);\r
+ //snapString += "Point/Plane y-snap ";\r
+ snap = true;\r
+ //addConstrainPlaneHighlight(constraintPoint, currentPoint,Y);\r
+ p1s.add(constraintPoint);\r
+ p2s.add(currentPoint);\r
+ axes.add(Y);\r
+ }\r
+ \r
+ if (MathTools.intersectStraightPlane(requestedPoint, requestedDir, new Vector3d(constraintPoint), getAxialVector(Z), snappedPoint,u) && Math.abs(1.0 - u[0]) < snapAngle) {\r
+ currentPoint = new Point3d(snappedPoint);\r
+ //snapString += "Point/Plane z-snap ";\r
+ snap = true;\r
+ //addConstrainPlaneHighlight(constraintPoint, currentPoint,Z);\r
+ p1s.add(constraintPoint);\r
+ p2s.add(currentPoint);\r
+ axes.add(Z);\r
+ }\r
+ if (snap)\r
+ break;\r
+ }\r
+ if (p1s.size() == 0)\r
+ return null;\r
+ if (p1s.size() == 1) {\r
+ snapString += "Point/Plane ";\r
+ switch (axes.get(0)) {\r
+ case X:\r
+ snapString += "x";\r
+ break;\r
+ case Y:\r
+ snapString += "y";\r
+ break;\r
+ case Z:\r
+ snapString += "z";\r
+ break;\r
+ }\r
+ snapString += "-snap ";\r
+ addConstrainPlaneHighlight(p1s.get(0), p2s.get(0),axes.get(0));\r
+ return currentPoint;\r
+ } else if (p1s.size() == 3){\r
+ // all axial planes are intersecting, snapping point must be the constraint point\r
+ // all constraint points are the same, so just pick the first in the list\r
+ snapString += "Point/Point ";\r
+ return p1s.get(0);\r
+ } else {\r
+ Vector3d dir = new Vector3d();\r
+ dir.cross(getAxialVector(axes.get(0)), getAxialVector(axes.get(1)));\r
+ currentPoint = new Point3d(MathTools.closestPointOnStraight(currentPoint, p1s.get(0), dir));\r
+ addConstrainLineHighlight(p1s.get(0), currentPoint, xColor);\r
+ snapString += "Point/Line ";\r
+ return currentPoint;\r
+ }\r
+ \r
+ }\r
+ \r
+ private Vector3d getAxialVector(int axis) {\r
+ switch (axis) {\r
+ case X:\r
+ return new Vector3d(1.0,0.0,0.0);\r
+ case Y:\r
+ return new Vector3d(0.0,1.0,0.0);\r
+ case Z:\r
+ return new Vector3d(0.0,0.0,1.0);\r
+ }\r
+ throw new RuntimeException("Unknown axis " + axis); \r
+ }\r
+ \r
+ /**\r
+ * Snaps the position to axis-aligned planes defined by constraint points\r
+ * @param requestedPoint point that is snapped\r
+ * @param requestedDir direction that point is allowed to move\r
+ * @return\r
+ */\r
+ \r
+ public Point3d getPointSnap2(Vector3d requestedPoint, Vector3d requestedDir) {\r
+ \r
+ Vector3d snappedPoint = new Vector3d();\r
+ Point3d currentPoint = null;\r
+ double u[] = new double[1];\r
+ //System.out.println(requestedPoint + " " + requestedDir);\r
+ for (Point3d constraintPoint : constraintPoints) {\r
+ boolean snap = false;\r
+ //System.out.print(constraintPoint + " ");\r
+ if (MathTools.intersectStraightPlane(requestedPoint, requestedDir, new Vector3d(constraintPoint), new Vector3d(1.0,0.0,0.0), snappedPoint,u) && Math.abs(u[0]) < snapAngle) {\r
+ currentPoint = new Point3d(snappedPoint);\r
+ snapString += "Point/Plane x-snap ";\r
+ snap = true;\r
+ addConstrainPlaneHighlight(constraintPoint, currentPoint,X);\r
+ //System.out.print(" x " + u[0]);\r
+ }\r
+ \r
+ if (MathTools.intersectStraightPlane(requestedPoint, requestedDir, new Vector3d(constraintPoint), new Vector3d(0.0,1.0,0.0), snappedPoint,u) && Math.abs(u[0]) < snapAngle) {\r
+ currentPoint = new Point3d(snappedPoint);\r
+ snapString += "Point/Plane y-snap ";\r
+ snap = true;\r
+ addConstrainPlaneHighlight(constraintPoint, currentPoint,Y);\r
+ //System.out.print(" y " + u[0]);\r
+ }\r
+ \r
+ \r
+ if (MathTools.intersectStraightPlane(requestedPoint, requestedDir, new Vector3d(constraintPoint), new Vector3d(0.0,0.0,1.0), snappedPoint,u) && Math.abs(u[0]) < snapAngle) {\r
+ currentPoint = new Point3d(snappedPoint);\r
+ snapString += "Point/Plane z-snap ";\r
+ snap = true;\r
+ addConstrainPlaneHighlight(constraintPoint, currentPoint,Z);\r
+ //System.out.print(" z " + u[0]);\r
+ }\r
+ //System.out.println();\r
+ if (snap)\r
+ break;\r
+ }\r
+ return currentPoint;\r
+ }\r
+ \r
+ public String getSnapString() {\r
+ return snapString;\r
+ }\r
+}
\ No newline at end of file
--- /dev/null
+package org.simantics.g3d.tools;\r
+\r
+import javax.vecmath.Point3d;\r
+\r
+import org.simantics.g3d.shape.Color4d;\r
+\r
+public class DummyConstraintDetector extends ConstraintDetector {\r
+ \r
+ @Override\r
+ protected void addConstrainLineHighlight(Point3d p1, Point3d p2, Color4d color) {\r
+ \r
+ }\r
+ \r
+ @Override\r
+ protected void addConstrainPlaneHighlight(Point3d p1, Point3d p2, int axis) {\r
+ \r
+ }\r
+ \r
+ @Override\r
+ public void clearConstraintHighlights() {\r
+ \r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.tools;\r
+\r
+import javax.vecmath.Matrix4d;\r
+import javax.vecmath.Quat4d;\r
+import javax.vecmath.Vector3d;\r
+\r
+import org.simantics.g3d.math.MathTools;\r
+import org.simantics.g3d.scenegraph.IG3DNode;\r
+\r
+public class NodeTools {\r
+\r
+ public static Vector3d getWorldPosition(IG3DNode node, Vector3d localPosition) {\r
+ Vector3d v = new Vector3d(localPosition);\r
+ MathTools.rotate(node.getOrientation(), v, v);\r
+ v.add(node.getPosition());\r
+ \r
+ IG3DNode parent = (IG3DNode)node.getParent();\r
+ if (parent == null)\r
+ return v;\r
+ return getWorldPosition(parent,v);\r
+ }\r
+ \r
+ public static Vector3d getWorldPosition(IG3DNode node) {\r
+ IG3DNode parent = (IG3DNode)node.getParent();\r
+ if (parent == null)\r
+ return node.getPosition();\r
+ return NodeTools.getWorldPosition(parent,new Vector3d(node.getPosition()));\r
+ }\r
+ \r
+ public static Quat4d getWorldOrientation(IG3DNode node, Quat4d localOrientation) {\r
+ Quat4d q = new Quat4d();\r
+ q.set(node.getOrientation());\r
+ Quat4d q2 = new Quat4d();\r
+ q2.set(localOrientation);\r
+ q.mul(q2);\r
+ \r
+ IG3DNode parent = (IG3DNode)node.getParent();\r
+ if (parent == null)\r
+ return q;\r
+ return getWorldOrientation(parent,q);\r
+ }\r
+ \r
+ public static Quat4d getWorldOrientation(IG3DNode node) {\r
+ IG3DNode parent = (IG3DNode)node.getParent();\r
+ if (parent == null)\r
+ return node.getOrientation();\r
+ return NodeTools.getWorldOrientation(parent, node.getOrientation());\r
+ }\r
+ \r
+ \r
+ public static Vector3d getLocalPosition(IG3DNode node, Vector3d worldCoord) {\r
+ \r
+ IG3DNode parent = (IG3DNode)node.getParent();\r
+ if (parent == null) {// this is a root node ( has no transformation) \r
+ return worldCoord;\r
+ }\r
+\r
+ Vector3d local = getLocalPosition(parent,worldCoord);\r
+ local.sub(node.getPosition());\r
+ \r
+ Quat4d q = new Quat4d();\r
+ q.set(node.getOrientation());\r
+ q.inverse();\r
+ MathTools.rotate(q, local, local);\r
+ \r
+ return local;\r
+ }\r
+ \r
+ public static Quat4d getLocalOrientation(IG3DNode node, Quat4d worldRot) {\r
+\r
+ IG3DNode parent = (IG3DNode) node.getParent();\r
+ if (parent == null) // this is a rootnode ( has no transformation)\r
+ return worldRot;\r
+ Quat4d local = getLocalOrientation(parent, worldRot);\r
+ Quat4d q = new Quat4d();\r
+ q.set(node.getOrientation());\r
+ q.inverse();\r
+ Quat4d q2 = new Quat4d();\r
+ q2.set(local);\r
+ q.mul(q2);\r
+ local.set(q);\r
+\r
+ return local;\r
+ }\r
+ \r
+ public static Matrix4d getWorldTransformation(IG3DNode node) {\r
+ Vector3d pos = node.getWorldPosition();\r
+ Quat4d q = node.getWorldOrientation();\r
+ \r
+ Matrix4d m1 = new Matrix4d();\r
+ Matrix4d m2 = new Matrix4d();\r
+ m1.set(pos);\r
+ m2.set(q);\r
+ m1.mul(m2);\r
+ return m1;\r
+ }\r
+ \r
+ public static Matrix4d getWorldOrientationMat(IG3DNode node) {\r
+ Quat4d q = node.getWorldOrientation();\r
+ \r
+ Matrix4d m2 = new Matrix4d();\r
+ m2.set(q);\r
+ return m2;\r
+ }\r
+ \r
+ public static Vector3d getPosition(IG3DNode relative, IG3DNode node) {\r
+ Vector3d wp = getWorldPosition(node);\r
+ return getLocalPosition(relative, wp);\r
+ }\r
+ \r
+ public static Quat4d getOrientation(IG3DNode relative, IG3DNode node) {\r
+ Quat4d wo = getWorldOrientation(node);\r
+ return getLocalOrientation(relative, wo);\r
+ }\r
+ \r
+ public static void setPosition(IG3DNode relative, IG3DNode node, Vector3d position) {\r
+ Vector3d wp = getWorldPosition(relative,position);\r
+ node.setWorldPosition(wp);\r
+ }\r
+ \r
+ public static void setOrientation(IG3DNode relative, IG3DNode node, Quat4d orientation) {\r
+ Quat4d wo = getWorldOrientation(relative,orientation);\r
+ node.setWorldOrientation(wo);\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.g3d.tools;\r
+\r
+import java.io.File;\r
+import java.net.URL;\r
+\r
+import org.eclipse.core.runtime.FileLocator;\r
+import org.eclipse.core.runtime.IPath;\r
+import org.eclipse.core.runtime.Path;\r
+import org.osgi.framework.Bundle;\r
+\r
+public class PluginTools {\r
+ \r
+ public static String getAbsolutePath(Bundle inBundle, String fullpath) {\r
+ IPath path = new Path(fullpath);\r
+ URL u = FileLocator.find(inBundle, path, null);\r
+ if (u != null) {\r
+ try {\r
+ u = FileLocator.resolve(u);\r
+ if ("file".equals(u.getProtocol())) {\r
+ return new File(u.getFile()).getAbsolutePath();\r
+ }\r
+ } catch (Exception e) {\r
+ }\r
+ }\r
+ return null;\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.ui;\r
+\r
+import org.eclipse.jface.layout.TreeColumnLayout;\r
+import org.eclipse.jface.viewers.CellLabelProvider;\r
+import org.eclipse.jface.viewers.ColumnWeightData;\r
+import org.eclipse.jface.viewers.TreeViewer;\r
+import org.eclipse.jface.viewers.TreeViewerColumn;\r
+import org.eclipse.jface.viewers.ViewerCell;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.ui.IPartListener2;\r
+import org.eclipse.ui.IPartService;\r
+import org.eclipse.ui.IWorkbenchPage;\r
+import org.eclipse.ui.IWorkbenchPart;\r
+import org.eclipse.ui.IWorkbenchPartReference;\r
+import org.eclipse.ui.IWorkbenchWindow;\r
+import org.eclipse.ui.part.ViewPart;\r
+import org.simantics.g3d.scenegraph.base.INode;\r
+import org.simantics.objmap.graph.IMapping;\r
+import org.simantics.objmap.structural.IStructuralObject;\r
+\r
+public class SceneGraphDebugger extends ViewPart {\r
+\r
+ private TreeViewer viewer;\r
+ \r
+ private boolean linkToPart = true;\r
+ \r
+ IWorkbenchPart lastPart;\r
+ \r
+ private IMapping<Object, Object> mapping;\r
+ \r
+ public SceneGraphDebugger() {\r
+ // TODO Auto-generated constructor stub\r
+ }\r
+\r
+ @Override\r
+ public void createPartControl(Composite parent) {\r
+\r
+ viewer = new TreeViewer(parent,SWT.SINGLE|SWT.FULL_SELECTION);\r
+\r
+ TreeColumnLayout layout = new TreeColumnLayout();\r
+ parent.setLayout(layout);\r
+ \r
+ viewer.setContentProvider(new ScenegraphOutlinePage.ScenegraphContentProvider());\r
+ viewer.getTree().setHeaderVisible(true);\r
+ \r
+ TreeViewerColumn nameColumn = new TreeViewerColumn(viewer, SWT.LEFT);\r
+ nameColumn.setLabelProvider(new CellLabelProvider() {\r
+ \r
+ @Override\r
+ public void update(ViewerCell cell) {\r
+ cell.setText(cell.getElement().toString());\r
+ }\r
+ });\r
+ \r
+ TreeViewerColumn typeColumn = new TreeViewerColumn(viewer, SWT.LEFT);\r
+ typeColumn.setLabelProvider(new CellLabelProvider() {\r
+ \r
+ @Override\r
+ public void update(ViewerCell cell) {\r
+ cell.setText(cell.getElement().getClass().getSimpleName());\r
+ }\r
+ });\r
+ \r
+ TreeViewerColumn contextColumn = new TreeViewerColumn(viewer, SWT.LEFT);\r
+ contextColumn.setLabelProvider(new CellLabelProvider() {\r
+ \r
+ @Override\r
+ public void update(ViewerCell cell) {\r
+ if (!(cell.getElement() instanceof IStructuralObject))\r
+ cell.setText("N/A");\r
+ else {\r
+ IStructuralObject o = (IStructuralObject)cell.getElement();\r
+ if (o.getContext() != null) {\r
+ cell.setText(o.getContext().toString());\r
+ } else {\r
+ cell.setText("none");\r
+ }\r
+ \r
+ }\r
+ \r
+ }\r
+ });\r
+ \r
+ TreeViewerColumn mappingColumn = new TreeViewerColumn(viewer, SWT.LEFT);\r
+ mappingColumn.setLabelProvider(new CellLabelProvider() {\r
+ \r
+ @Override\r
+ public void update(ViewerCell cell) {\r
+ if (mapping == null)\r
+ cell.setText("N/A");\r
+ else {\r
+ Object o = mapping.inverseGet(cell.getElement());\r
+ if (o != null) {\r
+ cell.setText(o.toString());\r
+ } else {\r
+ cell.setText("none");\r
+ }\r
+ \r
+ }\r
+ \r
+ }\r
+ });\r
+ \r
+ nameColumn.getColumn().setText("Name");\r
+ typeColumn.getColumn().setText("Type");\r
+ contextColumn.getColumn().setText("Context");\r
+ mappingColumn.getColumn().setText("Mapping");\r
+ \r
+ layout.setColumnData(nameColumn.getColumn(), new ColumnWeightData(10, true));\r
+ layout.setColumnData(typeColumn.getColumn(), new ColumnWeightData(10, true));\r
+ layout.setColumnData(contextColumn.getColumn(), new ColumnWeightData(10, true));\r
+ layout.setColumnData(mappingColumn.getColumn(), new ColumnWeightData(10, true));\r
+ \r
+ IPartService partService = (IPartService) getSite().getService(IPartService.class);\r
+ partService.addPartListener(partListener);\r
+ \r
+ }\r
+\r
+ @Override\r
+ public void setFocus() {\r
+ viewer.getTree().setFocus();\r
+ }\r
+ \r
+ protected void refresh() {\r
+ IWorkbenchPart part = null;\r
+ try {\r
+ IWorkbenchWindow window = getSite().getWorkbenchWindow();\r
+ if (window == null)\r
+ return;\r
+ IWorkbenchPage page = window.getActivePage();\r
+ if (page == null)\r
+ return;\r
+ part = page.getActiveEditor();\r
+ if (part == null)\r
+ return;\r
+ } finally {\r
+ if (part == null) {\r
+ setContentDescription("No scene graph nodes available.");\r
+ // TODO: Show info page instead of tree view.\r
+ }\r
+ }\r
+\r
+ refresh(part);\r
+ }\r
+ \r
+ @SuppressWarnings({ "unchecked", "rawtypes" })\r
+ protected boolean refresh(IWorkbenchPart part) {\r
+ if (viewer.getTree().isDisposed()) {\r
+ IPartService partService = (IPartService) getSite().getService(IPartService.class);\r
+ partService.removePartListener(partListener);\r
+ return false;\r
+ }\r
+ boolean foundInput = false;\r
+ try {\r
+ Object obj = null;\r
+ if (part != null) {\r
+ obj = part.getAdapter(INode.class);\r
+ }\r
+\r
+ if (obj != null) {\r
+ mapping = (IMapping)part.getAdapter(IMapping.class);\r
+ if (!viewer.getTree().isDisposed())\r
+ viewer.setInput(obj);\r
+ foundInput = true;\r
+ }\r
+ lastPart = part;\r
+ return foundInput;\r
+ } finally {\r
+ if (!foundInput) {\r
+ setContentDescription("No scene graph nodes available.");\r
+ // TODO: Show info page instead of tree view.\r
+ }\r
+ }\r
+ }\r
+ \r
+ IPartListener2 partListener = new IPartListener2() {\r
+ @Override\r
+ public void partVisible(IWorkbenchPartReference partRef) {\r
+ }\r
+ @Override\r
+ public void partOpened(IWorkbenchPartReference partRef) {\r
+ }\r
+ @Override\r
+ public void partInputChanged(IWorkbenchPartReference partRef) {\r
+ }\r
+ @Override\r
+ public void partHidden(IWorkbenchPartReference partRef) {\r
+ }\r
+ @Override\r
+ public void partDeactivated(IWorkbenchPartReference partRef) {\r
+ }\r
+ @Override\r
+ public void partClosed(IWorkbenchPartReference partRef) {\r
+ if (linkToPart) {\r
+ IWorkbenchPart part = partRef.getPart(false);\r
+ if (part != null)\r
+ refresh(null);\r
+ }\r
+ }\r
+ @Override\r
+ public void partBroughtToTop(IWorkbenchPartReference partRef) {\r
+ }\r
+ @Override\r
+ public void partActivated(IWorkbenchPartReference partRef) {\r
+ if (linkToPart) {\r
+ IWorkbenchPart part = partRef.getPart(false);\r
+ if (part != null) {\r
+ if (part != lastPart) {\r
+ refresh(part);\r
+ }\r
+ }\r
+ }\r
+ }\r
+ };\r
+\r
+}\r
--- /dev/null
+package org.simantics.g3d.ui;\r
+\r
+import java.util.HashSet;\r
+import java.util.Set;\r
+\r
+import org.eclipse.jface.viewers.ITreeContentProvider;\r
+import org.eclipse.jface.viewers.LabelProvider;\r
+import org.eclipse.jface.viewers.TreeViewer;\r
+import org.eclipse.jface.viewers.Viewer;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Display;\r
+import org.eclipse.ui.views.contentoutline.ContentOutlinePage;\r
+import org.simantics.g3d.scenegraph.base.INode;\r
+import org.simantics.g3d.scenegraph.base.NodeListener;\r
+import org.simantics.g3d.scenegraph.base.ParentNode;\r
+\r
+public class ScenegraphOutlinePage extends ContentOutlinePage implements NodeListener {\r
+ \r
+ private ParentNode<? extends INode> rootNode;\r
+ \r
+ public ScenegraphOutlinePage(ParentNode<? extends INode> rootNode) {\r
+ if (rootNode == null)\r
+ throw new NullPointerException();\r
+ this.rootNode = rootNode;\r
+ }\r
+\r
+ \r
+ @Override\r
+ public void createControl(Composite parent) {\r
+ super.createControl(parent);\r
+ if (rootNode == null)\r
+ return;\r
+ TreeViewer viewer = getTreeViewer();\r
+ createProviders(viewer);\r
+ viewer.setInput(rootNode);\r
+ listen(rootNode);\r
+ }\r
+ \r
+ protected void createProviders(TreeViewer viewer) {\r
+ viewer.setContentProvider(new ScenegraphContentProvider());\r
+ viewer.setLabelProvider(new ScenegraphLabelProvider());\r
+ }\r
+ \r
+ \r
+ \r
+ @SuppressWarnings("unchecked")\r
+ protected void listen(INode node) {\r
+ node.addListener(this);\r
+ if (node instanceof ParentNode<?>) {\r
+ ParentNode<INode> parentNode = (ParentNode<INode>)node;\r
+ for (INode n : parentNode.getNodes())\r
+ listen(n);\r
+ }\r
+ }\r
+ \r
+ @SuppressWarnings("unchecked")\r
+ protected void stopListening(INode node) {\r
+ node.removeListener(this);\r
+ if (node instanceof ParentNode<?>) {\r
+ ParentNode<INode> parentNode = (ParentNode<INode>)node;\r
+ for (INode n : parentNode.getNodes())\r
+ stopListening(n);\r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public void propertyChanged(INode node, String id) {\r
+ refershViewer(node);\r
+ }\r
+ \r
+ @Override\r
+ public <T extends INode> void nodeAdded(ParentNode<T> node, INode child,\r
+ String rel) {\r
+ listen(child);\r
+ refershViewer(node);\r
+ }\r
+ \r
+ \r
+ \r
+ @Override\r
+ public <T extends INode> void nodeRemoved(ParentNode<T> node, INode child,\r
+ String rel) {\r
+ stopListening(child);\r
+ refershViewer(node);\r
+ }\r
+ \r
+ //private Queue<INode> toRefresh = new LinkedList<INode>();\r
+ private Set<INode> toRefresh = new HashSet<INode>();\r
+ private NodeUpdater updater;\r
+ \r
+ protected void refershViewer(final INode node) {\r
+ if (getTreeViewer() == null)\r
+ return;\r
+ synchronized (toRefresh) {\r
+ toRefresh.add(node);\r
+ if (updater != null)\r
+ return;\r
+ }\r
+ \r
+ updater = new NodeUpdater();\r
+ Display.getDefault().asyncExec(updater);\r
+ }\r
+ \r
+ private class NodeUpdater implements Runnable {\r
+ @Override\r
+ public void run() {\r
+ if (getTreeViewer().getTree().isDisposed()) {\r
+ updater =null;\r
+ return;\r
+ }\r
+ int count = 0;\r
+ // limit the amount of refreshes.\r
+ while (count < 100) {\r
+ INode node = null;\r
+ synchronized (toRefresh) {\r
+ // if the queue becomes too long, refresh the whole tree\r
+// if (toRefresh.size() > 100) {\r
+// toRefresh.clear();\r
+// getTreeViewer().refresh();\r
+// updater = null;\r
+// return;\r
+// }\r
+ \r
+ //node = toRefresh.poll();\r
+ if (toRefresh.size() > 0) {\r
+ node = toRefresh.iterator().next();\r
+ toRefresh.remove(node);\r
+ }\r
+ if (node == null) {\r
+ updater = null;\r
+ return;\r
+ }\r
+ }\r
+ getTreeViewer().refresh(node);\r
+ count++;\r
+ }\r
+ if (toRefresh.size() > 0) {\r
+ Display.getDefault().asyncExec(this);\r
+ }\r
+ }\r
+ }\r
+ \r
+ public static class ScenegraphContentProvider implements ITreeContentProvider {\r
+ \r
+ public ScenegraphContentProvider() {\r
+ \r
+ }\r
+ \r
+ @Override\r
+ public Object[] getChildren(Object parentElement) {\r
+ if (parentElement instanceof ParentNode<?>) {\r
+ ParentNode<?> parentNode = (ParentNode<?>)parentElement;\r
+ return parentNode.getNodes().toArray();\r
+ }\r
+ return new Object[0];\r
+ }\r
+ \r
+ @Override\r
+ public Object[] getElements(Object inputElement) {\r
+ return getChildren(inputElement);\r
+ }\r
+ \r
+ @Override\r
+ public Object getParent(Object element) {\r
+ if (element instanceof INode) {\r
+ INode node = (INode) element;\r
+ return node.getParent();\r
+ }\r
+ return null;\r
+ }\r
+ \r
+ @Override\r
+ public boolean hasChildren(Object element) {\r
+ if (element instanceof ParentNode<?>) {\r
+ ParentNode<?> parentNode = (ParentNode<?>)element;\r
+ return parentNode.getNodes().size() > 0;\r
+ }\r
+ return false;\r
+ }\r
+ \r
+ @Override\r
+ public void dispose() {\r
+ \r
+ }\r
+ \r
+ @Override\r
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {\r
+ \r
+ }\r
+ }\r
+ \r
+ public class ScenegraphLabelProvider extends LabelProvider {\r
+ \r
+ }\r
+}\r
--- /dev/null
+package org.simantics.g3d.wizard;\r
+\r
+import java.io.File;\r
+import java.util.Deque;\r
+\r
+import org.simantics.db.common.NamedResource;\r
+\r
+public abstract class IExportModel {\r
+ \r
+ File exportLocation;\r
+ NamedResource model;\r
+ boolean overwrite;\r
+ \r
+ Deque<String> recentLocations;\r
+ \r
+ Object selection;\r
+ \r
+ public void setModel(NamedResource model) {\r
+ this.model = model;\r
+ }\r
+ \r
+ public NamedResource getModel() {\r
+ return model;\r
+ }\r
+ \r
+ public void setOverwrite(boolean overwrite) {\r
+ this.overwrite = overwrite;\r
+ }\r
+ \r
+ public boolean isOverwrite() {\r
+ return overwrite;\r
+ }\r
+\r
+ \r
+ public void setExportLocation(File exportLocation) {\r
+ this.exportLocation = exportLocation;\r
+ }\r
+ \r
+ public File getExportLocation() {\r
+ return exportLocation;\r
+ }\r
+ \r
+ public abstract boolean usesFile();\r
+ \r
+ public Deque<String> getRecentLocations() {\r
+ return recentLocations;\r
+ }\r
+ \r
+ public void setRecentLocations(Deque<String> recentLocations) {\r
+ this.recentLocations = recentLocations;\r
+ }\r
+ \r
+ public Object getSelection() {\r
+ return selection;\r
+ }\r
+ \r
+ public void setSelection(Object selection) {\r
+ this.selection = selection;\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.g3d.wizard;\r
+\r
+import java.io.File;\r
+import java.io.IOException;\r
+import java.lang.reflect.InvocationTargetException;\r
+import java.util.Deque;\r
+import java.util.Iterator;\r
+import java.util.LinkedList;\r
+import java.util.Set;\r
+import java.util.TreeSet;\r
+\r
+import org.eclipse.jface.dialogs.MessageDialog;\r
+import org.eclipse.jface.operation.IRunnableWithProgress;\r
+import org.eclipse.jface.preference.IPersistentPreferenceStore;\r
+import org.eclipse.jface.preference.IPreferenceStore;\r
+import org.eclipse.jface.viewers.IStructuredSelection;\r
+import org.eclipse.jface.wizard.Wizard;\r
+import org.eclipse.jface.wizard.WizardPage;\r
+import org.eclipse.ui.IExportWizard;\r
+import org.eclipse.ui.IMemento;\r
+import org.eclipse.ui.IWorkbench;\r
+import org.simantics.db.management.ISessionContext;\r
+import org.simantics.project.IProject;\r
+import org.simantics.project.ProjectKeys;\r
+import org.simantics.ui.SimanticsUI;\r
+import org.simantics.utils.ui.ErrorLogger;\r
+import org.simantics.utils.ui.ExceptionUtils;\r
+import org.simantics.utils.ui.workbench.StringMemento;\r
+\r
+public abstract class ModelExportWizard<T extends IExportModel> extends Wizard implements IExportWizard {\r
+ \r
+ private static final int MAX_RECENT_EXPORT_PATHS = 10;\r
+ Deque<String> recentExportPaths;\r
+ boolean overwrite;\r
+ \r
+ T exportModel;\r
+ \r
+ protected abstract T createExportModel(Deque<String> recentExportPaths);\r
+ \r
+ protected abstract ModelExportWizardPage<T> createExportPage(T exportModel);\r
+ \r
+ protected abstract IPersistentPreferenceStore getPreferenceStore();\r
+ \r
+ protected abstract IRunnableWithProgress createExportRunnable(T exportModel);\r
+ \r
+ protected abstract String getExportLocationId();\r
+ protected abstract String getExportOverwriteId();\r
+ \r
+ @Override\r
+ public void init(IWorkbench workbench, IStructuredSelection selection) {\r
+ readPreferences();\r
+\r
+ ISessionContext ctx = SimanticsUI.getSessionContext();\r
+ if (ctx == null)\r
+ return;\r
+ IProject project = ctx.getHint(ProjectKeys.KEY_PROJECT);\r
+ if (project == null)\r
+ return;\r
+ \r
+ exportModel = createExportModel(recentExportPaths);\r
+ exportModel.setSelection(selection.getFirstElement());\r
+ exportModel.setOverwrite(overwrite);\r
+ }\r
+ \r
+ @Override\r
+ public void addPages() {\r
+ super.addPages();\r
+ if (exportModel != null) {\r
+ addPage(createExportPage(exportModel));\r
+ }\r
+ }\r
+ \r
+ \r
+ \r
+ @Override\r
+ public boolean performFinish() {\r
+ try {\r
+ recentExportPaths.addFirst(exportModel.getExportLocation().getAbsolutePath());\r
+ removeDuplicates(recentExportPaths);\r
+ if (recentExportPaths.size() > MAX_RECENT_EXPORT_PATHS)\r
+ recentExportPaths.pollLast();\r
+\r
+ writePreferences();\r
+ } catch (IOException e) {\r
+ ErrorLogger.defaultLogError("Failed to write preferences", e);\r
+ }\r
+ \r
+ if (exportModel.usesFile()) {\r
+\r
+ File outputFile = exportModel.getExportLocation();\r
+ \r
+ if (outputFile.exists()) {\r
+ if (!outputFile.isFile()) {\r
+ MessageDialog.openError(getShell(), "File Problem", "Output target is not a file " + outputFile.getAbsolutePath());\r
+ return false;\r
+ }\r
+ if (!exportModel.isOverwrite()) {\r
+ boolean ok = MessageDialog.openConfirm(getShell(), "Overwrite", "A file by the name " + outputFile.getAbsolutePath() + " contains files.\n\nDo you want to overwrite the files?");\r
+ if (!ok) {\r
+ return false;\r
+ }\r
+ if (!outputFile.delete()) {\r
+ MessageDialog.openError(getShell(), "Delete Problem", "Could not overwrite previously existing file " + outputFile.getAbsolutePath());\r
+ return false;\r
+ }\r
+ }\r
+ } \r
+ } else {\r
+ File outputFolder = exportModel.getExportLocation();\r
+ \r
+ if (outputFolder.exists()) {\r
+ if (!outputFolder.isDirectory()) {\r
+ MessageDialog.openError(getShell(), "Folder Problem", "Output target is not a folder " + outputFolder.getAbsolutePath());\r
+ return false;\r
+ }\r
+ String files[] = outputFolder.list();\r
+ if (files.length > 0) {\r
+ if (!exportModel.isOverwrite()) {\r
+ boolean ok = MessageDialog.openConfirm(getShell(), "Overwrite", "A folder by the name " + outputFolder.getAbsolutePath() + " contains files.\n\nDo you want to overwrite the files?");\r
+ if (!ok) {\r
+ return false;\r
+ }\r
+ }\r
+ }\r
+\r
+ } else {\r
+ if (!outputFolder.mkdir()) {\r
+ MessageDialog.openError(getShell(), "Folder Problem", "Could not create new folder " + outputFolder);\r
+ return false;\r
+ }\r
+ }\r
+ }\r
+\r
+ try {\r
+ getContainer().run(true, true,createExportRunnable(exportModel));\r
+ } catch (InvocationTargetException e) {\r
+ Throwable t = e.getTargetException();\r
+ WizardPage cp = (WizardPage) getContainer().getCurrentPage();\r
+ if (t instanceof IOException) {\r
+ ErrorLogger.defaultLogError("An I/O problem occurred while exporting the model. See exception for details.", t);\r
+ cp.setErrorMessage("An I/O problem occurred while exporting the model.\n\nMessage: " + e.getMessage());\r
+ } else {\r
+ ErrorLogger.defaultLogError("Unexpected exception while exporting the model. See exception for details.", t);\r
+ cp.setErrorMessage("Unexpected exception while exporting the model. See error log for details.\n\nMessage: " + e.getMessage());\r
+ }\r
+ return false;\r
+ } catch (InterruptedException e) {\r
+ ExceptionUtils.logAndShowError(e);\r
+ return false;\r
+ }\r
+\r
+ return true;\r
+ }\r
+ \r
+ \r
+ \r
+ \r
+ private boolean readPreferences() {\r
+ IPreferenceStore store = getPreferenceStore();\r
+\r
+ String recentPathsPref = store.getString(getExportLocationId());\r
+ recentExportPaths = decodePaths(recentPathsPref);\r
+ overwrite = store.getBoolean(getExportOverwriteId());\r
+\r
+ return true;\r
+ }\r
+ \r
+ private void writePreferences() throws IOException {\r
+ IPersistentPreferenceStore store = getPreferenceStore();\r
+\r
+ store.putValue(getExportLocationId(), encodePaths(recentExportPaths));\r
+ store.setValue(getExportOverwriteId(), exportModel.isOverwrite());\r
+\r
+ if (store.needsSaving())\r
+ store.save();\r
+ }\r
+ \r
+ private static final String TAG_PATH = "path";\r
+ private static final String ATTR_NAME = "name";\r
+ \r
+ \r
+ public static Deque<String> decodePaths(String recentPathsPref) {\r
+ Deque<String> result = new LinkedList<String>();\r
+ try {\r
+ StringMemento sm = new StringMemento(recentPathsPref);\r
+ for (IMemento m : sm.getChildren(TAG_PATH)) {\r
+ String name = m.getString(ATTR_NAME);\r
+ if (name != null && !name.isEmpty())\r
+ result.add(name);\r
+ }\r
+ } catch (IllegalArgumentException e) {\r
+ }\r
+ return result;\r
+ }\r
+ \r
+ public static String encodePaths(Deque<String> recentPaths) {\r
+ StringMemento sm = new StringMemento();\r
+ for (String path : recentPaths) {\r
+ IMemento m = sm.createChild(TAG_PATH);\r
+ m.putString(ATTR_NAME, path);\r
+ }\r
+ return sm.toString();\r
+ }\r
+ \r
+ public static <T> void removeDuplicates(Iterable<String> iter) {\r
+ // Remove duplicates\r
+ Set<String> dups = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);\r
+ for (Iterator<String> it = iter.iterator(); it.hasNext();) {\r
+ String path = it.next();\r
+ if (!dups.add(path)) {\r
+ it.remove();\r
+ }\r
+ }\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.g3d.wizard;\r
+\r
+import java.io.File;\r
+import java.util.ArrayList;\r
+import java.util.Collections;\r
+import java.util.List;\r
+\r
+import org.eclipse.jface.layout.GridDataFactory;\r
+import org.eclipse.jface.resource.ImageDescriptor;\r
+import org.eclipse.jface.wizard.WizardPage;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.custom.CCombo;\r
+import org.eclipse.swt.events.ModifyEvent;\r
+import org.eclipse.swt.events.ModifyListener;\r
+import org.eclipse.swt.events.SelectionAdapter;\r
+import org.eclipse.swt.events.SelectionEvent;\r
+import org.eclipse.swt.layout.GridData;\r
+import org.eclipse.swt.layout.GridLayout;\r
+import org.eclipse.swt.widgets.Button;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.DirectoryDialog;\r
+import org.eclipse.swt.widgets.FileDialog;\r
+import org.eclipse.swt.widgets.Label;\r
+import org.simantics.Simantics;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.common.NamedResource;\r
+import org.simantics.db.common.request.ReadRequest;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.ui.utils.ResourceAdaptionUtils;\r
+\r
+\r
+public abstract class ModelExportWizardPage<T extends IExportModel> extends WizardPage{\r
+ T exportData;\r
+\r
+ CCombo model;\r
+ CCombo exportLocation;\r
+ \r
+ boolean exportToFile = true;\r
+\r
+ private List<NamedResource> models = new ArrayList<NamedResource>();\r
+\r
+ private Button overwrite;\r
+ \r
+ \r
+ \r
+ public ModelExportWizardPage(String pageName, String title, ImageDescriptor titleImage, T data) {\r
+ super(pageName, title, titleImage);\r
+ this.exportData = data;\r
+ exportToFile = data.usesFile();\r
+ }\r
+ \r
+ protected abstract List<NamedResource> getSupportedModels(ReadGraph graph, Resource project) throws DatabaseException;\r
+ \r
+ public String[] getFilterExtensions() {\r
+ return new String[0];\r
+ }\r
+ \r
+ public String[] getFilterNames() {\r
+ return new String[0];\r
+ }\r
+\r
+ @Override\r
+ public void createControl(Composite parent) {\r
+ Composite container = new Composite(parent, SWT.NONE);\r
+ {\r
+ GridLayout layout = new GridLayout();\r
+ layout.horizontalSpacing = 20;\r
+ layout.verticalSpacing = 10;\r
+ layout.numColumns = 3;\r
+ container.setLayout(layout);\r
+ }\r
+\r
+ new Label(container, SWT.NONE).setText("Exported &model:");\r
+ model = new CCombo(container, SWT.BORDER);\r
+ {\r
+ model.setEditable(false);\r
+ model.setText("");\r
+ model.setToolTipText("Selects the model to export.");\r
+ GridDataFactory.fillDefaults().grab(true, false).span(2, 1).applyTo(model);\r
+ model.addSelectionListener(new SelectionAdapter() {\r
+ @Override\r
+ public void widgetSelected(SelectionEvent e) {\r
+ exportData.setModel(((NamedResource) model.getData(Integer.toString(model.getSelectionIndex()))));\r
+ validatePage();\r
+ }\r
+ });\r
+\r
+ }\r
+ if (exportToFile) {\r
+ new Label(container, SWT.NONE).setText("&Target file:");\r
+ exportLocation = new CCombo(container, SWT.BORDER);\r
+ {\r
+ exportLocation.setText("");\r
+ GridDataFactory.fillDefaults().grab(true, false).span(1, 1).applyTo(exportLocation);\r
+ exportLocation.addModifyListener(new ModifyListener(){\r
+ @Override\r
+ public void modifyText(ModifyEvent e) {\r
+ validatePage();\r
+ }\r
+ });\r
+ }\r
+ Button browseFileButton = new Button(container, SWT.PUSH);\r
+ {\r
+ browseFileButton.setText("Browse...");\r
+ browseFileButton.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));\r
+ browseFileButton.addSelectionListener(new SelectionAdapter() {\r
+ @Override\r
+ public void widgetSelected(SelectionEvent e) {\r
+ FileDialog dialog = new FileDialog(getShell(), SWT.SAVE);\r
+ dialog.setText("Choose Export Target File");\r
+ dialog.setFilterExtensions(getFilterExtensions());\r
+ dialog.setFilterNames(getFilterNames());\r
+ String loc = exportLocation.getText();\r
+ dialog.setFilterPath(loc);\r
+ String file = dialog.open();\r
+ if (file == null)\r
+ return;\r
+ exportLocation.setText(file);\r
+ validatePage();\r
+ }\r
+ });\r
+ }\r
+\r
+ \r
+\r
+ \r
+ } else {\r
+ new Label(container, SWT.NONE).setText("&Target folder:");\r
+ exportLocation = new CCombo(container, SWT.BORDER);\r
+ {\r
+ exportLocation.setText("");\r
+ GridDataFactory.fillDefaults().grab(true, false).span(1, 1).applyTo(exportLocation);\r
+ exportLocation.addModifyListener(new ModifyListener(){\r
+ @Override\r
+ public void modifyText(ModifyEvent e) {\r
+ validatePage();\r
+ }\r
+ });\r
+ }\r
+ Button browseFileButton = new Button(container, SWT.PUSH);\r
+ {\r
+ browseFileButton.setText("Browse...");\r
+ browseFileButton.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));\r
+ browseFileButton.addSelectionListener(new SelectionAdapter() {\r
+ @Override\r
+ public void widgetSelected(SelectionEvent e) {\r
+ DirectoryDialog dialog = new DirectoryDialog(getShell(), SWT.SAVE);\r
+ dialog.setText("Choose Export Target Folder");\r
+ String loc = exportLocation.getText();\r
+ dialog.setFilterPath(loc);\r
+ String file = dialog.open();\r
+ if (file == null)\r
+ return;\r
+ exportLocation.setText(file);\r
+ validatePage();\r
+ }\r
+ });\r
+ }\r
+ }\r
+ \r
+ Label horizRule = new Label(container, SWT.BORDER);\r
+ GridDataFactory.fillDefaults().hint(SWT.DEFAULT, 0).grab(true, false).span(3, 1).applyTo(horizRule);\r
+ \r
+ overwrite = new Button(container, SWT.CHECK);\r
+ overwrite.setText("&Overwrite existing files without warning");\r
+ overwrite.setSelection(exportData.isOverwrite());\r
+ GridDataFactory.fillDefaults().grab(true, false).span(3, 1).applyTo(overwrite);\r
+ overwrite.addSelectionListener(new SelectionAdapter() {\r
+ @Override\r
+ public void widgetSelected(SelectionEvent e) {\r
+ validatePage();\r
+ }\r
+ });\r
+\r
+ try {\r
+ initializeData();\r
+ } catch (DatabaseException e) {\r
+ e.printStackTrace();\r
+ }\r
+\r
+ setControl(container);\r
+ validatePage();\r
+ \r
+ }\r
+ \r
+\r
+ \r
+ \r
+ protected void initializeData() throws DatabaseException {\r
+ final Resource selection = ResourceAdaptionUtils.toSingleResource(exportData.getSelection());\r
+\r
+ Simantics.getSessionContext().getSession().syncRequest(\r
+ new ReadRequest() {\r
+ @Override\r
+ public void run(ReadGraph graph) throws DatabaseException {\r
+ Layer0 L0 = Layer0.getInstance(graph);\r
+ models = getSupportedModels(graph, Simantics.getProject().get());\r
+ }\r
+ });\r
+\r
+ Collections.sort(models);\r
+\r
+ // Populate combo boxes\r
+ int i = 0;\r
+ boolean selected = false;\r
+ for (NamedResource s : models) {\r
+ model.add(s.getName());\r
+ model.setData(String.valueOf(i), s);\r
+ if (s.getResource().equals(selection)) {\r
+ model.select(i);\r
+ selected = true;\r
+ }\r
+ ++i;\r
+ }\r
+ if (!selected && i > 0)\r
+ model.select(0);\r
+ \r
+ if (model.getSelectionIndex() >= 0) {\r
+ exportData.setModel((NamedResource)model.getData(Integer.toString(model.getSelectionIndex())));\r
+ }\r
+ for (String path : exportData.getRecentLocations()) {\r
+ exportLocation.add(path);\r
+ }\r
+ if (exportLocation.getItemCount() > 0)\r
+ exportLocation.select(0);\r
+ }\r
+ \r
+ \r
+ \r
+ protected void validatePage() {\r
+ if (exportData.getModel() == null) {\r
+ setMessage("Select model to export.");\r
+ setErrorMessage(null);\r
+ setPageComplete(false);\r
+ return;\r
+ }\r
+ String exportLoc = exportLocation.getText();\r
+ File file;\r
+ if (exportToFile) {\r
+\r
+ if (exportLoc.isEmpty()) {\r
+ setMessage("Select target file.");\r
+ setErrorMessage(null);\r
+ setPageComplete(false);\r
+ return;\r
+ }\r
+ file = new File(exportLoc);\r
+ if (file.exists() && !file.isFile()) {\r
+ setErrorMessage("The target must be a file, an existing directory was given.");\r
+ setPageComplete(false);\r
+ return;\r
+ }\r
+ File parent = file.getParentFile();\r
+ if (parent == null || !parent.isDirectory()) {\r
+ setErrorMessage("The target directory does not exist.");\r
+ setPageComplete(false);\r
+ return;\r
+ }\r
+\r
+ } else {\r
+ if (exportLoc.isEmpty()) {\r
+ setMessage("Select target directory.");\r
+ setErrorMessage(null);\r
+ setPageComplete(false);\r
+ return;\r
+ }\r
+ file = new File(exportLoc);\r
+ if (file.exists() && !file.isDirectory()) {\r
+ setErrorMessage("The target must be a directory, an existing file was given.");\r
+ setPageComplete(false);\r
+ return;\r
+ }\r
+\r
+ }\r
+\r
+ exportData.setExportLocation(file);\r
+ exportData.setOverwrite(overwrite.getSelection());\r
+\r
+ setErrorMessage(null);\r
+ setMessage("Export selected model.");\r
+ setPageComplete(true);\r
+ }\r
+}\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<classpath>\r
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>\r
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>\r
+ <classpathentry kind="src" path="src"/>\r
+ <classpathentry kind="output" path="bin"/>\r
+</classpath>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<projectDescription>\r
+ <name>org.simantics.objmap2</name>\r
+ <comment></comment>\r
+ <projects>\r
+ </projects>\r
+ <buildSpec>\r
+ <buildCommand>\r
+ <name>org.eclipse.jdt.core.javabuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ <buildCommand>\r
+ <name>org.eclipse.pde.ManifestBuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ <buildCommand>\r
+ <name>org.eclipse.pde.SchemaBuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ </buildSpec>\r
+ <natures>\r
+ <nature>org.eclipse.pde.PluginNature</nature>\r
+ <nature>org.eclipse.jdt.core.javanature</nature>\r
+ </natures>\r
+</projectDescription>\r
--- /dev/null
+#Tue Jan 24 15:35:47 EET 2012\r
+eclipse.preferences.version=1\r
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled\r
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6\r
+org.eclipse.jdt.core.compiler.compliance=1.6\r
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error\r
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error\r
+org.eclipse.jdt.core.compiler.source=1.6\r
--- /dev/null
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Objmap2
+Bundle-SymbolicName: org.simantics.objmap2
+Bundle-Version: 1.0.0.qualifier
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Require-Bundle: org.simantics.db;bundle-version="1.1.0",
+ gnu.trove3;bundle-version="3.0.0",
+ org.eclipse.core.runtime;bundle-version="3.7.0",
+ org.simantics.layer0;bundle-version="1.0.0",
+ org.apache.log4j;bundle-version="1.2.15",
+ org.simantics.db.common;bundle-version="1.1.0",
+ org.simantics.structural.ontology;bundle-version="1.1.0"
+Export-Package: org.simantics.objmap.backward,
+ org.simantics.objmap.bidirectional,
+ org.simantics.objmap.exceptions,
+ org.simantics.objmap.forward,
+ org.simantics.objmap.graph,
+ org.simantics.objmap.graph.annotations,
+ org.simantics.objmap.graph.annotations.factories,
+ org.simantics.objmap.graph.rules.factory,
+ org.simantics.objmap.graph.schema,
+ org.simantics.objmap.structural,
+ org.simantics.objmap.structural.annotations,
+ org.simantics.objmap.structural.schema
--- /dev/null
+source.. = src/\r
+output.. = bin/\r
+bin.includes = META-INF/,\\r
+ .\r
--- /dev/null
+package org.simantics.objmap.backward;\r
+\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.objmap.exceptions.MappingException;\r
+\r
+/**\r
+ * Contains rules for creating and updating domain elements for given\r
+ * range elements.\r
+ * @author Hannu Niemistö\r
+ */\r
+public interface IBackwardLinkType<Domain, Range> extends IBackwardMappingRule<Domain, Range> {\r
+ /**\r
+ * Creates a domain element based on a known range element.\r
+ */\r
+ Domain createDomainElement(WriteGraph graph, Range rangeElement) throws MappingException;\r
+}\r
--- /dev/null
+package org.simantics.objmap.backward;\r
+\r
+import java.util.Set;\r
+\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.objmap.exceptions.MappingException;\r
+\r
+/**\r
+ * A backward mapping is a one-to-one correspondence between domain and range\r
+ * elements. It supports adding new range elements and creating corresponding\r
+ * domain elements.\r
+ * \r
+ * @author Hannu Niemistö\r
+ */\r
+public interface IBackwardMapping<Domain, Range> {\r
+ Set<Range> getRange();\r
+ Domain inverseGet(Range rangeElement);\r
+ Domain inverseMap(WriteGraph graph, Range rangeElement) throws MappingException;\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.backward;\r
+\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.objmap.exceptions.MappingException;\r
+\r
+public interface IBackwardMappingRule<Domain, Range> {\r
+ /**\r
+ * Modifies the domain element so that it corresponds to the range element.\r
+ * @param g write transaction\r
+ * @param map unidirectional view of the current mapping\r
+ * @param domainElement the domain element that is updated\r
+ * @param rangeElement the range element that corresponds to the domain element\r
+ * @return true if the rule made some modifications\r
+ * @throws MappingException \r
+ */ \r
+ boolean updateDomain(WriteGraph graph, IBackwardMapping<Domain, Range> mapping, Domain domainElement, Range rangeElement) throws MappingException;\r
+ void createDomain(WriteGraph graph, IBackwardMapping<Domain, Range> mapping, Domain domainElement, Range rangeElement) throws MappingException;\r
+}\r
--- /dev/null
+package org.simantics.objmap.backward;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.objmap.exceptions.MappingException;\r
+\r
+public interface IBackwardMappingSchema<Domain, Range> { \r
+ /**\r
+ * @return Link type that should be used for the element.\r
+ */\r
+ IBackwardLinkType<Domain, Range> linkTypeOfRangeElement(ReadGraph graph, Range element) throws MappingException;\r
+}\r
--- /dev/null
+package org.simantics.objmap.bidirectional;\r
+\r
+import org.simantics.objmap.backward.IBackwardLinkType;\r
+import org.simantics.objmap.forward.IForwardLinkType;\r
+\r
+\r
+public interface IBidirectionalLinkType<Domain, Range> \r
+extends IForwardLinkType<Domain, Range>, IBackwardLinkType<Domain, Range>,\r
+IBidirectionalMappingRule<Domain, Range> {\r
+}\r
--- /dev/null
+package org.simantics.objmap.bidirectional;\r
+\r
+import org.simantics.objmap.backward.IBackwardMapping;\r
+import org.simantics.objmap.forward.IForwardMapping;\r
+\r
+\r
+public interface IBidirectionalMapping<Domain, Range> \r
+extends IForwardMapping<Domain, Range>, IBackwardMapping<Domain, Range> {\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.bidirectional;\r
+\r
+import org.simantics.objmap.backward.IBackwardMappingRule;\r
+import org.simantics.objmap.forward.IForwardMappingRule;\r
+\r
+\r
+public interface IBidirectionalMappingRule<Domain, Range> \r
+extends IForwardMappingRule<Domain, Range>, IBackwardMappingRule<Domain, Range> {\r
+}\r
--- /dev/null
+package org.simantics.objmap.bidirectional;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.objmap.backward.IBackwardMappingSchema;\r
+import org.simantics.objmap.exceptions.MappingException;\r
+import org.simantics.objmap.forward.IForwardMappingSchema;\r
+\r
+\r
+public interface IBidirectionalMappingSchema<Domain, Range> \r
+extends IForwardMappingSchema<Domain, Range>, IBackwardMappingSchema<Domain, Range> {\r
+ IBidirectionalLinkType<Domain, Range> linkTypeOfDomainElement(ReadGraph graph, Domain element) throws MappingException;\r
+ IBidirectionalLinkType<Domain, Range> linkTypeOfRangeElement(ReadGraph graph, Range element) throws MappingException;\r
+}\r
--- /dev/null
+package org.simantics.objmap.exceptions;\r
+\r
+import org.simantics.db.exception.DatabaseException;\r
+\r
+public class MappingException extends DatabaseException {\r
+ private static final long serialVersionUID = 5381307568357191426L;\r
+ \r
+ \r
+ public MappingException() {\r
+ super();\r
+ }\r
+ \r
+ public MappingException(String message) {\r
+ super(message);\r
+ }\r
+ \r
+ public MappingException(Throwable cause) {\r
+ super(cause);\r
+ }\r
+ \r
+ public MappingException(String message, Throwable cause) {\r
+ super(message, cause);\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.objmap.forward;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.objmap.exceptions.MappingException;\r
+\r
+/**\r
+ * Contains rules for creating and updating range elements for given\r
+ * domain elements.\r
+ * @author Hannu Niemistö\r
+ */\r
+public interface IForwardLinkType<Domain, Range> extends IForwardMappingRule<Domain, Range> {\r
+ /**\r
+ * Creates a range element based on a known domain element.\r
+ */\r
+ Range createRangeElement(ReadGraph graph, Domain domainElement) throws MappingException;\r
+}\r
--- /dev/null
+package org.simantics.objmap.forward;\r
+\r
+import java.util.Set;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.objmap.exceptions.MappingException;\r
+\r
+public interface IForwardMapping<Domain, Range> {\r
+ Set<Domain> getDomain();\r
+ Range get(Domain domainElement);\r
+ Range map(ReadGraph graph, Domain domainElement) throws MappingException;\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.forward;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.objmap.exceptions.MappingException;\r
+\r
+public interface IForwardMappingRule<Domain, Range> {\r
+ /**\r
+ * Modifies the range element so that it corresponds to the domain element.\r
+ * @param g read transaction\r
+ * @param map unidirectional view of the current mapping\r
+ * @param domainElement the domain element that corresponds to the range element\r
+ * @param rangeElement the range element that is updated\r
+ * @return true if the rule made some modifications\r
+ * @throws MappingException\r
+ */\r
+ boolean updateRange(ReadGraph graph, IForwardMapping<Domain, Range> mapping, Domain domainElement, Range rangeElement) throws MappingException; \r
+ void createRange(ReadGraph graph, IForwardMapping<Domain, Range> mapping, Domain domainElement, Range rangeElement) throws MappingException;\r
+}\r
--- /dev/null
+package org.simantics.objmap.forward;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.objmap.exceptions.MappingException;\r
+\r
+public interface IForwardMappingSchema<Domain, Range> {\r
+ /**\r
+ * @return Link type that should be used for the element.\r
+ */\r
+ IForwardLinkType<Domain, Range> linkTypeOfDomainElement(ReadGraph graph, Domain element) throws MappingException;\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.graph;\r
+\r
+import java.util.Collection;\r
+import java.util.Set;\r
+\r
+import org.simantics.db.Disposable;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.objmap.bidirectional.IBidirectionalMapping;\r
+import org.simantics.objmap.exceptions.MappingException;\r
+\r
+/**\r
+ * A mapping consists of domain (a set of resources), range (a set of Java objects) and\r
+ * a set of links relating them. The mapping is used to propagate modifications of\r
+ * domain elements to range and vice versa. \r
+ * \r
+ * @see <a href="http://www.simantics.org/wiki/index.php/org.simantics.objmap_Manual#Concepts">Manual</a>\r
+ * \r
+ * @author Hannu Niemistö\r
+ */\r
+public interface IMapping<Domain,Range> extends Disposable, IBidirectionalMapping<Domain, Range> {\r
+\r
+ /**\r
+ * Returns the domain of the mapping. All set operations are supported.\r
+ * Adding a new domain element does not automatically create a link to it.\r
+ * Removal of a domain element removes also a link and the target element,\r
+ * but does not remove the element from the database.\r
+ */\r
+ Set<Domain> getDomain();\r
+\r
+ /**\r
+ * Returns the range of the mapping. All set operations are supported.\r
+ * Adding a new range element does not automatically create a link to it.\r
+ * Removal of a range element removes also a link and the domain element,\r
+ * but does not remove the domain element from the database.\r
+ */\r
+ Set<Range> getRange();\r
+\r
+ /**\r
+ * Updates all domain elements whose counterpart is modified and creates new\r
+ * domain elements for previously added range elements. Returns the\r
+ * collection of domain elements that were modified or created in the update\r
+ * process.\r
+ */\r
+ Collection<Domain> updateDomain(WriteGraph g) throws MappingException;\r
+\r
+ /**\r
+ * Updates all range elements whose counterpart is modified and creates new\r
+ * range elements for previously added domain elements. Returns the\r
+ * collection of range elements that were modified or created in the update\r
+ * process.\r
+ */\r
+ Collection<Range> updateRange(ReadGraph g) throws MappingException;\r
+\r
+ /**\r
+ * Returns the counterpart of a domain element or null if the element does\r
+ * not belong to the domain or does not have a link.\r
+ */\r
+ Range get(Domain domainElement);\r
+\r
+ /**\r
+ * Returns the counterpart of a range element or null if the element does\r
+ * not belong to the range or does not have a link.\r
+ */\r
+ Domain inverseGet(Range rangeElement);\r
+\r
+ /**\r
+ * A convenience method that adds a domain element to the mapping and\r
+ * immediately updates the mapping and returns the corresponding range\r
+ * element.\r
+ */\r
+ Range map(ReadGraph g, Domain domainElement) throws MappingException;\r
+\r
+ /**\r
+ * A convenience method that adds a range element to the mapping and\r
+ * immediately updates the mapping and returns the corresponding domain\r
+ * element.\r
+ */\r
+ Domain inverseMap(WriteGraph g, Range rangeElement)\r
+ throws MappingException;\r
+\r
+ /**\r
+ * Tells the mapping that the domain element has been modified.\r
+ */\r
+ void domainModified(Domain domainElement);\r
+\r
+ /**\r
+ * Tells the mapping that the range element has been modified.\r
+ */\r
+ void rangeModified(Range rangeElement);\r
+\r
+ /**\r
+ * Tells if some domain elements have been modified or added.\r
+ */\r
+ boolean isDomainModified();\r
+\r
+ /**\r
+ * Tells if some range elements have been modified or added.\r
+ */\r
+ boolean isRangeModified();\r
+ \r
+ Collection<Domain> getDomainModified();\r
+ Collection<Range> getRangeModified();\r
+\r
+ /**\r
+ * Returns a collection of domain elements which have been modified and also\r
+ * their counterparts in the mapping are modified. These elements are in\r
+ * conflict in the sense that the updating domain and range in different\r
+ * orders may produce different results.\r
+ */\r
+ Collection<Domain> getConflictingDomainElements();\r
+\r
+ /**\r
+ * Returns a collection of range elements which have been modified and also\r
+ * their counterparts in the mapping are modified. These elements are in\r
+ * conflict in the sense that the updating domain and range in different\r
+ * orders may produce different results.\r
+ */\r
+ Collection<Range> getConflictingRangeElements();\r
+\r
+ /**\r
+ * Adds a listener for domain and range modifications.\r
+ */\r
+ void addMappingListener(IMappingListener listener);\r
+\r
+ /**\r
+ * Removes a previously added listener.\r
+ */\r
+ void removeMappingListener(IMappingListener listener);\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.graph;\r
+\r
+/**\r
+ * Listens modifications in a mapping.\r
+ * @author Hannu Niemistö\r
+ */\r
+public interface IMappingListener {\r
+ /**\r
+ * Called when some domain element is modified or created\r
+ * and the mapping was previously up to date.\r
+ */\r
+ void domainModified();\r
+ \r
+ /**\r
+ * Called when some range element is modified or created\r
+ * and the mapping was previously up to date.\r
+ */\r
+ void rangeModified();\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.graph;\r
+\r
+import org.simantics.db.Resource;\r
+import org.simantics.objmap.graph.impl.Mapping;\r
+import org.simantics.objmap.graph.schema.IMappingSchema;\r
+/**\r
+ * Static utility methods for mappings. \r
+ * @author Hannu Niemistö\r
+ */\r
+public class Mappings {\r
+ private Mappings() {}\r
+ \r
+ /**\r
+ * Creates a new mapping based on the given mapping schema. \r
+ * The created mapping is not thread-safe and will not\r
+ * listen database changes automatically.\r
+ */\r
+ public static <Domain,Range> IMapping<Domain,Range> createWithoutListening(IMappingSchema<Domain,Range> schema) {\r
+ return new Mapping<Domain,Range>(schema, false);\r
+ }\r
+ \r
+ /**\r
+ * Creates a new mapping based on the given mapping schema. \r
+ * The created mapping is not thread-safe. It listens database\r
+ * changes automatically.\r
+ */\r
+ public static <Domain,Range> IMapping<Domain,Range> createWithListening(IMappingSchema<Domain,Range> schema) {\r
+ return new Mapping<Domain,Range>(schema, true);\r
+ }\r
+ \r
+ \r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.graph.annotations;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target({ElementType.FIELD,ElementType.METHOD})\r
+public @interface Composition {\r
+}\r
--- /dev/null
+package org.simantics.objmap.graph.annotations;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+import org.simantics.objmap.graph.annotations.meta.IsGetSetRule;\r
+import org.simantics.objmap.graph.rules.adapters.IdentityAdapter;\r
+import org.simantics.objmap.graph.rules.adapters.ValueAdapter;\r
+\r
+\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.METHOD)\r
+@IsGetSetRule\r
+@HasSetter(CompoundRelatedSetValue.class)\r
+public @interface CompoundRelatedGetValue {\r
+ String objRelation();\r
+ String objType();\r
+ String valRelation();\r
+// Class<? extends ValueAdapter> adapter() default IdentityAdapter.class;\r
+}\r
--- /dev/null
+package org.simantics.objmap.graph.annotations;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.METHOD)\r
+public @interface CompoundRelatedSetValue {\r
+ String value();\r
+}\r
--- /dev/null
+package org.simantics.objmap.graph.annotations;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.TYPE) \r
+public @interface DynamicGraphType {\r
+ String value();\r
+}\r
--- /dev/null
+package org.simantics.objmap.graph.annotations;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.METHOD)\r
+//@HasGetSetRuleFactory(RelatedGetSetValueRuleFactory.class)\r
+public @interface GetType {\r
+ String value();\r
+}\r
--- /dev/null
+package org.simantics.objmap.graph.annotations;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.TYPE) \r
+public @interface GraphType {\r
+ String value();\r
+}\r
--- /dev/null
+package org.simantics.objmap.graph.annotations;\r
+\r
+import java.lang.annotation.Annotation;\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.ANNOTATION_TYPE)\r
+public @interface HasCollectionAdder {\r
+ Class<? extends Annotation> value();\r
+}\r
--- /dev/null
+package org.simantics.objmap.graph.annotations;\r
+\r
+import java.lang.annotation.Annotation;\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.ANNOTATION_TYPE)\r
+public @interface HasCollectionRemover {\r
+ Class<? extends Annotation> value();\r
+}\r
--- /dev/null
+package org.simantics.objmap.graph.annotations;\r
+\r
+import java.lang.annotation.Annotation;\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.ANNOTATION_TYPE)\r
+public @interface HasSetter {\r
+ Class<? extends Annotation> value();\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.graph.annotations;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+import org.simantics.objmap.graph.annotations.meta.IsFieldRule;\r
+\r
+\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.FIELD)\r
+//@HasFieldRuleFactory(OptionalRelatedElementsRuleFactory.class)\r
+@IsFieldRule\r
+public @interface OptionalRelatedElements {\r
+ String value();\r
+ boolean composition() default false;\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.graph.annotations;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+import org.simantics.objmap.graph.annotations.meta.IsFieldRule;\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.FIELD)\r
+//HasFieldRuleFactory(RelatedElementRuleFactory.class)\r
+@IsFieldRule\r
+public @interface RelatedElement {\r
+ String value();\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.graph.annotations;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+import org.simantics.objmap.graph.annotations.meta.IsFieldRule;\r
+\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.FIELD)\r
+//@HasFieldRuleFactory(RelatedElementsRuleFactory.class)\r
+@IsFieldRule\r
+public @interface RelatedElements {\r
+ String value();\r
+ boolean composition() default false;\r
+}\r
--- /dev/null
+package org.simantics.objmap.graph.annotations;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.METHOD)\r
+public @interface RelatedElementsAdd {\r
+ String value();\r
+}\r
--- /dev/null
+package org.simantics.objmap.graph.annotations;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+import org.simantics.objmap.graph.annotations.meta.IsCollectionRule;\r
+\r
+\r
+\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.METHOD)\r
+//@HasCollectionRuleFactory(RelatedElementsRuleFactory2.class)\r
+@IsCollectionRule\r
+@HasCollectionAdder(RelatedElementsAdd.class)\r
+@HasCollectionRemover(RelatedElementsRem.class)\r
+public @interface RelatedElementsGet {\r
+ String value();\r
+ boolean composition() default false;\r
+}\r
--- /dev/null
+package org.simantics.objmap.graph.annotations;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.METHOD)\r
+public @interface RelatedElementsRem {\r
+ String value();\r
+}\r
--- /dev/null
+package org.simantics.objmap.graph.annotations;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+import org.simantics.objmap.graph.annotations.meta.IsGetSetRule;\r
+\r
+\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.METHOD)\r
+//@HasGetSetRuleFactory(RelatedGetSetObjRuleFactory.class)\r
+@IsGetSetRule\r
+@HasSetter(RelatedSetObj.class)\r
+public @interface RelatedGetObj {\r
+ String value();\r
+}\r
--- /dev/null
+package org.simantics.objmap.graph.annotations;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+import org.simantics.objmap.graph.annotations.meta.IsGetSetRule;\r
+import org.simantics.objmap.graph.rules.adapters.IdentityAdapter;\r
+import org.simantics.objmap.graph.rules.adapters.ValueAdapter;\r
+\r
+\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.METHOD)\r
+//@HasGetSetRuleFactory(RelatedGetSetValueRuleFactory.class)\r
+@IsGetSetRule\r
+@HasSetter(RelatedSetValue.class)\r
+public @interface RelatedGetValue {\r
+ String value();\r
+ Class<? extends ValueAdapter> adapter() default IdentityAdapter.class;\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.graph.annotations;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+import org.simantics.objmap.graph.annotations.meta.IsFieldRule;\r
+\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.FIELD)\r
+//@HasFieldRuleFactory(RelatedOrderedSetElementsRuleFactory.class)\r
+@IsFieldRule\r
+public @interface RelatedOrderedSetElements {\r
+ boolean composition() default false;\r
+}\r
--- /dev/null
+package org.simantics.objmap.graph.annotations;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.METHOD)\r
+public @interface RelatedSetObj {\r
+ String value();\r
+}\r
--- /dev/null
+package org.simantics.objmap.graph.annotations;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.METHOD)\r
+public @interface RelatedSetValue {\r
+ String value();\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.graph.annotations;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+import org.simantics.objmap.graph.annotations.meta.IsFieldRule;\r
+import org.simantics.objmap.graph.rules.adapters.IdentityAdapter;\r
+import org.simantics.objmap.graph.rules.adapters.ValueAdapter;\r
+\r
+\r
+\r
+/**\r
+ * Specifies a correspondence between a field and \r
+ * functional property.\r
+ * @author Hannu Niemistö\r
+ */\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.FIELD)\r
+//@HasFieldRuleFactory(RelatedValueRuleFactory.class)\r
+@IsFieldRule\r
+public @interface RelatedValue {\r
+ String value();\r
+ Class<? extends ValueAdapter> adapter() default IdentityAdapter.class;\r
+}\r
--- /dev/null
+package org.simantics.objmap.graph.annotations;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.METHOD)\r
+//@HasGetSetRuleFactory(RelatedGetSetValueRuleFactory.class)\r
+public @interface SetType {\r
+ String value();\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.graph.annotations;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+import org.simantics.objmap.graph.annotations.meta.IsFieldRule;\r
+\r
+\r
+\r
+/**\r
+ * Specifies that the annotated method should be called\r
+ * to update range object.\r
+ * @author Hannu Niemistö\r
+ */\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.METHOD)\r
+//@HasMethodRuleFactory(UpdateMethodFactory.class)\r
+@IsFieldRule\r
+public @interface UpdateMethod {\r
+}\r
--- /dev/null
+package org.simantics.objmap.graph.annotations.factories;\r
+\r
+import java.lang.annotation.Annotation;\r
+import java.lang.reflect.Method;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.objmap.bidirectional.IBidirectionalMappingRule;\r
+import org.simantics.objmap.graph.annotations.CompoundRelatedGetValue;\r
+import org.simantics.objmap.graph.annotations.CompoundRelatedSetValue;\r
+import org.simantics.objmap.graph.rules.ValueRule;\r
+import org.simantics.objmap.graph.rules.adapters.IdentityAdapter;\r
+import org.simantics.objmap.graph.rules.adapters.ValueAdapter;\r
+import org.simantics.objmap.graph.rules.domain.CompoundValueAccessor;\r
+import org.simantics.objmap.graph.rules.factory.IGetSetRuleFactory;\r
+import org.simantics.objmap.graph.rules.range.AdaptedRangeAccessor;\r
+import org.simantics.objmap.graph.rules.range.CompoundGetSetValueAccessor;\r
+import org.simantics.objmap.graph.rules.range.IRangeAccessor;\r
+\r
+/**\r
+ * Rule factory for mapped value using Getter/Setter-methods.\r
+ * \r
+ * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
+ *\r
+ */\r
+public class CompoundRelatedGetSetValueRuleFactory<Range> implements IGetSetRuleFactory<Resource,Range> {\r
+ \r
+ @Override\r
+ public IBidirectionalMappingRule<Resource, Range> create(ReadGraph g, Annotation annotation,\r
+ Method getter, Method setter)\r
+ throws DatabaseException {\r
+ CompoundRelatedGetValue getterAnn = (CompoundRelatedGetValue)annotation;\r
+ \r
+// Class<? extends ValueAdapter> adapterClass = getterAnn.adapter();\r
+ IRangeAccessor<Range,Object> rangeAccessor = new CompoundGetSetValueAccessor<Range,Object>(getter, setter);\r
+// Resource valueType;\r
+// if (adapterClass == IdentityAdapter.class) {\r
+// valueType = dataTypeOfClass(g, getter.getReturnType());\r
+// } else {\r
+// try{\r
+// ValueAdapter adapter = adapterClass.newInstance();\r
+// rangeAccessor = new AdaptedRangeAccessor<Range>(rangeAccessor, adapter);\r
+// valueType = adapter.rangeTypeToDomainType(g, getter.getReturnType());\r
+// } catch (InstantiationException e) {\r
+// throw new RuntimeException(e);\r
+// } catch (IllegalAccessException e) {\r
+// throw new RuntimeException(e);\r
+// }\r
+// }\r
+ return new ValueRule<Resource,Range>(new CompoundValueAccessor(g.getResource(getterAnn.objRelation()),\r
+ g.getResource(getterAnn.objType()),\r
+ g.getResource(getterAnn.valRelation())),\r
+ rangeAccessor);\r
+ }\r
+ \r
+ @Override\r
+ public boolean isSetter(Annotation getterAnnotation, Annotation annotation) {\r
+ CompoundRelatedGetValue getterAnn = (CompoundRelatedGetValue)getterAnnotation;\r
+ CompoundRelatedSetValue setterAnn = (CompoundRelatedSetValue)annotation;\r
+ return getterAnn.objRelation().equals(setterAnn.value());\r
+ }\r
+ \r
+ public static Resource dataTypeOfClass(ReadGraph g, Class<?> clazz) {\r
+ Layer0 b = Layer0.getInstance(g);\r
+ if(clazz.equals(Double.class) || clazz.equals(double.class))\r
+ return b.Double;\r
+ else if(clazz.equals(String.class))\r
+ return b.String;\r
+ else if(clazz.equals(Integer.class) || clazz.equals(int.class))\r
+ return b.Integer;\r
+ else if(clazz.equals(Float.class) || clazz.equals(float.class))\r
+ return b.Float;\r
+ else if(clazz.equals(Boolean.class) || clazz.equals(boolean.class))\r
+ return b.Boolean;\r
+ else if(clazz.equals(Long.class) || clazz.equals(long.class))\r
+ return b.Long;\r
+ else if(clazz.equals(Byte.class) || clazz.equals(byte.class))\r
+ return b.Byte;\r
+ \r
+ else if(clazz.equals(double[].class))\r
+ return b.DoubleArray;\r
+ else if(clazz.equals(int[].class))\r
+ return b.IntegerArray;\r
+ else if(clazz.equals(byte[].class))\r
+ return b.ByteArray;\r
+ else if(clazz.equals(float[].class))\r
+ return b.FloatArray;\r
+ else if(clazz.equals(boolean[].class))\r
+ return b.BooleanArray;\r
+ else if(clazz.equals(String[].class))\r
+ return b.StringArray;\r
+ else if(clazz.equals(long[].class))\r
+ return b.LongArray;\r
+ else {\r
+ System.out.println("Couldn't find a data type for " + clazz);\r
+ return null;\r
+ }\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.graph.annotations.factories;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.layer0.Layer0;\r
+\r
+public class DataTypeUtils {\r
+ \r
+ public static Resource dataTypeOfClass(ReadGraph g, Class<?> clazz) {\r
+ Layer0 b = Layer0.getInstance(g);\r
+ if(clazz.equals(Double.class) || clazz.equals(double.class))\r
+ return b.Double;\r
+ else if(clazz.equals(String.class))\r
+ return b.String;\r
+ else if(clazz.equals(Integer.class) || clazz.equals(int.class))\r
+ return b.Integer;\r
+ else if(clazz.equals(Float.class) || clazz.equals(float.class))\r
+ return b.Float;\r
+ else if(clazz.equals(Boolean.class) || clazz.equals(boolean.class))\r
+ return b.Boolean;\r
+ else if(clazz.equals(Long.class) || clazz.equals(long.class))\r
+ return b.Long;\r
+ else if(clazz.equals(Byte.class) || clazz.equals(byte.class))\r
+ return b.Byte;\r
+ \r
+ else if(clazz.equals(double[].class))\r
+ return b.DoubleArray;\r
+ else if(clazz.equals(int[].class))\r
+ return b.IntegerArray;\r
+ else if(clazz.equals(byte[].class))\r
+ return b.ByteArray;\r
+ else if(clazz.equals(float[].class))\r
+ return b.FloatArray;\r
+ else if(clazz.equals(boolean[].class))\r
+ return b.BooleanArray;\r
+ else if(clazz.equals(String[].class))\r
+ return b.StringArray;\r
+ else if(clazz.equals(long[].class))\r
+ return b.LongArray;\r
+ else {\r
+ System.out.println("Couldn't find a data type for " + clazz);\r
+ return null;\r
+ }\r
+ }\r
+ \r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.graph.annotations.factories;\r
+\r
+import java.lang.annotation.Annotation;\r
+import java.lang.reflect.Field;\r
+import java.util.Collection;\r
+import java.util.Collections;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.exception.ResourceNotFoundException;\r
+import org.simantics.db.exception.ServiceException;\r
+import org.simantics.db.exception.ValidationException;\r
+import org.simantics.objmap.bidirectional.IBidirectionalMappingRule;\r
+import org.simantics.objmap.graph.annotations.OptionalRelatedElements;\r
+import org.simantics.objmap.graph.rules.MappedElementsRule;\r
+import org.simantics.objmap.graph.rules.domain.RelatedObjectsAccessor;\r
+import org.simantics.objmap.graph.rules.factory.IFieldRuleFactory;\r
+import org.simantics.objmap.graph.rules.range.FieldAccessorWithDefault;\r
+\r
+\r
+public class OptionalRelatedElementsRuleFactory<Range> implements IFieldRuleFactory<Resource, Range> {\r
+\r
+ @Override\r
+ public IBidirectionalMappingRule<Resource, Range> create(ReadGraph g, Annotation _annotation, Field field) throws ResourceNotFoundException, ValidationException, ServiceException {\r
+ OptionalRelatedElements annotation = (OptionalRelatedElements)_annotation;\r
+ return new MappedElementsRule<Resource, Range>(\r
+ new RelatedObjectsAccessor(g.getResource(annotation.value()),\r
+ annotation.composition()),\r
+ new FieldAccessorWithDefault<Range,Collection<Range>>(field, (Collection<Range>)Collections.emptyList())\r
+ );\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.graph.annotations.factories;\r
+\r
+import java.lang.annotation.Annotation;\r
+import java.lang.reflect.Field;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.exception.ResourceNotFoundException;\r
+import org.simantics.db.exception.ServiceException;\r
+import org.simantics.db.exception.ValidationException;\r
+import org.simantics.objmap.bidirectional.IBidirectionalMappingRule;\r
+import org.simantics.objmap.graph.annotations.RelatedElement;\r
+import org.simantics.objmap.graph.rules.MappedElementRule;\r
+import org.simantics.objmap.graph.rules.domain.RelatedObjectAccessor;\r
+import org.simantics.objmap.graph.rules.factory.IFieldRuleFactory;\r
+import org.simantics.objmap.graph.rules.range.FieldAccessor;\r
+\r
+\r
+public class RelatedElementRuleFactory<Range> implements IFieldRuleFactory<Resource,Range> {\r
+\r
+ @Override\r
+ public IBidirectionalMappingRule<Resource, Range> create(ReadGraph g, Annotation _annotation, Field field) throws ResourceNotFoundException, ValidationException, ServiceException {\r
+ RelatedElement annotation = (RelatedElement)_annotation;\r
+ return new MappedElementRule<Resource,Range>(\r
+ new RelatedObjectAccessor(g.getResource(annotation.value())),\r
+ new FieldAccessor<Range,Range>(field)\r
+ );\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.graph.annotations.factories;\r
+\r
+import java.lang.annotation.Annotation;\r
+import java.lang.reflect.Field;\r
+import java.util.Collection;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.exception.ResourceNotFoundException;\r
+import org.simantics.db.exception.ServiceException;\r
+import org.simantics.db.exception.ValidationException;\r
+import org.simantics.objmap.bidirectional.IBidirectionalMappingRule;\r
+import org.simantics.objmap.graph.annotations.RelatedElements;\r
+import org.simantics.objmap.graph.rules.MappedElementsRule;\r
+import org.simantics.objmap.graph.rules.domain.RelatedObjectsAccessor;\r
+import org.simantics.objmap.graph.rules.factory.IFieldRuleFactory;\r
+import org.simantics.objmap.graph.rules.range.FieldAccessor;\r
+\r
+\r
+public class RelatedElementsRuleFactory<Range> implements IFieldRuleFactory<Resource, Range> {\r
+\r
+ @Override\r
+ public IBidirectionalMappingRule<Resource, Range> create(ReadGraph g, Annotation _annotation, Field field) throws ResourceNotFoundException, ValidationException, ServiceException {\r
+ RelatedElements annotation = (RelatedElements)_annotation;\r
+ return new MappedElementsRule<Resource,Range>(\r
+ new RelatedObjectsAccessor(g.getResource(annotation.value()),\r
+ annotation.composition()),\r
+ new FieldAccessor<Range,Collection<Range>>(field)\r
+ );\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.objmap.graph.annotations.factories;\r
+\r
+import java.lang.annotation.Annotation;\r
+import java.lang.reflect.Method;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.objmap.bidirectional.IBidirectionalMappingRule;\r
+import org.simantics.objmap.graph.annotations.RelatedElementsAdd;\r
+import org.simantics.objmap.graph.annotations.RelatedElementsGet;\r
+import org.simantics.objmap.graph.annotations.RelatedElementsRem;\r
+import org.simantics.objmap.graph.rules.MappedElementsRule;\r
+import org.simantics.objmap.graph.rules.domain.RelatedObjectsAccessor;\r
+import org.simantics.objmap.graph.rules.factory.ICollectionRuleFactory;\r
+import org.simantics.objmap.graph.rules.range.CollectionAccessor;\r
+\r
+\r
+public class RelatedElementsRuleFactory2<Range> implements ICollectionRuleFactory<Resource,Range> {\r
+ \r
+ @Override\r
+ public IBidirectionalMappingRule<Resource, Range> create(ReadGraph g, Annotation annotation,\r
+ Method getter, Method adder, Method remover)\r
+ throws DatabaseException {\r
+ RelatedElementsGet getterAnn = (RelatedElementsGet)annotation;\r
+ return new MappedElementsRule<Resource,Range>(new RelatedObjectsAccessor(g.getResource(getterAnn.value()),getterAnn.composition()),\r
+ new CollectionAccessor<Range,Range>(getter, adder, remover));\r
+ }\r
+ \r
+ @Override\r
+ public boolean isAdder(Annotation getterAnnotation, Annotation annotation) {\r
+ RelatedElementsGet getterAnn = (RelatedElementsGet)getterAnnotation;\r
+ RelatedElementsAdd adderAnn = (RelatedElementsAdd)annotation;\r
+ return getterAnn.value().equals(adderAnn.value());\r
+ }\r
+ \r
+ @Override\r
+ public boolean isRemover(Annotation getterAnnotation, Annotation annotation) {\r
+ RelatedElementsGet getterAnn = (RelatedElementsGet)getterAnnotation;\r
+ RelatedElementsRem adderAnn = (RelatedElementsRem)annotation;\r
+ return getterAnn.value().equals(adderAnn.value());\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.objmap.graph.annotations.factories;\r
+\r
+import java.lang.annotation.Annotation;\r
+import java.lang.reflect.Method;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.objmap.bidirectional.IBidirectionalMappingRule;\r
+import org.simantics.objmap.graph.annotations.RelatedGetObj;\r
+import org.simantics.objmap.graph.annotations.RelatedSetObj;\r
+import org.simantics.objmap.graph.rules.MappedElementRule;\r
+import org.simantics.objmap.graph.rules.domain.RelatedObjectAccessor;\r
+import org.simantics.objmap.graph.rules.factory.IGetSetRuleFactory;\r
+import org.simantics.objmap.graph.rules.range.GetSetObjectAccessor;\r
+\r
+\r
+/**\r
+ * Rule factory for mapped object using Getter/Setter-methods.\r
+ * \r
+ * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
+ *\r
+ */\r
+public class RelatedGetSetObjRuleFactory<Range> implements IGetSetRuleFactory<Resource,Range> {\r
+ \r
+ @Override\r
+ public IBidirectionalMappingRule<Resource,Range> create(ReadGraph g, Annotation annotation,\r
+ Method getter, Method setter)\r
+ throws DatabaseException {\r
+ RelatedGetObj getterAnn = (RelatedGetObj)annotation;\r
+ return new MappedElementRule<Resource,Range>(new RelatedObjectAccessor(g.getResource(getterAnn.value())),\r
+ new GetSetObjectAccessor<Range,Range>(getter, setter));\r
+ }\r
+ \r
+ @Override\r
+ public boolean isSetter(Annotation getterAnnotation, Annotation annotation) {\r
+ RelatedGetObj getterAnn = (RelatedGetObj)getterAnnotation;\r
+ RelatedSetObj setterAnn = (RelatedSetObj)annotation;\r
+ return getterAnn.value().equals(setterAnn.value());\r
+ }\r
+ \r
+ \r
+\r
+}\r
--- /dev/null
+package org.simantics.objmap.graph.annotations.factories;\r
+\r
+import java.lang.annotation.Annotation;\r
+import java.lang.reflect.Method;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.objmap.bidirectional.IBidirectionalMappingRule;\r
+import org.simantics.objmap.graph.annotations.RelatedGetValue;\r
+import org.simantics.objmap.graph.annotations.RelatedSetValue;\r
+import org.simantics.objmap.graph.rules.ValueRule;\r
+import org.simantics.objmap.graph.rules.adapters.IdentityAdapter;\r
+import org.simantics.objmap.graph.rules.adapters.ValueAdapter;\r
+import org.simantics.objmap.graph.rules.domain.RelatedValueAccessor;\r
+import org.simantics.objmap.graph.rules.factory.IGetSetRuleFactory;\r
+import org.simantics.objmap.graph.rules.range.AdaptedRangeAccessor;\r
+import org.simantics.objmap.graph.rules.range.GetSetValueAccessor;\r
+import org.simantics.objmap.graph.rules.range.IRangeAccessor;\r
+\r
+/**\r
+ * Rule factory for mapped value using Getter/Setter-methods.\r
+ * \r
+ * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
+ *\r
+ */\r
+public class RelatedGetSetValueRuleFactory<Range> implements IGetSetRuleFactory<Resource,Range> {\r
+ \r
+ @Override\r
+ public IBidirectionalMappingRule<Resource, Range> create(ReadGraph g, Annotation annotation,\r
+ Method getter, Method setter)\r
+ throws DatabaseException {\r
+ RelatedGetValue getterAnn = (RelatedGetValue)annotation;\r
+ \r
+ Class<? extends ValueAdapter> adapterClass = getterAnn.adapter();\r
+ IRangeAccessor<Range,Object> rangeAccessor = new GetSetValueAccessor<Range,Object>(getter, setter);\r
+ Resource valueType;\r
+ if (adapterClass == IdentityAdapter.class) {\r
+ valueType = dataTypeOfClass(g, getter.getReturnType());\r
+ } else {\r
+ try{\r
+ ValueAdapter adapter = adapterClass.newInstance();\r
+ rangeAccessor = new AdaptedRangeAccessor<Range>(rangeAccessor, adapter);\r
+ valueType = adapter.rangeTypeToDomainType(g, getter.getReturnType());\r
+ } catch (InstantiationException e) {\r
+ throw new RuntimeException(e);\r
+ } catch (IllegalAccessException e) {\r
+ throw new RuntimeException(e);\r
+ }\r
+ }\r
+ return new ValueRule<Resource,Range>(new RelatedValueAccessor(g.getResource(getterAnn.value()), valueType),\r
+ rangeAccessor);\r
+ }\r
+ \r
+ @Override\r
+ public boolean isSetter(Annotation getterAnnotation, Annotation annotation) {\r
+ RelatedGetValue getterAnn = (RelatedGetValue)getterAnnotation;\r
+ RelatedSetValue setterAnn = (RelatedSetValue)annotation;\r
+ return getterAnn.value().equals(setterAnn.value());\r
+ }\r
+ \r
+ public static Resource dataTypeOfClass(ReadGraph g, Class<?> clazz) {\r
+ Layer0 b = Layer0.getInstance(g);\r
+ if(clazz.equals(Double.class) || clazz.equals(double.class))\r
+ return b.Double;\r
+ else if(clazz.equals(String.class))\r
+ return b.String;\r
+ else if(clazz.equals(Integer.class) || clazz.equals(int.class))\r
+ return b.Integer;\r
+ else if(clazz.equals(Float.class) || clazz.equals(float.class))\r
+ return b.Float;\r
+ else if(clazz.equals(Boolean.class) || clazz.equals(boolean.class))\r
+ return b.Boolean;\r
+ else if(clazz.equals(Long.class) || clazz.equals(long.class))\r
+ return b.Long;\r
+ else if(clazz.equals(Byte.class) || clazz.equals(byte.class))\r
+ return b.Byte;\r
+ \r
+ else if(clazz.equals(double[].class))\r
+ return b.DoubleArray;\r
+ else if(clazz.equals(int[].class))\r
+ return b.IntegerArray;\r
+ else if(clazz.equals(byte[].class))\r
+ return b.ByteArray;\r
+ else if(clazz.equals(float[].class))\r
+ return b.FloatArray;\r
+ else if(clazz.equals(boolean[].class))\r
+ return b.BooleanArray;\r
+ else if(clazz.equals(String[].class))\r
+ return b.StringArray;\r
+ else if(clazz.equals(long[].class))\r
+ return b.LongArray;\r
+ else {\r
+ System.out.println("Couldn't find a data type for " + clazz);\r
+ return null;\r
+ }\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.graph.annotations.factories;\r
+\r
+import java.lang.annotation.Annotation;\r
+import java.lang.reflect.Field;\r
+import java.util.Collection;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.exception.ResourceNotFoundException;\r
+import org.simantics.db.exception.ServiceException;\r
+import org.simantics.db.exception.ValidationException;\r
+import org.simantics.objmap.bidirectional.IBidirectionalMappingRule;\r
+import org.simantics.objmap.graph.annotations.RelatedOrderedSetElements;\r
+import org.simantics.objmap.graph.rules.MappedElementsRule;\r
+import org.simantics.objmap.graph.rules.domain.RelatedOrderedSetElementsAccessor;\r
+import org.simantics.objmap.graph.rules.factory.IFieldRuleFactory;\r
+import org.simantics.objmap.graph.rules.range.FieldAccessor;\r
+\r
+\r
+public class RelatedOrderedSetElementsRuleFactory<Range> implements IFieldRuleFactory<Resource, Range> {\r
+\r
+ @Override\r
+ public IBidirectionalMappingRule<Resource, Range> create(ReadGraph g, Annotation _annotation, Field field) throws ResourceNotFoundException, ValidationException, ServiceException {\r
+ RelatedOrderedSetElements annotation = (RelatedOrderedSetElements)_annotation;\r
+ return new MappedElementsRule<Resource,Range>(\r
+ new RelatedOrderedSetElementsAccessor(annotation.composition()),\r
+ new FieldAccessor<Range,Collection<Range>>(field)\r
+ );\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.graph.annotations.factories;\r
+\r
+import java.lang.annotation.Annotation;\r
+import java.lang.reflect.Field;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.exception.ResourceNotFoundException;\r
+import org.simantics.db.exception.ServiceException;\r
+import org.simantics.db.exception.ValidationException;\r
+\r
+import org.simantics.objmap.bidirectional.IBidirectionalMappingRule;\r
+import org.simantics.objmap.graph.annotations.RelatedValue;\r
+import org.simantics.objmap.graph.rules.ValueRule;\r
+import org.simantics.objmap.graph.rules.adapters.IdentityAdapter;\r
+import org.simantics.objmap.graph.rules.adapters.ValueAdapter;\r
+import org.simantics.objmap.graph.rules.domain.RelatedValueAccessor;\r
+import org.simantics.objmap.graph.rules.factory.IFieldRuleFactory;\r
+import org.simantics.objmap.graph.rules.range.AdaptedRangeAccessor;\r
+import org.simantics.objmap.graph.rules.range.FieldAccessor;\r
+import org.simantics.objmap.graph.rules.range.IRangeAccessor;\r
+\r
+\r
+public class RelatedValueRuleFactory<Range> implements IFieldRuleFactory<Resource, Range> {\r
+\r
+ @Override\r
+ public IBidirectionalMappingRule<Resource, Range> create(ReadGraph g, Annotation _annotation, Field field) throws ResourceNotFoundException,\r
+ ValidationException, ServiceException {\r
+ RelatedValue annotation = (RelatedValue) _annotation;\r
+ Class<? extends ValueAdapter> adapterClass = annotation.adapter();\r
+ IRangeAccessor<Range,Object> rangeAccessor = new FieldAccessor<Range,Object>(field);\r
+ Resource valueType;\r
+ if (adapterClass == IdentityAdapter.class) {\r
+ valueType = DataTypeUtils.dataTypeOfClass(g, field.getType());\r
+ } else {\r
+ try {\r
+ ValueAdapter adapter = adapterClass.newInstance();\r
+ rangeAccessor = new AdaptedRangeAccessor<Range>(rangeAccessor, adapter);\r
+ valueType = adapter.rangeTypeToDomainType(g, field.getType());\r
+ } catch (InstantiationException e) {\r
+ throw new RuntimeException(e);\r
+ } catch (IllegalAccessException e) {\r
+ throw new RuntimeException(e);\r
+ }\r
+ }\r
+ return new ValueRule<Resource,Range>(new RelatedValueAccessor(g.getResource(annotation.value()), valueType), rangeAccessor);\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.graph.annotations.factories;\r
+\r
+import java.lang.annotation.Annotation;\r
+import java.lang.reflect.Method;\r
+\r
+import org.apache.log4j.Logger;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.objmap.backward.IBackwardMapping;\r
+import org.simantics.objmap.bidirectional.IBidirectionalMappingRule;\r
+import org.simantics.objmap.exceptions.MappingException;\r
+import org.simantics.objmap.forward.IForwardMapping;\r
+import org.simantics.objmap.graph.rules.factory.IMethodRuleFactory;\r
+\r
+public class UpdateMethodFactory<Domain, Range> implements IMethodRuleFactory<Domain, Range> {\r
+\r
+ static Logger LOGGER = Logger.getLogger("org.simantics.objmap");\r
+ \r
+ @Override\r
+ public IBidirectionalMappingRule<Domain, Range> create(ReadGraph g, \r
+ Annotation annotation, \r
+ final Method method)\r
+ throws DatabaseException {\r
+ method.setAccessible(true);\r
+ return new IBidirectionalMappingRule<Domain,Range>() {\r
+ \r
+ @Override\r
+ public boolean updateRange(ReadGraph g, IForwardMapping<Domain, Range> map,\r
+ Domain domainElement, Range rangeElement)\r
+ throws MappingException {\r
+ LOGGER.info(" UpdateMethodFactory.updateRange"); \r
+ try {\r
+ return (Boolean)method.invoke(rangeElement, g, domainElement);\r
+ } catch (Exception e) {\r
+ // TODO Auto-generated catch block\r
+ e.printStackTrace();\r
+ }\r
+ return false;\r
+ }\r
+ \r
+ @Override\r
+ public boolean updateDomain(WriteGraph g, IBackwardMapping<Domain,Range> map,\r
+ Domain domainElement, Range rangeElement)\r
+ throws MappingException {\r
+ return false;\r
+ }\r
+ \r
+ public void createDomain(WriteGraph g, IBackwardMapping<Domain,Range> map, Domain domainElement, Range rangeElement) throws MappingException {\r
+ updateDomain(g, map, domainElement, rangeElement);\r
+ };\r
+ \r
+ public void createRange(ReadGraph g, IForwardMapping<Domain,Range> map, Domain domainElement, Range rangeElement) throws MappingException {\r
+ updateRange(g, map, domainElement, rangeElement);\r
+ };\r
+ };\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.graph.annotations.meta;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.ANNOTATION_TYPE) \r
+public @interface IsClassRule {\r
+ \r
+}\r
--- /dev/null
+package org.simantics.objmap.graph.annotations.meta;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.ANNOTATION_TYPE) \r
+public @interface IsCollectionRule {\r
+ \r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.graph.annotations.meta;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.ANNOTATION_TYPE) \r
+public @interface IsFieldRule {\r
+}\r
--- /dev/null
+package org.simantics.objmap.graph.annotations.meta;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.ANNOTATION_TYPE) \r
+public @interface IsGetSetRule {\r
+ \r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.graph.annotations.meta;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.ANNOTATION_TYPE) \r
+public @interface IsMethodRule {\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+/**\r
+ * \r
+ */\r
+package org.simantics.objmap.graph.impl;\r
+\r
+import org.simantics.objmap.graph.schema.ILinkType;\r
+\r
+\r
+/**\r
+ * An indication that the domain element corresponds to the range element\r
+ * in the mapping. The link type describes how source and target objects\r
+ * are updated. There are additionally flags for dirtiness of the link.\r
+ * @author Hannu Niemistö\r
+ */\r
+public class Link<Domain,Range> {\r
+ public ILinkType<Domain,Range> type;\r
+ public Domain domainElement;\r
+ public Range rangeElement;\r
+ \r
+ public boolean domainModified = false;\r
+ public boolean rangeModified = false;\r
+ public boolean removed = false;\r
+ \r
+ public Link(ILinkType<Domain,Range> type, Domain domainElement, Range rangeElement) {\r
+ this.type = type;\r
+ this.domainElement = domainElement;\r
+ this.rangeElement = rangeElement; \r
+ } \r
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.graph.impl;\r
+\r
+\r
+import gnu.trove.map.hash.THashMap;\r
+\r
+import java.util.AbstractSet;\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.Iterator;\r
+import java.util.List;\r
+import java.util.Set;\r
+\r
+import org.apache.log4j.Logger;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+\r
+import org.simantics.objmap.backward.IBackwardMapping;\r
+import org.simantics.objmap.exceptions.MappingException;\r
+import org.simantics.objmap.forward.IForwardMapping;\r
+import org.simantics.objmap.graph.IMapping;\r
+import org.simantics.objmap.graph.IMappingListener;\r
+import org.simantics.objmap.graph.schema.ILinkType;\r
+import org.simantics.objmap.graph.schema.IMappingSchema;\r
+\r
+/**\r
+ * An implementation of IMapping. The class should not be created\r
+ * directly but using methods in Mappings.\r
+ * @see org.simantics.objmap.graph.Mappings\r
+ * @author Hannu Niemistö\r
+ */\r
+public class Mapping<Domain, Range> implements IMapping<Domain, Range> {\r
+\r
+ static Logger LOGGER = Logger.getLogger("org.simantics.objmap");\r
+ \r
+ \r
+ IMappingSchema<Domain, Range> schema;\r
+ \r
+ THashMap<Domain, Link<Domain,Range>> domain = new THashMap<Domain, Link<Domain,Range>>();\r
+ THashMap<Range, Link<Domain,Range>> range = new THashMap<Range, Link<Domain,Range>>();\r
+ ArrayList<IMappingListener> listeners = new ArrayList<IMappingListener>();\r
+\r
+ ArrayList<Link<Domain,Range>> modifiedDomainLinks = new ArrayList<Link<Domain,Range>>();\r
+ ArrayList<Link<Domain,Range>> modifiedRangeLinks = new ArrayList<Link<Domain,Range>>();\r
+\r
+ boolean disposed = false;\r
+ \r
+ boolean listensDomain; \r
+ \r
+ public Mapping(IMappingSchema<Domain, Range> schema, boolean listensDomain) {\r
+ this.schema = schema;\r
+ this.listensDomain = listensDomain;\r
+ }\r
+ \r
+ private void removeLink(Link<Domain,Range> link) {\r
+ if(link.domainModified)\r
+ modifiedDomainLinks.remove(link);\r
+ if(link.rangeModified)\r
+ modifiedRangeLinks.remove(link);\r
+ link.removed = true;\r
+ }\r
+ \r
+ private void createDomain(WriteGraph g, Link<Domain,Range> link) throws MappingException {\r
+ LOGGER.info(" createDomain for " + link.rangeElement);\r
+ ILinkType<Domain,Range> type = schema.linkTypeOfRangeElement(link.rangeElement);\r
+ Domain domainElement = type.createDomainElement(g, link.rangeElement);\r
+ link.type = type;\r
+ link.domainElement = domainElement;\r
+ domain.put(domainElement, link);\r
+ type.createDomain(g, new RangeToDomain(g), domainElement, link.rangeElement);\r
+ \r
+ // TODO Should we do this only if the mapping is listening?\r
+ domainModified(link);\r
+ }\r
+ \r
+ private void createRange(ReadGraph g, Link<Domain,Range> link) throws MappingException {\r
+ ILinkType<Domain,Range> type = schema.linkTypeOfDomainElement(g, link.domainElement); \r
+ Range rangeElement = type.createRangeElement(g, link.domainElement);\r
+ \r
+ link.type = type;\r
+ link.rangeElement = rangeElement;\r
+ range.put(rangeElement, link);\r
+ type.createRange(g, new DomainToRange(g), link.domainElement, rangeElement);\r
+ }\r
+ \r
+ Set<Domain> domainSet = new AbstractSet<Domain>() {\r
+\r
+ public boolean add(Domain e) {\r
+ if(domain.containsKey(e))\r
+ return false;\r
+ Link<Domain,Range> link = new Link<Domain,Range>(null, e, null);\r
+ domain.put(e, link);\r
+ modifiedDomainLinks.add(link);\r
+ return true;\r
+ }\r
+ \r
+ public boolean contains(Object o) {\r
+ return domain.contains(o);\r
+ }\r
+ \r
+ public boolean remove(Object o) {\r
+ Link<Domain,Range> link = domain.remove(o); \r
+ if(link == null)\r
+ return false;\r
+ removeLink(link);\r
+ if(link.rangeElement != null)\r
+ range.remove(link.rangeElement);\r
+ return true; \r
+ }\r
+ \r
+ @Override\r
+ public Iterator<Domain> iterator() {\r
+ // FIXME does not implement Iterator.remove correctly\r
+ return domain.keySet().iterator();\r
+ }\r
+\r
+ @Override\r
+ public int size() {\r
+ return domain.size();\r
+ }\r
+ \r
+ };\r
+ \r
+ Set<Range> rangeSet = new AbstractSet<Range>() {\r
+\r
+ public boolean add(Range e) {\r
+ if(range.containsKey(e))\r
+ return false;\r
+ Link<Domain,Range> link = new Link<Domain,Range>(null, null, e);\r
+ range.put(e, link);\r
+ modifiedRangeLinks.add(link);\r
+ return true;\r
+ }\r
+ \r
+ public boolean contains(Object o) {\r
+ return range.contains(o);\r
+ }\r
+ \r
+ public boolean remove(Object o) {\r
+ Link<Domain,Range> link = range.remove(o); \r
+ if(link == null)\r
+ return false;\r
+ removeLink(link);\r
+ if(link.domainElement != null)\r
+ domain.remove(link.domainElement);\r
+ return true;\r
+ }\r
+ \r
+ @Override\r
+ public Iterator<Range> iterator() {\r
+ // FIXME does not implement Iterator.remove correctly\r
+ return range.keySet().iterator();\r
+ }\r
+\r
+ @Override\r
+ public int size() {\r
+ return range.size();\r
+ }\r
+ \r
+ };\r
+ \r
+ class DomainToRange implements IForwardMapping<Domain, Range> {\r
+\r
+ ReadGraph g;\r
+ \r
+ public DomainToRange(ReadGraph g) {\r
+ this.g = g;\r
+ }\r
+\r
+ @Override\r
+ public Range get(Domain element) {\r
+ Link<Domain,Range> link = domain.get(element);\r
+ if (link != null)\r
+ return link.rangeElement;\r
+ return null;\r
+ \r
+ }\r
+ \r
+ @Override\r
+ public Range map(ReadGraph graph, Domain element)\r
+ throws MappingException {\r
+ Link<Domain,Range> link = domain.get(element);\r
+ if(link == null) {\r
+ link = new Link<Domain,Range>(null, element, null);\r
+ link.domainModified = true;\r
+ modifiedDomainLinks.add(link);\r
+ domain.put(element, link); \r
+ createRange(g, link); \r
+ }\r
+ else if(link.type == null) \r
+ createRange(g, link);\r
+ return link.rangeElement;\r
+ }\r
+ \r
+ @Override\r
+ public Set<Domain> getDomain() {\r
+ return domain.keySet();\r
+ }\r
+ \r
+ };\r
+ \r
+ class RangeToDomain extends DomainToRange implements IBackwardMapping<Domain, Range> {\r
+\r
+ WriteGraph g;\r
+ \r
+ public RangeToDomain(WriteGraph g) {\r
+ super(g);\r
+ this.g = g;\r
+ }\r
+ @Override\r
+ public Domain inverseGet(Range element) {\r
+ \r
+ Link<Domain,Range> link = range.get(element);\r
+ if(link != null)\r
+ return link.domainElement;\r
+ return null;\r
+ }\r
+ \r
+ @Override\r
+ public Domain inverseMap(WriteGraph graph, Range element)\r
+ throws MappingException {\r
+ Link<Domain,Range> link = range.get(element);\r
+ if(link == null) {\r
+ link = new Link<Domain,Range>(null, null, element);\r
+ link.rangeModified = true;\r
+ modifiedRangeLinks.add(link);\r
+ range.put(element, link);\r
+ createDomain(g, link); \r
+ }\r
+ else if(link.type == null)\r
+ createDomain(g, link);\r
+ return link.domainElement;\r
+ }\r
+ \r
+ \r
+ @Override\r
+ public Set<Range> getRange() {\r
+ return range.keySet();\r
+ }\r
+ };\r
+ \r
+ @Override\r
+ public Set<Domain> getDomain() {\r
+ return domainSet;\r
+ }\r
+ \r
+ @Override\r
+ public Set<Range> getRange() {\r
+ return rangeSet;\r
+ }\r
+ \r
+ \r
+ @Override\r
+ public synchronized Collection<Domain> updateDomain(WriteGraph g) throws MappingException {\r
+ LOGGER.info("Mapping.updateDomain");\r
+ RangeToDomain map = new RangeToDomain(g);\r
+ ArrayList<Domain> updated = new ArrayList<Domain>();\r
+ while(!modifiedRangeLinks.isEmpty()) {\r
+ LOGGER.info(" modifiedRangeLinks.size() = " + modifiedRangeLinks.size());\r
+ \r
+ Link<Domain,Range> link = modifiedRangeLinks.remove(modifiedRangeLinks.size()-1);\r
+ link.rangeModified = false;\r
+ /*if(link.domainModified) {\r
+ link.domainModified = false;\r
+ modifiedDomainLinks.remove(link);\r
+ }*/\r
+ \r
+ if(link.type == null) {\r
+ createDomain(g, link);\r
+ }\r
+ \r
+ if(link.type.updateDomain(g, map, link.domainElement, link.rangeElement))\r
+ updated.add(link.domainElement);\r
+ } \r
+ if (listensDomain)\r
+ updateRange(g); //FIXME: without this listening would stop. \r
+ return updated;\r
+ }\r
+ \r
+ @Override\r
+ public synchronized Collection<Range> updateRange(ReadGraph g) throws MappingException {\r
+ LOGGER.info("Mapping.updateRange");\r
+ DomainToRange map = new DomainToRange(g);\r
+ ArrayList<Range> updated = new ArrayList<Range>();\r
+ while(!modifiedDomainLinks.isEmpty()) { \r
+ LOGGER.info(" modifiedDomainLinks.size() = " + modifiedDomainLinks.size());\r
+ \r
+ Link<Domain,Range> link = modifiedDomainLinks.remove(modifiedDomainLinks.size()-1);\r
+ link.domainModified = false;\r
+ /*if(link.rangeModified) {\r
+ link.rangeModified = false;\r
+ modifiedRangeLinks.remove(link);\r
+ }*/\r
+ \r
+ if(link.type == null) {\r
+ createRange(g, link);\r
+ }\r
+ \r
+ if(listensDomain) {\r
+ RangeUpdateRequest<Domain,Range> request = new RangeUpdateRequest<Domain,Range>(link, map, this);\r
+ try {\r
+ g.syncRequest(request, request);\r
+ } catch (DatabaseException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ // TODO check if really modified\r
+ updated.add(link.rangeElement);\r
+ }\r
+ else\r
+ if(link.type.updateRange(g, map, link.domainElement, link.rangeElement))\r
+ updated.add(link.rangeElement);\r
+ } \r
+ return updated;\r
+ }\r
+\r
+ @Override\r
+ public Range get(Domain domainElement) {\r
+ Link<Domain,Range> link = domain.get(domainElement);\r
+ if(link == null)\r
+ return null;\r
+ return link.rangeElement;\r
+ }\r
+\r
+ @Override\r
+ public Domain inverseGet(Range rangeElement) {\r
+ Link<Domain,Range> link = range.get(rangeElement);\r
+ if(link == null)\r
+ return null;\r
+ return link.domainElement;\r
+ }\r
+\r
+ @Override\r
+ public Domain inverseMap(WriteGraph g, Range rangeElement) throws MappingException {\r
+ getRange().add(rangeElement);\r
+ updateDomain(g);\r
+ return inverseGet(rangeElement);\r
+ }\r
+\r
+ @Override\r
+ public Range map(ReadGraph g, Domain domainElement) throws MappingException {\r
+ getDomain().add(domainElement);\r
+ updateRange(g);\r
+ return get(domainElement);\r
+ }\r
+\r
+ void domainModified(Link<Domain,Range> link) {\r
+ if(!link.domainModified) { \r
+ synchronized(modifiedDomainLinks) {\r
+ LOGGER.info(" domainModified for " + link.rangeElement);\r
+ link.domainModified = true;\r
+ modifiedDomainLinks.add(link);\r
+ if(modifiedDomainLinks.size() == 1) {\r
+ for(IMappingListener listener : listeners)\r
+ listener.domainModified();\r
+ }\r
+ }\r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public void domainModified(Domain domainElement) {\r
+ Link<Domain,Range> link = domain.get(domainElement);\r
+ if(link != null)\r
+ domainModified(link);\r
+ }\r
+\r
+ void rangeModified(Link<Domain,Range> link) {\r
+ if(!link.rangeModified) {\r
+ synchronized(modifiedRangeLinks) {\r
+ link.rangeModified = true;\r
+ modifiedRangeLinks.add(link);\r
+ if(modifiedRangeLinks.size() == 1) {\r
+ for(IMappingListener listener : listeners)\r
+ listener.rangeModified();\r
+ }\r
+ }\r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public void rangeModified(Range rangeElement) {\r
+ Link<Domain,Range> link = range.get(rangeElement);\r
+ if(link != null)\r
+ rangeModified(link);\r
+ }\r
+\r
+ @Override\r
+ public boolean isDomainModified() {\r
+ return !modifiedDomainLinks.isEmpty();\r
+ }\r
+\r
+ @Override\r
+ public boolean isRangeModified() {\r
+ return !modifiedRangeLinks.isEmpty();\r
+ }\r
+ \r
+ @Override\r
+ public Collection<Domain> getDomainModified() {\r
+ List<Domain> list = new ArrayList<Domain>(modifiedDomainLinks.size());\r
+ for (Link<Domain, Range> link : modifiedDomainLinks)\r
+ list.add(link.domainElement);\r
+ return list;\r
+ \r
+ }\r
+ \r
+ @Override\r
+ public Collection<Range> getRangeModified() {\r
+ List<Range> list = new ArrayList<Range>(modifiedRangeLinks.size());\r
+ for (Link<Domain, Range> link : modifiedRangeLinks)\r
+ list.add(link.rangeElement);\r
+ return list;\r
+ }\r
+\r
+ @Override\r
+ public void addMappingListener(IMappingListener listener) {\r
+ listeners.add(listener);\r
+ }\r
+\r
+ @Override\r
+ public void removeMappingListener(IMappingListener listener) {\r
+ listeners.remove(listener); \r
+ }\r
+\r
+ @Override\r
+ public Collection<Domain> getConflictingDomainElements() {\r
+ ArrayList<Domain> result = new ArrayList<Domain>();\r
+ if(modifiedDomainLinks.size() < modifiedRangeLinks.size()) {\r
+ for(Link<Domain,Range> link : modifiedDomainLinks)\r
+ if(link.rangeModified)\r
+ result.add(link.domainElement);\r
+ }\r
+ else {\r
+ for(Link<Domain,Range> link : modifiedRangeLinks)\r
+ if(link.domainModified)\r
+ result.add(link.domainElement);\r
+ }\r
+ return result;\r
+ }\r
+\r
+ @Override\r
+ public Collection<Range> getConflictingRangeElements() {\r
+ ArrayList<Range> result = new ArrayList<Range>();\r
+ if(modifiedDomainLinks.size() < modifiedRangeLinks.size()) {\r
+ for(Link<Domain,Range> link : modifiedDomainLinks)\r
+ if(link.rangeModified)\r
+ result.add(link.rangeElement);\r
+ }\r
+ else {\r
+ for(Link<Domain,Range> link : modifiedRangeLinks)\r
+ if(link.domainModified)\r
+ result.add(link.rangeElement);\r
+ }\r
+ return result;\r
+ }\r
+\r
+ @Override\r
+ public void dispose() {\r
+ disposed = true;\r
+ }\r
+ \r
+ public boolean isDisposed() {\r
+ return disposed;\r
+ }\r
+ \r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.graph.impl;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.procedure.SyncListener;\r
+import org.simantics.db.request.Read;\r
+\r
+import org.simantics.objmap.exceptions.MappingException;\r
+import org.simantics.objmap.forward.IForwardMapping;\r
+import org.simantics.objmap.graph.impl.Link;\r
+\r
+\r
+public class RangeUpdateRequest<Domain,Range> implements Read<Boolean>, SyncListener<Boolean> {\r
+\r
+ Link<Domain,Range> link;\r
+ /*\r
+ * Note that this map uses a read request that it has got from caller and \r
+ * not the one that is used in updateRange. This is intentional.\r
+ */\r
+ IForwardMapping<Domain, Range> map; // map==null is used to flag that request is performed once\r
+ Mapping<Domain, Range> mapping; // mapping==null is used as a flag the request disposed\r
+ \r
+ public RangeUpdateRequest(Link<Domain,Range> link, IForwardMapping<Domain,Range> map, Mapping<Domain,Range> mapping) {\r
+ this.link = link;\r
+ this.map = map;\r
+ this.mapping = mapping;\r
+ }\r
+\r
+ @Override\r
+ public Boolean perform(ReadGraph g) throws DatabaseException {\r
+ if(map != null) {\r
+ link.type.updateRange(g, map, link.domainElement, link.rangeElement);\r
+ map = null;\r
+ return Boolean.TRUE;\r
+ }\r
+ else if(mapping != null) {\r
+ mapping.domainModified(link);\r
+ mapping = null;\r
+ return Boolean.FALSE;\r
+ }\r
+ else\r
+ return null;\r
+ }\r
+ \r
+ @Override\r
+ public void exception(ReadGraph graph, Throwable throwable)\r
+ throws DatabaseException {\r
+ if(throwable instanceof DatabaseException)\r
+ throw (DatabaseException)throwable;\r
+ else\r
+ throw new MappingException(throwable);\r
+ }\r
+\r
+ @Override\r
+ public void execute(ReadGraph graph, Boolean result)\r
+ throws DatabaseException { \r
+ }\r
+\r
+ @Override\r
+ public boolean isDisposed() {\r
+ return mapping == null || link.removed || mapping.isDisposed();\r
+ }\r
+ \r
+ \r
+ \r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.graph.rules;\r
+\r
+import org.apache.log4j.Logger;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.objmap.backward.IBackwardMapping;\r
+import org.simantics.objmap.bidirectional.IBidirectionalMappingRule;\r
+import org.simantics.objmap.exceptions.MappingException;\r
+import org.simantics.objmap.forward.IForwardMapping;\r
+import org.simantics.objmap.graph.rules.domain.IDomainAccessor;\r
+import org.simantics.objmap.graph.rules.range.IRangeAccessor;\r
+\r
+\r
+\r
+\r
+/**\r
+ * A rule that synchronizes collection of elements between\r
+ * domain and range accessors. Elements are mapped from\r
+ * between domain and range during the synchronization.\r
+ * @author Hannu Niemistö\r
+ */\r
+public class MappedElementRule<Domain, Range> implements IBidirectionalMappingRule<Domain, Range> {\r
+ \r
+ static Logger LOGGER = Logger.getLogger("org.simantics.objmap");\r
+ \r
+ IDomainAccessor<Domain,Domain> domainAccessor;\r
+ IRangeAccessor<Range,Range> rangeAccessor;\r
+ \r
+ public MappedElementRule(IDomainAccessor<Domain,Domain> domainAccessor,\r
+ IRangeAccessor<Range,Range> rangeAccessor) {\r
+ this.domainAccessor = domainAccessor;\r
+ this.rangeAccessor = rangeAccessor;\r
+ }\r
+\r
+ @Override\r
+ public boolean updateDomain(WriteGraph g, IBackwardMapping<Domain, Range> map,\r
+ Domain domainElement, Range rangeElement)\r
+ throws MappingException {\r
+ LOGGER.info(" MappedElementRule.updateDomain");\r
+ Range value = rangeAccessor.get(rangeElement);\r
+ Domain mappedValue = value == null ? null : map.inverseMap(g, value);//map.inverseGet(value);\r
+ return domainAccessor.set(g, domainElement, mappedValue);\r
+ }\r
+\r
+ @Override\r
+ public boolean updateRange(ReadGraph g, IForwardMapping<Domain, Range> map,\r
+ Domain domainElement, Range rangeElement)\r
+ throws MappingException {\r
+ LOGGER.info(" MappedElementRule.updateRange"); \r
+ Domain value = domainAccessor.get(g, domainElement);\r
+ Range mappedValue = value == null ? null : map.map(g, value);////map.get(value);\r
+ return rangeAccessor.set(rangeElement, mappedValue);\r
+ } \r
+ \r
+ public void createDomain(WriteGraph g, IBackwardMapping<Domain,Range> map, Domain domainElement, Range rangeElement) throws MappingException {\r
+ updateDomain(g, map, domainElement, rangeElement);\r
+ };\r
+ \r
+ public void createRange(ReadGraph g, IForwardMapping<Domain,Range> map, Domain domainElement, Range rangeElement) throws MappingException {\r
+ updateRange(g, map, domainElement, rangeElement);\r
+ };\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.graph.rules;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+\r
+import org.apache.log4j.Logger;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.objmap.backward.IBackwardMapping;\r
+import org.simantics.objmap.bidirectional.IBidirectionalMappingRule;\r
+import org.simantics.objmap.exceptions.MappingException;\r
+import org.simantics.objmap.forward.IForwardMapping;\r
+import org.simantics.objmap.graph.rules.domain.IDomainAccessor;\r
+import org.simantics.objmap.graph.rules.range.IRangeAccessor;\r
+\r
+\r
+/**\r
+ * A rule that synchronizes collection of elements between\r
+ * domain and range accessors. Elements are mapped from\r
+ * between domain and range during the synchronization.\r
+ * @author Hannu Niemistö\r
+ */\r
+public class MappedElementsRule<Domain, Range> implements IBidirectionalMappingRule<Domain, Range> {\r
+\r
+ static Logger LOGGER = Logger.getLogger("org.simantics.objmap");\r
+\r
+ IDomainAccessor<Domain,Collection<Domain>> domainAccessor;\r
+ IRangeAccessor<Range,Collection<Range>> rangeAccessor;\r
+\r
+ public MappedElementsRule(IDomainAccessor<Domain,Collection<Domain>> domainAccessor,\r
+ IRangeAccessor<Range,Collection<Range>> rangeAccessor) {\r
+ this.domainAccessor = domainAccessor;\r
+ this.rangeAccessor = rangeAccessor;\r
+ }\r
+\r
+ @Override\r
+ public boolean updateDomain(WriteGraph g, IBackwardMapping<Domain, Range> map,\r
+ Domain domainElement, Range rangeElement)\r
+ throws MappingException {\r
+ LOGGER.info(" MappedElementsRule.updateDomain");\r
+ // Snapshot the accessed range value for concurrency safety.\r
+ // NOTE: still assumes that the accessed collection is concurrent or\r
+ // synchronized for toArray to be atomic.\r
+ Collection<Range> value = rangeAccessor.get(rangeElement);\r
+ Object[] rangeSnapshot = value.toArray();\r
+ ArrayList<Domain> mappedValue = new ArrayList<Domain>(rangeSnapshot.length);\r
+ for (Object obj : rangeSnapshot)\r
+ mappedValue.add(map.inverseMap(g, (Range)obj));//map.inverseGet((Range)obj));\r
+ return domainAccessor.set(g, domainElement, mappedValue);\r
+ }\r
+\r
+ @Override\r
+ public boolean updateRange(ReadGraph g, IForwardMapping<Domain, Range> map,\r
+ Domain domainElement, Range rangeElement)\r
+ throws MappingException {\r
+ LOGGER.info(" MappedElementsRule.updateRange");\r
+ Collection<Domain> value = domainAccessor.get(g, domainElement);\r
+ ArrayList<Range> mappedValue = new ArrayList<Range>(value.size());\r
+ for(Domain r : value)\r
+ mappedValue.add(map.map(g, r));//map.get(r));\r
+ return rangeAccessor.set(rangeElement, mappedValue);\r
+ }\r
+ \r
+ public void createDomain(WriteGraph g, IBackwardMapping<Domain,Range> map, Domain domainElement, Range rangeElement) throws MappingException {\r
+ updateDomain(g, map, domainElement, rangeElement);\r
+ };\r
+ \r
+ public void createRange(ReadGraph g, IForwardMapping<Domain,Range> map, Domain domainElement, Range rangeElement) throws MappingException {\r
+ updateRange(g, map, domainElement, rangeElement);\r
+ };\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.graph.rules;\r
+\r
+import org.apache.log4j.Logger;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.objmap.backward.IBackwardMapping;\r
+import org.simantics.objmap.bidirectional.IBidirectionalMappingRule;\r
+import org.simantics.objmap.exceptions.MappingException;\r
+import org.simantics.objmap.forward.IForwardMapping;\r
+import org.simantics.objmap.graph.rules.domain.IDomainAccessor;\r
+import org.simantics.objmap.graph.rules.range.IRangeAccessor;\r
+\r
+\r
+/**\r
+ * A rule that synchronizes values between domain and\r
+ * range accessors.\r
+ * @author Hannu Niemistö\r
+ */\r
+public class ValueRule<Domain, Range> implements IBidirectionalMappingRule<Domain, Range> {\r
+ \r
+ static Logger LOGGER = Logger.getLogger("org.simantics.objmap");\r
+ \r
+ IDomainAccessor<Domain,Object> domainAccessor;\r
+ IRangeAccessor<Range,Object> rangeAccessor;\r
+ \r
+ public ValueRule(IDomainAccessor<Domain,Object> domainAccessor,\r
+ IRangeAccessor<Range,Object> rangeAccessor) {\r
+ this.domainAccessor = domainAccessor;\r
+ this.rangeAccessor = rangeAccessor;\r
+ }\r
+\r
+ @Override\r
+ public boolean updateDomain(WriteGraph g, IBackwardMapping<Domain, Range> map,\r
+ Domain domainElement, Range rangeElement)\r
+ throws MappingException {\r
+ LOGGER.info(" ValueRule.updateDomain"); \r
+ Object value = rangeAccessor.get(rangeElement);\r
+ return domainAccessor.set(g, domainElement, value);\r
+ }\r
+\r
+ @Override\r
+ public boolean updateRange(ReadGraph g, IForwardMapping<Domain, Range> map,\r
+ Domain domainElement, Range rangeElement)\r
+ throws MappingException {\r
+ LOGGER.info(" ValueRule.updateRange");\r
+ Object value = domainAccessor.get(g, domainElement);\r
+ return rangeAccessor.set(rangeElement, value);\r
+ } \r
+ \r
+ public void createDomain(WriteGraph g, IBackwardMapping<Domain,Range> map, Domain domainElement, Range rangeElement) throws MappingException {\r
+ updateDomain(g, map, domainElement, rangeElement);\r
+ };\r
+ public void createRange(ReadGraph g, IForwardMapping<Domain,Range> map, Domain domainElement, Range rangeElement) throws MappingException {\r
+ updateRange(g, map, domainElement, rangeElement);\r
+ };\r
+}\r
+\r
+\r
--- /dev/null
+package org.simantics.objmap.graph.rules.adapters;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+\r
+public enum IdentityAdapter implements ValueAdapter {\r
+ INSTANCE;\r
+\r
+ @Override\r
+ public Object domainToRange(Object domainValue) {\r
+ return domainValue;\r
+ }\r
+\r
+ @Override\r
+ public Object rangeToDomain(Object rangeValue) {\r
+ return rangeValue;\r
+ }\r
+\r
+ @Override\r
+ public Resource rangeTypeToDomainType(ReadGraph graph, Class<?> rangeType) {\r
+ return null;\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.objmap.graph.rules.adapters;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+\r
+public interface ValueAdapter {\r
+ Resource rangeTypeToDomainType(ReadGraph graph, Class<?> rangeType);\r
+ Object domainToRange(Object domainValue);\r
+ Object rangeToDomain(Object rangeValue);\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.graph.rules.domain;\r
+\r
+import java.util.Arrays;\r
+import java.util.Collection;\r
+import java.util.HashMap;\r
+import java.util.Map;\r
+\r
+import org.apache.log4j.Logger;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.Statement;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.objmap.exceptions.MappingException;\r
+import org.simantics.objmap.graph.annotations.factories.CompoundRelatedGetSetValueRuleFactory;\r
+\r
+/**\r
+ * \r
+ * @author Marko Luukkainen\r
+ */\r
+public class CompoundValueAccessor implements IDomainAccessor<Resource,Object> {\r
+\r
+ static Logger LOGGER = Logger.getLogger("org.simantics.objmap");\r
+ \r
+ Resource objRelation;\r
+ Resource objType;\r
+ Resource valRelation;\r
+\r
+ public CompoundValueAccessor(Resource objRelation, Resource objType, Resource valRelation) {\r
+ this.objRelation = objRelation;\r
+ this.objType = objType;\r
+ this.valRelation = valRelation;\r
+ }\r
+\r
+ @Override\r
+ public Object get(ReadGraph g, Resource element) throws MappingException {\r
+ try {\r
+ Layer0 l0 = Layer0.getInstance(g);\r
+ LOGGER.info(" CompoundValueAccessor.get");\r
+ Collection<Statement> coll = g.getStatements(element, objRelation);\r
+ Map<String,Object> map = new HashMap<String, Object>();\r
+ for (Statement c : coll) {\r
+ String name = g.getRelatedValue(c.getObject(), l0.HasName);\r
+ if (!map.containsKey(name) || !c.isAsserted(element))\r
+ map.put(name, g.getRelatedValue(c.getObject(), valRelation));\r
+ }\r
+ return map;\r
+ } catch (DatabaseException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public boolean set(WriteGraph g, Resource element, Object v)\r
+ throws MappingException {\r
+ try {\r
+ Layer0 l0 = Layer0.getInstance(g);\r
+ LOGGER.info(" CompoundValueAccessor.set");\r
+ Map<String,Object> values = (Map<String, Object>)v;\r
+ \r
+ Collection<Statement> coll = g.getStatements(element, objRelation);\r
+ Map<String,Statement> stmMap = new HashMap<String, Statement>();\r
+ Map<String,Object> valueMap = new HashMap<String, Object>();\r
+ for (Statement c : coll) {\r
+ String name = g.getRelatedValue(c.getObject(), l0.HasName);\r
+ if (!stmMap.containsKey(name) || !c.isAsserted(element)) {\r
+ stmMap.put(name, c);\r
+ valueMap.put(name, g.getRelatedValue(c.getObject(), valRelation));\r
+ }\r
+ }\r
+ boolean changed = false;\r
+ for (String key : values.keySet()) {\r
+ Object value = values.get(key);\r
+ if (value.equals(valueMap.get(key)))\r
+ continue;\r
+ changed = true;\r
+ Statement stm = stmMap.get(key);\r
+ if (stm == null || stm.isAsserted(element)) {\r
+ Resource obj = g.newResource();\r
+ g.claim(obj, l0.InstanceOf, objType);\r
+ g.claimLiteral(obj, l0.HasName, key);\r
+ g.claim(element, objRelation, obj);\r
+ stm = getStatement(g, element, objRelation, obj);\r
+ }\r
+ \r
+ Statement valueStatement = g.getPossibleStatement(stm.getObject(), valRelation);\r
+ Resource valueType = CompoundRelatedGetSetValueRuleFactory.dataTypeOfClass(g, value.getClass());\r
+ if(valueStatement == null) {\r
+ \r
+ Resource valueResource = g.newResource();\r
+ g.claim(valueResource, Layer0.getInstance(g).InstanceOf, null, valueType);\r
+ g.claim(stm.getObject(), valRelation, valueResource);\r
+ g.claimValue(valueResource, value); \r
+ } else {\r
+ \r
+ \r
+ if (!valueStatement.isAsserted(stm.getObject()))\r
+ g.claimValue(valueStatement.getObject(), value);\r
+ else {\r
+ Resource valueResource = g.newResource();\r
+ g.claim(valueResource, Layer0.getInstance(g).InstanceOf, null,\r
+ valueType);\r
+ g.claim(stm.getObject(), valRelation, valueResource);\r
+ g.claimValue(valueResource, value);\r
+ }\r
+ }\r
+ }\r
+ return changed;\r
+ \r
+ } catch (DatabaseException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ \r
+ }\r
+ \r
+ private Statement getStatement(ReadGraph g, Resource s, Resource p, Resource o) throws DatabaseException{\r
+ for (Statement stm : g.getStatements(s, p)) {\r
+ if (stm.getObject().equals(o))\r
+ return stm;\r
+ }\r
+ return null;\r
+ }\r
+ \r
+ private boolean equals(Object o1, Object o2) {\r
+ if (o1 instanceof boolean[])\r
+ Arrays.equals((boolean[])o1,(boolean[])o2);\r
+ if (o1 instanceof int[])\r
+ Arrays.equals((int[])o1,(int[])o2);\r
+ if (o1 instanceof float[])\r
+ Arrays.equals((float[])o1,(float[])o2);\r
+ if (o1 instanceof double[])\r
+ Arrays.equals((double[])o1,(double[])o2);\r
+ if (o1 instanceof byte[])\r
+ Arrays.equals((byte[])o1,(byte[])o2);\r
+ return o1.equals(o2);\r
+ \r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.graph.rules.domain;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.objmap.exceptions.MappingException;\r
+\r
+\r
+/**\r
+ * Provides access to some property of domain elements.\r
+ * @author Hannu Niemistö\r
+ */\r
+public interface IDomainAccessor<Domain,T> {\r
+ T get(ReadGraph g, Domain element) throws MappingException;\r
+ boolean set(WriteGraph g, Domain element, T value) throws MappingException;\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.graph.rules.domain;\r
+\r
+import java.util.Arrays;\r
+import java.util.Collection;\r
+\r
+import org.apache.log4j.Logger;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+\r
+/**\r
+ * Static utility methods for rule implementations.\r
+ * @author Hannu Niemistö\r
+ */\r
+public class MappingUtils {\r
+\r
+ static Logger LOGGER = Logger.getLogger("org.simantics.objmap");\r
+ \r
+ /**\r
+ * Adds and removes statements to/from the database so that <code>objects</code>\r
+ * will be exactly the objects connected to <code>subject</code> by <code>predicate</code>.\r
+ * Returns true if the method made modifications to the database.\r
+ */\r
+ public static boolean synchronizeStatements(WriteGraph g, Resource subject, Resource predicate, Resource[] objects,\r
+ boolean deleteExtraObjects) \r
+ throws DatabaseException {\r
+ Collection<Resource> currentObjects0 = g.getObjects(subject, predicate);\r
+ Resource[] currentObjects = currentObjects0.toArray(new Resource[currentObjects0.size()]);\r
+ \r
+ Arrays.sort(objects);\r
+ Arrays.sort(currentObjects);\r
+ \r
+ boolean modified = false;\r
+ int i=0, j=0; \r
+ if(currentObjects.length > 0 && objects.length > 0)\r
+ while(true) {\r
+ int cmp = currentObjects[i].compareTo(objects[j]);\r
+ if(cmp < 0) {\r
+ LOGGER.info(" remove statement");\r
+ if(deleteExtraObjects)\r
+ g.deny(currentObjects[i]);\r
+ else\r
+ g.denyStatement(subject, predicate, currentObjects[i]); \r
+ modified = true;\r
+ ++i;\r
+ if(i >= currentObjects.length)\r
+ break;\r
+ }\r
+ else if(cmp > 0) {\r
+ LOGGER.info(" add statement");\r
+ g.claim(subject, predicate, objects[j]);\r
+ modified = true;\r
+ ++j;\r
+ if(j >= objects.length)\r
+ break;\r
+ }\r
+ else {\r
+ ++i; ++j;\r
+ if(i >= currentObjects.length)\r
+ break;\r
+ if(j >= objects.length)\r
+ break;\r
+ }\r
+ }\r
+ while(i < currentObjects.length) {\r
+ if(deleteExtraObjects)\r
+ g.deny(currentObjects[i]);\r
+ else\r
+ g.denyStatement(subject, predicate, currentObjects[i]);\r
+ modified = true;\r
+ ++i;\r
+ }\r
+ while(j < objects.length) {\r
+ g.claim(subject, predicate, objects[j]);\r
+ modified = true;\r
+ ++j;\r
+ }\r
+ return modified;\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.graph.rules.domain;\r
+\r
+import org.apache.log4j.Logger;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.objmap.exceptions.MappingException;\r
+\r
+/**\r
+ * Accesses a resource attached to the element by given functional relation.\r
+ * @author Hannu Niemistö\r
+ */\r
+public class RelatedObjectAccessor implements IDomainAccessor<Resource,Resource> {\r
+\r
+ static Logger LOGGER = Logger.getLogger("org.simantics.objmap");\r
+ \r
+ Resource relation;\r
+ \r
+ public RelatedObjectAccessor(Resource relation) {\r
+ this.relation = relation;\r
+ }\r
+\r
+ @Override\r
+ public Resource get(ReadGraph g, Resource element) throws MappingException {\r
+ try {\r
+ LOGGER.info(" RelatedObjectAccessor.get");\r
+ return g.getPossibleObject(element, relation);\r
+ } catch (DatabaseException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public boolean set(WriteGraph g, Resource element, Resource value)\r
+ throws MappingException {\r
+ try {\r
+ LOGGER.info(" RelatedObjectAccessor.set");\r
+ Resource resource = g.getPossibleObject(element, relation);\r
+ if(resource == null) {\r
+ if(value == null)\r
+ return false;\r
+ g.claim(element, relation, value);\r
+ return true;\r
+ }\r
+ else if(resource.equals(value))\r
+ return false;\r
+ else {\r
+ g.deny(element, relation);\r
+ if(value != null)\r
+ g.claim(element, relation, value);\r
+ return true;\r
+ }\r
+ } catch (DatabaseException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ \r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.graph.rules.domain;\r
+\r
+import java.util.Collection;\r
+\r
+import org.apache.log4j.Logger;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.objmap.exceptions.MappingException;\r
+\r
+/**\r
+ * Accesses the set of objects attached to the element by the given relation.\r
+ * @author Hannu Niemistö\r
+ */\r
+public class RelatedObjectsAccessor implements IDomainAccessor<Resource,Collection<Resource>> {\r
+\r
+ static Logger LOGGER = Logger.getLogger("org.simantics.objmap");\r
+ \r
+ Resource relation;\r
+ boolean deleteExtraObjects;\r
+\r
+ public RelatedObjectsAccessor(Resource relation, boolean deleteExtraObjects) {\r
+ super();\r
+ this.relation = relation;\r
+ this.deleteExtraObjects = deleteExtraObjects;\r
+ }\r
+\r
+ @Override\r
+ public Collection<Resource> get(ReadGraph g, Resource element) throws MappingException {\r
+ try {\r
+ LOGGER.info(" RelatedObjectsAccessor.get");\r
+ return g.getObjects(element, relation);\r
+ } catch (DatabaseException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public boolean set(WriteGraph g, Resource element, Collection<Resource> value)\r
+ throws MappingException {\r
+ try {\r
+ LOGGER.info(" RelatedObjectsAccessor.set");\r
+ return MappingUtils.synchronizeStatements(g, element, relation, \r
+ value.toArray(new Resource[value.size()]), deleteExtraObjects);\r
+ } catch (DatabaseException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ \r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.graph.rules.domain;\r
+\r
+import java.util.Collection;\r
+\r
+import org.apache.log4j.Logger;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.utils.OrderedSetUtils;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.objmap.exceptions.MappingException;\r
+\r
+/**\r
+ * Accesses the set of objects attached to the element by the given relation.\r
+ * @author Hannu Niemistö\r
+ */\r
+public class RelatedOrderedSetElementsAccessor implements IDomainAccessor<Resource, Collection<Resource>> {\r
+\r
+ static Logger LOGGER = Logger.getLogger("org.simantics.objmap");\r
+ \r
+ boolean deleteExtraObjects;\r
+\r
+ public RelatedOrderedSetElementsAccessor(boolean deleteExtraObjects) {\r
+ super();\r
+ this.deleteExtraObjects = deleteExtraObjects;\r
+ }\r
+\r
+ @Override\r
+ public Collection<Resource> get(ReadGraph g, Resource element) throws MappingException {\r
+ try {\r
+ LOGGER.info(" RelatedOrderedSetElementsAccessor.get");\r
+ return OrderedSetUtils.toList(g, element);\r
+ } catch (DatabaseException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public boolean set(WriteGraph g, Resource element, Collection<Resource> value)\r
+ throws MappingException {\r
+ try {\r
+ LOGGER.info(" RelatedOrderedSetElementsAccessor.set");\r
+ return OrderedSetUtils.set(g, element, value);\r
+ // FIXME Implement deleteExtraObjects\r
+ } catch (DatabaseException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ \r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.graph.rules.domain;\r
+\r
+import java.util.Arrays;\r
+\r
+import org.apache.log4j.Logger;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.Statement;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.objmap.exceptions.MappingException;\r
+\r
+/**\r
+ * Accesses a value attached to the element by given functional relation.\r
+ * @author Hannu Niemist�\r
+ */\r
+public class RelatedValueAccessor implements IDomainAccessor<Resource,Object> {\r
+\r
+ static Logger LOGGER = Logger.getLogger("org.simantics.objmap");\r
+ \r
+ Resource relation;\r
+ Resource valueType;\r
+\r
+ public RelatedValueAccessor(Resource relation, Resource valueType) {\r
+ this.relation = relation;\r
+ this.valueType = valueType;\r
+ }\r
+\r
+ @Override\r
+ public Object get(ReadGraph g, Resource element) throws MappingException {\r
+ try {\r
+ LOGGER.info(" RelatedValueAccessor.get");\r
+ Resource valueResource = g.getPossibleObject(element, relation);\r
+ if(valueResource == null)\r
+ return null;\r
+ return g.getValue(valueResource);\r
+ } catch (DatabaseException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public boolean set(WriteGraph g, Resource element, Object value)\r
+ throws MappingException {\r
+ try {\r
+ LOGGER.info(" RelatedValueAccessor.set");\r
+ Statement valueStatement = g.getPossibleStatement(element, relation);\r
+ if(valueStatement == null) {\r
+ if(value == null)\r
+ return false;\r
+ Resource valueResource = g.newResource();\r
+ g.claim(valueResource, Layer0.getInstance(g).InstanceOf, null,\r
+ valueType);\r
+ g.claim(element, relation, valueResource);\r
+ g.claimValue(valueResource, value); \r
+ return true;\r
+ }\r
+ else {\r
+ if(value == null) {\r
+ if (!valueStatement.isAsserted(element)) {\r
+ g.deny(valueStatement.getObject());\r
+ return true;\r
+ } else {\r
+ return false;\r
+ }\r
+ } \r
+ Object currentValue = g.getValue(valueStatement.getObject());\r
+ if(equals(currentValue,value))\r
+ return false;\r
+ if (!valueStatement.isAsserted(element))\r
+ g.claimValue(valueStatement.getObject(), value);\r
+ else {\r
+ Resource valueResource = g.newResource();\r
+ g.claim(valueResource, Layer0.getInstance(g).InstanceOf, null,\r
+ valueType);\r
+ g.claim(element, relation, valueResource);\r
+ g.claimValue(valueResource, value);\r
+ }\r
+ return true;\r
+ }\r
+ } catch (DatabaseException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ \r
+ }\r
+ \r
+ private boolean equals(Object o1, Object o2) {\r
+ if (o1 instanceof boolean[])\r
+ Arrays.equals((boolean[])o1,(boolean[])o2);\r
+ if (o1 instanceof int[])\r
+ Arrays.equals((int[])o1,(int[])o2);\r
+ if (o1 instanceof float[])\r
+ Arrays.equals((float[])o1,(float[])o2);\r
+ if (o1 instanceof double[])\r
+ Arrays.equals((double[])o1,(double[])o2);\r
+ if (o1 instanceof byte[])\r
+ Arrays.equals((byte[])o1,(byte[])o2);\r
+ return o1.equals(o2);\r
+ \r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.graph.rules.factory;\r
+\r
+import java.lang.annotation.Annotation;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.objmap.bidirectional.IBidirectionalMappingRule;\r
+\r
+public interface IClassRuleFactory<Domain, Range> {\r
+ IBidirectionalMappingRule<Domain, Range> create(ReadGraph g, Annotation annotation, Class<?> clazz) throws DatabaseException;\r
+}\r
--- /dev/null
+package org.simantics.objmap.graph.rules.factory;\r
+\r
+import java.lang.annotation.Annotation;\r
+import java.lang.reflect.Method;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.objmap.bidirectional.IBidirectionalMappingRule;\r
+\r
+public interface ICollectionRuleFactory<Domain,Range> {\r
+ IBidirectionalMappingRule<Domain, Range> create(ReadGraph g, Annotation annotation, Method getter, Method adder, Method remover) throws DatabaseException;\r
+ boolean isAdder(Annotation getterAnnotation, Annotation annotation);\r
+ boolean isRemover(Annotation getterAnnotation, Annotation annotation);\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.graph.rules.factory;\r
+\r
+import java.lang.annotation.Annotation;\r
+import java.lang.reflect.Field;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.objmap.bidirectional.IBidirectionalMappingRule;\r
+\r
+public interface IFieldRuleFactory<Domain, Range> {\r
+ IBidirectionalMappingRule<Domain, Range> create(ReadGraph g, Annotation annotation, Field field) throws DatabaseException;\r
+}\r
--- /dev/null
+package org.simantics.objmap.graph.rules.factory;\r
+\r
+import java.lang.annotation.Annotation;\r
+import java.lang.reflect.Method;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.objmap.bidirectional.IBidirectionalMappingRule;\r
+\r
+public interface IGetSetRuleFactory<Domain,Range> {\r
+ IBidirectionalMappingRule<Domain, Range> create(ReadGraph g, Annotation annotation, Method getter, Method setter) throws DatabaseException;\r
+ boolean isSetter(Annotation getterAnnotation, Annotation annotation);\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.graph.rules.factory;\r
+\r
+import java.lang.annotation.Annotation;\r
+import java.lang.reflect.Method;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.objmap.bidirectional.IBidirectionalMappingRule;\r
+\r
+public interface IMethodRuleFactory<Domain, Range> {\r
+ IBidirectionalMappingRule<Domain, Range> create(ReadGraph g, Annotation annotation, Method method) throws DatabaseException;\r
+}\r
--- /dev/null
+package org.simantics.objmap.graph.rules.range;\r
+\r
+import org.simantics.objmap.exceptions.MappingException;\r
+import org.simantics.objmap.graph.rules.adapters.ValueAdapter;\r
+\r
+\r
+\r
+public class AdaptedRangeAccessor<Range> implements IRangeAccessor<Range,Object> {\r
+ IRangeAccessor<Range,Object> baseAccessor;\r
+ ValueAdapter adapter;\r
+ \r
+ public AdaptedRangeAccessor(IRangeAccessor<Range,Object> baseAccessror,\r
+ ValueAdapter adapter) {\r
+ this.baseAccessor = baseAccessror;\r
+ this.adapter = adapter;\r
+ }\r
+\r
+ @Override\r
+ public Object get(Range element) throws MappingException {\r
+ return adapter.rangeToDomain(baseAccessor.get(element)); \r
+ }\r
+ \r
+ @Override\r
+ public boolean set(Range element, Object value) throws MappingException {\r
+ return baseAccessor.set(element, adapter.domainToRange(value));\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.objmap.graph.rules.range;\r
+\r
+import java.lang.reflect.InvocationTargetException;\r
+import java.lang.reflect.Method;\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+\r
+import org.simantics.objmap.exceptions.MappingException;\r
+\r
+\r
+/**\r
+ * Accessor for mapped collections. \r
+ * Uses three methods:\r
+ * - Getter: returns the collection.\r
+ * - Adder: adds one item into the collection.\r
+ * - Remover: removes one item from the collection. \r
+ * \r
+ * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
+ *\r
+ * @param <T>\r
+ */\r
+public class CollectionAccessor<Range,T> implements IRangeAccessor<Range,Collection<T>> {\r
+ \r
+ private Method getter;\r
+ private Method adder;\r
+ private Method remover;\r
+ \r
+ public CollectionAccessor(Method getter, Method adder, Method remover) {\r
+ this.getter = getter;\r
+ this.adder = adder;\r
+ this.remover = remover;\r
+ }\r
+ \r
+ @SuppressWarnings("unchecked")\r
+ public java.util.Collection<T> get(Object element) throws MappingException {\r
+ try {\r
+ return (Collection<T>) getter.invoke(element);\r
+ } catch (IllegalArgumentException e) {\r
+ throw new MappingException(e);\r
+ } catch (IllegalAccessException e) {\r
+ throw new MappingException(e);\r
+ } catch (InvocationTargetException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ };\r
+\r
+ @Override\r
+ public boolean set(Range element, Collection<T> value)\r
+ throws MappingException {\r
+ java.util.Collection<T> current = get(element);\r
+ Collection<T> adding = new ArrayList<T>();\r
+ Collection<T> removing = new ArrayList<T>();\r
+ for (T e : current) {\r
+ if (!value.contains(e))\r
+ removing.add(e);\r
+ }\r
+ for (T e : value) {\r
+ if (!current.contains(e))\r
+ adding.add(e);\r
+ }\r
+ \r
+ try {\r
+ for (T e : removing) {\r
+ remover.invoke(element, e);\r
+ }\r
+ \r
+ for (T e : adding) {\r
+ adder.invoke(element, e);\r
+ }\r
+ } catch (IllegalArgumentException e) {\r
+ throw new MappingException(e);\r
+ } catch (IllegalAccessException e) {\r
+ throw new MappingException(e);\r
+ } catch (InvocationTargetException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ return removing.size() > 0 || adding.size() > 0;\r
+ \r
+ }\r
+}\r
--- /dev/null
+package org.simantics.objmap.graph.rules.range;\r
+\r
+import java.lang.reflect.InvocationTargetException;\r
+import java.lang.reflect.Method;\r
+\r
+import org.simantics.objmap.exceptions.MappingException;\r
+\r
+\r
+/**\r
+ * Accessor for mapped value. Uses two methods:\r
+ * - Getter: returns the current value.\r
+ * - Setter: sets the current value. The value may be null. (if setter parameter is primitive, null value is not mapped).\r
+ * \r
+ * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
+ *\r
+ * @param <T>\r
+ */\r
+public class CompoundGetSetValueAccessor<Range,T> implements IRangeAccessor<Range,T> {\r
+ \r
+ private Method getter;\r
+ private Method setter;\r
+ private boolean primitive;\r
+ \r
+ public CompoundGetSetValueAccessor(Method getter, Method setter) {\r
+ this.getter = getter;\r
+ this.setter = setter;\r
+ this.primitive = setter.getParameterTypes()[0].isPrimitive();\r
+ }\r
+ \r
+ @SuppressWarnings("unchecked")\r
+ public T get(Range element) throws MappingException {\r
+ try {\r
+ return (T) getter.invoke(element);\r
+ } catch (IllegalArgumentException e) {\r
+ throw new MappingException(e);\r
+ } catch (IllegalAccessException e) {\r
+ throw new MappingException(e);\r
+ } catch (InvocationTargetException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ };\r
+\r
+ @Override\r
+ public boolean set(Range element, T value)\r
+ throws MappingException {\r
+ if (value == null && primitive)\r
+ return false;\r
+ if (equal(get(element),value))\r
+ return false;\r
+ try {\r
+ setter.invoke(element, value);\r
+ } catch (IllegalArgumentException e) {\r
+ throw new MappingException(e);\r
+ } catch (IllegalAccessException e) {\r
+ throw new MappingException(e);\r
+ } catch (InvocationTargetException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ return true;\r
+ \r
+ }\r
+ \r
+ private boolean equal(Object v1, Object v2) {\r
+ if (v1 == null) {\r
+ if (v2 == null)\r
+ return true;\r
+ return false;\r
+ } else if (v2 == null) {\r
+ return false;\r
+ }\r
+ return v1.equals(v2);\r
+ }\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.graph.rules.range;\r
+\r
+import java.lang.reflect.Field;\r
+\r
+import org.apache.log4j.Logger;\r
+import org.simantics.objmap.exceptions.MappingException;\r
+\r
+\r
+/**\r
+ * Accesses the given field of the element.\r
+ * @author Hannu Niemistö\r
+ */\r
+public class FieldAccessor<Range,T> implements IRangeAccessor<Range,T> {\r
+ \r
+ static Logger LOGGER = Logger.getLogger("org.simantics.objmap");\r
+ \r
+ Field field;\r
+\r
+ public FieldAccessor(Field field) {\r
+ this.field = field;\r
+ }\r
+\r
+ @Override\r
+ public T get(Range element) throws MappingException {\r
+ try {\r
+ T result = (T)field.get(element);\r
+ \r
+ if(LOGGER.isInfoEnabled())\r
+ LOGGER.info(" FieldAccessor.get " +\r
+ field.getName() + " -> " + result\r
+ );\r
+ \r
+ return result;\r
+ } catch (IllegalArgumentException e) {\r
+ throw new MappingException(e);\r
+ } catch (IllegalAccessException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public boolean set(Range element, T value) throws MappingException {\r
+ try {\r
+ Object currentValue = field.get(element);\r
+ \r
+ if(LOGGER.isInfoEnabled())\r
+ LOGGER.info(" FieldAccessor.set " +\r
+ field.getName() + " " + currentValue + \r
+ " -> " + value\r
+ );\r
+ \r
+ if(value == null \r
+ ? (currentValue == null || field.getType().isPrimitive()) \r
+ : value.equals(currentValue))\r
+ return false; \r
+ field.set(element, value);\r
+ return true;\r
+ } catch (IllegalArgumentException e) {\r
+ throw new MappingException(e);\r
+ } catch (IllegalAccessException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ } \r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.graph.rules.range;\r
+\r
+import java.lang.reflect.Field;\r
+\r
+import org.simantics.objmap.exceptions.MappingException;\r
+\r
+\r
+/**\r
+ * Accesses the given field of the element.\r
+ * @author Hannu Niemist�\r
+ */\r
+public class FieldAccessorWithDefault<Range,T> extends FieldAccessor<Range,T> {\r
+ \r
+ T defaultValue;\r
+\r
+ public FieldAccessorWithDefault(Field field, T defaultValue) {\r
+ super(field);\r
+ this.defaultValue = defaultValue;\r
+ }\r
+\r
+ @Override\r
+ public T get(Range element) throws MappingException {\r
+ T value = super.get(element);\r
+ if(value == null)\r
+ return defaultValue;\r
+ else\r
+ return value;\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.objmap.graph.rules.range;\r
+\r
+import java.lang.reflect.InvocationTargetException;\r
+import java.lang.reflect.Method;\r
+\r
+import org.simantics.objmap.exceptions.MappingException;\r
+\r
+\r
+/**\r
+ * Accessor for mapped objects. Uses two methods:\r
+ * - Getter: returns the current object.\r
+ * - Setter: sets the current object. The object may be null.\r
+ * \r
+ * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
+ *\r
+ * @param <T>\r
+ */\r
+public class GetSetObjectAccessor<Range,T> implements IRangeAccessor<Range,T> {\r
+ \r
+ private Method getter;\r
+ private Method setter;\r
+ \r
+ \r
+ public GetSetObjectAccessor(Method getter, Method setter) {\r
+ this.getter = getter;\r
+ this.setter = setter;\r
+ \r
+ }\r
+ \r
+ @SuppressWarnings("unchecked")\r
+ public T get(Range element) throws MappingException {\r
+ try {\r
+ return (T) getter.invoke(element);\r
+ } catch (IllegalArgumentException e) {\r
+ throw new MappingException(e);\r
+ } catch (IllegalAccessException e) {\r
+ throw new MappingException(e);\r
+ } catch (InvocationTargetException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ };\r
+\r
+ @Override\r
+ public boolean set(Range element, T value)\r
+ throws MappingException { \r
+ try {\r
+ setter.invoke(element, value);\r
+ } catch (IllegalArgumentException e) {\r
+ throw new MappingException(e);\r
+ } catch (IllegalAccessException e) {\r
+ throw new MappingException(e);\r
+ } catch (InvocationTargetException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ return true;\r
+ \r
+ }\r
+}\r
--- /dev/null
+package org.simantics.objmap.graph.rules.range;\r
+\r
+import java.lang.reflect.InvocationTargetException;\r
+import java.lang.reflect.Method;\r
+\r
+import org.simantics.objmap.exceptions.MappingException;\r
+\r
+\r
+/**\r
+ * Accessor for mapped value. Uses two methods:\r
+ * - Getter: returns the current value.\r
+ * - Setter: sets the current value. The value may be null. (if setter parameter is primitive, null value is not mapped).\r
+ * \r
+ * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
+ *\r
+ * @param <T>\r
+ */\r
+public class GetSetValueAccessor<Range,T> implements IRangeAccessor<Range,T> {\r
+ \r
+ private Method getter;\r
+ private Method setter;\r
+ private boolean primitive;\r
+ \r
+ public GetSetValueAccessor(Method getter, Method setter) {\r
+ this.getter = getter;\r
+ this.setter = setter;\r
+ this.primitive = setter.getParameterTypes()[0].isPrimitive();\r
+ }\r
+ \r
+ @SuppressWarnings("unchecked")\r
+ public T get(Range element) throws MappingException {\r
+ try {\r
+ return (T) getter.invoke(element);\r
+ } catch (IllegalArgumentException e) {\r
+ throw new MappingException(e);\r
+ } catch (IllegalAccessException e) {\r
+ throw new MappingException(e);\r
+ } catch (InvocationTargetException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ };\r
+\r
+ @Override\r
+ public boolean set(Range element, T value)\r
+ throws MappingException {\r
+ if (value == null && primitive)\r
+ return false;\r
+ if (equal(get(element),value))\r
+ return false;\r
+ try {\r
+ setter.invoke(element, value);\r
+ } catch (IllegalArgumentException e) {\r
+ throw new MappingException(e);\r
+ } catch (IllegalAccessException e) {\r
+ throw new MappingException(e);\r
+ } catch (InvocationTargetException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ return true;\r
+ \r
+ }\r
+ \r
+ private boolean equal(Object v1, Object v2) {\r
+ if (v1 == null) {\r
+ if (v2 == null)\r
+ return true;\r
+ return false;\r
+ } else if (v2 == null) {\r
+ return false;\r
+ }\r
+ return v1.equals(v2);\r
+ }\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.graph.rules.range;\r
+\r
+import org.simantics.objmap.exceptions.MappingException;\r
+\r
+\r
+\r
+/**\r
+ * Provides access to some property of range elements.\r
+ * @author Hannu Niemistö\r
+ */\r
+public interface IRangeAccessor<Range,T> {\r
+ T get(Range element) throws MappingException;\r
+ boolean set(Range element, T value) throws MappingException;\r
+}\r
--- /dev/null
+package org.simantics.objmap.graph.schema;\r
+\r
+//import org.apache.log4j.Logger;\r
+import org.eclipse.core.runtime.IAdaptable;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+\r
+import org.simantics.objmap.backward.IBackwardMapping;\r
+import org.simantics.objmap.exceptions.MappingException;\r
+import org.simantics.objmap.forward.IForwardMapping;\r
+\r
+/**\r
+ * A link type that is associated with adaptable resource (ReadGraph.getAdapter(Resource,Class)). \r
+ * The adapted object must implement IAdaptable interface for returning the original Resource. \r
+ * \r
+ * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
+ *\r
+ */\r
+public class AdaptedLinkType<Range> implements ILinkType<Resource,Range> {\r
+\r
+ \r
+ //static Logger LOGGER = Logger.getLogger("org.simantics.objmap");\r
+ \r
+ Resource domainType;\r
+ Class<?> rangeType;\r
+ \r
+ \r
+ public AdaptedLinkType(Resource domainType, Class<?> rangeType) {\r
+ this.domainType = domainType;\r
+ this.rangeType = rangeType;\r
+ }\r
+ \r
+ @Override\r
+ public Resource createDomainElement(WriteGraph g, Range rangeElement)\r
+ throws MappingException {\r
+ try {\r
+ IAdaptable adaptable = (IAdaptable)rangeElement;\r
+ Resource res = (Resource)adaptable.getAdapter(Resource.class);\r
+ if (res == null)\r
+ throw new NullPointerException();\r
+ return res;\r
+ } catch (Exception e) {\r
+ throw new MappingException("Adapted object must implement IAdaptable interface to return the source Resource.", e);\r
+ }\r
+ \r
+ }\r
+ \r
+ @Override\r
+ public Range createRangeElement(ReadGraph g, Resource domainElement)\r
+ throws MappingException {\r
+ try {\r
+ return (Range)g.adapt(domainElement, rangeType);\r
+ } catch (DatabaseException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ }\r
+ \r
+ public void createDomain(WriteGraph graph, IBackwardMapping<Resource,Range> mapping, Resource domainElement, Range rangeElement) throws MappingException {\r
+ \r
+ };\r
+ \r
+ public void createRange(ReadGraph graph, org.simantics.objmap.forward.IForwardMapping<Resource,Range> mapping, Resource domainElement, Range rangeElement) throws MappingException {\r
+ \r
+ };\r
+ \r
+ public boolean updateDomain(WriteGraph g, IBackwardMapping<Resource,Range> map, Resource domainElement, Range rangeElement) throws MappingException {\r
+ return false;\r
+ }\r
+ \r
+ public boolean updateRange(ReadGraph g, IForwardMapping<Resource,Range> map, Resource domainElement, Range rangeElement) throws MappingException {\r
+ return false;\r
+ }\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.graph.schema;\r
+\r
+\r
+\r
+import gnu.trove.map.hash.THashMap;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.common.utils.NameUtils;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.objmap.exceptions.MappingException;\r
+\r
+\r
+/**\r
+ * \r
+ */\r
+public class DefaultSchema implements IMappingSchema<Resource,Object> {\r
+\r
+ THashMap<Resource, ILinkType<Resource,Object>> domainLinkTypes = \r
+ new THashMap<Resource, ILinkType<Resource,Object>>();\r
+ THashMap<Class<?>, ILinkType<Resource,Object>> rangeLinkTypes = \r
+ new THashMap<Class<?>, ILinkType<Resource,Object>>();\r
+ \r
+ public void addLinkType(SimpleLinkType<Object> linkType) {\r
+ domainLinkTypes.put(linkType.domainType, linkType);\r
+ rangeLinkTypes.put(linkType.rangeType, linkType);\r
+ }\r
+ \r
+ public void addLinkType(AdaptedLinkType<Object> linkType) {\r
+ domainLinkTypes.put(linkType.domainType, linkType);\r
+ rangeLinkTypes.put(linkType.rangeType, linkType);\r
+ }\r
+ \r
+ @Override\r
+ public ILinkType<Resource,Object> linkTypeOfDomainElement(ReadGraph g, Resource element) throws MappingException { \r
+ try {\r
+ \r
+ for(Resource type : g.getTypes(element)) {\r
+\r
+ ILinkType<Resource,Object> linkType = domainLinkTypes.get(type);\r
+ if(linkType != null) return linkType;\r
+ \r
+ }\r
+ \r
+ throw new MappingException("Didn't find a link type for " +\r
+ NameUtils.getSafeName(g, element) + ".");\r
+ \r
+ } catch (DatabaseException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public ILinkType<Resource,Object> linkTypeOfRangeElement(Object element) throws MappingException {\r
+ ILinkType<Resource,Object> type = rangeLinkTypes.get(element.getClass());\r
+ if(type == null) {\r
+ for (Class<?> clazz : element.getClass().getInterfaces()) {\r
+ type = rangeLinkTypes.get(clazz);\r
+ if (type != null)\r
+ return type;\r
+ \r
+ }\r
+ throw new MappingException("Didn't find a link type for " + element + ".");\r
+ }\r
+ return type;\r
+ }\r
+\r
+ \r
+ public ILinkType<Resource,Object> linkTypeOfDomainType(ReadGraph g, Resource type) { \r
+ return domainLinkTypes.get(type);\r
+ }\r
+ \r
+ public ILinkType<Resource,Object> linkTypeOfRangeType(Class<?> clazz) {\r
+ ILinkType<Resource,Object> type = rangeLinkTypes.get(clazz);\r
+ if(type == null) {\r
+ for (Class<?> c : clazz.getInterfaces()) {\r
+ type = rangeLinkTypes.get(clazz);\r
+ if (type != null)\r
+ return type;\r
+ \r
+ }\r
+ }\r
+ return null;\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.objmap.graph.schema;\r
+\r
+import java.lang.reflect.InvocationTargetException;\r
+import java.lang.reflect.Method;\r
+import java.util.ArrayList;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.utils.NameUtils;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.objmap.bidirectional.IBidirectionalMappingRule;\r
+import org.simantics.objmap.exceptions.MappingException;\r
+import org.simantics.objmap.graph.annotations.GetType;\r
+import org.simantics.objmap.graph.annotations.SetType;\r
+\r
+public class DynamicSimpleLinkType<Range> extends SimpleLinkType<Range>{\r
+\r
+ protected Method typeGetter;\r
+ protected Method typeSetter;\r
+ \r
+ public DynamicSimpleLinkType(Resource domainType, Class<?> rangeType, ArrayList<IBidirectionalMappingRule<Resource, Range>> rules) {\r
+ super(domainType, rangeType, rules);\r
+ findTypeGetter(rangeType);\r
+ }\r
+\r
+ public DynamicSimpleLinkType(Resource domainType, Class<?> rangeType) {\r
+ super(domainType, rangeType);\r
+ findTypeGetter(rangeType);\r
+ }\r
+ \r
+ private void findTypeGetter(Class<?> clazz) {\r
+ for (Method m : clazz.getDeclaredMethods()) {\r
+ m.setAccessible(true);\r
+ GetType t = m.getAnnotation(GetType.class);\r
+ if (t != null) {\r
+ typeGetter = m;\r
+ }\r
+ SetType t2 = m.getAnnotation(SetType.class);\r
+ if (t2 != null) {\r
+ typeSetter = m;\r
+ }\r
+ }\r
+ if (typeGetter == null || typeSetter == null) {\r
+ Class<?> superClazz = clazz.getSuperclass();\r
+ if (superClazz != Object.class)\r
+ findTypeGetter(superClazz);\r
+ if (typeGetter == null || typeSetter == null) {\r
+ throw new RuntimeException("Cannot find dynamic type methods for class " + clazz.getSimpleName()); \r
+ }\r
+ }\r
+ \r
+ \r
+ }\r
+ \r
+ @Override\r
+ public Resource createDomainElement(WriteGraph g, Range rangeElement)\r
+ throws MappingException {\r
+ try {\r
+ String typeUri = (String)typeGetter.invoke(rangeElement, null);\r
+ if(LOGGER.isInfoEnabled())\r
+ LOGGER.info("SimpleLinkType.createDomainElement " +\r
+ rangeElement.toString()\r
+ );\r
+ Resource actualDomainType = g.getResource(typeUri);\r
+ Resource result = g.newResource();\r
+ //g.claim(result, Layer0.getInstance(g).InstanceOf, null, domainType);\r
+ g.claim(result, Layer0.getInstance(g).InstanceOf, null, actualDomainType);\r
+ return result;\r
+ } catch(DatabaseException e) {\r
+ throw new MappingException(e);\r
+ } catch (IllegalArgumentException e) {\r
+ throw new MappingException(e);\r
+ } catch (IllegalAccessException e) {\r
+ throw new MappingException(e);\r
+ } catch (InvocationTargetException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public Range createRangeElement(ReadGraph g, Resource domainElement)\r
+ throws MappingException {\r
+ try {\r
+ if(LOGGER.isInfoEnabled())\r
+ try { \r
+ LOGGER.info("SimpleLinkType.createRangeElement " +\r
+ NameUtils.getSafeName(g, domainElement)\r
+ );\r
+ } catch(DatabaseException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ Range r = (Range)rangeType.newInstance();\r
+ Resource type = g.getSingleType(domainElement, domainType);\r
+ String uri = g.getURI(type);\r
+ typeSetter.invoke(r, uri);\r
+ return r;\r
+ } catch (InstantiationException e) {\r
+ throw new MappingException(e);\r
+ } catch (IllegalAccessException e) {\r
+ throw new MappingException(e);\r
+ } catch (DatabaseException e) {\r
+ throw new MappingException(e);\r
+ } catch (IllegalArgumentException e) {\r
+ throw new MappingException(e);\r
+ } catch (InvocationTargetException e) {\r
+ throw new MappingException(e);\r
+ } \r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.graph.schema;\r
+\r
+import org.simantics.objmap.backward.IBackwardLinkType;\r
+import org.simantics.objmap.bidirectional.IBidirectionalMappingRule;\r
+import org.simantics.objmap.forward.IForwardLinkType;\r
+\r
+/**\r
+ * Contains rules for how a link should be created and maintained.\r
+ * @author Hannu Niemistö\r
+ */\r
+public interface ILinkType<Domain,Range> extends IBidirectionalMappingRule<Domain, Range>, IBackwardLinkType<Domain,Range>, IForwardLinkType<Domain,Range> {\r
+ /**\r
+ * Creates a domain element based on known range element.\r
+ */\r
+ //Resource createDomainElement(WriteGraph g, Object rangeElement) throws MappingException;\r
+ \r
+ /**\r
+ * Creates a range element based on known domain element.\r
+ */\r
+ //Object createRangeElement(ReadGraph g, Resource domainElement) throws MappingException;\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.graph.schema;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.objmap.exceptions.MappingException;\r
+\r
+/**\r
+ * Specifies the link types of new elements added to a mapping.\r
+ * @author Hannu Niemistö\r
+ */\r
+public interface IMappingSchema<Domain,Range> {\r
+ /**\r
+ * @return Link type that should be used for the element.\r
+ */\r
+ ILinkType<Domain,Range> linkTypeOfDomainElement(ReadGraph g, Domain element) throws MappingException;\r
+ \r
+ /**\r
+ * @return Link type that should be used for the element.\r
+ */\r
+ ILinkType<Domain,Range> linkTypeOfRangeElement(Range element) throws MappingException;\r
+}\r
--- /dev/null
+package org.simantics.objmap.graph.schema;\r
+\r
+import java.lang.annotation.Annotation;\r
+import java.lang.reflect.Field;\r
+import java.lang.reflect.Method;\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.objmap.bidirectional.IBidirectionalMappingRule;\r
+import org.simantics.objmap.graph.annotations.CompoundRelatedGetValue;\r
+import org.simantics.objmap.graph.annotations.DynamicGraphType;\r
+import org.simantics.objmap.graph.annotations.GraphType;\r
+import org.simantics.objmap.graph.annotations.HasCollectionAdder;\r
+import org.simantics.objmap.graph.annotations.HasCollectionRemover;\r
+import org.simantics.objmap.graph.annotations.HasSetter;\r
+import org.simantics.objmap.graph.annotations.OptionalRelatedElements;\r
+import org.simantics.objmap.graph.annotations.RelatedElements;\r
+import org.simantics.objmap.graph.annotations.RelatedElementsGet;\r
+import org.simantics.objmap.graph.annotations.RelatedGetObj;\r
+import org.simantics.objmap.graph.annotations.RelatedGetValue;\r
+import org.simantics.objmap.graph.annotations.RelatedOrderedSetElements;\r
+import org.simantics.objmap.graph.annotations.RelatedValue;\r
+import org.simantics.objmap.graph.annotations.UpdateMethod;\r
+import org.simantics.objmap.graph.annotations.factories.CompoundRelatedGetSetValueRuleFactory;\r
+import org.simantics.objmap.graph.annotations.factories.OptionalRelatedElementsRuleFactory;\r
+import org.simantics.objmap.graph.annotations.factories.RelatedElementsRuleFactory;\r
+import org.simantics.objmap.graph.annotations.factories.RelatedElementsRuleFactory2;\r
+import org.simantics.objmap.graph.annotations.factories.RelatedGetSetObjRuleFactory;\r
+import org.simantics.objmap.graph.annotations.factories.RelatedGetSetValueRuleFactory;\r
+import org.simantics.objmap.graph.annotations.factories.RelatedOrderedSetElementsRuleFactory;\r
+import org.simantics.objmap.graph.annotations.factories.RelatedValueRuleFactory;\r
+import org.simantics.objmap.graph.annotations.factories.UpdateMethodFactory;\r
+import org.simantics.objmap.graph.annotations.meta.IsClassRule;\r
+import org.simantics.objmap.graph.annotations.meta.IsCollectionRule;\r
+import org.simantics.objmap.graph.annotations.meta.IsFieldRule;\r
+import org.simantics.objmap.graph.annotations.meta.IsGetSetRule;\r
+import org.simantics.objmap.graph.annotations.meta.IsMethodRule;\r
+import org.simantics.objmap.graph.rules.factory.IClassRuleFactory;\r
+import org.simantics.objmap.graph.rules.factory.ICollectionRuleFactory;\r
+import org.simantics.objmap.graph.rules.factory.IFieldRuleFactory;\r
+import org.simantics.objmap.graph.rules.factory.IGetSetRuleFactory;\r
+import org.simantics.objmap.graph.rules.factory.IMethodRuleFactory;\r
+\r
+\r
+public class MappingSchemas {\r
+ /**\r
+ * Creates a new SimpleLinkType based on the annotations in the given class.\r
+ * @throws IllegalAccessException \r
+ * @throws InstantiationException \r
+ * @see GraphType\r
+ * @see RelatedValue\r
+ */\r
+ public static SimpleLinkType<Object> fromAnnotations(ReadGraph g, Class<?> clazz) throws DatabaseException, InstantiationException, IllegalAccessException {\r
+ GraphType graphType = clazz.getAnnotation(GraphType.class);\r
+ \r
+ if (graphType != null) {\r
+ ArrayList<IBidirectionalMappingRule<Resource, Object>> rules = new ArrayList<IBidirectionalMappingRule<Resource, Object>>();\r
+ collectRulesFromAnnotations(g, clazz, rules);\r
+ \r
+ return new SimpleLinkType<Object>(g.getResource(graphType.value()), clazz, rules); \r
+ }\r
+ DynamicGraphType dynamicType = clazz.getAnnotation(DynamicGraphType.class);\r
+ if (dynamicType != null) {\r
+ ArrayList<IBidirectionalMappingRule<Resource, Object>> rules = new ArrayList<IBidirectionalMappingRule<Resource, Object>>();\r
+ collectRulesFromAnnotations(g, clazz, rules);\r
+ \r
+ return new DynamicSimpleLinkType<Object>(g.getResource(dynamicType.value()), clazz, rules);\r
+ }\r
+ throw new IllegalArgumentException("Class " + clazz.toString() + " does not contain annotations.");\r
+ }\r
+ \r
+ public static void collectRulesFromAnnotations(ReadGraph g, Class<?> clazz, Collection<IBidirectionalMappingRule<Resource, Object>> rules) throws DatabaseException, InstantiationException, IllegalAccessException {\r
+ Class<?> superclass = clazz.getSuperclass();\r
+ if(superclass != null)\r
+ collectRulesFromAnnotations(g, superclass, rules);\r
+ \r
+ for(Annotation annotation : clazz.getAnnotations()) {\r
+\r
+ IsClassRule tag = annotation.annotationType().getAnnotation(IsClassRule.class);\r
+ if(tag!= null) {\r
+ rules.add(createClassRule(g, annotation, clazz).create(g, annotation, clazz));\r
+ }\r
+ }\r
+\r
+ for(Field f : clazz.getDeclaredFields()) {\r
+ f.setAccessible(true);\r
+\r
+ for(Annotation annotation : f.getAnnotations()) {\r
+\r
+ IsFieldRule tag = annotation.annotationType().getAnnotation(IsFieldRule.class);\r
+ if(tag != null) {\r
+ rules.add(createFieldRule(g, annotation, f).create(g, annotation, f));\r
+ }\r
+ }\r
+ }\r
+\r
+ for(Method m : clazz.getDeclaredMethods()) {\r
+ m.setAccessible(true);\r
+\r
+ for(Annotation annotation : m.getAnnotations()) {\r
+ IsMethodRule tag = \r
+ annotation.annotationType().getAnnotation(IsMethodRule.class);\r
+ if(tag != null) {\r
+ rules.add(createMethodRule(g, annotation, m).create(g, annotation, m));\r
+ }\r
+ }\r
+ }\r
+ \r
+ for (Method m : clazz.getDeclaredMethods()) {\r
+ m.setAccessible(true);\r
+ for (Annotation annotation : m.getAnnotations()) {\r
+ Class<? extends Annotation> annotationType = annotation.annotationType();\r
+\r
+ IsGetSetRule tag = \r
+ annotationType.getAnnotation(IsGetSetRule.class);\r
+ if (tag != null) {\r
+ \r
+ HasSetter setterAnnType = annotationType.getAnnotation(HasSetter.class);\r
+ \r
+ Class<? extends Annotation> setterAnn = setterAnnType.value();\r
+ \r
+ Method getter = m;\r
+ \r
+ IGetSetRuleFactory<Resource,Object> ruleFactory = createGetSetRuleFactory(g, annotation, getter);\r
+ \r
+ \r
+ Method setter = null;\r
+ \r
+ for (Method m2 : clazz.getDeclaredMethods()) {\r
+ Annotation set = m2.getAnnotation(setterAnn);\r
+ if (set != null && ruleFactory.isSetter(annotation, set))\r
+ setter = m2;\r
+ }\r
+\r
+ rules.add(ruleFactory.create(g, annotation, getter, setter));\r
+ }\r
+ \r
+ }\r
+ }\r
+ \r
+ for (Method m : clazz.getDeclaredMethods()) {\r
+ m.setAccessible(true);\r
+ for (Annotation annotation : m.getAnnotations()) {\r
+ Class<? extends Annotation> annotationType = annotation.annotationType();\r
+\r
+ IsCollectionRule tag = \r
+ annotationType.getAnnotation(IsCollectionRule.class);\r
+ if (tag != null) {\r
+ \r
+ HasCollectionAdder adderAnnType = annotationType.getAnnotation(HasCollectionAdder.class);\r
+ HasCollectionRemover removerAnnType = annotationType.getAnnotation(HasCollectionRemover.class);\r
+ \r
+ Class<? extends Annotation> adderAnn = adderAnnType.value();\r
+ Class<? extends Annotation> removerAnn = removerAnnType.value();\r
+ \r
+ Method getter = m;\r
+ \r
+ ICollectionRuleFactory<Resource,Object> ruleFactory = createCollectionRuleFactory(g, annotation, getter);\r
+ \r
+ \r
+ Method adder = null;\r
+ Method remover = null;\r
+ \r
+ for (Method m2 : clazz.getDeclaredMethods()) {\r
+ Annotation add = m2.getAnnotation(adderAnn);\r
+ Annotation rem = m2.getAnnotation(removerAnn);\r
+ if (add != null && ruleFactory.isAdder(annotation, add))\r
+ adder = m2;\r
+ if (rem != null && ruleFactory.isRemover(annotation, rem))\r
+ remover = m2;\r
+ }\r
+ \r
+ \r
+ \r
+ rules.add(ruleFactory.create(g, annotation, getter,adder,remover));\r
+ }\r
+ \r
+ }\r
+ }\r
+ }\r
+ \r
+ public static IClassRuleFactory<Resource, Object> createClassRule(ReadGraph g, Annotation annotation, Class<?> clazz) {\r
+ return null;\r
+ }\r
+ \r
+ public static IFieldRuleFactory<Resource,Object> createFieldRule(ReadGraph g, Annotation annotation, Field field) {\r
+ if (annotation.annotationType().equals(RelatedElements.class))\r
+ return new RelatedElementsRuleFactory<Object>();\r
+ if (annotation.annotationType().equals(RelatedValue.class))\r
+ return new RelatedValueRuleFactory<Object>();\r
+ if (annotation.annotationType().equals(OptionalRelatedElements.class))\r
+ return new OptionalRelatedElementsRuleFactory<Object>();\r
+ if (annotation.annotationType().equals(RelatedOrderedSetElements.class))\r
+ return new RelatedOrderedSetElementsRuleFactory<Object>();\r
+ return null;\r
+ }\r
+ \r
+ public static IMethodRuleFactory<Resource, Object> createMethodRule(ReadGraph g, Annotation annotation, Method m) {\r
+ if (annotation.annotationType().equals(UpdateMethod.class))\r
+ return new UpdateMethodFactory<Resource,Object>();\r
+ return null;\r
+ }\r
+ \r
+ public static IGetSetRuleFactory<Resource,Object> createGetSetRuleFactory(ReadGraph g, Annotation annotation, Method getter) {\r
+ if (annotation.annotationType().equals(RelatedGetValue.class))\r
+ return new RelatedGetSetValueRuleFactory<Object>();\r
+ if (annotation.annotationType().equals(RelatedGetObj.class))\r
+ return new RelatedGetSetObjRuleFactory<Object>();\r
+ if (annotation.annotationType().equals(CompoundRelatedGetValue.class))\r
+ return new CompoundRelatedGetSetValueRuleFactory<Object>();\r
+ return null;\r
+ }\r
+ \r
+ public static ICollectionRuleFactory<Resource,Object> createCollectionRuleFactory(ReadGraph g, Annotation annotation, Method getter) {\r
+ if (annotation.annotationType().equals(RelatedElementsGet.class))\r
+ return new RelatedElementsRuleFactory2<Object>();\r
+ return null;\r
+ }\r
+ \r
+ /**\r
+ * Creates a new SimpleLinkType based on the annotations in the given class.\r
+ * @throws IllegalAccessException \r
+ * @throws InstantiationException \r
+ * @see GraphType\r
+ * @see RelatedValue\r
+ */\r
+ \r
+ public static AdaptedLinkType<Object> fromAdaptable(ReadGraph g, String type, Class<?> clazz) throws DatabaseException, InstantiationException, IllegalAccessException {\r
+ \r
+ \r
+ return new AdaptedLinkType<Object>(g.getResource(type), clazz); \r
+ }\r
+ \r
+ \r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.graph.schema;\r
+\r
+import java.util.ArrayList;\r
+\r
+import org.apache.log4j.Logger;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.utils.NameUtils;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.objmap.backward.IBackwardMapping;\r
+import org.simantics.objmap.bidirectional.IBidirectionalMappingRule;\r
+import org.simantics.objmap.exceptions.MappingException;\r
+import org.simantics.objmap.forward.IForwardMapping;\r
+\r
+\r
+/**\r
+ * A link type that is associated with single domain and range type (class).\r
+ * SimpleLinkType is composed of simpler rules whose combination determines\r
+ * its update policy.\r
+ * @author Hannu Niemist�\r
+ */\r
+public class SimpleLinkType<Range> implements ILinkType<Resource,Range> {\r
+ \r
+ static Logger LOGGER = Logger.getLogger("org.simantics.objmap");\r
+ \r
+ public Resource domainType;\r
+ public Class<?> rangeType;\r
+ ArrayList<IBidirectionalMappingRule<Resource, Range>> rules;\r
+ \r
+ public SimpleLinkType(Resource domainType, Class<?> rangeType,\r
+ ArrayList<IBidirectionalMappingRule<Resource, Range>> rules) {\r
+ this.domainType = domainType;\r
+ this.rangeType = rangeType;\r
+ this.rules = rules;\r
+ }\r
+\r
+ public SimpleLinkType(Resource domainType, Class<?> rangeType) {\r
+ this(domainType, rangeType, new ArrayList<IBidirectionalMappingRule<Resource, Range>>());\r
+ }\r
+\r
+ /**\r
+ * Adds a new rule to this link type that is enforced\r
+ * during updates.\r
+ */\r
+ public void addRule(IBidirectionalMappingRule<Resource, Range> rule) {\r
+ rules.add(rule);\r
+ }\r
+ \r
+ @Override\r
+ public Resource createDomainElement(WriteGraph g, Range rangeElement)\r
+ throws MappingException {\r
+ try {\r
+ if(LOGGER.isInfoEnabled())\r
+ LOGGER.info("SimpleLinkType.createDomainElement " +\r
+ rangeElement.toString()\r
+ );\r
+ Resource result = g.newResource();\r
+ g.claim(result, Layer0.getInstance(g).InstanceOf, null, domainType);\r
+ return result;\r
+ } catch(DatabaseException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ }\r
+ @Override\r
+ public Range createRangeElement(ReadGraph g, Resource domainElement)\r
+ throws MappingException {\r
+ try {\r
+ if(LOGGER.isInfoEnabled())\r
+ try { \r
+ LOGGER.info("SimpleLinkType.createRangeElement " +\r
+ NameUtils.getSafeName(g, domainElement)\r
+ );\r
+ } catch(DatabaseException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ return (Range)rangeType.newInstance();\r
+ } catch (InstantiationException e) {\r
+ throw new MappingException(e);\r
+ } catch (IllegalAccessException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ }\r
+ \r
+ public void createDomain(WriteGraph graph, IBackwardMapping<Resource,Range> mapping, Resource domainElement, Range rangeElement) throws MappingException {\r
+ updateDomain(graph, mapping, domainElement, rangeElement);\r
+ };\r
+ \r
+ public void createRange(ReadGraph graph, org.simantics.objmap.forward.IForwardMapping<Resource,Range> mapping, Resource domainElement, Range rangeElement) throws MappingException {\r
+ updateRange(graph, mapping, domainElement, rangeElement);\r
+ };\r
+ \r
+ public boolean updateDomain(WriteGraph g, IBackwardMapping<Resource,Range> map, Resource domainElement, Range rangeElement) throws MappingException {\r
+ if(LOGGER.isInfoEnabled())\r
+ try { \r
+ LOGGER.info("SimpleLinkType.updateDomain " +\r
+ NameUtils.getSafeName(g, domainElement) + " " +\r
+ rangeElement.toString()\r
+ );\r
+ } catch(DatabaseException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ \r
+ boolean updated = false;\r
+ for(IBidirectionalMappingRule<Resource, Range> rule : rules)\r
+ updated |= rule.updateDomain(g, map, domainElement, rangeElement);\r
+ return updated;\r
+ }\r
+ \r
+ public boolean updateRange(ReadGraph g, IForwardMapping<Resource,Range> map, Resource domainElement, Range rangeElement) throws MappingException {\r
+ \r
+ if(LOGGER.isInfoEnabled())\r
+ try { \r
+ LOGGER.info("SimpleLinkType.updateRange " +\r
+ NameUtils.getSafeName(g, domainElement) + " " +\r
+ rangeElement.toString()\r
+ );\r
+ } catch(DatabaseException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ \r
+ boolean updated = false;\r
+ for(IBidirectionalMappingRule<Resource, Range> rule : rules)\r
+ updated |= rule.updateRange(g, map, domainElement, rangeElement);\r
+ return updated;\r
+ }\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.graph.schema;\r
+\r
+\r
+import java.util.Stack;\r
+\r
+import gnu.trove.map.hash.THashMap;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.common.utils.NameUtils;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.objmap.exceptions.MappingException;\r
+\r
+\r
+/**\r
+ * An implementation of IMappingSchema that contains\r
+ * only SimpleLinkTypes. The link type of any domain\r
+ * element is based solely on its type in database and\r
+ * the link type of any range element is based on its class.\r
+ * @author Hannu Niemistö\r
+ */\r
+public class SimpleSchema implements IMappingSchema<Resource,Object> {\r
+\r
+ THashMap<Resource, ILinkType<Resource,Object>> domainLinkTypes = \r
+ new THashMap<Resource, ILinkType<Resource,Object>>();\r
+ THashMap<Class<?>, ILinkType<Resource,Object>> rangeLinkTypes = \r
+ new THashMap<Class<?>, ILinkType<Resource,Object>>();\r
+ \r
+ public void addLinkType(SimpleLinkType<Object> linkType) {\r
+ domainLinkTypes.put(linkType.domainType, linkType);\r
+ rangeLinkTypes.put(linkType.rangeType, linkType);\r
+ }\r
+ \r
+ public void addLinkType(AdaptedLinkType<Object> linkType) {\r
+ domainLinkTypes.put(linkType.domainType, linkType);\r
+ rangeLinkTypes.put(linkType.rangeType, linkType);\r
+ }\r
+ \r
+ @Override\r
+ public ILinkType<Resource,Object> linkTypeOfDomainElement(ReadGraph g, Resource element) throws MappingException { \r
+ try {\r
+ \r
+ for(Resource type : g.getTypes(element)) {\r
+\r
+ ILinkType<Resource,Object> linkType = domainLinkTypes.get(type);\r
+ if(linkType != null) return linkType;\r
+ \r
+ }\r
+ \r
+ throw new MappingException("Didn't find a link type for " + NameUtils.getSafeName(g, element) + ".");\r
+ \r
+ } catch (DatabaseException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public ILinkType<Resource,Object> linkTypeOfRangeElement(Object element) throws MappingException {\r
+ ILinkType<Resource,Object> type = rangeLinkTypes.get(element.getClass());\r
+ if(type == null) {\r
+ Stack<Class<?>> clazzes = new Stack<Class<?>>();\r
+ for (Class<?> clazz : element.getClass().getInterfaces()) {\r
+ clazzes.add(clazz);\r
+ }\r
+ clazzes.add(element.getClass().getSuperclass());\r
+ \r
+ \r
+ while (!clazzes.isEmpty()) {\r
+ Class<?> clazz = clazzes.pop();\r
+ \r
+ type = rangeLinkTypes.get(clazz);\r
+ if (type != null)\r
+ return type;\r
+ for (Class<?> c : clazz.getInterfaces())\r
+ clazzes.add(c);\r
+ \r
+ }\r
+ throw new MappingException("Didn't find a link type for " + element.getClass() + ".");\r
+ }\r
+ return type;\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.objmap.internal;\r
+\r
+import org.simantics.objmap.bidirectional.IBidirectionalLinkType;\r
+\r
+public class BidirectionalLink<Domain, Range> {\r
+ IBidirectionalLinkType<Domain, Range> linkType;\r
+ Domain domainElement;\r
+ Range rangeElement;\r
+ \r
+ boolean domainModified;\r
+ boolean rangeModified;\r
+ \r
+ public BidirectionalLink(IBidirectionalLinkType<Domain, Range> linkType,\r
+ Domain domainElement, Range rangeElement) {\r
+ this.linkType = linkType;\r
+ this.domainElement = domainElement;\r
+ this.rangeElement = rangeElement;\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.objmap.internal;\r
+\r
+import gnu.trove.map.hash.THashMap;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.Collections;\r
+import java.util.Set;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.objmap.bidirectional.IBidirectionalLinkType;\r
+import org.simantics.objmap.bidirectional.IBidirectionalMapping;\r
+import org.simantics.objmap.bidirectional.IBidirectionalMappingSchema;\r
+import org.simantics.objmap.exceptions.MappingException;\r
+\r
+public class BidirectionalMapping<Domain, Range> implements IBidirectionalMapping<Domain, Range> {\r
+\r
+ IBidirectionalMappingSchema<Domain, Range> schema;\r
+ THashMap<Domain, BidirectionalLink<Domain, Range>> forwardMap =\r
+ new THashMap<Domain, BidirectionalLink<Domain, Range>>();\r
+ THashMap<Range, BidirectionalLink<Domain, Range>> backwardMap =\r
+ new THashMap<Range, BidirectionalLink<Domain, Range>>();\r
+ \r
+ ArrayList<BidirectionalLink<Domain, Range>> modifiedDomain = new ArrayList<BidirectionalLink<Domain, Range>>();\r
+ ArrayList<BidirectionalLink<Domain, Range>> modifiedRange = new ArrayList<BidirectionalLink<Domain, Range>>();\r
+ \r
+ private void markDomainModified(BidirectionalLink<Domain, Range> link) {\r
+ if(!link.domainModified) {\r
+ link.domainModified = true;\r
+ modifiedDomain.add(link);\r
+ }\r
+ }\r
+ \r
+ private void markRangeModified(BidirectionalLink<Domain, Range> link) {\r
+ if(!link.rangeModified) {\r
+ link.rangeModified = true;\r
+ modifiedRange.add(link);\r
+ }\r
+ }\r
+ \r
+ public BidirectionalMapping(IBidirectionalMappingSchema<Domain, Range> schema) {\r
+ this.schema = schema;\r
+ }\r
+\r
+ private BidirectionalLink<Domain, Range> addLink(IBidirectionalLinkType<Domain, Range> linkType, Domain domainElement, Range rangeElement) {\r
+ BidirectionalLink<Domain, Range> link = \r
+ new BidirectionalLink<Domain, Range>(linkType, domainElement, rangeElement);\r
+ forwardMap.put(domainElement, link);\r
+ backwardMap.put(rangeElement, link);\r
+ return link;\r
+ }\r
+ \r
+ @Override\r
+ public Set<Domain> getDomain() {\r
+ return Collections.unmodifiableSet(forwardMap.keySet());\r
+ }\r
+\r
+ @Override\r
+ public Range get(Domain domainElement) {\r
+ BidirectionalLink<Domain, Range> link = forwardMap.get(domainElement);\r
+ if(link == null)\r
+ return null;\r
+ return link.rangeElement;\r
+ }\r
+\r
+ @Override\r
+ public Range map(ReadGraph graph, Domain domainElement) throws MappingException {\r
+ Range result = get(domainElement);\r
+ if(result == null) {\r
+ IBidirectionalLinkType<Domain, Range> linkType = \r
+ schema.linkTypeOfDomainElement(graph, domainElement);\r
+ Range rangeElement = linkType.createRangeElement(graph, domainElement);\r
+ addLink(linkType, domainElement, rangeElement);\r
+ linkType.createRange(graph, this, domainElement, rangeElement);\r
+ }\r
+ return result;\r
+ }\r
+ \r
+ public Collection<Range> updateRange(ReadGraph graph) throws MappingException {\r
+ ArrayList<Range> updated = new ArrayList<Range>(Math.max(10, modifiedDomain.size())); \r
+ for(BidirectionalLink<Domain, Range> link : modifiedDomain) {\r
+ link.domainModified = false;\r
+ if(link.linkType.updateRange(graph, this, link.domainElement, link.rangeElement))\r
+ updated.add(link.rangeElement);\r
+ }\r
+ modifiedDomain.clear();\r
+ return updated; \r
+ }\r
+\r
+ @Override\r
+ public Set<Range> getRange() {\r
+ return Collections.unmodifiableSet(backwardMap.keySet());\r
+ }\r
+\r
+ @Override\r
+ public Domain inverseGet(Range rangeElement) {\r
+ BidirectionalLink<Domain, Range> link = backwardMap.get(rangeElement);\r
+ if(link == null)\r
+ return null;\r
+ return link.domainElement;\r
+ }\r
+\r
+ @Override\r
+ public Domain inverseMap(WriteGraph graph, Range rangeElement)\r
+ throws MappingException {\r
+ Domain result = inverseGet(rangeElement);\r
+ if(result == null) {\r
+ IBidirectionalLinkType<Domain, Range> linkType = \r
+ schema.linkTypeOfRangeElement(graph, rangeElement);\r
+ Domain domainElement = linkType.createDomainElement(graph, rangeElement);\r
+ addLink(linkType, domainElement, rangeElement);\r
+ linkType.createDomain(graph, this, domainElement, rangeElement);\r
+ }\r
+ return result;\r
+ }\r
+ \r
+ public Collection<Domain> updateDomain(WriteGraph graph) throws MappingException {\r
+ ArrayList<Domain> updated = new ArrayList<Domain>(Math.max(10, modifiedRange.size())); \r
+ for(BidirectionalLink<Domain, Range> link : modifiedRange) {\r
+ link.rangeModified = false;\r
+ if(link.linkType.updateDomain(graph, this, link.domainElement, link.rangeElement))\r
+ updated.add(link.domainElement);\r
+ }\r
+ modifiedDomain.clear();\r
+ return updated; \r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.objmap.internal;\r
+\r
+import gnu.trove.map.hash.THashMap;\r
+\r
+import java.util.Collections;\r
+import java.util.Set;\r
+\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.objmap.backward.IBackwardLinkType;\r
+import org.simantics.objmap.backward.IBackwardMapping;\r
+import org.simantics.objmap.backward.IBackwardMappingSchema;\r
+import org.simantics.objmap.exceptions.MappingException;\r
+\r
+/**\r
+ * An unidirectional (from range to domain) mapping that does not support removals.\r
+ * \r
+ * @author Hannu Niemistö\r
+ */\r
+public class MonotoneBackwardMapping<Domain, Range> implements IBackwardMapping<Domain, Range> {\r
+\r
+ IBackwardMappingSchema<Domain, Range> schema;\r
+ THashMap<Range, Domain> map = new THashMap<Range, Domain>();\r
+ \r
+ public MonotoneBackwardMapping(IBackwardMappingSchema<Domain, Range> schema) {\r
+ this.schema = schema;\r
+ }\r
+\r
+ @Override\r
+ public Set<Range> getRange() {\r
+ return Collections.unmodifiableSet(map.keySet());\r
+ }\r
+\r
+ @Override\r
+ public Domain inverseGet(Range rangeElement) {\r
+ return map.get(rangeElement);\r
+ }\r
+\r
+ @Override\r
+ public Domain inverseMap(WriteGraph graph, Range rangeElement) throws MappingException {\r
+ Domain result = inverseGet(rangeElement);\r
+ if(result == null) {\r
+ IBackwardLinkType<Domain, Range> linkType = \r
+ schema.linkTypeOfRangeElement(graph, rangeElement);\r
+ // Two phase creation makes cyclic references possible\r
+ Domain domainElement = linkType.createDomainElement(graph, rangeElement);\r
+ map.put(rangeElement, domainElement);\r
+ linkType.createDomain(graph, this, domainElement, rangeElement);\r
+ }\r
+ return result;\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.objmap.internal;\r
+\r
+import gnu.trove.map.hash.THashMap;\r
+\r
+import java.util.Collections;\r
+import java.util.Set;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.objmap.exceptions.MappingException;\r
+import org.simantics.objmap.forward.IForwardLinkType;\r
+import org.simantics.objmap.forward.IForwardMapping;\r
+import org.simantics.objmap.forward.IForwardMappingSchema;\r
+\r
+public class MonotoneForwardMapping<Domain, Range> implements IForwardMapping<Domain, Range> {\r
+\r
+ IForwardMappingSchema<Domain, Range> schema;\r
+ THashMap<Domain, Range> map = new THashMap<Domain, Range>();\r
+ \r
+ public MonotoneForwardMapping(IForwardMappingSchema<Domain, Range> schema) {\r
+ this.schema = schema;\r
+ }\r
+\r
+ @Override\r
+ public Set<Domain> getDomain() {\r
+ return Collections.unmodifiableSet(map.keySet());\r
+ }\r
+\r
+ @Override\r
+ public Range get(Domain domainElement) {\r
+ return map.get(domainElement);\r
+ }\r
+\r
+ @Override\r
+ public Range map(ReadGraph graph, Domain domainElement) throws MappingException {\r
+ Range result = get(domainElement);\r
+ if(result == null) {\r
+ IForwardLinkType<Domain, Range> linkType = \r
+ schema.linkTypeOfDomainElement(graph, domainElement);\r
+ // Two phase creation makes cyclic references possible\r
+ Range rangeElement = linkType.createRangeElement(graph, domainElement);\r
+ map.put(domainElement, rangeElement);\r
+ linkType.createRange(graph, this, domainElement, rangeElement);\r
+ }\r
+ return result;\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.objmap.structural;\r
+\r
+import java.util.List;\r
+\r
+import org.simantics.db.Resource;\r
+\r
+/**\r
+ * Interface for structurally mapped Java objects.\r
+ * \r
+ * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
+ *\r
+ */\r
+public interface IStructuralObject {\r
+ \r
+ /**\r
+ * Context of an object. \r
+ * @return\r
+ */\r
+ public List<IStructuralObject> getContext();\r
+\r
+ /**\r
+ * Sets object's context. Used by ObjMap, don't touch. \r
+ * @param object\r
+ */\r
+ public void setContext(List<IStructuralObject> object);\r
+ \r
+ /**\r
+ * Return type resource for Structural instances. For other objects returns null.\r
+ * @return\r
+ */\r
+ public Resource getType();\r
+ \r
+ /**\r
+ * Sets object's type. Used by ObjMap, don't touch.\r
+ * @param object\r
+ */\r
+ public void setType(Resource type);\r
+}\r
--- /dev/null
+package org.simantics.objmap.structural;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.layer0.Layer0;\r
+\r
+/**\r
+ * An object representing structural Resource.\r
+ * \r
+ * \r
+ * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
+ *\r
+ */\r
+public class StructuralResource {\r
+\r
+ private Resource resource;\r
+ private List<Resource> context = new ArrayList<Resource>(1);\r
+ \r
+ private Resource typeResource = null;\r
+ \r
+ public StructuralResource(Resource resource) {\r
+ assert(resource != null);\r
+ this.resource = resource;\r
+ }\r
+ public StructuralResource(ReadGraph g, Resource resource, Resource context) throws DatabaseException {\r
+ assert(resource != null);\r
+ this.resource = resource;\r
+ this.context.add(context);\r
+ resolveType(g);\r
+ }\r
+ \r
+ public StructuralResource(ReadGraph g, Resource resource, Resource... context) throws DatabaseException {\r
+ assert(resource != null);\r
+ this.resource = resource;\r
+ for (Resource r : context)\r
+ this.context.add(r);\r
+ resolveType(g);\r
+ }\r
+ \r
+ public StructuralResource(ReadGraph g, Resource resource, List<Resource> context) throws DatabaseException {\r
+ assert(resource != null);\r
+ this.resource = resource;\r
+ for (Resource r : context)\r
+ this.context.add(r);\r
+ resolveType(g); \r
+ }\r
+ public StructuralResource(ReadGraph g, Resource resource, List<Resource> context, Resource context2) throws DatabaseException {\r
+ assert(resource != null);\r
+ this.resource = resource;\r
+ for (Resource r : context)\r
+ this.context.add(r);\r
+ this.context.add(context2);\r
+ resolveType(g);\r
+ }\r
+ \r
+ private void resolveType(ReadGraph g) throws DatabaseException {\r
+ if (this.context.contains(resource)) {\r
+ Layer0 l0 = Layer0.getInstance(g);\r
+ typeResource = g.getSingleObject(resource, l0.InstanceOf);\r
+ } \r
+ }\r
+ \r
+ \r
+ /**\r
+ * The Resource in the DB.\r
+ * @return\r
+ */\r
+ public Resource getResource() {\r
+ return resource;\r
+ }\r
+ \r
+ /**\r
+ * Context in which this resource is accessed. Each context resource represents a structural model instance. \r
+ * @return\r
+ */\r
+ public List<Resource> getContext() {\r
+ return context;\r
+ }\r
+ \r
+ /**\r
+ * If the resource is structural model instance, this returns the type Resource. Otherwise returns null.\r
+ * @return\r
+ */\r
+ public Resource getTypeResource() {\r
+ return typeResource;\r
+ }\r
+ \r
+ /**\r
+ * Returns true, if the resource is structural, \r
+ * @return\r
+ */\r
+ public boolean isStructural() {\r
+ return context.size() > 0;\r
+ }\r
+ \r
+ /**\r
+ * Returns true is the Resource is root of Structural Model instance.\r
+ * In this case the resource instance is editable.\r
+ * \r
+ * @return\r
+ */\r
+ public boolean isStructuralRoot() {\r
+ return (context.size() == 1 && context.get(0).equals(resource));\r
+ }\r
+ \r
+ /**\r
+ * Returns true, the resource is structural model instance.\r
+ * @return\r
+ */\r
+ public boolean isStructuralInstance() {\r
+ return typeResource != null;\r
+ }\r
+ \r
+ @Override\r
+ public int hashCode() {\r
+ int hashCode = resource.hashCode();\r
+ for (Resource ctx : context)\r
+ hashCode += ctx.hashCode();\r
+ return hashCode;\r
+ }\r
+ \r
+ @Override\r
+ public boolean equals(Object obj) {\r
+ if (obj == this)\r
+ return true;\r
+ if (obj == null)\r
+ return false;\r
+ if (obj.getClass() != getClass())\r
+ return false;\r
+ StructuralResource other = (StructuralResource)obj;\r
+ if (!resource.equals(other.resource))\r
+ return false;\r
+ if (context.size() != other.context.size())\r
+ return false;\r
+ for (int i = 0; i < context.size(); i++) {\r
+ if (!context.get(i).equals(other.context.get(i)))\r
+ return false;\r
+ }\r
+ return true;\r
+ }\r
+ \r
+ @Override\r
+ public String toString() {\r
+ String s = "Res: " + resource + " Context:";\r
+ for (Resource ctx : context) \r
+ s+= " "+ ctx;\r
+ if (typeResource != null)\r
+ s+= " Type: " + typeResource;\r
+ return s;\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.objmap.structural.annotations;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.METHOD)\r
+public @interface StructuralRelatedElementsAdd {\r
+ String value();\r
+}\r
--- /dev/null
+package org.simantics.objmap.structural.annotations;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+import org.simantics.objmap.graph.annotations.HasCollectionAdder;\r
+import org.simantics.objmap.graph.annotations.HasCollectionRemover;\r
+import org.simantics.objmap.graph.annotations.meta.IsCollectionRule;\r
+\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.METHOD)\r
+@IsCollectionRule\r
+@HasCollectionAdder(StructuralRelatedElementsAdd.class)\r
+@HasCollectionRemover(StructuralRelatedElementsRem.class)\r
+public @interface StructuralRelatedElementsGet {\r
+ String value();\r
+ boolean composition() default false;\r
+}\r
--- /dev/null
+package org.simantics.objmap.structural.annotations;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.METHOD)\r
+public @interface StructuralRelatedElementsRem {\r
+ String value();\r
+}\r
--- /dev/null
+package org.simantics.objmap.structural.annotations;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+import org.simantics.objmap.graph.annotations.HasSetter;\r
+import org.simantics.objmap.graph.annotations.meta.IsGetSetRule;\r
+\r
+\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.METHOD)\r
+@IsGetSetRule\r
+@HasSetter(StructuralRelatedSetObj.class)\r
+public @interface StructuralRelatedGetObj {\r
+ String value();\r
+}\r
--- /dev/null
+package org.simantics.objmap.structural.annotations;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.METHOD)\r
+public @interface StructuralRelatedSetObj {\r
+ String value();\r
+}\r
--- /dev/null
+package org.simantics.objmap.structural.annotations;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.METHOD)\r
+public @interface TypeRelatedElementsAdd {\r
+ String value();\r
+}\r
--- /dev/null
+package org.simantics.objmap.structural.annotations;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+import org.simantics.objmap.graph.annotations.HasCollectionAdder;\r
+import org.simantics.objmap.graph.annotations.HasCollectionRemover;\r
+import org.simantics.objmap.graph.annotations.meta.IsCollectionRule;\r
+\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.METHOD)\r
+@IsCollectionRule\r
+@HasCollectionAdder(TypeRelatedElementsAdd.class)\r
+@HasCollectionRemover(TypeRelatedElementsRem.class)\r
+public @interface TypeRelatedElementsGet {\r
+ String value();\r
+ boolean composition() default false;\r
+}\r
--- /dev/null
+package org.simantics.objmap.structural.annotations;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.METHOD)\r
+public @interface TypeRelatedElementsRem {\r
+ String value();\r
+}\r
--- /dev/null
+package org.simantics.objmap.structural.annotations;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+import org.simantics.objmap.graph.annotations.HasSetter;\r
+import org.simantics.objmap.graph.annotations.meta.IsGetSetRule;\r
+\r
+\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.METHOD)\r
+//@HasGetSetRuleFactory(RelatedGetSetObjRuleFactory.class)\r
+@IsGetSetRule\r
+@HasSetter(TypeRelatedSetObj.class)\r
+public @interface TypeRelatedGetObj {\r
+ String value();\r
+}\r
--- /dev/null
+package org.simantics.objmap.structural.annotations;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+import org.simantics.objmap.graph.annotations.HasSetter;\r
+import org.simantics.objmap.graph.annotations.meta.IsGetSetRule;\r
+import org.simantics.objmap.graph.rules.adapters.IdentityAdapter;\r
+import org.simantics.objmap.graph.rules.adapters.ValueAdapter;\r
+\r
+\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.METHOD)\r
+//@HasGetSetRuleFactory(RelatedGetSetValueRuleFactory.class)\r
+@IsGetSetRule\r
+@HasSetter(TypeRelatedSetValue.class)\r
+public @interface TypeRelatedGetValue {\r
+ String value();\r
+ Class<? extends ValueAdapter> adapter() default IdentityAdapter.class;\r
+}\r
--- /dev/null
+package org.simantics.objmap.structural.annotations;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.METHOD)\r
+public @interface TypeRelatedSetObj {\r
+ String value();\r
+}\r
--- /dev/null
+package org.simantics.objmap.structural.annotations;\r
+\r
+import java.lang.annotation.ElementType;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+\r
+@Retention(RetentionPolicy.RUNTIME)\r
+@Target(ElementType.METHOD)\r
+public @interface TypeRelatedSetValue {\r
+ String value();\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.structural.annotations.factories;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.layer0.Layer0;\r
+\r
+public class DataTypeUtils {\r
+ \r
+ public static Resource dataTypeOfClass(ReadGraph g, Class<?> clazz) {\r
+ Layer0 b = Layer0.getInstance(g);\r
+ if(clazz.equals(Double.class) || clazz.equals(double.class))\r
+ return b.Double;\r
+ else if(clazz.equals(String.class))\r
+ return b.String;\r
+ else if(clazz.equals(Integer.class) || clazz.equals(int.class))\r
+ return b.Integer;\r
+ else if(clazz.equals(Float.class) || clazz.equals(float.class))\r
+ return b.Float;\r
+ else if(clazz.equals(Boolean.class) || clazz.equals(boolean.class))\r
+ return b.Boolean;\r
+ else if(clazz.equals(Long.class) || clazz.equals(long.class))\r
+ return b.Long;\r
+ else if(clazz.equals(Byte.class) || clazz.equals(byte.class))\r
+ return b.Byte;\r
+ \r
+ else if(clazz.equals(double[].class))\r
+ return b.DoubleArray;\r
+ else if(clazz.equals(int[].class))\r
+ return b.IntegerArray;\r
+ else if(clazz.equals(byte[].class))\r
+ return b.ByteArray;\r
+ else if(clazz.equals(float[].class))\r
+ return b.FloatArray;\r
+ else if(clazz.equals(boolean[].class))\r
+ return b.BooleanArray;\r
+ else if(clazz.equals(String[].class))\r
+ return b.StringArray;\r
+ else if(clazz.equals(long[].class))\r
+ return b.LongArray;\r
+ else {\r
+ System.out.println("Couldn't find a data type for " + clazz);\r
+ return null;\r
+ }\r
+ }\r
+ \r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.structural.annotations.factories;\r
+\r
+import java.lang.annotation.Annotation;\r
+import java.lang.reflect.Field;\r
+import java.util.Collection;\r
+import java.util.Collections;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.exception.ResourceNotFoundException;\r
+import org.simantics.db.exception.ServiceException;\r
+import org.simantics.db.exception.ValidationException;\r
+import org.simantics.objmap.bidirectional.IBidirectionalMappingRule;\r
+import org.simantics.objmap.graph.annotations.OptionalRelatedElements;\r
+import org.simantics.objmap.graph.rules.MappedElementsRule;\r
+import org.simantics.objmap.structural.rules.domain.RelatedObjectsAccessor;\r
+import org.simantics.objmap.graph.rules.factory.IFieldRuleFactory;\r
+import org.simantics.objmap.graph.rules.range.FieldAccessorWithDefault;\r
+import org.simantics.objmap.structural.StructuralResource;\r
+\r
+\r
+public class OptionalRelatedElementsRuleFactory<Range> implements IFieldRuleFactory<StructuralResource, Range> {\r
+\r
+ @Override\r
+ public IBidirectionalMappingRule<StructuralResource, Range> create(ReadGraph g, Annotation _annotation, Field field) throws ResourceNotFoundException, ValidationException, ServiceException {\r
+ OptionalRelatedElements annotation = (OptionalRelatedElements)_annotation;\r
+ return new MappedElementsRule<StructuralResource, Range>(\r
+ new RelatedObjectsAccessor(g.getResource(annotation.value()),\r
+ annotation.composition(),false),\r
+ new FieldAccessorWithDefault<Range,Collection<Range>>(field, (Collection<Range>)Collections.emptyList())\r
+ );\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.structural.annotations.factories;\r
+\r
+import java.lang.annotation.Annotation;\r
+import java.lang.reflect.Field;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.exception.ResourceNotFoundException;\r
+import org.simantics.db.exception.ServiceException;\r
+import org.simantics.db.exception.ValidationException;\r
+import org.simantics.objmap.bidirectional.IBidirectionalMappingRule;\r
+import org.simantics.objmap.graph.annotations.RelatedElement;\r
+import org.simantics.objmap.graph.rules.MappedElementRule;\r
+import org.simantics.objmap.graph.rules.domain.RelatedObjectAccessor;\r
+import org.simantics.objmap.graph.rules.factory.IFieldRuleFactory;\r
+import org.simantics.objmap.graph.rules.range.FieldAccessor;\r
+\r
+\r
+public class RelatedElementRuleFactory<Range> implements IFieldRuleFactory<Resource,Range> {\r
+\r
+ @Override\r
+ public IBidirectionalMappingRule<Resource, Range> create(ReadGraph g, Annotation _annotation, Field field) throws ResourceNotFoundException, ValidationException, ServiceException {\r
+ RelatedElement annotation = (RelatedElement)_annotation;\r
+ return new MappedElementRule<Resource,Range>(\r
+ new RelatedObjectAccessor(g.getResource(annotation.value())),\r
+ new FieldAccessor<Range,Range>(field)\r
+ );\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.structural.annotations.factories;\r
+\r
+import java.lang.annotation.Annotation;\r
+import java.lang.reflect.Field;\r
+import java.util.Collection;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.exception.ResourceNotFoundException;\r
+import org.simantics.db.exception.ServiceException;\r
+import org.simantics.db.exception.ValidationException;\r
+import org.simantics.objmap.bidirectional.IBidirectionalMappingRule;\r
+import org.simantics.objmap.graph.annotations.RelatedElements;\r
+import org.simantics.objmap.graph.rules.MappedElementsRule;\r
+import org.simantics.objmap.structural.rules.domain.RelatedObjectsAccessor;\r
+import org.simantics.objmap.graph.rules.factory.IFieldRuleFactory;\r
+import org.simantics.objmap.graph.rules.range.FieldAccessor;\r
+import org.simantics.objmap.structural.StructuralResource;\r
+\r
+\r
+public class RelatedElementsRuleFactory<Range> implements IFieldRuleFactory<StructuralResource, Range> {\r
+\r
+ @Override\r
+ public IBidirectionalMappingRule<StructuralResource, Range> create(ReadGraph g, Annotation _annotation, Field field) throws ResourceNotFoundException, ValidationException, ServiceException {\r
+ RelatedElements annotation = (RelatedElements)_annotation;\r
+ return new MappedElementsRule<StructuralResource,Range>(\r
+ new RelatedObjectsAccessor(g.getResource(annotation.value()),\r
+ annotation.composition(),false),\r
+ new FieldAccessor<Range,Collection<Range>>(field)\r
+ );\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.objmap.structural.annotations.factories;\r
+\r
+import java.lang.annotation.Annotation;\r
+import java.lang.reflect.Method;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.objmap.bidirectional.IBidirectionalMappingRule;\r
+import org.simantics.objmap.graph.annotations.RelatedElementsAdd;\r
+import org.simantics.objmap.graph.annotations.RelatedElementsGet;\r
+import org.simantics.objmap.graph.annotations.RelatedElementsRem;\r
+import org.simantics.objmap.graph.rules.MappedElementsRule;\r
+import org.simantics.objmap.graph.rules.factory.ICollectionRuleFactory;\r
+import org.simantics.objmap.graph.rules.range.CollectionAccessor;\r
+import org.simantics.objmap.structural.StructuralResource;\r
+import org.simantics.objmap.structural.rules.domain.RelatedObjectsAccessor;\r
+\r
+\r
+public class RelatedElementsRuleFactory2<Range> implements ICollectionRuleFactory<StructuralResource,Range> {\r
+ \r
+ @Override\r
+ public IBidirectionalMappingRule<StructuralResource, Range> create(ReadGraph g, Annotation annotation,\r
+ Method getter, Method adder, Method remover)\r
+ throws DatabaseException {\r
+ RelatedElementsGet getterAnn = (RelatedElementsGet)annotation;\r
+ return new MappedElementsRule<StructuralResource,Range>(new RelatedObjectsAccessor(g.getResource(getterAnn.value()),getterAnn.composition(),false,true,false),\r
+ new CollectionAccessor<Range,Range>(getter, adder, remover));\r
+ }\r
+ \r
+ @Override\r
+ public boolean isAdder(Annotation getterAnnotation, Annotation annotation) {\r
+ RelatedElementsGet getterAnn = (RelatedElementsGet)getterAnnotation;\r
+ RelatedElementsAdd adderAnn = (RelatedElementsAdd)annotation;\r
+ return getterAnn.value().equals(adderAnn.value());\r
+ }\r
+ \r
+ @Override\r
+ public boolean isRemover(Annotation getterAnnotation, Annotation annotation) {\r
+ RelatedElementsGet getterAnn = (RelatedElementsGet)getterAnnotation;\r
+ RelatedElementsRem adderAnn = (RelatedElementsRem)annotation;\r
+ return getterAnn.value().equals(adderAnn.value());\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.objmap.structural.annotations.factories;\r
+\r
+import java.lang.annotation.Annotation;\r
+import java.lang.reflect.Method;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.objmap.bidirectional.IBidirectionalMappingRule;\r
+import org.simantics.objmap.graph.annotations.RelatedGetObj;\r
+import org.simantics.objmap.graph.annotations.RelatedSetObj;\r
+import org.simantics.objmap.graph.rules.MappedElementRule;\r
+import org.simantics.objmap.structural.rules.domain.RelatedObjectAccessor;\r
+import org.simantics.objmap.graph.rules.factory.IGetSetRuleFactory;\r
+import org.simantics.objmap.graph.rules.range.GetSetObjectAccessor;\r
+import org.simantics.objmap.structural.StructuralResource;\r
+\r
+\r
+/**\r
+ * Rule factory for mapped object using Getter/Setter-methods.\r
+ * \r
+ * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
+ *\r
+ */\r
+public class RelatedGetSetObjRuleFactory<Range> implements IGetSetRuleFactory<StructuralResource,Range> {\r
+ \r
+ @Override\r
+ public IBidirectionalMappingRule<StructuralResource,Range> create(ReadGraph g, Annotation annotation,\r
+ Method getter, Method setter)\r
+ throws DatabaseException {\r
+ RelatedGetObj getterAnn = (RelatedGetObj)annotation;\r
+ return new MappedElementRule<StructuralResource,Range>(new RelatedObjectAccessor(g.getResource(getterAnn.value()),false,true,false),\r
+ new GetSetObjectAccessor<Range,Range>(getter, setter));\r
+ }\r
+ \r
+ @Override\r
+ public boolean isSetter(Annotation getterAnnotation, Annotation annotation) {\r
+ RelatedGetObj getterAnn = (RelatedGetObj)getterAnnotation;\r
+ RelatedSetObj setterAnn = (RelatedSetObj)annotation;\r
+ return getterAnn.value().equals(setterAnn.value());\r
+ }\r
+ \r
+ \r
+\r
+}\r
--- /dev/null
+package org.simantics.objmap.structural.annotations.factories;\r
+\r
+import java.lang.annotation.Annotation;\r
+import java.lang.reflect.Method;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.objmap.bidirectional.IBidirectionalMappingRule;\r
+import org.simantics.objmap.graph.annotations.RelatedGetValue;\r
+import org.simantics.objmap.graph.annotations.RelatedSetValue;\r
+import org.simantics.objmap.graph.rules.ValueRule;\r
+import org.simantics.objmap.graph.rules.adapters.IdentityAdapter;\r
+import org.simantics.objmap.graph.rules.adapters.ValueAdapter;\r
+import org.simantics.objmap.structural.StructuralResource;\r
+import org.simantics.objmap.structural.rules.domain.RelatedValueAccessor;\r
+import org.simantics.objmap.graph.rules.factory.IGetSetRuleFactory;\r
+import org.simantics.objmap.graph.rules.range.AdaptedRangeAccessor;\r
+import org.simantics.objmap.graph.rules.range.GetSetValueAccessor;\r
+import org.simantics.objmap.graph.rules.range.IRangeAccessor;\r
+\r
+/**\r
+ * Rule factory for mapped value using Getter/Setter-methods.\r
+ * \r
+ * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
+ *\r
+ */\r
+public class RelatedGetSetValueRuleFactory<Range> implements IGetSetRuleFactory<StructuralResource,Range> {\r
+ \r
+ @Override\r
+ public IBidirectionalMappingRule<StructuralResource, Range> create(ReadGraph g, Annotation annotation,\r
+ Method getter, Method setter)\r
+ throws DatabaseException {\r
+ RelatedGetValue getterAnn = (RelatedGetValue)annotation;\r
+ \r
+ Class<? extends ValueAdapter> adapterClass = getterAnn.adapter();\r
+ IRangeAccessor<Range,Object> rangeAccessor = new GetSetValueAccessor<Range,Object>(getter, setter);\r
+ Resource valueType;\r
+ if (adapterClass == IdentityAdapter.class) {\r
+ valueType = dataTypeOfClass(g, getter.getReturnType());\r
+ } else {\r
+ try{\r
+ ValueAdapter adapter = adapterClass.newInstance();\r
+ rangeAccessor = new AdaptedRangeAccessor<Range>(rangeAccessor, adapter);\r
+ valueType = adapter.rangeTypeToDomainType(g, getter.getReturnType());\r
+ } catch (InstantiationException e) {\r
+ throw new RuntimeException(e);\r
+ } catch (IllegalAccessException e) {\r
+ throw new RuntimeException(e);\r
+ }\r
+ }\r
+ return new ValueRule<StructuralResource,Range>(new RelatedValueAccessor(g.getResource(getterAnn.value()), valueType,false,true,false),\r
+ rangeAccessor);\r
+ }\r
+ \r
+ @Override\r
+ public boolean isSetter(Annotation getterAnnotation, Annotation annotation) {\r
+ RelatedGetValue getterAnn = (RelatedGetValue)getterAnnotation;\r
+ RelatedSetValue setterAnn = (RelatedSetValue)annotation;\r
+ return getterAnn.value().equals(setterAnn.value());\r
+ }\r
+ \r
+ public static Resource dataTypeOfClass(ReadGraph g, Class<?> clazz) {\r
+ Layer0 b = Layer0.getInstance(g);\r
+ if(clazz.equals(Double.class) || clazz.equals(double.class))\r
+ return b.Double;\r
+ else if(clazz.equals(String.class))\r
+ return b.String;\r
+ else if(clazz.equals(Integer.class) || clazz.equals(int.class))\r
+ return b.Integer;\r
+ else if(clazz.equals(Float.class) || clazz.equals(float.class))\r
+ return b.Float;\r
+ else if(clazz.equals(Boolean.class) || clazz.equals(boolean.class))\r
+ return b.Boolean;\r
+ else if(clazz.equals(Long.class) || clazz.equals(long.class))\r
+ return b.Long;\r
+ else if(clazz.equals(Byte.class) || clazz.equals(byte.class))\r
+ return b.Byte;\r
+ \r
+ else if(clazz.equals(double[].class))\r
+ return b.DoubleArray;\r
+ else if(clazz.equals(int[].class))\r
+ return b.IntegerArray;\r
+ else if(clazz.equals(byte[].class))\r
+ return b.ByteArray;\r
+ else if(clazz.equals(float[].class))\r
+ return b.FloatArray;\r
+ else if(clazz.equals(boolean[].class))\r
+ return b.BooleanArray;\r
+ else if(clazz.equals(String[].class))\r
+ return b.StringArray;\r
+ else if(clazz.equals(long[].class))\r
+ return b.LongArray;\r
+ else {\r
+ System.out.println("Couldn't find a data type for " + clazz);\r
+ return null;\r
+ }\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.structural.annotations.factories;\r
+\r
+import java.lang.annotation.Annotation;\r
+import java.lang.reflect.Field;\r
+import java.util.Collection;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.exception.ResourceNotFoundException;\r
+import org.simantics.db.exception.ServiceException;\r
+import org.simantics.db.exception.ValidationException;\r
+import org.simantics.objmap.bidirectional.IBidirectionalMappingRule;\r
+import org.simantics.objmap.graph.annotations.RelatedOrderedSetElements;\r
+import org.simantics.objmap.graph.rules.MappedElementsRule;\r
+import org.simantics.objmap.graph.rules.factory.IFieldRuleFactory;\r
+import org.simantics.objmap.graph.rules.range.FieldAccessor;\r
+import org.simantics.objmap.structural.StructuralResource;\r
+import org.simantics.objmap.structural.rules.domain.RelatedOrderedSetElementsAccessor;\r
+\r
+\r
+public class RelatedOrderedSetElementsRuleFactory<Range> implements IFieldRuleFactory<StructuralResource, Range> {\r
+\r
+ @Override\r
+ public IBidirectionalMappingRule<StructuralResource, Range> create(ReadGraph g, Annotation _annotation, Field field) throws ResourceNotFoundException, ValidationException, ServiceException {\r
+ RelatedOrderedSetElements annotation = (RelatedOrderedSetElements)_annotation;\r
+ return new MappedElementsRule<StructuralResource,Range>(\r
+ new RelatedOrderedSetElementsAccessor(annotation.composition(),false),\r
+ new FieldAccessor<Range,Collection<Range>>(field)\r
+ );\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.structural.annotations.factories;\r
+\r
+import java.lang.annotation.Annotation;\r
+import java.lang.reflect.Field;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.exception.ResourceNotFoundException;\r
+import org.simantics.db.exception.ServiceException;\r
+import org.simantics.db.exception.ValidationException;\r
+\r
+import org.simantics.objmap.bidirectional.IBidirectionalMappingRule;\r
+import org.simantics.objmap.graph.annotations.RelatedValue;\r
+import org.simantics.objmap.graph.rules.ValueRule;\r
+import org.simantics.objmap.graph.rules.adapters.IdentityAdapter;\r
+import org.simantics.objmap.graph.rules.adapters.ValueAdapter;\r
+import org.simantics.objmap.structural.rules.domain.RelatedValueAccessor;\r
+import org.simantics.objmap.graph.rules.factory.IFieldRuleFactory;\r
+import org.simantics.objmap.graph.rules.range.AdaptedRangeAccessor;\r
+import org.simantics.objmap.graph.rules.range.FieldAccessor;\r
+import org.simantics.objmap.graph.rules.range.IRangeAccessor;\r
+import org.simantics.objmap.structural.StructuralResource;\r
+\r
+\r
+public class RelatedValueRuleFactory<Range> implements IFieldRuleFactory<StructuralResource, Range> {\r
+\r
+ @Override\r
+ public IBidirectionalMappingRule<StructuralResource, Range> create(ReadGraph g, Annotation _annotation, Field field) throws ResourceNotFoundException,\r
+ ValidationException, ServiceException {\r
+ RelatedValue annotation = (RelatedValue) _annotation;\r
+ Class<? extends ValueAdapter> adapterClass = annotation.adapter();\r
+ IRangeAccessor<Range,Object> rangeAccessor = new FieldAccessor<Range,Object>(field);\r
+ Resource valueType;\r
+ if (adapterClass == IdentityAdapter.class) {\r
+ valueType = DataTypeUtils.dataTypeOfClass(g, field.getType());\r
+ } else {\r
+ try {\r
+ ValueAdapter adapter = adapterClass.newInstance();\r
+ rangeAccessor = new AdaptedRangeAccessor<Range>(rangeAccessor, adapter);\r
+ valueType = adapter.rangeTypeToDomainType(g, field.getType());\r
+ } catch (InstantiationException e) {\r
+ throw new RuntimeException(e);\r
+ } catch (IllegalAccessException e) {\r
+ throw new RuntimeException(e);\r
+ }\r
+ }\r
+ return new ValueRule<StructuralResource,Range>(new RelatedValueAccessor(g.getResource(annotation.value()), valueType,false,true,false), rangeAccessor);\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.objmap.structural.annotations.factories;\r
+\r
+import java.lang.annotation.Annotation;\r
+import java.lang.reflect.Method;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.objmap.bidirectional.IBidirectionalMappingRule;\r
+import org.simantics.objmap.graph.rules.MappedElementsRule;\r
+import org.simantics.objmap.graph.rules.factory.ICollectionRuleFactory;\r
+import org.simantics.objmap.graph.rules.range.CollectionAccessor;\r
+import org.simantics.objmap.structural.StructuralResource;\r
+import org.simantics.objmap.structural.annotations.StructuralRelatedElementsAdd;\r
+import org.simantics.objmap.structural.annotations.StructuralRelatedElementsGet;\r
+import org.simantics.objmap.structural.annotations.StructuralRelatedElementsRem;\r
+import org.simantics.objmap.structural.rules.domain.StructuralRelatedObjectsAccessor;\r
+\r
+\r
+public class StructuralRelatedElementsRuleFactory2<Range> implements ICollectionRuleFactory<StructuralResource,Range> {\r
+ \r
+ @Override\r
+ public IBidirectionalMappingRule<StructuralResource, Range> create(ReadGraph g, Annotation annotation,\r
+ Method getter, Method adder, Method remover)\r
+ throws DatabaseException {\r
+ StructuralRelatedElementsGet getterAnn = (StructuralRelatedElementsGet)annotation;\r
+ return new MappedElementsRule<StructuralResource,Range>(new StructuralRelatedObjectsAccessor(g.getResource(getterAnn.value()),getterAnn.composition()),\r
+ new CollectionAccessor<Range,Range>(getter, adder, remover));\r
+ }\r
+ \r
+ @Override\r
+ public boolean isAdder(Annotation getterAnnotation, Annotation annotation) {\r
+ StructuralRelatedElementsGet getterAnn = (StructuralRelatedElementsGet)getterAnnotation;\r
+ StructuralRelatedElementsAdd adderAnn = (StructuralRelatedElementsAdd)annotation;\r
+ return getterAnn.value().equals(adderAnn.value());\r
+ }\r
+ \r
+ @Override\r
+ public boolean isRemover(Annotation getterAnnotation, Annotation annotation) {\r
+ StructuralRelatedElementsGet getterAnn = (StructuralRelatedElementsGet)getterAnnotation;\r
+ StructuralRelatedElementsRem adderAnn = (StructuralRelatedElementsRem)annotation;\r
+ return getterAnn.value().equals(adderAnn.value());\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.objmap.structural.annotations.factories;\r
+\r
+import java.lang.annotation.Annotation;\r
+import java.lang.reflect.Method;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.objmap.bidirectional.IBidirectionalMappingRule;\r
+import org.simantics.objmap.graph.rules.MappedElementRule;\r
+import org.simantics.objmap.graph.rules.factory.IGetSetRuleFactory;\r
+import org.simantics.objmap.graph.rules.range.GetSetObjectAccessor;\r
+import org.simantics.objmap.structural.StructuralResource;\r
+import org.simantics.objmap.structural.annotations.StructuralRelatedGetObj;\r
+import org.simantics.objmap.structural.annotations.StructuralRelatedSetObj;\r
+import org.simantics.objmap.structural.rules.domain.StructuralRelatedObjectAccessor;\r
+\r
+\r
+/**\r
+ * Rule factory for mapped object using Getter/Setter-methods.\r
+ * \r
+ * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
+ *\r
+ */\r
+public class StructuralRelatedGetSetObjRuleFactory<Range> implements IGetSetRuleFactory<StructuralResource,Range> {\r
+ \r
+ @Override\r
+ public IBidirectionalMappingRule<StructuralResource,Range> create(ReadGraph g, Annotation annotation,\r
+ Method getter, Method setter)\r
+ throws DatabaseException {\r
+ StructuralRelatedGetObj getterAnn = (StructuralRelatedGetObj)annotation;\r
+ return new MappedElementRule<StructuralResource,Range>(new StructuralRelatedObjectAccessor(g.getResource(getterAnn.value()),false,true,false),\r
+ new GetSetObjectAccessor<Range,Range>(getter, setter));\r
+ }\r
+ \r
+ @Override\r
+ public boolean isSetter(Annotation getterAnnotation, Annotation annotation) {\r
+ StructuralRelatedGetObj getterAnn = (StructuralRelatedGetObj)getterAnnotation;\r
+ StructuralRelatedSetObj setterAnn = (StructuralRelatedSetObj)annotation;\r
+ return getterAnn.value().equals(setterAnn.value());\r
+ }\r
+ \r
+ \r
+\r
+}\r
--- /dev/null
+package org.simantics.objmap.structural.annotations.factories;\r
+\r
+import java.lang.annotation.Annotation;\r
+import java.lang.reflect.Method;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.objmap.bidirectional.IBidirectionalMappingRule;\r
+import org.simantics.objmap.graph.rules.MappedElementsRule;\r
+import org.simantics.objmap.graph.rules.factory.ICollectionRuleFactory;\r
+import org.simantics.objmap.graph.rules.range.CollectionAccessor;\r
+import org.simantics.objmap.structural.StructuralResource;\r
+import org.simantics.objmap.structural.annotations.TypeRelatedElementsAdd;\r
+import org.simantics.objmap.structural.annotations.TypeRelatedElementsGet;\r
+import org.simantics.objmap.structural.annotations.TypeRelatedElementsRem;\r
+import org.simantics.objmap.structural.rules.domain.RelatedObjectsAccessor;\r
+\r
+\r
+public class TypeRelatedElementsRuleFactory2<Range> implements ICollectionRuleFactory<StructuralResource,Range> {\r
+ \r
+ @Override\r
+ public IBidirectionalMappingRule<StructuralResource, Range> create(ReadGraph g, Annotation annotation,\r
+ Method getter, Method adder, Method remover)\r
+ throws DatabaseException {\r
+ TypeRelatedElementsGet getterAnn = (TypeRelatedElementsGet)annotation;\r
+ return new MappedElementsRule<StructuralResource,Range>(new RelatedObjectsAccessor(g.getResource(getterAnn.value()),getterAnn.composition(),true,true,true),\r
+ new CollectionAccessor<Range,Range>(getter, adder, remover));\r
+ }\r
+ \r
+ @Override\r
+ public boolean isAdder(Annotation getterAnnotation, Annotation annotation) {\r
+ TypeRelatedElementsGet getterAnn = (TypeRelatedElementsGet)getterAnnotation;\r
+ TypeRelatedElementsAdd adderAnn = (TypeRelatedElementsAdd)annotation;\r
+ return getterAnn.value().equals(adderAnn.value());\r
+ }\r
+ \r
+ @Override\r
+ public boolean isRemover(Annotation getterAnnotation, Annotation annotation) {\r
+ TypeRelatedElementsGet getterAnn = (TypeRelatedElementsGet)getterAnnotation;\r
+ TypeRelatedElementsRem adderAnn = (TypeRelatedElementsRem)annotation;\r
+ return getterAnn.value().equals(adderAnn.value());\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.objmap.structural.annotations.factories;\r
+\r
+import java.lang.annotation.Annotation;\r
+import java.lang.reflect.Method;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.objmap.bidirectional.IBidirectionalMappingRule;\r
+import org.simantics.objmap.graph.rules.MappedElementRule;\r
+import org.simantics.objmap.graph.rules.factory.IGetSetRuleFactory;\r
+import org.simantics.objmap.graph.rules.range.GetSetObjectAccessor;\r
+import org.simantics.objmap.structural.StructuralResource;\r
+import org.simantics.objmap.structural.annotations.TypeRelatedGetObj;\r
+import org.simantics.objmap.structural.annotations.TypeRelatedSetObj;\r
+import org.simantics.objmap.structural.rules.domain.RelatedObjectAccessor;\r
+\r
+\r
+/**\r
+ * Rule factory for mapped object using Getter/Setter-methods.\r
+ * \r
+ * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
+ *\r
+ */\r
+public class TypeRelatedGetSetObjRuleFactory<Range> implements IGetSetRuleFactory<StructuralResource,Range> {\r
+ \r
+ @Override\r
+ public IBidirectionalMappingRule<StructuralResource,Range> create(ReadGraph g, Annotation annotation,\r
+ Method getter, Method setter)\r
+ throws DatabaseException {\r
+ TypeRelatedGetObj getterAnn = (TypeRelatedGetObj)annotation;\r
+ return new MappedElementRule<StructuralResource,Range>(new RelatedObjectAccessor(g.getResource(getterAnn.value()),true,true,true),\r
+ new GetSetObjectAccessor<Range,Range>(getter, setter));\r
+ }\r
+ \r
+ @Override\r
+ public boolean isSetter(Annotation getterAnnotation, Annotation annotation) {\r
+ TypeRelatedGetObj getterAnn = (TypeRelatedGetObj)getterAnnotation;\r
+ TypeRelatedSetObj setterAnn = (TypeRelatedSetObj)annotation;\r
+ return getterAnn.value().equals(setterAnn.value());\r
+ }\r
+ \r
+ \r
+\r
+}\r
--- /dev/null
+package org.simantics.objmap.structural.annotations.factories;\r
+\r
+import java.lang.annotation.Annotation;\r
+import java.lang.reflect.Method;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.objmap.bidirectional.IBidirectionalMappingRule;\r
+import org.simantics.objmap.graph.rules.ValueRule;\r
+import org.simantics.objmap.graph.rules.adapters.IdentityAdapter;\r
+import org.simantics.objmap.graph.rules.adapters.ValueAdapter;\r
+import org.simantics.objmap.graph.rules.factory.IGetSetRuleFactory;\r
+import org.simantics.objmap.graph.rules.range.AdaptedRangeAccessor;\r
+import org.simantics.objmap.graph.rules.range.GetSetValueAccessor;\r
+import org.simantics.objmap.graph.rules.range.IRangeAccessor;\r
+import org.simantics.objmap.structural.StructuralResource;\r
+import org.simantics.objmap.structural.annotations.TypeRelatedGetValue;\r
+import org.simantics.objmap.structural.annotations.TypeRelatedSetValue;\r
+import org.simantics.objmap.structural.rules.domain.RelatedValueAccessor;\r
+\r
+/**\r
+ * Rule factory for mapped value using Getter/Setter-methods.\r
+ * \r
+ * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
+ *\r
+ */\r
+public class TypeRelatedGetSetValueRuleFactory<Range> implements IGetSetRuleFactory<StructuralResource,Range> {\r
+ \r
+ @Override\r
+ public IBidirectionalMappingRule<StructuralResource, Range> create(ReadGraph g, Annotation annotation,\r
+ Method getter, Method setter)\r
+ throws DatabaseException {\r
+ TypeRelatedGetValue getterAnn = (TypeRelatedGetValue)annotation;\r
+ \r
+ Class<? extends ValueAdapter> adapterClass = getterAnn.adapter();\r
+ IRangeAccessor<Range,Object> rangeAccessor = new GetSetValueAccessor<Range,Object>(getter, setter);\r
+ Resource valueType;\r
+ if (adapterClass == IdentityAdapter.class) {\r
+ valueType = dataTypeOfClass(g, getter.getReturnType());\r
+ } else {\r
+ try{\r
+ ValueAdapter adapter = adapterClass.newInstance();\r
+ rangeAccessor = new AdaptedRangeAccessor<Range>(rangeAccessor, adapter);\r
+ valueType = adapter.rangeTypeToDomainType(g, getter.getReturnType());\r
+ } catch (InstantiationException e) {\r
+ throw new RuntimeException(e);\r
+ } catch (IllegalAccessException e) {\r
+ throw new RuntimeException(e);\r
+ }\r
+ }\r
+ return new ValueRule<StructuralResource,Range>(new RelatedValueAccessor(g.getResource(getterAnn.value()), valueType,true,true,true),\r
+ rangeAccessor);\r
+ }\r
+ \r
+ @Override\r
+ public boolean isSetter(Annotation getterAnnotation, Annotation annotation) {\r
+ TypeRelatedGetValue getterAnn = (TypeRelatedGetValue)getterAnnotation;\r
+ TypeRelatedSetValue setterAnn = (TypeRelatedSetValue)annotation;\r
+ return getterAnn.value().equals(setterAnn.value());\r
+ }\r
+ \r
+ public static Resource dataTypeOfClass(ReadGraph g, Class<?> clazz) {\r
+ Layer0 b = Layer0.getInstance(g);\r
+ if(clazz.equals(Double.class) || clazz.equals(double.class))\r
+ return b.Double;\r
+ else if(clazz.equals(String.class))\r
+ return b.String;\r
+ else if(clazz.equals(Integer.class) || clazz.equals(int.class))\r
+ return b.Integer;\r
+ else if(clazz.equals(Float.class) || clazz.equals(float.class))\r
+ return b.Float;\r
+ else if(clazz.equals(Boolean.class) || clazz.equals(boolean.class))\r
+ return b.Boolean;\r
+ else if(clazz.equals(Long.class) || clazz.equals(long.class))\r
+ return b.Long;\r
+ else if(clazz.equals(Byte.class) || clazz.equals(byte.class))\r
+ return b.Byte;\r
+ \r
+ else if(clazz.equals(double[].class))\r
+ return b.DoubleArray;\r
+ else if(clazz.equals(int[].class))\r
+ return b.IntegerArray;\r
+ else if(clazz.equals(byte[].class))\r
+ return b.ByteArray;\r
+ else if(clazz.equals(float[].class))\r
+ return b.FloatArray;\r
+ else if(clazz.equals(boolean[].class))\r
+ return b.BooleanArray;\r
+ else if(clazz.equals(String[].class))\r
+ return b.StringArray;\r
+ else if(clazz.equals(long[].class))\r
+ return b.LongArray;\r
+ else {\r
+ System.out.println("Couldn't find a data type for " + clazz);\r
+ return null;\r
+ }\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.structural.annotations.factories;\r
+\r
+import java.lang.annotation.Annotation;\r
+import java.lang.reflect.Method;\r
+\r
+import org.apache.log4j.Logger;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.objmap.backward.IBackwardMapping;\r
+import org.simantics.objmap.bidirectional.IBidirectionalMappingRule;\r
+import org.simantics.objmap.exceptions.MappingException;\r
+import org.simantics.objmap.forward.IForwardMapping;\r
+import org.simantics.objmap.graph.rules.factory.IMethodRuleFactory;\r
+\r
+public class UpdateMethodFactory<Domain, Range> implements IMethodRuleFactory<Domain, Range> {\r
+\r
+ static Logger LOGGER = Logger.getLogger("org.simantics.objmap");\r
+ \r
+ @Override\r
+ public IBidirectionalMappingRule<Domain, Range> create(ReadGraph g, \r
+ Annotation annotation, \r
+ final Method method)\r
+ throws DatabaseException {\r
+ method.setAccessible(true);\r
+ return new IBidirectionalMappingRule<Domain,Range>() {\r
+ \r
+ @Override\r
+ public boolean updateRange(ReadGraph g, IForwardMapping<Domain, Range> map,\r
+ Domain domainElement, Range rangeElement)\r
+ throws MappingException {\r
+ LOGGER.info(" UpdateMethodFactory.updateRange"); \r
+ try {\r
+ return (Boolean)method.invoke(rangeElement, g, domainElement);\r
+ } catch (Exception e) {\r
+ // TODO Auto-generated catch block\r
+ e.printStackTrace();\r
+ }\r
+ return false;\r
+ }\r
+ \r
+ @Override\r
+ public boolean updateDomain(WriteGraph g, IBackwardMapping<Domain,Range> map,\r
+ Domain domainElement, Range rangeElement)\r
+ throws MappingException {\r
+ return false;\r
+ }\r
+ \r
+ public void createDomain(WriteGraph g, IBackwardMapping<Domain,Range> map, Domain domainElement, Range rangeElement) throws MappingException {\r
+ updateDomain(g, map, domainElement, rangeElement);\r
+ };\r
+ \r
+ public void createRange(ReadGraph g, IForwardMapping<Domain,Range> map, Domain domainElement, Range rangeElement) throws MappingException {\r
+ updateRange(g, map, domainElement, rangeElement);\r
+ };\r
+ };\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.structural.rules.domain;\r
+\r
+import org.apache.log4j.Logger;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.objmap.exceptions.MappingException;\r
+import org.simantics.objmap.graph.rules.domain.IDomainAccessor;\r
+import org.simantics.objmap.structural.StructuralResource;\r
+\r
+\r
+public class RelatedObjectAccessor implements IDomainAccessor<StructuralResource,StructuralResource> {\r
+\r
+ static Logger LOGGER = Logger.getLogger("org.simantics.objmap");\r
+ \r
+ Resource relation;\r
+ boolean useTypeResource;\r
+ \r
+ private boolean preventStructuralChanges = true;\r
+ private boolean preventStructuralRootChanges = true;\r
+ \r
+ public RelatedObjectAccessor(Resource relation, boolean useTypeResource) {\r
+ this.relation = relation;\r
+ this.useTypeResource = useTypeResource;\r
+ }\r
+ \r
+ public RelatedObjectAccessor(Resource relation, boolean useTypeResource, boolean preventStructuralChanges, boolean preventStructuralRootChanges) {\r
+ this.relation = relation;\r
+ this.useTypeResource = useTypeResource;\r
+ this.preventStructuralChanges = preventStructuralChanges;\r
+ this.preventStructuralRootChanges = preventStructuralRootChanges;\r
+ }\r
+ \r
+ private boolean preventChange(StructuralResource element) {\r
+ return preventStructuralChanges && element.isStructural() && (!element.isStructuralRoot()||preventStructuralRootChanges); \r
+ }\r
+\r
+ @Override\r
+ public StructuralResource get(ReadGraph g, StructuralResource element) throws MappingException {\r
+ try {\r
+ LOGGER.info(" RelatedObjectAccessor.get");\r
+ Resource res = getServiceResource(g, element);\r
+ if (res == null)\r
+ return null;\r
+ Resource r = g.getPossibleObject(res, relation);\r
+ if (r == null)\r
+ return null;\r
+ if (StructuralUtils.isStructuralInstance(g, r)) {\r
+ return new StructuralResource(g, r, element.getContext(),r);\r
+ } else {\r
+ return new StructuralResource(g, r, element.getContext());\r
+ }\r
+ } catch (DatabaseException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public boolean set(WriteGraph g, StructuralResource selement, StructuralResource value)\r
+ throws MappingException {\r
+ try {\r
+ LOGGER.info(" RelatedObjectAccessor.set");\r
+ Resource element = getServiceResource(g, selement);\r
+ if (element == null)\r
+ return false;\r
+ Resource resource = g.getPossibleObject(element, relation);\r
+ if(resource == null) {\r
+ if(value == null)\r
+ return false;\r
+ if (preventChange(selement))\r
+ return false;\r
+ g.claim(element, relation, value.getResource());\r
+ return true;\r
+ }\r
+ else if(resource.equals(value))\r
+ return false;\r
+ else {\r
+ if (preventChange(selement))\r
+ return false;\r
+ g.deny(element, relation);\r
+ if(value != null)\r
+ g.claim(element, relation, value.getResource());\r
+ return true;\r
+ }\r
+ } catch (DatabaseException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ \r
+ }\r
+ \r
+ \r
+ \r
+ private Resource getServiceResource(ReadGraph g, StructuralResource element) {\r
+ if(!useTypeResource)\r
+ return element.getResource();\r
+ return element.getTypeResource();\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.structural.rules.domain;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.Collections;\r
+import java.util.List;\r
+\r
+import org.apache.log4j.Logger;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.objmap.exceptions.MappingException;\r
+import org.simantics.objmap.graph.rules.domain.IDomainAccessor;\r
+import org.simantics.objmap.graph.rules.domain.MappingUtils;\r
+import org.simantics.objmap.structural.StructuralResource;\r
+\r
+\r
+public class RelatedObjectsAccessor implements IDomainAccessor<StructuralResource,Collection<StructuralResource>> {\r
+\r
+ static Logger LOGGER = Logger.getLogger("org.simantics.objmap");\r
+ \r
+ Resource relation;\r
+ boolean deleteExtraObjects;\r
+ boolean useTypeResource;\r
+ \r
+ private boolean preventStructuralChanges = true;\r
+ private boolean preventStructuralRootChanges = true;\r
+\r
+ public RelatedObjectsAccessor(Resource relation, boolean deleteExtraObjects, boolean useTypeResource) {\r
+ super();\r
+ this.relation = relation;\r
+ this.deleteExtraObjects = deleteExtraObjects;\r
+ this.useTypeResource = useTypeResource;\r
+ }\r
+ \r
+ public RelatedObjectsAccessor(Resource relation, boolean deleteExtraObjects, boolean useTypeResource, boolean preventStructuralChanges, boolean preventStructuralRootChanges) {\r
+ super();\r
+ this.relation = relation;\r
+ this.deleteExtraObjects = deleteExtraObjects;\r
+ this.useTypeResource = useTypeResource;\r
+ this.preventStructuralChanges = preventStructuralChanges;\r
+ this.preventStructuralRootChanges = preventStructuralRootChanges;\r
+ }\r
+\r
+ @Override\r
+ public Collection<StructuralResource> get(ReadGraph g, StructuralResource element) throws MappingException {\r
+ try {\r
+ LOGGER.info(" RelatedObjectsAccessor.get");\r
+ \r
+ \r
+ Resource res = getServiceResource(g, element);\r
+ if (res == null)\r
+ return Collections.EMPTY_LIST;\r
+ Collection<Resource> coll = g.getObjects(res, relation);\r
+ List<StructuralResource> result = new ArrayList<StructuralResource>(coll.size());\r
+ for (Resource r : coll) {\r
+ if (StructuralUtils.isStructuralInstance(g, r)) {\r
+ result.add(new StructuralResource(g, r, element.getContext(),r));\r
+ } else {\r
+ result.add(new StructuralResource(g, r, element.getContext()));\r
+ }\r
+ }\r
+ return result;\r
+ } catch (DatabaseException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ }\r
+ \r
+ private boolean preventChange(StructuralResource element) {\r
+ return preventStructuralChanges && element.isStructural() && (!element.isStructuralRoot()||preventStructuralRootChanges); \r
+ }\r
+ \r
+ @Override\r
+ public boolean set(WriteGraph g, StructuralResource element, Collection<StructuralResource> value)\r
+ throws MappingException {\r
+ try {\r
+ LOGGER.info(" RelatedObjectsAccessor.set");\r
+ Resource res = getServiceResource(g, element);\r
+ if (res == null)\r
+ return false;\r
+ if (preventChange(element))\r
+ return false;\r
+ Resource[] arr = new Resource[value.size()];\r
+ int i = 0; \r
+ for (StructuralResource sr : value) {\r
+ arr[i++] = sr.getResource();\r
+ }\r
+ return MappingUtils.synchronizeStatements(g, res, relation, \r
+ arr, deleteExtraObjects);\r
+ } catch (DatabaseException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ \r
+ }\r
+\r
+ private Resource getServiceResource(ReadGraph g, StructuralResource element) {\r
+ if (!useTypeResource)\r
+ return element.getResource();\r
+ return element.getTypeResource();\r
+ }\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.structural.rules.domain;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.Collections;\r
+import java.util.List;\r
+\r
+import org.apache.log4j.Logger;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.utils.OrderedSetUtils;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.objmap.exceptions.MappingException;\r
+import org.simantics.objmap.graph.rules.domain.IDomainAccessor;\r
+import org.simantics.objmap.structural.StructuralResource;\r
+\r
+public class RelatedOrderedSetElementsAccessor implements IDomainAccessor<StructuralResource, Collection<StructuralResource>> {\r
+\r
+ static Logger LOGGER = Logger.getLogger("org.simantics.objmap");\r
+ \r
+ boolean deleteExtraObjects;\r
+ boolean useTypeResource;\r
+\r
+ public RelatedOrderedSetElementsAccessor(boolean deleteExtraObjects, boolean useTypeResource) {\r
+ super();\r
+ this.deleteExtraObjects = deleteExtraObjects;\r
+ this.useTypeResource = useTypeResource;\r
+ }\r
+\r
+ @Override\r
+ public Collection<StructuralResource> get(ReadGraph g, StructuralResource element) throws MappingException {\r
+ try {\r
+ LOGGER.info(" RelatedOrderedSetElementsAccessor.get");\r
+ Resource res = getServiceResource(g, element);\r
+ if (res == null)\r
+ return Collections.EMPTY_LIST;\r
+ List<Resource> list = OrderedSetUtils.toList(g, res);\r
+ List<StructuralResource> result = new ArrayList<StructuralResource>(list.size());\r
+ for (Resource r : list) {\r
+ result.add(new StructuralResource(g,r,element.getContext()));\r
+ }\r
+ return result;\r
+ } catch (DatabaseException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public boolean set(WriteGraph g, StructuralResource element, Collection<StructuralResource> value)\r
+ throws MappingException {\r
+ try {\r
+ LOGGER.info(" RelatedOrderedSetElementsAccessor.set");\r
+ Resource res = getServiceResource(g, element);\r
+ if (res == null)\r
+ return false;\r
+ List<Resource> list = new ArrayList<Resource>(value.size());\r
+ for (StructuralResource r : value) {\r
+ list.add(r.getResource());\r
+ }\r
+ return OrderedSetUtils.set(g, res, list);\r
+ // FIXME Implement deleteExtraObjects\r
+ } catch (DatabaseException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ \r
+ }\r
+ \r
+ private Resource getServiceResource(ReadGraph g, StructuralResource element) {\r
+ if (!useTypeResource)\r
+ return element.getResource();\r
+ return element.getTypeResource();\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.structural.rules.domain;\r
+\r
+import java.util.Arrays;\r
+\r
+import org.apache.log4j.Logger;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.Statement;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.objmap.exceptions.MappingException;\r
+import org.simantics.objmap.graph.rules.domain.IDomainAccessor;\r
+import org.simantics.objmap.structural.StructuralResource;\r
+\r
+\r
+public class RelatedValueAccessor implements IDomainAccessor<StructuralResource,Object> {\r
+\r
+ static Logger LOGGER = Logger.getLogger("org.simantics.objmap");\r
+ \r
+ Resource relation;\r
+ Resource valueType;\r
+ boolean useTypeResource;\r
+ \r
+ private boolean preventStructuralChanges = true;\r
+ private boolean preventStructuralRootChanges = true;\r
+ \r
+ public RelatedValueAccessor(Resource relation, Resource valueType, boolean useTypeResource) {\r
+ this.relation = relation;\r
+ this.valueType = valueType;\r
+ this.useTypeResource = useTypeResource;\r
+ }\r
+ \r
+ public RelatedValueAccessor(Resource relation, Resource valueType, boolean useTypeResource, boolean preventStructuralChanges, boolean preventStructuralRootChanges) {\r
+ this.relation = relation;\r
+ this.valueType = valueType;\r
+ this.useTypeResource = useTypeResource;\r
+ this.preventStructuralChanges = preventStructuralChanges;\r
+ this.preventStructuralRootChanges = preventStructuralRootChanges;\r
+ }\r
+ \r
+ private boolean preventChange(StructuralResource element) {\r
+ return preventStructuralChanges && element.isStructural() && (!element.isStructuralRoot()||preventStructuralRootChanges); \r
+ }\r
+\r
+ @Override\r
+ public Object get(ReadGraph g, StructuralResource element) throws MappingException {\r
+ try {\r
+ LOGGER.info(" RelatedValueAccessor.get");\r
+ Resource res = getServiceResource(g, element);\r
+ if (res == null)\r
+ return null;\r
+ Resource valueResource = g.getPossibleObject(res, relation);\r
+ if(valueResource == null)\r
+ return null;\r
+ return g.getValue(valueResource);\r
+ } catch (DatabaseException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public boolean set(WriteGraph g, StructuralResource relement, Object value)\r
+ throws MappingException {\r
+ try {\r
+ LOGGER.info(" RelatedValueAccessor.set");\r
+ \r
+ Resource element = getServiceResource(g, relement);\r
+ if (element == null)\r
+ return false;\r
+ Statement valueStatement = g.getPossibleStatement(element, relation);\r
+ if(valueStatement == null) {\r
+ if(value == null)\r
+ return false;\r
+ if (preventChange(relement))\r
+ return false;\r
+ Resource valueResource = g.newResource();\r
+ g.claim(valueResource, Layer0.getInstance(g).InstanceOf, null,\r
+ valueType);\r
+ g.claim(element, relation, valueResource);\r
+ g.claimValue(valueResource, value); \r
+ return true;\r
+ }\r
+ else {\r
+ if(value == null) {\r
+ if (preventChange(relement))\r
+ return false;\r
+ if (!valueStatement.isAsserted(element)) {\r
+ g.deny(valueStatement.getObject());\r
+ return true;\r
+ } else {\r
+ return false;\r
+ }\r
+ \r
+ } \r
+ Object currentValue = g.getValue(valueStatement.getObject());\r
+ if(equals(currentValue,value))\r
+ return false;\r
+ if (preventChange(relement))\r
+ return false;\r
+ if (!valueStatement.isAsserted(element))\r
+ g.claimValue(valueStatement.getObject(), value);\r
+ else {\r
+ Resource valueResource = g.newResource();\r
+ g.claim(valueResource, Layer0.getInstance(g).InstanceOf, null,\r
+ valueType);\r
+ g.claim(element, relation, valueResource);\r
+ g.claimValue(valueResource, value);\r
+ }\r
+ return true;\r
+ }\r
+ } catch (DatabaseException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ \r
+ }\r
+ \r
+ private Resource getServiceResource(ReadGraph g, StructuralResource element) {\r
+ if (!useTypeResource)\r
+ return element.getResource();\r
+ return element.getTypeResource();\r
+ }\r
+ \r
+ private boolean equals(Object o1, Object o2) {\r
+ if (o1 instanceof boolean[])\r
+ Arrays.equals((boolean[])o1,(boolean[])o2);\r
+ if (o1 instanceof int[])\r
+ Arrays.equals((int[])o1,(int[])o2);\r
+ if (o1 instanceof float[])\r
+ Arrays.equals((float[])o1,(float[])o2);\r
+ if (o1 instanceof double[])\r
+ Arrays.equals((double[])o1,(double[])o2);\r
+ if (o1 instanceof byte[])\r
+ Arrays.equals((byte[])o1,(byte[])o2);\r
+ return o1.equals(o2);\r
+ \r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.structural.rules.domain;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import org.apache.log4j.Logger;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.objmap.exceptions.MappingException;\r
+import org.simantics.objmap.graph.rules.domain.IDomainAccessor;\r
+import org.simantics.objmap.structural.StructuralResource;\r
+\r
+\r
+public class StructuralRelatedObjectAccessor implements IDomainAccessor<StructuralResource,StructuralResource> {\r
+\r
+ static Logger LOGGER = Logger.getLogger("org.simantics.objmap");\r
+ \r
+ Resource relation;\r
+ boolean useTypeResource;\r
+ \r
+ private boolean preventStructuralChanges = true;\r
+ private boolean preventStructuralRootChanges = true;\r
+ \r
+ public StructuralRelatedObjectAccessor(Resource relation, boolean useTypeResource) {\r
+ this.relation = relation;\r
+ this.useTypeResource = useTypeResource;\r
+ }\r
+ \r
+ public StructuralRelatedObjectAccessor(Resource relation, boolean useTypeResource, boolean preventStructuralChanges, boolean preventStructuralRootChanges) {\r
+ this.relation = relation;\r
+ this.useTypeResource = useTypeResource;\r
+ this.preventStructuralChanges = preventStructuralChanges;\r
+ this.preventStructuralRootChanges = preventStructuralRootChanges;\r
+ }\r
+ \r
+ private boolean preventChange(StructuralResource element) {\r
+ return preventStructuralChanges && element.isStructural() && (!element.isStructuralRoot()||preventStructuralRootChanges); \r
+ }\r
+\r
+ @Override\r
+ public StructuralResource get(ReadGraph g, StructuralResource element) throws MappingException {\r
+ try {\r
+ \r
+ LOGGER.info(" RelatedObjectAccessor.get");\r
+ \r
+ if (!element.isStructural())\r
+ return null;\r
+ Resource instance = StructuralUtils.getContainingInstance(element);\r
+ \r
+ Resource publicRelation = StructuralUtils.getPublishedRelation(g, element, relation);\r
+\r
+ if (publicRelation == null)\r
+ return null;\r
+ Resource r = g.getPossibleObject(instance, publicRelation);\r
+ if (r == null)\r
+ return null;\r
+ List<Resource> context = new ArrayList<Resource>();\r
+ for (int i = 0; i < element.getContext().size()-1; i++)\r
+ context.add(element.getContext().get(i));\r
+ if (StructuralUtils.isStructuralInstance(g, r)) {\r
+ return new StructuralResource(g, r, context,r);\r
+ } else {\r
+ return new StructuralResource(g, r, context);\r
+ }\r
+ } catch (DatabaseException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public boolean set(WriteGraph g, StructuralResource element, StructuralResource value)\r
+ throws MappingException {\r
+ try {\r
+ LOGGER.info(" RelatedObjectAccessor.set");\r
+ Resource instance = StructuralUtils.getContainingInstance(element);\r
+ Resource publicRelation = null;\r
+ if (instance == null)\r
+ return false;\r
+ publicRelation = StructuralUtils.getPublishedRelation(g, element, relation);\r
+ if (value == null) {\r
+ if (publicRelation == null)\r
+ return false;\r
+ if (preventChange(element))\r
+ return false;\r
+ g.deny(instance, publicRelation);\r
+ return true;\r
+ } else {\r
+ if (publicRelation == null) {\r
+ if (preventChange(element))\r
+ return false;\r
+ publicRelation = StructuralUtils.getOrCreatePublishedRelation(g, element, relation);\r
+ g.claim(instance, publicRelation, value.getResource());\r
+ return true;\r
+ } else {\r
+ Resource r = g.getPossibleObject(instance, publicRelation);\r
+ if (r == null) {\r
+ if (preventChange(element))\r
+ return false;\r
+ g.claim(instance, publicRelation, value.getResource());\r
+ return true;\r
+ } else {\r
+ if (r.equals(value.getResource()))\r
+ return false;\r
+ if (preventChange(element))\r
+ return false;\r
+ g.deny(instance, publicRelation);\r
+ g.claim(instance, publicRelation, value.getResource());\r
+ return true;\r
+ }\r
+ }\r
+ }\r
+ } catch (DatabaseException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ \r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.structural.rules.domain;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.Collections;\r
+import java.util.List;\r
+\r
+import org.apache.log4j.Logger;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.objmap.exceptions.MappingException;\r
+import org.simantics.objmap.graph.rules.domain.IDomainAccessor;\r
+import org.simantics.objmap.graph.rules.domain.MappingUtils;\r
+import org.simantics.objmap.structural.StructuralResource;\r
+import org.simantics.structural.stubs.StructuralResource2;\r
+\r
+\r
+public class StructuralRelatedObjectsAccessor implements IDomainAccessor<StructuralResource,Collection<StructuralResource>> {\r
+\r
+ static Logger LOGGER = Logger.getLogger("org.simantics.objmap");\r
+ \r
+ Resource relation;\r
+ boolean deleteExtraObjects;\r
+\r
+ public StructuralRelatedObjectsAccessor(Resource relation, boolean deleteExtraObjects) {\r
+ super();\r
+ this.relation = relation;\r
+ this.deleteExtraObjects = deleteExtraObjects;\r
+ }\r
+\r
+ @Override\r
+ public Collection<StructuralResource> get(ReadGraph g, StructuralResource element) throws MappingException {\r
+ try {\r
+ LOGGER.info(" RelatedObjectsAccessor.get");\r
+ \r
+ if (!element.isStructural())\r
+ return Collections.EMPTY_LIST;\r
+ \r
+ // Structural instance\r
+ Resource instance = StructuralUtils.getContainingInstance(element);\r
+ \r
+ Resource publicRelation = StructuralUtils.getPublishedRelation(g, element, relation);\r
+ \r
+ if (publicRelation == null)\r
+ return Collections.EMPTY_LIST;\r
+ \r
+ Collection<Resource> coll = g.getObjects(instance, publicRelation);\r
+ List<StructuralResource> result = new ArrayList<StructuralResource>(coll.size());\r
+ List<Resource> context = new ArrayList<Resource>();\r
+ for (int i = 0; i < element.getContext().size()-1; i++)\r
+ context.add(element.getContext().get(i));\r
+ for (Resource r : coll) {\r
+ if (StructuralUtils.isStructuralInstance(g, r)) {\r
+ result.add(new StructuralResource(g, r, context,r));\r
+ } else {\r
+ result.add(new StructuralResource(g, r, context));\r
+ }\r
+ }\r
+ return result;\r
+ } catch (DatabaseException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public boolean set(WriteGraph g, StructuralResource element, Collection<StructuralResource> value)\r
+ throws MappingException {\r
+ try {\r
+ LOGGER.info(" RelatedObjectsAccessor.set");\r
+ \r
+ if (!element.isStructural())\r
+ return false;\r
+ \r
+ Resource instance = StructuralUtils.getContainingInstance(element);\r
+ Resource publicRelation = null;\r
+ if (value.size() == 0) {\r
+ publicRelation = StructuralUtils.getPublishedRelation(g, element, relation);\r
+ if (publicRelation == null)\r
+ return false;\r
+ else {\r
+ return MappingUtils.synchronizeStatements(g, instance, publicRelation, new Resource[0], deleteExtraObjects);\r
+ }\r
+ } else {\r
+ publicRelation = StructuralUtils.getOrCreatePublishedRelation(g, element, relation);\r
+ if (publicRelation == null)\r
+ throw new MappingException("Structural Resource " + element + " cannot contain structural elements, the Resource is not published.");\r
+ Resource[] arr = new Resource[value.size()];\r
+ int i = 0; \r
+ for (StructuralResource sr : value) {\r
+ arr[i++] = sr.getResource();\r
+ }\r
+ return MappingUtils.synchronizeStatements(g, instance, publicRelation, arr, deleteExtraObjects);\r
+ }\r
+ \r
+ \r
+ \r
+ } catch (DatabaseException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ \r
+ }\r
+\r
+ \r
+}\r
--- /dev/null
+package org.simantics.objmap.structural.rules.domain;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.exception.NoSingleResultException;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.objmap.structural.StructuralResource;\r
+import org.simantics.structural.stubs.StructuralResource2;\r
+\r
+public class StructuralUtils {\r
+\r
+ \r
+ public static boolean isStructuralInstance(ReadGraph g, Resource r) throws DatabaseException {\r
+ StructuralResource2 sr = StructuralResource2.getInstance(g);\r
+ if (g.isInstanceOf(r, sr.Component)) {\r
+ Resource type = g.getSingleType(r);\r
+ return g.isInstanceOf(type, sr.Component);\r
+ }\r
+ return false;\r
+ \r
+ }\r
+ \r
+ public static Resource getContainingInstance(StructuralResource element) {\r
+ if (!element.isStructural())\r
+ return null;\r
+ Resource instance = element.getContext().get(element.getContext().size()-1);\r
+ return instance;\r
+ }\r
+ \r
+ public static Resource getPublishedRelation(ReadGraph g, StructuralResource element, Resource relation) throws DatabaseException{\r
+ Resource instance = getContainingInstance(element);\r
+ if (instance == null)\r
+ return null;\r
+ \r
+ Layer0 l0 = Layer0.getInstance(g);\r
+ StructuralResource2 sr = StructuralResource2.getInstance(g);\r
+ \r
+ Resource type = null;\r
+ try {\r
+ type = g.getSingleType(instance);\r
+ } catch (NoSingleResultException e) {\r
+ \r
+ }\r
+ if (type == null)\r
+ return null;\r
+ \r
+ boolean elementPublished = false;\r
+ Resource publicRelation = null;\r
+ for (Resource r : g.getObjects(type, l0.DomainOf)) {\r
+ if (r.equals(element.getResource()))\r
+ elementPublished = true;\r
+ if (g.isInstanceOf(r, relation)) {\r
+ if (element.getResource().equals(g.getPossibleObject(r, sr.IsBoundBy)))\r
+ publicRelation = r;\r
+ }\r
+ }\r
+ if (!elementPublished)\r
+ return null;\r
+ return publicRelation;\r
+ }\r
+ \r
+ public static Resource getOrCreatePublishedRelation(WriteGraph g, StructuralResource element, Resource relation) throws DatabaseException{\r
+ Resource instance = getContainingInstance(element);\r
+ if (instance == null)\r
+ return null;\r
+ \r
+ Layer0 l0 = Layer0.getInstance(g);\r
+ StructuralResource2 sr = StructuralResource2.getInstance(g);\r
+ \r
+ Resource type = g.getSingleType(instance);\r
+ \r
+ boolean elementPublished = false;\r
+ Resource publicRelation = null;\r
+ for (Resource r : g.getObjects(type, l0.DomainOf)) {\r
+ if (r.equals(element.getResource()))\r
+ elementPublished = true;\r
+ if (g.isInstanceOf(r, relation)) {\r
+ if (element.getResource().equals(g.getPossibleObject(r, sr.IsBoundBy)))\r
+ publicRelation = r;\r
+ }\r
+ }\r
+ if (!elementPublished)\r
+ return null;\r
+ if (publicRelation != null)\r
+ return publicRelation;\r
+ \r
+ publicRelation = g.newResource();\r
+ // TODO: type ConsistsOf publicRelation, publicRelation ConsistsOf publicInverse ?\r
+ g.claim(publicRelation, l0.SubrelationOf, l0.IsRelatedTo);\r
+ g.claim(publicRelation, l0.InstanceOf, relation);\r
+ g.claim(publicRelation, sr.IsBoundBy, element.getResource());\r
+ g.claim(type, l0.DomainOf, publicRelation);\r
+ g.claimLiteral(publicRelation, l0.HasName, g.getRelatedValue(element.getResource(), l0.HasName) +"_" + g.getRelatedValue(relation, l0.HasName)); \r
+ Resource inverse = g.getPossibleInverse(relation);\r
+ if (inverse != null) {\r
+ Resource publicInverse = g.newResource();\r
+ g.claim(publicInverse, l0.SubrelationOf, inverse);\r
+ g.claim(publicRelation, l0.InverseOf, publicInverse);\r
+ }\r
+ return publicRelation;\r
+ \r
+ }\r
+}\r
--- /dev/null
+package org.simantics.objmap.structural.schema;\r
+\r
+//import org.apache.log4j.Logger;\r
+import org.eclipse.core.runtime.IAdaptable;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.objmap.backward.IBackwardMapping;\r
+import org.simantics.objmap.exceptions.MappingException;\r
+import org.simantics.objmap.forward.IForwardMapping;\r
+import org.simantics.objmap.graph.schema.ILinkType;\r
+import org.simantics.objmap.structural.IStructuralObject;\r
+import org.simantics.objmap.structural.StructuralResource;\r
+\r
+/**\r
+ * A link type that is associated with adaptable resource (ReadGraph.getAdapter(Resource,Class)). \r
+ * The adapted object must implement IAdaptable interface for returning the original Resource. \r
+ * \r
+ * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
+ *\r
+ */\r
+public class AdaptedLinkType implements ILinkType<StructuralResource,IStructuralObject> {\r
+\r
+ \r
+ //static Logger LOGGER = Logger.getLogger("org.simantics.objmap");\r
+ \r
+ Resource domainType;\r
+ Class<?> rangeType;\r
+ \r
+ \r
+ public AdaptedLinkType(Resource domainType, Class<?> rangeType) {\r
+ this.domainType = domainType;\r
+ this.rangeType = rangeType;\r
+ }\r
+ \r
+ @Override\r
+ public StructuralResource createDomainElement(WriteGraph g, IStructuralObject rangeElement)\r
+ throws MappingException {\r
+ try {\r
+ IAdaptable adaptable = (IAdaptable)rangeElement;\r
+ Resource res = (Resource)adaptable.getAdapter(Resource.class);\r
+ if (res == null)\r
+ throw new NullPointerException();\r
+ return new StructuralResource(g,res);\r
+ } catch (Exception e) {\r
+ throw new MappingException("Adapted object must implement IAdaptable interface to return the source Resource.", e);\r
+ }\r
+ \r
+ }\r
+\r
+ \r
+ @Override\r
+ public IStructuralObject createRangeElement(ReadGraph g, StructuralResource domainElement)\r
+ throws MappingException {\r
+ try {\r
+ // FIXME : this will not work, we cannot assume that adapted objects would implement IStructuralObject interface.\r
+ return (IStructuralObject)g.adapt(domainElement.getResource(), rangeType);\r
+ } catch (DatabaseException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ }\r
+ \r
+ public void createDomain(WriteGraph graph, IBackwardMapping<StructuralResource, IStructuralObject> mapping, StructuralResource domainElement, IStructuralObject rangeElement) throws MappingException {\r
+ \r
+ };\r
+ \r
+ public void createRange(ReadGraph graph, org.simantics.objmap.forward.IForwardMapping<StructuralResource, IStructuralObject> mapping, StructuralResource domainElement, IStructuralObject rangeElement) throws MappingException {\r
+ \r
+ };\r
+ \r
+ public boolean updateDomain(WriteGraph g, IBackwardMapping<StructuralResource, IStructuralObject> map, StructuralResource domainElement, IStructuralObject rangeElement) throws MappingException {\r
+ return false;\r
+ }\r
+ \r
+ public boolean updateRange(ReadGraph g, IForwardMapping<StructuralResource, IStructuralObject> map, StructuralResource domainElement, IStructuralObject rangeElement) throws MappingException {\r
+ return false;\r
+ }\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.structural.schema;\r
+\r
+\r
+\r
+import java.util.Stack;\r
+\r
+import gnu.trove.map.hash.THashMap;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.common.utils.NameUtils;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.objmap.exceptions.MappingException;\r
+import org.simantics.objmap.graph.schema.ILinkType;\r
+import org.simantics.objmap.graph.schema.IMappingSchema;\r
+import org.simantics.objmap.structural.IStructuralObject;\r
+import org.simantics.objmap.structural.StructuralResource;\r
+\r
+\r
+/**\r
+ * \r
+ */\r
+public class DefaultSchema implements IMappingSchema<StructuralResource, IStructuralObject> {\r
+\r
+ THashMap<Resource, ILinkType<StructuralResource, IStructuralObject>> domainLinkTypes = \r
+ new THashMap<Resource, ILinkType<StructuralResource, IStructuralObject>>();\r
+ THashMap<Class<?>, ILinkType<StructuralResource, IStructuralObject>> rangeLinkTypes = \r
+ new THashMap<Class<?>, ILinkType<StructuralResource, IStructuralObject>>();\r
+ \r
+ public void addLinkType(SimpleLinkType linkType) {\r
+ domainLinkTypes.put(linkType.domainType, linkType);\r
+ rangeLinkTypes.put(linkType.rangeType, linkType);\r
+ }\r
+ \r
+ public void addLinkType(AdaptedLinkType linkType) {\r
+ domainLinkTypes.put(linkType.domainType, linkType);\r
+ rangeLinkTypes.put(linkType.rangeType, linkType);\r
+ }\r
+ \r
+ @Override\r
+ public ILinkType<StructuralResource, IStructuralObject> linkTypeOfDomainElement(ReadGraph g, StructuralResource element) throws MappingException { \r
+ try {\r
+ \r
+ for(Resource type : g.getTypes(element.getResource())) {\r
+\r
+ ILinkType<StructuralResource, IStructuralObject> linkType = domainLinkTypes.get(type);\r
+ if(linkType != null) return linkType;\r
+ \r
+ }\r
+ \r
+ throw new MappingException("Didn't find a link type for " +\r
+ NameUtils.getSafeName(g, element.getResource()) + ".");\r
+ \r
+ } catch (DatabaseException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public ILinkType<StructuralResource, IStructuralObject> linkTypeOfRangeElement(IStructuralObject element) throws MappingException {\r
+ ILinkType<StructuralResource, IStructuralObject> type = rangeLinkTypes.get(element.getClass());\r
+ if(type == null) {\r
+ Stack<Class<?>> clazzes = new Stack<Class<?>>();\r
+ for (Class<?> clazz : element.getClass().getInterfaces()) {\r
+ clazzes.add(clazz);\r
+ }\r
+ clazzes.add(element.getClass().getSuperclass());\r
+ \r
+ while (!clazzes.isEmpty()) {\r
+ Class<?> clazz = clazzes.pop();\r
+ \r
+ type = rangeLinkTypes.get(clazz);\r
+ if (type != null)\r
+ return type;\r
+ for (Class<?> c : clazz.getInterfaces())\r
+ clazzes.add(c);\r
+ \r
+ }\r
+ throw new MappingException("Didn't find a link type for " + element + ".");\r
+ }\r
+ return type;\r
+ }\r
+\r
+ \r
+ public ILinkType<StructuralResource, IStructuralObject> linkTypeOfDomainType(ReadGraph g, Resource type) { \r
+ return domainLinkTypes.get(type);\r
+ }\r
+ \r
+ public ILinkType<StructuralResource, IStructuralObject> linkTypeOfRangeType(Class<?> clazz) {\r
+ ILinkType<StructuralResource, IStructuralObject> type = rangeLinkTypes.get(clazz);\r
+ if(type == null) {\r
+ Stack<Class<?>> clazzes = new Stack<Class<?>>();\r
+ for (Class<?> c : clazz.getInterfaces()) {\r
+ clazzes.add(c);\r
+ }\r
+ clazzes.add(clazz.getSuperclass());\r
+ \r
+ while (!clazzes.isEmpty()) {\r
+ Class<?> c = clazzes.pop();\r
+ \r
+ type = rangeLinkTypes.get(c);\r
+ if (type != null)\r
+ return type;\r
+ for (Class<?> c2 : c.getInterfaces())\r
+ clazzes.add(c2);\r
+ \r
+ }\r
+ \r
+ }\r
+ return null;\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.objmap.structural.schema;\r
+\r
+import java.lang.annotation.Annotation;\r
+import java.lang.reflect.Field;\r
+import java.lang.reflect.Method;\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.objmap.bidirectional.IBidirectionalMappingRule;\r
+import org.simantics.objmap.graph.annotations.GraphType;\r
+import org.simantics.objmap.graph.annotations.HasCollectionAdder;\r
+import org.simantics.objmap.graph.annotations.HasCollectionRemover;\r
+import org.simantics.objmap.graph.annotations.HasSetter;\r
+import org.simantics.objmap.graph.annotations.OptionalRelatedElements;\r
+import org.simantics.objmap.graph.annotations.RelatedElements;\r
+import org.simantics.objmap.graph.annotations.RelatedElementsGet;\r
+import org.simantics.objmap.graph.annotations.RelatedGetObj;\r
+import org.simantics.objmap.graph.annotations.RelatedGetValue;\r
+import org.simantics.objmap.graph.annotations.RelatedOrderedSetElements;\r
+import org.simantics.objmap.graph.annotations.RelatedValue;\r
+import org.simantics.objmap.graph.annotations.UpdateMethod;\r
+import org.simantics.objmap.structural.annotations.StructuralRelatedElementsGet;\r
+import org.simantics.objmap.structural.annotations.StructuralRelatedGetObj;\r
+import org.simantics.objmap.structural.annotations.TypeRelatedElementsGet;\r
+import org.simantics.objmap.structural.annotations.TypeRelatedGetObj;\r
+import org.simantics.objmap.structural.annotations.TypeRelatedGetValue;\r
+import org.simantics.objmap.structural.annotations.factories.OptionalRelatedElementsRuleFactory;\r
+import org.simantics.objmap.structural.annotations.factories.RelatedElementsRuleFactory;\r
+import org.simantics.objmap.structural.annotations.factories.RelatedElementsRuleFactory2;\r
+import org.simantics.objmap.structural.annotations.factories.RelatedGetSetObjRuleFactory;\r
+import org.simantics.objmap.structural.annotations.factories.RelatedGetSetValueRuleFactory;\r
+import org.simantics.objmap.structural.annotations.factories.RelatedOrderedSetElementsRuleFactory;\r
+import org.simantics.objmap.structural.annotations.factories.RelatedValueRuleFactory;\r
+import org.simantics.objmap.structural.annotations.factories.StructuralRelatedElementsRuleFactory2;\r
+import org.simantics.objmap.structural.annotations.factories.StructuralRelatedGetSetObjRuleFactory;\r
+import org.simantics.objmap.structural.annotations.factories.TypeRelatedElementsRuleFactory2;\r
+import org.simantics.objmap.structural.annotations.factories.TypeRelatedGetSetObjRuleFactory;\r
+import org.simantics.objmap.structural.annotations.factories.TypeRelatedGetSetValueRuleFactory;\r
+import org.simantics.objmap.structural.annotations.factories.UpdateMethodFactory;\r
+import org.simantics.objmap.graph.annotations.meta.IsClassRule;\r
+import org.simantics.objmap.graph.annotations.meta.IsCollectionRule;\r
+import org.simantics.objmap.graph.annotations.meta.IsFieldRule;\r
+import org.simantics.objmap.graph.annotations.meta.IsGetSetRule;\r
+import org.simantics.objmap.graph.annotations.meta.IsMethodRule;\r
+import org.simantics.objmap.graph.rules.factory.IClassRuleFactory;\r
+import org.simantics.objmap.graph.rules.factory.ICollectionRuleFactory;\r
+import org.simantics.objmap.graph.rules.factory.IFieldRuleFactory;\r
+import org.simantics.objmap.graph.rules.factory.IGetSetRuleFactory;\r
+import org.simantics.objmap.graph.rules.factory.IMethodRuleFactory;\r
+import org.simantics.objmap.structural.IStructuralObject;\r
+import org.simantics.objmap.structural.StructuralResource;\r
+\r
+\r
+public class MappingSchemas {\r
+ /**\r
+ * Creates a new SimpleLinkType based on the annotations in the given class.\r
+ * @throws IllegalAccessException \r
+ * @throws InstantiationException \r
+ * @see GraphType\r
+ * @see RelatedValue\r
+ */\r
+ public static SimpleLinkType fromAnnotations(ReadGraph g, Class<?> clazz) throws DatabaseException, InstantiationException, IllegalAccessException {\r
+ GraphType graphType = clazz.getAnnotation(GraphType.class);\r
+ \r
+ ArrayList<IBidirectionalMappingRule<StructuralResource, IStructuralObject>> rules = new ArrayList<IBidirectionalMappingRule<StructuralResource, IStructuralObject>>();\r
+ collectRulesFromAnnotations(g, clazz, rules);\r
+ \r
+ return new SimpleLinkType(\r
+ g.getResource(graphType.value()), \r
+ clazz, rules); \r
+ }\r
+ \r
+ public static void collectRulesFromAnnotations(ReadGraph g, Class<?> clazz, Collection<IBidirectionalMappingRule<StructuralResource, IStructuralObject>> rules) throws DatabaseException, InstantiationException, IllegalAccessException {\r
+ Class<?> superclass = clazz.getSuperclass();\r
+ if(superclass != null)\r
+ collectRulesFromAnnotations(g, superclass, rules);\r
+ \r
+ for(Annotation annotation : clazz.getAnnotations()) {\r
+\r
+ IsClassRule tag = annotation.annotationType().getAnnotation(IsClassRule.class);\r
+ if(tag!= null) {\r
+ rules.add(createClassRule(g, annotation, clazz).create(g, annotation, clazz));\r
+ }\r
+ }\r
+\r
+ for(Field f : clazz.getDeclaredFields()) {\r
+ f.setAccessible(true);\r
+\r
+ for(Annotation annotation : f.getAnnotations()) {\r
+\r
+ IsFieldRule tag = annotation.annotationType().getAnnotation(IsFieldRule.class);\r
+ if(tag != null) {\r
+ rules.add(createFieldRule(g, annotation, f).create(g, annotation, f));\r
+ }\r
+ }\r
+ }\r
+\r
+ for(Method m : clazz.getDeclaredMethods()) {\r
+ m.setAccessible(true);\r
+\r
+ for(Annotation annotation : m.getAnnotations()) {\r
+ IsMethodRule tag = \r
+ annotation.annotationType().getAnnotation(IsMethodRule.class);\r
+ if(tag != null) {\r
+ rules.add(createMethodRule(g, annotation, m).create(g, annotation, m));\r
+ }\r
+ }\r
+ }\r
+ \r
+ for (Method m : clazz.getDeclaredMethods()) {\r
+ m.setAccessible(true);\r
+ for (Annotation annotation : m.getAnnotations()) {\r
+ Class<? extends Annotation> annotationType = annotation.annotationType();\r
+\r
+ IsGetSetRule tag = \r
+ annotationType.getAnnotation(IsGetSetRule.class);\r
+ if (tag != null) {\r
+ \r
+ HasSetter setterAnnType = annotationType.getAnnotation(HasSetter.class);\r
+ \r
+ Class<? extends Annotation> setterAnn = setterAnnType.value();\r
+ \r
+ Method getter = m;\r
+ \r
+ IGetSetRuleFactory<StructuralResource, IStructuralObject> ruleFactory = createGetSetRuleFactory(g, annotation, getter);\r
+ \r
+ \r
+ Method setter = null;\r
+ \r
+ for (Method m2 : clazz.getDeclaredMethods()) {\r
+ Annotation set = m2.getAnnotation(setterAnn);\r
+ if (set != null && ruleFactory.isSetter(annotation, set))\r
+ setter = m2;\r
+ }\r
+\r
+ rules.add(ruleFactory.create(g, annotation, getter, setter));\r
+ }\r
+ \r
+ }\r
+ }\r
+ \r
+ for (Method m : clazz.getDeclaredMethods()) {\r
+ m.setAccessible(true);\r
+ for (Annotation annotation : m.getAnnotations()) {\r
+ Class<? extends Annotation> annotationType = annotation.annotationType();\r
+\r
+ IsCollectionRule tag = \r
+ annotationType.getAnnotation(IsCollectionRule.class);\r
+ if (tag != null) {\r
+ \r
+ HasCollectionAdder adderAnnType = annotationType.getAnnotation(HasCollectionAdder.class);\r
+ HasCollectionRemover removerAnnType = annotationType.getAnnotation(HasCollectionRemover.class);\r
+ \r
+ Class<? extends Annotation> adderAnn = adderAnnType.value();\r
+ Class<? extends Annotation> removerAnn = removerAnnType.value();\r
+ \r
+ Method getter = m;\r
+ \r
+ ICollectionRuleFactory<StructuralResource, IStructuralObject> ruleFactory = createCollectionRuleFactory(g, annotation, getter);\r
+ \r
+ \r
+ Method adder = null;\r
+ Method remover = null;\r
+ \r
+ for (Method m2 : clazz.getDeclaredMethods()) {\r
+ Annotation add = m2.getAnnotation(adderAnn);\r
+ Annotation rem = m2.getAnnotation(removerAnn);\r
+ if (add != null && ruleFactory.isAdder(annotation, add))\r
+ adder = m2;\r
+ if (rem != null && ruleFactory.isRemover(annotation, rem))\r
+ remover = m2;\r
+ }\r
+ \r
+ \r
+ \r
+ rules.add(ruleFactory.create(g, annotation, getter,adder,remover));\r
+ }\r
+ \r
+ }\r
+ }\r
+ }\r
+ \r
+ public static IClassRuleFactory<StructuralResource, IStructuralObject> createClassRule(ReadGraph g, Annotation annotation, Class<?> clazz) {\r
+ return null;\r
+ }\r
+ \r
+ public static IFieldRuleFactory<StructuralResource, IStructuralObject> createFieldRule(ReadGraph g, Annotation annotation, Field field) {\r
+ if (annotation.annotationType().equals(RelatedElements.class))\r
+ return new RelatedElementsRuleFactory<IStructuralObject>();\r
+ if (annotation.annotationType().equals(RelatedValue.class))\r
+ return new RelatedValueRuleFactory<IStructuralObject>();\r
+ if (annotation.annotationType().equals(OptionalRelatedElements.class))\r
+ return new OptionalRelatedElementsRuleFactory<IStructuralObject>();\r
+ if (annotation.annotationType().equals(RelatedOrderedSetElements.class))\r
+ return new RelatedOrderedSetElementsRuleFactory<IStructuralObject>();\r
+ return null;\r
+ }\r
+ \r
+ public static IMethodRuleFactory<StructuralResource, IStructuralObject> createMethodRule(ReadGraph g, Annotation annotation, Method m) {\r
+ if (annotation.annotationType().equals(UpdateMethod.class))\r
+ return new UpdateMethodFactory<StructuralResource,IStructuralObject>();\r
+ return null;\r
+ }\r
+ \r
+ public static IGetSetRuleFactory<StructuralResource, IStructuralObject> createGetSetRuleFactory(ReadGraph g, Annotation annotation, Method getter) {\r
+ if (annotation.annotationType().equals(RelatedGetValue.class))\r
+ return new RelatedGetSetValueRuleFactory<IStructuralObject>();\r
+ if (annotation.annotationType().equals(RelatedGetObj.class))\r
+ return new RelatedGetSetObjRuleFactory<IStructuralObject>();\r
+ if (annotation.annotationType().equals(TypeRelatedGetValue.class))\r
+ return new TypeRelatedGetSetValueRuleFactory<IStructuralObject>();\r
+ if (annotation.annotationType().equals(TypeRelatedGetObj.class))\r
+ return new TypeRelatedGetSetObjRuleFactory<IStructuralObject>();\r
+ if (annotation.annotationType().equals(StructuralRelatedGetObj.class))\r
+ return new StructuralRelatedGetSetObjRuleFactory<IStructuralObject>();\r
+ return null;\r
+ }\r
+ \r
+ public static ICollectionRuleFactory<StructuralResource, IStructuralObject> createCollectionRuleFactory(ReadGraph g, Annotation annotation, Method getter) {\r
+ if (annotation.annotationType().equals(RelatedElementsGet.class))\r
+ return new RelatedElementsRuleFactory2<IStructuralObject>();\r
+ if (annotation.annotationType().equals(TypeRelatedElementsGet.class))\r
+ return new TypeRelatedElementsRuleFactory2<IStructuralObject>();\r
+ if (annotation.annotationType().equals(StructuralRelatedElementsGet.class))\r
+ return new StructuralRelatedElementsRuleFactory2<IStructuralObject>();\r
+ return null;\r
+ }\r
+ \r
+ \r
+ /**\r
+ * Creates a new SimpleLinkType based on the annotations in the given class.\r
+ * @throws IllegalAccessException \r
+ * @throws InstantiationException \r
+ * @see GraphType\r
+ * @see RelatedValue\r
+ */\r
+ public static AdaptedLinkType fromAdaptable(ReadGraph g, String type, Class<?> clazz) throws DatabaseException, InstantiationException, IllegalAccessException {\r
+ \r
+ \r
+ return new AdaptedLinkType(g.getResource(type), clazz); \r
+ }\r
+ \r
+ \r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.objmap.structural.schema;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collections;\r
+import java.util.List;\r
+\r
+import org.apache.log4j.Logger;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.utils.NameUtils;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.objmap.backward.IBackwardMapping;\r
+import org.simantics.objmap.bidirectional.IBidirectionalMappingRule;\r
+import org.simantics.objmap.exceptions.MappingException;\r
+import org.simantics.objmap.forward.IForwardMapping;\r
+import org.simantics.objmap.graph.schema.ILinkType;\r
+import org.simantics.objmap.structural.IStructuralObject;\r
+import org.simantics.objmap.structural.StructuralResource;\r
+\r
+\r
+\r
+public class SimpleLinkType implements ILinkType<StructuralResource,IStructuralObject> {\r
+ \r
+ static Logger LOGGER = Logger.getLogger("org.simantics.objmap");\r
+ \r
+ public Resource domainType;\r
+ public Class<?> rangeType;\r
+ ArrayList<IBidirectionalMappingRule<StructuralResource,IStructuralObject>> rules;\r
+ \r
+ public SimpleLinkType(Resource domainType, Class<?> rangeType,\r
+ ArrayList<IBidirectionalMappingRule<StructuralResource,IStructuralObject>> rules) {\r
+ this.domainType = domainType;\r
+ this.rangeType = rangeType;\r
+ this.rules = rules;\r
+ }\r
+\r
+ public SimpleLinkType(Resource domainType, Class<?> rangeType) {\r
+ this(domainType, rangeType, new ArrayList<IBidirectionalMappingRule<StructuralResource,IStructuralObject>>());\r
+ }\r
+\r
+ /**\r
+ * Adds a new rule to this link type that is enforced\r
+ * during updates.\r
+ */\r
+ public void addRule(IBidirectionalMappingRule<StructuralResource,IStructuralObject> rule) {\r
+ rules.add(rule);\r
+ }\r
+ \r
+ @Override\r
+ public StructuralResource createDomainElement(WriteGraph g, IStructuralObject rangeElement)\r
+ throws MappingException {\r
+ try {\r
+ if(LOGGER.isInfoEnabled())\r
+ LOGGER.info("SimpleLinkType.createDomainElement " +\r
+ rangeElement.toString()\r
+ );\r
+ if (rangeElement.getContext().size() == 0) {\r
+ // there is no context, this not a structural resource / object.\r
+ Resource result = g.newResource();\r
+ g.claim(result, Layer0.getInstance(g).InstanceOf, null, domainType);\r
+ return new StructuralResource(g,result);\r
+ } else {\r
+ if (rangeElement.getContext().size() == 1 && rangeElement.getContext().get(0).equals(rangeElement)) {\r
+ // Structural object's context is itself, we are instantiating a new structural model.\r
+ Resource type = rangeElement.getType();\r
+ Resource result = g.newResource();\r
+ g.claim(result, Layer0.getInstance(g).InstanceOf, null, type);\r
+ return new StructuralResource(g,result,result);\r
+ } else {\r
+ // Structural object's context is not itself, which means that the object is inside of a structural model.\r
+ // At the moment we do not support modifying instantiated structural models.\r
+ throw new MappingException("Cannot create a new StucturalObject " + rangeElement + " " + rangeElement.getClass());\r
+ }\r
+ }\r
+ } catch(DatabaseException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ }\r
+ @Override\r
+ public IStructuralObject createRangeElement(ReadGraph g, StructuralResource domainElement)\r
+ throws MappingException {\r
+ try {\r
+ if(LOGGER.isInfoEnabled())\r
+ try { \r
+ LOGGER.info("SimpleLinkType.createRangeElement " + NameUtils.getSafeName(g, domainElement.getResource()));\r
+ } catch(DatabaseException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ IStructuralObject result = (IStructuralObject)rangeType.newInstance();\r
+ if (domainElement.getContext().size() == 1) {\r
+ if (domainElement.getContext().get(0).equals(domainElement.getResource()))\r
+ result.setContext(Collections.singletonList(result));\r
+ else {\r
+ //result.setContext(result); \r
+ }\r
+ }\r
+ return result;\r
+ } catch (InstantiationException e) {\r
+ throw new MappingException(e);\r
+ } catch (IllegalAccessException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ }\r
+ \r
+ @SuppressWarnings("unchecked")\r
+ public void createDomain(WriteGraph graph, IBackwardMapping<StructuralResource,IStructuralObject> mapping, StructuralResource domainElement, IStructuralObject rangeElement) throws MappingException {\r
+ if (domainElement.isStructuralRoot())\r
+ // FIXME: this is nasty, but when a structural model is instantiated by creating new IStructuralObject, its related objects must be read from the graph first, or otherwise the objects would be deleted from the graph.\r
+ // as a side effect, if the new IStructuralObject has any properties set, those properties are set to null (because the graph does not contain those values).\r
+ // \r
+ updateRange(graph, (IForwardMapping<StructuralResource, IStructuralObject>)mapping, domainElement, rangeElement);\r
+ updateDomain(graph, mapping, domainElement, rangeElement);\r
+ };\r
+ \r
+ \r
+ @Override\r
+ public void createRange(ReadGraph graph, IForwardMapping<StructuralResource, IStructuralObject> mapping, StructuralResource domainElement, IStructuralObject rangeElement) throws MappingException {\r
+ if (rangeElement.getContext().size() == 0 && domainElement.getContext().size() > 0) {\r
+ List<IStructuralObject> ctx = new ArrayList<IStructuralObject>(domainElement.getContext().size());\r
+ try {\r
+ List<Resource> context = new ArrayList<Resource>();\r
+ for (int i = 0; i <domainElement.getContext().size(); i++) {\r
+ context.add(domainElement.getContext().get(i));\r
+ IStructuralObject ctxObj = mapping.get(new StructuralResource(graph,context.get(context.size()-1),context));\r
+ if (ctxObj == null) throw new MappingException("Cannot resolve range context for domain element " + domainElement);\r
+ ctx.add(ctxObj);\r
+ }\r
+ //ctx = mapping.get(new StructuralResource(graph,context.get(context.size()-1),context));\r
+ } catch (DatabaseException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ if (ctx.size() == 0)\r
+ throw new MappingException("Cannot find context for structural object, " + domainElement);\r
+ rangeElement.setContext(ctx);\r
+ }\r
+ updateRange(graph, mapping, domainElement, rangeElement);\r
+ }\r
+ \r
+ public boolean updateDomain(WriteGraph g, IBackwardMapping<StructuralResource,IStructuralObject> map, StructuralResource domainElement, IStructuralObject rangeElement) throws MappingException {\r
+ if(LOGGER.isInfoEnabled())\r
+ try { \r
+ LOGGER.info("SimpleLinkType.updateDomain " +\r
+ NameUtils.getSafeName(g, domainElement.getResource()) + " " +\r
+ rangeElement.toString()\r
+ );\r
+ } catch(DatabaseException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ \r
+ boolean updated = false;\r
+ for(IBidirectionalMappingRule<StructuralResource, IStructuralObject> rule : rules)\r
+ updated |= rule.updateDomain(g, map, domainElement, rangeElement);\r
+ return updated;\r
+ }\r
+ \r
+ public boolean updateRange(ReadGraph g, IForwardMapping<StructuralResource, IStructuralObject> map, StructuralResource domainElement, IStructuralObject rangeElement) throws MappingException {\r
+ \r
+ if(LOGGER.isInfoEnabled())\r
+ try { \r
+ LOGGER.info("SimpleLinkType.updateRange " +\r
+ NameUtils.getSafeName(g, domainElement.getResource()) + " " +\r
+ rangeElement.toString()\r
+ );\r
+ } catch(DatabaseException e) {\r
+ throw new MappingException(e);\r
+ }\r
+ \r
+ boolean updated = false;\r
+ for(IBidirectionalMappingRule<StructuralResource, IStructuralObject> rule : rules)\r
+ updated |= rule.updateRange(g, map, domainElement, rangeElement);\r
+ return updated;\r
+ }\r
+}\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<classpath>\r
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>\r
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>\r
+ <classpathentry kind="src" path="src"/>\r
+ <classpathentry kind="output" path="bin"/>\r
+</classpath>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<projectDescription>\r
+ <name>org.simantics.opencascade.vtk</name>\r
+ <comment></comment>\r
+ <projects>\r
+ </projects>\r
+ <buildSpec>\r
+ <buildCommand>\r
+ <name>org.eclipse.jdt.core.javabuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ <buildCommand>\r
+ <name>org.eclipse.pde.ManifestBuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ <buildCommand>\r
+ <name>org.eclipse.pde.SchemaBuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ </buildSpec>\r
+ <natures>\r
+ <nature>org.eclipse.pde.PluginNature</nature>\r
+ <nature>org.eclipse.jdt.core.javanature</nature>\r
+ </natures>\r
+</projectDescription>\r
--- /dev/null
+#Wed Aug 08 16:10:05 EEST 2012\r
+eclipse.preferences.version=1\r
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled\r
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6\r
+org.eclipse.jdt.core.compiler.compliance=1.6\r
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error\r
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error\r
+org.eclipse.jdt.core.compiler.source=1.6\r
--- /dev/null
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Vtk
+Bundle-SymbolicName: org.simantics.opencascade.vtk
+Bundle-Version: 1.0.0.qualifier
+Bundle-Activator: org.simantics.opencascade.vtk.Activator
+Bundle-Vendor: VTT
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.core.runtime,
+ org.jcae.opencascade;bundle-version="6.5.2",
+ org.simantics.opencascade;bundle-version="1.0.0",
+ vtk;bundle-version="5.8.0",
+ javax.vecmath;bundle-version="1.5.2",
+ org.simantics.utils.datastructures;bundle-version="1.1.0"
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Bundle-ActivationPolicy: lazy
+Export-Package: org.simantics.opencascade.vtk
--- /dev/null
+source.. = src/\r
+output.. = bin/\r
+bin.includes = META-INF/,\\r
+ .\r
--- /dev/null
+package org.simantics.opencascade.vtk;\r
+\r
+import org.eclipse.ui.plugin.AbstractUIPlugin;\r
+import org.osgi.framework.BundleContext;\r
+\r
+/**\r
+ * The activator class controls the plug-in life cycle\r
+ */\r
+public class Activator extends AbstractUIPlugin {\r
+\r
+ // The plug-in ID\r
+ public static final String PLUGIN_ID = "org.simantics.opencascade.vtk"; //$NON-NLS-1$\r
+\r
+ // The shared instance\r
+ private static Activator plugin;\r
+ \r
+ /**\r
+ * The constructor\r
+ */\r
+ public Activator() {\r
+ }\r
+\r
+ /*\r
+ * (non-Javadoc)\r
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)\r
+ */\r
+ public void start(BundleContext context) throws Exception {\r
+ super.start(context);\r
+ plugin = this;\r
+ }\r
+\r
+ /*\r
+ * (non-Javadoc)\r
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)\r
+ */\r
+ public void stop(BundleContext context) throws Exception {\r
+ plugin = null;\r
+ super.stop(context);\r
+ }\r
+\r
+ /**\r
+ * Returns the shared instance\r
+ *\r
+ * @return the shared instance\r
+ */\r
+ public static Activator getDefault() {\r
+ return plugin;\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.opencascade.vtk;\r
+\r
+import java.util.HashSet;\r
+import java.util.List;\r
+import java.util.Set;\r
+\r
+import javax.vecmath.Point3d;\r
+import javax.vecmath.Vector3d;\r
+\r
+import org.simantics.utils.datastructures.MapList;\r
+\r
+import vtk.vtkCell;\r
+import vtk.vtkIdList;\r
+import vtk.vtkLine;\r
+import vtk.vtkPoints;\r
+import vtk.vtkPolyData;\r
+import vtk.vtkProgrammableFilter;\r
+import vtk.vtkVertex;\r
+\r
+public class EdgePointsFilter extends vtkProgrammableFilter {\r
+ vtkPoints outputPoints;\r
+ \r
+ \r
+ public EdgePointsFilter() {\r
+ SetExecuteMethod(this, "compute");\r
+ }\r
+ \r
+ public void compute() {\r
+ vtkPolyData polyDataInput = GetPolyDataInput();\r
+ vtkPolyData polyDataOutput = GetPolyDataOutput();\r
+ vtkPoints inputPoints = polyDataInput.GetPoints();\r
+ \r
+ outputPoints = new vtkPoints();\r
+\r
+ MapList<Integer, Integer> edgeIndices = new MapList<Integer, Integer>();\r
+ for (int i = 0; i <polyDataInput.GetNumberOfCells(); i++) {\r
+ vtkCell cell= polyDataInput.GetCell(i);\r
+ if (cell.IsA("vtkLine") > 0) {\r
+ vtkLine line = (vtkLine)cell;\r
+ int i1 = line.GetPointId(0);\r
+ int i2 = line.GetPointId(1);\r
+ if (!edgeIndices.contains(i1, i2)) {\r
+ edgeIndices.add(i1, i2);\r
+ edgeIndices.add(i2, i1);\r
+ }\r
+ line.Delete();\r
+ } \r
+ }\r
+ \r
+ Set<Integer> vertices = new HashSet<Integer>();\r
+ for (Integer i : edgeIndices.getKeys()) {\r
+ List<Integer> edges = edgeIndices.getValues(i);\r
+ if (edges.size() != 2)\r
+ vertices.add(i);\r
+ else {\r
+ double tp[] = inputPoints.GetPoint(i);\r
+ double ep1[] = inputPoints.GetPoint(edges.get(0));\r
+ double ep2[] = inputPoints.GetPoint(edges.get(1));\r
+ Point3d t = new Point3d(tp);\r
+ Vector3d v1 = new Vector3d(ep1);\r
+ Vector3d v2 = new Vector3d(ep2);\r
+ v1.sub(t);\r
+ v2.sub(t);\r
+ double angle = Math.PI - v1.angle(v2);\r
+ if (angle > Math.PI/6)\r
+ vertices.add(i);\r
+ }\r
+ }\r
+ for (int i : vertices) {\r
+ outputPoints.InsertNextPoint(inputPoints.GetPoint(i));\r
+ }\r
+ polyDataOutput.Allocate(vertices.size(), vertices.size());\r
+ \r
+ vtkVertex vertex = new vtkVertex();\r
+ vtkIdList list = vertex.GetPointIds();\r
+ for (int i = 0; i < vertices.size(); i++) {\r
+ list.SetId(0, i);\r
+ polyDataOutput.InsertNextCell(vertex.GetCellType(), list);\r
+ }\r
+ \r
+ polyDataOutput.SetPoints(outputPoints);\r
+ \r
+ \r
+ list.Delete();\r
+ vertex.Delete();\r
+ \r
+ polyDataOutput.Delete();\r
+ polyDataInput.Delete();\r
+ \r
+ }\r
+ \r
+ @Override\r
+ public void Delete() {\r
+ outputPoints.Delete();\r
+ super.Delete();\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.opencascade.vtk;\r
+\r
+import java.util.List;\r
+\r
+import javax.vecmath.Matrix4d;\r
+import javax.vecmath.Point3d;\r
+\r
+import org.jcae.opencascade.jni.BRepMesh_IncrementalMesh;\r
+import org.jcae.opencascade.jni.BRep_Tool;\r
+import org.jcae.opencascade.jni.GP_Trsf;\r
+import org.jcae.opencascade.jni.Poly_Triangulation;\r
+import org.jcae.opencascade.jni.TopAbs_Orientation;\r
+import org.jcae.opencascade.jni.TopAbs_ShapeEnum;\r
+import org.jcae.opencascade.jni.TopExp_Explorer;\r
+import org.jcae.opencascade.jni.TopLoc_Location;\r
+import org.jcae.opencascade.jni.TopoDS_Face;\r
+import org.jcae.opencascade.jni.TopoDS_Shape;\r
+import org.simantics.opencascade.OCCTTool;\r
+\r
+import vtk.vtkActor;\r
+import vtk.vtkAlgorithmOutput;\r
+import vtk.vtkAppendPolyData;\r
+import vtk.vtkAssembly;\r
+import vtk.vtkCleanPolyData;\r
+import vtk.vtkDataSetMapper;\r
+import vtk.vtkFeatureEdges;\r
+import vtk.vtkGlyph3D;\r
+import vtk.vtkIdList;\r
+import vtk.vtkPoints;\r
+import vtk.vtkPolyData;\r
+import vtk.vtkPolyDataMapper;\r
+import vtk.vtkPolyDataNormals;\r
+import vtk.vtkProp;\r
+import vtk.vtkPropCollection;\r
+import vtk.vtkProperty;\r
+import vtk.vtkSphereSource;\r
+import vtk.vtkTriangle;\r
+\r
+public class VTKOCCTool {\r
+ public static vtkAssembly vtkTestAssembly() {\r
+ vtkAssembly assemblies = new vtkAssembly();\r
+ vtkPolyData partGrid = createTestPartGrid();\r
+ gridToAssembly(assemblies, partGrid);\r
+ return assemblies;\r
+ }\r
+ \r
+ public static vtkAssembly vtkOCCShapeToAssembly(TopoDS_Shape shape) {\r
+ double deflection = 0.001;\r
+\r
+ if (deflection <= 0.0) {\r
+ deflection = 0.0005;\r
+ System.out.println("Bad value for deflection. Using: " + deflection);\r
+ }\r
+\r
+ // FIXME : leaks memory!\r
+ //BRepTools.clean(shape);\r
+\r
+ double mass = OCCTTool.getMass(shape);\r
+\r
+ if (mass < 1.0e-12) {\r
+ System.out.println("Non 3D-shape detected");\r
+ System.out.println("The cad import features are currently limited to 3D models.");\r
+ }\r
+\r
+ double length = OCCTTool.getBoundingBoxDiagonal(shape);\r
+ deflection *= length; // use relative units\r
+\r
+ BRepMesh_IncrementalMesh mesh = new BRepMesh_IncrementalMesh(shape,deflection);\r
+\r
+ int faceNumber = 0;\r
+ TopExp_Explorer expFace = new TopExp_Explorer();\r
+\r
+ vtkAssembly assemblies = new vtkAssembly();\r
+ for (expFace.init(shape, TopAbs_ShapeEnum.FACE); expFace.more(); expFace.next()) {\r
+ TopoDS_Face face = (TopoDS_Face) expFace.current();\r
+ vtkPolyData partGrid = createPartGrid(face);\r
+ face.delete();\r
+ if (partGrid == null)\r
+ continue;\r
+ faceNumber++;\r
+ //gridToAssembly(assemblies, partGrid, stlSurfaceData, stlEdgeData);\r
+ gridToAssembly(assemblies, partGrid);\r
+ \r
+ }\r
+ expFace.delete();\r
+ mesh.delete();\r
+\r
+ if (faceNumber == 0) {\r
+ System.out\r
+ .println("Cad import: error: no surface triangulation was generated.");\r
+ return null;\r
+ }\r
+\r
+ return assemblies;\r
+ }\r
+ \r
+ private static void gridToAssembly(vtkAssembly assemblies, vtkPolyData partGrid, vtkAppendPolyData stlSurfaceData, vtkAppendPolyData stlEdgeData) {\r
+ \r
+ double featureAngle = 30;\r
+\r
+ \r
+ vtkDataSetMapper partMapper = new vtkDataSetMapper();\r
+ \r
+ boolean computeNormals = true;\r
+ boolean cleanPart = true;\r
+ boolean mergePoints = false;\r
+\r
+ vtkCleanPolyData partCleaner = new vtkCleanPolyData(); \r
+ if (cleanPart)\r
+ {\r
+ partCleaner.SetInput(partGrid);\r
+ if(mergePoints) {\r
+ partCleaner.PointMergingOn();\r
+ } else {\r
+ partCleaner.PointMergingOff();\r
+ }\r
+ }\r
+ \r
+ if (computeNormals)\r
+ {\r
+ vtkPolyDataNormals partNormals = new vtkPolyDataNormals();\r
+ \r
+ if (cleanPart)\r
+ {\r
+ partNormals.SetInputConnection(partCleaner.GetOutputPort());\r
+ }\r
+ else partNormals.SetInput(partGrid);\r
+ \r
+ partNormals.SetFeatureAngle(featureAngle); // this do not have to be neccesarily called\r
+ partMapper.SetInputConnection(partNormals.GetOutputPort());\r
+ partNormals.Delete(); \r
+ }\r
+ else\r
+ {\r
+ if (cleanPart) partMapper.SetInputConnection(partCleaner.GetOutputPort()); // metoda 2, ne tak pekne, viz http://www.codeguru.com/cpp/g-m/opengl/article.php/c2681\r
+ else partMapper.SetInput(partGrid); // metoda 1, ne tak pekne stinovani, viz: http://www.codeguru.com/cpp/g-m/opengl/article.php/c2681\r
+ }\r
+ partMapper.ScalarVisibilityOn();\r
+ \r
+ vtkActor partActor = new vtkActor();\r
+\r
+ partActor.SetPickable(1);\r
+ partActor.GetProperty().SetColor(1, 1, 0);\r
+ partActor.SetMapper(partMapper);\r
+ \r
+ // EDGES OF PARTS DETECTION\r
+ vtkFeatureEdges partEdges = new vtkFeatureEdges();\r
+ if (cleanPart) partEdges.SetInputConnection(partCleaner.GetOutputPort());\r
+ else partEdges.SetInput(partGrid); \r
+ partEdges.SetFeatureAngle(featureAngle); // this do not have to be neccesarily called\r
+ partEdges.FeatureEdgesOn();\r
+ partEdges.BoundaryEdgesOn();\r
+ partEdges.NonManifoldEdgesOn();\r
+ partEdges.ManifoldEdgesOn();\r
+\r
+ vtkDataSetMapper partEdgesMapper = new vtkDataSetMapper();\r
+ partEdgesMapper.SetInputConnection(partEdges.GetOutputPort());\r
+ partEdgesMapper.SetResolveCoincidentTopologyToPolygonOffset();\r
+ partEdgesMapper.ScalarVisibilityOff();\r
+ \r
+ vtkActor partEdgesActor = new vtkActor();\r
+ partEdgesActor.SetPickable(0);\r
+ partEdgesActor.GetProperty().SetColor(1, 0, 1);\r
+ partEdgesActor.SetMapper(partEdgesMapper);\r
+ \r
+\r
+ // Add triangles and edges to STL structures:\r
+ //--------------------------------------------\r
+ if (cleanPart) stlSurfaceData.AddInput(partCleaner.GetOutput());\r
+ else stlSurfaceData.AddInput(partGrid);\r
+ stlEdgeData.AddInput(partEdges.GetOutput());\r
+ \r
+ assemblies.AddPart(partActor);\r
+ assemblies.AddPart(partEdgesActor); \r
+ \r
+ // Clean up:\r
+ //----------\r
+ partEdgesActor.Delete();\r
+ partEdgesMapper.Delete();\r
+ partEdges.Delete();\r
+ partActor.Delete();\r
+ partMapper.Delete();\r
+ partGrid.Delete();\r
+ partCleaner.Delete();\r
+ }\r
+\r
+public static void gridToAssembly(vtkAssembly assemblies, vtkPolyData partGrid) {\r
+ \r
+ double featureAngle = 30;\r
+\r
+ \r
+ vtkDataSetMapper partMapper = new vtkDataSetMapper();\r
+ \r
+ boolean computeNormals = true;\r
+ boolean cleanPart = false;\r
+ boolean mergePoints = false;\r
+\r
+ vtkCleanPolyData partCleaner = new vtkCleanPolyData(); \r
+ if (cleanPart)\r
+ {\r
+ partCleaner.SetInput(partGrid);\r
+ if(mergePoints) {\r
+ partCleaner.PointMergingOn();\r
+ } else {\r
+ partCleaner.PointMergingOff();\r
+ }\r
+ }\r
+ \r
+ if (computeNormals)\r
+ {\r
+ vtkPolyDataNormals partNormals = new vtkPolyDataNormals();\r
+ \r
+ if (cleanPart)\r
+ {\r
+ vtkAlgorithmOutput out = partCleaner.GetOutputPort();\r
+ partNormals.SetInputConnection(out);\r
+ out.Delete();\r
+ }\r
+ else partNormals.SetInput(partGrid);\r
+ \r
+ partNormals.SetFeatureAngle(featureAngle); // this do not have to be neccesarily called\r
+ vtkAlgorithmOutput out = partNormals.GetOutputPort();\r
+ partMapper.SetInputConnection(out);\r
+ out.Delete();\r
+ partNormals.Delete(); \r
+ }\r
+ else\r
+ {\r
+ if (cleanPart) {\r
+ vtkAlgorithmOutput out = partCleaner.GetOutputPort();\r
+ partMapper.SetInputConnection(out); // metoda 2, ne tak pekne, viz http://www.codeguru.com/cpp/g-m/opengl/article.php/c2681\r
+ out.Delete();\r
+ }\r
+ else partMapper.SetInput(partGrid); // metoda 1, ne tak pekne stinovani, viz: http://www.codeguru.com/cpp/g-m/opengl/article.php/c2681\r
+ }\r
+ partMapper.ScalarVisibilityOn();\r
+ \r
+ vtkActor partActor = new vtkActor();\r
+ partActor.SetPickable(1);\r
+ vtkProperty prop = partActor.GetProperty();\r
+ prop.SetColor(1, 1, 0);\r
+ prop.Delete();\r
+ partActor.SetMapper(partMapper);\r
+ \r
+ assemblies.AddPart(partActor);\r
+ \r
+ {\r
+ // EDGES OF PARTS DETECTION\r
+ vtkFeatureEdges partEdges = new vtkFeatureEdges();\r
+ if (cleanPart) {\r
+ vtkAlgorithmOutput out = partCleaner.GetOutputPort();\r
+ partEdges.SetInputConnection(out);\r
+ out.Delete();\r
+ }\r
+ else partEdges.SetInput(partGrid); \r
+ // partEdges.SetFeatureAngle(featureAngle); // this do not have to be neccesarily called\r
+ partEdges.FeatureEdgesOn();\r
+ partEdges.BoundaryEdgesOn();\r
+ partEdges.NonManifoldEdgesOn();\r
+ partEdges.ManifoldEdgesOn();\r
+ \r
+ vtkDataSetMapper partEdgesMapper = new vtkDataSetMapper();\r
+ vtkAlgorithmOutput out = partEdges.GetOutputPort();\r
+ partEdgesMapper.SetInputConnection(out);\r
+ out.Delete();\r
+ partEdgesMapper.SetResolveCoincidentTopologyToPolygonOffset();\r
+ partEdgesMapper.ScalarVisibilityOff();\r
+ \r
+ vtkActor partEdgesActor = new vtkActor();\r
+ \r
+ prop = partEdgesActor.GetProperty();\r
+ prop.SetColor(0, 0, 0);\r
+ prop.SetLineWidth(2.0);\r
+ prop.Delete();\r
+ partEdgesActor.SetMapper(partEdgesMapper);\r
+ partEdgesActor.PickableOn(); \r
+ \r
+ assemblies.AddPart(partEdgesActor); \r
+ \r
+ {\r
+\r
+ EdgePointsFilter edgePoints = new EdgePointsFilter();\r
+ \r
+ \r
+ out = partEdges.GetOutputPort();\r
+ edgePoints.SetInputConnection(out);\r
+ out.Delete();\r
+ \r
+// vtkDataSetMapper partEdgePointsMapper = new vtkDataSetMapper();\r
+// out = edgePoints.GetOutputPort();\r
+// partEdgePointsMapper.SetInputConnection(out);\r
+// out.Delete();\r
+ \r
+// vtkVertexGlyphFilter glyphFilter = new vtkVertexGlyphFilter();\r
+// out = edgePoints.GetOutputPort();\r
+// glyphFilter.SetInputConnection(out);\r
+// glyphFilter.Update();\r
+// out.Delete();\r
+// \r
+// vtkPolyDataMapper partEdgePointsMapper = new vtkPolyDataMapper();\r
+// out = glyphFilter.GetOutputPort();\r
+// partEdgePointsMapper.SetInputConnection(out);\r
+// out.Delete();\r
+ \r
+ vtkSphereSource sphereSource = new vtkSphereSource();\r
+ vtkGlyph3D glyph3D = new vtkGlyph3D();\r
+ out = sphereSource.GetOutputPort();\r
+ glyph3D.SetSourceConnection(out);\r
+ out.Delete();\r
+ \r
+ out = edgePoints.GetOutputPort();\r
+ glyph3D.SetInputConnection(out);\r
+ out.Delete();\r
+ \r
+ //glyph3D.ScalingOff();\r
+ glyph3D.SetScaleFactor(0.03);\r
+ \r
+ glyph3D.Update();\r
+ \r
+ vtkPolyDataMapper partEdgePointsMapper = new vtkPolyDataMapper();\r
+ out = glyph3D.GetOutputPort();\r
+ partEdgePointsMapper.SetInputConnection(out);\r
+ out.Delete();\r
+ \r
+ vtkActor edgePointsActor = new vtkActor();\r
+ \r
+ prop = edgePointsActor.GetProperty();\r
+ prop.SetColor(0, 0, 1);\r
+ //prop.SetPointSize(10.0);\r
+ //prop.SetRepresentationToPoints();\r
+ prop.Delete();\r
+ edgePointsActor.SetMapper(partEdgePointsMapper);\r
+ \r
+ edgePointsActor.PickableOn();\r
+ assemblies.AddPart(edgePointsActor);\r
+ \r
+ \r
+ edgePointsActor.Delete();\r
+ partEdgePointsMapper.Delete();\r
+ // edgePoints.Delete();\r
+ }\r
+ // Clean up:\r
+ //----------\r
+ partEdgesActor.Delete();\r
+ partEdgesMapper.Delete();\r
+ partEdges.Delete();\r
+ }\r
+ \r
+ partActor.Delete();\r
+ partMapper.Delete();\r
+ partGrid.Delete();\r
+ partCleaner.Delete();\r
+}\r
+ \r
+ \r
+ \r
+ public static vtkPolyData createPartGrid ( TopoDS_Face face)\r
+ {\r
+ TopLoc_Location Location = new TopLoc_Location();\r
+ \r
+ Poly_Triangulation triangulation = BRep_Tool.triangulation(face, Location);\r
+\r
+ if(triangulation == null) {\r
+ Location.delete();\r
+ System.out.println("Encountered empty triangulation after face");\r
+ return null;\r
+ }\r
+ \r
+ boolean reverse = face.orientation()==TopAbs_Orientation.REVERSED;\r
+\r
+ int[]triangles = triangulation.triangles();\r
+ double[]nodes = triangulation.nodes();\r
+\r
+ int nofTriangles = triangulation.nbTriangles();\r
+ int nofNodes = triangulation.nbNodes();\r
+ \r
+ triangulation.delete();\r
+\r
+ if(nofTriangles < 1) {\r
+ System.out.println("No triangles for mesh on face");\r
+ Location.delete();\r
+ return null;\r
+ }\r
+\r
+ if(nofNodes < 1) {\r
+ System.out.println("No nodes for mesh on face:");\r
+ Location.delete();\r
+ return null;\r
+ }\r
+ //System.out.println("v " + nofNodes + " t " +nofTriangles);\r
+ vtkPolyData partGrid = new vtkPolyData();\r
+ partGrid.Allocate(nofTriangles, nofTriangles);\r
+\r
+ vtkTriangle triangle = new vtkTriangle();\r
+ vtkIdList list = triangle.GetPointIds();\r
+ for(int i = 0; i < nofTriangles; i++) \r
+ {\r
+ int n0, n1, n2;\r
+ if (!reverse) {\r
+ n0 = triangles[3 * i]; \r
+ n1 = triangles[3 * i + 1]; \r
+ n2 = triangles[3 * i + 2];\r
+ } else {\r
+ n0 = triangles[3 * i + 2]; \r
+ n1 = triangles[3 * i + 1]; \r
+ n2 = triangles[3 * i];\r
+ }\r
+ \r
+ list.SetId(0, n0);\r
+ list.SetId(1, n1);\r
+ list.SetId(2, n2);\r
+ partGrid.InsertNextCell(triangle.GetCellType(), list);\r
+ \r
+ }\r
+ list.Delete();\r
+ triangle.Delete(); \r
+ \r
+ GP_Trsf transformation = Location.transformation();\r
+ Location.delete();\r
+\r
+ double d_mat[] = new double[16];\r
+ double d_p[] = new double[3];\r
+ transformation.getValues(d_mat);\r
+ Matrix4d mat = new Matrix4d(d_mat);\r
+ \r
+ vtkPoints partPoints = new vtkPoints();\r
+ \r
+ for(int i = 0; i < nofNodes; i++) { \r
+ // FIXME: GP_Trsf.transform(double[]) leaks memory\r
+ \r
+ //double xyz[] = new double[]{nodes[3 * i], nodes[3 * i + 1], nodes[3 * i + 2]}; \r
+ //transformation.transforms(xyz);\r
+ //partPoints.InsertPoint(i, xyz);\r
+ Point3d p = new Point3d(nodes[3 * i], nodes[3 * i + 1], nodes[3 * i + 2]);\r
+ mat.transform(p);\r
+ d_p[0] = p.x;\r
+ d_p[1] = p.y;\r
+ d_p[2] = p.z;\r
+ partPoints.InsertPoint(i, d_p);\r
+ }\r
+ \r
+ transformation.delete();\r
+ \r
+ partGrid.SetPoints(partPoints);\r
+ partPoints.Delete();\r
+ \r
+ return partGrid;\r
+ }\r
+ \r
+ \r
+ \r
+ public static vtkPolyData createPartGrid ( List<Double> meshPoints, List<Integer> meshTriangles)\r
+ {\r
+ \r
+ \r
+ \r
+\r
+ \r
+ int nofTriangles = meshTriangles.size() / 3;\r
+ int nofNodes = meshPoints.size() /3;\r
+ \r
+ \r
+ if(nofTriangles < 1) {\r
+ System.out.println("No triangles for mesh on face");\r
+ return null;\r
+ }\r
+\r
+ if(nofNodes < 1) {\r
+ System.out.println("No nodes for mesh on face:");\r
+ return null;\r
+ }\r
+ //System.out.println("v " + nofNodes + " t " +nofTriangles);\r
+ vtkPolyData partGrid = new vtkPolyData();\r
+ partGrid.Allocate(nofTriangles, nofTriangles);\r
+\r
+ vtkTriangle triangle = new vtkTriangle();\r
+ vtkIdList list = triangle.GetPointIds();\r
+ for(int i = 0; i < nofTriangles; i++) \r
+ {\r
+ int n0, n1, n2; \r
+ n0 = meshTriangles.get(3 * i); \r
+ n1 = meshTriangles.get(3 * i + 1);\r
+ n2 = meshTriangles.get(3 * i + 2); \r
+\r
+ \r
+ list.SetId(0, n0);\r
+ list.SetId(1, n1);\r
+ list.SetId(2, n2);\r
+ partGrid.InsertNextCell(triangle.GetCellType(), list);\r
+ \r
+ }\r
+ list.Delete();\r
+ triangle.Delete(); \r
+ \r
+\r
+\r
+ double d_p[] = new double[3];\r
+\r
+ \r
+ vtkPoints partPoints = new vtkPoints();\r
+ \r
+ for(int i = 0; i < nofNodes; i++) { \r
+\r
+ d_p[0] = meshPoints.get(3*i);\r
+ d_p[1] = meshPoints.get(3*i+1);\r
+ d_p[2] = meshPoints.get(3*i+2);\r
+ partPoints.InsertPoint(i, d_p);\r
+ }\r
+ \r
+ partGrid.SetPoints(partPoints);\r
+ partPoints.Delete();\r
+ \r
+ return partGrid;\r
+ }\r
+ \r
+ private static vtkPolyData createTestPartGrid ()\r
+ {\r
+ int size = 64;\r
+ \r
+ double[] nodes = new double[(size+1)*(size+1)*3];\r
+ int[] triangles = new int[3 * size * size * 2];\r
+\r
+ double es = 1.0;\r
+ for (int i = 0; i <= size; i++) {\r
+ for (int j = 0; j <= size; j++) {\r
+ int index = j * size + i;\r
+ index *= 3;\r
+ double x = (double)i * es;\r
+ double y = (Math.sin((double)i/(double)size) + Math.sin((double)j/(double)size)) * es;\r
+ double z = (double)j * es;\r
+ nodes[index] = x;\r
+ nodes[index+1] = y;\r
+ nodes[index+2] = z;\r
+ }\r
+ }\r
+ \r
+ for (int i = 0; i < size; i++) {\r
+ for (int j = 0; j < size; j++) {\r
+ int index = j * size + i;\r
+ index *= 3;\r
+ index *= 2;\r
+ triangles[index ] = (j * (size+1) + i );\r
+ triangles[index+1] = (j * (size+1) + i+1);\r
+ triangles[index+2] = ((j+1) * (size+1) + i );\r
+ triangles[index+3] = ((j+1) * (size+1) + i );\r
+ triangles[index+4] = ((j ) * (size+1) + i +1 );\r
+ triangles[index+5] = ((j+1) * (size+1) + i +1 );\r
+ }\r
+ }\r
+\r
+ int nofTriangles = triangles.length / 3;\r
+ int nofNodes = nodes.length / 3;\r
+\r
+ if(nofTriangles < 1) {\r
+ \r
+ return null;\r
+ }\r
+\r
+ if(nofNodes < 1) {\r
+ \r
+ return null;\r
+ }\r
+ //System.out.println("v " + nofNodes + " t " +nofTriangles);\r
+ vtkPolyData partGrid = new vtkPolyData();\r
+ partGrid.Allocate(nofTriangles, nofTriangles);\r
+\r
+ vtkTriangle triangle = new vtkTriangle();\r
+ vtkIdList list = triangle.GetPointIds();\r
+ for(int i = 0; i < nofTriangles; i++) \r
+ {\r
+ int n0, n1, n2; \r
+ n0 = triangles[3 * i]; n1 = triangles[3 * i + 1]; n2 = triangles[3 * i + 2]; // triangles(i).Get(n0, n1, n2);\r
+\r
+// if(face.orientation() != TopAbs_Orientation.FORWARD) {\r
+// int tmp = n2; n2 = n1; n1 = tmp;\r
+// }\r
+ \r
+ list.SetId(0, n0);\r
+ list.SetId(1, n1);\r
+ list.SetId(2, n2);\r
+ partGrid.InsertNextCell(triangle.GetCellType(), list);\r
+ \r
+ }\r
+ list.Delete();\r
+ triangle.Delete(); \r
+\r
+ vtkPoints partPoints = new vtkPoints();\r
+ for(int i = 0; i < nofNodes; i++) { \r
+ double xyz[] = new double[]{nodes[3 * i], nodes[3 * i + 1], nodes[3 * i + 2]}; \r
+ partPoints.InsertPoint(i, xyz);\r
+ }\r
+ \r
+ partGrid.SetPoints(partPoints);\r
+ \r
+ partPoints.Delete();\r
+\r
+ return partGrid;\r
+ }\r
+ \r
+ public static void test() {\r
+ TopoDS_Shape shape = null;\r
+ //shape = OccTriangulator.makeCylinder(new double[]{0,0,0}, new double[]{0,1,0}, 1, 1);\r
+ for (int t = 0; t < 5000; t++) {\r
+ //shape = OccTriangulator.makeCylinder(new double[]{0,0,0}, new double[]{0,1,0}, 1, 1);\r
+ int test = 2;\r
+ if (test == 0) {\r
+ vtkAssembly ass = VTKOCCTool.vtkOCCShapeToAssembly(shape);\r
+ vtkPropCollection col;\r
+ col = ass.GetParts();\r
+ for (int i = 0; i < col.GetNumberOfItems(); i++)\r
+ {\r
+ vtkProp prop = (vtkProp) col.GetItemAsObject(i);\r
+ //System.out.println(prop.Print());\r
+ prop.Delete();\r
+ }\r
+ col.Delete();\r
+ ass.Delete();\r
+ }\r
+ else if (test == 1) {\r
+ //BRepTools.clean(shape);\r
+ \r
+ \r
+ vtkAssembly ass = new vtkAssembly();\r
+ \r
+ double vol = OCCTTool.getBoundingBoxDiagonal(shape);\r
+ double d = 0.001 * vol;\r
+ BRepMesh_IncrementalMesh mesh = new BRepMesh_IncrementalMesh(shape,d);\r
+ TopExp_Explorer expFace = new TopExp_Explorer();\r
+ for (expFace.init(shape, TopAbs_ShapeEnum.FACE); expFace.more(); expFace.next()) {\r
+ TopoDS_Face face = (TopoDS_Face) expFace.current();\r
+ {\r
+// TopLoc_Location Location = new TopLoc_Location();\r
+// Poly_Triangulation triangulation = BRep_Tool.triangulation(face, Location);\r
+// if (triangulation != null) {\r
+// \r
+// int[]triangles = triangulation.triangles();\r
+// double[]nodes = triangulation.nodes();\r
+// int nofTriangles = triangulation.nbTriangles();\r
+// int nofNodes = triangulation.nbNodes();\r
+// \r
+// triangulation.delete();\r
+// \r
+// GP_Trsf transformation = Location.transformation();\r
+// double d_mat[] = new double[16];\r
+// transformation.getValues(d_mat);\r
+// Matrix4d mat = new Matrix4d(d_mat);\r
+// for(int i = 0; i < nofNodes; i++) { \r
+// //double xyz[] = new double[]{nodes[3 * i], nodes[3 * i + 1], nodes[3 * i + 2]}; \r
+// Point3d p = new Point3d(nodes[3 * i], nodes[3 * i + 1], nodes[3 * i + 2]);\r
+// //transformation.transforms(xyz);\r
+// mat.transform(p);\r
+// }\r
+// transformation.delete();\r
+// }\r
+// \r
+// Location.delete();\r
+ vtkPolyData data = VTKOCCTool.createPartGrid(face);\r
+ VTKOCCTool.gridToAssembly(ass, data);\r
+ //data.Delete();\r
+ }\r
+ face.delete();\r
+ }\r
+ expFace.delete();\r
+ mesh.delete();\r
+ \r
+ vtkPropCollection col;\r
+ col = ass.GetParts();\r
+ for (int i = 0; i < col.GetNumberOfItems(); i++)\r
+ {\r
+ vtkProp prop = (vtkProp) col.GetItemAsObject(i);\r
+ //System.out.println(prop.Print());\r
+ prop.Delete();\r
+ }\r
+ col.Delete();\r
+ ass.Delete();\r
+ } else if (test == 2) {\r
+ double[] pointStruct = new double[]{0,0,0}, dirStruct = new double[]{0,1,0};\r
+ double radius = 1.0;\r
+ double height = 1.0;\r
+ \r
+ double[] axe = new double[6];\r
+ \r
+ System.arraycopy(pointStruct, 0, axe, 0, 3);\r
+ System.arraycopy(dirStruct, 0, axe, 3, 3);\r
+ org.jcae.opencascade.jni.BRepPrimAPI_MakeCylinder cyl = new org.jcae.opencascade.jni.BRepPrimAPI_MakeCylinder(axe, radius, height, 2 * Math.PI);\r
+ org.jcae.opencascade.jni.TopoDS_Shape tds = cyl.shape();\r
+ cyl.delete();\r
+ \r
+ double vol = OCCTTool.getBoundingBoxDiagonal(tds);\r
+ double d = 0.001 * vol;\r
+ BRepMesh_IncrementalMesh mesh = new BRepMesh_IncrementalMesh(tds,d);\r
+// TopExp_Explorer expFace = new TopExp_Explorer();\r
+// for (expFace.init(tds, TopAbs_ShapeEnum.FACE); expFace.more(); expFace.next()) {\r
+// TopoDS_Face face = (TopoDS_Face) expFace.current();\r
+// {\r
+// \r
+// }\r
+// face.delete();\r
+// }\r
+ mesh.delete();\r
+ \r
+ tds.delete();\r
+ }\r
+ //shape.delete();\r
+ System.out.println(t);\r
+ }\r
+ //shape.delete();\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.opencascade.vtk;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.List;\r
+\r
+import org.jcae.opencascade.jni.BRepMesh_IncrementalMesh;\r
+import org.jcae.opencascade.jni.TopAbs_ShapeEnum;\r
+import org.jcae.opencascade.jni.TopExp_Explorer;\r
+import org.jcae.opencascade.jni.TopoDS_Face;\r
+import org.jcae.opencascade.jni.TopoDS_Shape;\r
+import org.simantics.opencascade.OCCTTool;\r
+import org.simantics.utils.threads.AWTThread;\r
+import org.simantics.utils.threads.ThreadUtils;\r
+\r
+import vtk.vtkActor;\r
+import vtk.vtkAlgorithmOutput;\r
+import vtk.vtkCleanPolyData;\r
+import vtk.vtkDataSetMapper;\r
+import vtk.vtkFeatureEdges;\r
+import vtk.vtkGlyph3D;\r
+import vtk.vtkPanel;\r
+import vtk.vtkPolyData;\r
+import vtk.vtkPolyDataMapper;\r
+import vtk.vtkPolyDataNormals;\r
+import vtk.vtkPolyDataSilhouette;\r
+import vtk.vtkProp3D;\r
+import vtk.vtkProperty;\r
+import vtk.vtkRenderer;\r
+import vtk.vtkSphereSource;\r
+\r
+public class vtkSolidObject {\r
+ \r
+ public static double deflection = 0.001;\r
+ \r
+ public static double featureAngle = 30;\r
+ public static boolean computeNormals = true;\r
+ public static boolean cleanPart = false;\r
+ public static boolean mergePoints = false;\r
+ \r
+ private vtkPanel panel;\r
+ private TopoDS_Shape shape;\r
+ \r
+ private List<vtkProp3D> actors = new ArrayList<vtkProp3D>(2);\r
+ \r
+ private List<vtkProp3D> solid = new ArrayList<vtkProp3D>(1);\r
+ private List<vtkProp3D> edges = new ArrayList<vtkProp3D>(1);\r
+ private vtkActor silhouette = null;\r
+ \r
+ public vtkSolidObject(vtkPanel panel,TopoDS_Shape shape) {\r
+ this.shape = shape;\r
+ this.panel = panel;\r
+ }\r
+ \r
+ public void visualizeSolid(boolean showEdges, boolean showVertices) {\r
+ visualizeSolid(true, showEdges, showVertices);\r
+ }\r
+ \r
+ public void visualizeSolid(boolean showFaces, boolean showEdges, boolean showVertices) {\r
+ visualizeSolid(showFaces, showEdges, showVertices, false);\r
+ }\r
+ \r
+ public void visualizeSolid(boolean showFaces, boolean showEdges, boolean showVertices, boolean showSilhouette) {\r
+ clearActorsAWT();\r
+ vtkPolyData data = createSolidMesh(shape);\r
+ if (data == null)\r
+ return;\r
+ if (showFaces) {\r
+ solid.add(createActor(data)); \r
+ }\r
+ if (showEdges) {\r
+ vtkActor edge = createEdgesActor(data);\r
+ edges.add(edge); \r
+ if (showVertices) {\r
+ actors.add(createVerticesActor(edge));\r
+ }\r
+ }\r
+ if (showSilhouette) {\r
+ silhouette = createSilhouette(panel.GetRenderer(), data);\r
+ }\r
+ actors.addAll(solid);\r
+ actors.addAll(edges);\r
+ if (silhouette != null)\r
+ actors.add(silhouette);\r
+ data.Delete();\r
+ showActorsAWT();\r
+ }\r
+ \r
+ public void visualizeFaces(boolean showEdges, boolean showVertices) {\r
+ clearActorsAWT();\r
+ Collection<vtkPolyData> datas = createFaceMeshes(shape);\r
+ for (vtkPolyData data : datas) {\r
+ solid.add(createActor(data));\r
+ \r
+ if (showEdges) {\r
+ vtkActor edgesActor = createEdgesActor(data); \r
+ edges.add(edgesActor);\r
+ if (showVertices) {\r
+ actors.add(createVerticesActor(edgesActor));\r
+ }\r
+ }\r
+ data.Delete();\r
+ }\r
+ actors.addAll(solid);\r
+ actors.addAll(edges);\r
+ \r
+ showActorsAWT();\r
+ }\r
+ \r
+ public List<vtkProp3D> getActors() {\r
+ assert (Thread.currentThread() == AWTThread.getThreadAccess().getThread());\r
+ return actors;\r
+ }\r
+ \r
+ public List<vtkProp3D> getSolid() {\r
+ assert (Thread.currentThread() == AWTThread.getThreadAccess().getThread());\r
+ return solid;\r
+ }\r
+ \r
+ public List<vtkProp3D> getEdges() {\r
+ assert (Thread.currentThread() == AWTThread.getThreadAccess().getThread());\r
+ return edges;\r
+ }\r
+ \r
+ public vtkActor getSilhouette() {\r
+ assert (Thread.currentThread() == AWTThread.getThreadAccess().getThread());\r
+ return silhouette;\r
+ }\r
+ \r
+ public void showActorsAWT() {\r
+ assert (Thread.currentThread() == AWTThread.getThreadAccess().getThread());\r
+ vtkRenderer ren = panel.GetRenderer();\r
+ for (vtkProp3D act : actors) {\r
+ ren.AddActor(act);\r
+ }\r
+ }\r
+ \r
+ public void showActors() {\r
+ ThreadUtils.asyncExec(AWTThread.getThreadAccess(), new Runnable() {\r
+ \r
+ @Override\r
+ public void run() {\r
+ showActorsAWT();\r
+ }\r
+ });\r
+ }\r
+ \r
+ public void clearActorsAWT() {\r
+ assert (Thread.currentThread() == AWTThread.getThreadAccess().getThread());\r
+ if (actors.size() == 0)\r
+ return;\r
+ vtkRenderer ren = panel.GetRenderer();\r
+ for (vtkProp3D act : actors) {\r
+ if (act.GetVTKId() != 0) {\r
+ ren.RemoveActor(act);\r
+ act.Delete();\r
+ }\r
+ }\r
+ actors.clear();\r
+ solid.clear();\r
+ edges.clear();\r
+ }\r
+ \r
+ private void clearActorsAWT(List<vtkProp3D> actors) {\r
+ assert (Thread.currentThread() == AWTThread.getThreadAccess().getThread());\r
+ \r
+ if (actors.size() == 0)\r
+ return;\r
+ vtkRenderer ren = panel.GetRenderer();\r
+ panel.lock();\r
+ for (vtkProp3D act : actors) {\r
+ if (act.GetVTKId() != 0) {\r
+ ren.RemoveActor(act);\r
+ act.Delete();\r
+ }\r
+ }\r
+ panel.unlock();\r
+ }\r
+ \r
+ public void clearActors() {\r
+ if (actors.size() == 0)\r
+ return;\r
+ final List<vtkProp3D> temp = new ArrayList<vtkProp3D>(actors.size());\r
+ temp.addAll(actors);\r
+ actors.clear();\r
+ solid.clear();\r
+ edges.clear();\r
+ ThreadUtils.asyncExec(AWTThread.getThreadAccess(), new Runnable() {\r
+ \r
+ @Override\r
+ public void run() {\r
+ clearActorsAWT(temp);\r
+ }\r
+ });\r
+ }\r
+ \r
+ public void dispose() {\r
+ if (shape != null) {\r
+ shape.delete();\r
+ shape = null;\r
+ }\r
+ clearActors();\r
+ }\r
+ \r
+ public void delete() {\r
+ if (shape != null) {\r
+ shape.delete();\r
+ shape = null;\r
+ }\r
+ clearActorsAWT();\r
+ }\r
+ \r
+ private static double TOLERANCE = 0.01;\r
+ \r
+ public static vtkPolyData createSolidMesh(TopoDS_Shape shape) {\r
+ \r
+ double volume = OCCTTool.getBoundingBoxDiagonal(shape);\r
+ if (volume < TOLERANCE)\r
+ return null;\r
+ \r
+ BRepMesh_IncrementalMesh mesh = new BRepMesh_IncrementalMesh(shape,deflection*volume);\r
+ \r
+ TopExp_Explorer expFace = new TopExp_Explorer();\r
+ \r
+ List<Double> meshPoints = new ArrayList<Double>();\r
+ List<Integer> meshTriangles = new ArrayList<Integer>();\r
+ for (expFace.init(shape, TopAbs_ShapeEnum.FACE); expFace.more(); expFace.next()) {\r
+ TopoDS_Face face = (TopoDS_Face) expFace.current();\r
+ OCCTTool.appendToMesh(face, meshPoints, meshTriangles);\r
+ face.delete();\r
+ }\r
+ if (meshPoints.size() == 0 || meshTriangles.size() == 0)\r
+ return null;\r
+ \r
+ vtkPolyData data = VTKOCCTool.createPartGrid(meshPoints, meshTriangles);\r
+ \r
+ expFace.delete();\r
+ mesh.delete();\r
+ \r
+ return data;\r
+ }\r
+ \r
+ public static Collection<vtkPolyData> createFaceMeshes(TopoDS_Shape shape) {\r
+ \r
+ double volume = OCCTTool.getBoundingBoxDiagonal(shape);\r
+ Collection<vtkPolyData> faces = new ArrayList<vtkPolyData>();\r
+ \r
+ if (volume > TOLERANCE) {\r
+ \r
+ BRepMesh_IncrementalMesh mesh = new BRepMesh_IncrementalMesh(shape,deflection*volume);\r
+ \r
+ TopExp_Explorer expFace = new TopExp_Explorer();\r
+ \r
+ \r
+ for (expFace.init(shape, TopAbs_ShapeEnum.FACE); expFace.more(); expFace.next()) {\r
+ TopoDS_Face face = (TopoDS_Face) expFace.current();\r
+ vtkPolyData data = VTKOCCTool.createPartGrid(face);\r
+ face.delete();\r
+ faces.add(data);\r
+ }\r
+ \r
+ expFace.delete();\r
+ mesh.delete();\r
+ }\r
+ \r
+ return faces;\r
+ }\r
+ \r
+ \r
+ \r
+ public static vtkActor createActor(vtkPolyData partGrid) {\r
+ \r
+ \r
+ vtkDataSetMapper partMapper = new vtkDataSetMapper();\r
+ \r
+ vtkCleanPolyData partCleaner = null; \r
+ if (cleanPart)\r
+ {\r
+ partCleaner = new vtkCleanPolyData();\r
+ partCleaner.SetInput(partGrid);\r
+ if(mergePoints) {\r
+ partCleaner.PointMergingOn();\r
+ } else {\r
+ partCleaner.PointMergingOff();\r
+ }\r
+ }\r
+ \r
+ if (computeNormals)\r
+ {\r
+ vtkPolyDataNormals partNormals = new vtkPolyDataNormals();\r
+ \r
+ if (cleanPart)\r
+ {\r
+ vtkAlgorithmOutput out = partCleaner.GetOutputPort();\r
+ partNormals.SetInputConnection(out);\r
+ out.Delete();\r
+ }\r
+ else partNormals.SetInput(partGrid);\r
+ \r
+ partNormals.SetFeatureAngle(featureAngle); // this do not have to be neccesarily called\r
+ vtkAlgorithmOutput out = partNormals.GetOutputPort();\r
+ partMapper.SetInputConnection(out);\r
+ out.Delete();\r
+ partNormals.Delete(); \r
+ }\r
+ else\r
+ {\r
+ if (cleanPart) {\r
+ vtkAlgorithmOutput out = partCleaner.GetOutputPort();\r
+ partMapper.SetInputConnection(out); // metoda 2, ne tak pekne, viz http://www.codeguru.com/cpp/g-m/opengl/article.php/c2681\r
+ out.Delete();\r
+ }\r
+ else partMapper.SetInput(partGrid); // metoda 1, ne tak pekne stinovani, viz: http://www.codeguru.com/cpp/g-m/opengl/article.php/c2681\r
+ }\r
+ partMapper.ScalarVisibilityOn();\r
+ \r
+ vtkActor partActor = new vtkActor();\r
+ // partActor.SetPickable(1);\r
+ vtkProperty prop = partActor.GetProperty();\r
+ prop.SetColor(1, 1, 0);\r
+ prop.Delete();\r
+ partActor.SetMapper(partMapper);\r
+ \r
+ partMapper.Delete();\r
+ \r
+ if (cleanPart)\r
+ partCleaner.Delete();\r
+ \r
+ return partActor;\r
+ }\r
+ \r
+ public static vtkActor createEdgesActor(vtkPolyData partGrid) {\r
+ vtkCleanPolyData partCleaner = null; \r
+ \r
+ if (cleanPart)\r
+ {\r
+ partCleaner = new vtkCleanPolyData();\r
+ partCleaner.SetInput(partGrid);\r
+ if(mergePoints) {\r
+ partCleaner.PointMergingOn();\r
+ } else {\r
+ partCleaner.PointMergingOff();\r
+ }\r
+ }\r
+ \r
+ vtkFeatureEdges partEdges = new vtkFeatureEdges();\r
+ if (cleanPart) {\r
+ vtkAlgorithmOutput out = partCleaner.GetOutputPort();\r
+ partEdges.SetInputConnection(out);\r
+ out.Delete();\r
+ }\r
+ else partEdges.SetInput(partGrid); \r
+ // partEdges.SetFeatureAngle(featureAngle); // this do not have to be neccesarily called\r
+ partEdges.FeatureEdgesOn();\r
+ partEdges.BoundaryEdgesOn();\r
+ partEdges.NonManifoldEdgesOn();\r
+ partEdges.ManifoldEdgesOn();\r
+ \r
+ vtkDataSetMapper partEdgesMapper = new vtkDataSetMapper();\r
+ vtkAlgorithmOutput out = partEdges.GetOutputPort();\r
+ partEdgesMapper.SetInputConnection(out);\r
+ out.Delete();\r
+ partEdgesMapper.SetResolveCoincidentTopologyToPolygonOffset();\r
+ partEdgesMapper.ScalarVisibilityOff();\r
+ \r
+ vtkActor partEdgesActor = new vtkActor();\r
+ \r
+ vtkProperty prop = partEdgesActor.GetProperty();\r
+ prop.SetColor(0, 0, 0);\r
+ prop.SetLineWidth(2.0);\r
+ prop.Delete();\r
+ partEdgesActor.SetMapper(partEdgesMapper);\r
+\r
+ partEdgesMapper.Delete();\r
+ partEdges.Delete();\r
+ \r
+ if (cleanPart)\r
+ partCleaner.Delete();\r
+ \r
+ return partEdgesActor;\r
+ }\r
+ \r
+ public static vtkActor createVerticesActor(vtkActor partEdgesActor) {\r
+ vtkDataSetMapper partEdgesMapper = (vtkDataSetMapper) partEdgesActor.GetMapper();\r
+ vtkAlgorithmOutput out = partEdgesMapper.GetInputConnection(0, 0);\r
+ vtkFeatureEdges partEdges = (vtkFeatureEdges)out.GetProducer();\r
+ \r
+ vtkActor edgePointsActor = createVerticesActor(partEdges);\r
+ \r
+ partEdges.Delete();\r
+ //out.Delete();\r
+ partEdgesMapper.Delete();\r
+ return edgePointsActor;\r
+ }\r
+ \r
+ public static vtkActor createVerticesActor(vtkFeatureEdges partEdges) {\r
+ EdgePointsFilter edgePoints = new EdgePointsFilter();\r
+ \r
+ \r
+ vtkAlgorithmOutput out = partEdges.GetOutputPort();\r
+ edgePoints.SetInputConnection(out);\r
+ out.Delete();\r
+ \r
+ vtkSphereSource sphereSource = new vtkSphereSource();\r
+ vtkGlyph3D glyph3D = new vtkGlyph3D();\r
+ out = sphereSource.GetOutputPort();\r
+ glyph3D.SetSourceConnection(out);\r
+ out.Delete();\r
+ \r
+ out = edgePoints.GetOutputPort();\r
+ glyph3D.SetInputConnection(out);\r
+ out.Delete();\r
+ \r
+ glyph3D.SetScaleFactor(0.03);\r
+ \r
+ glyph3D.Update();\r
+ \r
+ vtkPolyDataMapper partEdgePointsMapper = new vtkPolyDataMapper();\r
+ out = glyph3D.GetOutputPort();\r
+ partEdgePointsMapper.SetInputConnection(out);\r
+ out.Delete();\r
+ \r
+ vtkActor edgePointsActor = new vtkActor();\r
+ \r
+ vtkProperty prop = edgePointsActor.GetProperty();\r
+ prop.SetColor(0, 0, 1);\r
+ prop.Delete();\r
+ edgePointsActor.SetMapper(partEdgePointsMapper);\r
+ \r
+ edgePointsActor.PickableOn();\r
+\r
+ \r
+ partEdgePointsMapper.Delete();\r
+ edgePoints.Delete();\r
+ sphereSource.Delete();\r
+ \r
+ return edgePointsActor;\r
+ }\r
+ \r
+ public static vtkActor createSilhouette(vtkRenderer ren, vtkPolyData data) {\r
+ \r
+ \r
+ vtkPolyDataSilhouette silhouette = new vtkPolyDataSilhouette();\r
+ \r
+ silhouette.SetInput(data);\r
+ silhouette.SetCamera(ren.GetActiveCamera());\r
+ silhouette.SetEnableFeatureAngle(0);\r
+ vtkPolyDataMapper mapper = new vtkPolyDataMapper();\r
+ \r
+ mapper.SetInputConnection(silhouette.GetOutputPort());\r
+ \r
+ vtkActor actor = new vtkActor();\r
+ actor.SetMapper(mapper);\r
+ \r
+ actor.GetProperty().SetColor(0,0,1);\r
+ actor.GetProperty().SetLineWidth(6);\r
+ \r
+ return actor;\r
+ \r
+ \r
+ \r
+ }\r
+\r
+}\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<classpath>\r
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>\r
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>\r
+ <classpathentry kind="src" path="src"/>\r
+ <classpathentry kind="output" path="bin"/>\r
+</classpath>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<projectDescription>\r
+ <name>org.simantics.opencascade</name>\r
+ <comment></comment>\r
+ <projects>\r
+ </projects>\r
+ <buildSpec>\r
+ <buildCommand>\r
+ <name>org.eclipse.jdt.core.javabuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ <buildCommand>\r
+ <name>org.eclipse.pde.ManifestBuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ <buildCommand>\r
+ <name>org.eclipse.pde.SchemaBuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ </buildSpec>\r
+ <natures>\r
+ <nature>org.eclipse.pde.PluginNature</nature>\r
+ <nature>org.eclipse.jdt.core.javanature</nature>\r
+ </natures>\r
+</projectDescription>\r
--- /dev/null
+#Mon Dec 12 17:21:52 EET 2011\r
+eclipse.preferences.version=1\r
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled\r
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6\r
+org.eclipse.jdt.core.compiler.compliance=1.6\r
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error\r
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error\r
+org.eclipse.jdt.core.compiler.source=1.6\r
--- /dev/null
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Opencascade
+Bundle-SymbolicName: org.simantics.opencascade
+Bundle-Version: 1.0.0.qualifier
+Bundle-Activator: org.simantics.opencascade.Activator
+Bundle-Vendor: VTT
+Require-Bundle: org.eclipse.core.runtime,
+ javax.vecmath;bundle-version="1.5.2",
+ org.jcae.opencascade;bundle-version="1.0.0",
+ org.simantics.utils.datastructures;bundle-version="1.1.0"
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Bundle-ActivationPolicy: lazy
+Export-Package: org.simantics.opencascade
--- /dev/null
+source.. = src/\r
+output.. = bin/\r
+bin.includes = META-INF/,\\r
+ .\r
--- /dev/null
+package org.simantics.opencascade;\r
+\r
+import org.osgi.framework.BundleActivator;\r
+import org.osgi.framework.BundleContext;\r
+\r
+public class Activator implements BundleActivator {\r
+\r
+ private static BundleContext context;\r
+\r
+ static BundleContext getContext() {\r
+ return context;\r
+ }\r
+\r
+ /*\r
+ * (non-Javadoc)\r
+ * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)\r
+ */\r
+ public void start(BundleContext bundleContext) throws Exception {\r
+ Activator.context = bundleContext;\r
+ }\r
+\r
+ /*\r
+ * (non-Javadoc)\r
+ * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)\r
+ */\r
+ public void stop(BundleContext bundleContext) throws Exception {\r
+ Activator.context = null;\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.opencascade;\r
+\r
+import java.util.List;\r
+\r
+import javax.vecmath.Matrix4d;\r
+import javax.vecmath.Point3d;\r
+\r
+import org.jcae.opencascade.jni.BRepBndLib;\r
+import org.jcae.opencascade.jni.BRepGProp;\r
+import org.jcae.opencascade.jni.BRep_Tool;\r
+import org.jcae.opencascade.jni.Bnd_Box;\r
+import org.jcae.opencascade.jni.GP_Trsf;\r
+import org.jcae.opencascade.jni.GProp_GProps;\r
+import org.jcae.opencascade.jni.GProp_VelGProps;\r
+import org.jcae.opencascade.jni.Poly_Triangulation;\r
+import org.jcae.opencascade.jni.TopAbs_Orientation;\r
+import org.jcae.opencascade.jni.TopLoc_Location;\r
+import org.jcae.opencascade.jni.TopoDS_Face;\r
+import org.jcae.opencascade.jni.TopoDS_Shape;\r
+\r
+public class OCCTTool {\r
+public static double getBoundingBoxDiagonal(TopoDS_Shape shape) {\r
+ \r
+ double []min = new double[3];\r
+ double []max = new double[3];\r
+ double []mmm = new double[3];\r
+ double []bb = new double[6];\r
+ \r
+ // Compute bounding box:\r
+ //----------------------\r
+ Bnd_Box boundingBox = new Bnd_Box();\r
+ BRepBndLib.add(shape, boundingBox);\r
+ boundingBox.get(bb);\r
+ boundingBox.delete();\r
+ \r
+ min[0] = bb[0]; min[1] = bb[1]; min[2] = bb[2];\r
+ max[0] = bb[3]; max[1] = bb[4]; max[2] = bb[5];\r
+\r
+ //System.out.println("Bounding box: "+"[ "+min[0]+", "+min[1]+", " + min[2] + "] x "+"[ " +max[0] +", " +max[1] +", " +max[2] +"]");\r
+\r
+ // The length of the space diagonal of cuboid\r
+ for (int i = 0; i < 3; i++) mmm[i] = max[i] - min[i];\r
+ double length = Math.sqrt(mmm[2]*mmm[2] + mmm[1]*mmm[1] + mmm[0]*mmm[0]);\r
+\r
+ double t0 = mmm[0]*mmm[0];\r
+ double t1 = mmm[1]*mmm[1];\r
+ double t2 = mmm[2]*mmm[2];\r
+\r
+ double tol = 1.0e-6 * length;\r
+\r
+ if((t0 < tol) || (t1 < tol) || (t2 < tol)) {\r
+ System.out.println("Shape seems to be 2D. Unable to proceed. Aborting.");\r
+ return 0;\r
+ }\r
+ return length;\r
+ }\r
+ \r
+ public static double getBoundingBoxVolume(TopoDS_Shape shape) {\r
+ \r
+ double []min = new double[3];\r
+ double []max = new double[3];\r
+ double []mmm = new double[3];\r
+ double []bb = new double[6];\r
+ \r
+ // Compute bounding box:\r
+ //----------------------\r
+ Bnd_Box boundingBox = new Bnd_Box();\r
+ BRepBndLib.add(shape, boundingBox);\r
+ boundingBox.get(bb);\r
+ boundingBox.delete();\r
+ \r
+ min[0] = bb[0]; min[1] = bb[1]; min[2] = bb[2];\r
+ max[0] = bb[3]; max[1] = bb[4]; max[2] = bb[5];\r
+\r
+ //System.out.println("Bounding box: "+"[ "+min[0]+", "+min[1]+", " + min[2] + "] x "+"[ " +max[0] +", " +max[1] +", " +max[2] +"]");\r
+\r
+ for (int i = 0; i < 3; i++) mmm[i] = max[i] - min[i];\r
+ double vol = Math.sqrt(mmm[2]*mmm[1]*mmm[0]);\r
+\r
+ return vol;\r
+ }\r
+ \r
+ private static GProp_GProps getGProp(TopoDS_Shape shape) {\r
+ GProp_GProps GSystem = null;\r
+ int type = 0;\r
+ if (type == 0) {\r
+ GSystem = new GProp_GProps();\r
+ BRepGProp.volumeProperties(shape, GSystem,0.001);\r
+ } else if (type == 1) {\r
+ GSystem = new GProp_VelGProps();\r
+ BRepGProp.volumeProperties(shape, GSystem,0.001);\r
+ } else if (type == 2) {\r
+ GSystem = new GProp_VelGProps();\r
+ BRepGProp.volumePropertiesGK(shape, GSystem, 0.001);\r
+ }\r
+ return GSystem;\r
+ }\r
+ \r
+ public static double getMass( TopoDS_Shape shape) {\r
+ \r
+ GProp_GProps GSystem = getGProp(shape);\r
+ \r
+ \r
+ double mass = GSystem.mass();\r
+ //System.out.println("Mass " + mass);\r
+ GSystem.delete();\r
+ return mass;\r
+ }\r
+ \r
+ public static double[] getInertia(TopoDS_Shape shape) {\r
+ GProp_GProps GSystem = getGProp(shape);\r
+ \r
+ double inertia[] = GSystem.matrixOfInertia();\r
+ GSystem.delete();\r
+ return inertia;\r
+ }\r
+ \r
+ public static double[] getCentreOfMass(TopoDS_Shape shape) {\r
+ GProp_GProps GSystem = getGProp(shape);\r
+ \r
+ double cm[] = GSystem.centreOfMass();\r
+ GSystem.delete();\r
+ return cm;\r
+ }\r
+ \r
+ public static boolean appendToMesh (TopoDS_Face face, List<Double> meshPoints, List<Integer> meshTriangles)\r
+ {\r
+ TopLoc_Location Location = new TopLoc_Location();\r
+ \r
+ Poly_Triangulation triangulation = BRep_Tool.triangulation(face, Location);\r
+\r
+ if(triangulation == null) {\r
+ Location.delete();\r
+ System.out.println("Encountered empty triangulation after face");\r
+ return false;\r
+ }\r
+ \r
+ boolean reverse = face.orientation()==TopAbs_Orientation.REVERSED;\r
+ \r
+ int lastPoint = meshPoints.size() / 3;\r
+\r
+ int[]triangles = triangulation.triangles();\r
+ double[]nodes = triangulation.nodes();\r
+\r
+ int nofTriangles = triangulation.nbTriangles();\r
+ int nofNodes = triangulation.nbNodes();\r
+ \r
+ \r
+ triangulation.delete();\r
+\r
+ if(nofTriangles < 1) {\r
+ System.out.println("No triangles for mesh on face");\r
+ Location.delete();\r
+ return false;\r
+ }\r
+\r
+ if(nofNodes < 1) {\r
+ System.out.println("No nodes for mesh on face:");\r
+ Location.delete();\r
+ return false;\r
+ }\r
+ \r
+ for(int i = 0; i < nofTriangles; i++) \r
+ {\r
+ int n0, n1, n2; \r
+ if (!reverse) {\r
+ n0 = triangles[3 * i]; \r
+ n1 = triangles[3 * i + 1]; \r
+ n2 = triangles[3 * i + 2];\r
+ } else {\r
+ n0 = triangles[3 * i + 2]; \r
+ n1 = triangles[3 * i + 1]; \r
+ n2 = triangles[3 * i];\r
+ }\r
+ \r
+ meshTriangles.add(n0 + lastPoint);\r
+ meshTriangles.add(n1 + lastPoint);\r
+ meshTriangles.add(n2 + lastPoint);\r
+ }\r
+\r
+ \r
+ GP_Trsf transformation = Location.transformation();\r
+ Location.delete();\r
+\r
+ double d_mat[] = new double[16];\r
+\r
+ transformation.getValues(d_mat);\r
+ Matrix4d mat = new Matrix4d(d_mat);\r
+ \r
+ \r
+ for(int i = 0; i < nofNodes; i++) { \r
+\r
+ Point3d p = new Point3d(nodes[3 * i], nodes[3 * i + 1], nodes[3 * i + 2]);\r
+ mat.transform(p);\r
+\r
+ meshPoints.add(p.x);\r
+ meshPoints.add(p.y);\r
+ meshPoints.add(p.z);\r
+ \r
+ }\r
+ \r
+ transformation.delete();\r
+ \r
+ return true;\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.opencascade;\r
+\r
+/*******************************************************************************\r
+ * Copyright (c) 2007- VTT Technical Research Centre of Finland.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+\r
+import javax.vecmath.Vector2d;\r
+\r
+import org.jcae.opencascade.jni.BRepBuilderAPI_MakeEdge;\r
+import org.jcae.opencascade.jni.BRepBuilderAPI_MakeFace;\r
+import org.jcae.opencascade.jni.BRepBuilderAPI_MakeWire;\r
+import org.jcae.opencascade.jni.BRepBuilderAPI_Transform;\r
+import org.jcae.opencascade.jni.BRepPrimAPI_MakePrism;\r
+import org.jcae.opencascade.jni.BRepPrimAPI_MakeTorus;\r
+import org.jcae.opencascade.jni.BRep_Builder;\r
+import org.jcae.opencascade.jni.GP_Elips;\r
+import org.jcae.opencascade.jni.GP_Trsf;\r
+import org.jcae.opencascade.jni.TopoDS_Edge;\r
+import org.jcae.opencascade.jni.TopoDS_Face;\r
+import org.jcae.opencascade.jni.TopoDS_Shape;\r
+import org.jcae.opencascade.jni.TopoDS_Wire;\r
+\r
+\r
+public class OccTriangulator {\r
+\r
+ \r
+ public static final double MIN_VALUE = 0.001;\r
+ \r
+ public OccTriangulator() {\r
+ \r
+ }\r
+\r
+\r
+ public static TopoDS_Shape getShapeFromFile(String filename) {\r
+ assert (filename != null);\r
+ String lowerFileName = filename.toLowerCase(); \r
+ if (lowerFileName.endsWith(".stp") || lowerFileName.endsWith(".step")) {\r
+ TopoDS_Shape shape = importSTEP(filename);\r
+ return shape;\r
+ } else if (lowerFileName.endsWith(".iges")) {\r
+ TopoDS_Shape shape = importIGES(filename);\r
+ return shape;\r
+ } else if (lowerFileName.endsWith(".brep")) {\r
+ TopoDS_Shape shape = importBREP(filename);\r
+ return shape;\r
+ } else {\r
+ throw new UnsupportedOperationException("Unsupported format " + filename);\r
+ }\r
+ }\r
+\r
+ public static TopoDS_Shape importBREP(String filename) {\r
+ return importBREP(filename,1.0); // convert to meters.\r
+ }\r
+ public static TopoDS_Shape importBREP(String filename, double scale) {\r
+ org.jcae.opencascade.jni.BRep_Builder aBuilder = new org.jcae.opencascade.jni.BRep_Builder();\r
+ org.jcae.opencascade.jni.TopoDS_Shape myShape = org.jcae.opencascade.jni.BRepTools.read(filename, aBuilder);\r
+ aBuilder.delete();\r
+ if (Math.abs(scale-1.0) < 0.001)\r
+ return myShape;\r
+ TopoDS_Shape scaled = makeScale(myShape, scale);\r
+ myShape.delete();\r
+ return scaled;\r
+ }\r
+\r
+ public static TopoDS_Shape importIGES(String filename) {\r
+ org.jcae.opencascade.jni.IGESControl_Reader aReader = new org.jcae.opencascade.jni.IGESControl_Reader();\r
+ aReader.setReadUnitM();\r
+ aReader.readFile(filename.getBytes());\r
+ aReader.clearShapes();\r
+ aReader.transferRoots();\r
+ TopoDS_Shape result = aReader.oneShape();\r
+ aReader.delete();\r
+ return result;\r
+ }\r
+ \r
+ public static TopoDS_Shape importSTEP(String filename) {\r
+ org.jcae.opencascade.jni.STEPControl_Reader aReader = new org.jcae.opencascade.jni.STEPControl_Reader();\r
+ aReader.setReadUnitM();\r
+ aReader.readFile(filename.getBytes());\r
+ aReader.clearShapes();\r
+ aReader.transferRoots();\r
+ TopoDS_Shape result = aReader.oneShape();\r
+ aReader.delete();\r
+ return result;\r
+ }\r
+\r
+\r
+\r
+ public static TopoDS_Shape makeTranslation(TopoDS_Shape aShape, double x, double y, double z) {\r
+ GP_Trsf theTransformation = new GP_Trsf();\r
+ theTransformation.setTranslation(new double[] { x, y, z });\r
+ BRepBuilderAPI_Transform bt = new BRepBuilderAPI_Transform(aShape, theTransformation, true);\r
+\r
+ TopoDS_Shape shape = bt.shape();\r
+ bt.delete();\r
+ theTransformation.delete();\r
+ return shape;\r
+ }\r
+\r
+ public static TopoDS_Shape makeTorus(double[] pointStruct, double[] dirStruct, double r1, double r2) {\r
+ double[] axe = new double[6];\r
+ System.arraycopy(pointStruct, 0, axe, 0, 3);\r
+ System.arraycopy(dirStruct, 0, axe, 3, 3);\r
+ BRepPrimAPI_MakeTorus torus = new BRepPrimAPI_MakeTorus(axe, r1, r2);\r
+ org.jcae.opencascade.jni.TopoDS_Shape tds = torus.shape();\r
+ torus.delete();\r
+ return tds;\r
+ }\r
+ \r
+ public static TopoDS_Shape makeTorus(double[] pointStruct, double[] dirStruct, double r1, double r2, double angle1, double angle2, double angle) {\r
+ double[] axe = new double[6];\r
+ System.arraycopy(pointStruct, 0, axe, 0, 3);\r
+ System.arraycopy(dirStruct, 0, axe, 3, 3);\r
+ BRepPrimAPI_MakeTorus torus = new BRepPrimAPI_MakeTorus(axe, r1, r2,angle1,angle2,angle);\r
+ org.jcae.opencascade.jni.TopoDS_Shape tds = torus.shape();\r
+ torus.delete();\r
+ return tds;\r
+ }\r
+\r
+ public static TopoDS_Shape makeSphere(double x, double y, double z, double radius) {\r
+ double[] c = new double[] { x, y, z };\r
+ org.jcae.opencascade.jni.BRepPrimAPI_MakeSphere sphere = new org.jcae.opencascade.jni.BRepPrimAPI_MakeSphere(c, radius);\r
+ org.jcae.opencascade.jni.TopoDS_Shape tds = sphere.shape();\r
+ sphere.delete();\r
+ return tds;\r
+ }\r
+\r
+\r
+ public static TopoDS_Shape makeRotation(TopoDS_Shape aShape, double[] axisStruct, double angle) {\r
+\r
+ GP_Trsf theTransformation = new GP_Trsf();\r
+ theTransformation.setRotation(axisStruct, angle);\r
+ BRepBuilderAPI_Transform bt = new BRepBuilderAPI_Transform(aShape, theTransformation, true);\r
+ TopoDS_Shape shape = bt.shape();\r
+ bt.delete();\r
+ theTransformation.delete();\r
+ return shape;\r
+ }\r
+\r
+ public static TopoDS_Shape makeScale(TopoDS_Shape aShape, double s) {\r
+\r
+ GP_Trsf theTransformation = new GP_Trsf();\r
+ theTransformation.setValues(s, 0, 0, 0,\r
+ 0, s, 0, 0, \r
+ 0, 0, s, 0, 1, 1);\r
+ BRepBuilderAPI_Transform bt = new BRepBuilderAPI_Transform(aShape, theTransformation, true);\r
+ TopoDS_Shape shape = bt.shape();\r
+ bt.delete();\r
+ theTransformation.delete();\r
+ return shape;\r
+ }\r
+\r
+\r
+ public static TopoDS_Shape makeCylinder(double[] pointStruct, double[] dirStruct, double radius, double height) {\r
+ double[] axe = new double[6];\r
+ System.arraycopy(pointStruct, 0, axe, 0, 3);\r
+ System.arraycopy(dirStruct, 0, axe, 3, 3);\r
+ org.jcae.opencascade.jni.BRepPrimAPI_MakeCylinder cyl = new org.jcae.opencascade.jni.BRepPrimAPI_MakeCylinder(axe, radius, height, 2 * Math.PI);\r
+ org.jcae.opencascade.jni.TopoDS_Shape tds = cyl.shape();\r
+ cyl.delete();\r
+ return tds;\r
+ }\r
+\r
+ public static TopoDS_Shape makeCopy(TopoDS_Shape topoDS_Shape) {\r
+ throw new UnsupportedOperationException();\r
+ }\r
+\r
+ public static TopoDS_Shape makeCone(double[] pointStruct, double[] dirStruct, double radius1, double radius2, double height) {\r
+ double[] axe = new double[6];\r
+ System.arraycopy(pointStruct, 0, axe, 0, 3);\r
+ System.arraycopy(dirStruct, 0, axe, 3, 3);\r
+ org.jcae.opencascade.jni.BRepPrimAPI_MakeCone cone = new org.jcae.opencascade.jni.BRepPrimAPI_MakeCone(axe, radius1, radius2, height, 2 * Math.PI);\r
+ org.jcae.opencascade.jni.TopoDS_Shape tds = cone.shape();\r
+ cone.delete();\r
+ return tds;\r
+ }\r
+\r
+ public static TopoDS_Shape makeCompound(TopoDS_Shape[] shapes) {\r
+ BRep_Builder builder = new BRep_Builder();\r
+ org.jcae.opencascade.jni.TopoDS_Compound comp = new org.jcae.opencascade.jni.TopoDS_Compound();\r
+ builder.makeCompound(comp);\r
+ for (int i = 0; i < shapes.length; i++) {\r
+\r
+ builder.add(comp, shapes[i]);\r
+ }\r
+ builder.delete();\r
+ return comp;\r
+ }\r
+\r
+\r
+ public static TopoDS_Shape makeBox(double x1, double y1, double z1, double x2, double y2, double z2) {\r
+ double[] p1 = new double[] { x1, y1, z1 };\r
+ double[] p2 = new double[] { x2, y2, z2 };\r
+ org.jcae.opencascade.jni.BRepPrimAPI_MakeBox box = new org.jcae.opencascade.jni.BRepPrimAPI_MakeBox(p1, p2); \r
+ org.jcae.opencascade.jni.TopoDS_Shape tds = box.shape();\r
+ box.delete();\r
+ return tds;\r
+ }\r
+\r
+ public static TopoDS_Shape makeCut(TopoDS_Shape shape1, TopoDS_Shape shape2) {\r
+ org.jcae.opencascade.jni.BRepAlgoAPI_Cut cut = new org.jcae.opencascade.jni.BRepAlgoAPI_Cut(shape1, shape2);\r
+ org.jcae.opencascade.jni.TopoDS_Shape s = cut.shape();\r
+ cut.delete();\r
+ return s;\r
+ }\r
+ \r
+ public static TopoDS_Shape makeCommon(TopoDS_Shape shape1, TopoDS_Shape shape2) {\r
+ org.jcae.opencascade.jni.BRepAlgoAPI_Common common = new org.jcae.opencascade.jni.BRepAlgoAPI_Common(shape1, shape2); \r
+ org.jcae.opencascade.jni.TopoDS_Shape s = common.shape();\r
+ common.delete();\r
+ return s;\r
+ }\r
+ \r
+ public static TopoDS_Shape makeFuse(TopoDS_Shape shape1, TopoDS_Shape shape2) {\r
+ org.jcae.opencascade.jni.BRepAlgoAPI_Fuse fuse = new org.jcae.opencascade.jni.BRepAlgoAPI_Fuse(shape1, shape2);\r
+ org.jcae.opencascade.jni.TopoDS_Shape s = fuse.shape();\r
+ fuse.delete();\r
+ return s;\r
+ }\r
+\r
+ \r
+ public static TopoDS_Shape makeWedge(double[] pointStruct, double[] dirStruct,double dx, double dy, double dz, double xmin, double zmin, double xmax, double zmax) {\r
+ double[] axe = new double[6];\r
+ System.arraycopy(pointStruct, 0, axe, 0, 3);\r
+ System.arraycopy(dirStruct, 0, axe, 3, 3);\r
+ \r
+ org.jcae.opencascade.jni.BRepPrimAPI_MakeWedge wedge = new org.jcae.opencascade.jni.BRepPrimAPI_MakeWedge(axe, dx, dy, dz, xmin, zmin, xmax, zmax); \r
+ org.jcae.opencascade.jni.TopoDS_Shape s = wedge.shape();\r
+ wedge.delete();\r
+ return s;\r
+ }\r
+ \r
+ public static TopoDS_Shape makeEllipticCylinder(double h, double r1, double r2) {\r
+ GP_Elips ellipse;\r
+ if (r1 < r2) {\r
+ // FIXME : ellipse should be rotated, but current JNI won't allow it since Ax2 is not separate object\r
+ ellipse = new GP_Elips(new double[]{0.0,-h*0.5,0.0,0.0,1.0,0.0},r2,r1);\r
+ } else {\r
+ ellipse = new GP_Elips(new double[]{0.0,-h*0.5,0.0,0.0,1.0,0.0},r1,r2);\r
+ }\r
+ BRepBuilderAPI_MakeEdge edge = new BRepBuilderAPI_MakeEdge(ellipse);\r
+ TopoDS_Edge ed = (TopoDS_Edge) edge.shape();\r
+ BRepBuilderAPI_MakeWire wire = new BRepBuilderAPI_MakeWire(ed);\r
+ TopoDS_Wire w = (TopoDS_Wire) wire.shape();\r
+ BRepBuilderAPI_MakeFace face = new BRepBuilderAPI_MakeFace(w); \r
+ TopoDS_Face F = (TopoDS_Face) face.shape();\r
+ BRepPrimAPI_MakePrism prism = new BRepPrimAPI_MakePrism(F, new double[] { 0.0, h, 0.0 }); \r
+ TopoDS_Shape shape = prism.shape();\r
+ ellipse.delete();\r
+ edge.delete();\r
+ wire.delete();\r
+ face.delete();\r
+ ed.delete();\r
+ w.delete();\r
+ F.delete();\r
+ prism.delete();\r
+ return shape;\r
+ }\r
+\r
+ public static TopoDS_Shape makeReqularPrism(double h, double r, int n) {\r
+ if (n < 3)\r
+ n = 3;\r
+ Vector2d vertices[] = new Vector2d[n];\r
+ for (int i = 0; i < n; i++) {\r
+ vertices[i] = new Vector2d(Math.sin(Math.PI * 2.0 * i / n)*r,Math.cos(Math.PI * 2.0 * i / n)*r);\r
+ }\r
+ BRepBuilderAPI_MakeWire wire = new BRepBuilderAPI_MakeWire();\r
+ for (int i = 0; i < n; i++) {\r
+ Vector2d v1 = vertices[i];\r
+ Vector2d v2 = vertices[(i+1)%n];\r
+ BRepBuilderAPI_MakeEdge edge = new BRepBuilderAPI_MakeEdge(new double[]{v1.x,-h*0.5,v1.y},new double[]{v2.x,-h*0.5,v2.y}); \r
+ wire.add((TopoDS_Edge)edge.shape());\r
+ edge.delete();\r
+ }\r
+ TopoDS_Wire w = (TopoDS_Wire)wire.shape();\r
+ \r
+ BRepBuilderAPI_MakeFace face = new BRepBuilderAPI_MakeFace(w);\r
+ TopoDS_Face F = (TopoDS_Face) face.shape();\r
+ face.delete();\r
+ \r
+ BRepPrimAPI_MakePrism prism = new BRepPrimAPI_MakePrism(F, new double[] { 0.0, h, 0.0 }); \r
+ TopoDS_Shape shape = prism.shape(); \r
+ prism.delete();\r
+ \r
+ wire.delete();\r
+ w.delete();\r
+ F.delete();\r
+ return shape;\r
+ }\r
+ \r
+\r
+ public static void exportBREP(TopoDS_Shape shape, String filename) {\r
+ org.jcae.opencascade.jni.BRepTools.write(shape, filename);\r
+ }\r
+ \r
+}\r
--- /dev/null
+package org.simantics.opencascade;\r
+\r
+import java.util.Map;\r
+\r
+public interface ParametricSolidModelProvider extends SolidModelProvider{\r
+ \r
+ public void setProperties(Map<String,Object> props);\r
+ \r
+ public void updateCalculatedProperties(Map<String,Object> returnProps);\r
+\r
+}\r
--- /dev/null
+package org.simantics.opencascade;\r
+\r
+import java.util.Collection;\r
+\r
+import org.jcae.opencascade.jni.TopoDS_Shape;\r
+\r
+public interface SolidModelProvider {\r
+\r
+ \r
+ public Collection<TopoDS_Shape> getModel() throws Exception;\r
+}\r