--- /dev/null
+package org.simantics.plant3d.scenegraph;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.jcae.opencascade.jni.TopoDS_Shape;
+import org.simantics.g3d.math.MathTools;
+import org.simantics.g3d.scenegraph.NodeHighlighter;
+import org.simantics.g3d.vtk.utils.vtkUtil;
+import org.simantics.objmap.graph.annotations.RelatedGetObj;
+import org.simantics.objmap.graph.annotations.RelatedSetObj;
+import org.simantics.opencascade.OccTriangulator;
+import org.simantics.opencascade.ParametricSolidModelProvider;
+import org.simantics.opencascade.SolidModelProvider;
+import org.simantics.opencascade.vtk.vtkSolidObject;
+import org.simantics.plant3d.ontology.Plant3D;
+
+import vtk.vtkActor;
+import vtk.vtkPanel;
+import vtk.vtkProp3D;
+import vtk.vtkProperty;
+import vtk.vtkRenderer;
+
+public abstract class GeometryNode extends P3DNode implements ParameterizedNode, NodeHighlighter {
+
+ private TopoDS_Shape solidModel;
+ private vtkSolidObject solidObject;
+
+ private Map<String,Object> currentParameters;
+ private Map<String,Object> calculatedParameters;
+
+ private boolean parametersUpdated = true;
+
+ public GeometryNode() {
+ currentParameters = new HashMap<String, Object>();
+ calculatedParameters = new HashMap<String, Object>();
+ }
+
+ @Override
+ public void visualize(vtkPanel panel) {
+ if (solidModelProvider != null) {
+
+ updateParameters();
+ if (solidModel == null || parametersUpdated) {
+ createGeometry();
+ }
+ }
+ if ((solidObject == null || parametersUpdated) && solidModel != null) {
+ solidObject = new vtkSolidObject(panel, solidModel);
+ }
+ if (solidObject != null) {
+ solidObject.visualizeSolid(true,true, false,false);
+ updateVisuals(true, true);
+ }
+ parametersUpdated = false;
+
+ }
+
+ public void updateParameters() {
+ if (solidModelProvider instanceof ParametricSolidModelProvider) {
+ ((ParametricSolidModelProvider)solidModelProvider).setProperties(currentParameters);
+ ((ParametricSolidModelProvider)solidModelProvider).updateCalculatedProperties(calculatedParameters);
+ }
+ }
+
+ private void createGeometry() {
+ Collection<TopoDS_Shape> shapes;
+ try {
+ shapes = solidModelProvider.getModel();
+ if (shapes.size() == 1) {
+ solidModel = shapes.iterator().next();
+ } else {
+ solidModel = OccTriangulator.makeCompound(shapes.toArray(new TopoDS_Shape[shapes.size()]));
+ for (TopoDS_Shape shape : shapes) {
+ shape.delete();
+ }
+ }
+// shapes.clear();
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ public Map<String, Object> getParameterMap() {
+ return Collections.unmodifiableMap(currentParameters);
+ }
+
+ public Map<String, Object> getCalculatedParameters() {
+ return calculatedParameters;
+ }
+
+ public void setParametersUpdated(boolean parametersUpdated) {
+ this.parametersUpdated = parametersUpdated;
+ }
+
+ public void setParameterMap(Map<String, Object> parameters) {
+ for (String id : parameters.keySet()) {
+ Object currentValue = currentParameters.get(id);
+ Object newValue = parameters.get(id);
+ if (currentValue == newValue)
+ continue;
+ if (currentValue instanceof Double) {
+ if (Math.abs((Double)currentValue-(Double)newValue) < MathTools.NEAR_ZERO)
+ continue;
+ }
+ currentParameters.put(id, newValue);
+ parametersUpdated = true;
+ firePropertyChanged(id);
+ }
+ }
+
+ private SolidModelProvider solidModelProvider;
+
+ @RelatedGetObj(Plant3D.URIs.hasGeometry)
+ public SolidModelProvider getGeometry() {
+ return solidModelProvider;
+ }
+
+ @RelatedSetObj(Plant3D.URIs.hasGeometry)
+ public void setGeometry(final SolidModelProvider provider) {
+ if (provider != null && provider.equals(solidModelProvider))
+ return;
+
+ if (solidModelProvider != null) {
+ deleteData();
+ }
+ solidModelProvider = provider;
+ firePropertyChanged(Plant3D.URIs.hasGeometry);
+ }
+
+ private void deleteData() {
+ solidModelProvider = null;
+ if (solidObject != null) {
+ solidObject.clearActors();
+ solidObject = null;
+ }
+ if (solidModel != null) {
+ solidModel.delete();
+ solidModel = null;
+ }
+ }
+
+ @Override
+ public Collection<vtkProp3D> getActors() {
+ List<vtkProp3D> list = new ArrayList<vtkProp3D>();
+ if (solidObject != null)
+ list.addAll(solidObject.getActors());
+ return list;
+ }
+
+ @Override
+ public void stopVisualize() {
+ if (solidObject != null) {
+ solidObject.clearActorsAWT();
+ solidObject = null;
+ }
+ if (solidModel != null) {
+ solidModel.delete();
+ solidModel = null;
+ }
+
+ }
+
+ private boolean selected = false;
+ private boolean hover = false;
+
+ @Override
+ public void highlight(HighlightEventType type) {
+ if (type == HighlightEventType.Selection || type == HighlightEventType.ClearSelection) {
+ selected = type == HighlightEventType.Selection;
+// hingeA.visualizeSolid(selected,true,false);
+// hingeB.visualizeSolid(selected,true,false);
+ updateVisuals(true, false);
+// update(null);
+ } else {
+ hover = type == HighlightEventType.Hover;
+ updateVisuals(false, true);
+ }
+
+
+ }
+
+ protected double[] getSelectedColor() {
+ return new double[]{1,0,0};
+ }
+
+ protected double[] getColor() {
+ return new double[]{1,1,0};
+ }
+
+ private void updateVisuals(boolean s, boolean h) {
+ if (solidObject != null) {
+ if (s) {
+ double color[];
+ if (selected) {
+ color = getSelectedColor();
+
+ } else {
+ color = getColor();
+
+ }
+ for (vtkProp3D prop : solidObject.getSolid()) {
+ vtkProperty property = ((vtkActor)prop).GetProperty();
+ property.SetColor(color);
+ property.Delete();
+ }
+ }
+ if (h) {
+ double color[] = new double[]{0,0,0};
+ if (hover)
+ color = new double[]{1,0,1};
+ for (vtkProp3D prop : solidObject.getEdges()) {
+ vtkProperty property = ((vtkActor)prop).GetProperty();
+ property.SetColor(color);
+ property.Delete();
+ }
+
+ }
+ } else {
+// if (s) {
+// axes.addToRenderer();
+// axes.setAxesVisibility(selected);
+// }
+ }
+ }
+
+ public void update(vtkRenderer ren) {
+ vtkUtil.updateTransform(getActors(), getWorldPosition(), getWorldOrientation());
+ }
+
+ public TopoDS_Shape getSolidModel() {
+ return solidModel;
+ }
+}