1 /*******************************************************************************
\r
2 * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.
\r
3 * All rights reserved. This program and the accompanying materials
\r
4 * are made available under the terms of the Eclipse Public License v1.0
\r
5 * which accompanies this distribution, and is available at
\r
6 * http://www.eclipse.org/legal/epl-v10.html
\r
9 * VTT Technical Research Centre of Finland - initial API and implementation
\r
10 *******************************************************************************/
\r
11 package org.simantics.proconf.g3d.scenegraph;
\r
13 import java.util.ArrayList;
\r
14 import java.util.Collection;
\r
15 import java.util.Iterator;
\r
16 import java.util.List;
\r
18 import org.simantics.db.Builtins;
\r
19 import org.simantics.db.ContextGraph;
\r
20 import org.simantics.db.Graph;
\r
21 import org.simantics.db.Resource;
\r
22 import org.simantics.equation.solver.Solver;
\r
23 import org.simantics.animation.stubs.Animation;
\r
24 import org.simantics.layer0.utils.Property;
\r
25 import org.simantics.layer0.utils.IEntity;
\r
26 import org.simantics.layer0.utils.EntityFactory;
\r
27 import org.simantics.layer0.utils.Statement;
\r
28 import org.simantics.proconf.g3d.Resources;
\r
29 import org.simantics.proconf.g3d.base.ThreeDimensionalEditorBase;
\r
30 import org.simantics.proconf.g3d.stubs.G3DModel;
\r
31 import org.simantics.proconf.g3d.stubs.G3DNode;
\r
32 import org.simantics.utils.ui.ErrorLogger;
\r
35 * IGraphicsNode for parameterized models. Implementation assumes that G3DNode itself does not contain
\r
36 * graphical representation but has link to it.
\r
38 * @author Marko Luukkainen
\r
41 public class ParameterizedModelNode extends ModelNode {
\r
47 * @param resource this node (G3DNode).
\r
48 * @param nodeToModelRelation relation from this node to the model, or from type of this node to the model.
\r
49 * @param modelToParametersRelation relation from the model to its sizing parameters
\r
51 public ParameterizedModelNode(ThreeDimensionalEditorBase editor, IGraphicsNode parent, Graph graph, Resource resource, Resource nodeToModelRelation) {
\r
52 super(editor,parent,graph,resource);
\r
53 G3DNode shape = getG3DNode(graph);
\r
54 List<IEntity> models = new ArrayList<IEntity>();
\r
55 models.addAll(shape.getRelatedObjects(nodeToModelRelation));
\r
56 if (models.size() == 0) {
\r
57 Collection<IEntity> types = shape.getTypes();
\r
58 for (IEntity type : types) {
\r
59 models.addAll(type.getRelatedObjects(nodeToModelRelation));
\r
62 if (models.size() != 1)
\r
63 throw new IllegalArgumentException("Cannot find proper model: found " + models.size() + " models.");
\r
65 this.modelResource = models.iterator().next().getResource();
\r
69 protected void createGeometry(Graph graph) {
\r
70 super.createGeometry(createParameterization(graph));
\r
74 public void updateGeometry(Graph graph) {
\r
75 super.updateGeometry(createParameterization(graph));
\r
78 private void updateSizeParameters(ContextGraph graph, Solver solver) {
\r
79 Builtins builtins = graph.getBuiltins();
\r
82 G3DNode node = getG3DNode(graph);
\r
83 //Collection<Property> nodeProperties = node.getRelatedProperties(builtins.HasProperty);
\r
84 Collection<Statement> nodeProperties = node.getRelatedStatements(builtins.HasProperty);
\r
85 G3DModel model = getG3DModel(graph);
\r
86 Collection<Property> modelProperties = model.getRelatedProperties(Resources.g3dResource.HasSizingParameter);
\r
88 // there are no relations between then nodes properties and the model's sizing parameters
\r
89 // link between them is done by matching names
\r
90 for (Property m : modelProperties) {
\r
91 boolean set = false;
\r
92 //if(m.canBeSet(builtins.HasName)) {
\r
94 String modelPropertyname = m.getAtMostOneRelatedProperty(builtins.HasName).getScalarString();
\r
95 for (Statement n : nodeProperties) {
\r
96 String relationName = n.getPredicate().getName();
\r
97 if (relationName.startsWith("Has "))
\r
98 relationName = relationName.substring(4);
\r
99 if (relationName.equalsIgnoreCase(modelPropertyname)) {
\r
101 // set property's value for Solver
\r
102 solver.setValue(m.getResource(), graph.getValueAsObject(n.getObject().getResource()));
\r
109 ErrorLogger.defaultLogError("Cannot map property " + modelPropertyname, null);
\r
115 for (Property p : modelProperties) {
\r
116 IEntity t = EntityFactory.create(graph, p.getResource());
\r
117 Collection<IEntity> exp = t.getRelatedObjects(Resources.equationResource.HasTarget);
\r
118 if (exp.size() > 0) {
\r
119 Iterator<IEntity> i = exp.iterator();
\r
121 solver.evaluate(i.next());
\r
123 ErrorLogger.defaultLogError("Model property " + p + " is not bound to a expression",null);
\r
125 solver.pushToGraph(graph);
\r
126 Collection<Animation> animations = model.getAnimation();
\r
127 for (Animation animation : animations) {
\r
128 Collection<org.simantics.animation.stubs.Interpolator> interpolators = animation.getInterpolator();
\r
129 for (org.simantics.animation.stubs.Interpolator interpolator : interpolators) {
\r
130 IEntity target = interpolator.getTarget();
\r
131 // check all model properties
\r
132 for (Property p : modelProperties) {
\r
133 IEntity t = EntityFactory.create(graph,p.getResource());
\r
134 // get parameterization equations
\r
135 Collection<IEntity> equations = t.getRelatedObjects(Resources.equationResource.HasTarget);
\r
136 // get parameterized values
\r
137 Collection<IEntity> parameterTargets = new ArrayList<IEntity>();
\r
138 for (IEntity eq : equations) {
\r
139 Collection<IEntity> tgts = eq.getRelatedObjects(Resources.equationResource.HasTarget);
\r
140 assert(tgts.size() == 1);
\r
141 parameterTargets.add(tgts.iterator().next());
\r
143 // do matching between interpolator targets and parameterized values
\r
144 // TODO : old system did not have inverse relations but current system does.
\r
145 // it is possible to take interpolation target and find if it is connected to an equation
\r
146 // this would make code much faster (no more stupid loops over everything)
\r
147 for (IEntity d : parameterTargets) {
\r
148 if (d.getResource().equals(target.getResource())) {
\r
149 // get default value for sizing property
\r
150 Collection<IEntity> prop = t.getRelatedObjects(Resources.g3dResource.HasDefaultDoubleValue);
\r
151 if (prop.size() == 1) {
\r
152 Resources.curveBuilder.parameterize(interpolator, prop.iterator().next().toProperty().getDoubleArray(), p.getDoubleArray());
\r
154 ErrorLogger.defaultLogError("Cannot parameterize interpolator " + interpolator.getResource() + " of animation " + animation.getResource() + " since parameter " + p.getResource() + " has no default value", null);
\r
164 protected Graph createParameterization(Graph graph) {
\r
165 // create ContextGraph if needed
\r
167 if (!(graph instanceof ContextGraph))
\r
168 g = new ContextGraph(graph);
\r
170 g = (ContextGraph)graph;
\r
172 g.setContext(this.shapeResource);
\r
173 // create solver and calculate parameterized values
\r
174 Solver solver = new Solver();
\r
175 updateSizeParameters(g, solver);
\r
176 // push parameterized values to context
\r
177 solver.pushToGraph(g);
\r
178 // return graph with parameterized values
\r
183 public boolean setAnimation(Graph graph, Resource animation) {
\r
184 return super.setAnimation(createParameterization(graph), animation);
\r