using OpenCvSharp; using System; using System.Drawing; using System.Drawing.Imaging; using System.IO; namespace PaintDotNet.Data.SurfacePlot { class SurfacePlot { private int gridWidth = 256; private int gridHeight = 256; private SurfacePlotData[] plotList = null; //Bitmap image; private int[] bufferPixels; private double[] zbufferPixels; private int bufferWidth; private int bufferHeight; private int lutNr = JRenderer3D.LUT_ORIGINAL; public Lut lut; private Transform tr; private double light; private int surfacePlotMode; private double xCenter; private double yCenter; private double zCenter; private int min = 0; private int max = 100; private int inversefactor = 1; private int[] pixelsOrigColor; private int[] pixelsOrigLum; private int widthOrig; private int heightOrig; private int widthTex; private int heightTex; private int[] pixelsTexColor; //private byte[] maskPixels; public bool hasOtherLut = false; public void draw() { surfacePlotLines(); /** if (surfacePlotMode == JRenderer3D.SURFACEPLOT_FILLED) surfacePlotFilled(); else if (surfacePlotMode == JRenderer3D.SURFACEPLOT_ISOLINES) surfacePlotIsoLines(); else if (surfacePlotMode == JRenderer3D.SURFACEPLOT_MESH) surfacePlotMesh(); else if (surfacePlotMode == JRenderer3D.SURFACEPLOT_LINES) surfacePlotLines(); else if (surfacePlotMode == JRenderer3D.SURFACEPLOT_DOTS) surfacePlotDots(); else if (surfacePlotMode == JRenderer3D.SURFACEPLOT_DOTSNOLIGHT) surfacePlotDotsNoLight(); **/ } public unsafe void setSurfacePlotImage(Bitmap imp) { int widthTmp = imp.Width; int heightTmp = imp.Height; int[] pixelsTmp = new int[widthTmp * heightTmp]; Mat mat = OpenCvSharp.Extensions.BitmapConverter.ToMat(imp); lut = new Lut(); int kk = 0; for (int i = 0; i < mat.Rows; i++) { for (int j = 0; j < mat.Cols; j++) { pixelsTmp[kk] = mat.At(i, j); kk++; } } bool isLut = false; //ip.isColorLut(); if (isLut) { lut.readLut(imp); hasOtherLut = true; } byte[] lutPixels = null; int bitDepth = Image.GetPixelFormatSize(imp.PixelFormat); //Depth(); if (isLut) { if (bitDepth == 8) { lutPixels = ToByteArray(imp);//.(byte[])ip.getPixels(); } else { lutPixels = new byte[widthTmp * heightTmp]; double min_ = 0; //ip.getMin(); double max_ = 255; //ip.getMax(); double a = 0, b = 1; /** Calibration cal = imp.getCalibration(); if (cal != null) { if (cal.calibrated()) { min_ = cal.getCValue((int)min_); max_ = cal.getCValue((int)max_); double[] coef = cal.getCoefficients(); if (coef != null) { a = coef[0]; b = coef[1]; } } } **/ float scale = (float)(255f / (max_ - min_)); if (bitDepth == 16) { byte[] pixels = ToByteArray(imp); int pos = 0; for (int y = 0; y < heightTmp; y++) { for (int x = 0; x < widthTmp; x++) { int val = (int)((int)(0xFFFF & pixels[pos++]) * b + a - min_); if (val < 0f) val = 0; val = (int)(val * scale); if (val > 255) val = 255; lutPixels[y * widthTmp + x] = (byte)(val); } } } if (bitDepth == 32) { byte[] pixels = ToByteArray(imp); int pos = 0; for (int y = 0; y < heightTmp; y++) { for (int x = 0; x < widthTmp; x++) { // float value = (float) (pixels[pos++] - min); float value = (float)(pixels[pos++] - min_); // LL ============== if (value < 0f) value = 0f; int ivalue = (int)(value * scale); if (ivalue > 255) ivalue = 255; lutPixels[y * widthTmp + x] = (byte)(ivalue); } } } } } Mat roi = null;//.getRoi(); if (roi != null) { /** ImageProcessor mask = roi.getMask(); ImageProcessor ipMask; maskPixels = null; if (mask != null) { ipMask = mask.duplicate(); maskPixels = (byte[])ipMask.getPixels(); } Rectangle rect = new Rectangle(); //roi.getBounds(); if (rect.X < 0) rect.X = 0; if (rect.Y < 0) rect.Y = 0; widthOrig = rect.Width; heightOrig = rect.Height; pixelsOrigColor = new int[widthOrig * heightOrig]; pixelsOrigLum = new int[widthOrig * heightOrig]; for (int j = 0, y = rect.Y; y < rect.Y + rect.Height; y++) { int offset = y * widthTmp; for (int x = rect.X; x < rect.X + rect.Width; x++, j++) { int i = offset + x; int c = pixelsOrigColor[j] = pixelsTmp[i]; int lum; if (!isLut) { int r = ((c >> 16) & 255); int g = ((c >> 8) & 255); int b = ((c) & 255); lum = (int)(0.299 * r + 0.587 * g + 0.114 * b); } else lum = (int)(0xFF & lutPixels[i]); pixelsOrigLum[j] = lum; } }**/ } else { widthOrig = widthTmp; heightOrig = heightTmp; pixelsOrigColor = new int[widthOrig * heightOrig]; pixelsOrigLum = new int[widthOrig * heightOrig]; for (int y = 0; y < heightTmp; y++) { for (int x = 0; x < widthTmp; x++) { int pos = y * widthTmp + x; int c = pixelsOrigColor[pos] = pixelsTmp[pos]; int lum; int r = ((c >> 16) & 255); int g = ((c >> 8) & 255); int b = ((c) & 255); if (!isLut) { lum = (int)Math.Round(0.299 * r + 0.587 * g + 0.114 * b); } else { lum = lutPixels[pos]; //(int)(0xFF & lutPixels[pos]); } pixelsOrigLum[pos] = lum; } } } } public void setSurfacePlotTextureImage(Bitmap imp) { widthTex = imp.Width; heightTex = imp.Height; pixelsTexColor = new int[widthTex * heightTex]; /** image = imp; int kk = 0; for (int i = 0; i < image.Width; i++) { for (int j = 0; j < image.Height; j++) { pixelsTexColor[kk] = image.GetPixel(i, j).ToArgb(); kk++; } } **/ /** PixelGrabber pg = new PixelGrabber(image, 0, 0, widthTex, heightTex, pixelsTexColor, 0, widthTex); try { pg.grabPixels(); } catch (Exception ex) { //---IJ.error("error grabbing pixels"); pixelsTexColor = null; } **/ } public void resample() { plotList = new SurfacePlotData[gridWidth * gridHeight]; if (pixelsOrigColor != null && pixelsOrigLum != null) { double xOffset = xCenter; double yOffset = yCenter; double sx = widthOrig / (double)gridWidth; double sy = heightOrig / (double)gridHeight; for (int y = 0; y < gridHeight; y++) { int yB = (int)(y * sy); for (int x = 0; x < gridWidth; x++) { int posGrid = y * gridWidth + x; int xB = (int)(x * sx); int posOrig = yB * widthOrig + xB; plotList[posGrid] = new SurfacePlotData(); plotList[posGrid].color = pixelsOrigColor[posOrig]; plotList[posGrid].x = sx * (x + 0.5) - xOffset; plotList[posGrid].y = sy * (y + 0.5) - yOffset; plotList[posGrid].z = plotList[posGrid].zf = plotList[posGrid].lum = pixelsOrigLum[posOrig] - zCenter; /** if (maskPixels != null) { if (maskPixels[posOrig] != 0) plotList[posGrid].isVisible = true; else plotList[posGrid].isVisible = false; } else**/ plotList[posGrid].isVisible = true; } } } if (pixelsTexColor != null) { double sx = widthTex / (double)gridWidth; double sy = heightTex / (double)gridHeight; for (int y = 0; y < gridHeight; y++) { int yB = (int)(y * sy); for (int x = 0; x < gridWidth; x++) { int pos = y * gridWidth + x; int xB = (int)(x * sx); plotList[pos].color = pixelsTexColor[yB * widthTex + xB]; } } } computeNormals(); } private void computeNormals() { for (int y = 0; y < gridHeight; y++) { for (int x = 0; x < gridWidth; x++) { int i = y * gridWidth + x; double dx1 = 0; double dy1 = 0; double dz1 = 0; for (int y_ = -1; y_ <= 1; y_++) { int yn = y + y_; if (yn < 0) yn = 0; if (yn >= gridHeight) yn = gridHeight - 1; for (int x_ = -1; x_ < 1; x_++) { int xn = x + x_; if (xn < 0) xn = 0; if (xn >= gridWidth) xn = gridWidth - 1; int xn1 = xn + 1; if (xn1 < 0) xn1 = 0; if (xn1 >= gridWidth) xn1 = gridWidth - 1; int posn = yn * gridWidth + xn; int posn1 = yn * gridWidth + xn1; dx1 += plotList[posn1].x - plotList[posn].x; dz1 += plotList[posn1].z - plotList[posn].z; } } double dx2 = 0; double dy2 = 0; double dz2 = 0; for (int y_ = -1; y_ < 1; y_++) { int yn = y + y_; if (yn < 0) yn = 0; if (yn >= gridHeight) yn = gridHeight - 1; int yn1 = yn + 1; if (yn1 < 0) yn1 = 0; if (yn1 >= gridHeight) yn1 = gridHeight - 1; for (int x_ = -1; x_ <= 1; x_++) { int xn = x + x_; if (xn < 0) xn = 0; if (xn >= gridWidth) xn = gridWidth - 1; int posn = yn * gridWidth + xn; int posn1 = yn1 * gridWidth + xn; dy2 += plotList[posn1].y - plotList[posn].y; dz2 += plotList[posn1].z - plotList[posn].z; } } // outer product double dx = (dy1 * dz2 - dz1 * dy2); double dy = (dz1 * dx2 - dx1 * dz2); double dz = (dx1 * dy2 - dy1 * dx2); double len = Math.Sqrt(dx * dx + dy * dy + dz * dz); plotList[i].dx = dx / len; plotList[i].dy = dy / len; plotList[i].dz = dz / len; } } } public void applyMinMax() { //System.out.println("applyMinMax inverseFactor: " + inversefactor); int add = 0; if (inversefactor == -1) add = -1; for (int i = 0; i < gridHeight * gridWidth; i++) { double val = (100 * (plotList[i].zf + zCenter - 2.55 * (min)) / (max - min) - zCenter); plotList[i].z = inversefactor * Math.Min(Math.Max(-128, val), 127) + add; } computeNormals(); } public void applySmoothingFilter(double rad) { float[] pixels = new float[gridHeight * gridWidth]; for (int i = 0; i < gridHeight * gridWidth; i++) { pixels[i] = (float)plotList[i].lum; } /** ImageProcessor ip = new FloatProcessor(gridWidth, gridHeight, pixels, null); new GaussianBlur().blur(ip, rad); pixels = (float[])ip.getPixels(); for (int i = 0; i < gridHeight * gridWidth; i++) { plotList[i].z = plotList[i].zf = pixels[i]; } applyMinMax(); **/ } public static byte[] ToByteArray(Bitmap bmp) { MemoryStream ms = new MemoryStream(); bmp.Save(ms, ImageFormat.Jpeg); ms.Seek(0, SeekOrigin.Begin); //一定不要忘记将流的初始位置重置 //byte[] bytes = new byte[ms.Length]; byte[] bytes = new byte[bmp.Height * bmp.Width]; ms.Read(bytes, 0, bytes.Length); //如果上面流没有seek 则这里读取的数据全会为0 ms.Dispose(); return bytes; } /************************************************************************************** * * Drawing Routines * **************************************************************************************/ private int getColor(SurfacePlotData p0) { int c0 = p0.color; /** if (lutNr == JRenderer3D.LUT_ORIGINAL) { c0 = p0.color; } else if (lutNr == JRenderer3D.LUT_GRADIENT) { c0 = ((int)(p0.dx * 127 + 127) << 16) | ((int)(p0.dy * 127 + 127) << 8) | (int)(p0.dz * 127 + 127); } else if (lutNr == JRenderer3D.LUT_GRADIENT2) { c0 = ((int)(p0.dx2 * 127 + 127) << 16) | ((int)(p0.dy2 * 127 + 127) << 8) | (int)(0); } else { int index = (int)(p0.z + 128); if (index > 255) index = 255; if (index < 0) index = 0; c0 = lut.colors[index]; } **/ return c0; } private void surfacePlotFilled() { for (int row = 0; row < gridHeight - 1; row++) { for (int col = 0; col < gridWidth - 1; col++) { int i = row * gridWidth + col; SurfacePlotData p0 = plotList[i]; if (p0.isVisible) { SurfacePlotData p1 = plotList[i + 1]; SurfacePlotData p2 = plotList[i + gridWidth]; SurfacePlotData p3 = plotList[i + gridWidth + 1]; if (p1.isVisible && p2.isVisible && p3.isVisible) { tr.transform(p0); double x0 = tr.X, y0 = tr.Y, z0 = tr.Z; tr.x = p0.dx; tr.y = p0.dy; double light0 = tr.getScalarProduct(); tr.transform(p1); double x1 = tr.X, y1 = tr.Y, z1 = tr.Z; tr.x = p1.dx; tr.y = p1.dy; double light1 = tr.getScalarProduct(); tr.transform(p2); double x2 = tr.X, y2 = tr.Y, z2 = tr.Z; tr.x = p2.dx; tr.y = p2.dy; double light2 = tr.getScalarProduct(); tr.transform(p3); double x3 = tr.X, y3 = tr.Y, z3 = tr.Z; tr.x = p3.dx; tr.y = p3.dy; double light3 = tr.getScalarProduct(); if (!(x0 >= bufferWidth && x0 < 0 && y0 >= bufferHeight && y0 < 0 && x1 >= bufferWidth && x1 < 0 && y1 >= bufferHeight && y1 < 0 && x2 >= bufferWidth && x2 < 0 && y2 >= bufferHeight && y2 < 0 && x3 >= bufferWidth && x3 < 0 && y3 >= bufferHeight && y3 < 0)) { int c0 = getColor(p0); int c1 = getColor(p1); int c2 = getColor(p2); int c3 = getColor(p3); int r0 = ((c0 >> 16) & 0xff); int g0 = ((c0 >> 8) & 0xff); int b0 = ((c0) & 0xff); int r1 = ((c1 >> 16) & 0xff); int g1 = ((c1 >> 8) & 0xff); int b1 = ((c1) & 0xff); int r2 = ((c2 >> 16) & 0xff); int g2 = ((c2 >> 8) & 0xff); int b2 = ((c2) & 0xff); int r3 = ((c3 >> 16) & 0xff); int g3 = ((c3 >> 8) & 0xff); int b3 = ((c3) & 0xff); double n13 = Math.Abs(y1 - y3) + Math.Abs(x1 - x3); double n02 = Math.Abs(y0 - y2) + Math.Abs(x0 - x2); // double n13 = Math.sqrt((y1-y3)*(y1-y3) + (x1-x3)*(x1-x3)); // double n02 = Math.sqrt((y0-y2)*(y0-y2) + (x0-x2)*(x0-x2)); int stepsY = (int)(Math.Max(n13, n02) + 1); double dy = 1 / stepsY; double dx02 = (x2 - x0) * dy; double dy02 = (y2 - y0) * dy; double dx13 = (x3 - x1) * dy; double dy13 = (y3 - y1) * dy; double x02 = x0; double y02 = y0; double x13 = x1; double y13 = y1; double v = 0; for (int sy = 0; sy < stepsY; sy++, v += dy) { x02 += dx02; y02 += dy02; x13 += dx13; y13 += dy13; //int stepsX = (int) (Math.abs(x02-x13) + Math.abs(y02-y13) + 1); int stepsX = (int)(Math.Abs(x02 - x13) + Math.Abs(y02 - y13) + 1); double dx = 1 / stepsX; double dx0213 = (x13 - x02) * dx; double dy0213 = (y13 - y02) * dx; double x0213 = x02; double y0213 = y02; double h = 0; for (int sx = 0; sx < stepsX; sx++, h += dx) { x0213 += dx0213; y0213 += dy0213; if (x0213 >= 0 && x0213 < bufferWidth && y0213 >= 0 && y0213 < bufferHeight) { double d0 = (1 - h) * (1 - v); double d1 = h * (1 - v); double d2 = (1 - h) * v; double d3 = h * v; double z = d0 * z0 + d1 * z1 + d2 * z2 + d3 * z3; // System.out.println("x: " + (int)x0213 + " y: " + (int)y0213); int pos = (int)y0213 * bufferWidth + (int)x0213; if (z < zbufferPixels[pos]) { zbufferPixels[pos] = z; int r = (int)(r3 * d3 + r2 * d2 + r1 * d1 + r0 * d0); int g = (int)(g3 * d3 + g2 * d2 + g1 * d1 + g0 * d0); int b = (int)(b3 * d3 + b2 * d2 + b1 * d1 + b0 * d0); double light0123 = d3 * light3 + d2 * light2 + d1 * light1 + d0 * light0; double l = -light * light0123 * 255; r = (int)Math.Min(255, Math.Max(0, r + l)); g = (int)Math.Min(255, Math.Max(0, g + l)); b = (int)Math.Min(255, Math.Max(0, b + l)); uint temp = (uint)(0xff000000 | (uint)(r << 16) | (uint)(g << 8) | (uint)b); bufferPixels[pos] = (int)temp;//(0xff000000 | (r << 16) | (g << 8) | b); } } } } } } } } } } private void surfacePlotIsoLines() { for (int row = 0; row < gridHeight - 1; row++) { for (int col = 0; col < gridWidth - 1; col++) { int i = row * gridWidth + col; SurfacePlotData p0 = plotList[i]; if (p0.isVisible) { SurfacePlotData p1 = plotList[i + 1]; SurfacePlotData p2 = plotList[i + gridWidth]; SurfacePlotData p3 = plotList[i + gridWidth + 1]; if ((p1.isVisible) && (p2.isVisible) && (p3.isVisible)) { tr.transform(p0); double x0 = tr.X, y0 = tr.Y, z0 = tr.Z; tr.x = p0.dx; tr.y = p0.dy; double light0 = tr.getScalarProduct(); tr.transform(p1); double x1 = tr.X, y1 = tr.Y, z1 = tr.Z; tr.x = p1.dx; tr.y = p1.dy; double light1 = tr.getScalarProduct(); tr.transform(p2); double x2 = tr.X, y2 = tr.Y, z2 = tr.Z; tr.x = p2.dx; tr.y = p2.dy; double light2 = tr.getScalarProduct(); tr.transform(p3); double x3 = tr.X, y3 = tr.Y, z3 = tr.Z; tr.x = p3.dx; tr.y = p3.dy; double light3 = tr.getScalarProduct(); if (!(x0 >= bufferWidth && x0 < 0 && y0 >= bufferHeight && y0 < 0 && x1 >= bufferWidth && x1 < 0 && y1 >= bufferHeight && y1 < 0 && x2 >= bufferWidth && x2 < 0 && y2 >= bufferHeight && y2 < 0 && x3 >= bufferWidth && x3 < 0 && y3 >= bufferHeight && y3 < 0)) { int c0 = getColor(p0); int c1 = getColor(p1); int c2 = getColor(p2); int c3 = getColor(p3); double lum0 = p0.z; double lum1 = p1.z; double lum2 = p2.z; double lum3 = p3.z; int r0 = ((c0 >> 16) & 0xff); int g0 = ((c0 >> 8) & 0xff); int b0 = ((c0) & 0xff); int r1 = ((c1 >> 16) & 0xff); int g1 = ((c1 >> 8) & 0xff); int b1 = ((c1) & 0xff); int r2 = ((c2 >> 16) & 0xff); int g2 = ((c2 >> 8) & 0xff); int b2 = ((c2) & 0xff); int r3 = ((c3 >> 16) & 0xff); int g3 = ((c3 >> 8) & 0xff); int b3 = ((c3) & 0xff); double n13 = Math.Abs(x1 - x3) + Math.Abs(y1 - y3); double n02 = Math.Abs(x0 - x2) + Math.Abs(y0 - y2); int stepsY = (int)(Math.Max(n13, n02) + 1); double dy = 1 / stepsY; double dx02 = (x2 - x0) * dy; double dy02 = (y2 - y0) * dy; double dx13 = (x3 - x1) * dy; double dy13 = (y3 - y1) * dy; double x02 = x0; double y02 = y0; double x13 = x1; double y13 = y1; double v = 0; for (int sy = 0; sy < stepsY; sy++, v += dy) { x02 += dx02; y02 += dy02; x13 += dx13; y13 += dy13; int stepsX = (int)(Math.Abs(x02 - x13) + Math.Abs(y02 - y13) + 1); double dx = 1 / stepsX; double dx0213 = (x13 - x02) * dx; double dy0213 = (y13 - y02) * dx; double x0213 = x02; double y0213 = y02; double h = 0; for (int sx = 0; sx < stepsX; sx++, h += dx) { x0213 += dx0213; y0213 += dy0213; double d0 = (1 - h) * (1 - v); double d1 = h * (1 - v); double d2 = (1 - h) * v; double d3 = h * v; double z = d0 * z0 + d1 * z1 + d2 * z2 + d3 * z3; if (x0213 >= 0 && x0213 < bufferWidth && y0213 >= 0 && y0213 < bufferHeight) { int pos = (int)y0213 * bufferWidth + (int)x0213; if (z < zbufferPixels[pos]) { double lum = d0 * lum0 + d1 * lum1 + d2 * lum2 + d3 * lum3 + 132; if (lum - 12 * (int)(lum / 12) < 1.5) { zbufferPixels[pos] = z; int r = (int)(r3 * d3 + r2 * d2 + r1 * d1 + r0 * d0); int g = (int)(g3 * d3 + g2 * d2 + g1 * d1 + g0 * d0); int b = (int)(b3 * d3 + b2 * d2 + b1 * d1 + b0 * d0); double light0123 = d3 * light3 + d2 * light2 + d1 * light1 + d0 * light0; double l = -light * light0123 * 255; r = (int)Math.Min(255, Math.Max(0, r + l)); g = (int)Math.Min(255, Math.Max(0, g + l)); b = (int)Math.Min(255, Math.Max(0, b + l)); //uint temp = (uint)(0xff000000 | (uint)(r << 16) | (uint)(g << 8) | (uint)b); bufferPixels[pos] = (int)(((uint)r << 16) | (ushort)(((ushort)g << 8) | b)); //bufferPixels[pos] = (int)temp;// (0xff000000 | (r << 16) | (g << 8) | b); } } } } } } } } } } } private void surfacePlotMesh() { for (int row = 0; row < gridHeight; row++) { for (int col = 0; col < gridWidth; col++) { int i = row * gridWidth + col; SurfacePlotData p0 = plotList[i]; int r0, g0, b0, r1, g1, b1, r2, g2, b2; if (p0.isVisible) { tr.transform(p0); double x0 = tr.X, y0 = tr.Y, z0 = tr.Z; int c0 = getColor(p0); r0 = ((c0 >> 16) & 0xff); g0 = ((c0 >> 8) & 0xff); b0 = ((c0) & 0xff); SurfacePlotData p1 = (col < gridWidth - 1) ? plotList[i + 1] : plotList[i]; if (p1.isVisible) { tr.transform(p1); double x1 = tr.X, y1 = tr.Y, z1 = tr.Z; double dx10 = x1 - x0, dy10 = y1 - y0, dz10 = z1 - z0; int c1 = getColor(p1); r1 = ((c1 >> 16) & 0xff); g1 = ((c1 >> 8) & 0xff); b1 = ((c1) & 0xff); int numSteps = (int)(Math.Max(Math.Abs(dx10), Math.Abs(dy10)) + 1); double step = 1 / numSteps; for (int s = 0; s < numSteps; s++) { double f = s * step; int x = (int)(x0 + f * dx10); int y = (int)(y0 + f * dy10); if (x >= 0 && y >= 0 && x < bufferWidth && y < bufferHeight) { int pos = y * bufferWidth + x; int z = (int)(z0 + f * dz10); if (z < zbufferPixels[pos]) { zbufferPixels[pos] = z; int r = (int)(f * r1 + (1 - f) * r0); int g = (int)(f * g1 + (1 - f) * g0); int b = (int)(f * b1 + (1 - f) * b0); tr.x = p0.dx; tr.y = p0.dy; double l = -light * tr.getScalarProduct() * 255; r = (int)Math.Min(255, Math.Max(0, r + l)); g = (int)Math.Min(255, Math.Max(0, g + l)); b = (int)Math.Min(255, Math.Max(0, b + l)); bufferPixels[pos] = (int)(((uint)r << 16) | (ushort)(((ushort)g << 8) | b)); //uint temp = (uint)(0xff000000 | (uint)(r << 16) | (uint)(g << 8) | (uint)b); //bufferPixels[pos] = (int)temp; //(int)(0xff000000 | (r << 16) | (g << 8) | b); } } } } SurfacePlotData p2 = (row < gridHeight - 1) ? plotList[i + gridWidth] : plotList[i]; if (p2.isVisible) { tr.transform(p2); double x2 = tr.X, y2 = tr.Y, z2 = tr.Z; double dx20 = x2 - x0, dy20 = y2 - y0, dz20 = z2 - z0; int c2 = getColor(p2); r2 = ((c2 >> 16) & 0xff); g2 = ((c2 >> 8) & 0xff); b2 = ((c2) & 0xff); int numSteps = (int)(Math.Max(Math.Abs(dx20), Math.Abs(dy20)) + 1); double step = 1 / numSteps; for (int s = 0; s < numSteps; s++) { double f = s * step; int x = (int)(x0 + f * dx20); int y = (int)(y0 + f * dy20); if (x >= 0 && y >= 0 && x < bufferWidth && y < bufferHeight) { int pos = y * bufferWidth + x; int z = (int)(z0 + f * dz20); if (z < zbufferPixels[pos]) { zbufferPixels[pos] = z; int r = (int)(f * r2 + (1 - f) * r0); int g = (int)(f * g2 + (1 - f) * g0); int b = (int)(f * b2 + (1 - f) * b0); tr.x = p0.dx; tr.y = p0.dy; double l = -light * tr.getScalarProduct() * 255; r = (int)Math.Min(255, Math.Max(0, r + l)); g = (int)Math.Min(255, Math.Max(0, g + l)); b = (int)Math.Min(255, Math.Max(0, b + l)); bufferPixels[pos] = (int)(((uint)r << 16) | (ushort)(((ushort)g << 8) | b)); /** uint temp = (uint)(0xff000000 | (uint)(r << 16) | (uint)(g << 8) | (uint)b); bufferPixels[pos] = (int)(temp); **/ } } } } } } } } private void surfacePlotLines() { for (int row = 0; row < gridHeight; row++) { for (int col = 0; col < gridWidth - 1; col++) { int i = row * gridWidth + col; SurfacePlotData p0 = plotList[i]; SurfacePlotData p1 = plotList[i + 1]; if (p0.isVisible && p1.isVisible) { tr.transform(p0); double x0 = tr.X, y0 = tr.Y, z0 = tr.Z; int c0 = getColor(p0); int r0 = ((c0 >> 16) & 0xff); int g0 = ((c0 >> 8) & 0xff); int b0 = ((c0) & 0xff); tr.transform(p1); double x1 = tr.X, y1 = tr.Y, z1 = tr.Z; double dx1 = x1 - x0, dy1 = y1 - y0, dz1 = z1 - z0; int numSteps = (int)(Math.Max(Math.Abs(dx1), Math.Abs(dy1)) + 1); int c1 = getColor(p1); int r1 = ((c1 >> 16) & 0xff); int g1 = ((c1 >> 8) & 0xff); int b1 = ((c1) & 0xff); double step = 1 / numSteps; int r, g, b; for (int s = 0; s < numSteps; s++) { double f = s * step; int x = (int)(x0 + f * dx1); int y = (int)(y0 + f * dy1); if (x >= 0 && y >= 0 && x < bufferWidth && y < bufferHeight) { int pos = y * bufferWidth + x; double z = z0 + f * dz1; if (z < zbufferPixels[pos]) { zbufferPixels[pos] = z; r = (int)((1 - f) * r0 + f * r1); g = (int)((1 - f) * g0 + f * g1); b = (int)((1 - f) * b0 + f * b1); tr.x = p0.dx; tr.y = p0.dy; double l = -light * tr.getScalarProduct() * 255; r = (int)Math.Min(255, Math.Max(0, r + l)); g = (int)Math.Min(255, Math.Max(0, g + l)); b = (int)Math.Min(255, Math.Max(0, b + l)); bufferPixels[pos] = (int)(((uint)r << 16) | (ushort)(((ushort)g << 8) | b)); /* long lv = (0xff000000 | (r << 16) | (g << 8) | b); if (lv > int.MaxValue) { bufferPixels[pos] = int.MaxValue; } else { bufferPixels[pos] = (int)lv; }**/ } } } } } } } private void surfacePlotDots() { for (int i = plotList.Length - 1; i >= 0; i--) { SurfacePlotData p0 = plotList[i]; if (p0.isVisible) { tr.transform(p0); int x = (int)tr.X, y = (int)tr.Y; if (x >= 0 && y >= 0 && x < bufferWidth && y < bufferHeight) { int pos = y * bufferWidth + x; int z = (int)tr.Z; if (z < zbufferPixels[pos]) { zbufferPixels[pos] = z; int c0 = getColor(p0); int r0 = ((c0 >> 16) & 0xff); int g0 = ((c0 >> 8) & 0xff); int b0 = ((c0) & 0xff); tr.x = p0.dx; tr.y = p0.dy; double l = -light * tr.getScalarProduct() * 255; int r = (int)Math.Min(255, Math.Max(0, r0 + l)); int g = (int)Math.Min(255, Math.Max(0, g0 + l)); int b = (int)Math.Min(255, Math.Max(0, b0 + l)); uint temp = (uint)(0xff000000 | (uint)(r << 16) | (uint)(g << 8) | (uint)b); bufferPixels[pos] = (int)temp; //(int)(0xff000000 | (r << 16) | (g << 8) | b); } } } } } public void surfacePlotDotsNoLight() { int delta = Math.Max(gridHeight, gridWidth) / 128; if (delta < 1) delta = 1; for (int row = 0; row < gridHeight; row += delta) { for (int col = 0; col < gridWidth; col += delta) { int i = row * gridWidth + col; SurfacePlotData p0 = plotList[i]; if (p0.isVisible) { tr.transform(p0); int x = (int)tr.X; int y = (int)tr.Y; if (x >= 0 && y >= 0 && x < bufferWidth - 1 && y < bufferHeight - 1) { int pos = y * bufferWidth + x; int z = (int)tr.Z; if (z < zbufferPixels[pos]) { int c0 = (int)(0xFF000000 | getColor(p0)); zbufferPixels[pos] = z; zbufferPixels[pos + 1] = z; zbufferPixels[pos + bufferWidth] = z; zbufferPixels[pos + bufferWidth + 1] = z; bufferPixels[pos] = c0; bufferPixels[pos + 1] = c0; bufferPixels[pos + bufferWidth] = c0; bufferPixels[pos + bufferWidth + 1] = c0; } } } } } } public void setSurfacePLotSetLight(double light) { this.light = light; } public void setSurfaceGridSize(int width, int height) { this.gridWidth = width; this.gridHeight = height; } public void setSurfacePlotMode(int surfacePlotMode) { this.surfacePlotMode = surfacePlotMode; } public void setBuffers(int[] bufferPixels, double[] zbufferPixels, int bufferWidth, int bufferHeight) { this.bufferPixels = bufferPixels; this.zbufferPixels = zbufferPixels; this.bufferWidth = bufferWidth; this.bufferHeight = bufferHeight; } public void setTransform(Transform transform) { this.tr = transform; } public void setSurfacePlotCenter(double xCenter, double yCenter, double zCenter) { this.xCenter = xCenter; this.yCenter = yCenter; this.zCenter = zCenter; } public void setSurfacePlotLut(int lutNr) { this.lutNr = lutNr; if (lut != null) lut.setLut(lutNr); } public int getSurfacePlotLut() { return lut.getLutNr(); } public void setMinMax(int min, int max) { this.min = min; this.max = max; } public void setInverse(bool b) { inversefactor = (b) ? -1 : 1; for (int i = 0; i < plotList.Length; i++) plotList[i].z = inversefactor * plotList[i].zf; } public int getInversefactor() { return inversefactor; } } }