Joining 'Neighboring' Meshes / Connected Graphs to Meshes

grasshopper
mesh
unhandled

#1

Hi all,

Given a Delaunay mesh, if I cull out some faces, and implement either the MeshExplode or Disjoint component, I will get a list of meshes that’s made up of the original mesh faces.
How could I only join those that are either adjacent (sharing and edge) or those that share a vertex.

Attached is an example that will probably explain the question better.
meshJoin.gh (7.5 KB)

The upper list of meshes should return two meshes after the process because the region where there are only two faces, connected to each other with a vertex, will be joined together as one, but not joined with the rest;
and the lower will join as one mesh because all faces are sharing at least one vertex with another.

Or…perhaps join and weld them using the weaverbird component and somehow explodes them into either two or one single mesh(es) respectively?

Thanks,

Tim


#2

If anyone is interested, I’ve done it by using the networkx library and building on some sample mesh to graph script to identify connected graphs, and weave back to mesh from line segments output through weaverbird:

import Rhino as rc
import networkx as nx
import clr
clr.AddReference("Grasshopper")
from Grasshopper.Kernel.Data import GH_Path
from Grasshopper import DataTree

# [function] Mesh to networkx graph
def meshVertexGraph(mesh,weightMode):
    """ Make a networkx graph with mesh vertices as nodes and mesh edges as edges """
    # Create graph
    g = nx.Graph()
    for i in range(mesh.Vertices.Count):
        # Get vertex as point3D
        pt3D = rc.Geometry.Point3d(mesh.Vertices.Item[i])
        # Add node to graph and get its neighbours
        g.add_node(i,point=pt3D)
        neighbours = mesh.Vertices.GetConnectedVertices(i)
        # Add edges to graph
        for n in neighbours:
            if n > i:
                line = rc.Geometry.Line(mesh.Vertices.Item[i],mesh.Vertices.Item[n])
                if weightMode == "edgeLength":
                    w = line.Length
                elif weightMode == "sameWeight":
                    w = 1
                g.add_edge(i,n,weight=w,line=line)
    return g


# Initiate DataTree
p_all = DataTree[rc.Geometry.Point3d]()
ln_all = DataTree[rc.Geometry.Line]()

for m_cnt in range(len(mesh)):
    m = mesh[m_cnt]
    # mesh to networkx graph
    g = meshVertexGraph(m,"edgeLength")

    # create graphs of connected edges
    subg = nx.connected_component_subgraphs(g)
    subg_list = list(subg)

    #output
    for mgraph in range(len(subg_list)):
        n_list = [subg_list[mgraph].node[i]["point"] for i in subg_list[mgraph].nodes()]
        e_list = [e[2]["line"] for e in subg_list[mgraph].edges(data=True)]
        p_all.AddRange(n_list, GH_Path(mgraph))
        ln_all.AddRange(e_list, GH_Path(mgraph))

pt = p_all
ln = ln_all