JRenderer3D.cs 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248
  1. using System;
  2. using System.Collections;
  3. using System.Drawing;
  4. using System.Drawing.Drawing2D;
  5. using System.Drawing.Imaging;
  6. namespace PaintDotNet.Data.SurfacePlot
  7. {
  8. unsafe class JRenderer3D
  9. {
  10. SolidBrush brush = new SolidBrush(Color.Blue);
  11. SolidBrush brush1 = new SolidBrush(Color.White);
  12. Pen pen = new Pen(Color.Blue);
  13. Pen pen1 = new Pen(Color.Red);
  14. IntPtr ptr;
  15. BitmapData bmpData;
  16. int bytes;
  17. byte[] rgbValues;
  18. Rectangle rect;
  19. private Bitmap bufferedImage = null;
  20. private Graphics g2D = null;
  21. private int[] bufferPixels = null; // render buffer
  22. private double[] zbufferPixels = null; // Z-buffer
  23. private int bufferWidth = 512; // size of the buffers
  24. private int bufferHeight = 512;
  25. // Global rendering parameters
  26. private Color backgroundColor = Color.Gray;
  27. private Color legendTextColor = Color.White;
  28. // transform parameters
  29. private Transform transform = null; // the actual transformation
  30. private double tr_rotationX = 1.34;
  31. private double tr_rotationY = 0;
  32. private double tr_rotationZ = 1;
  33. private double tr_perspective = 0;
  34. private double tr_maxDistance = 256;
  35. private int zOrientation = -1;
  36. private double scale = 1;
  37. private double zAspectRatio = 1;
  38. private double xCenter = 0; // the x, y, and z - coordinates of the rotation center
  39. private double yCenter = 0;
  40. private double zCenter = 0;
  41. // objects to be drawn
  42. private ArrayList lines3D = null;
  43. private ArrayList cubeLines3D = null;
  44. private ArrayList text3D = null;
  45. // 3D points
  46. private PointsPlot pointsPlot = null;
  47. /**
  48. * Draws a point as a sphere (slowest).
  49. */
  50. public static int POINT_SPHERE = Point3D.SPHERE;
  51. /**
  52. * Draws a point as a (2D) circle.
  53. */
  54. public static int POINT_CIRCLE = Point3D.CIRCLE;
  55. /**
  56. * Draws a point as a dot. Size information has no effect.
  57. */
  58. public static int POINT_DOT = Point3D.DOT;
  59. // surfacePlot constants & parameters
  60. private static int SURFACEGRID_DEFAULTWIDTH = 256;
  61. private static int SURFACEGRID_DEFAULTHEIGHT = 256;
  62. /**
  63. * Draws a surface plot using only dots, no illumination is used (fastest mode).
  64. */
  65. public static int SURFACEPLOT_DOTSNOLIGHT = 10;
  66. /**
  67. * Draws a surface plot using only dots, illumination is active.
  68. */
  69. public static int SURFACEPLOT_DOTS = 11;
  70. /**
  71. * Draws a surface plot using lines. Number of lines can be adjusted.
  72. */
  73. public static int SURFACEPLOT_LINES = 12;
  74. /**
  75. * Draws a surface plot using a mesh. Mesh size can be adapted.
  76. */
  77. public static int SURFACEPLOT_MESH = 13;
  78. /**
  79. * Draws a filled surface plot .
  80. */
  81. public static int SURFACEPLOT_FILLED = 14;
  82. /**
  83. * Draws a filled surface plot (Slowest mode).
  84. */
  85. public static int SURFACEPLOT_ISOLINES = 15;
  86. private SurfacePlot surfacePlot = null;
  87. private int surfacePlot_gridWidth = SURFACEGRID_DEFAULTWIDTH;
  88. private int surfacePlot_gridHeight = SURFACEGRID_DEFAULTHEIGHT;
  89. private Bitmap surfacePlot_imagePlusData = null; // image used for the surface plot
  90. private Bitmap surfacePlot_imagePlusTexture = null; // texture image
  91. private int surfacePlot_plotMode = SURFACEPLOT_LINES;
  92. private int surfacePlot_lutNr = LUT_ORIGINAL;
  93. private double surfacePlot_light = 0;
  94. /**
  95. * Draws a volume using only dots (fastest mode).
  96. */
  97. public static int VOLUME_DOTS = 20;
  98. /**
  99. * Draws a volume using nearest neighbor interpolation.
  100. */
  101. public static int VOLUME_SLICE_NEAREST_NEIGHBOR = 21;
  102. /**
  103. * Draws a volume using trilinear interpolation.
  104. */
  105. public static int VOLUME_SLICE_TRILINEAR = 22;
  106. // public final static int VOLUME_SLICE_AND_BORDERS = 23;
  107. // public final static int VOLUME_SLICE_AND_VOLUME_DOTS = 24;
  108. /**
  109. * Draws a volume using trilinear interpolation projection from the front
  110. */
  111. public static int VOLUME_PROJECTION_TRILINEAR_FRONT = 25;
  112. /**
  113. * Draws a volume using trilinear interpolation projection from the back
  114. */
  115. // public static final int VOLUME_PROJECTION_TRILINEAR_BACK = 26;
  116. private Volume volume = null;
  117. private int volume_drawMode = VOLUME_DOTS;
  118. //private int volume_threshold = 0;
  119. //private int volume_cutDist = 0; // clips the view sceen
  120. private int volume_lutNr = LUT_ORIGINAL; // LUT type
  121. //private int volume_dotsDeltaX = 1; // subsampling factor in x direction (used by dots drawing)
  122. //private int volume_dotsDeltaY = 1; // subsampling factor in x direction (used by dots drawing)
  123. //private int volume_dotsDeltaZ = 1; // subsampling factor in x direction (used by dots drawing)
  124. private int surfacePlot_min = 0; // minimum value for the luminance transform
  125. private int surfacePlot_max = 255; // maximum value for the luminance transform
  126. private Bitmap image;
  127. private bool axes = true;
  128. private bool lines = true;
  129. private bool text = true;
  130. private bool legend = true;
  131. private double minZ;
  132. private double maxZ;
  133. // LUT constants
  134. /**
  135. * 3D represenations of objects are drawn with their original colors.
  136. */
  137. public static int LUT_ORIGINAL = 50;
  138. /**
  139. * 3D representations of objects are drawn with grayscale colors.
  140. */
  141. public static int LUT_GRAY = 51;
  142. /**
  143. * 3D representations of objects are drawn with spectrum colors.
  144. */
  145. public static int LUT_SPECTRUM = 52;
  146. /**
  147. * 3D representations of objects are drawn with fire colors.
  148. */
  149. public static int LUT_FIRE = 53;
  150. /**
  151. * 3D representations of objects are drawn with thermal colors.
  152. */
  153. public static int LUT_THERMAL = 54;
  154. /**
  155. * 3D representations of objects are drawn in orange.
  156. */
  157. public static int LUT_ORANGE = 55;
  158. /**
  159. * 3D representations of objects are drawn in blue.
  160. */
  161. public static int LUT_BLUE = 56;
  162. /**
  163. * 3D representations of objects are drawn in black.
  164. */
  165. public static int LUT_BLACK = 57;
  166. /**
  167. * 3D representations of objects are cored according to their gradient.
  168. */
  169. public static int LUT_GRADIENT = 58;
  170. public static int LUT_GRADIENT2 = 59;
  171. /**
  172. * Creates a new JRenderer3D object.
  173. *
  174. * This has always to be the first step to generate a 3D scene.
  175. *
  176. * The center is assumed at (0,0,0)
  177. *
  178. */
  179. public JRenderer3D()
  180. {
  181. //initBuffer();
  182. }
  183. /**
  184. * Creates a new JRenderer3D object. <p>
  185. *
  186. * This has always to be the first step to generate a 3D scene.
  187. *
  188. * @param xCenter The x-coordinate of the rotation / plot center.
  189. * @param yCenter The y-coordinate of the rotation / plot center.
  190. * @param zCenter The z-coordinate of the rotation / plot center.
  191. */
  192. public JRenderer3D(double xCenter, double yCenter, double zCenter)
  193. {
  194. this.xCenter = xCenter;
  195. this.yCenter = yCenter;
  196. this.zCenter = zCenter;
  197. //initBuffer();
  198. }
  199. private void initBuffer()
  200. {
  201. image = new Bitmap(bufferWidth, bufferHeight);
  202. bytes = image.Width * image.Height;
  203. rgbValues = new byte[bytes * 3];
  204. rect = new Rectangle(0, 0, image.Width, image.Height);
  205. bufferPixels = new int[bufferWidth * bufferHeight];
  206. zbufferPixels = new double[bufferWidth * bufferHeight];
  207. if (transform != null)
  208. {
  209. tr_rotationX = transform.getRotationX();
  210. tr_rotationY = transform.getRotationY();
  211. tr_rotationZ = transform.getRotationZ();
  212. scale = transform.getScale();
  213. zAspectRatio = transform.getZAspectRatio();
  214. tr_perspective = transform.getPerspective();
  215. tr_maxDistance = transform.getMaxDistance();
  216. }
  217. transform = new Transform(bufferWidth, bufferHeight);
  218. // restore values from previous transformation
  219. transform.setZOrientation(zOrientation);
  220. transform.setRotationXYZ(tr_rotationX, tr_rotationY, tr_rotationZ);
  221. transform.setScale(scale);
  222. transform.setZAspectRatio(zAspectRatio);
  223. transform.setPerspective(tr_perspective);
  224. transform.setMaxDistance(tr_maxDistance);
  225. // if the surfacePlot exists, then update the references to the buffers
  226. if (surfacePlot != null)
  227. {
  228. surfacePlot.setBuffers(bufferPixels, zbufferPixels, bufferWidth, bufferHeight);
  229. surfacePlot.setTransform(transform);
  230. }
  231. /**
  232. if (volume != null)
  233. {
  234. volume.setBuffers(bufferPixels, zbufferPixels, bufferWidth, bufferHeight);
  235. volume.setTransform(transform);
  236. }**/
  237. }
  238. private void lines1()
  239. {
  240. Point3D p0 = new Point3D();
  241. Point3D p1 = new Point3D();
  242. for (int i = 0; i < lines3D.Count; i++)
  243. {
  244. if (lines3D[i] != null && lines3D[i] is Line3D)
  245. {
  246. Line3D line = (Line3D)lines3D[i];
  247. int color = line.color;
  248. setPoints(line, p0, p1);
  249. transform.transform(p0);
  250. double x0 = transform.X, y0 = transform.Y, z0 = transform.Z + 2;
  251. transform.transform(p1);
  252. double x1 = transform.X, y1 = transform.Y, z1 = transform.Z + 2;
  253. if (line.isPair)
  254. {
  255. i++;
  256. Line3D line2 = (Line3D)lines3D[i];
  257. int color2 = line2.color;
  258. setPoints(line2, p0, p1);
  259. transform.transform(p0);
  260. double x0_2 = transform.X, y0_2 = transform.Y, z0_2 = transform.Z + 2;
  261. transform.transform(p1);
  262. double x1_2 = transform.X, y1_2 = transform.Y, z1_2 = transform.Z + 2;
  263. if (z0_2 + z1_2 > z0 + z1)
  264. {
  265. x0 = x0_2;
  266. y0 = y0_2;
  267. z0 = z0_2;
  268. x1 = x1_2;
  269. y1 = y1_2;
  270. z1 = z1_2;
  271. color = color2;
  272. }
  273. }
  274. double dx1 = x1 - x0, dy1 = y1 - y0, dz1 = z1 - z0;
  275. int numSteps = (int)Math.Max(Math.Abs(dx1), Math.Abs(dy1));
  276. double step = (numSteps > 0) ? 1 / (double)numSteps : 1;
  277. for (int s = 0; s < numSteps; s++)
  278. {
  279. double f = s * step;
  280. int x = (int)(x0 + f * dx1);
  281. int y = (int)(y0 + f * dy1);
  282. if (x >= 0 && y >= 0 && x < bufferWidth && y < bufferHeight)
  283. {
  284. int pos = y * bufferWidth + x;
  285. double z = z0 + f * dz1;
  286. int v_ = (int)((z * 20) + 128);
  287. v_ = Math.Min(Math.Max(0, v_), 255);
  288. v_ = (int)(0xFF000000 | (v_ << 8));
  289. if (z <= zbufferPixels[pos])
  290. {
  291. zbufferPixels[pos] = z;
  292. bufferPixels[pos] = color; // v_;
  293. }
  294. }
  295. }
  296. }
  297. }
  298. }
  299. public void cubeLines()
  300. {
  301. Point3D p0 = new Point3D();
  302. Point3D p1 = new Point3D();
  303. for (int i = 0; i < cubeLines3D.Count; i++)
  304. {
  305. if (cubeLines3D[i] != null && cubeLines3D[i] is Line3D)
  306. {
  307. Line3D line = (Line3D)cubeLines3D[i];
  308. int color = line.color;
  309. setPoints(line, p0, p1);
  310. transform.transform(p0);
  311. double x0 = transform.X, y0 = transform.Y, z0 = transform.Z;
  312. transform.transform(p1);
  313. double x1 = transform.X, y1 = transform.Y, z1 = transform.Z;
  314. double dx1 = x1 - x0, dy1 = y1 - y0, dz1 = z1 - z0;
  315. int numSteps = (int)Math.Max(Math.Abs(dx1), Math.Abs(dy1));
  316. double step = (numSteps > 0) ? 1 / (double)numSteps : 1;
  317. for (int s = 0; s < numSteps; s++)
  318. {
  319. double f = s * step;
  320. int x = (int)(x0 + f * dx1);
  321. int y = (int)(y0 + f * dy1);
  322. if (x >= 0 && y >= 0 && x < bufferWidth && y < bufferHeight)
  323. {
  324. int pos = y * bufferWidth + x;
  325. double z = z0 + f * dz1;
  326. if (z <= zbufferPixels[pos])
  327. {
  328. zbufferPixels[pos] = z;
  329. bufferPixels[pos] = color;
  330. }
  331. }
  332. }
  333. }
  334. }
  335. //第一个版本
  336. /**
  337. if (image != null)
  338. {
  339. bmpData = image.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
  340. ptr = bmpData.Scan0;
  341. Color color;
  342. for (int i = 0; i < bufferPixels.Length; i++)
  343. {
  344. color = Color.FromArgb(bufferPixels[i]);
  345. rgbValues[i * 3 + 2] = color.R;
  346. rgbValues[i * 3 + 1] = color.G;
  347. rgbValues[i * 3] = color.B;
  348. }
  349. System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes * 3);
  350. image.UnlockBits(bmpData);
  351. }**/
  352. //第二个版本
  353. if (image != null)
  354. {
  355. //bmpData = new BitmapData();
  356. bmpData = image.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);//.Format24bppRgb
  357. ptr = bmpData.Scan0;
  358. for (int i = 0; i < bufferPixels.Length; i++)
  359. {
  360. int c0 = bufferPixels[i];
  361. rgbValues[i * 3 + 2] = (byte)((c0 >> 16) & 0xff);
  362. rgbValues[i * 3 + 1] = (byte)((c0 >> 8) & 0xff);
  363. rgbValues[i * 3] = (byte)((c0) & 0xff);
  364. }
  365. System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes * 3);
  366. image.UnlockBits(bmpData);
  367. }
  368. //第三个版本
  369. /**
  370. if (image != null)
  371. {
  372. bmpData = image.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);//.Format24bppRgb
  373. byte* ptr = (byte*)(bmpData.Scan0);
  374. for (int i = 0; i < bmpData.Width; i++) {
  375. for (int j = 0; j < bmpData.Height; j++)
  376. {
  377. int c0 = bufferPixels[i*j];
  378. ptr[0] = (byte)((c0) & 0xff);
  379. ptr[1] = (byte)((c0 >> 8) & 0xff);
  380. ptr[2] = (byte)((c0 >> 16) & 0xff);
  381. }
  382. ptr += bmpData.Stride - bmpData.Width * 3;
  383. }
  384. //System.Runtime.InteropServices.Marshal.Copy(bufferPixels, 0, ptr, bytes);
  385. image.UnlockBits(bmpData);
  386. }**/
  387. }
  388. private void setPoints(Line3D l0, Point3D p0, Point3D p1)
  389. {
  390. p0.x = l0.x1;
  391. p0.y = l0.y1;
  392. p0.z = l0.z1;
  393. p1.x = l0.x2;
  394. p1.y = l0.y2;
  395. p1.z = l0.z2;
  396. }
  397. private void finishAndDrawText()
  398. {
  399. if (bufferedImage == null ||
  400. bufferedImage.Height != bufferHeight ||
  401. bufferedImage.Width != bufferWidth)
  402. {
  403. bufferedImage = new Bitmap(bufferWidth, bufferHeight);
  404. g2D = Graphics.FromImage(bufferedImage);
  405. }
  406. g2D.FillRectangle(brush, 0, 0, bufferWidth, bufferHeight);
  407. g2D.DrawImage(image, 0, 0);
  408. Font font;
  409. if (text)
  410. {
  411. if (text3D != null)
  412. {
  413. double scale = transform.getScale();
  414. for (int i = 0; i < text3D.Count; i++)
  415. {
  416. if (text3D[i] != null && text3D[i] is Text3D)
  417. {
  418. Text3D ti = (Text3D)text3D[i];
  419. transform.transform(ti);
  420. double x = transform.X;
  421. double y = transform.Y;
  422. double z = transform.Z;
  423. double x2 = 0;
  424. double y2 = 0;
  425. double z2 = 0;
  426. if (ti.number == 2)
  427. {
  428. i++;
  429. Text3D ti2 = (Text3D)text3D[i];
  430. transform.transform(ti2);
  431. x2 = transform.X;
  432. y2 = transform.Y;
  433. z2 = transform.Z;
  434. if (z2 < z)
  435. {
  436. x = x2;
  437. y = y2;
  438. z = z2;
  439. }
  440. }
  441. if (ti.number == 4)
  442. {
  443. i++;
  444. Text3D ti2 = (Text3D)text3D[i];
  445. transform.transform(ti2);
  446. x2 = transform.X;
  447. y2 = transform.Y;
  448. z2 = transform.Z;
  449. i++;
  450. ti = (Text3D)text3D[i];
  451. transform.transform(ti);
  452. double x3 = transform.X;
  453. double y3 = transform.Y;
  454. double z3 = transform.Z;
  455. i++;
  456. ti = (Text3D)text3D[i];
  457. transform.transform(ti);
  458. double x4 = transform.X;
  459. double y4 = transform.Y;
  460. double z4 = transform.Z;
  461. if (x2 < x)
  462. {
  463. x = x2;
  464. y = y2;
  465. z = z3;
  466. }
  467. if (x3 < x)
  468. {
  469. x = x3;
  470. y = y3;
  471. z = z3;
  472. }
  473. if (x4 < x)
  474. {
  475. x = x4;
  476. y = y4;
  477. z = z4;
  478. }
  479. }
  480. if (z >= 0)
  481. {
  482. //g2D.setColor(ti.color);
  483. int strHeight = (int)(scale * ti.size);
  484. font = new Font("Sans", strHeight);
  485. //g2D.setFont(font);
  486. //FontMetrics metrics = g2D.getFontMetrics();
  487. //int strWidth = metrics.stringWidth(ti.text);
  488. SizeF size = g2D.MeasureString(ti.text, font);
  489. g2D.DrawString(ti.text, font, brush1, (int)x - size.Width/ 2, (int)y + strHeight / 2);
  490. }
  491. }
  492. }
  493. }
  494. }
  495. if (text)
  496. {
  497. if (text3D != null)
  498. {
  499. double scale = transform.getScale();
  500. for (int i = 0; i < text3D.Count; i++)
  501. {
  502. if (text3D[i] != null && text3D[i] is Text3D)
  503. {
  504. Text3D ti = (Text3D)text3D[i];
  505. transform.transform(ti);
  506. double x = transform.X;
  507. double y = transform.Y;
  508. double z = transform.Z;
  509. double x2 = 0;
  510. double y2 = 0;
  511. double z2 = 0;
  512. if (ti.number == 2)
  513. {
  514. i++;
  515. Text3D ti2 = (Text3D)text3D[i];
  516. transform.transform(ti2);
  517. x2 = transform.X;
  518. y2 = transform.Y;
  519. z2 = transform.Z;
  520. if (z2 < z)
  521. {
  522. x = x2;
  523. y = y2;
  524. z = z2;
  525. }
  526. }
  527. if (ti.number == 4)
  528. {
  529. i++;
  530. Text3D ti2 = (Text3D)text3D[i];
  531. transform.transform(ti2);
  532. x2 = transform.X;
  533. y2 = transform.Y;
  534. z2 = transform.Z;
  535. i++;
  536. ti = (Text3D)text3D[i];
  537. transform.transform(ti);
  538. double x3 = transform.X;
  539. double y3 = transform.Y;
  540. double z3 = transform.Z;
  541. i++;
  542. ti = (Text3D)text3D[i];
  543. transform.transform(ti);
  544. double x4 = transform.X;
  545. double y4 = transform.Y;
  546. double z4 = transform.Z;
  547. if (x2 < x)
  548. {
  549. x = x2;
  550. y = y2;
  551. z = z3;
  552. }
  553. if (x3 < x)
  554. {
  555. x = x3;
  556. y = y3;
  557. z = z3;
  558. }
  559. if (x4 < x)
  560. {
  561. x = x4;
  562. y = y4;
  563. z = z4;
  564. }
  565. }
  566. //System.out.println("2 x:" + x + " y: " + y + " z: " + z + " " + ti.text);
  567. if (z < 0)
  568. {
  569. //g2D.setColor(ti.color);
  570. int strHeight = (int)(scale * ti.size);
  571. font = new Font("Sans", strHeight);
  572. //g2D.setFont(font);
  573. //FontMetrics metrics = g2D.getFontMetrics();
  574. SizeF size = g2D.MeasureString(ti.text, font);
  575. g2D.DrawString(ti.text, font, brush1, (int)x - size.Width / 2, (int)y + strHeight / 2);
  576. }
  577. }
  578. }
  579. }
  580. }
  581. // show lut
  582. if (legend && surfacePlot != null)
  583. {
  584. int lutNr = surfacePlot.getSurfacePlotLut();
  585. if ((lutNr > LUT_ORIGINAL && lutNr <= LUT_THERMAL) || (lutNr == LUT_ORIGINAL && surfacePlot.hasOtherLut))
  586. {
  587. int hLut = 256;
  588. int wLut = 20;
  589. int xs = bufferWidth - 30;
  590. int xe = xs + wLut;
  591. int ys = (bufferHeight - hLut) / 2;
  592. bool isInverse = (surfacePlot.getInversefactor() == -1);
  593. //g2D.setColor(legendTextColor);
  594. g2D.DrawRectangle(pen1, new Rectangle(xs - 1, ys - 1, wLut + 2, hLut + 1));
  595. for (int j = 0; j < 256; j++)
  596. {
  597. //g2D.setColor(new Color(surfacePlot.lut.colors[255 - j]));
  598. g2D.DrawLine(pen1, xs, ys + j, xe, ys + j);
  599. }
  600. double d = maxZ - minZ;
  601. double stepValue = calcStepSize(d, 11);
  602. double minStart = Math.Floor(minZ / stepValue) * stepValue;
  603. double delta = minStart - minZ;
  604. //g2D.setColor(legendTextColor);
  605. font = new Font("Sans", 12);
  606. //g2D.setFont(font);
  607. //FontMetrics metrics = g2D.getFontMetrics();
  608. int stringHeight = 5;
  609. for (double value = 0; value + delta <= d; value += stepValue)
  610. {
  611. String s;
  612. if (Math.Floor(minStart + value) - (minStart + value) == 0)
  613. s = "" + (int)(minStart + value);
  614. else
  615. s = "" + (int)Math.Round((minStart + value) * 1000) / 1000;
  616. double pos = ((value + delta) * 256 / d);
  617. int y;
  618. if (pos >= 0)
  619. {
  620. y = (int)(-pos + 255 + ys);
  621. if (isInverse)
  622. y = (int)(pos + ys);
  623. //int strWidth = metrics.stringWidth(s);
  624. g2D.DrawString(s, font, brush1, xs - 5, y + stringHeight);
  625. g2D.DrawLine(pen1, xs - 3, y, xs - 1, y);
  626. }
  627. }
  628. }
  629. }
  630. }
  631. public void showRotation()
  632. {
  633. Font font = new Font("Sans", 13);
  634. //g2D.setFont(font);
  635. String str = "Rotation x = " + (int)((180 / Math.PI) * transform.getRotationX()) + "\u00b0" + ", Rotation z =" + (int)((180 / Math.PI) * transform.getRotationZ()) + "\u00b0";
  636. g2D.DrawString(str, font, brush1, 10, 20);
  637. }
  638. public void setLegendTextColor(Color legendTextColor)
  639. {
  640. this.legendTextColor = legendTextColor;
  641. }
  642. double calcStepSize(double range, double targetSteps)
  643. {
  644. // Calculate an initial guess at step size
  645. double tempStep = range / targetSteps;
  646. // Get the magnitude of the step size
  647. double mag = Math.Floor(Math.Log(tempStep) / Math.Log(10));
  648. double magPow = Math.Pow((double)10.0, mag);
  649. // Calculate most significant digit of the new step size
  650. double magMsd = ((int)(tempStep / magPow + .5));
  651. // promote the MSD to either 1, 2, 4, or 5
  652. if (magMsd > 6) // 5
  653. magMsd = 10.0;
  654. else if (magMsd > 3)
  655. magMsd = 5.0;
  656. else if (magMsd > 2)
  657. magMsd = 4.0;
  658. else if (magMsd > 1)
  659. magMsd = 2.0;
  660. return magMsd * magPow;
  661. }
  662. private void clearBuffers()
  663. {
  664. for (int i = bufferPixels.Length - 1; i >= 0; i--)
  665. {
  666. bufferPixels[i] = 0;
  667. zbufferPixels[i] = 1000000;
  668. }
  669. }
  670. private Line3D setLinePoints(Line3D lineItem, double[] p1, double[] p2, int color)
  671. {
  672. lineItem.x1 = p1[0];
  673. lineItem.y1 = p1[1];
  674. lineItem.z1 = p1[2];
  675. lineItem.x2 = p2[0];
  676. lineItem.y2 = p2[1];
  677. lineItem.z2 = p2[2];
  678. lineItem.color = color;
  679. return lineItem;
  680. }
  681. private void addCubeLinesList(Line3D[] lines3D)
  682. {
  683. if (cubeLines3D == null) cubeLines3D = new ArrayList();
  684. for (int i = 0; i < lines3D.Length; i++)
  685. {
  686. this.cubeLines3D.Add(lines3D[i]);
  687. }
  688. }
  689. private void clearCubeLines3D()
  690. {
  691. if (cubeLines3D != null)
  692. this.cubeLines3D.Clear();
  693. }
  694. /**
  695. * This methods does the rendering and creates the 3D output.
  696. * It has to be redone after all setting changes (scale, angle, surface modes, lightning modes, color modes etc.)
  697. * Draws all given input data (lines, text, points, cubes, surfaces).
  698. */
  699. public void doRendering()
  700. {
  701. clearBuffers();
  702. if (volume != null)
  703. {
  704. transform.setOffsets(xCenter, yCenter, zCenter);
  705. volume.draw();
  706. transform.setOffsets(0, 0, 0);
  707. }
  708. if (surfacePlot != null)
  709. {
  710. surfacePlot.draw();
  711. }
  712. if (pointsPlot != null)
  713. {
  714. pointsPlot.draw();
  715. }
  716. if (lines && lines3D != null)
  717. {
  718. //lines1();
  719. }
  720. if (axes && cubeLines3D != null)
  721. {
  722. cubeLines();
  723. }
  724. finishAndDrawText();
  725. if (getSurfacePlotMode() == JRenderer3D.SURFACEPLOT_DOTSNOLIGHT)
  726. showRotation();
  727. }
  728. /**
  729. * Creates the surface plot.
  730. *
  731. * @param imp The images to be drawn in 3D.
  732. */
  733. public void setSurfacePlot(Bitmap imp)
  734. {
  735. //Cv2.ImShow("d111dd", OpenCvSharp.Extensions.BitmapConverter.ToMat(imp));
  736. //在这里把图片resize下看看
  737. //surfacePlot_imagePlusData = KiResizeImage(imp, surfacePlot_gridWidth, surfacePlot_gridHeight);
  738. surfacePlot_imagePlusData = imp;
  739. surfacePlot = new SurfacePlot();
  740. surfacePlot.setSurfacePlotCenter(xCenter, yCenter, zCenter);
  741. surfacePlot.setSurfaceGridSize(surfacePlot_gridWidth, surfacePlot_gridHeight);
  742. surfacePlot.setSurfacePlotImage(surfacePlot_imagePlusData);
  743. if (surfacePlot_imagePlusTexture != null)
  744. {
  745. surfacePlot.setSurfacePlotTextureImage(surfacePlot_imagePlusTexture);
  746. }
  747. surfacePlot.resample();
  748. surfacePlot.setSurfacePlotMode(surfacePlot_plotMode);
  749. surfacePlot.setSurfacePLotSetLight(surfacePlot_light);
  750. surfacePlot.setBuffers(bufferPixels, zbufferPixels, bufferWidth, bufferHeight);
  751. surfacePlot.setTransform(transform);
  752. }
  753. public void setSurfacePlotTexture(Bitmap impTexture)
  754. {
  755. surfacePlot_imagePlusTexture = impTexture;
  756. if (surfacePlot != null)
  757. {
  758. surfacePlot.setSurfacePlotTextureImage(impTexture);
  759. surfacePlot.resample();
  760. }
  761. }
  762. /**
  763. * Sets the surface plot mode.
  764. * <p>
  765. * Available options:
  766. * <ul>
  767. * <li> <strong>PLOT_DOTSNOLIGHT</strong>: if used, no lightning options are applied (fastest)</li>
  768. * <li> <strong>PLOT_DOTS</strong>: draws dots</li>
  769. * <li> <strong>PLOT_LINES</strong>: draws lines</li>
  770. * <li> <strong>PLOT_MESH</strong>: draws a mesh</li>
  771. * <li> <strong>PLOT_FILLED</strong>: fills the 3d object completely (slowest)</li>
  772. * </ul>
  773. *
  774. * @param surfacePlot_plotMode the surface plot mode
  775. */
  776. public void setSurfacePlotMode(int surfacePlot_plotMode)
  777. {
  778. this.surfacePlot_plotMode = surfacePlot_plotMode;
  779. if (surfacePlot != null)
  780. surfacePlot.setSurfacePlotMode(surfacePlot_plotMode);
  781. }
  782. public int getSurfacePlotMode()
  783. {
  784. return surfacePlot_plotMode;
  785. }
  786. /**
  787. * Sets the surface grid size (sampling rate).
  788. * Should be set to an integer fraction of the image of which the surface plot has to be generated.
  789. *
  790. * @param width the width of surface grid
  791. * @param height the height of surface grid
  792. */
  793. public void setSurfacePlotGridSize(int width, int height)
  794. {
  795. this.surfacePlot_gridWidth = width;
  796. this.surfacePlot_gridHeight = height;
  797. if (surfacePlot != null)
  798. {
  799. surfacePlot.setSurfaceGridSize(surfacePlot_gridWidth, surfacePlot_gridHeight);
  800. surfacePlot.resample();
  801. }
  802. }
  803. /**
  804. * Sets scale of the redered 3D scene.
  805. *
  806. * @param scale scales the scene
  807. */
  808. public void setTransformScale(double scale)
  809. {
  810. transform.setScale(scale);
  811. }
  812. /**
  813. * Sets the rotation on x-, y- and z-axis.
  814. *
  815. * @param ax rotation angle of x-axis in degree
  816. * @param ay rotation angle of y-axis in degree
  817. * @param az rotation angle of z-axis in degree
  818. */
  819. public void setTransformRotationXYZ(double ax, double ay, double az)
  820. {
  821. transform.setRotationXYZ(ax / 180 * Math.PI, ay / 180 * Math.PI, az / 180 * Math.PI);
  822. }
  823. /**
  824. * Changes the rotation of x- and z-axis by the values of changeX and changeY.
  825. *
  826. * @param changeX change of rotation angle of x-axis in degree
  827. * @param changeZ change of rotation angle of z-axis in degree
  828. */
  829. public void changeTransformRotationXZ(double changeX, double changeZ)
  830. {
  831. transform.changeRotationXZ(changeX / 180 * Math.PI, changeZ / 180 * Math.PI);
  832. }
  833. /**
  834. * Sets the background color of the rendered 3D presenation
  835. *
  836. * @param rgb the background color (argb int)
  837. */
  838. public void setBackgroundColor(int rgb)
  839. {
  840. this.backgroundColor = Color.FromArgb(rgb);
  841. }
  842. /**
  843. * Sets the background color of the rendered 3D presentation
  844. *
  845. * @param color Color
  846. */
  847. public void setBackgroundColor(Color color)
  848. {
  849. this.backgroundColor = color;
  850. }
  851. /**
  852. * Adds a single 3D line to the 3D scene.
  853. *
  854. * @param line3D the 3D line to add
  855. */
  856. public void addLine3D(Line3D line3D)
  857. {
  858. if (this.lines3D == null) this.lines3D = new ArrayList();
  859. line3D.x1 -= xCenter;
  860. line3D.y1 -= yCenter;
  861. line3D.z1 -= zCenter;
  862. line3D.x2 -= xCenter;
  863. line3D.y2 -= yCenter;
  864. line3D.z2 -= zCenter;
  865. this.lines3D.Add(line3D);
  866. }
  867. public void clearLines()
  868. {
  869. if (this.lines3D != null)
  870. this.lines3D.Clear();
  871. }
  872. /**
  873. * Adds a single 3D text to the 3D scene.
  874. *
  875. * @param text3D the 3D text to add
  876. */
  877. public void addText3D(Text3D text3D)
  878. {
  879. if (this.text3D == null) this.text3D = new ArrayList();
  880. text3D.x -= xCenter;
  881. text3D.y -= yCenter;
  882. text3D.z -= zCenter;
  883. this.text3D.Add(text3D);
  884. }
  885. public void addTextPair3D(Text3D text1_3D, Text3D text2_3D)
  886. {
  887. if (this.text3D == null) this.text3D = new ArrayList();
  888. text1_3D.x -= xCenter;
  889. text1_3D.y -= yCenter;
  890. text1_3D.z -= zCenter;
  891. text2_3D.x -= xCenter;
  892. text2_3D.y -= yCenter;
  893. text2_3D.z -= zCenter;
  894. this.text3D.Add(text1_3D);
  895. this.text3D.Add(text2_3D);
  896. }
  897. public void clearText()
  898. {
  899. if (this.text3D != null)
  900. this.text3D.Clear();
  901. }
  902. /**
  903. * Sets the buffer size. (The size of the rendered 2D image)
  904. *
  905. * @param width The width to be set.
  906. * @param height The height to be set.
  907. */
  908. public void setBufferSize(int width, int height)
  909. {
  910. this.bufferWidth = width;
  911. this.bufferHeight = height;
  912. initBuffer();
  913. }
  914. /**
  915. * Adds a cube (drawn with 12 lines) to the 3D scene.
  916. *
  917. * @param xMin minimum value x
  918. * @param yMin minimum value y
  919. * @param zMin minimum value z
  920. * @param xMax maximum value x
  921. * @param yMax maximum value y
  922. * @param zMax maximum value z
  923. * @param color Color of cube lines (argb)
  924. */
  925. public void add3DCube(int xMin, int yMin, int zMin, int xMax, int yMax, int zMax, Color color)
  926. {
  927. int colorInt = color.ToArgb();
  928. add3DCube(xMin, yMin, zMin, xMax, yMax, zMax, colorInt);
  929. }
  930. /**
  931. * Adds a cube (drawn with 12 lines) to the 3D scene.
  932. *
  933. * @param xMin minimum value x
  934. * @param yMin minimum value y
  935. * @param zMin minimum value z
  936. * @param xMax maximum value x
  937. * @param yMax maximum value y
  938. * @param zMax maximum value z
  939. * @param rgb Color of cube lines (argb)
  940. */
  941. public void add3DCube(int xMin, int yMin, int zMin, int xMax, int yMax, int zMax, int rgb)
  942. {
  943. double[][] cube = new double[8][]{
  944. new double[]{ xMin-xCenter, yMin-yCenter, zMin-zCenter }, // left front down [0]
  945. new double[]{ xMax-xCenter, yMin-yCenter, zMin-zCenter }, // right front down [1]
  946. new double[]{ xMin-xCenter, yMin-yCenter, zMax-zCenter }, // left front up [2]
  947. new double[]{ xMax-xCenter, yMin-yCenter, zMax-zCenter }, // right front up [3]
  948. new double[]{ xMin-xCenter, yMax-yCenter, zMin-zCenter }, // left back down [4]
  949. new double[]{ xMax-xCenter, yMax-yCenter, zMin-zCenter }, // right back down [5]
  950. new double[]{ xMin-xCenter, yMax-yCenter, zMax-zCenter }, // left back up [6]
  951. new double[]{ xMax-xCenter, yMax-yCenter, zMax-zCenter } // right back up [7]
  952. };
  953. // set up new 3D lines list
  954. Line3D[] lines3D = new Line3D[12];
  955. lines3D[0] = setLinePoints(new Line3D(), cube[0], cube[1], rgb);
  956. lines3D[1] = setLinePoints(new Line3D(), cube[0], cube[2], rgb);
  957. lines3D[2] = setLinePoints(new Line3D(), cube[0], cube[4], rgb);
  958. lines3D[3] = setLinePoints(new Line3D(), cube[2], cube[6], rgb);
  959. lines3D[4] = setLinePoints(new Line3D(), cube[4], cube[6], rgb);
  960. lines3D[5] = setLinePoints(new Line3D(), cube[6], cube[7], rgb);
  961. lines3D[6] = setLinePoints(new Line3D(), cube[3], cube[7], rgb);
  962. lines3D[7] = setLinePoints(new Line3D(), cube[2], cube[3], rgb);
  963. lines3D[8] = setLinePoints(new Line3D(), cube[1], cube[3], rgb);
  964. lines3D[9] = setLinePoints(new Line3D(), cube[1], cube[5], rgb);
  965. lines3D[10] = setLinePoints(new Line3D(), cube[4], cube[5], rgb);
  966. lines3D[11] = setLinePoints(new Line3D(), cube[5], cube[7], rgb);
  967. addCubeLinesList(lines3D);
  968. }
  969. public void clearCubes()
  970. {
  971. this.clearCubeLines3D();
  972. }
  973. /**
  974. * Sets the color lut for the surface plot.
  975. * <p>
  976. * <ul>
  977. * <li> <strong>ORIGINAL</strong></li>
  978. * <li> <strong>GRAY</strong></li>
  979. * <li> <strong>SPECTRUM</strong></li>
  980. * <li> <strong>FIRE</strong></li>
  981. * <li> <strong>THERMAL</strong></li>
  982. * <li> <strong>ORANGE</strong></li>
  983. * <li> <strong>BLUE</strong></li>
  984. * <li> <strong>BLACK</strong></li>
  985. *</ul>
  986. *
  987. * @param surfacePlot_lutNr color of look-up-table
  988. */
  989. public void setSurfacePlotLut(int surfacePlot_lutNr)
  990. {
  991. this.surfacePlot_lutNr = surfacePlot_lutNr;
  992. if (surfacePlot != null)
  993. surfacePlot.setSurfacePlotLut(surfacePlot_lutNr);
  994. }
  995. /**
  996. * Sets the lightning for the surface plot illumination .
  997. * <p>
  998. * <ul>
  999. * <li>0: no light</li>
  1000. * <li>1: strong light</li>
  1001. * </ul>
  1002. *
  1003. * @param surfacePlot_light intensity value between 0 and 1 (default is 0)
  1004. *
  1005. */
  1006. public void setSurfacePlotLight(double surfacePlot_light)
  1007. {
  1008. this.surfacePlot_light = surfacePlot_light;
  1009. if (surfacePlot != null)
  1010. surfacePlot.setSurfacePLotSetLight(surfacePlot_light);
  1011. }
  1012. public void setSurfacePlotMinMax(int surfacePlot_min, int surfacePlot_max)
  1013. {
  1014. //IJ.log("Min: " + surfacePlot_min + " Max: " + surfacePlot_max);
  1015. this.surfacePlot_min = surfacePlot_min;
  1016. this.surfacePlot_max = surfacePlot_max;
  1017. if (surfacePlot != null)
  1018. {
  1019. surfacePlot.setMinMax(surfacePlot_min, surfacePlot_max);
  1020. surfacePlot.applyMinMax();
  1021. }
  1022. }
  1023. /**
  1024. * Aplies a smoothing to the surface plot data
  1025. *
  1026. * @param smoothRadius the radius of the smoothing kernel
  1027. *
  1028. */
  1029. public void setSurfaceSmoothingFactor(double smoothRadius)
  1030. {
  1031. surfacePlot.applySmoothingFilter(smoothRadius);
  1032. }
  1033. /**
  1034. * Sets the z-aspect ratio (the relative z-height of a voxel).
  1035. * When setting a volume, the z-aspect ratio is reset to ratio read from the stack.
  1036. * If the z-aspect ratio needs to set this has to be done after calling the setVolume method.
  1037. *
  1038. * @param zAspectRatio z-aspect ratio (the relative z-ratio of a voxel) to be set.
  1039. */
  1040. public void setTransformZAspectRatio(double zAspectRatio)
  1041. {
  1042. this.zAspectRatio = zAspectRatio;
  1043. transform.setZAspectRatio(zAspectRatio);
  1044. }
  1045. /**
  1046. * Returns the buffer width of the image.
  1047. *
  1048. * @return buffer width
  1049. */
  1050. public int getWidth()
  1051. {
  1052. return bufferWidth;
  1053. }
  1054. /**
  1055. * Returns the buffer height of the image.
  1056. *
  1057. * @return buffer height
  1058. */
  1059. public int getHeight()
  1060. {
  1061. return bufferHeight;
  1062. }
  1063. /**
  1064. * Returns actual rendered image.
  1065. *
  1066. * @return image
  1067. */
  1068. public Bitmap getImage()
  1069. {
  1070. return bufferedImage;
  1071. }
  1072. public void setTransformPerspective(double perspective)
  1073. {
  1074. transform.setPerspective(perspective);
  1075. }
  1076. public void setTransformMaxDistance(double maxDistance)
  1077. {
  1078. transform.setMaxDistance(maxDistance);
  1079. }
  1080. public void setAxes(bool axes)
  1081. {
  1082. this.axes = axes;
  1083. }
  1084. public void setLines(bool lines)
  1085. {
  1086. this.lines = lines;
  1087. }
  1088. public void setText(bool text)
  1089. {
  1090. this.text = text;
  1091. }
  1092. public void setLegend(bool legend)
  1093. {
  1094. this.legend = legend;
  1095. }
  1096. public void surfacePlotSetInverse(bool b)
  1097. {
  1098. if (surfacePlot != null)
  1099. surfacePlot.setInverse(b);
  1100. }
  1101. public void setMinZValue(double minZ)
  1102. {
  1103. this.minZ = minZ;
  1104. }
  1105. public void setMaxZValue(double maxZ)
  1106. {
  1107. this.maxZ = maxZ;
  1108. }
  1109. public double getTransformRotationX()
  1110. {
  1111. return (180 / Math.PI) * transform.getRotationX();
  1112. }
  1113. public double getTransformRotationY()
  1114. {
  1115. return (180 / Math.PI) * transform.getRotationY();
  1116. }
  1117. public double getTransformRotationZ()
  1118. {
  1119. return (180 / Math.PI) * transform.getRotationZ();
  1120. }
  1121. }
  1122. }