C#:如何按VectorInt3世界位置分组多Mesh的顶点索引?
按世界位置分组Mesh顶点索引的实现方案
现有IDictionary<Key, Mesh>集合,其中Mesh类包含顶点集合IEnumerable<Vertex>,Vertex结构体带有代表世界位置的VectorInt3字段。需求是编写查询,将所有Mesh的顶点索引按世界位置分组,最终得到以世界位置为键,每个键对应一组按Mesh划分的顶点索引集合的结构(预期类型类似IGrouping<VectorInt3,IGrouping<Mesh,int>>)。
你尝试的代码如下:
var vertexMeshGroups = meshes.Values.GroupBy(mesh => mesh.Vertices.Select((RoomVertex vertex,int idx) => (vertex,idx)) .GroupBy(ele => ele.vertex.WorldPosition));
这段代码逻辑错误:它先对单个Mesh内的顶点按位置分组,再把这个分组结果作为键来分组Mesh,最终得到的类型是IGrouping<IEnumerable<IGrouping<VectorInt3,(Vertex, int)>>,Mesh>,完全不符合需求。
正确实现方式
核心思路是先扁平化所有Mesh的顶点数据(将每个顶点的所属Mesh、索引、世界位置整合为单个条目),再按「世界位置→Mesh」的层级分组:
// 第一步:扁平化所有顶点数据,整合Mesh、顶点索引、世界位置 var allVertexData = meshes.Values .SelectMany(mesh => mesh.Vertices.Select((vertex, index) => new { Mesh = mesh, VertexIndex = index, Position = vertex.WorldPosition })); // 第二步:先按世界位置分组,再在每个位置组内按Mesh分组 var groupedResult = allVertexData .GroupBy(item => item.Position) .Select(positionGroup => new { WorldPosition = positionGroup.Key, MeshVertexGroups = positionGroup .GroupBy(item => item.Mesh) .Select(meshGroup => new { Mesh = meshGroup.Key, VertexIndices = meshGroup.Select(item => item.VertexIndex) }) });
如果需要严格匹配IGrouping<VectorInt3,IGrouping<Mesh,int>>的类型,可以自定义一个Grouping类(LINQ默认的Grouping是内部实现,无法直接实例化):
// 自定义Grouping类,实现IGrouping接口 public class Grouping<TKey, TElement> : IGrouping<TKey, TElement> { public TKey Key { get; } public IEnumerable<TElement> Elements { get; } public Grouping(TKey key, IEnumerable<TElement> elements) { Key = key; Elements = elements; } public IEnumerator<TElement> GetEnumerator() => Elements.GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); } // 生成符合预期类型的结果 var typedResult = allVertexData .GroupBy(item => item.Position) .Select(positionGroup => new Grouping<VectorInt3, IGrouping<Mesh, int>>( positionGroup.Key, positionGroup.GroupBy(item => item.Mesh) .Select(meshGroup => new Grouping<Mesh, int>(meshGroup.Key, meshGroup.Select(i => i.VertexIndex))) )) as IEnumerable<IGrouping<VectorInt3, IGrouping<Mesh, int>>>;
相关类定义
public class Mesh { public List<Vertex> Vertices = new List<Vertex>(); public Mesh() { } } public struct Vertex { public VectorInt3 WorldPosition; }
内容的提问来源于stack exchange,提问作者user3001150
相关产品推荐
相关产品推荐

