MatchMeshEdge through scripting or Grasshopper 3D components

Hi all,
I am aiming to close a mesh which due to some previous surface modifications (added approximated patch by blending two separate objects) has a number of small gaps at both ends. A closed mesh is required for the subsequent conversion into a solid SubD geometry and modifications in Grasshopper.

I did try to analyse previous topics/attempts regarding _MatchMeshEdge and came across the following:

  1. MatchMeshEdge C# Component - Grasshopper - I cannot access the file there;
  2. MatchMeshEdge - seems like a request for future work/Beta releases

Could you please advise me on how I can replicate the existing manual _MatchMeshEdge Rhino command in Grasshopper 3D (avoiding to bake the geometry and scripting a customised command via the MacroEditor )
Any GhPython and c# scripting solutions are also welcome.

Rhino 5 file and STL data of the depicted model above are attached here:
MatchMeshEdge_discourse_request_25_10_2020.3dm (10.6 MB) MatchMeshEdge_discourse_request_25_10_2020.stl (4.6 MB)

The gaps are very tiny and manually I am able to close the mesh surface using the following _MatchMeshEdge parameters:
*DistanceToAdjust=0.1
*RatchetMode=On

I have access to the most up-to-date Rhino v6 and Rhino Beta versions.

I look forward to receiving your help/advice.
Thank you,
Ilja

So as I understand the _MatchMeshEdge is not scriptable or accessible with Grasshopper?

Thank you,
Ilja

Hi Ilja,

It looks like scripting it works:

import rhinoscriptsyntax as rs
import Grasshopper
import Rhino

rhdoc = Rhino.RhinoDoc.ActiveDoc
rhdoc.Views.RedrawEnabled = False

rh_mesh = rhdoc.Objects.AddMesh(mesh)
current = rhdoc.Objects.Find(rh_mesh).RuntimeSerialNumber

# Select the mesh at the end of the command, when it is preselected the options are not available
rhdoc.Objects.UnselectAll()
command = """_MatchMeshEdge _DistanceToAdjust 0.1 _RatchetMode=_On _SelId {} _EnterEnd""".format(str(rh_mesh))
rs.Command(command)

new_obj = rhdoc.Objects.AllObjectsSince(current)

if len(new_obj) > 0:
    mesh_out = new_obj[0].Geometry.Duplicate()
else:
    mesh_out = None

for m in new_obj:
    rhdoc.Objects.Purge(m)

rhdoc.Objects.Purge(current)
rhdoc.Views.RedrawEnabled = True

in a GHPython component, where mesh is a GH mesh input, and mesh_out the output when successful.

Technically this is equivalent to baking, running a macro, and deleting the temporary baked geometries, but it’s all automated so I guess it’s not really an issue. You could also parametrize the DistanceToAdjust parameter by adding an input to the GHPython component and feeding that to the command through .format().

2020-11-24_DI-110943_MatchMeshEdge scripting.gh (4.0 KB)

Hi Pierre,

Is it still on the wishlist to be added to the sdk, for example accessible through Python?

I also support this request :+1:

This is still in the pile: https://mcneel.myjetbrains.com/youtrack/issue/RH-30345, although at a low priority.

Hi all,

I’m hoping to reactivate this topic. I’d really love to access to MatchMeshEdge in GH. Does anybody know of any updates or is aware of a working script in Grasshopper (Rhino Version 7 SR29)?

Best,
Coerte

I too would like to use this

Thanks,
Bathsheba

This issue has been fixed since 7.4 and MatchMeshEdge is now available in RhinoCommon

RH-30345 SDK RhinoCommon: Added Mesh.MatchEdges() which calls RhinoMatchMeshEdge

Thank you for looking at this @pierrec . I tried to copy/paste the script into GhPython node, but failing to get any result? Could you show how this can be implemented in GhPython component? I’ve attached a simple GH definition with internalized STL model that is open.

Many many thanks,
MatchMeshEdge.gh (2.0 MB)

Ilja

Hi @ilmar_ik,

That script you copied was meant to be run from the Rhino script editor, not from Grasshopper. Here is a version that is more compatible with Grasshopper:

import rhinoscriptsyntax as rs
import Rhino

def test_match_mesh_edges(mesh):
    meshobj = rs.coercemesh(mesh)
    if not meshobj:
        return None
        
    mcopy = meshobj.DuplicateMesh()
    distance = 0.1
    rachet = True
    rc = mcopy.MatchEdges(distance, rachet)
    if rc:
        rs.Redraw()
        return mcopy
    return None

mesh_out = test_match_mesh_edges(mesh)

Hi @pierrec . That is exactly what I needed. Amazing work!

Awesome, thanks!
I’ll use it every day. :smiley_cat:

Thanks so much for following up to this request. I feel like I’m missing something obvious here, but the provided Python script returns null. I set the input/output names to match your script and assigned Mesh as the input hint, any idea what I might be missing? I attached a screenshot.

Thanks in advance for any tips! :slight_smile:

Hi Coerte,

if the input mesh has no edges to match, the result will be null, I guess that’s what’s happening in your case. If you always want a mesh to be returned, you could replace return none by return mesh

Thanks @Gijs - that is useful as well :+1:

Yes, that’s exactly what was happening. I knew it would be something obvious. xD This will be a huge improvement to future scripts. Thanks everyone!

Very nice to see this added! I used to find use with it to fix meshes generated from textures in a nurbs/mesh mix workflow working downstream to watertight parts. I don’t have use for it anymore, but nice to know if I go back then I could!

This is a great tool!
I was wondering if and when the new options now available for MeshMatchEdge in Rhino8 (e.g. multiple mesh input, AverageVertexesToAdjust and Join) will be added also to the RhinoCommon version of the command.

I am working on a per part meshing workflow in Grasshopper and it would be amazing to have:

  • more than one mesh as input (e.g. the components of an assembly, meshed separately)

  • an exact (i.e. conformal) matching of the edges

  • output as separate mesh entities.

Many thanks,

Michele

Hi Michele,

I’ll look into what it takes to add that stuff to the SDK function. It would be in V9 though, not V8.

I’ll add a bug tracking link here soon.

Tim