PlotlyScene.cs 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Numerics;
  5. using System.Text;
  6. using Plotly;
  7. using Plotly.Types;
  8. using TRACES = Plotly.Box<Plotly.Types.ITracesProperty>;
  9. using VERTEX = SharpGLTF.Geometry.IVertexBuilder;
  10. using VERTEXBUILDER = SharpGLTF.Geometry.VertexBuilder<SharpGLTF.Geometry.VertexTypes.VertexPositionNormal, SharpGLTF.Geometry.VertexTypes.VertexEmpty, SharpGLTF.Geometry.VertexTypes.VertexEmpty>;
  11. namespace SharpGLTF
  12. {
  13. public class PlotlyScene
  14. {
  15. #region data
  16. private readonly List<TRACES> _Traces = new List<TRACES>();
  17. private readonly Dictionary<Object, int> _Materials = new Dictionary<Object, int>(); // materials to color mapping
  18. #endregion
  19. #region API
  20. public void AppendTriangles<TMaterial>(IEnumerable<(VERTEX A, VERTEX B, VERTEX C, TMaterial Material)> tris, Func<TMaterial, int> materialColorFunc)
  21. {
  22. var trace = _CreateTrace(tris, materialColorFunc);
  23. _Traces.Add(trace);
  24. }
  25. public void AppendTriangles<TMaterial>(IEnumerable<(Vector3 A, Vector3 B, Vector3 C, TMaterial Material)> tris, Func<TMaterial, int> materialColorFunc)
  26. {
  27. (VERTEX A, VERTEX B, VERTEX C, TMaterial Material) _Convert((Vector3 A, Vector3 B, Vector3 C, TMaterial Material) tri)
  28. {
  29. var ab = tri.B - tri.A;
  30. var ac = tri.C - tri.A;
  31. var n = Vector3.Normalize(Vector3.Cross(ab, ac));
  32. var aa = new VERTEXBUILDER((tri.A, n));
  33. var bb = new VERTEXBUILDER((tri.B, n));
  34. var cc = new VERTEXBUILDER((tri.C, n));
  35. return (aa, bb, cc, tri.Material);
  36. }
  37. var trace = _CreateTrace(tris.Select(_Convert), materialColorFunc);
  38. _Traces.Add(trace);
  39. }
  40. public Box<IPlotProperty> ToPlotProperties() { return Plot.traces(_Traces.ToArray()); }
  41. public Plot ToPlot()
  42. {
  43. var plot = ToPlotProperties();
  44. var layout = _CreateLayoutProperties();
  45. var document = new Plot(plot, layout);
  46. return document;
  47. }
  48. public string ToHtml()
  49. {
  50. Plot document = ToPlot();
  51. return document.Render().ToString();
  52. }
  53. #endregion
  54. #region core
  55. private static Box<IPlotProperty> _CreateLayoutProperties()
  56. {
  57. var xaxis = Scene.xaxis(Xaxis.color("red"));
  58. var yaxis = Scene.yaxis(Yaxis.color("green"));
  59. var zaxis = Scene.zaxis(Zaxis.color("blue"));
  60. var camera = Camera.up(Up.x(0), Up.y(1), Up.z(0));
  61. var scene = Layout.scene(Scene.Aspectmode.data(), Scene.camera(camera), xaxis, yaxis, zaxis);
  62. return Plot.layout
  63. (Layout.autosize(true)
  64. // , Layout.width(0)
  65. , Layout.height(920)
  66. // , Layout.margin(Margin.autoexpand(true))
  67. // , Layout.margin(Margin.pad(5))
  68. // , Layout.margin(Margin.t(5), Margin.b(5))
  69. , scene
  70. );
  71. }
  72. private TRACES _CreateTrace<TMaterial>(IEnumerable<(VERTEX A, VERTEX B, VERTEX C, TMaterial Material)> tris, Func<TMaterial, int> materialColorFunc)
  73. {
  74. var vrts = new List<(Vector3 p, Vector3 n)>(); // vertex list
  75. var vrtm = new Dictionary<(Vector3 p, Vector3 n), int>(); // vertex sharing map
  76. var idxs = new List<(int, int, int)>(); // triangle indices
  77. var tric = new List<int>(); // face colors
  78. int _useSharedVertex(VERTEX v)
  79. {
  80. var g = v.GetGeometry();
  81. g.TryGetNormal(out Vector3 n);
  82. var item = (g.GetPosition(), n);
  83. if (vrtm.TryGetValue(item, out int idx)) return idx;
  84. idx = vrts.Count;
  85. vrts.Add(item);
  86. vrtm.Add(item, idx);
  87. return idx;
  88. }
  89. foreach (var (A, B, C, Material) in tris)
  90. {
  91. if (!_Materials.TryGetValue(Material, out int color))
  92. {
  93. _Materials[Material] = color = materialColorFunc(Material);
  94. }
  95. var ap = _useSharedVertex(A);
  96. var bp = _useSharedVertex(B);
  97. var cp = _useSharedVertex(C);
  98. idxs.Add((ap, bp, cp));
  99. tric.Add(color);
  100. }
  101. // create a Plotly Mesh3D from the previously filled lists.
  102. var mx = Mesh3d.x(vrts.Select(item => item.p.X));
  103. var my = Mesh3d.y(vrts.Select(item => item.p.Y));
  104. var mz = Mesh3d.z(vrts.Select(item => item.p.Z));
  105. var mi = Mesh3d.i(idxs.Select(item => item.Item1).ToArray());
  106. var mj = Mesh3d.j(idxs.Select(item => item.Item2).ToArray());
  107. var mk = Mesh3d.k(idxs.Select(item => item.Item3).ToArray());
  108. var mo = Mesh3d.opacity(1);
  109. var mc = Mesh3d.facecolor(tric.ToArray());
  110. return Traces.mesh3d(mx, my, mz, mi, mj, mk, mo, mc);
  111. }
  112. #endregion
  113. }
  114. }