Search in sources :

Example 46 with LayerSet

use of ini.trakem2.display.LayerSet in project TrakEM2 by trakem2.

the class LayerTree method actionPerformed.

public void actionPerformed(ActionEvent ae) {
    try {
        String command = ae.getActionCommand();
        // commands for multiple selections:
        TreePath[] paths = this.getSelectionPaths();
        if (null != paths && paths.length > 1) {
            if (command.equals("Reverse layer Z coords")) {
                // check that all layers belong to the same layer set
                // just do it
                Layer[] layer = new Layer[paths.length];
                LayerSet ls = null;
                for (int i = 0; i < paths.length; i++) {
                    layer[i] = (Layer) ((LayerThing) ((DefaultMutableTreeNode) paths[i].getLastPathComponent()).getUserObject()).getObject();
                    if (null == ls)
                        ls = layer[i].getParent();
                    else if (!ls.equals(layer[i].getParent())) {
                        Utils.showMessage("To reverse, all layers must belong to the same layer set");
                        return;
                    }
                }
                final ArrayList<Layer> al = new ArrayList<Layer>();
                for (int i = 0; i < layer.length; i++) al.add(layer[i]);
                ls.addLayerEditedStep(al);
                // ASSSUMING layers are already Z ordered! CHECK
                for (int i = 0, j = layer.length - 1; i < layer.length / 2; i++, j--) {
                    double z = layer[i].getZ();
                    layer[i].setZ(layer[j].getZ());
                    layer[j].setZ(z);
                }
                updateList(ls);
                ls.addLayerEditedStep(al);
                Display.updateLayerScroller(ls);
            } else if (command.equals("Translate layers in Z...")) {
                GenericDialog gd = ControlWindow.makeGenericDialog("Range");
                gd.addMessage("Translate selected range in the Z axis:");
                gd.addNumericField("by: ", 0, 4);
                gd.showDialog();
                if (gd.wasCanceled())
                    return;
                // else, displace
                double dz = gd.getNextNumber();
                if (Double.isNaN(dz)) {
                    Utils.showMessage("Invalid number");
                    return;
                }
                HashSet<LayerSet> hs_parents = new HashSet<LayerSet>();
                for (int i = 0; i < paths.length; i++) {
                    Layer layer = (Layer) ((LayerThing) ((DefaultMutableTreeNode) paths[i].getLastPathComponent()).getUserObject()).getObject();
                    layer.setZ(layer.getZ() + dz);
                    hs_parents.add(layer.getParent());
                }
                for (LayerSet ls : hs_parents) {
                    updateList(ls);
                }
                // now update all profile's Z ordering in the ProjectTree
                ProjectThing root_pt = project.getRootProjectThing();
                for (final ProjectThing pt : root_pt.findChildrenOfType("profile_list")) {
                    pt.fixZOrdering();
                    project.getProjectTree().updateList(pt);
                }
                project.getProjectTree().updateUILater();
            // Display.updateLayerScroller((LayerSet)((DefaultMutableTreeNode)getModel().getRoot()).getUserObject());
            } else if (command.equals("Delete...")) {
                if (!Utils.check("Really remove all selected layers?"))
                    return;
                for (int i = 0; i < paths.length; i++) {
                    DefaultMutableTreeNode lnode = (DefaultMutableTreeNode) paths[i].getLastPathComponent();
                    LayerThing lt = (LayerThing) lnode.getUserObject();
                    Layer layer = (Layer) lt.getObject();
                    if (!layer.remove(false)) {
                        Utils.showMessage("Could not delete layer " + layer);
                        this.updateUILater();
                        return;
                    }
                    if (lt.remove(false)) {
                        ((DefaultTreeModel) this.getModel()).removeNodeFromParent(lnode);
                    }
                }
                this.updateUILater();
            } else if (command.equals("Scale Z and thickness...")) {
                GenericDialog gd = new GenericDialog("Scale Z");
                gd.addNumericField("scale: ", 1.0, 2);
                gd.showDialog();
                double scale = gd.getNextNumber();
                if (Double.isNaN(scale) || 0 == scale) {
                    Utils.showMessage("Imvalid scaling factor: " + scale);
                    return;
                }
                for (int i = 0; i < paths.length; i++) {
                    DefaultMutableTreeNode lnode = (DefaultMutableTreeNode) paths[i].getLastPathComponent();
                    LayerThing lt = (LayerThing) lnode.getUserObject();
                    Layer layer = (Layer) lt.getObject();
                    layer.setZ(layer.getZ() * scale);
                    layer.setThickness(layer.getThickness() * scale);
                }
                this.updateUILater();
            } else {
                Utils.showMessage("Don't know what to do with command " + command + " for multiple selected nodes");
            }
            return;
        }
        // commands for single selection:
        if (null == selected_node)
            return;
        LayerThing thing = (LayerThing) selected_node.getUserObject();
        LayerThing new_thing = null;
        TemplateThing tt = null;
        Object ob = null;
        int i_position = -1;
        if (command.startsWith("new ")) {
            String name = command.substring(4).toLowerCase();
            if (name.equals("layer")) {
                // Create new Layer and add it to the selected node
                LayerSet set = (LayerSet) thing.getObject();
                Layer new_layer = Layer.create(thing.getProject(), set);
                if (null == new_layer)
                    return;
                tt = thing.getChildTemplate("layer");
                ob = new_layer;
                Display.updateTitle(set);
            } else if (name.equals("layer set")) {
                // with space in the middle
                // Create a new LayerSet and add it in the middle
                Layer layer = (Layer) thing.getObject();
                LayerSet new_set = layer.getParent().create(layer);
                if (null == new_set)
                    return;
                layer.add(new_set);
                // add it at the end of the list
                // with space, not underscore
                tt = thing.getChildTemplate("layer set");
                ob = new_set;
                i_position = selected_node.getChildCount();
                Display.update(layer);
            } else {
                Utils.log("LayerTree.actionPerformed: don't know what to do with the command: " + command);
                return;
            }
        } else if (command.equals("many new layers...")) {
            LayerSet set = (LayerSet) thing.getObject();
            List<Layer> layers = Layer.createMany(set.getProject(), set);
            // add them to the tree as LayerThing
            if (null == layers)
                return;
            for (Layer la : layers) {
                // null layers will be skipped
                addLayer(set, la);
            }
            Display.updateTitle(set);
            return;
        } else if (command.equals("Show")) {
            // create a new Display
            DBObject dbo = (DBObject) thing.getObject();
            // the top level LayerSet
            if (thing.getType().equals("layer_set") && null == ((LayerSet) dbo).getParent())
                return;
            Display.createDisplay(dbo.getProject(), thing.getType().equals("layer") ? (Layer) dbo : ((LayerSet) dbo).getParent());
            return;
        } else if (command.equals("Show centered in Display")) {
            LayerSet ls = (LayerSet) thing.getObject();
            Display.showCentered(ls.getParent(), ls, false, false);
        } else if (command.equals("Delete...")) {
            remove(true, thing, selected_node);
            return;
        } else if (command.equals("Import stack...")) {
            if (thing.getObject() instanceof LayerSet) {
                LayerSet set = (LayerSet) thing.getObject();
                Layer layer = null;
                if (0 == set.getLayers().size()) {
                    layer = Layer.create(set.getProject(), set);
                    if (null == layer)
                        return;
                    tt = thing.getChildTemplate("Layer");
                    ob = layer;
                } else
                    // click on a desired, existing layer.
                    return;
                layer.getProject().getLoader().importStack(layer, null, true);
            } else if (thing.getObject() instanceof Layer) {
                Layer layer = (Layer) thing.getObject();
                layer.getProject().getLoader().importStack(layer, null, true);
                return;
            }
        } else if (command.equals("Import grid...")) {
            if (thing.getObject() instanceof Layer) {
                Layer layer = (Layer) thing.getObject();
                layer.getProject().getLoader().importGrid(layer);
            }
        } else if (command.equals("Import sequence as grid...")) {
            if (thing.getObject() instanceof Layer) {
                Layer layer = (Layer) thing.getObject();
                layer.getProject().getLoader().importSequenceAsGrid(layer);
            }
        } else if (command.equals("Import from text file...")) {
            if (thing.getObject() instanceof Layer) {
                Layer layer = (Layer) thing.getObject();
                layer.getProject().getLoader().importImages(layer);
            }
        } else if (command.equals("Resize LayerSet...")) {
            if (thing.getObject() instanceof LayerSet) {
                LayerSet ls = (LayerSet) thing.getObject();
                ij.gui.GenericDialog gd = ControlWindow.makeGenericDialog("Resize LayerSet");
                gd.addNumericField("new width: ", ls.getLayerWidth(), 3);
                gd.addNumericField("new height: ", ls.getLayerHeight(), 3);
                gd.addChoice("Anchor: ", LayerSet.ANCHORS, LayerSet.ANCHORS[0]);
                gd.showDialog();
                if (gd.wasCanceled())
                    return;
                float new_width = (float) gd.getNextNumber(), new_height = (float) gd.getNextNumber();
                // will complain and prevent cropping existing Displayable objects
                ls.setDimensions(new_width, new_height, gd.getNextChoiceIndex());
            }
        } else if (command.equals("Autoresize LayerSet")) {
            if (thing.getObject() instanceof LayerSet) {
                LayerSet ls = (LayerSet) thing.getObject();
                ls.setMinimumDimensions();
            }
        } else if (command.equals("Adjust...")) {
            if (thing.getObject() instanceof Layer) {
                Layer layer = (Layer) thing.getObject();
                ij.gui.GenericDialog gd = ControlWindow.makeGenericDialog("Adjust Layer");
                gd.addNumericField("new z: ", layer.getZ(), 4);
                gd.addNumericField("new thickness: ", layer.getThickness(), 4);
                gd.showDialog();
                if (gd.wasCanceled())
                    return;
                double new_z = gd.getNextNumber();
                layer.setThickness(gd.getNextNumber());
                if (new_z != layer.getZ()) {
                    layer.setZ(new_z);
                    // move in the tree
                    /*
						DefaultMutableTreeNode child = findNode(thing, this);
						DefaultMutableTreeNode parent = (DefaultMutableTreeNode)child.getParent();
						parent.remove(child);
						// reinsert
						int n = parent.getChildCount();
						int i = 0;
						for (; i < n; i++) {
							DefaultMutableTreeNode child_node = (DefaultMutableTreeNode)parent.getChildAt(i);
							LayerThing child_thing = (LayerThing)child_node.getUserObject();
							if (!child_thing.getType().equals("Layer")) continue;
							double iz = ((Layer)child_thing.getObject()).getZ();
							if (iz < new_z) continue;
							// else, add the layer here, after this one
							break;
						}
						((DefaultTreeModel)this.getModel()).insertNodeInto(child, parent, i);
						*/
                    // fix tree crappiness (empty slot ?!?)
                    /* // the fix doesn't work. ARGH TODO
						Enumeration e = parent.children();
						parent.removeAllChildren();
						i = 0;
						while (e.hasMoreElements()) {
							//parent.add((DefaultMutableTreeNode)e.nextElement());
							((DefaultTreeModel)this.getModel()).insertNodeInto(child, parent, i);
							i++;
						}*/
                    // easier and correct: overkill
                    updateList(layer.getParent());
                    // set selected
                    DefaultMutableTreeNode child = findNode(thing, this);
                    TreePath treePath = new TreePath(child.getPath());
                    this.scrollPathToVisible(treePath);
                    this.setSelectionPath(treePath);
                }
            }
            return;
        } else if (command.equals("Rename...")) {
            GenericDialog gd = ControlWindow.makeGenericDialog("Rename");
            gd.addStringField("new name: ", thing.getTitle());
            gd.showDialog();
            if (gd.wasCanceled())
                return;
            project.getRootLayerSet().addUndoStep(new RenameThingStep(thing));
            thing.setTitle(gd.getNextString());
            project.getRootLayerSet().addUndoStep(new RenameThingStep(thing));
        } else if (command.equals("Translate layers in Z...")) {
            // / TODO: this method should use multiple selections directly on the tree
            if (thing.getObject() instanceof LayerSet) {
                LayerSet ls = (LayerSet) thing.getObject();
                ArrayList<Layer> al_layers = ls.getLayers();
                String[] layer_names = new String[al_layers.size()];
                for (int i = 0; i < layer_names.length; i++) {
                    layer_names[i] = ls.getProject().findLayerThing(al_layers.get(i)).toString();
                }
                GenericDialog gd = ControlWindow.makeGenericDialog("Range");
                gd.addMessage("Translate selected range in the Z axis:");
                gd.addChoice("from: ", layer_names, layer_names[0]);
                gd.addChoice("to: ", layer_names, layer_names[layer_names.length - 1]);
                gd.addNumericField("by: ", 0, 4);
                gd.showDialog();
                if (gd.wasCanceled())
                    return;
                // else, displace
                double dz = gd.getNextNumber();
                if (Double.isNaN(dz)) {
                    Utils.showMessage("Invalid number");
                    return;
                }
                int i_start = gd.getNextChoiceIndex();
                int i_end = gd.getNextChoiceIndex();
                for (int i = i_start; i <= i_end; i++) {
                    Layer layer = (Layer) al_layers.get(i);
                    layer.setZ(layer.getZ() + dz);
                }
                // update node labels and position
                updateList(ls);
            }
        } else if (command.equals("Reverse layer Z coords...")) {
            // / TODO: this method should use multiple selections directly on the tree
            if (thing.getObject() instanceof LayerSet) {
                LayerSet ls = (LayerSet) thing.getObject();
                ArrayList<Layer> al_layers = ls.getLayers();
                String[] layer_names = new String[al_layers.size()];
                for (int i = 0; i < layer_names.length; i++) {
                    layer_names[i] = ls.getProject().findLayerThing(al_layers.get(i)).toString();
                }
                GenericDialog gd = ControlWindow.makeGenericDialog("Range");
                gd.addMessage("Reverse Z coordinates of selected range:");
                gd.addChoice("from: ", layer_names, layer_names[0]);
                gd.addChoice("to: ", layer_names, layer_names[layer_names.length - 1]);
                gd.showDialog();
                if (gd.wasCanceled())
                    return;
                int i_start = gd.getNextChoiceIndex();
                int i_end = gd.getNextChoiceIndex();
                for (int i = i_start, j = i_end; i < i_end / 2; i++, j--) {
                    Layer layer1 = (Layer) al_layers.get(i);
                    double z1 = layer1.getZ();
                    Layer layer2 = (Layer) al_layers.get(j);
                    layer1.setZ(layer2.getZ());
                    layer2.setZ(z1);
                }
                // update node labels and position
                updateList(ls);
            }
        } else if (command.equals("Search...")) {
            Search.showWindow();
        } else if (command.equals("Reset layer Z and thickness")) {
            LayerSet ls = ((LayerSet) thing.getObject());
            List<Layer> layers = ls.getLayers();
            ls.addLayerEditedStep(layers);
            int i = 0;
            for (final Layer la : ls.getLayers()) {
                la.setZ(i++);
                la.setThickness(1);
            }
            ls.addLayerEditedStep(layers);
        } else {
            Utils.log("LayerTree.actionPerformed: don't know what to do with the command: " + command);
            return;
        }
        if (null == tt)
            return;
        new_thing = new LayerThing(tt, thing.getProject(), ob);
        if (-1 == i_position && new_thing.getType().equals("layer")) {
            // find the node whose 'z' is larger than z, and add the Layer before that.
            // (just because there could be objects other than LayerThing with a Layer in it in the future, so set.getLayers().indexOf(layer) may not be useful)
            double z = ((Layer) ob).getZ();
            int n = selected_node.getChildCount();
            int i = 0;
            for (; i < n; i++) {
                DefaultMutableTreeNode child_node = (DefaultMutableTreeNode) selected_node.getChildAt(i);
                LayerThing child_thing = (LayerThing) child_node.getUserObject();
                if (!child_thing.getType().equals("layer")) {
                    continue;
                }
                double iz = ((Layer) child_thing.getObject()).getZ();
                if (iz < z) {
                    continue;
                }
                // else, add the layer here, after this one
                break;
            }
            i_position = i;
        }
        thing.addChild(new_thing);
        DefaultMutableTreeNode new_node = new DefaultMutableTreeNode(new_thing);
        ((DefaultTreeModel) this.getModel()).insertNodeInto(new_node, selected_node, i_position);
        TreePath treePath = new TreePath(new_node.getPath());
        this.scrollPathToVisible(treePath);
        this.setSelectionPath(treePath);
        if (new_thing.getType().equals("layer set")) {
            // add the first layer to it, and open it in a Display
            LayerSet newls = (LayerSet) new_thing.getObject();
            Layer la = new Layer(newls.getProject(), 0, 1, newls);
            addLayer(newls, la);
            new Display(newls.getProject(), la);
        }
    } catch (Exception e) {
        IJError.print(e);
    }
}
Also used : DefaultMutableTreeNode(javax.swing.tree.DefaultMutableTreeNode) ArrayList(java.util.ArrayList) DBObject(ini.trakem2.persistence.DBObject) GenericDialog(ij.gui.GenericDialog) ArrayList(java.util.ArrayList) List(java.util.List) HashSet(java.util.HashSet) LayerSet(ini.trakem2.display.LayerSet) DefaultTreeModel(javax.swing.tree.DefaultTreeModel) Layer(ini.trakem2.display.Layer) TreePath(javax.swing.tree.TreePath) DBObject(ini.trakem2.persistence.DBObject) Display(ini.trakem2.display.Display)

Example 47 with LayerSet

use of ini.trakem2.display.LayerSet in project TrakEM2 by trakem2.

the class DBLoader method fetchLayer.

/**
 * Load all objects into the Layer: Profile and Pipe from the hs_pt (full of ProjectThing wrapping them), and Patch, LayerSet, DLabel, etc from the database.
 */
private Layer fetchLayer(Project project, long id, HashMap hs_pt) throws Exception {
    ResultSet r = connection.prepareStatement("SELECT * FROM ab_layers WHERE id=" + id).executeQuery();
    Layer layer = null;
    if (r.next()) {
        long layer_id = r.getLong("id");
        layer = new Layer(project, layer_id, r.getDouble("z"), r.getDouble("thickness"));
        // find the Layer's parent
        long parent_id = r.getLong("layer_set_id");
        Object set = hs_pt.get(new Long(parent_id));
        if (null != set) {
            ((LayerSet) set).addSilently(layer);
        } else {
            Utils.log("Loader.fetchLayer: WARNING no parent for layer " + layer);
        }
        // add the displayables from hs_pt that correspond to this layer (and all other objects that belong to the layer)
        HashMap hs_d = new HashMap();
        ResultSet rd = connection.prepareStatement("SELECT ab_displayables.id, ab_profiles.id, layer_id, stack_index FROM ab_displayables,ab_profiles WHERE ab_displayables.id=ab_profiles.id AND layer_id=" + layer_id).executeQuery();
        while (rd.next()) {
            Long idd = new Long(rd.getLong("id"));
            Object ob = hs_pt.get(idd);
            // Utils.log("Found profile with id=" + idd + " and ob = " + ob);
            if (null != ob) {
                hs_d.put(new Integer(rd.getInt("stack_index")), ob);
            }
        }
        rd.close();
        // fetch LayerSet objects (which are also Displayable), and put them in the hs_pt (this is hackerous)
        ResultSet rls = connection.prepareStatement("SELECT * FROM ab_layer_sets, ab_displayables WHERE ab_layer_sets.id=ab_displayables.id AND ab_layer_sets.parent_layer_id=" + id).executeQuery();
        while (rls.next()) {
            long ls_id = rls.getLong("id");
            LayerSet layer_set = new LayerSet(project, ls_id, rls.getString("title"), (float) rls.getDouble("width"), (float) rls.getDouble("height"), rls.getDouble("rot_x"), rls.getDouble("rot_y"), rls.getDouble("rot_z"), (float) rls.getDouble("layer_width"), (float) rls.getDouble("layer_height"), rls.getBoolean("locked"), rls.getInt("snapshots_mode"), new AffineTransform(rls.getDouble("m00"), rls.getDouble("m10"), rls.getDouble("m01"), rls.getDouble("m11"), rls.getDouble("m02"), rls.getDouble("m12")));
            hs_pt.put(new Long(ls_id), layer_set);
            hs_d.put(new Integer(rls.getInt("stack_index")), layer_set);
            layer_set.setLayer(layer, false);
            // find the pipes (or other possible ZDisplayable objects) in the hs_pt that belong to this LayerSet and add them silently
            ResultSet rpi = connection.prepareStatement("SELECT ab_displayables.id, ab_zdisplayables.id, layer_id, layer_set_id, stack_index FROM ab_displayables,ab_zdisplayables WHERE ab_displayables.id=ab_zdisplayables.id AND layer_set_id=" + ls_id + " ORDER BY stack_index ASC").executeQuery();
            while (rpi.next()) {
                Long idd = new Long(rpi.getLong("id"));
                Object ob = hs_pt.get(idd);
                if (null != ob && ob instanceof ZDisplayable) {
                    layer_set.addSilently((ZDisplayable) ob);
                } else {
                    Utils.log("fetchLayer: failed to add a ZDisplayable to the layer_set. zdispl id = " + idd);
                }
            }
            rpi.close();
        }
        rls.close();
        // add Patch objects from ab_patches joint-called with ab_displayables
        ResultSet rp = connection.prepareStatement("SELECT ab_patches.id, ab_displayables.id, layer_id, title, width, height, stack_index, imp_type, locked, min, max, m00, m10, m01, m11, m02, m12 FROM ab_patches,ab_displayables WHERE ab_patches.id=ab_displayables.id AND ab_displayables.layer_id=" + layer_id).executeQuery();
        while (rp.next()) {
            long patch_id = rp.getLong("id");
            Patch patch = new Patch(project, patch_id, rp.getString("title"), (float) rp.getDouble("width"), (float) rp.getDouble("height"), rp.getInt("o_width"), rp.getInt("o_height"), rp.getInt("imp_type"), rp.getBoolean("locked"), rp.getDouble("min"), rp.getDouble("max"), new AffineTransform(rp.getDouble("m00"), rp.getDouble("m10"), rp.getDouble("m01"), rp.getDouble("m11"), rp.getDouble("m02"), rp.getDouble("m12")));
            // collecting all Displayable objects to reconstruct links
            hs_pt.put(new Long(patch_id), patch);
            hs_d.put(new Integer(rp.getInt("stack_index")), patch);
        }
        rp.close();
        // add DLabel objects
        ResultSet rl = connection.prepareStatement("SELECT ab_labels.id, ab_displayables.id, layer_id, title, width, height, m00, m10, m01, m11, m02, m12, stack_index, font_name, font_style, font_size, ab_labels.type, locked FROM ab_labels,ab_displayables WHERE ab_labels.id=ab_displayables.id AND ab_displayables.layer_id=" + layer_id).executeQuery();
        while (rl.next()) {
            long label_id = rl.getLong("id");
            DLabel label = new DLabel(project, label_id, rl.getString("title"), (float) rl.getDouble("width"), (float) rl.getDouble("height"), rl.getInt("type"), rl.getString("font_name"), rl.getInt("font_style"), rl.getInt("font_size"), rl.getBoolean("locked"), new AffineTransform(rl.getDouble("m00"), rl.getDouble("m10"), rl.getDouble("m01"), rl.getDouble("m11"), rl.getDouble("m02"), rl.getDouble("m12")));
            // collecting all Displayable objects to reconstruct links
            hs_pt.put(new Long(label_id), label);
            hs_d.put(new Integer(rl.getInt("stack_index")), label);
        }
        rl.close();
        // Add silently to the Layer ordered by stack index
        Set e = hs_d.keySet();
        Object[] si = new Object[hs_d.size()];
        si = e.toArray(si);
        // will it sort an array of integers correctly? Who knows!
        Arrays.sort(si);
        for (int i = 0; i < si.length; i++) {
            // Utils.log("Loader layer.addSilently: adding " + (DBObject)hs_d.get(si[i]));
            layer.addSilently((DBObject) hs_d.get(si[i]));
        }
        // find displays and open later, when fully loaded.
        ResultSet rdi = connection.prepareStatement("SELECT * FROM ab_displays WHERE layer_id=" + layer.getId()).executeQuery();
        while (rdi.next()) {
            fetchDisplay(rdi, layer);
        }
        rdi.close();
    }
    r.close();
    return layer;
}
Also used : ResultSet(java.sql.ResultSet) Set(java.util.Set) LayerSet(ini.trakem2.display.LayerSet) LayerSet(ini.trakem2.display.LayerSet) HashMap(java.util.HashMap) Layer(ini.trakem2.display.Layer) Point(java.awt.Point) PGpoint(org.postgresql.geometric.PGpoint) ZDisplayable(ini.trakem2.display.ZDisplayable) DLabel(ini.trakem2.display.DLabel) ResultSet(java.sql.ResultSet) AffineTransform(java.awt.geom.AffineTransform) Patch(ini.trakem2.display.Patch)

Example 48 with LayerSet

use of ini.trakem2.display.LayerSet in project TrakEM2 by trakem2.

the class AreaUtils method generateTriangles.

/**
 * Expects areas in local coordinates to the Displayable @param d.
 *  @param d
 *  @param scale The scaling of the entire universe, to limit the overall box
 *  @param resample_ The optimization parameter for marching cubes (i.e. a value of 2 will scale down to half, then apply marching cubes, then scale up by 2 the vertices coordinates).
 *  @param areas
 *  @return The List of triangles involved, specified as three consecutive vertices. A list of Point3f vertices.
 */
public static List<Point3f> generateTriangles(final Displayable d, final double scale, final int resample_, final Map<Layer, Area> areas) {
    // in the LayerSet, layers are ordered by Z already.
    try {
        int n = areas.size();
        if (0 == n)
            return null;
        final int resample;
        if (resample_ <= 0) {
            resample = 1;
            Utils.log2("Fixing zero or negative resampling value to 1.");
        } else
            resample = resample_;
        final LayerSet layer_set = d.getLayerSet();
        final AffineTransform aff = d.getAffineTransformCopy();
        final Rectangle r = d.getBoundingBox(null);
        // remove translation from a copy of the Displayable's AffineTransform
        final AffineTransform at_translate = new AffineTransform();
        at_translate.translate(-r.x, -r.y);
        aff.preConcatenate(at_translate);
        // incorporate resampling scaling into the transform
        final AffineTransform atK = new AffineTransform();
        // Utils.log("resample: " + resample + "  scale: " + scale);
        // 'scale' is there to limit gigantic universes
        final double K = (1.0 / resample) * scale;
        atK.scale(K, K);
        aff.preConcatenate(atK);
        final Calibration cal = layer_set.getCalibrationCopy();
        // Find first layer, compute depth, and fill in the depth vs area map
        Layer first_layer = null, last_layer = null;
        final int w = (int) Math.ceil(r.width * K);
        final int h = (int) Math.ceil(r.height * K);
        int depth = 0;
        final Map<Integer, Area> ma = new HashMap<Integer, Area>();
        for (final Layer la : layer_set.getLayers()) {
            // layers sorted by Z ASC
            final Area area = areas.get(la);
            if (null != area) {
                ma.put(depth, area);
                if (null == first_layer) {
                    first_layer = la;
                }
                // Utils.log("area at depth " + depth + " for layer " + la);
                depth++;
                n--;
            } else if (0 != depth) {
                // Utils.log("Empty area at depth " + depth);
                // an empty layer
                depth++;
            }
            if (0 == n) {
                last_layer = la;
                // no more areas to paint
                break;
            }
        }
        if (0 == depth) {
            Utils.log("ERROR could not find any areas for " + d);
            return null;
        }
        if (0 != n) {
            Utils.log("WARNING could not find all areas for " + d);
        }
        // No zero-padding: Marching Cubes now can handle edges
        final ShapeList<ByteType> shapeList = new ShapeListCached<ByteType>(new int[] { w, h, depth }, new ByteType(), 32);
        final Image<ByteType> shapeListImage = new Image<ByteType>(shapeList, shapeList.getBackground(), "ShapeListContainer");
        // 255 or -1 don't work !? So, giving the highest value (127) that is both a byte and an int.
        final ByteType intensity = new ByteType((byte) 127);
        for (final Map.Entry<Integer, Area> e : ma.entrySet()) {
            Area a = e.getValue();
            if (!aff.isIdentity()) {
                a = M.areaInIntsByRounding(a.createTransformedArea(aff));
            }
            shapeList.addShape(a, intensity, new int[] { e.getKey() });
        }
        // debug:
        // ImagePlus imp = ImageJFunctions.displayAsVirtualStack(shapeListImage);
        // imp.getProcessor().setMinAndMax( 0, 255 );
        // imp.show();
        // Utils.log2("Using imglib Shape List Image Container");
        // Now marching cubes
        // origins at 0,0,0: uncalibrated
        final List<Point3f> list = new MCTriangulator().getTriangles(shapeListImage, 1, new float[3]);
        // The list of triangles has coordinates:
        // - in x,y: in pixels, scaled by K = (1 / resample) * scale,
        // translated by r.x, r.y (the top-left coordinate of this AreaList bounding box)
        // - in z: in stack slice indices
        // So all x,y,z must be corrected in x,y and z of the proper layer
        // final double offset = first_layer.getZ();
        final int i_first_layer = layer_set.indexOf(first_layer);
        // The x,y translation to correct each point by:
        final float dx = (float) (r.x * scale * cal.pixelWidth);
        final float dy = (float) (r.y * scale * cal.pixelHeight);
        // Correct x,y by resampling and calibration, but not scale
        // scale is already in the pixel coordinates
        final float rsw = (float) (resample * cal.pixelWidth);
        final float rsh = (float) (resample * cal.pixelHeight);
        // no resampling in Z. and Uses pixelWidth, not pixelDepth.
        final double sz = scale * cal.pixelWidth;
        // debug:
        /*
			// which p.z types exist?
			final TreeSet<Float> ts = new TreeSet<Float>();
			for (final Iterator it = list.iterator(); it.hasNext(); ) {
				ts.add(((Point3f)it.next()).z);
			}
			for (final Float pz : ts) Utils.log2("A z: " + pz);
			*/
        // debug: How many different Z?
        /*
			HashSet<Float> zs = new HashSet<Float>();
			for (Point3f p : list) {
				zs.add(p.z);
			}
			ArrayList<Float> a = new ArrayList<Float>(zs);
			java.util.Collections.sort(a);
			for (Float f : a) {
				Utils.log("f: " + f);
			}
			*/
        // Utils.log2("Number of slices: " + imp.getNSlices());
        // Fix all points:
        // Read from list, modify and put into verts
        // and don't modify it if the verts already has it (it's just coincident)
        final Point3f[] verts = new Point3f[list.size()];
        // Utils.log("number of verts: " + verts.length + " mod 3: " + (verts.length % 3));
        final TreeMap<Integer, Point3f> output = new TreeMap<Integer, Point3f>();
        // The first section generates vertices at -1 and 0
        // The last section generates them at last_section_index and last_section_index +1
        // Capture from -1 to 0
        fix3DPoints(list, output, verts, first_layer.getZ(), 0, -1, dx, dy, rsw, rsh, sz, 1);
        int slice_index = 0;
        for (final Layer la : layer_set.getLayers().subList(i_first_layer, i_first_layer + depth)) {
            // If layer is empty, continue
            /* // YEAH don't! At least the immediate next layer would have points, like the extra Z level after last layer, to account for the thickness of the layer!
				if (empty_layers.contains(la)) {
					slice_index++;
					continue;
				}
				*/
            fix3DPoints(list, output, verts, la.getZ(), la.getThickness(), slice_index, dx, dy, rsw, rsh, sz, 1);
            slice_index++;
        }
        // Do the last layer again. The last layer has two Z planes in which it has pixels:
        try {
            // Capture from last_section_index to last_section_index+1, inclusive
            fix3DPoints(list, output, verts, last_layer.getZ() + last_layer.getThickness(), 0, slice_index, dx, dy, rsw, rsh, sz, 2);
        } catch (final Exception ee) {
            IJError.print(ee);
        }
        // Handle potential errors:
        if (0 != list.size() - output.size()) {
            Utils.log2("Unprocessed/unused points: " + (list.size() - output.size()));
            for (int i = 0; i < verts.length; i++) {
                if (null == verts[i]) {
                    final Point3f p = (Point3f) list.get(i);
                    Utils.log2("verts[" + i + "] = " + p.x + ", " + p.y + ", " + p.z + "  p.z as int: " + ((int) (p.z + 0.05f)));
                }
            }
            return new ArrayList<Point3f>(output.values());
        } else {
            return java.util.Arrays.asList(verts);
        }
    } catch (final Exception e) {
        e.printStackTrace();
    }
    return null;
}
Also used : HashMap(java.util.HashMap) Rectangle(java.awt.Rectangle) ArrayList(java.util.ArrayList) ShapeListCached(mpicbg.imglib.container.shapelist.ShapeListCached) ByteType(mpicbg.imglib.type.numeric.integer.ByteType) Image(mpicbg.imglib.image.Image) Point3f(org.scijava.vecmath.Point3f) LayerSet(ini.trakem2.display.LayerSet) Calibration(ij.measure.Calibration) TreeMap(java.util.TreeMap) Layer(ini.trakem2.display.Layer) ExecutionException(java.util.concurrent.ExecutionException) Area(java.awt.geom.Area) AffineTransform(java.awt.geom.AffineTransform) HashMap(java.util.HashMap) Map(java.util.Map) TreeMap(java.util.TreeMap)

Example 49 with LayerSet

use of ini.trakem2.display.LayerSet in project TrakEM2 by trakem2.

the class ControlClickBehavior method doProcess.

@Override
public void doProcess(final MouseEvent e) {
    if (!e.isControlDown() || e.getID() != MouseEvent.MOUSE_PRESSED) {
        super.doProcess(e);
        return;
    }
    final Picker picker = universe.getPicker();
    final Content content = picker.getPickedContent(e.getX(), e.getY());
    if (content == null)
        return;
    final Point3d p = picker.getPickPointGeometry(content, e);
    if (p == null) {
        Utils.log("No point was found on content " + content);
        return;
    }
    final Display display = Display.getFront(ls.getProject());
    if (display == null) {
        // If there's no Display, just return...
        return;
    }
    if (display.getLayerSet() != ls) {
        Utils.log("The LayerSet instances do not match");
        return;
    }
    if (ls == null) {
        Utils.log("No LayerSet was found for the Display");
        return;
    }
    final Calibration cal = ls.getCalibration();
    if (cal == null) {
        Utils.log("No calibration information was found for the LayerSet");
        return;
    }
    final double scaledZ = p.z / cal.pixelWidth;
    final Layer l = ls.getNearestLayer(scaledZ);
    if (l == null) {
        Utils.log("No layer was found nearest to " + scaledZ);
        return;
    }
    final Coordinate<?> coordinate = new Coordinate<Object>(p.x / cal.pixelWidth, p.y / cal.pixelHeight, l, null);
    display.center(coordinate);
}
Also used : Coordinate(ini.trakem2.display.Coordinate) Content(ij3d.Content) Point3d(org.scijava.vecmath.Point3d) Picker(ij3d.behaviors.Picker) Calibration(ij.measure.Calibration) Layer(ini.trakem2.display.Layer) Display(ini.trakem2.display.Display)

Example 50 with LayerSet

use of ini.trakem2.display.LayerSet in project TrakEM2 by trakem2.

the class AmiraImporter method extractAreaLists.

/**
 * Returns a map of label vs AreaList.
 */
public static Map<Float, AreaList> extractAreaLists(final ImagePlus imp, final Layer first_layer, final double base_x, final double base_y, final float alpha, final boolean add_background) {
    try {
        final HashMap<Integer, HashMap<Float, Area>> map = new HashMap<Integer, HashMap<Float, Area>>();
        // works even for images that are not stacks: it creates one
        final ImageStack stack = imp.getStack();
        final AtomicInteger ai = new AtomicInteger(1);
        final AtomicInteger completed_slices = new AtomicInteger(0);
        final int n_slices = imp.getNSlices();
        final Thread parent = Thread.currentThread();
        final Thread[] threads = MultiThreading.newThreads();
        for (int ithread = 0; ithread < threads.length; ithread++) {
            threads[ithread] = new Thread() {

                public void run() {
                    final Rectangle box = new Rectangle(0, 0, 1, 1);
                    for (int i = ai.getAndIncrement(); i <= n_slices; i = ai.getAndIncrement()) {
                        final ImageProcessor ip;
                        synchronized (map) {
                            ip = stack.getProcessor(i);
                        }
                        if (parent.isInterrupted())
                            return;
                        final HashMap<Float, Area> layer_map = new HashMap<Float, Area>();
                        synchronized (map) {
                            map.put(i, layer_map);
                        }
                        AreaUtils.extractAreas(ip, layer_map, add_background, box, parent, true);
                        Utils.showProgress(completed_slices.incrementAndGet() / (float) n_slices);
                    }
                }
            };
        }
        MultiThreading.startAndJoin(threads);
        Utils.showProgress(1);
        if (parent.isInterrupted())
            return null;
        final HashMap<Float, AreaList> alis = new HashMap<Float, AreaList>();
        Utils.log2("Recreating arealists...");
        Utils.log2("map.size() = " + map.size());
        final double thickness = first_layer.getThickness();
        final double first_z = first_layer.getZ();
        // Recreate AreaLists
        for (final Map.Entry<Integer, HashMap<Float, Area>> e : map.entrySet()) {
            final int slice_index = e.getKey();
            final HashMap<Float, Area> layer_map = e.getValue();
            for (final Map.Entry<Float, Area> fa : layer_map.entrySet()) {
                Float label = fa.getKey();
                AreaList ali = alis.get(label);
                if (null == ali) {
                    ali = new AreaList(first_layer.getProject(), "Label " + label.intValue(), base_x, base_y);
                    alis.put(label, ali);
                }
                double z = first_z + (slice_index - 1) * thickness;
                Layer layer = first_layer.getParent().getLayer(z, thickness, true);
                ali.setArea(layer.getId(), fa.getValue());
            }
        }
        Utils.log2("Done recreating.");
        first_layer.getParent().addAll(alis.values());
        Utils.log2("Done adding all to LayerSet");
        float hue = 0;
        for (final Map.Entry<Float, AreaList> e : alis.entrySet()) {
            final AreaList ali = e.getValue();
            ali.setProperty("label", Integer.toString(e.getKey().intValue()));
            ali.calculateBoundingBox(null);
            ali.setColor(Color.getHSBColor(hue, 1, 1));
            ali.setAlpha(alpha);
            // golden angle
            hue += 0.38197f;
            if (hue > 1)
                hue = hue - 1;
        }
        Utils.log2("Done setting properties");
        return alis;
    } catch (Exception e) {
        IJError.print(e);
    }
    return null;
}
Also used : ImageStack(ij.ImageStack) HashMap(java.util.HashMap) Rectangle(java.awt.Rectangle) AreaList(ini.trakem2.display.AreaList) Layer(ini.trakem2.display.Layer) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ImageProcessor(ij.process.ImageProcessor) Area(java.awt.geom.Area) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) HashMap(java.util.HashMap) Map(java.util.Map)

Aggregations

ArrayList (java.util.ArrayList)24 Layer (ini.trakem2.display.Layer)22 LayerSet (ini.trakem2.display.LayerSet)20 HashMap (java.util.HashMap)20 HashSet (java.util.HashSet)19 Rectangle (java.awt.Rectangle)14 Patch (ini.trakem2.display.Patch)13 ImagePlus (ij.ImagePlus)11 GenericDialog (ij.gui.GenericDialog)11 ProjectThing (ini.trakem2.tree.ProjectThing)11 AffineTransform (java.awt.geom.AffineTransform)11 Map (java.util.Map)11 Future (java.util.concurrent.Future)11 Displayable (ini.trakem2.display.Displayable)10 ZDisplayable (ini.trakem2.display.ZDisplayable)10 Area (java.awt.geom.Area)10 Worker (ini.trakem2.utils.Worker)9 Point (java.awt.Point)9 TreeMap (java.util.TreeMap)9 DBObject (ini.trakem2.persistence.DBObject)8