public void runClassifyVoxel()
        {
            var gpu = Gpu.Default;

            samplePts = ConvertPointsToFloat3(samplePoints);

            // allocate memorys
            var d_voxelVerts = gpu.Allocate <int>(numVoxels);

            float3[] d_samplePts = gpu.Allocate <float3>(samplePts);

            //Copy const values
            float3 baseP = new float3((float)basePoint.X, (float)basePoint.Y, (float)basePoint.Z);

            gpu.Copy(isoValue, constIsovalue);
            gpu.Copy(fusion, constFusion);
            gpu.Copy(baseP, constBasePoint);
            gpu.Copy(voxelSize, constVoxelSize);
            gpu.Copy(gridSize, constGridSize);
            gpu.Copy(Tables.VertsTable, verticesTable);

            gpu.For(0, numVoxels, i => ClassifyVoxel(i, d_samplePts, d_voxelVerts));
            voxelVerts = Gpu.CopyToHost(d_voxelVerts);

            Gpu.Free(d_samplePts);
            Gpu.Free(d_voxelVerts);
        }
        public void ClassifyVoxel(deviceptr <int3> d_gridIdx, deviceptr <float3> d_voxelV, deviceptr <int> d_voxelVerts,
                                  deviceptr <int> d_voxelOccupied, deviceptr <float3> d_samplePts, int sampleLength)
        {
            int blockId = blockIdx.y * gridDim.x + blockIdx.x; //block在grid中的位置
            int i       = blockId * blockDim.x + threadIdx.x;  //线程索引

            // compute 3d index in the grid
            int3 gridPos = calcGridPos(i, constGridSize.Value);

            d_gridIdx[i] = gridPos;
            float3 p = new float3();

            p.x = constBasePoint.Value.x + gridPos.x * constVoxelSize.Value.x;
            p.y = constBasePoint.Value.y + gridPos.y * constVoxelSize.Value.y;
            p.z = constBasePoint.Value.z + gridPos.z * constVoxelSize.Value.z;

            // compute all vertices
            d_voxelV[i * 8]     = p;
            d_voxelV[i * 8 + 1] = CreateFloat3(constVoxelSize.Value.x + p.x, 0 + p.y, 0 + p.z);
            d_voxelV[i * 8 + 2] = CreateFloat3(constVoxelSize.Value.x + p.x, constVoxelSize.Value.y + p.y, 0 + p.z);
            d_voxelV[i * 8 + 3] = CreateFloat3(0 + p.x, constVoxelSize.Value.y + p.y, 0 + p.z);
            d_voxelV[i * 8 + 4] = CreateFloat3(0 + p.x, 0 + p.y, constVoxelSize.Value.z + p.z);
            d_voxelV[i * 8 + 5] = CreateFloat3(constVoxelSize.Value.x + p.x, 0 + p.y, constVoxelSize.Value.z + p.z);
            d_voxelV[i * 8 + 6] = CreateFloat3(constVoxelSize.Value.x + p.x, constVoxelSize.Value.y + p.y, constVoxelSize.Value.z + p.z);
            d_voxelV[i * 8 + 7] = CreateFloat3(0 + p.x, constVoxelSize.Value.y + p.y, constVoxelSize.Value.z + p.z);

            // compute cube value of each vertex
            float d0 = ComputeValue(d_samplePts, d_voxelV[i * 8], sampleLength);
            float d1 = ComputeValue(d_samplePts, d_voxelV[i * 8 + 1], sampleLength);
            float d2 = ComputeValue(d_samplePts, d_voxelV[i * 8 + 2], sampleLength);
            float d3 = ComputeValue(d_samplePts, d_voxelV[i * 8 + 3], sampleLength);
            float d4 = ComputeValue(d_samplePts, d_voxelV[i * 8 + 4], sampleLength);
            float d5 = ComputeValue(d_samplePts, d_voxelV[i * 8 + 5], sampleLength);
            float d6 = ComputeValue(d_samplePts, d_voxelV[i * 8 + 6], sampleLength);
            float d7 = ComputeValue(d_samplePts, d_voxelV[i * 8 + 7], sampleLength);

            // check their status
            int cubeindex;

            cubeindex  = Compact(d0, constIsovalue.Value);
            cubeindex += Compact(d1, constIsovalue.Value) * 2;
            cubeindex += Compact(d2, constIsovalue.Value) * 4;
            cubeindex += Compact(d3, constIsovalue.Value) * 8;
            cubeindex += Compact(d4, constIsovalue.Value) * 16;
            cubeindex += Compact(d5, constIsovalue.Value) * 32;
            cubeindex += Compact(d6, constIsovalue.Value) * 64;
            cubeindex += Compact(d7, constIsovalue.Value) * 128;

            //find out the number of vertices in each voxel
            int numVerts = verticesTable[cubeindex];

            d_voxelVerts[i] = numVerts;
            if (numVerts > 0)
            {
                d_voxelOccupied[i] = 1;
            }
        }
        public float3 CreateFloat3(float x, float y, float z)
        {
            float3 p = new float3();

            p.x = x;
            p.y = y;
            p.z = z;
            return(p);
        }
 private float3[] ConvertPointsToFloat3(Point3d[] pts)
 {
     float3[] d = new float3[pts.Length];
     for (int i = 0; i < pts.Length; i++)
     {
         d[i].x = (float)pts[i].X;
         d[i].y = (float)pts[i].Y;
         d[i].z = (float)pts[i].Z;
     }
     return(d);
 }
        // classify all voxels according to their activity
        public void ClassifyVoxel(int i, float3[] d_samplePts, int[] d_voxelVerts)
        {
            //计算grid中的位置
            int3   gridPos = calcGridPos(i, constGridSize.Value);
            float3 p       = new float3();

            p.x = constBasePoint.Value.x + gridPos.x * constVoxelSize.Value.x;
            p.y = constBasePoint.Value.y + gridPos.y * constVoxelSize.Value.y;
            p.z = constBasePoint.Value.z + gridPos.z * constVoxelSize.Value.z;

            //输出所有顶点
            float3 a0 = p;
            float3 a1 = CreateFloat3(constVoxelSize.Value.x + p.x, 0 + p.y, 0 + p.z);
            float3 a2 = CreateFloat3(constVoxelSize.Value.x + p.x, constVoxelSize.Value.y + p.y, 0 + p.z);
            float3 a3 = CreateFloat3(0 + p.x, constVoxelSize.Value.y + p.y, 0 + p.z);
            float3 a4 = CreateFloat3(0 + p.x, 0 + p.y, constVoxelSize.Value.z + p.z);
            float3 a5 = CreateFloat3(constVoxelSize.Value.x + p.x, 0 + p.y, constVoxelSize.Value.z + p.z);
            float3 a6 = CreateFloat3(constVoxelSize.Value.x + p.x, constVoxelSize.Value.y + p.y, constVoxelSize.Value.z + p.z);
            float3 a7 = CreateFloat3(0 + p.x, constVoxelSize.Value.y + p.y, constVoxelSize.Value.z + p.z);

            float distance = constVoxelSize.Value.x * constVoxelSize.Value.x +
                             constVoxelSize.Value.y * constVoxelSize.Value.y + constVoxelSize.Value.z * constVoxelSize.Value.z;
            float radius = distance * constFusion.Value;

            //计算cube中的8个点对应的value
            float d0 = ComputeValue(d_samplePts, a0, d_samplePts.Length, constFusion.Value, radius);
            float d1 = ComputeValue(d_samplePts, a1, d_samplePts.Length, constFusion.Value, radius);
            float d2 = ComputeValue(d_samplePts, a2, d_samplePts.Length, constFusion.Value, radius);
            float d3 = ComputeValue(d_samplePts, a3, d_samplePts.Length, constFusion.Value, radius);
            float d4 = ComputeValue(d_samplePts, a4, d_samplePts.Length, constFusion.Value, radius);
            float d5 = ComputeValue(d_samplePts, a5, d_samplePts.Length, constFusion.Value, radius);
            float d6 = ComputeValue(d_samplePts, a6, d_samplePts.Length, constFusion.Value, radius);
            float d7 = ComputeValue(d_samplePts, a7, d_samplePts.Length, constFusion.Value, radius);

            //判定它们的状态
            int cubeindex;

            cubeindex  = Compact(d0, constIsovalue.Value);
            cubeindex += Compact(d1, constIsovalue.Value) * 2;
            cubeindex += Compact(d2, constIsovalue.Value) * 4;
            cubeindex += Compact(d3, constIsovalue.Value) * 8;
            cubeindex += Compact(d4, constIsovalue.Value) * 16;
            cubeindex += Compact(d5, constIsovalue.Value) * 32;
            cubeindex += Compact(d6, constIsovalue.Value) * 64;
            cubeindex += Compact(d7, constIsovalue.Value) * 128;

            //根据表来查出该体素的顶点数
            int vertexNum = verticesTable[cubeindex];

            d_voxelVerts[i] = vertexNum;
        }
        public float ComputeValue(deviceptr <float3> samplePts, float3 testP, int sampleLength)
        {
            float result = 0.0f;
            float Dx, Dy, Dz;

            for (int j = 0; j < sampleLength; j++)
            {
                Dx = testP.x - samplePts[j].x;
                Dy = testP.y - samplePts[j].y;
                Dz = testP.z - samplePts[j].z;

                result += 1 / (Dx * Dx + Dy * Dy + Dz * Dz);
            }
            return(result);
        }
        public float ComputeValue(float3[] samplePts, float3 testP, int sampleLength, float fusion, float radius)
        {
            float result = 0.0f;
            float Dx, Dy, Dz;

            for (int j = 0; j < sampleLength; j++)
            {
                Dx = testP.x - samplePts[j].x;
                Dy = testP.y - samplePts[j].y;
                Dz = testP.z - samplePts[j].z;

                // very slow field function
                // result += 1.0f / (Dx * Dx + Dy * Dy + Dz * Dz);
                // field function of soft object
                float di = Dx * Dx + Dy * Dy + Dz * Dz;
                if (di <= radius)
                {
                    float a = di / radius;
                    result += (1.0f - (a * a * a * a * a * a * 4.0f / 9.0f) + (a * a * a * a * 17.0f / 9.0f) - (a * a * 22.0f / 9.0f));
                }
            }
            return(result);
        }
        public void ExtractIsoSurface(deviceptr <float> d_cubeValues, deviceptr <float3> d_pts, deviceptr <float3> Apts,
                                      deviceptr <int3> d_index3d_voxelActive, deviceptr <float3> d_model_voxelActive, deviceptr <float3> d_samplePts, deviceptr <int> d_verts_scanIdx, int sampleLength)
        {
            int blockId = blockIdx.y * gridDim.x + blockIdx.x;
            int i       = blockId * blockDim.x + threadIdx.x;

            //Compute cubeValues of 8 vertices
            d_cubeValues[i * 8]     = ComputeValue(d_samplePts, d_model_voxelActive[i * 8], sampleLength);
            d_cubeValues[i * 8 + 1] = ComputeValue(d_samplePts, d_model_voxelActive[i * 8 + 1], sampleLength);
            d_cubeValues[i * 8 + 2] = ComputeValue(d_samplePts, d_model_voxelActive[i * 8 + 2], sampleLength);
            d_cubeValues[i * 8 + 3] = ComputeValue(d_samplePts, d_model_voxelActive[i * 8 + 3], sampleLength);
            d_cubeValues[i * 8 + 4] = ComputeValue(d_samplePts, d_model_voxelActive[i * 8 + 4], sampleLength);
            d_cubeValues[i * 8 + 5] = ComputeValue(d_samplePts, d_model_voxelActive[i * 8 + 5], sampleLength);
            d_cubeValues[i * 8 + 6] = ComputeValue(d_samplePts, d_model_voxelActive[i * 8 + 6], sampleLength);
            d_cubeValues[i * 8 + 7] = ComputeValue(d_samplePts, d_model_voxelActive[i * 8 + 7], sampleLength);

            //Check each vertex state
            int flag = Compact(d_cubeValues[i * 8], constIsovalue.Value);

            flag += Compact(d_cubeValues[i * 8 + 1], constIsovalue.Value) * 2;
            flag += Compact(d_cubeValues[i * 8 + 2], constIsovalue.Value) * 4;
            flag += Compact(d_cubeValues[i * 8 + 3], constIsovalue.Value) * 8;
            flag += Compact(d_cubeValues[i * 8 + 4], constIsovalue.Value) * 16;
            flag += Compact(d_cubeValues[i * 8 + 5], constIsovalue.Value) * 32;
            flag += Compact(d_cubeValues[i * 8 + 6], constIsovalue.Value) * 64;
            flag += Compact(d_cubeValues[i * 8 + 7], constIsovalue.Value) * 128;

            //find out which edge intersects the isosurface
            int EdgeFlag = edgeTable[flag];

            //check whether this voxel is crossed by the isosurface
            for (int j = 0; j < 12; j++)
            {
                //check whether an edge have a point
                if ((EdgeFlag & (1 << j)) != 0)
                {
                    //compute t values from two end points on each edge
                    float  Offset = GetOffset(d_cubeValues[i * 8 + constEdgeConnection[j * 2 + 0]], d_cubeValues[i * 8 + constEdgeConnection[j * 2 + 1]], constIsovalue.Value);
                    float3 pt     = new float3();
                    //get positions
                    pt.x = constBasePoint.Value.x + (d_index3d_voxelActive[i].x + constVertices[constEdgeConnection[j * 2 + 0] * 3 + 0] + Offset * constEdgeDirection[j * 3 + 0]) * constScale.Value;
                    pt.y = constBasePoint.Value.y + (d_index3d_voxelActive[i].y + constVertices[constEdgeConnection[j * 2 + 0] * 3 + 1] + Offset * constEdgeDirection[j * 3 + 1]) * constScale.Value;
                    pt.z = constBasePoint.Value.z + (d_index3d_voxelActive[i].z + constVertices[constEdgeConnection[j * 2 + 0] * 3 + 2] + Offset * constEdgeDirection[j * 3 + 2]) * constScale.Value;
                    d_pts[12 * i + j] = pt;
                }
            }
            int num = 0;

            //Find out points from each triangle
            for (int Triangle = 0; Triangle < 5; Triangle++)
            {
                if (triangleTable[flag * 16 + 3 * Triangle] < 0)
                {
                    break;
                }

                for (int Corner = 0; Corner < 3; Corner++)
                {
                    int    Vertex = triangleTable[flag * 16 + 3 * Triangle + Corner];
                    float3 pd     = CreateFloat3(d_pts[12 * i + Vertex].x, d_pts[12 * i + Vertex].y, d_pts[12 * i + Vertex].z);
                    Apts[d_verts_scanIdx[i] + num] = pd;
                    num++;
                }
            }
        }
        // extract isosurface points using GPU
        public List <Point3f> runExtractIsoSurfaceGPU()
        {
            var gpu = Gpu.Default;

            // output arguments
            float3[] pts          = new float3[12 * num_voxelActive];
            float3[] d_pts        = Gpu.Default.Allocate <float3>(pts);
            float3[] d_resultV    = Gpu.Default.Allocate <float3>(sumVerts);
            float[]  d_cubeValues = Gpu.Default.Allocate <float>(8 * num_voxelActive);

            // input arguments
            float3[] d_samplePts         = Gpu.Default.Allocate <float3>(samplePts);
            int[]    d_verts_scanIdx     = Gpu.Default.Allocate <int>(verts_scanIdx);
            int[]    d_index_voxelActive = Gpu.Default.Allocate <int>(index_voxelActive);

            // const values
            gpu.Copy(Vertices, constVertices);
            gpu.Copy(EdgeDirection, constEdgeDirection);
            gpu.Copy(EdgeConnection, constEdgeConnection);
            gpu.Copy(Tables.EdgeTable, edgeTable);
            gpu.Copy(Tables.TriangleTable_GPU, triangleTable);

            float3 baseP = new float3((float)basePoint.X, (float)basePoint.Y, (float)basePoint.Z);

            gpu.Copy(baseP, constBasePoint);
            gpu.Copy(isoValue, constIsovalue);
            gpu.Copy(scale, constScale);


            gpu.For(0, num_voxelActive, i =>
            {
                //计算grid中的位置
                int3 gridPos = calcGridPos(d_index_voxelActive[i], constGridSize.Value);
                float3 p     = new float3();

                p.x = constBasePoint.Value.x + gridPos.x * constVoxelSize.Value.x;
                p.y = constBasePoint.Value.y + gridPos.y * constVoxelSize.Value.y;
                p.z = constBasePoint.Value.z + gridPos.z * constVoxelSize.Value.z;

                //输出所有顶点
                float3 a0 = p;
                float3 a1 = CreateFloat3(constVoxelSize.Value.x + p.x, 0 + p.y, 0 + p.z);
                float3 a2 = CreateFloat3(constVoxelSize.Value.x + p.x, constVoxelSize.Value.y + p.y, 0 + p.z);
                float3 a3 = CreateFloat3(0 + p.x, constVoxelSize.Value.y + p.y, 0 + p.z);
                float3 a4 = CreateFloat3(0 + p.x, 0 + p.y, constVoxelSize.Value.z + p.z);
                float3 a5 = CreateFloat3(constVoxelSize.Value.x + p.x, 0 + p.y, constVoxelSize.Value.z + p.z);
                float3 a6 = CreateFloat3(constVoxelSize.Value.x + p.x, constVoxelSize.Value.y + p.y, constVoxelSize.Value.z + p.z);
                float3 a7 = CreateFloat3(0 + p.x, constVoxelSize.Value.y + p.y, constVoxelSize.Value.z + p.z);

                float distance = constVoxelSize.Value.x * constVoxelSize.Value.x +
                                 constVoxelSize.Value.y * constVoxelSize.Value.y + constVoxelSize.Value.z * constVoxelSize.Value.z;
                float radius = distance * constFusion.Value;

                //Compute cubeValues of 8 vertices
                d_cubeValues[i * 8]     = ComputeValue(d_samplePts, a0, d_samplePts.Length, constFusion.Value, radius);
                d_cubeValues[i * 8 + 1] = ComputeValue(d_samplePts, a1, d_samplePts.Length, constFusion.Value, radius);
                d_cubeValues[i * 8 + 2] = ComputeValue(d_samplePts, a2, d_samplePts.Length, constFusion.Value, radius);
                d_cubeValues[i * 8 + 3] = ComputeValue(d_samplePts, a3, d_samplePts.Length, constFusion.Value, radius);
                d_cubeValues[i * 8 + 4] = ComputeValue(d_samplePts, a4, d_samplePts.Length, constFusion.Value, radius);
                d_cubeValues[i * 8 + 5] = ComputeValue(d_samplePts, a5, d_samplePts.Length, constFusion.Value, radius);
                d_cubeValues[i * 8 + 6] = ComputeValue(d_samplePts, a6, d_samplePts.Length, constFusion.Value, radius);
                d_cubeValues[i * 8 + 7] = ComputeValue(d_samplePts, a7, d_samplePts.Length, constFusion.Value, radius);

                //Check each vertex state
                int flag = Compact(d_cubeValues[i * 8], constIsovalue.Value);
                flag    += Compact(d_cubeValues[i * 8 + 1], constIsovalue.Value) * 2;
                flag    += Compact(d_cubeValues[i * 8 + 2], constIsovalue.Value) * 4;
                flag    += Compact(d_cubeValues[i * 8 + 3], constIsovalue.Value) * 8;
                flag    += Compact(d_cubeValues[i * 8 + 4], constIsovalue.Value) * 16;
                flag    += Compact(d_cubeValues[i * 8 + 5], constIsovalue.Value) * 32;
                flag    += Compact(d_cubeValues[i * 8 + 6], constIsovalue.Value) * 64;
                flag    += Compact(d_cubeValues[i * 8 + 7], constIsovalue.Value) * 128;

                //find out which edge intersects the isosurface
                int EdgeFlag = edgeTable[flag];

                //check whether this voxel is crossed by the isosurface
                for (int j = 0; j < 12; j++)
                {
                    //check whether an edge have a point
                    if ((EdgeFlag & (1 << j)) != 0)
                    {
                        //compute t values from two end points on each edge
                        float Offset = GetOffset(d_cubeValues[i * 8 + constEdgeConnection[j * 2 + 0]], d_cubeValues[i * 8 + constEdgeConnection[j * 2 + 1]], constIsovalue.Value);
                        float3 pt    = new float3();
                        //get positions
                        pt.x = constBasePoint.Value.x + (gridPos.x + constVertices[constEdgeConnection[j * 2 + 0] * 3 + 0] + Offset * constEdgeDirection[j * 3 + 0]) * constScale.Value;
                        pt.y = constBasePoint.Value.y + (gridPos.y + constVertices[constEdgeConnection[j * 2 + 0] * 3 + 1] + Offset * constEdgeDirection[j * 3 + 1]) * constScale.Value;
                        pt.z = constBasePoint.Value.z + (gridPos.z + constVertices[constEdgeConnection[j * 2 + 0] * 3 + 2] + Offset * constEdgeDirection[j * 3 + 2]) * constScale.Value;
                        d_pts[12 * i + j] = pt;
                    }
                }
                int num = 0;
                //Find out points from each triangle
                for (int Triangle = 0; Triangle < 5; Triangle++)
                {
                    if (triangleTable[flag * 16 + 3 * Triangle] < 0)
                    {
                        break;
                    }

                    for (int Corner = 0; Corner < 3; Corner++)
                    {
                        int Vertex = triangleTable[flag * 16 + 3 * Triangle + Corner];
                        float3 pd  = CreateFloat3(d_pts[12 * i + Vertex].x, d_pts[12 * i + Vertex].y, d_pts[12 * i + Vertex].z);
                        d_resultV[d_verts_scanIdx[i] + num] = pd;
                        num++;
                    }
                }
            });
            resultVerts = Gpu.CopyToHost(d_resultV);

            Gpu.Free(d_resultV);
            Gpu.Free(d_pts);
            Gpu.Free(d_samplePts);
            Gpu.Free(d_verts_scanIdx);
            Gpu.Free(d_index_voxelActive);

            return(ConvertFloat3ToPoint3f(resultVerts));
        }