/******************************************************************************* * Copyright (c) 2012, 2013 Association for Decentralized Information Management in * Industry THTH ry. * 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.g3d.vtk.shape; import javax.vecmath.AxisAngle4d; import javax.vecmath.Matrix4d; import javax.vecmath.Point3d; import javax.vecmath.Vector3d; import org.simantics.g3d.math.MathTools; import org.simantics.utils.threads.AWTThread; import org.simantics.utils.threads.ThreadUtils; import vtk.vtkActor; import vtk.vtkAssembly; import vtk.vtkConeSource; import vtk.vtkLineSource; import vtk.vtkLinearTransform; import vtk.vtkMatrix4x4; import vtk.vtkPolyDataMapper; import vtk.vtkProp3D; import vtk.vtkRenderer; import vtk.vtkTextActor; import vtk.vtkTubeFilter; public class DualHeadArrowActor extends vtkAssembly implements IvtkVisualObject{ private vtkRenderer ren; private Vector3d axisDir = new Vector3d(1,0,0); private vtkTextActor tactor; private vtkActor tubeActor; private vtkActor coneActor; private vtkActor coneActor2; private boolean rendered = false; public DualHeadArrowActor(vtkRenderer _ren, String label) { super(); ren = _ren; createAxis(label); } public DualHeadArrowActor(vtkRenderer _ren, String label, Vector3d dir) { super(); ren = _ren; this.axisDir = dir; if (dir.lengthSquared() < MathTools.NEAR_ZERO) throw new IllegalArgumentException("Direction vector length must mer larger than zero"); createAxis(label); } public void createAxis(String label) { double coneScale = 0.3 * axisDir.length(); Vector3d coneOffset = new Vector3d(axisDir); coneOffset.normalize(); coneOffset.scale(coneScale*0.5); vtkLineSource line = new vtkLineSource(); //line.SetPoint1(0.0,0.0,0.0); line.SetPoint1(coneOffset.x,coneOffset.y,coneOffset.z); line.SetPoint2(axisDir.x-coneOffset.x,axisDir.y-coneOffset.y,axisDir.z-coneOffset.z); tactor = new vtkTextActor(); tactor.SetInput(label); tactor.SetTextScaleModeToNone(); tactor.GetTextProperty().SetColor(0.0, 0.0, 0.0); tactor.GetTextProperty().ShadowOff(); tactor.GetTextProperty().ItalicOff(); tactor.GetTextProperty().BoldOff(); tactor.GetTextProperty().Delete(); tactor.SetMaximumLineHeight(0.25); tactor.SetPickable(0); vtkTubeFilter tube = new vtkTubeFilter(); tube.SetInput(line.GetOutput()); tube.SetRadius(0.05 * axisDir.length()); tube.SetNumberOfSides(8); vtkPolyDataMapper tubeMapper = new vtkPolyDataMapper(); tubeMapper.SetInput(tube.GetOutput()); tubeActor = new vtkActor(); tubeActor.SetMapper(tubeMapper); tubeActor.PickableOff(); int coneRes = 12; // --- x-Cone vtkConeSource cone = new vtkConeSource(); cone.SetResolution(coneRes); vtkPolyDataMapper coneMapper = new vtkPolyDataMapper(); coneMapper.SetInput(cone.GetOutput()); coneActor = new vtkActor(); coneActor.SetMapper(coneMapper); coneActor.GetProperty().SetColor(1, 0, 0); coneActor.SetScale(coneScale, coneScale, coneScale); coneActor.SetPosition(axisDir.x-coneOffset.x,axisDir.y-coneOffset.y,axisDir.z-coneOffset.z); coneActor.SetPickable(0); AxisAngle4d aa = MathTools.createRotation(new Vector3d(1,0,0), axisDir); if (aa != null) coneActor.RotateWXYZ(MathTools.radToDeg(aa.angle), aa.x, aa.y, aa.z); coneActor2 = new vtkActor(); coneActor2.SetMapper(coneMapper); coneActor2.GetProperty().SetColor(1, 0, 0); coneActor2.SetScale(coneScale, coneScale, coneScale); coneActor2.SetPosition(coneOffset.x,coneOffset.y,coneOffset.z); coneActor2.SetPickable(0); aa = MathTools.createRotation(new Vector3d(-1,0,0), axisDir); if (aa != null) coneActor2.RotateWXYZ(MathTools.radToDeg(aa.angle), aa.x, aa.y, aa.z); this.AddPart(tubeActor); this.AddPart(coneActor); this.AddPart(coneActor2); tube.GetOutput().Delete(); cone.GetOutput().Delete(); line.GetOutput().Delete(); tubeMapper.Delete(); tube.Delete(); cone.Delete(); line.Delete(); coneMapper.Delete(); coneActor.GetProperty().Delete(); coneActor2.GetProperty().Delete(); } public void addToRenderer() { if (rendered) return; rendered = true; ren.AddActor2D(tactor); ren.AddActor(this); } public void removeFromRenderer() { if (!rendered) return; rendered = false; ren.RemoveActor2D(tactor); ren.RemoveActor(this); } public boolean isRendered() { return rendered; } public void setAxesVisibility(boolean ison) { this.SetVisibility(ison ? 1 : 0); tactor.SetVisibility(ison ? 1 : 0); } public void setLabelVisibility(boolean ison) { tactor.SetVisibility(ison ? 1 : 0); } double mat[] = new double[16]; Matrix4d m = new Matrix4d(); private void updateTextLoc() { tactor.GetPositionCoordinate().SetCoordinateSystemToWorld(); GetMatrix(mat); MathTools.set(m,mat); Point3d p = new Point3d(axisDir.x*0.5, axisDir.y*0.5,axisDir.z*0.5); m.transform(p); tactor.GetPositionCoordinate().SetValue(p.x, p.y, p.z); tactor.GetPositionCoordinate().Delete(); } @Override public void SetPickable(int id0) { super.SetPickable(id0); tubeActor.SetPickable(id0); coneActor.SetPickable(id0); coneActor2.SetPickable(id0); } @Override public void SetOrientation(double id0, double id1, double id2) { super.SetOrientation(id0, id1, id2); updateTextLoc(); } @Override public void RotateWXYZ(double id0, double id1, double id2, double id3) { super.RotateWXYZ(id0, id1, id2, id3); updateTextLoc(); } @Override public void SetPosition(double[] id0) { super.SetPosition(id0); updateTextLoc(); } @Override public void SetPosition(double id0, double id1, double id2) { super.SetPosition(id0, id1, id2); updateTextLoc(); } @Override public void SetOrientation(double[] id0) { super.SetOrientation(id0); updateTextLoc(); } @Override public void SetScale(double id0) { super.SetScale(id0); updateTextLoc(); } @Override public void SetScale(double id0, double id1, double id2) { super.SetScale(id0, id1, id2); updateTextLoc(); } @Override public void SetScale(double[] id0) { super.SetScale(id0); updateTextLoc(); } public void SetColor(double r, double g, double b) { coneActor.GetProperty().SetColor(r, g, b); coneActor2.GetProperty().SetColor(r, g, b); tubeActor.GetProperty().SetColor(r, g, b); coneActor.GetProperty().Delete(); coneActor2.GetProperty().Delete(); tubeActor.GetProperty().Delete(); } public void SetTextColor(double r, double g, double b) { tactor.GetTextProperty().SetColor(r, g, b); tactor.GetTextProperty().Delete(); } @Override public void SetUserMatrix(vtkMatrix4x4 id0) { super.SetUserMatrix(id0); updateTextLoc(); } @Override public void SetUserTransform(vtkLinearTransform id0) { super.SetUserTransform(id0); updateTextLoc(); } @Override public void Delete() { ren.RemoveActor(tactor); ren.RemoveActor(tubeActor); ren.RemoveActor(coneActor); ren.RemoveActor(coneActor2); tactor.Delete(); tubeActor.Delete(); coneActor.Delete(); coneActor2.Delete(); super.Delete(); } public void dispose() { ThreadUtils.asyncExec(AWTThread.getThreadAccess(), new Runnable() { @Override public void run() { removeFromRenderer(); Delete(); } }); } @Override public vtkProp3D getVtkProp() { return this; } }