use of ij3d.ContentInstant in project GDSC-SMLM by aherbert.
the class ImageJ3DResultsViewer method createImage3DUniverse.
/**
* Creates the image 3D universe with a unique name.
*
* @param title the title
* @param titleList the title list (of titles to ignore)
* @return the image 3D universe
*/
private Image3DUniverse createImage3DUniverse(String title, List<String> titleList) {
// Get a unique name by appending numbers to the end
String title2 = title;
int counter = 2;
while (titleList.contains(title2)) {
title2 = title + " " + (counter++);
}
final Image3DUniverse universe = new Image3DUniverse();
universe.addUniverseListener(new LocalUniverseListener());
universe.setShowBoundingBoxUponSelection(false);
universe.showAttribute(DefaultUniverse.ATTRIBUTE_SCALEBAR, false);
// Capture a canvas mouse click/region and identify the coordinates.
final ImageCanvas3D canvas = (ImageCanvas3D) universe.getCanvas();
final BranchGroup scene = universe.getScene();
final MouseListener mouseListener = new MouseAdapter() {
@Override
public void mouseClicked(final MouseEvent event) {
if (!consumeEvent(event)) {
return;
}
// Consume the event
event.consume();
// This finds the vertex indices of the rendered object.
final Pair<Content, IntersectionInfo> pair = getPickedContent(canvas, scene, event.getX(), event.getY());
if (pair == null) {
// Do the same as the mouseClicked in Image3DUniverse
universe.select(null);
return;
}
// Only process content added from localisations
final Content c = pair.getKey();
if (!(c.getUserData() instanceof ResultsMetaData)) {
// Do the same as the mouseClicked in Image3DUniverse
universe.select(c);
return;
}
final ResultsMetaData data = (ResultsMetaData) c.getUserData();
final MemoryPeakResults results = data.results;
// Look up the localisation from the clicked vertex
final ContentInstant content = c.getCurrent();
int index = -1;
if (content.getContent() instanceof CustomMeshNode) {
final CustomMeshNode node = (CustomMeshNode) content.getContent();
final CustomMesh mesh = node.getMesh();
int vertexCount;
final GeometryArray ga = (GeometryArray) mesh.getGeometry();
// Default to the number of vertices
vertexCount = ga.getValidVertexCount();
final int countPerLocalisation = vertexCount / results.size();
// Determine the localisation
final int vertexIndex = pair.getValue().getVertexIndices()[0];
index = vertexIndex / countPerLocalisation;
} else if (content.getContent() instanceof ItemGroupNode) {
// All shapes have the index as the user data
final Object o = pair.getValue().getGeometry().getUserData();
if (o instanceof Integer) {
index = (Integer) pair.getValue().getGeometry().getUserData();
}
}
if (index == -1) {
return;
}
final PeakResult result = results.get(index);
if (event.getClickCount() > 1) {
// Centre on the localisation
final Point3d coordinate = new Point3d();
coordinate.set(data.points.get(index));
// Handle the local transform of the content ...
final Transform3D vWorldToLocal = getVworldToLocal(content);
vWorldToLocal.transform(coordinate);
universe.centerAt(coordinate);
} else if (event.isShiftDown()) {
// Ctrl+Shift held down to remove selected
data.removeFromSelectionModel(result);
} else {
// Ctrl held down to set selection
data.addToSelectionModel(result);
}
}
private boolean consumeEvent(final MouseEvent event) {
if (event.isConsumed() || event.getButton() != MouseEvent.BUTTON1 || !(event.isControlDown())) {
return false;
}
if (event.getClickCount() == 1) {
return true;
}
return (event.getClickCount() == 2);
}
};
// 0 = ImageCanvas3D
// 1 = DefaultUniverse
// 2 = Image3DUniverse
final MouseListener[] l = canvas.getMouseListeners();
for (int i = 0; i < l.length; i++) {
if (l[i].getClass().getName().contains("Image3DUniverse")) {
// We want to be before the Image3DUniverse to allow consuming the click event.
// Only allow the click event.
// This disables the right-click pop-up menu.
// It doesn't have anything of use for localisations anyway.
canvas.removeMouseListener(l[i]);
canvas.addMouseListener(mouseListener);
canvas.addMouseListener(new MouseListenerWrapper(l[i], MouseListenerWrapper.MOUSE_CLICKED));
}
}
// 0 = ImageCanvas3D
// 1 = DefaultUniverse
// 2 = Image3DUniverse
// 3 = EventCatcher (from scijava)
final MouseMotionListener[] ml = canvas.getMouseMotionListeners();
for (int i = 0; i < ml.length; i++) {
if (ml[i].getClass().getName().contains("Image3DUniverse")) {
// Ignore this as it just shows the name in the IJ status bar
canvas.removeMouseMotionListener(ml[i]);
}
}
// Finally display the window
universe.show();
final ImageWindow3D window = universe.getWindow();
GUI.center(window);
window.setTitle(title2);
WindowManager.addWindow(window);
window.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent event) {
WindowManager.removeWindow(window);
}
});
// Add a new menu for SMLM functionality
createSmlmMenuBar(universe);
return universe;
}
use of ij3d.ContentInstant in project GDSC-SMLM by aherbert.
the class ImageJ3DResultsViewer method getTotalTransparentObjects.
private static long getTotalTransparentObjects(Image3DUniverse univ, String ignoreName) {
long size = 0;
for (final Iterator<Content> it = univ.contents(); it.hasNext(); ) {
final Content c = it.next();
if (ignoreName.equals(c.getName())) {
continue;
}
if (!(c.getUserData() instanceof ResultsMetaData)) {
return 0;
}
final ContentInstant content = c.getCurrent();
if (content.getContent() instanceof ItemGroupNode) {
final ItemGroupNode node = (ItemGroupNode) content.getContent();
final ItemGroup g = node.getItemGroup();
if (g instanceof ItemGeometryGroup) {
size += g.size();
}
}
}
return size;
}
use of ij3d.ContentInstant in project GDSC-SMLM by aherbert.
the class ImageJ3DResultsViewerDemo method run.
@Override
public void run(String arg) {
if (ImageJ3DViewerUtils.JAVA_3D_VERSION == null) {
IJ.error(TITLE, "Java 3D is not available");
return;
}
final boolean renderingTest = true;
if (renderingTest) {
// Put all the shapes from rendering on a view and see how they look.
final Image3DUniverse univ = new Image3DUniverse();
univ.showAttribute(DefaultUniverse.ATTRIBUTE_SCALEBAR, false);
univ.show();
final ImageWindow3D w = univ.getWindow();
GUI.center(w);
// Test how many vertices a primitive sphere has
float x = 0;
final float y = 0;
final float space = 2.5f;
for (final Rendering rendering : Rendering.values()) {
final Shape3D shape = Shape3DHelper.createShape(rendering, 3);
final Appearance a = shape.getAppearance();
final ItemMesh mesh = new ReferenceItemMesh(new Point3f[] { new Point3f(x, y, 0) }, (GeometryArray) shape.getGeometry(), a, null, null, 0f);
ImageJUtils.log("R=%s %s Vc=%d V=%d T=%d", rendering, shape.getGeometry().getClass().getSimpleName(), mesh.getVerticesCountPerItem(), mesh.getVerticesPerItem(), Shape3DHelper.getNumberOfTriangles(rendering));
if (rendering == Rendering.POINT) {
a.getPointAttributes().setPointSize(10);
}
univ.addCustomMesh(mesh, x + "," + y);
x += space;
}
return;
}
final boolean sphereTest = true;
if (sphereTest) {
// Sphere test
// Put lots of spheres on a view and see how they look.
// Is it worth supporting an ItemTriangleStripMesh so we can control
// the sphere better than the icosahedron?
final Image3DUniverse univ = new Image3DUniverse();
univ.showAttribute(DefaultUniverse.ATTRIBUTE_SCALEBAR, false);
univ.show();
final ImageWindow3D w = univ.getWindow();
GUI.center(w);
// Test how many vertices a primitive sphere has
float x = 0;
float y = 0;
final float space = 2.5f;
Appearance app = null;
for (int d = 0; d < 4; d++) {
final List<Point3f> points = customnode.MeshMaker.createIcosahedron(d, 1f);
final Pair<Point3f[], int[]> p = CustomContentHelper.createIndexedObject(points);
final int v = points.size();
final int t = v / 3;
ImageJUtils.log("Icosahedron divisions = %d, V=%d, T=%d, Vi=%d (%.2f), i=%d", d, v, t, p.getKey().length, v / (double) p.getKey().length, p.getValue().length);
CustomMesh mesh = new ItemTriangleMesh(points.toArray(new Point3f[0]), new Point3f[] { new Point3f(x, y, 0) }, null, null, 0);
app = mesh.getAppearance();
univ.addCustomMesh(mesh, x + "," + y + "," + t);
final float y2 = y + space;
mesh = new ItemIndexedTriangleMesh(p.getKey(), p.getValue(), new Point3f[] { new Point3f(x, y2, 0) }, null, null, 0);
univ.addCustomMesh(mesh, x + "," + y2 + "," + t);
x += space;
}
// Avoid null pointer warnings
if (app == null) {
throw new NullPointerException();
}
// The T=800 sphere looks about the same as the Icosahedron(div=3) T=1280
// This may be a better super-high resolution option.
x = 0;
y += 2 * space;
app = (Appearance) app.cloneNodeComponent(true);
// a.getColoringAttributes().setColor(0, 1, 0);
app.getMaterial().setDiffuseColor(0, 1, 0);
for (int d = 4; d < 50; d += 4) {
// This is a triangle strip array so is more space efficient
final Sphere s = new Sphere(1, Primitive.GENERATE_NORMALS, d);
final int t = s.getNumTriangles();
ImageJUtils.log("Sphere divisions = %d, V=%d, T=%d", d, s.getNumVertices(), t);
final ItemGeometryGroup g = new ItemGeometryGroup(new Point3f[] { new Point3f(x, y, 0) }, (GeometryArray) s.getShape().getGeometry(), app, null, null, null);
final String name = x + "," + y + "," + t;
final CustomContent content = new CustomContent(name, true);
content.getCurrent().display(new ItemGroupNode(g));
univ.addContent(content);
x += space;
}
return;
}
LocalList<Point3f> pointList;
float scale;
if (MemoryPeakResults.isMemoryEmpty()) {
pointList = new LocalList<>();
int range;
// 9 points
range = 1;
// range = 49; // 99^3 = 970299 points
for (int x = -range; x <= range; x++) {
for (int y = -range; y <= range; y++) {
for (int z = -range; z <= range; z++) {
pointList.add(new Point3f(x, y, z));
}
}
}
scale = 0.25f;
} else {
final ImageJ3DResultsViewerSettings.Builder settings = SettingsManager.readImageJ3DResultsViewerSettings(0).toBuilder();
final ExtendedGenericDialog gd = new ExtendedGenericDialog(TITLE);
gd.addMessage("Select a dataset to display");
ResultsManager.addInput(gd, settings.getInputOption(), InputSource.MEMORY);
gd.showDialog();
if (gd.wasCanceled()) {
return;
}
final String name = ResultsManager.getInputSource(gd);
settings.setInputOption(name);
SettingsManager.writeSettings(settings);
final MemoryPeakResults results = ResultsManager.loadInputResults(name, false, null, null);
if (MemoryPeakResults.isEmpty(results)) {
IJ.error(TITLE, "No results could be loaded");
IJ.showStatus("");
return;
}
pointList = ImageJ3DResultsViewer.getPoints(results, settings);
if (pointList == null) {
return;
}
scale = 10f;
}
final Image3DUniverse univ = new Image3DUniverse();
univ.showAttribute(DefaultUniverse.ATTRIBUTE_SCALEBAR, false);
univ.show();
final ImageWindow3D w = univ.getWindow();
GUI.center(w);
final View view = univ.getViewer().getView();
view.setTransparencySortingPolicy(View.TRANSPARENCY_SORT_GEOMETRY);
// I am not sure if this is required if objects are sorted.
// view.setDepthBufferFreezeTransparent(false)
IJ.showStatus("Creating points ...");
final Point3f[] points = pointList.toArray(new Point3f[0]);
final Point3f[] sizes = new Point3f[] { new Point3f(scale, scale, scale) };
final Appearance appearance = new Appearance();
final TransparencyAttributes ta = new TransparencyAttributes();
ta.setTransparency(0.5f);
ta.setTransparencyMode(TransparencyAttributes.FASTEST);
appearance.setTransparencyAttributes(ta);
final ItemGeometryGroup pointGroup = new ItemGeometryGroup(points, null, appearance, sizes, null, null);
// pointGroup = new OrderedItemGeometryGroup(points, null, appearance, sizes, null, null);
// // This supports transparency sorting
// BranchGroup bg = new BranchGroup();
// bg.addChild(pointGroup);
// bg.compile();
// univ.getScene().addChild(bg);
// // This does not since ContentInstant uses an OrderedPath to show:
// // the content; the object bounding box, coordinate system and point list
// final Content c = new Content("Test");
// final ContentInstant content = c.getCurrent();
// content.display(new PointGroupNode(pointGroup));
// univ.addContent(c);
// This does since ItemGeometryNode uses a Group to show the points as individual shapes
// and the CustomContentInstant uses a group not an ordered group so show all the adornments.
IJ.showStatus("Displaying points ...");
final CustomContent c = new CustomContent("Test", false);
final ContentInstant content = c.getCurrent();
content.display(new ItemGroupNode(pointGroup));
univ.addContent(c);
IJ.showStatus("Done");
}
Aggregations