/// <summary> /// Инициализировать буферы и списки /// </summary> void InitializeData(ConvexHullComputationConfig config) { UnprocessedFaces = new FaceList(); ConvexFaces = new IndexBuffer(); FacePool = new ConvexFaceInternal[(Dimension + 1) * 10]; // Должен быть инициализирован перед менеджером объектов AffectedFaceFlags = new bool[(Dimension + 1) * 10]; ObjectManager = new ObjectManager(this); Center = new double[Dimension]; TraverseStack = new IndexBuffer(); UpdateBuffer = new int[Dimension]; UpdateIndices = new int[Dimension]; EmptyBuffer = new IndexBuffer(); AffectedFaceBuffer = new IndexBuffer(); ConeFaceBuffer = new SimpleList <DeferredFace>(); SingularVertices = new HashSet <int>(); BeyondBuffer = new IndexBuffer(); ConnectorTable = new ConnectorList[ConnectorTableSize]; for (int i = 0; i < ConnectorTableSize; i++) { ConnectorTable[i] = new ConnectorList(); } VertexMarks = new bool[Vertices.Length]; InitializePositions(config); MathHelper = new MathHelper(Dimension, Positions); }
/// <summary> /// Обертка вершины и определения размера, если он неизвесен /// </summary> private ConvexHullInternal(IVertex[] vertices, bool lift, ConvexHullComputationConfig config) { if (config.PointTranslationType != PointTranslationType.None && config.PointTranslationGenerator == null) { throw new InvalidOperationException("PointTranslationGenerator cannot be null if PointTranslationType is enabled."); } this.IsLifted = lift; this.Vertices = vertices; this.PlaneDistanceTolerance = config.PlaneDistanceTolerance; Dimension = DetermineDimension(); if (Dimension < 2) { throw new InvalidOperationException("Dimension of the input must be 2 or greater."); } if (lift) { Dimension++; } InitializeData(config); }
/// <summary> /// Проинициализируем позиции вершин на основе типа перевода от конфигурации /// </summary> void InitializePositions(ConvexHullComputationConfig config) { Positions = new double[Vertices.Length * Dimension]; int index = 0; if (IsLifted) { var origDim = Dimension - 1; var tf = config.PointTranslationGenerator; switch (config.PointTranslationType) { case PointTranslationType.None: foreach (var v in Vertices) { double lifted = 0.0; for (int i = 0; i < origDim; i++) { var t = v.Position[i]; Positions[index++] = t; lifted += t * t; } Positions[index++] = lifted; } break; case PointTranslationType.TranslateInternal: foreach (var v in Vertices) { double lifted = 0.0; for (int i = 0; i < origDim; i++) { var t = v.Position[i] + tf(); Positions[index++] = t; lifted += t * t; } Positions[index++] = lifted; } break; } } else { var tf = config.PointTranslationGenerator; switch (config.PointTranslationType) { case PointTranslationType.None: foreach (var v in Vertices) { for (int i = 0; i < Dimension; i++) { Positions[index++] = v.Position[i]; } } break; case PointTranslationType.TranslateInternal: foreach (var v in Vertices) { for (int i = 0; i < Dimension; i++) { Positions[index++] = v.Position[i] + tf(); } } break; } } }
/// <summary> /// Создает выпуклую оболочку из входных данных /// </summary> public static ConvexHull <TVertex, TFace> Create <TVertex, TFace>(IList <TVertex> data, ConvexHullComputationConfig config = null) where TVertex : IVertex where TFace : ConvexFace <TVertex, TFace>, new() { return(ConvexHull <TVertex, TFace> .Create(data, config)); }
/// <summary> /// Класс выпуклой оболочки /// </summary> internal static ConvexHull <TVertex, TFace> GetConvexHull <TVertex, TFace>(IList <TVertex> data, ConvexHullComputationConfig config) where TFace : ConvexFace <TVertex, TFace>, new() where TVertex : IVertex { config = config ?? new ConvexHullComputationConfig(); var vertices = new IVertex[data.Count]; for (int i = 0; i < data.Count; i++) { vertices[i] = data[i]; } ConvexHullInternal ch = new ConvexHullInternal(vertices, false, config); ch.FindConvexHull(); var hull = ch.GetHullVertices(data); return(new ConvexHull <TVertex, TFace> { Points = hull, Faces = ch.GetConvexFaces <TVertex, TFace>() }); }