--- /dev/null
+/*******************************************************************************\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
+package org.simantics.proconf.g3d.scenegraph;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.Iterator;\r
+import java.util.List;\r
+\r
+import org.simantics.db.Builtins;\r
+import org.simantics.db.ContextGraph;\r
+import org.simantics.db.Graph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.equation.solver.Solver;\r
+import org.simantics.animation.stubs.Animation;\r
+import org.simantics.layer0.utils.Property;\r
+import org.simantics.layer0.utils.IEntity;\r
+import org.simantics.layer0.utils.EntityFactory;\r
+import org.simantics.layer0.utils.Statement;\r
+import org.simantics.proconf.g3d.Resources;\r
+import org.simantics.proconf.g3d.base.ThreeDimensionalEditorBase;\r
+import org.simantics.proconf.g3d.stubs.G3DModel;\r
+import org.simantics.proconf.g3d.stubs.G3DNode;\r
+import org.simantics.utils.ui.ErrorLogger;\r
+\r
+/**\r
+ * IGraphicsNode for parameterized models. Implementation assumes that G3DNode itself does not contain\r
+ * graphical representation but has link to it. \r
+ * \r
+ * @author Marko Luukkainen\r
+ *\r
+ */\r
+public class ParameterizedModelNode extends ModelNode {\r
+ \r
+ /**\r
+ * @param editor\r
+ * @param parent\r
+ * @param graph\r
+ * @param resource this node (G3DNode).\r
+ * @param nodeToModelRelation relation from this node to the model, or from type of this node to the model.\r
+ * @param modelToParametersRelation relation from the model to its sizing parameters\r
+ */\r
+ public ParameterizedModelNode(ThreeDimensionalEditorBase editor, IGraphicsNode parent, Graph graph, Resource resource, Resource nodeToModelRelation) {\r
+ super(editor,parent,graph,resource);\r
+ G3DNode shape = getG3DNode(graph);\r
+ List<IEntity> models = new ArrayList<IEntity>();\r
+ models.addAll(shape.getRelatedObjects(nodeToModelRelation));\r
+ if (models.size() == 0) {\r
+ Collection<IEntity> types = shape.getTypes();\r
+ for (IEntity type : types) {\r
+ models.addAll(type.getRelatedObjects(nodeToModelRelation));\r
+ }\r
+ }\r
+ if (models.size() != 1)\r
+ throw new IllegalArgumentException("Cannot find proper model: found " + models.size() + " models.");\r
+ \r
+ this.modelResource = models.iterator().next().getResource();\r
+ }\r
+ \r
+ @Override\r
+ protected void createGeometry(Graph graph) {\r
+ super.createGeometry(createParameterization(graph));\r
+ }\r
+ \r
+ @Override\r
+ public void updateGeometry(Graph graph) { \r
+ super.updateGeometry(createParameterization(graph));\r
+ }\r
+ \r
+ private void updateSizeParameters(ContextGraph graph, Solver solver) {\r
+ Builtins builtins = graph.getBuiltins();\r
+\r
+ \r
+ G3DNode node = getG3DNode(graph);\r
+ //Collection<Property> nodeProperties = node.getRelatedProperties(builtins.HasProperty);\r
+ Collection<Statement> nodeProperties = node.getRelatedStatements(builtins.HasProperty);\r
+ G3DModel model = getG3DModel(graph);\r
+ Collection<Property> modelProperties = model.getRelatedProperties(Resources.g3dResource.HasSizingParameter);\r
+ \r
+ // there are no relations between then nodes properties and the model's sizing parameters\r
+ // link between them is done by matching names\r
+ for (Property m : modelProperties) {\r
+ boolean set = false;\r
+ //if(m.canBeSet(builtins.HasName)) {\r
+\r
+ String modelPropertyname = m.getAtMostOneRelatedProperty(builtins.HasName).getScalarString();\r
+ for (Statement n : nodeProperties) {\r
+ String relationName = n.getPredicate().getName();\r
+ if (relationName.startsWith("Has "))\r
+ relationName = relationName.substring(4);\r
+ if (relationName.equalsIgnoreCase(modelPropertyname)) {\r
+ // found a match\r
+ // set property's value for Solver\r
+ solver.setValue(m.getResource(), graph.getValueAsObject(n.getObject().getResource()));\r
+ set = true;\r
+ break;\r
+ }\r
+ \r
+ }\r
+ if (!set) {\r
+ ErrorLogger.defaultLogError("Cannot map property " + modelPropertyname, null);\r
+ }\r
+ //}\r
+ \r
+ }\r
+ \r
+ for (Property p : modelProperties) {\r
+ IEntity t = EntityFactory.create(graph, p.getResource());\r
+ Collection<IEntity> exp = t.getRelatedObjects(Resources.equationResource.HasTarget);\r
+ if (exp.size() > 0) { \r
+ Iterator<IEntity> i = exp.iterator();\r
+ while(i.hasNext())\r
+ solver.evaluate(i.next());\r
+ } else\r
+ ErrorLogger.defaultLogError("Model property " + p + " is not bound to a expression",null);\r
+ }\r
+ solver.pushToGraph(graph);\r
+ Collection<Animation> animations = model.getAnimation();\r
+ for (Animation animation : animations) {\r
+ Collection<org.simantics.animation.stubs.Interpolator> interpolators = animation.getInterpolator();\r
+ for (org.simantics.animation.stubs.Interpolator interpolator : interpolators) {\r
+ IEntity target = interpolator.getTarget();\r
+ // check all model properties\r
+ for (Property p : modelProperties) {\r
+ IEntity t = EntityFactory.create(graph,p.getResource());\r
+ // get parameterization equations\r
+ Collection<IEntity> equations = t.getRelatedObjects(Resources.equationResource.HasTarget);\r
+ // get parameterized values\r
+ Collection<IEntity> parameterTargets = new ArrayList<IEntity>();\r
+ for (IEntity eq : equations) {\r
+ Collection<IEntity> tgts = eq.getRelatedObjects(Resources.equationResource.HasTarget);\r
+ assert(tgts.size() == 1);\r
+ parameterTargets.add(tgts.iterator().next());\r
+ }\r
+ // do matching between interpolator targets and parameterized values\r
+ // TODO : old system did not have inverse relations but current system does.\r
+ // it is possible to take interpolation target and find if it is connected to an equation\r
+ // this would make code much faster (no more stupid loops over everything)\r
+ for (IEntity d : parameterTargets) {\r
+ if (d.getResource().equals(target.getResource())) {\r
+ // get default value for sizing property\r
+ Collection<IEntity> prop = t.getRelatedObjects(Resources.g3dResource.HasDefaultDoubleValue);\r
+ if (prop.size() == 1) {\r
+ Resources.curveBuilder.parameterize(interpolator, prop.iterator().next().toProperty().getDoubleArray(), p.getDoubleArray());\r
+ } else {\r
+ ErrorLogger.defaultLogError("Cannot parameterize interpolator " + interpolator.getResource() + " of animation " + animation.getResource() + " since parameter " + p.getResource() + " has no default value", null);\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ \r
+ }\r
+ \r
+ protected Graph createParameterization(Graph graph) {\r
+ // create ContextGraph if needed\r
+ ContextGraph g;\r
+ if (!(graph instanceof ContextGraph))\r
+ g = new ContextGraph(graph);\r
+ else\r
+ g = (ContextGraph)graph;\r
+ // set the context\r
+ g.setContext(this.shapeResource);\r
+ // create solver and calculate parameterized values\r
+ Solver solver = new Solver();\r
+ updateSizeParameters(g, solver);\r
+ // push parameterized values to context\r
+ solver.pushToGraph(g);\r
+ // return graph with parameterized values\r
+ return g;\r
+ }\r
+ \r
+ @Override\r
+ public boolean setAnimation(Graph graph, Resource animation) { \r
+ return super.setAnimation(createParameterization(graph), animation);\r
+ }\r
+ \r
+ \r
+}\r