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