using System; using System.Drawing; using System.Threading; using System.Windows.Forms; namespace PaintDotNet.Data.SurfacePlot { public class Interactive3DSurfacePlot { private int DOTS = 0; private int LINES = 1; private int MESH = 2; private int FILLED = 3; private int ISOLINES = 4; private int plotType = 1; /** private String DOTS_PLOT = "Dots"; private String LINES_PLOT = "Lines"; private String MESH_PLOT = "Mesh"; private String FILLED_PLOT = "Filled"; private String ISOLINES_PLOT = "Isolines"; **/ private static int ORIGINAL = 0; //private static int GRAYSCALE = 1; //private static int SPECTRUM = 2; //private static int FIRE = 3; //private static int THERMAL = 4; //private static int GRADIENT = 5; //private static int BLUE = 6; //private static int ORANGE = 7; private int colorType = ORIGINAL; //private String ORIGINAL_COLORS = "Original Colors"; //private String GRAYSCALE_LUT = "Grayscale"; //private String SPECTRUM_LUT = "Spectrum LUT"; //private String FIRE_LUT = "Fire LUT"; //private String THERMAL_LUT = "Thermal LUT"; //private String GRADIENT_COLORS = "Gradient"; //private String ORANGE_LUT = "Orange"; //private String BLUE_LUT = "Blue"; // imgeJ3D API components private JRenderer3D jRenderer3D; // other global params static int SIZE = 600; private int windowWidth = (int)(SIZE * 1.2); private int windowHeight = SIZE; private int startWindowWidth = (int)(SIZE * 1.2); private int startWindowHeight = SIZE; private double scaleWindow = 1; // scaling caused by the resize private int xStart; private int yStart; private bool drag; private int xdiff; private int ydiff; private double light = 0.2; private bool invertZ = false; private int imageWidth; private int imageHeight; private double scaleInit = 1; private double zRatioInit = 1; private double scaledWidth; private double scaledHeight; private double minVal; private double maxVal; private string units; private double maxDistance; //private Calibration cal; private bool isEqualxyzRatio = true; private double zAspectRatioSlider = 1; private double zAspectRatio = 1; private double scaleSlider = 1; private double minZ; private double maxZ; protected bool draftDrawing = true; private int xloc; private int yloc; private int grid = 128; private double smooth = 3; private double perspective = 0; private bool drawText = true; private bool drawLegend = true; private bool drawAxes = true; private bool drawLines = true; private double rotationX = 65; private double rotationZ = 39; private int minSlider = 0; private int maxSlider = 100; private bool snapshot = false; protected Color bgColor = Color.Gray; protected Color lineColor = Color.White; //zyh加的参数 private Bitmap image; private Form frame; private PictureBox mainPanel; public void run(Bitmap mat) { if (mat == null) { MessageBox.Show(PdnResources.GetString("Menu.Pleaseselectapicture.text")); } else { image = mat; imageWidth = image.Width; imageHeight = image.Height; runApplication("3D展示"); } } private void runApplication(String name) { readPrefs(); string strFrame = "Interactive 3D Surface Plot"; string str = ""; // read macro parameters try { if (str != null) { string[] params1 = new string[]{ "light=", "perspective=", "grid=", "smooth=", "plotType=", "colorType=", "drawAxes=", "drawLines=", "drawText=","drawLegend=", "invertZ=", "isEqualxyzRatio=", "rotationX=", "rotationZ=", "scale=", "scaleZ=", "min=", "max=", "snapshot=", "backgroundColor=", "lineColor=" , "windowHeight=", "windowWidth=" }; double[] paramVals = { light, perspective, grid, smooth, plotType, colorType, (drawAxes == true) ? 1 : 0, (drawLines == true) ? 1 : 0, (drawText == true) ? 1 : 0, (drawLegend == true) ? 1 : 0, (invertZ == true) ? 1 : 0, (isEqualxyzRatio == true) ? 1 : 0, rotationX, rotationZ, scaleSlider, zAspectRatioSlider, minSlider, maxSlider, (snapshot == true) ? 1 : 0, bgColor.ToArgb(), lineColor.ToArgb(), windowHeight, windowWidth }; light = Math.Min(1, Math.Max(0, paramVals[0])); perspective = Math.Min(1, Math.Max(0, paramVals[1])); grid = (int)Math.Min(1024, Math.Max(10, paramVals[2])); smooth = paramVals[3]; plotType = (int)paramVals[4]; colorType = (int)paramVals[5]; drawAxes = (paramVals[6] == 1) ? true : false; drawLines = (paramVals[7] == 1) ? true : false; drawText = (paramVals[8] == 1) ? true : false; drawLegend = (paramVals[9] == 1) ? true : false; invertZ = (paramVals[10] == 1) ? true : false; isEqualxyzRatio = (paramVals[11] == 1) ? true : false; rotationX = paramVals[12]; rotationZ = paramVals[13]; scaleSlider = Math.Min(3, Math.Max(0.25, paramVals[14])); zAspectRatioSlider = Math.Min(10, Math.Max(0.1, paramVals[15])); minSlider = (int)Math.Min(99, Math.Max(0, paramVals[16])); maxSlider = (int)Math.Min(100, Math.Max(1, paramVals[17])); snapshot = (paramVals[18] == 1) ? true : false; bgColor = Color.Gray; lineColor = Color.Red; windowHeight = (int)paramVals[21]; windowWidth = (int)paramVals[22]; } } catch (Exception e1) { Console.WriteLine(e1.ToString()); } frame = new Form(); frame.Width = windowWidth; // image.Width * 3; frame.Height = windowHeight; // image.Height * 3; frame.Name = strFrame; createGUI(); frame.Location = new System.Drawing.Point(xloc, yloc); create3DRenderer(); } /** * Initializes the JRenderer3D. Set Background, the surface plot, plot mode, lightning mode. * Adds a coordinate system. Sets scale. Renders and updates the image. */ private void create3DRenderer() { double wc = (imageWidth) / 2; double hc = (imageHeight) / 2; double dc = 256 / 2; /** *zyh 这里比较重要,目前是写死的,需要换算缩放比例 **/ scaledWidth = imageWidth;// cal.getX(imageWidth); scaledHeight = imageHeight;// cal.getY(imageHeight); minVal = 0; //ip.getMin(); maxVal = 255; //ip.getMax(); units = "pixels"; // cal.getUnits(); // create 3D renderer // center in the middle of the image jRenderer3D = new JRenderer3D(wc, hc, dc); jRenderer3D.setBufferSize(windowWidth, windowHeight); setScaleAndZRatio(); int gridHeight, gridWidth; ; if (imageHeight > imageWidth) { gridHeight = grid; gridWidth = grid * imageWidth / imageHeight; } else { gridWidth = grid; gridHeight = grid * imageHeight / imageWidth; } jRenderer3D.setSurfacePlotGridSize(gridWidth, gridHeight); jRenderer3D.setAxes(drawAxes); jRenderer3D.setLines(drawLines); jRenderer3D.setText(drawText); jRenderer3D.setLegend(drawLegend); // surface plot jRenderer3D.setSurfacePlot(image); jRenderer3D.surfacePlotSetInverse(invertZ); jRenderer3D.setTransformRotationXYZ(rotationX, 0, rotationZ); // viewing angle (in degrees) jRenderer3D.setSurfaceSmoothingFactor(smooth); jRenderer3D.setSurfacePlotLight(light); jRenderer3D.setSurfacePlotMinMax(minSlider, maxSlider); jRenderer3D.setBackgroundColor(bgColor.ToArgb()); setSurfaceColorType(colorType); setSurfacePlotType(plotType); try { Thread.Sleep(2500); } catch (Exception e) { Console.WriteLine(e.ToString()); } renderAndUpdateDisplay(); } /** * Sets the surface color type. * */ private void setSurfaceColorType(int type) { colorType = type; jRenderer3D.setSurfacePlotLut(JRenderer3D.LUT_ORIGINAL); /** if (type == ORIGINAL) jRenderer3D.setSurfacePlotLut(JRenderer3D.LUT_ORIGINAL); else if (type == GRAYSCALE) jRenderer3D.setSurfacePlotLut(JRenderer3D.LUT_GRAY); else if (type == SPECTRUM) jRenderer3D.setSurfacePlotLut(JRenderer3D.LUT_SPECTRUM); else if (type == FIRE) jRenderer3D.setSurfacePlotLut(JRenderer3D.LUT_FIRE); else if (type == THERMAL) jRenderer3D.setSurfacePlotLut(JRenderer3D.LUT_THERMAL); else if (type == GRADIENT) jRenderer3D.setSurfacePlotLut(JRenderer3D.LUT_GRADIENT); else if (type == ORANGE) jRenderer3D.setSurfacePlotLut(JRenderer3D.LUT_ORANGE); else if (type == BLUE) jRenderer3D.setSurfacePlotLut(JRenderer3D.LUT_BLUE); **/ } /** * Sets the surface plot mode. * */ private void setSurfacePlotType(int type) { if (type == DOTS) jRenderer3D.setSurfacePlotMode(JRenderer3D.SURFACEPLOT_DOTS); else if (type == LINES) jRenderer3D.setSurfacePlotMode(JRenderer3D.SURFACEPLOT_LINES); else if (type == MESH) jRenderer3D.setSurfacePlotMode(JRenderer3D.SURFACEPLOT_MESH); else if (type == ISOLINES) jRenderer3D.setSurfacePlotMode(JRenderer3D.SURFACEPLOT_ISOLINES); else if (type == FILLED) jRenderer3D.setSurfacePlotMode(JRenderer3D.SURFACEPLOT_FILLED); } /** * Renders and updates the 3D image. * Image region is repainted. */ bool show = false; private void renderAndUpdateDisplay() { jRenderer3D.doRendering(); if (mainPanel != null) { mainPanel.Refresh(); mainPanel.Image = jRenderer3D.getImage(); if (!show) { show = true; frame.ShowDialog(); } } } private void setScaleAndZRatio() { if (isEqualxyzRatio) { zRatioInit = (maxVal - minVal) / (255 * scaledWidth / imageWidth); // determine initial scale factor scaleInit = 0.55 * Math.Max(startWindowHeight, startWindowWidth) / (double)Math.Max(imageWidth, Math.Max(255 * zRatioInit, imageHeight)); } else { scaleInit = 0.55 * Math.Max(startWindowHeight, startWindowWidth) / (double)Math.Max(imageHeight, imageWidth); zRatioInit = 0.55 * startWindowHeight / (256 * scaleInit); } zAspectRatio = zRatioInit * zAspectRatioSlider; scaleWindow = Math.Min(windowHeight, windowWidth) / (double)startWindowHeight; jRenderer3D.setTransformZAspectRatio(zAspectRatio); double scale = scaleInit * scaleSlider * scaleWindow; jRenderer3D.setTransformScale(scale); jRenderer3D.setTransformPerspective(perspective); maxDistance = Math.Max(scaledWidth, Math.Max(scaledHeight, 256 * Math.Max(zAspectRatio, 1))); jRenderer3D.setTransformMaxDistance(maxDistance); jRenderer3D.setLegendTextColor(lineColor); addCoordinateSystem(); } private void addCoordinateSystem() { jRenderer3D.clearText(); jRenderer3D.clearLines(); jRenderer3D.clearCubes(); int id = 256; minZ = minVal + minSlider / 100 * (maxVal - minVal); maxZ = maxVal - (100 - maxSlider) / 100 * (maxVal - minVal); jRenderer3D.setMinZValue(minZ); jRenderer3D.setMaxZValue(maxZ); // add text to the coordinate system double off = 16 / scaleInit; double fontSize = 12 / scaleInit; double offZ = off / zAspectRatio; int ticksDist = 40; Color textColor = lineColor; double x1 = 0; double y1 = 0; double z1 = 0; double x2 = imageWidth; double y2 = imageHeight; double z2 = id; int numTicks = (int)Math.Round(imageHeight * scaleInit / ticksDist); double pos = 0; double stepValue = calcStepSize(scaledHeight, numTicks); for (double value = 0; value <= scaledHeight; value += stepValue) { String s; if (Math.Floor(value) - value == 0) s = "" + (int)value; else s = "" + (int)Math.Round(value * 1000) / 1000; // unit String for the last position if (value + stepValue > scaledHeight || value == scaledHeight) { if (!units.Equals("pixels")) s = "y/" + units; else s = "y"; } pos = (value * imageHeight / scaledHeight); y1 = y2 = pos; jRenderer3D.addText3D(new Text3D(s, x1 - off, y1, z1 - offZ, textColor, fontSize, 2)); jRenderer3D.addText3D(new Text3D(s, x2 + off, y2, z1 - offZ, textColor, fontSize)); jRenderer3D.addLine3D(new Line3D(x1, y1, z1, x1, y1, z2, lineColor, true)); jRenderer3D.addLine3D(new Line3D(x2, y2, z1, x2, y2, z2, lineColor)); jRenderer3D.addLine3D(new Line3D(x1, y1, z1, x2, y2, z1, lineColor, true)); jRenderer3D.addLine3D(new Line3D(x1, y1, z2, x2, y2, z2, lineColor)); } numTicks = (int)Math.Round(imageWidth * scaleInit / ticksDist); stepValue = calcStepSize(scaledWidth, numTicks); y1 = 0; y2 = imageHeight; for (double value = 0; value <= scaledWidth; value += stepValue) { String s; if (Math.Floor(value) - value == 0) s = "" + (int)value; else s = "" + (int)Math.Round(value * 1000) / 1000; if (value + stepValue > scaledWidth || value == scaledWidth) { if (!units.Equals("pixels")) s = "x/" + units; else s = "x"; } pos = value * imageWidth / scaledWidth; x1 = x2 = pos; jRenderer3D.addText3D(new Text3D(s, x1, y1 - off, z1 - offZ, textColor, fontSize, 2)); jRenderer3D.addText3D(new Text3D(s, x2, y2 + off, z1 - offZ, textColor, fontSize)); jRenderer3D.addLine3D(new Line3D(x1, y1, z1, x1, y1, z2, lineColor, true)); jRenderer3D.addLine3D(new Line3D(x2, y2, z1, x2, y2, z2, lineColor)); jRenderer3D.addLine3D(new Line3D(x1, y1, z1, x2, y2, z1, lineColor, true)); jRenderer3D.addLine3D(new Line3D(x1, y1, z2, x2, y2, z2, lineColor)); } double d = maxZ - minZ; numTicks = (int)Math.Round(255 * zAspectRatio * scaleInit / (ticksDist / 1.3)); if (numTicks < 2) numTicks = 2; stepValue = calcStepSize(d, numTicks); x1 = 0; y1 = 0; x2 = imageWidth; y2 = imageHeight; double minStart = Math.Floor(minZ / stepValue) * stepValue; double delta = minStart - minZ; for (double value = 0; value + delta <= d; value += stepValue) { String s; if (Math.Floor(minStart + value) - (minStart + value) == 0) s = "" + (int)(minStart + value); else s = "" + (int)Math.Round((minStart + value) * 1000) / 1000; pos = ((value + delta) * id / d); if (pos >= 0) { z1 = z2 = pos; if (invertZ) z1 = z2 = 255 - pos; jRenderer3D.addText3D(new Text3D(s, x1 - off, y1 - off, z1, textColor, fontSize, 4)); jRenderer3D.addText3D(new Text3D(s, x2 + off, y2 + off, z2, textColor, fontSize)); jRenderer3D.addText3D(new Text3D(s, x1 - off, y2 + off, z1, textColor, fontSize)); jRenderer3D.addText3D(new Text3D(s, x2 + off, y1 - off, z2, textColor, fontSize)); jRenderer3D.addLine3D(new Line3D(x1, y1, z1, x1, y2, z2, lineColor, true)); jRenderer3D.addLine3D(new Line3D(x2, y1, z1, x2, y2, z2, lineColor)); jRenderer3D.addLine3D(new Line3D(x1, y1, z1, x2, y1, z2, lineColor, true)); jRenderer3D.addLine3D(new Line3D(x1, y2, z1, x2, y2, z2, lineColor)); } } double myvalue = d + stepValue / 1.3; String mys = " z"; double fontzoom = 1; pos = ((myvalue + delta) * id / d); if (pos >= 0) { z1 = z2 = pos; if (invertZ) z1 = z2 = 255 - pos; jRenderer3D.addText3D(new Text3D(mys, x1 - off, y1 - off, z1, textColor, fontSize * fontzoom, 4)); jRenderer3D.addText3D(new Text3D(mys, x2 + off, y2 + off, z2, textColor, fontSize * fontzoom)); jRenderer3D.addText3D(new Text3D(mys, x1 - off, y2 + off, z1, textColor, fontSize * fontzoom)); jRenderer3D.addText3D(new Text3D(mys, x2 + off, y1 - off, z2, textColor, fontSize * fontzoom)); } // add coordinate system jRenderer3D.add3DCube(0, 0, 0, imageWidth, imageHeight, id, lineColor); } double calcStepSize(double range, double targetSteps) { // Calculate an initial guess at step size double tempStep = range / targetSteps; // Get the magnitude of the step size double mag = Math.Floor(Math.Log(tempStep) / Math.Log(10)); double magPow = Math.Pow((double)10.0, mag); // Calculate most significant digit of the new step size double magMsd = ((int)(tempStep / magPow + .5)); // promote the MSD to either 1, 2, 4, or 5 if (magMsd > 6) // 5 magMsd = 10.0; else if (magMsd > 3) magMsd = 5.0; else if (magMsd > 2) magMsd = 4.0; else if (magMsd > 1) magMsd = 2.0; return magMsd * magPow; } private void createGUI() { mainPanel = createImagePanel(); frame.Controls.Add(mainPanel); } private PictureBox createImagePanel() { mainPanel = new PictureBox(); mainPanel.Dock = DockStyle.Fill; mainPanel.MouseDown += new MouseEventHandler(this.picMoveDownListener); mainPanel.MouseUp += new MouseEventHandler(this.picMoveUpListener); mainPanel.MouseMove += new MouseEventHandler(this.picMoveListener); mainPanel.DoubleClick += new EventHandler(this.picDoubleClickListener); return mainPanel; } private void picDoubleClickListener(object sender, EventArgs e) { jRenderer3D.setTransformRotationXYZ(0, 0, 0); renderAndUpdateDisplay(); } private void picMoveDownListener(object sender, MouseEventArgs e) { xStart = e.X; yStart = e.Y; xdiff = 0; ydiff = 0; drag = true; } private void picMoveUpListener(object sender, MouseEventArgs e) { drag = false; } private void picMoveListener(object sender, MouseEventArgs e) { if (drag) { if (draftDrawing) jRenderer3D.setSurfacePlotMode(JRenderer3D.SURFACEPLOT_DOTSNOLIGHT); int xAct = e.X; int yAct = e.Y; xdiff = xAct - xStart; ydiff = yAct - yStart; xStart = xAct; yStart = yAct; jRenderer3D.changeTransformRotationXZ(-ydiff / 2, xdiff / 2); rotationX = jRenderer3D.getTransformRotationX(); rotationZ = jRenderer3D.getTransformRotationZ(); renderAndUpdateDisplay(); } } private void readPrefs() { if (true) { // get screen dimensions //Toolkit toolkit = Toolkit.getDefaultToolkit(); //Dimension screenSize = toolkit.getScreenSize(); int screenWidth = Screen.PrimaryScreen.Bounds.Width; int screenHeight = Screen.PrimaryScreen.Bounds.Height; //Insets ins = frame.getInsets(); //xloc = (screenWidth-windowWidth-ins.left-ins.right - 70)/2; //yloc = (screenHeight-windowHeight-ins.bottom-ins.top - 75)/2; xloc = (screenWidth - windowWidth - 70) / 2; yloc = (screenHeight - windowHeight - 75) / 2; light = 0.0; perspective = 0.0; grid = 512; smooth = 43.0; plotType = 1;// FILLED; colorType = 1;// GRADIENT; drawAxes = true; drawLines = true; drawText = true; drawLegend = true; invertZ = false; isEqualxyzRatio = false; rotationX = 65; rotationZ = 39; scaleSlider = 1; zAspectRatioSlider = 1; minSlider = 0; maxSlider = 100; } else { /** int screenWidth = Screen.PrimaryScreen.Bounds.Width; int screenHeight = Screen.PrimaryScreen.Bounds.Height; xloc = (screenWidth - windowWidth - 70) / 2; yloc = (screenHeight - windowHeight - 75) / 2; //xloc = 541; // (int)Prefs.get("ISP3D.xloc", 100); //yloc = 95; // (int)Prefs.get("ISP3D.yloc", 50); light = 0.3; //Prefs.get("ISP3D.light", 0.2); perspective = 0.0; // Prefs.get("ISP3D.perspective", 0); grid = 256; // (int)Prefs.get("ISP3D.grid", 256); smooth = 22.0; // Prefs.get("ISP3D.smooth", 0); plotType = 1;// (int)Prefs.get("ISP3D.plotType", LINES); colorType = 1;// (int)Prefs.get("ISP3D.colorType", ORIGINAL); drawAxes = true;//Prefs.get("ISP3D.drawAxes", true); drawLines = true;//Prefs.get("ISP3D.drawLines", true); drawText = true;//Prefs.get("ISP3D.drawText", true); drawLegend = true;//Prefs.get("ISP3D.drawLegend", true); invertZ = false;//Prefs.get("ISP3D.invertZ", false); isEqualxyzRatio = false;//Prefs.get("ISP3D.isEqualxyzRatio", false); rotationX = 359;// Prefs.get("ISP3D.rotationX", 65); rotationZ = -1.5;// Prefs.get("ISP3D.rotationZ", 39); windowHeight = 600;// (int)Prefs.get("ISP3D.windowHeight", windowHeight); windowWidth = 720;// (int)Prefs.get("ISP3D.windowWidth", windowWidth); scaleSlider = 1.01;// Prefs.get("ISP3D.scale", scaleSlider); zAspectRatioSlider = 2.8138;// Prefs.get("ISP3D.zScale", zAspectRatioSlider); minSlider = 0;// Math.min(Math.max((int)Prefs.get("ISP3D.min", minSlider), 0), 99); maxSlider = 100;// Math.min(Math.max((int)Prefs.get("ISP3D.max", maxSlider), 1), 100); bgColor = Color.Gray;//new Color((int)Prefs.get("ISP3D.bgColor", Color.GRAY.getRGB())); lineColor = Color.White;// new Color((int)Prefs.get("ISP3D.lineColor", Color.WHITE.getRGB())); **/ } } } }