@Override public void mouseWheelMoved(final MouseWheelEvent e) { final double v = keyModfiedSpeed(e.getModifiersEx()); final int s = e.getWheelRotation(); p.setF(p.getF() * (1 - 0.05f * s * v)); update(false); }
private static final void visualize( final ImagePlus imp, final int w, final int h, final EquirectangularProjection p) { try { final double maxD = imp.getWidth() / 2; final GeneralPath gp = new GeneralPath(); final double[] l = new double[] {0, 0}; p.applyInverseInPlace(l); double x0 = l[0]; gp.moveTo(l[0], l[1]); for (int x = 1; x < w; ++x) { l[0] = x; l[1] = 0; p.applyInverseInPlace(l); final double dx = l[0] - x0; if (dx > maxD) { gp.lineTo(l[0] - imp.getWidth(), l[1]); gp.moveTo(l[0], l[1]); } else if (dx < -maxD) { gp.lineTo(l[0] + imp.getWidth(), l[1]); gp.moveTo(l[0], l[1]); } else gp.lineTo(l[0], l[1]); x0 = l[0]; } for (int y = 1; y < h; ++y) { l[0] = w - 1; l[1] = y; p.applyInverseInPlace(l); final double dx = l[0] - x0; if (dx > maxD) { gp.lineTo(l[0] - imp.getWidth(), l[1]); gp.moveTo(l[0], l[1]); } else if (dx < -maxD) { gp.lineTo(l[0] + imp.getWidth(), l[1]); gp.moveTo(l[0], l[1]); } else gp.lineTo(l[0], l[1]); x0 = l[0]; } for (int x = w - 2; x >= 0; --x) { l[0] = x; l[1] = h - 1; p.applyInverseInPlace(l); final double dx = l[0] - x0; if (dx > maxD) { gp.lineTo(l[0] - imp.getWidth(), l[1]); gp.moveTo(l[0], l[1]); } else if (dx < -maxD) { gp.lineTo(l[0] + imp.getWidth(), l[1]); gp.moveTo(l[0], l[1]); } else gp.lineTo(l[0], l[1]); x0 = l[0]; } for (int y = h - 2; y >= 0; --y) { l[0] = 0; l[1] = y; p.applyInverseInPlace(l); final double dx = l[0] - x0; if (dx > maxD) { gp.lineTo(l[0] - imp.getWidth(), l[1]); gp.moveTo(l[0], l[1]); } else if (dx < -maxD) { gp.lineTo(l[0] + imp.getWidth(), l[1]); gp.moveTo(l[0], l[1]); } else gp.lineTo(l[0], l[1]); x0 = l[0]; } imp.getCanvas().setDisplayList(gp, Color.YELLOW, null); imp.updateAndDraw(); } catch (final NoninvertibleModelException e) { } }
private final void renderCubeFaces(final double hfov, final double vfov) { /* fragile, but that's not public API and we know what we're doing... */ final double cubeSize = frontSource.getWidth() - 1; /* prepare extended image */ ipSource = ip.createProcessor( hfov == 2.0 * Math.PI ? imp.getWidth() + 1 : imp.getWidth(), vfov == Math.PI ? imp.getHeight() + 1 : imp.getHeight()); prepareExtendedImage(imp.getProcessor(), ipSource); /* render cube faces */ final EquirectangularProjection q = p.clone(); q.resetOrientation(); q.setTargetWidth(cubeSize); q.setTargetHeight(cubeSize); q.setF(0.5f); final InverseTransformMapping<EquirectangularProjection> qMapping = new InverseTransformMapping<EquirectangularProjection>(q); IJ.showStatus("Rendering cube faces..."); IJ.showProgress(0, 6); qMapping.mapInterpolated(ipSource, frontSource); IJ.showProgress(1, 6); q.pan(Math.PI); qMapping.mapInterpolated(ipSource, backSource); IJ.showProgress(2, 6); q.resetOrientation(); q.pan(Math.PI / 2); qMapping.mapInterpolated(ipSource, leftSource); IJ.showProgress(3, 6); q.resetOrientation(); q.pan(-Math.PI / 2); qMapping.mapInterpolated(ipSource, rightSource); IJ.showProgress(4, 6); q.resetOrientation(); q.tilt(-Math.PI / 2); qMapping.mapInterpolated(ipSource, topSource); IJ.showProgress(5, 6); q.resetOrientation(); q.tilt(Math.PI / 2); qMapping.mapInterpolated(ipSource, bottomSource); IJ.showProgress(6, 6); if (showCubefaces) { new ImagePlus("front", frontSource).show(); new ImagePlus("back", backSource).show(); new ImagePlus("left", leftSource).show(); new ImagePlus("right", rightSource).show(); new ImagePlus("top", topSource).show(); new ImagePlus("bottom", bottomSource).show(); } }
@Override public void keyPressed(final KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_ESCAPE || e.getKeyCode() == KeyEvent.VK_ENTER) { painter.interrupt(); imp.getCanvas().setDisplayList(null); gui.restoreGui(); if (e.getKeyCode() == KeyEvent.VK_ESCAPE) gui.close(); } else if (e.getKeyCode() == KeyEvent.VK_SHIFT) { dLambda *= 10; dPhi *= 10; } else if (e.getKeyCode() == KeyEvent.VK_CONTROL) { dLambda /= 10; dPhi /= 10; } else { final double v = keyModfiedSpeed(e.getModifiersEx()); if (e.getKeyCode() == KeyEvent.VK_LEFT) { lambda -= v * step; update(false); } else if (e.getKeyCode() == KeyEvent.VK_RIGHT) { lambda += v * step; update(false); } else if (e.getKeyCode() == KeyEvent.VK_UP) { phi -= v * step; update(false); } else if (e.getKeyCode() == KeyEvent.VK_DOWN) { phi += v * step; update(false); } else if (e.getKeyCode() == KeyEvent.VK_PLUS || e.getKeyCode() == KeyEvent.VK_EQUALS) { p.setF(p.getF() * (1 + 0.1f * v)); update(false); } else if (e.getKeyCode() == KeyEvent.VK_MINUS) { p.setF(p.getF() / (1 + 0.1f * v)); update(false); } else if (e.getKeyCode() == KeyEvent.VK_SPACE) { renderCubeFaces(hfov, vfov); update(false); } else if (e.getKeyCode() == KeyEvent.VK_I) { painter.toggleInterpolation(); update(false); } else if (e.getKeyCode() == KeyEvent.VK_V) { painter.toggleVisualization(); imp.getCanvas().setDisplayList(null); update(false); } else if (e.getKeyCode() == KeyEvent.VK_A) { naviMode = NaviMode.PAN_TILT; dLambda = dPhi = 0; update(false); } else if (e.getKeyCode() == KeyEvent.VK_P) { naviMode = NaviMode.PAN_ONLY; dLambda = dPhi = 0; update(false); } else if (e.getKeyCode() == KeyEvent.VK_T) { naviMode = NaviMode.TILT_ONLY; dLambda = dPhi = 0; update(false); } else if (e.getKeyCode() == KeyEvent.VK_R) { naviMode = NaviMode.ROLL_ONLY; dLambda = dPhi = 0; update(false); } else if (e.getKeyCode() == KeyEvent.VK_F1) { IJ.showMessage( "Interactive Panorama Viewer", "Mouse control:" + NL + " " + NL + "Pan and tilt the panorama by dragging the image in the canvas and" + NL + "zoom in and out using the mouse-wheel." + NL + " " + NL + "Key control:" + NL + " " + NL + "CURSOR LEFT - Pan left." + NL + "CURSOR RIGHT - Pan right." + NL + "CURSOR UP - Tilt up." + NL + "CURSOR DOWN - Tilt down." + NL + "SHIFT - Move 10x faster." + NL + "CTRL - Move browse 10x slower." + NL + "ENTER/ESC - Leave interactive mode." + NL + "I - Toggle interpolation." + NL + "V - Toggle FOV visualization." + NL + "R - Roll-mode (roll via mouse drag)." + NL + "P - Pan/Tilt-mode (pan/tilt via mouse drag)."); } } }
public final void run( final ImagePlus imp, final int width, final int height, final double minLambda, final double minPhi, final double hfov, final double vfov) { ip = imp.getProcessor().createProcessor(width, height); final ImagePlus impViewer = new ImagePlus("Panorama View", ip); /* initialize projection */ p.setMinLambda(minLambda); p.setMinPhi(minPhi); p.setLambdaPiScale(Math.PI / hfov * imp.getWidth()); p.setPhiPiScale(Math.PI / vfov * (imp.getHeight() - 1)); p.setTargetWidth(ip.getWidth()); p.setTargetHeight(ip.getHeight()); p.setF(0.5); System.out.println(p.getLambdaPiScale() + " " + p.getPhiPiScale()); /* TODO calculate proper size */ // final int cubeSize = 500; final int cubeSize = (int) Math.round(Math.max(p.getPhiPiScale(), p.getLambdaPiScale()) * 2.0 / Math.PI); frontSource = ip.createProcessor(cubeSize + 1, cubeSize + 1); backSource = ip.createProcessor(cubeSize + 1, cubeSize + 1); leftSource = ip.createProcessor(cubeSize + 1, cubeSize + 1); rightSource = ip.createProcessor(cubeSize + 1, cubeSize + 1); topSource = ip.createProcessor(cubeSize + 1, cubeSize + 1); bottomSource = ip.createProcessor(cubeSize + 1, cubeSize + 1); renderCubeFaces(hfov, vfov); /* instantiate and run mapper and painter */ final Mapper mapper = new CubeFaceMapper( frontSource, backSource, leftSource, rightSource, topSource, bottomSource, p); painter = new MappingThread(imp, impViewer, mapper, ip, p); impViewer.show(); gui = new GUI(impViewer); gui.backupGui(); gui.takeOverGui(); painter.start(); update(false); }