fable.imageviewer.views.ReliefView.java Source code

Java tutorial

Introduction

Here is the source code for fable.imageviewer.views.ReliefView.java

Source

/*
 * Copyright (c) 2012 European Synchrotron Radiation Facility,
 *                    Diamond Light Source Ltd.
 *
 * 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
 */
package fable.imageviewer.views;

import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IContributionManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.opengl.GLCanvas;
import org.eclipse.swt.opengl.GLData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Spinner;
import org.eclipse.ui.part.ViewPart;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GLContext;
import org.lwjgl.util.glu.GLU;

import fable.framework.toolbox.FableUtils;
import fable.framework.toolbox.GridUtils;
import fable.imageviewer.rcp.Activator;

/**
 * Display an image as a 3d relief plot using opengl as an eclipse view. The
 * data to display are updated by calling the setData() method.
 * 
 * @author andy gotz
 * 
 */
public class ReliefView extends ViewPart implements IImageSizeProvider {

    public static final String ID = "fable.imageviewer.views.ReliefView";

    /* a simple lookup table to display a temperature-like lut */
    private static float[] blue = { 1.0f, 0.333f, 0.666f, 0.999f, 0.833f, 0.666f, 0.5f, 0.333f, 0.166f, 0.0f,
            0.0f };
    private static float[] green = { 1.0f, 0.0f, 0.111f, 0.222f, 0.333f, 0.666f, 0.999f, 0.666f, 0.333f, 0.0f,
            0.0f };
    private static float[] red = { 1.0f, 0.0f, 0.055f, 0.110f, 0.165f, 0.220f, 0.275f, 0.333f, 0.666f, 0.999f,
            1.0f };

    public ReliefView thisView = null;
    public GLContext context;
    // public static GL11 gl;
    public GLU glu = new GLU();
    // public static GLUT glut = new GLUT();
    private SceneGrip grip;
    private GLCanvas canvas;
    private Spinner minimumSpinner, maximumSpinner;
    private Action freezeButton, autoscaleButton;
    private boolean freeze = false, autoscale = true;
    private Action updateButton, highZReset;
    private int colorIndexMax = 10;
    private float scaleMinimum, scaleMaximum;
    private int pointSize = 4;
    // private static float scale=1;
    private float[] image = null;
    // private static float zcenter;
    private float imageAsFloat[] = null;
    // private float maximum;
    private float minimum, mean;
    private String fileName;
    // private float size;
    private float zscale;
    private boolean reliefListFirst = true;
    private int reliefList;
    private boolean firstImage = true;
    private int imageWidth = 0;
    private int imageHeight = 0;

    private void drawRelief() {
        canvas.setCurrent();
        try {
            GLContext.useContext(canvas);
        } catch (LWJGLException ex) {
            FableUtils.excMsg(ReliefView.class, "Error in drawRelief using GLContext.useContext", ex);
        }
        // context.makeCurrent();
        // gl = context.getGL ();
        GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
        if (!freeze)
            grip.adjust();
        if (image != null) {
            GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
            GL11.glDisable(GL11.GL_LIGHTING);
            GL11.glCallList(reliefList);
            GL11.glEnable(GL11.GL_LIGHTING);
        }
    }

    private void drawReliefList() {
        // long started = System.currentTimeMillis();
        if (!reliefListFirst) {
            GL11.glDeleteLists(reliefList, 1);
        }
        reliefListFirst = false;
        reliefList = GL11.glGenLists(1);
        GL11.glNewList(reliefList, GL11.GL_COMPILE);
        GL11.glColor3f(1.0f, 1.0f, 1.0f); // white
        GL11.glPointSize(pointSize);
        for (int i = 0; i < imageWidth; i++) {
            GL11.glBegin(GL11.GL_LINE_STRIP);
            for (int j = 0; j < imageHeight; j++) {
                int color_index;
                color_index = (int) image[j * imageWidth + i];
                if (color_index < 0)
                    color_index = 0;
                if (color_index > colorIndexMax)
                    color_index = colorIndexMax;
                GL11.glColor3f(red[color_index], green[color_index], blue[color_index]); // temperature lut
                GL11.glVertex3f(i, j, image[j * imageWidth + i]);
            }
            GL11.glEnd();
        }
        for (int i = 0; i < imageHeight; i++) {
            GL11.glBegin(GL11.GL_LINE_STRIP);
            for (int j = 0; j < imageWidth; j++) {
                int color_index;
                color_index = (int) image[i * imageWidth + j];
                if (color_index < 0)
                    color_index = 0;
                if (color_index > colorIndexMax)
                    color_index = colorIndexMax;
                GL11.glColor3f(red[color_index], green[color_index], blue[color_index]); // temperature lut
                GL11.glVertex3f(j, i, image[i * imageWidth + j]);
            }
            GL11.glEnd();
        }
        GL11.glEndList();
        // long elapsed = System.currentTimeMillis()-started;
        // logger.debug("time to draw relief list "+elapsed+" ms");
    }

    public void setImageAsFloat(float[] _imageAsFloat, int _width, int _height, float _minimum, float _maximum,
            float _mean, String _fileName) {
        /*
         * do not listen for new images - display on the selected image until a
         * new image is set manually
         */
        imageAsFloat = _imageAsFloat; /* save a copy for rescaling later */
        image = new float[_width * _height];
        imageWidth = _width;
        imageHeight = _height;
        minimum = _minimum;
        // maximum = _maximum;
        mean = _mean;
        if (autoscale) {
            scaleMinimum = _minimum;
            scaleMaximum = _mean;
        }
        fileName = _fileName;
        // this.size = (imageWidth+imageHeight)/2;
        setPartName("Relief " + fileName);
        if (firstImage) {
            grip.init();
            firstImage = false;
        }
        scaleImage();
        drawReliefList();
        drawRelief();
    }

    public void scaleImage() {
        if (autoscale) {
            scaleMinimum = minimum;
            scaleMaximum = mean;
            minimumSpinner.setSelection((int) (scaleMinimum));
            maximumSpinner.setSelection((int) (scaleMaximum));
        } else {
            scaleMinimum = minimumSpinner.getSelection();
            scaleMaximum = maximumSpinner.getSelection();
        }
        if (scaleMinimum == scaleMaximum)
            scaleMaximum = scaleMinimum + 1;
        zscale = 10.0f / (2.f * (scaleMaximum - scaleMinimum));
        for (int i = 0; i < imageWidth; i++) {
            for (int j = 0; j < imageHeight; j++) {
                float imageValue;
                int imageIndex;
                imageIndex = j * imageWidth + i;
                imageValue = imageAsFloat[j * imageWidth + i];
                image[imageIndex] = (imageValue - scaleMinimum) * zscale;
            }
        }
    }

    /* (non-Javadoc)
     * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite)
     */
    @Override
    public void createPartControl(Composite parent) {

        thisView = this;
        parent.setLayout(new GridLayout(1, false));
        GridUtils.removeMargins(parent);

        createActions();

        Composite comp = new Composite(parent, SWT.NONE);
        comp.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
        comp.setLayout(new FillLayout());
        GLData data = new GLData();
        data.doubleBuffer = true;
        canvas = new GLCanvas(comp, SWT.NONE, data);
        canvas.setSize(comp.getSize());
        canvas.setCurrent();
        try {
            GLContext.useContext(canvas);
        } catch (LWJGLException ex) {
            FableUtils.excMsg(ReliefView.class, "Error in createPartControl using GLContext.useContext", ex);
        }
        // context = GLDrawableFactory.getFactory().createExternalGLContext();
        canvas.addListener(SWT.Resize, new Listener() {
            public void handleEvent(Event event) {
                Rectangle bounds = canvas.getBounds();
                // float fAspect = (float) bounds.width / (float) bounds.height;
                canvas.setCurrent();
                try {
                    GLContext.useContext(canvas);
                } catch (LWJGLException ex) {
                    FableUtils.excMsg(ReliefView.class, "Error in resize listener using GLContext.useContext", ex);
                }
                // context.makeCurrent();
                // GL11 gl = context.getGL ();
                GL11.glViewport(0, 0, bounds.width, bounds.height);
                GL11.glMatrixMode(GL11.GL_PROJECTION);
                GL11.glLoadIdentity();
                // GLU glu = new GLU();
                GL11.glMatrixMode(GL11.GL_MODELVIEW);
                GL11.glLoadIdentity();
                drawRelief();
                canvas.swapBuffers();
                // context.release();
            }
        });
        canvas.setCurrent();
        try {
            GLContext.useContext(canvas);
        } catch (LWJGLException ex) {
            FableUtils.excMsg(ReliefView.class, "Error in createPartControl using GLContext.useContext", ex);
        }
        // GL11 gl = context.getGL ();
        GL11.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
        GL11.glColor3f(1.0f, 0.0f, 0.0f);
        GL11.glHint(GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_NICEST);
        GL11.glClearDepth(1.0);
        GL11.glLineWidth(2);
        GL11.glEnable(GL11.GL_DEPTH_TEST);
        // context.release();
        // create the grip for users to change the orientation, translation and
        // zoom
        grip = new SceneGrip(canvas, this);
        canvas.addMouseListener(grip);
        canvas.addMouseMoveListener(grip);
        canvas.addListener(SWT.MouseWheel, grip);
        canvas.addKeyListener(grip);
        // apparently opengl has to be redrawn constantly (why ?)
        Display.getCurrent().asyncExec(new Runnable() {
            // int rot = 0;
            public void run() {
                if (canvas == null)
                    return;
                if (!canvas.isDisposed()) {
                    canvas.setCurrent();
                    Rectangle bounds = canvas.getBounds();
                    grip.setBounds(bounds);
                    canvas.setCurrent();
                    try {
                        GLContext.useContext(canvas);
                    } catch (LWJGLException ex) {
                        FableUtils.excMsg(ReliefView.class,
                                "Error in createPartControl using " + "GLContext.useContext", ex);
                    }
                    // GL11 gl = context.getGL ();
                    GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
                    GL11.glClearColor(.0f, .0f, .0f, 1.0f); // black background
                    drawRelief();
                    canvas.swapBuffers();
                    // context.release();
                    Display.getCurrent().timerExec(200, this);
                }
            }
        });

        createImageInformationPanel(parent);
    }

    public void dispose() {
        super.dispose();
        canvas = null;
    }

    private void createImageInformationPanel(Composite parent) {

        Composite controlPanelComposite = new Composite(parent, SWT.NULL);
        controlPanelComposite.setLayout(new GridLayout(4, false));
        controlPanelComposite.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, true, false));

        Label minLabel = new Label(controlPanelComposite, SWT.NULL);
        minLabel.setText("Minimum");
        minimumSpinner = new Spinner(controlPanelComposite, SWT.NULL);
        minimumSpinner.setLayoutData(new GridData(SWT.FILL, SWT.NONE, true, false));
        minimumSpinner.setMinimum(0);
        minimumSpinner.setMaximum(Integer.MAX_VALUE);
        minimumSpinner.setEnabled(false);
        Label maxLabel = new Label(controlPanelComposite, SWT.NULL);
        maxLabel.setText("Maximum");
        maximumSpinner = new Spinner(controlPanelComposite, SWT.NULL);
        maximumSpinner.setLayoutData(new GridData(SWT.FILL, SWT.NONE, true, false));
        maximumSpinner.setMinimum(0);
        maximumSpinner.setMaximum(Integer.MAX_VALUE);
        maximumSpinner.setEnabled(false);
    }

    private void createActions() {

        final IContributionManager man = getViewSite().getActionBars().getToolBarManager();

        freezeButton = new Action("Freeze", IAction.AS_CHECK_BOX) {
            public void run() {
                freeze = freezeButton.isChecked();
            }
        };
        freezeButton.setToolTipText("Freeze 3d relief, disable rotation");
        freezeButton.setImageDescriptor(Activator.getImageDescriptor("/icons/freeze.png"));
        man.add(freezeButton);

        man.add(new Separator(getClass().getName() + ".zoom"));

        final Action zoomIn = new Action("Zoom In", IAction.AS_PUSH_BUTTON) {
            public void run() {
                grip.zoomIn();
            }
        };
        zoomIn.setToolTipText("Zoom in (Page Up)");
        zoomIn.setImageDescriptor(Activator.getImageDescriptor("/icons/magnifier_zoom_in.png"));
        man.add(zoomIn);

        final Action zoomOut = new Action("Zoom Out", IAction.AS_PUSH_BUTTON) {
            public void run() {
                grip.zoomOut();
            }
        };
        zoomOut.setToolTipText("Zoom out (Page Down)");
        zoomOut.setImageDescriptor(Activator.getImageDescriptor("/icons/magnifier_zoom_out.png"));
        man.add(zoomOut);

        man.add(new Separator(getClass().getName() + ".translate"));

        Action action = new Action("Translate up", IAction.AS_PUSH_BUTTON) {
            public void run() {
                grip.translate(SWT.ARROW_UP);
            }
        };
        action.setToolTipText("Translate up (Up Arrow)");
        action.setImageDescriptor(Activator.getImageDescriptor("/icons/arrow_up.png"));
        man.add(action);

        action = new Action("Translate down", IAction.AS_PUSH_BUTTON) {
            public void run() {
                grip.translate(SWT.ARROW_DOWN);
            }
        };
        action.setToolTipText("Translate down (Down Arrow)");
        action.setImageDescriptor(Activator.getImageDescriptor("/icons/arrow_down.png"));
        man.add(action);

        action = new Action("Translate left", IAction.AS_PUSH_BUTTON) {
            public void run() {
                grip.translate(SWT.ARROW_LEFT);
            }
        };
        action.setToolTipText("Translate left (Left Arrow)");
        action.setImageDescriptor(Activator.getImageDescriptor("/icons/arrow_left.png"));
        man.add(action);

        action = new Action("Translate right", IAction.AS_PUSH_BUTTON) {
            public void run() {
                grip.translate(SWT.ARROW_RIGHT);
            }
        };
        action.setToolTipText("Translate right (Right Arrow)");
        action.setImageDescriptor(Activator.getImageDescriptor("/icons/arrow_right.png"));
        man.add(action);

        man.add(new Separator(getClass().getName() + ".rotate"));

        action = new Action("Rotate X, high Y", IAction.AS_PUSH_BUTTON) {
            public void run() {
                grip.rotate(SWT.ARROW_UP);
            }
        };
        action.setToolTipText("Rotate X, high Y (Control + Up Arrow)");
        action.setImageDescriptor(Activator.getImageDescriptor("/icons/rotate_up.png"));
        man.add(action);

        action = new Action("Rotate X, low Y", IAction.AS_PUSH_BUTTON) {
            public void run() {
                grip.rotate(SWT.ARROW_DOWN);
            }
        };
        action.setToolTipText("Rotate X, low Y (Contol + Down Arrow)");
        action.setImageDescriptor(Activator.getImageDescriptor("/icons/rotate_down.png"));
        man.add(action);

        action = new Action("Rotate Y, low X", IAction.AS_PUSH_BUTTON) {
            public void run() {
                grip.rotate(SWT.ARROW_LEFT);
            }
        };
        action.setToolTipText("Rotate Y, low X (Control + Left Arrow)");
        action.setImageDescriptor(Activator.getImageDescriptor("/icons/rotate_left.png"));
        man.add(action);

        action = new Action("Rotate Y, high X", IAction.AS_PUSH_BUTTON) {
            public void run() {
                grip.rotate(SWT.ARROW_RIGHT);
            }
        };
        action.setToolTipText("Rotate Y, high X (Control + Right Arrow)");
        action.setImageDescriptor(Activator.getImageDescriptor("/icons/rotate_right.png"));
        man.add(action);

        man.add(new Separator(getClass().getName() + ".reset"));
        highZReset = new Action("Reset", IAction.AS_PUSH_BUTTON) {
            public void run() {
                grip.init();
            }
        };
        highZReset.setText("Reset");
        highZReset.setToolTipText("Reset 3d projection to be flat and fill the canvas and use X/Y view.");
        highZReset.setImageDescriptor(Activator.getImageDescriptor("/icons/z-high.png"));
        man.add(highZReset);

        autoscaleButton = new Action("Autoscale", IAction.AS_CHECK_BOX) {
            public void run() {
                if (autoscaleButton.isChecked()) {
                    if (!autoscale) {
                        autoscale = true;
                        scaleImage();
                        drawReliefList();
                    }
                    minimumSpinner.setEnabled(false);
                    maximumSpinner.setEnabled(false);
                } else {
                    if (autoscale) {
                        autoscale = false;
                        scaleImage();
                        drawReliefList();
                    }
                    minimumSpinner.setEnabled(true);
                    maximumSpinner.setEnabled(true);
                }
            }
        };
        autoscaleButton.setText("Autoscale");
        autoscaleButton.setToolTipText("Autoscale 3d relief between minimum and mean");
        autoscaleButton.setImageDescriptor(Activator.getImageDescriptor("/icons/autoscale.png"));
        autoscaleButton.setChecked(true);
        man.add(autoscaleButton);

        updateButton = new Action("Refresh", IAction.AS_PUSH_BUTTON) {
            public void run() {
                scaleImage();
                drawReliefList();
                drawRelief();
            }
        };
        updateButton.setText("Refresh");
        updateButton.setToolTipText("Redraw 3d relief plot");
        updateButton.setImageDescriptor(Activator.getImageDescriptor("/icons/update.png"));
        man.add(updateButton);
    }

    /**
     * Passing the focus request to the viewer's control.
     */
    public void setFocus() {
        if (canvas != null && !canvas.isDisposed()) {
            try {
                canvas.setFocus();
            } catch (Throwable ignored) {
                // The inability to focus is ignored
            }
        }
    }

    public int getImageWidth() {
        return imageWidth;
    }

    public int getImageHeight() {
        return imageHeight;
    }

}