1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251
|
package vtk.sample;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import vtk.vtkActor;
import vtk.vtkDataSetMapper;
import vtk.vtkNativeLibrary;
import vtk.vtkObject;
import vtk.vtkPanel;
import vtk.vtkReferenceInformation;
import vtk.vtkRenderer;
import vtk.vtkShrinkFilter;
import vtk.vtkSphereSource;
/**
* This application run concurrently thread that create VTK objects and the EDT
* that collect those objects and render them.
*
* @author sebastien jourdain - sebastien.jourdain@kitware.com
*/
public class Demo extends JPanel {
private static final long serialVersionUID = 1L;
private vtkPanel panel3d;
private JCheckBox runGC;
private JCheckBox debugMode;
private JLabel gcStatus;
private int NUMBER_OF_PIPLINE_TO_BUILD = 120;
private int nbSeconds;
private final CompletionService<vtkActor> exec;
// -----------------------------------------------------------------
// Load VTK library and print which library was not properly loaded
static {
if (!vtkNativeLibrary.LoadAllNativeLibraries()) {
for (vtkNativeLibrary lib : vtkNativeLibrary.values()) {
if (!lib.IsLoaded()) {
System.out.println(lib.GetLibraryName() + " not loaded");
}
}
}
vtkNativeLibrary.DisableOutputWindow(null);
}
// -----------------------------------------------------------------
public static class AddActorRunnable implements Runnable {
private vtkActor actorToAdd;
private vtkRenderer renderer;
private vtkPanel panel;
void setRenderer(vtkPanel panel) {
this.renderer = panel.GetRenderer();
this.panel = panel;
}
void setActor(vtkActor a) {
this.actorToAdd = a;
}
public void run() {
this.renderer.AddActor(this.actorToAdd);
this.panel.Render();
}
}
// -----------------------------------------------------------------
public static class PipelineBuilder implements Callable<vtkActor> {
private vtkActor actor;
private vtkDataSetMapper mapper;
private vtkShrinkFilter shrink;
private vtkSphereSource sphere;
public vtkActor call() throws Exception {
// New
actor = new vtkActor();
mapper = new vtkDataSetMapper();
shrink = new vtkShrinkFilter();
sphere = new vtkSphereSource();
// Settings
sphere.SetPhiResolution(60);
sphere.SetThetaResolution(60);
double[] center = new double[3];
sphere.SetCenter(GetRandomCenter(center));
actor.GetProperty().SetColor(Math.random(), Math.random(), Math.random());
// Binding
actor.SetMapper(mapper);
mapper.SetInputConnection(shrink.GetOutputPort());
shrink.SetInputConnection(sphere.GetOutputPort());
// Update
mapper.Update();
// Wait some time
Thread.sleep((long) (Math.random() * 500));
// Return
return actor;
}
public double[] GetRandomCenter(double[] center) {
for (int i = 0; i < 3; i++) {
center[i] = Math.random() * 10;
}
return center;
}
}
// -----------------------------------------------------------------
public Demo() {
super(new BorderLayout());
panel3d = new vtkPanel();
gcStatus = new JLabel("");
runGC = new JCheckBox("Enable GC", false);
debugMode = new JCheckBox("Debug mode", false);
exec = new ExecutorCompletionService<vtkActor>(Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()));
// Setup UI
JPanel statusBar = new JPanel();
statusBar.setLayout(new BoxLayout(statusBar, BoxLayout.X_AXIS));
statusBar.add(runGC);
statusBar.add(debugMode);
statusBar.add(Box.createHorizontalGlue());
statusBar.add(gcStatus);
add(panel3d, BorderLayout.CENTER);
add(statusBar, BorderLayout.SOUTH);
// Init app
// this.setupGC(); // We use a Swing timer that show the result in UI
// instead..
this.setupWorkers();
// Update GC info into the UI every seconds
// Reset camera each seconds the first 10 ones
this.nbSeconds = 0;
new Timer(1000, new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (nbSeconds++ < 10) {
panel3d.resetCamera();
}
vtkRenderer renderer = panel3d.GetRenderer();
if (renderer.GetNumberOfPropsRendered() > 1) {
renderer.RemoveActor(renderer.GetActors().GetLastProp());
}
// Run GC in local thread (EDT)
if (runGC.isSelected()) {
vtkReferenceInformation info = vtkObject.JAVA_OBJECT_MANAGER.gc(debugMode.isSelected());
if (debugMode.isSelected()) {
System.out.println(info.listKeptReferenceToString());
System.out.println(info.listRemovedReferenceToString());
}
gcStatus.setText(info.toString());
} else {
gcStatus.setText("");
}
panel3d.Render();
}
}).start();
}
private void setupGC() {
// Setup GC to run every 1 second in EDT
vtkObject.JAVA_OBJECT_MANAGER.getAutoGarbageCollector().SetScheduleTime(1, TimeUnit.SECONDS);
// Start/Stop the GC based on the checkbox
runGC.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
vtkObject.JAVA_OBJECT_MANAGER.getAutoGarbageCollector().SetAutoGarbageCollection(runGC.isSelected());
}
});
// Change GC mode based on the checkbox
debugMode.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
vtkObject.JAVA_OBJECT_MANAGER.getAutoGarbageCollector().SetDebug(debugMode.isSelected());
}
});
}
private void setupWorkers() {
// Add actor thread: Consume the working queue and add the actor into
// the render inside the EDT thread
final AddActorRunnable adderRunnable = new AddActorRunnable();
adderRunnable.setRenderer(panel3d);
new Thread() {
public void run() {
for (int i = 0; i < NUMBER_OF_PIPLINE_TO_BUILD; i++) {
try {
adderRunnable.setActor(exec.take().get());
SwingUtilities.invokeAndWait(adderRunnable);
panel3d.repaint();
} catch (InterruptedException e) {
return;
} catch (ExecutionException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
};
}.start();
}
public void startWorking() {
for (int i = 0; i < NUMBER_OF_PIPLINE_TO_BUILD; i++) {
exec.submit(new PipelineBuilder());
}
}
// -----------------------------------------------------------------
public static void main(String[] args) throws InterruptedException, InvocationTargetException {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Demo app = new Demo();
JFrame f = new JFrame("Concurrency test");
f.getContentPane().setLayout(new BorderLayout());
f.getContentPane().add(app, BorderLayout.CENTER);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(400, 400);
f.setVisible(true);
f.validate();
app.startWorking();
}
});
}
}
|