public static BitMap3d CreateSampleForLobsterX2() { BitMap3d image = new BitMap3d(602, 648, 112, BitMap3d.BLACK); image.ReadRaw("D://VTKproj//lobsterx2.raw"); byte[] data = image.data; for (int i = 0; i < data.Length; i++) { if (data[i] >= 37 && data[i] <= 255) { data[i] = BitMap3d.WHITE; } else { data[i] = BitMap3d.BLACK; } } for (int k = 0; k < image.depth; k++) { for (int j = 0; j < image.height; j++) { for (int i = 0; i < image.width; i++) { int index = k * image.width * image.height + j * image.width + i; if (i == 0 || i == image.width - 1 || j == 0 || j == image.height - 1 || k == 0 || k == image.depth - 1) { data[index] = BitMap3d.BLACK; } } } } return(image); }
public static void Test4() { BitMap3d image = BitMap3d.CreateSampleForLobsterX2(); Mesh m = OctreeSurfaceGenerator.GenerateSurface(image); PlyManager.Output(m, "Tree_Lobster_602.ply"); }
public static void Test3() { BitMap3d image = BitMap3d.CreateSampleForFan(); Mesh m = OctreeSurfaceGenerator.GenerateSurface(image); PlyManager.Output(m, "D://VTKproj//Tree_Fan.ply"); }
public static void Test2() { string str = "x2"; BitMap3d image = BitMap3d.CreateSampleEngineVolume(str); Mesh m = OctreeSurfaceGenerator.GenerateSurface(image); PlyManager.Output(m, "D://VTKproj//Tree_Engine" + str + ".ply"); }
public static void Test1() { int width = 400; BitMap3d image = BitMap3d.CreateSampleTedVolume(width); Mesh m = OctreeSurfaceGenerator.GenerateSurface(image); PlyManager.Output(m, string.Format("D://VTKproj//Tree_Ted_{0}.ply", width)); }
public static BitMap3d CreateSampleTedVolume(int is400_300_200_100) { BitMap3d image = new BitMap3d(is400_300_200_100, is400_300_200_100, is400_300_200_100, BitMap3d.BLACK); image.ReadRaw(string.Format("D://VTKproj//Ted_{0}.raw", is400_300_200_100)); byte[] data = image.data; for (int i = 0; i < data.Length; i++) { if (data[i] > 128) { data[i] = BitMap3d.WHITE; } else { data[i] = BitMap3d.BLACK; } } return(image); }
public static BitMap3d CreateSampleEngineVolume(string x2) { BitMap3d image; if (x2 == "") { image = new BitMap3d(256, 256, 128, BitMap3d.BLACK); image.ReadRaw("D://VTKproj//engine.raw"); } else { image = new BitMap3d(512, 512, 256, BitMap3d.BLACK); image.ReadRaw("D://VTKproj//enginex2.raw"); } byte[] data = image.data; for (int i = 0; i < data.Length; i++) { if (data[i] >= 64 && data[i] <= 255) { data[i] = BitMap3d.WHITE; } else { data[i] = BitMap3d.BLACK; } } for (int k = 0; k < image.depth; k++) { for (int j = 0; j < image.height; j++) { for (int i = 0; i < image.width; i++) { int index = k * image.width * image.height + j * image.width + i; if (i == 0 || i == image.width - 1 || j == 0 || j == image.height - 1 || k == 0 || k == image.depth - 1) { data[index] = BitMap3d.BLACK; } } } } return(image); }
public static Mesh GenerateSurface(BitMap3d bmp) { int width = bmp.width; int height = bmp.height; int depth = bmp.depth; Int16Triple[] tempArray = new Int16Triple[8]; #region CreateTree RegionOctree <NodeParms> otree = new RegionOctree <NodeParms>(width, height, depth); Queue <OctreeNode <NodeParms> > nodequeue = new Queue <OctreeNode <NodeParms> >(); for (int k = 0; k < depth - 1; k++) { for (int j = 0; j < height - 1; j++) { for (int i = 0; i < width - 1; i++) { byte value = 0; for (int pi = 0; pi < 8; pi++) { tempArray[pi].X = i + PointIndexToPointDelta[pi].X; tempArray[pi].Y = j + PointIndexToPointDelta[pi].Y; tempArray[pi].Z = k + PointIndexToPointDelta[pi].Z; if (InRange(bmp, tempArray[pi].X, tempArray[pi].Y, tempArray[pi].Z) && IsWhite(bmp, tempArray[pi].X, tempArray[pi].Y, tempArray[pi].Z)) { value |= PointIndexToFlag[pi]; } } if (value != 0 && value != 255) { OctreeNode <NodeParms> leafnode = otree.CreateToLeafNode(i, j, k); leafnode.Parms = new NodeParms(); leafnode.Parms.Config = value; leafnode.Parms.NormalTypeId = OctreeTable.ConfigToNormalTypeId[value]; leafnode.Parms.D = CaculateDFromNormalAndCoord(i, j, k, value); nodequeue.Enqueue(leafnode.Parent); } } } } #endregion #region Shrink while (nodequeue.Count != 0) { OctreeNode <NodeParms> node = nodequeue.Dequeue(); byte normalType = OctreeTable.NormalNotSimple; int D = int.MinValue; if (CanMergeNode(node, ref normalType, ref D)) { node.Parms = new NodeParms(); //node.Parms.Config = GetConfigFromChildren(node.Children); node.Parms.NormalTypeId = normalType; node.Parms.D = D; nodequeue.Enqueue(node.Parent); } } #endregion #region ExtractTriangles MeshBuilder_IntegerVertex mb = new MeshBuilder_IntegerVertex(width + 1, height + 1, depth + 1); nodequeue.Enqueue(otree.Root); while (nodequeue.Count != 0) { OctreeNode <NodeParms> node = nodequeue.Dequeue(); if (node.Parms == null) { for (int i = 0; i < 8; i++) { if (node.Children[i] != null) { nodequeue.Enqueue(node.Children[i]); } } } else { if (node.Parms.NormalTypeId != OctreeTable.NormalNotSimple) { if (node.IsLeaf()) { GenerateFaceLeaf(node, mb, ref tempArray, bmp); } else { GenerateFace(node, mb, ref tempArray, bmp); } } else { if (node.IsLeaf()) { GenerateFaceLeaf(node, mb, ref tempArray, bmp); } else { for (int i = 0; i < 8; i++) { if (node.Children[i] != null) { nodequeue.Enqueue(node.Children[i]); } } } } } }//采用层次遍历寻找需要抽取三角片的节点 #endregion return(mb.GetMesh()); }
}//对非叶子节点的超体元的抽取需要参考MCTable求取被截断边的信息 private static void GenerateFaceLeaf(OctreeNode <NodeParms> node, MeshBuilder_IntegerVertex mb, ref Int16Triple[] tempArray, BitMap3d bmp) { for (int k = 0; k < 8; k++) { tempArray[k].X = node.XMin + PointIndexToPointDelta[k].X; tempArray[k].Y = node.YMin + PointIndexToPointDelta[k].Y; tempArray[k].Z = node.ZMin + PointIndexToPointDelta[k].Z; } byte value = node.Parms.Config; int index = 0; while (SMCTable.TableFat[value, index] != -1) { Int16Triple t0 = tempArray[SMCTable.TableFat[value, index]]; Int16Triple t1 = tempArray[SMCTable.TableFat[value, index + 1]]; Int16Triple t2 = tempArray[SMCTable.TableFat[value, index + 2]]; mb.AddTriangle(t0, t1, t2); index += 3; } }//对叶子节点的单位体元的抽取和SMC算法中的抽取一致
private static void GenerateFace(OctreeNode <NodeParms> node, MeshBuilder_IntegerVertex mb, ref Int16Triple[] tempArray, BitMap3d bmp) { InitVoxelPositionForNodeRange(node.XMin, node.XMax, node.YMin, node.YMax, node.ZMin, node.ZMax, ref tempArray); //需要找到该节点的端点位置 byte cubeConfig = 0; for (int pi = 0; pi < 8; pi++) { if (InRange(bmp, tempArray[pi].X, tempArray[pi].Y, tempArray[pi].Z) && IsWhite(bmp, tempArray[pi].X, tempArray[pi].Y, tempArray[pi].Z)) { cubeConfig |= PointIndexToFlag[pi]; } } int index = 0; while (MCTable.TriTable[cubeConfig, index] != -1) { int ei1 = MCTable.TriTable[cubeConfig, index]; int ei2 = MCTable.TriTable[cubeConfig, index + 1]; int ei3 = MCTable.TriTable[cubeConfig, index + 2]; Int16Triple p1 = GetIntersetedPointAtEdge(node, ei1, OctreeTable.NormalTypeIdToNormal[node.Parms.NormalTypeId], node.Parms.D); Int16Triple p2 = GetIntersetedPointAtEdge(node, ei2, OctreeTable.NormalTypeIdToNormal[node.Parms.NormalTypeId], node.Parms.D); Int16Triple p3 = GetIntersetedPointAtEdge(node, ei3, OctreeTable.NormalTypeIdToNormal[node.Parms.NormalTypeId], node.Parms.D); mb.AddTriangle(p1, p2, p3); index += 3; } }//对非叶子节点的超体元的抽取需要参考MCTable求取被截断边的信息
private static bool IsWhite(BitMap3d bmp, int x, int y, int z) { return(bmp.GetPixel(x, y, z) == BitMap3d.WHITE); }
private static bool InRange(BitMap3d bmp, int x, int y, int z) { return(x > 0 && x < bmp.width && y > 0 && y < bmp.height && z > 0 && z < bmp.depth); }