/// <summary> /// Test intersections in 3D on a big dataset. /// </summary> public static void TestIntersectExampleData() { var parser = new Parser(); var generators = new List <Vertex>(); using (var streamReader = new StreamReader("Data/exampleVoronoi.txt")) { int i = 0; string line; while ((line = streamReader.ReadLine()) != null) { var vertex = parser.ParseVertex(line); vertex.Index = i; generators.Add(vertex); i++; } } var reader = new TriangulationReader(); var tetrahedralization = reader.Read("Data/exampleTetra.dat"); for (int i = 0; i < tetrahedralization.Indices.Count; i++) { var indices = tetrahedralization.Indices[i].Indices; for (int j = 0; j < indices.Length; j++) { indices[j] = indices[j] - 1; } } //var boundingBox = CreateBoundingBox3D(tetrahedralization.Vertices); //var voronoiData = new VolumeData3D(); //voronoiData.FromVoronoi(generators); var tetrahedralizationData = new VolumeData3D(); tetrahedralizationData.FromTriangulation(tetrahedralization.Vertices, tetrahedralization.Indices); //var bitmap = new System.Drawing.Bitmap(800, 800); //VolumeVisualisator.Visualise3D(bitmap, 0.4, voronoiData, boundingBox); //bitmap.Save("export000.png"); //bitmap = new System.Drawing.Bitmap(800, 800); //VolumeVisualisator.Visualise3D(bitmap, 0.4, tetrahedralizationData, boundingBox); //bitmap.Save("example.png"); var volumeIntersection = new VolumeIntersection3D(new BruteForceHalfSpaceRemoval3D()); var volumeData = volumeIntersection.Intersect(tetrahedralization.Vertices, tetrahedralization.Indices, generators); var writer = new VolumeData3DWriter(','); writer.Write("exampleIntersection.txt", volumeData); //bitmap = new System.Drawing.Bitmap(800, 800); //VolumeVisualisator.Visualise3D(bitmap, 0.4, volumeData, boundingBox); //bitmap.Save("intersectExample.png"); }
/// <summary> /// Visualises a slice of a 3D volumetric data. /// </summary> /// <param name="bitmap">Bitmap that contains the visualisation.</param> /// <param name="zValue">Slicing value.</param> /// <param name="volume">3D Volumetric data.</param> /// <param name="volumeBoundingBox">Bounding box.</param> public static void Visualise3D(Bitmap bitmap, double zValue, VolumeData3D volume, BoundingBox3D volumeBoundingBox) { // Setup color of each cell var colors = SetupColors(volume.Cells.Count); // Access bitmap data int width = bitmap.Width; int height = bitmap.Height; BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); unsafe { // Get pointer to bitmap data byte *pointer = (byte *)bitmapData.Scan0; // Setup a point var point = new Vector3D(); point.Z = zValue; // For each pixel of a bitmap find a cell and color the pixel. for (int i = 0; i < height; i++) { // Remap pixel to a position in 3D space. point.Y = MathUtils.Remap(i, 0, height, volumeBoundingBox.Max.Y, volumeBoundingBox.Min.Y); for (int j = 0; j < width; j++) { // Remap pixel to a position in 3D space point.X = MathUtils.Remap(j, 0, width, volumeBoundingBox.Min.X, volumeBoundingBox.Max.X); // For each cell check if it contains the point for (int k = 0; k < volume.Cells.Count; k++) { if (volume.Cells[k].Contains(point)) { // Color the pixel pointer[0] = colors[k].B; pointer[1] = colors[k].G; pointer[2] = colors[k].R; pointer[3] = colors[k].A; break; } } pointer += BytesPerPixel; } } } bitmap.UnlockBits(bitmapData); }
/// <summary> /// Test triangulation volumetric data in 3D. /// </summary> public static void TestFromTriangulationSingleTetrahedron() { var vertices = new List <Vertex>() { new Vertex(0, 0, 0), new Vertex(1, 0, 0), new Vertex(0, 1, 0), new Vertex(0, 0, 1) }; var tetrahedra = new List <Triangle>() { new Triangle(0, 1, 2, 3) }; var volumeData = new VolumeData3D(); volumeData.FromTriangulation(vertices, tetrahedra); }
/// <summary> /// Test intersection in 3D on a small dataset. /// </summary> public static void TestIntersectSmallData() { var reader = new TriangulationReader(); var tetrahedralization = reader.Read("Data/smallTetra.dat"); Random rd = new Random(); var generators = new List <Vertex>(); for (int i = 0; i < 5; i++) { generators.Add(new Vertex(rd.NextDouble() * 0.6 + 0.1, rd.NextDouble() * 0.9, rd.NextDouble() * 0.7 + 0.2) { Index = i }); } var boundingBox = CreateBoundingBox3D(tetrahedralization.Vertices); var voronoiData = new VolumeData3D(); voronoiData.FromVoronoi(generators); var tetrahedralizationData = new VolumeData3D(); tetrahedralizationData.FromTriangulation(tetrahedralization.Vertices, tetrahedralization.Indices); var bitmap = new System.Drawing.Bitmap(800, 800); VolumeVisualisator.Visualise3D(bitmap, 0.4, voronoiData, boundingBox); bitmap.Save("smallVoronoi.png"); bitmap = new System.Drawing.Bitmap(800, 800); VolumeVisualisator.Visualise3D(bitmap, 0.4, tetrahedralizationData, boundingBox); bitmap.Save("smallTetra.png"); var volumeData = new VolumeIntersection3D(new BruteForceHalfSpaceRemoval3D()).Intersect(tetrahedralization.Vertices, tetrahedralization.Indices, generators); bitmap = new System.Drawing.Bitmap(800, 800); VolumeVisualisator.Visualise3D(bitmap, 0.4, volumeData, boundingBox); bitmap.Save("intersectSmallData.png"); }
/// <summary> /// Test voronoi volumetric data in 3D /// </summary> public static void TestFromVoronoi3D() { var generators = new List <Vertex>() { new Vertex(1, 0, 0) { Index = 0 }, new Vertex(0, 0, 0) { Index = 1 }, new Vertex(-1, 0, 0) { Index = 2 }, new Vertex(0, 1, 0) { Index = 3 }, new Vertex(0, -1, 0) { Index = 4 }, new Vertex(0, 0, 1) { Index = 5 }, new Vertex(0, 0, -1) { Index = 6 } }; var volumeData = new VolumeData3D(); volumeData.FromVoronoi(generators); }
/// <summary> /// Writer 3D volumetric data to a file. /// </summary> /// <param name="path">Path of a file.</param> /// <param name="volumeData">3D data.</param> public void Write(string path, VolumeData3D volumeData) { StreamWriter writer = new StreamWriter(path); writer.WriteLine("# centroid.X" + separator + "centroid.Y" + separator + "centroid.Z" + separator + "triangleIndex" + separator + "voronoiIndex" + separator + "weight" + separator + "visited" + separator + "edgeIndices"); var edgeList = new List <Edge3D>(); foreach (var cell in volumeData.Cells) { writer.Write(cell.Centroid.X); writer.Write(separator); writer.Write(cell.Centroid.Y); writer.Write(separator); writer.Write(cell.Centroid.Z); writer.Write(separator); writer.Write(cell.TriangleIndex); writer.Write(separator); writer.Write(cell.VoronoiIndex); writer.Write(separator); writer.Write(cell.Weight); writer.Write(separator); writer.Write(cell.Visited); for (int i = 0; i < cell.Edges.Count; i++) { writer.Write(separator); writer.Write(edgeList.Count); edgeList.Add(cell.Edges[i]); } writer.WriteLine(); } writer.WriteLine("# normal.x" + separator + "normal.y" + separator + "normal.z" + separator + "c" + separator + "sourceIndex" + separator + "targetIndex"); foreach (var edge in edgeList) { writer.Write(edge.Normal.X); writer.Write(separator); writer.Write(edge.Normal.Y); writer.Write(separator); writer.Write(edge.Normal.Z); writer.Write(separator); writer.Write(edge.C); writer.Write(separator); int sourceIndex = -1; int targetIndex = -1; for (int i = 0; i < volumeData.Cells.Count; i++) { if (volumeData.Cells[i] == edge.Source) { sourceIndex = i; } if (volumeData.Cells[i] == edge.Target) { targetIndex = i; } if (sourceIndex != -1 && targetIndex != -1) { break; } } writer.Write(sourceIndex); writer.Write(separator); writer.Write(targetIndex); writer.WriteLine(); } writer.Close(); }