Tri angular me sh структура данных и проблема с точечным хранилищем - PullRequest
0 голосов
/ 10 июля 2020

Я почти уверен, что это будет закрыто как основанное на мнении, но вот ... Я делаю некоторую работу sh в C#, преобразовывая облако точек в три angular меня sh. Это доступно в C ++, но не совсем для C# (которое мне удалось найти).

У меня есть класс для Point3d, Edge и Face. Point3d - это основа, Edge относится к индексам Point3d для конечных точек кромки, а Face относится к индексам Edge для создания грани:

public class MeshStructure
{
    public List<Point3d> Points = new List<Point3d>();
    public List<Edge> Edges = new List<Edge>();
    public List<Face> Faces = new List<Face>();
....
}

///////////////////////////////////////////////
    public class Edge
{
    int point1Index;
    int point2Index;

    public Edge(int point1Index, int point2Index)
    {
        this.point1Index = point1Index;
        this.point2Index = point2Index;
    }

    public int Point1 => point1Index;
    public int Point2 => point2Index;
}
//////////////////////////////////////////////
public class Face
{
    public Face(int edge1Index, int edge2Index, int edge3Index)
    {
        if(edge1Index == edge2Index || edge1Index == edge3Index || edge2Index == edge3Index)
        {
            throw new ArgumentException("No two edges may be identical. A face must be made up of three different edges.");
        }
        Edges.Add(edge1Index);
        Edges.Add(edge2Index);
        Edges.Add(edge3Index);
    }

    public List<int> Edges { get; } = new List<int>();
}

Моя проблема заключается в том, как «получить» значения точек при работе в контексте Face или Edge. Я придумал две стратегии:

  1. Передавать список точек по ссылке в каждый новый экземпляр Edge и Face, который я создаю. Это почему-то кажется мне неправильным.

    public Edge(int point1Index, int point2Index, ref List<Point3d> points)
    {
        this.point1Index = point1Index;
        this.point2Index = point2Index;
        this.points = points;
    }
    
  2. Передайте очки, используемые в каждом Edge, по значению в каждый экземпляр Edge и ту же концепцию с Face. Это также кажется неправильным из-за раздувания памяти и наличия нескольких копий одного и того же Point3d.

Есть ли шаблон проектирования для такого рода проблем?

1 Ответ

1 голос
/ 13 июля 2020

Представление, которое у вас есть, немного необычно. Обычное представление Face-vertex может тривиально воспроизвести ваши ребра, поэтому явный список ребер, кажется, не добавляет никакого значения, насколько я могу видеть. Другое популярное представление - это (половина) крылатый меня sh, но для этого требуется хранить больше данных.

Я предполагаю, что цель здесь - иметь некоторые методы, которые возвращают некоторые структурные данные о me sh, такие как список связанных ребер для ребра. В противном случае ребро может быть просто двумя индексами.

Поскольку у вас может быть большое количество граней / ребер, есть смысл сохранить размер данных как можно меньшим. По этой причине я предпочитаю использовать структуры, поскольку они не связаны с объектами. Подумайте об использовании массивов, и ref возвращает / в параметрах , чтобы избежать копирования.

Один из возможных вариантов - сохранить грани / края как структуры только для данных, а MeshStructure есть все методы. Таким образом, для итерации всех связанных ребер может быть метод IEnumerable<Edge> GetConnectedEdges(Edge edge).

Более сложный дизайн может заключаться в двухуровневом дизайне. Внутренняя граничная структура, которая хранит минимально возможные данные, и граничная структура publi c, которая также содержит ссылку на родительский объект, чтобы разрешить сложные методы. Это дает более приятный API за счет некоторой сложности. Пример:

    public class MeshStructure
{
    private Point3d[] Points ;
    private EdgeInternal[] Edges ;

    public Edge GetEdge(int index) => new Edge(index, this);

    private readonly struct EdgeInternal
    {
        public int P1 { get; }
        public int P2 { get; }
        public EdgeInternal(int p1, int p2) => (P1, P2) = (p1, p2);
    }
    
    public readonly struct Edge
    {
        private readonly int edgeIndex;
        private readonly MeshStructure mesh;
        public int P1 => mesh.Edges[edgeIndex].P1;
        public int P2 => mesh.Edges[edgeIndex].P2;
        public Edge(int edgeIndex, MeshStructure mesh) => (this.edgeIndex, this.mesh) = (edgeIndex, mesh);
        public IEnumerable<Edge> GetConnectedEdges()
        {
            var edges = mesh.Edges;
            // Add logic
            return null;
        }
    }
}
...