meshmash / Plankton

A C# half-edge mesh data structure, and components for using this in Grasshopper/Rhino
http://meshmash.github.io/Plankton
GNU Lesser General Public License v3.0
216 stars 66 forks source link

Naked edges as joined polyline. #40

Closed petrasvestartas closed 7 years ago

petrasvestartas commented 7 years ago

Hi,

Is it possible to get naked edges of plankton mesh in as using rhino meshes and naked edges.

If I understand correctly plankton mesh is directed graph. Would it be possible to apply breadth first search to get components as naked edges?

Kind Regards, Petras

pearswj commented 7 years ago

Hi Petras,

Personally I would just do a dumb O(n) search through all the halfedges to find all those which don't have an adjacent face. Then I would pick one and use the NextHalfedge field to traverse the boundary and create a polyline from the vertices (StartVertex). Keep in mind that there might be multiple boundaries if the mesh has "holes". You could tick the naked halfedges off as you traverse the first boundary and if you have any left at the end, pick another and start again. Not very smart, I know... If you come up with something better, perhaps you could submit a pull request :)

Sent from my iPhone

On 6 Jan 2017, at 11:18, Petras Vestartas notifications@github.com wrote:

Hi,

Is it possible to get naked edges of plankton mesh in as using rhino meshes and naked edges.

If I understand correctly plankton mesh is directed graph. Would it be possible to apply breadth first search to get components as naked edges?

Kind Regards, Petras

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub, or mute the thread.

Dan-Piker commented 7 years ago

Also - although each halfedge is directed, every edge consists of one in both directions, so the mesh is not a directed graph in that sense. I suppose you could consider the set of all even (or all odd) indexed halfedges as a directed graph though, since each edge always has one of each.

pearswj commented 7 years ago

2x speed boost 🚀

petrasvestartas commented 7 years ago

Thank you;)

petrasvestartas commented 7 years ago

Hi,

I had time to write something to get a polyline according to your instructions. It works well and I tested with one naked polyline, but I can finish it to work with more than one hole.

I have one question.

When I use a method to get next halfedge. Why looking at edge list I see that I must repeat first halfedge to have closed loop. Why is that so? Probably I am missing a concept behind halfedge library.

If there first and last edge in halfedges list are the same integer, why I am getting two different lines ? question

petrasvestartas commented 7 years ago

Oh, stupid, got it.

pearswj commented 7 years ago

I assume you figured out that a Polyline only considers itself to be closed if its start is identical to its endpoint? :)

petrasvestartas commented 7 years ago

It was an issue with looping not with the starting point:) I finally managed to get all naked edges.

I upload it here if somebody needs it too. There is a check which looks strange but it works: I have to check if current edge is boundary, if next edge is boundary and if previous edge is boundary. Otherwise it takes interior face. If there is a cleaner solution to do above, please let me know.

The nice thing about looping through next edges is that naked edges are always in order.

Also thank you very much for previous post answer, it would be nice to crack this issue to create plankton mesh from polylines. As working with poly faces this function would be very efficient. For instance if working with hexagons after kangaroo simulation and preparing all the faces for fabrication simple models - adjacency and poly meshes are such a useful thing.

  private void RunScript(Mesh m, ref object A, ref object B, ref object C)
  {

    //1. Mesh to planktonMesh
    PlanktonMesh pm = m.ToPlanktonMesh();

    //1.1 Global parameters
    List<int> usedNakedEdges = new List<int>();
    List<List<Line>> allLines = new List<List<Line>>();
    List<List<int>> allNE = new List<List<int>>();

    //2. Get whatever first naked edge
    int ne = -2;

    while(ne != -1){

      ne = -1;

      //2.1 Loop through edges
      //2.2. Check if they are naked and nextHalfedge is naked too (otherwise interior faces will be added) and check all previously looped naked edges
      for(int i = 0; i < pm.Halfedges.Count; i++ ){
        if( pm.Halfedges.IsBoundary(i) && pm.Halfedges.IsBoundary(pm.Halfedges[i].NextHalfedge) && pm.Halfedges.IsBoundary(pm.Halfedges[i].PrevHalfedge) && !usedNakedEdges.Contains(i) ){
          usedNakedEdges.Add(i);
          ne = i;
          break;
        }
      }

      //3.1 If naked edge exists
      if(ne != -1){

        //3.2 Get all indices of first polyline
        //Then I would pick one and use the `NextHalfedge` field to traverse the boundary and create a polyline from the vertices (`StartVertex`).

        List < int > p1 = new List<int>(){ne};
        List < Line > linesA = new List<Line>{new Line(pm.Vertices[pm.Halfedges[ne].StartVertex].ToPoint3d(), pm.Vertices[pm.Halfedges.EndVertex(ne)].ToPoint3d())};
        bool flag = true;
        while (flag){
          int edge = pm.Halfedges[p1.Last()].NextHalfedge;
          if(!p1.Contains(edge)){
            p1.Add(edge);
            usedNakedEdges.Add(edge);
            linesA.Add(new Line(pm.Vertices[pm.Halfedges[edge].StartVertex].ToPoint3d(), pm.Vertices[pm.Halfedges.EndVertex(edge)].ToPoint3d()));
          }
          else
            flag = false;
        }

        allLines.Add(linesA);
        allNE.Add(p1);

      }//If
    } //While

    A = allLines;
    B = allNE;
    C = usedNakedEdges;
  }

check

pearswj commented 7 years ago

Thanks for the update and the script! You never know, we might find some time to integrate this into Plankton at some point...

We implemented the PlanktonMesh.Halfedges.IsBoundary() method in a way that returns true if either the halfedge itself has no adjacent face or its pair halfedge has no adjacent face. It felt like the right decision at the time! You could try directly querying the AdjacentFace...

if (pm.Halfedges[i].AdjacentFace < 0 && !usedNakedEdges.Contains(i)){
  usedNakedEdges.Add(i);
  ne = i;
}
petrasvestartas commented 7 years ago

Thanks this is much cleaner and faster:)

Dan-Piker commented 7 years ago

...it would be nice to crack this issue to create plankton mesh from polylines. As working with poly faces this function would be very efficient. For instance if working with hexagons after kangaroo simulation...

So do you have a Plankton mesh that you want to do some stuff with in Kangaroo, then recreate that plankton mesh with the modified vertex positions on the output?

If so, you could make a goal which references both Plankton and K2, so it can keep the plankton topology without having to recreate it from polylines plankton_k2goal.zip