/// <summary> /// Initializes the marching cubes scene by loading the dataset from disk and creating a mesh for it. /// </summary> public override void Initialize() { base.Initialize(); _brush = new NormalBrush(); _pen = new SolidColorPen(Color.Black); var triangleBuilder = new TriangleMeshDescriptionBuilder(); // isolevel defines which points are inside/outside the structure int lastProgress = 0; // for each point we will at all 8 points forming a cube, we will simply take the index + 1 in each direction, thus our iteration counters must be reduced by 1 to prevent out of bound exception int xlen = InputData.XLength - 1; int ylen = InputData.YLength - 1; int zlen = InputData.ZLength - 1; var mcAlgo = new MarchingCubesAlgorithm(false); var box = new BoundingBox(); for (int x = 0; x < xlen; x++) { for (int y = 0; y < ylen; y++) { // report progress here as one dimension by itself would progress really fast (too small increments) var progress = (y + x * ylen) / (float)(ylen * xlen); var newProgress = (int)(progress * 100); if (newProgress >= 100) { newProgress = 99; // don't send 100 yet, send it only once at the end of the method } if (newProgress != lastProgress) { var p = InitializeProgress; p?.Invoke(this, newProgress); lastProgress = newProgress; } for (int z = 0; z < zlen; z++) { box.Min.X = x; box.Min.Y = y; box.Min.Z = z; box.Max.X = x + 1; box.Max.Y = y + 1; box.Max.Z = z + 1; var vertices = mcAlgo.Polygonize(InputData, _isolevel, box); if (vertices != null && vertices.Count > 0) { triangleBuilder.Vertices.AddRange(vertices); } } } } _dataMesh = RenderContext.MeshCreator.CreateMesh(triangleBuilder); var i = InitializeProgress; i?.Invoke(this, 100); InitializeProgress = null; Initialized = true; }
public List <GridCube> Сheck(double from, double to, double step) { var edgesPerSide = Region3D.GetLenght(from, to) / step; var countOfCubes = Math.Pow(edgesPerSide, 3); var vertexPerSide = edgesPerSide + 1; var uniqueEdgesPerSide = edgesPerSide * vertexPerSide; uniqueEdgesPerSide += uniqueEdgesPerSide; var edjesCount = vertexPerSide * uniqueEdgesPerSide + (vertexPerSide * vertexPerSide * edgesPerSide); var marchingCubes = new MarchingCubesAlgorithm(null); var region = new CommonTypes.Region3D(from, to, from, to, from, to); var cubes = marchingCubes.BuildGrid(region, step); Assert.AreEqual(cubes.Count, countOfCubes); var uniqueVertexes = new List <Point>(); // 18 unique edges var lines = new List <GridLine>(); foreach (var cube in cubes) { foreach (var edge in cube.Edges) { if (!lines.Contains(edge)) { lines.Add(edge); } } foreach (var vert in cube.Vertex) { // Check that objects are not created. Exclude overriden values. //if (!uniqueVertexes.Any(p => object.ReferenceEquals(uniqueVertexes, vert))) if (!uniqueVertexes.Contains(vert)) { uniqueVertexes.Add(vert); } } } var totalVertexes = vertexPerSide * vertexPerSide * vertexPerSide; Assert.AreEqual(uniqueVertexes.Count, totalVertexes); Assert.AreEqual(lines.Count, edjesCount); // Check last cube vertex var firstCube = cubes.FirstOrDefault(); CheckVertexes(firstCube, from, from + step); var lastCube = cubes.LastOrDefault(); CheckVertexes(lastCube, to - step, to); return(cubes); }
/// <summary> /// Creates a new instance of the visualizer /// </summary> /// <param name="renderContext"></param> /// <param name="inputData"></param> /// <param name="isoLevel"></param> public VisualizerBackgroundWorker(IRenderContext renderContext, IInputData inputData, int isoLevel) { _inputData = inputData; _isoLevel = isoLevel; _backgroundWorker = new BackgroundWorker(); _backgroundWorker.DoWork += MarchCube; _backgroundWorker.RunWorkerCompleted += CubeMarched; _mesh1 = renderContext.MeshCreator.CreateDynamicMesh(PrimitiveType.TriangleList, typeof(VertexPositionNormal), VertexPositionNormal.VertexDeclaration, DynamicMeshUsage.UpdateOften); _mesh2 = renderContext.MeshCreator.CreateDynamicMesh(PrimitiveType.TriangleList, typeof(VertexPositionNormal), VertexPositionNormal.VertexDeclaration, DynamicMeshUsage.UpdateOften); _vertices = new List <VertexPositionNormal>(); _marchingCubesAlgorithm = new MarchingCubesAlgorithm(false); // setup our indices so we don't have to recheck everytime we need this info // technically the marching cube algorithm will run over all cubes, but we will skip all that have 0 as a value // precalculate all the indices where data exists var data = new List <int>(); for (int z = 0; z < _inputData.ZLength - 1; z++) { for (int y = 0; y < _inputData.YLength - 1; y++) { for (int x = 0; x < _inputData.XLength - 1; x++) { // skipping doesn't work because it will skip edge cases such as flat surfaces // -> the cube doesn't have any data in it, but is next to one that does -> marching cubes will insert flat pane // if we skip it the final result will contain missing parts //if (_inputData[x, y, z] > 0) { var index = x + _inputData.XLength * (y + z * _inputData.YLength); data.Add(index); } } } } _filledDataIndices = data.ToArray(); _primitiveCountPerDataPoint = new int[_filledDataIndices.Length]; }