Fastest way to get index of MeshFace?

It seems that MeshFace and MeshFaceList doesn’t provide a simple way to return an index for a given MeshFace (only the other way around, retrieving a MeshFace based on a index).

So using C#, what is the fastest way to get a hole bunch of indexes strating from a list of MeshFaces?

// Rolf

Hi Rolf

… may be a stupid question …
How did you get the MeshFace objects ?

I keep two lists after some intersections. One with indexes (the std way) and another with the faces themself.

The “direct faces” were useful for later display (of what was intersected) even after manipulating the mesh, changes which would disprupt the initial index. Now I wanted to do some checking, when and where the index changes (I got into some trouble), but can’t retrieve the indexes in a very efficient way.

Of course I could spin through the entire mesh.Faces list, but I had hoped to see a hashed list with “IndexOf” or the alike. .NET experts also may have a trick with lists which performs reasonably well.

// Rolf

Hmmm … couldn’t the MeshFace objects have changed after the mesh editing ?
I mean, the MeshFace objects you stored are still part of the edited mesh ?
… Or are there now in the mesh new, different Meshface objects ?

Can’t you use the rs.MeshFaceVertices() ?

Of course both cases applies, depending on what I do, but that wouldn’t be a problem in my case. A mishap like mesh.IndexOf( deletedFace ) would only return = -1, so that would be no problem to handle.

Anyway, I make my own slow for-loop fpr lookup for now.

// Rolf

That one also requires that very Index which I want to get hold of in the first place…

public bool GetFaceVertices(
    int faceIndex,  <---
    out Point3f a,
    out Point3f b,
    out Point3f c,
    out Point3f d
)

All methods I have found so far only uses index, no one returns the index. I had hoped for a loop-hole or “backdoor” somewhere that would give me the index, but I haven’t found any so far.

// Rolf

I think that with interactive selection, this one might work:

http://developer.rhino3d.com/api/RhinoCommonWin/html/M_Rhino_DocObjects_ObjRef_SetSelectionComponent.htm

… But I don’t know if and how we could simulate object mouse picking programmatically … :confused:

I don’t think I understand your problem fully, but I use rs.MeshVertices() to get the vertices, then I use rs.MeshFaceVertices() to find out which 4 vertices from the first list are the vertices of the given face.

import rhinoscriptsyntax as rs

mesh_id=rs.GetObject(filter=32)
if mesh_id:
    mesh_faces=rs.MeshFaces(mesh_id)
    mesh_vertices=rs.MeshVertices(mesh_id)
    mesh_faceVertices=rs.MeshFaceVertices(mesh_id)
    
    # The facevertices I want is from face nr 2
    # So I make a list of the facevertices for face 2
    facevertices=mesh_faceVertices[ 2 ]
    
    # now I have a list of 4 numbers, each indicating a vertex number
    for facevertex in facevertices:
        rs.AddPoint(mesh_vertices [facevertex] )

PS! If facevertices 0 and 3 (1 and 4) are the same then it is a triangle and not a quad.

Yes @Holo, I’m with you all the way there. It’s just that I have a case where I want to get the index of a face, rather than the other way around, retrieving a face based on an index.

Regarding face vertices 1…3 I tend to retrieve the points like so instead:

var face = mesh.Faces[Index];
var ptA = mesh.Vertices[face.A];
var ptB = mesh.Vertices[face.B];
var ptC = mesh.Vertices[face.C];
if (face.IsQuad)
    var ptD = mesh.Vertices[face.D];

But I guess it’s a matter of taste.

// Rolf

Try
rs.MeshVertexFaces(mesh,i)

It will return all faces that uses vertex i

The thing is, I’m not trying to retrieve the face. I already have the face. So I want to find the index of a face which I already have.

// Rolf

Hi RIL

Lets suppose we have:
MeshFaceList myMeshFaceList … our meshface list
MeshFace myMeshFaceToFindIndex … meshface for which we want to find inex

Some Facts:

  1. Meshfaces collection may contain two faces with same data (=> they are the same by default comparer, they overlap each other => they have the same values for A, B, C and D)
  2. becasue of 1) we can have more then one index for the same meshface =>

One of way to do what you want is to create LookUp for your meshfaces collection. We choose lookup because of 2).

using System.Collections.Generic;
using System.Linq;
using Rhino.Geometry.Collections;

Lookup<MeshFace, int> myLookUpForMeshFaces = (Lookup<MeshFace, int>)myMeshFaceList.Select((mface, index) => new { mface, index });

Now you can lookup for all faces which are eqaul to your myMeshFaceToFindIndex and get result as array of indexes for matching face:
int[] indexesArray = myLookUpForMeshFaces[myMeshFaceToFindIndex].ToArray();

Of course, you keep LookUp available all the way in your code until it changes and then you recreate it (no sense to create it every time when you lookup for indexes if you know that it has not been changed).

Radovan

Hm, now that doesn’t make sense to me… In my mind you either have the face and thus the index, or you have a duplicate and need to use the vertices from that and compare with those in the other mesh’ vertex list.
Is the latter the case?

Jørgen, I was confused too. :slight_smile:
But Rolf explained why he needs to do that:

Fastest way to get index of MeshFace?

Yeah, thanks that makes sense. So he does not have the face, he has a duplicate. I might be nitpicking but it’s makes huge difference.

For now and for my debugging purposes the following snippet does what I want (assuming that face1.Equals(face2) returns a unique/distinct match):

    private int MeshFaceIndexOf(Mesh m, MeshFace face)
    {
        var res = -1;
        for (var i = 0; i < m.Faces.Count; i++)
        {
            if (face.Equals(m.Faces[i]))
            {
                res = i;
                break;
            }
        }
        return res;
    }

// Rolf