# Implmentation of flying-edges.

**URL:** https://discourse.vtk.org/t/implmentation-of-flying-edges/14806
**Category:** Support
**Created:** [November 1, 2024, 9:04pm UTC](https://discourse.vtk.org/t/implmentation-of-flying-edges/14806 "2024-11-01T21:04:43Z")
**Posts on this page:** 8
**Page:** 1

<div class="post-metadata">

### Author: ![Anant\_Bharti](https://discourse.vtk.org/user_avatar/discourse.vtk.org/anant_bharti/32/8464_2.png) [@Anant\_Bharti](https://discourse.vtk.org/u/Anant_Bharti)
#### Post date: [November 1, 2024, 9:04pm UTC](https://discourse.vtk.org/t/implmentation-of-flying-edges/14806/1 "2024-11-01T21:04:43Z")

</div>

Hi, I am trying to implement flying-edges. Can somebody help me? I am working on a software which previously using marching cubes and I am shifting it flying-edges. (3d). Is this the right place to ask a question here?

---

<div class="post-metadata">

### Author: ![amaclean](https://discourse.vtk.org/user_avatar/discourse.vtk.org/amaclean/32/224_2.png) [@amaclean](https://discourse.vtk.org/u/amaclean)
#### Post date: [November 2, 2024, 7:58am UTC](https://discourse.vtk.org/t/implmentation-of-flying-edges/14806/2 "2024-11-02T07:58:19Z")

</div>

Look in the VTK Examples, there are arouund 10 C++ examples (with corresponding Python ones) using vtkFlyingEdges3D, may of these examples also use vtkMarchingCubes as an option. E.g. (MedicalDemo1)[[https://examples.vtk.org/site/Cxx/Medical/MedicalDemo1/](https://examples.vtk.org/site/Cxx/Medical/MedicalDemo1/)], also here is a list of classes demonstraten in the examples: [VTK Classes Used](https://examples.vtk.org/site/Cxx/Coverage/CxxVTKClassesUsed/)

---

<div class="post-metadata">

### Author: ![will.schroeder](https://discourse.vtk.org/user_avatar/discourse.vtk.org/will.schroeder/32/233_2.png) [@will.schroeder](https://discourse.vtk.org/u/will.schroeder)
#### Post date: [November 2, 2024, 2:43pm UTC](https://discourse.vtk.org/t/implmentation-of-flying-edges/14806/3 "2024-11-02T14:43:42Z")

</div>

Hopefully you’ve read the paper:  
[https://www.researchgate.net/publication/282975362\_Flying\_Edges\_A\_High-Performance\_Scalable\_Isocontouring\_Algorithm](https://www.researchgate.net/publication/282975362_Flying_Edges_A_High-Performance_Scalable_Isocontouring_Algorithm).

---

<div class="post-metadata">

### Author: ![Anant\_Bharti](https://discourse.vtk.org/user_avatar/discourse.vtk.org/anant_bharti/32/8464_2.png) [@Anant\_Bharti](https://discourse.vtk.org/u/Anant_Bharti)
#### Post date: [November 3, 2024, 2:57pm UTC](https://discourse.vtk.org/t/implmentation-of-flying-edges/14806/4 "2024-11-03T14:57:11Z")

</div>

thankyou so much WILL. I have read that and I feel I have implemented the same way as they have described. But My output comes out to be something like this:

![image](https://discourse.vtk.org/uploads/default/original/2X/f/f61c60d8e2ecaed2bbb6d6d1c94f5fc477b16be6.png)

It should basically cover the whole molecule.

Also, I have a bit confusion, can you confirm if I am pushing `m_vertices` and `m_normals` in a right way at the end?

```cpp
void MeshGenerator::FlyingEdgesAlgorithmPass4()
{
    size_t nx = m_dim.x();
    size_t ny = m_dim.y();
    size_t nz = m_dim.z();

 for(size_t k = 0; k != nz -1; ++k) {
    for(size_t j = 0; j != ny-1; ++j)
    {
        // find adjusted trim values
        size_t xl, xr;
        calcTrimValues(xl, xr, j, k); // xl, xr set in this function

        if(xl == xr)
            continue;

        size_t triIdx = triCounter[k*(ny-1) + j];
        auto curCubeCaseIds = cubeCases.begin() + (m_dim.x()-1)*(k*(m_dim.y()-1) + j);

        gridEdge const& ge0 = gridEdges[k* m_dim.y() + j];
        gridEdge const& ge1 = gridEdges[k* m_dim.y() + j + 1];
        gridEdge const& ge2 = gridEdges[(k+1)* m_dim.y() + j];
        gridEdge const& ge3 = gridEdges[(k+1)* m_dim.y() + j + 1];

        size_t x0counter = 0;
        size_t y0counter = 0;
        size_t z0counter = 0;

        size_t x1counter = 0;
        size_t z1counter = 0;

        size_t x2counter = 0;
        size_t y2counter = 0;

        size_t x3counter = 0;

        bool isYEnd = (j == ny-2);
        bool isZEnd = (k == nz-2);

        for(size_t i = xl; i != xr; ++i)
        {
            bool isXEnd = (i == nx-2);

            unsigned char caseId = curCubeCaseIds[i];

            if(caseId == 0 || caseId == 255)
            {
                continue;
            }

           const bool* isCutCase = isCut[caseId]; // size 12
            std::array<std::array<float, 3>, 8> pointCube = m_cube->getPosCube(i, j, k);
            std::array<float, 8> isovalCube = m_cube->getValsCube(i, j, k);
            std::array<std::array<float, 3>, 8> gradCube = m_cube->getGradCube(i, j, k);

            // Add Points and normals.
            // Calculate global indices for triangles
            std::array<size_t, 12> globalIdxs;

            if(isCutCase[0])
            {
              // points-> array<vector3f>
                size_t idx = ge0.xstart + x0counter;
                std::array<float, 3> interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 0);
                std::array<float, 3> interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 0);

                points[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]);
                normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]);
                globalIdxs[0] = idx;
                ++x0counter;
            }

            if(isCutCase[3])
            {
                size_t idx = ge0.ystart + y0counter;
                std::array<float, 3> interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 3);
                std::array<float, 3> interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 3);
                points[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]);
                normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]);
                globalIdxs[3] = idx;
                ++y0counter;
            }

            if(isCutCase[8])
            {
                size_t idx = ge0.zstart + z0counter;
                std::array<float, 3> interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 8);
                std::array<float, 3> interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 8);
                points[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]);
                normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]);
                globalIdxs[8] = idx;
                ++z0counter;
            }

            if(isCutCase[1])
            {
                size_t idx = ge0.ystart + y0counter;
                if(isXEnd)
                {
                    std::array<float, 3> interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 1);
                    std::array<float, 3> interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 1);                  
                    points[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]);
                    normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]);
                    // y0counter counter doesn't need to be incremented
                    // because it won't be used again.
                }
                globalIdxs[1] = idx;
            }

            if(isCutCase[9])
            {
                size_t idx = ge0.zstart + z0counter;
                if(isXEnd)
                {
                    std::array<float, 3> interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 9);
                    std::array<float, 3> interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 9);                                    
                    points[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]);
                    normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]);
                    // z0counter doesn't need to in incremented.
                }
                globalIdxs[9] = idx;
            }

            if(isCutCase[2])
            {
                size_t idx = ge1.xstart + x1counter;
                if(isYEnd)
                {
                    std::array<float, 3> interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 2);
                    std::array<float, 3> interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 2);                                                      
                    points[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]);
                    normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]);
                }
                globalIdxs[2] = idx;
                ++x1counter;
            }

            if(isCutCase[10])
            {
                size_t idx = ge1.zstart + z1counter;

                if(isYEnd)
                {
                    std::array<float, 3> interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 10);
                    std::array<float, 3> interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 10);                                                      
                  
                    points[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]);
                    normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]);
                }
                globalIdxs[10] = idx;
                ++z1counter;
            }

            if(isCutCase[4])
            {
                size_t idx = ge2.xstart + x2counter;
                if(isZEnd)
                {
                    std::array<float, 3> interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 4);

                    std::array<float, 3> interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 4);                                                      

                    points[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]);
                    normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]);
                }
                globalIdxs[4] = idx;
                ++x2counter;
            }

            if(isCutCase[7])
            {
                size_t idx = ge2.ystart + y2counter;
                if(isZEnd)
                {
                    std::array<float, 3> interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 7);

                    std::array<float, 3> interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 7);                                                      

                    points[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]);
                    normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]);
                }
                globalIdxs[7] = idx;
                ++y2counter;
            }

            if(isCutCase[11])
            {
                size_t idx = ge1.zstart + z1counter;
                if(isXEnd and isYEnd)
                {
                    std::array<float, 3> interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 11);

                    std::array<float, 3> interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 11);                                                      

                    points[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]);
                    normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]);
                }
                globalIdxs[11] = idx;
            }

            if(isCutCase[5])
            {
                size_t idx = ge2.ystart + y2counter;
                if(isXEnd and isZEnd)
                {
                    std::array<float, 3> interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 5);

                    std::array<float, 3> interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 5);                                                      

                    points[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]);
                    normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]);
                    // y2 counter does not need to be incremented.
                }
                globalIdxs[5] = idx;
            }

            if(isCutCase[6])
            {
                size_t idx = ge3.xstart + x3counter;
                if(isYEnd and isZEnd)
                {
                    std::array<float, 3> interpolatedPoint = interpolateOnCube(pointCube, isovalCube, 6);
                    std::array<float, 3> interpolatedNormal = interpolateOnCube(gradCube, isovalCube, 6);                                                      

                    points[idx] = Vector3f(interpolatedPoint[0], interpolatedPoint[1], interpolatedPoint[2]);
                    normals[idx] = Vector3f(interpolatedNormal[0], interpolatedNormal[1], interpolatedNormal[2]);
                }
                globalIdxs[6] = idx;
                ++x3counter;
            }

            // Add triangles
            const char* caseTri = caseTriangles[caseId]; // size 16
            for(int idx = 0; caseTri[idx] != -1; idx += 3)
            {

                size_t globalIdx = globalIdxs[caseTri[idx]];
                size_t globalIdx1 = globalIdxs[caseTri[idx + 1]];
                size_t globalIdx2 = globalIdxs[caseTri[idx + 2]];

                m_vertices.push_back(points[globalIdx]);
                m_vertices.push_back(points[globalIdx1]);
                m_vertices.push_back(points[globalIdx2]);

                m_normals.push_back(normals[globalIdx]);
                m_normals.push_back(normals[globalIdx1]);
                m_normals.push_back(normals[globalIdx2]);    

              
            }
        }
    }}
  // qDebug() << "pass 4 ended";

}

```

Please if you have any suggestions do let me know.

---

<div class="post-metadata">

### Author: ![Anant\_Bharti](https://discourse.vtk.org/user_avatar/discourse.vtk.org/anant_bharti/32/8464_2.png) [@Anant\_Bharti](https://discourse.vtk.org/u/Anant_Bharti)
#### Post date: [November 4, 2024, 2:50pm UTC](https://discourse.vtk.org/t/implmentation-of-flying-edges/14806/5 "2024-11-04T14:50:37Z")

</div>

@will.schroeder Any help?

---

<div class="post-metadata">

### Author: ![will.schroeder](https://discourse.vtk.org/user_avatar/discourse.vtk.org/will.schroeder/32/233_2.png) [@will.schroeder](https://discourse.vtk.org/u/will.schroeder)
#### Post date: [November 4, 2024, 2:56pm UTC](https://discourse.vtk.org/t/implmentation-of-flying-edges/14806/6 "2024-11-04T14:56:32Z")

</div>

It’s almost certainly an indexing problem. Managing all of the offsets and indices is what makes the algorithm tricky to implement and why my hair turned gray 🙂 I recommend that you start with a simple volume 3x3x3 with just the single center point val==1, and all other points ==0. Make sure that is working. Then build up from there: 5x5x5 volumes, and also move the point with val==1 towards the various boundaries to make sure all of that works.

---

<div class="post-metadata">

### Author: ![Anant\_Bharti](https://discourse.vtk.org/user_avatar/discourse.vtk.org/anant_bharti/32/8464_2.png) [@Anant\_Bharti](https://discourse.vtk.org/u/Anant_Bharti)
#### Post date: [November 6, 2024, 8:17pm UTC](https://discourse.vtk.org/t/implmentation-of-flying-edges/14806/7 "2024-11-06T20:17:59Z")

</div>

Thanks so much @will.schroeder sir. I wasn’t aware that you only have wrote the research papers. Really a pleasure of mine that you replied. I have completed the algorithm and it’s working perfectly.

One last doubt, Do you think we can remove the artifacts by laplacian smoothing? I used to remove the artifacts and make it smooth via laplacian smoothing when i used marching cubes.

Can we do the same with flying-edges as well?

---

<div class="post-metadata">

### Author: ![will.schroeder](https://discourse.vtk.org/user_avatar/discourse.vtk.org/will.schroeder/32/233_2.png) [@will.schroeder](https://discourse.vtk.org/u/will.schroeder)
#### Post date: [November 7, 2024, 10:21am UTC](https://discourse.vtk.org/t/implmentation-of-flying-edges/14806/8 "2024-11-07T10:21:17Z")

</div>

I prefer vtkWindowedSincPolyDataFilter. The laplacian smoother tends to “shrink” the surface.
