This internal class manages the faces of the convex hull. It is a separate class from the desired user class.
Пример #1
0
 private void GetConvexHull()
 {
     SerializeVerticesToPositions();
     FindBoundingBoxPoints();
     ShiftAndScalePositions();
     CreateInitialSimplex();
     while (UnprocessedFaces.First != null)
     {
         ConvexFaceInternal first = UnprocessedFaces.First;
         CurrentVertex = first.FurthestVertex;
         UpdateCenter();
         TagAffectedFaces(first);
         if (!SingularVertices.Contains(CurrentVertex) && CreateCone())
         {
             CommitCone();
         }
         else
         {
             HandleSingular();
         }
         int count = AffectedFaceBuffer.Count;
         for (int i = 0; i < count; i++)
         {
             AffectedFaceFlags[AffectedFaceBuffer[i]] = false;
         }
     }
 }
Пример #2
0
        private void RemoveUpperFaces()
        {
            IndexBuffer convexFaces = ConvexFaces;
            int         num         = NumOfDimensions - 1;

            for (int num2 = convexFaces.Count - 1; num2 >= 0; num2--)
            {
                int num3 = convexFaces[num2];
                ConvexFaceInternal convexFaceInternal = FacePool[num3];
                if (convexFaceInternal.Normal[num] >= 0.0)
                {
                    for (int i = 0; i < convexFaceInternal.AdjacentFaces.Length; i++)
                    {
                        int num4 = convexFaceInternal.AdjacentFaces[i];
                        if (num4 >= 0)
                        {
                            ConvexFaceInternal convexFaceInternal2 = FacePool[num4];
                            for (int j = 0; j < convexFaceInternal2.AdjacentFaces.Length; j++)
                            {
                                if (convexFaceInternal2.AdjacentFaces[j] == num3)
                                {
                                    convexFaceInternal2.AdjacentFaces[j] = -1;
                                }
                            }
                        }
                    }
                    convexFaces[num2] = convexFaces[convexFaces.Count - 1];
                    convexFaces.Pop();
                }
            }
        }
Пример #3
0
        public static double GetSimplexVolume(ConvexFaceInternal cell, IList <IVertex> vertices, SimplexVolumeBuffer buffer)
        {
            int[]    numArray  = cell.Vertices;
            double[] position  = vertices[numArray[0]].Position;
            double[] data      = buffer.Data;
            int      dimension = buffer.Dimension;
            double   num2      = 1.0;
            int      index     = 1;

            while (index < numArray.Length)
            {
                num2 *= index + 1;
                double[] numArray4 = vertices[numArray[index]].Position;
                int      num4      = 0;
                while (true)
                {
                    if (num4 >= numArray4.Length)
                    {
                        index++;
                        break;
                    }
                    data[((num4 * dimension) + index) - 1] = numArray4[num4] - position[num4];
                    num4++;
                }
            }
            return(Math.Abs(DeterminantDestructive(buffer)) / num2);
        }
        /// <summary>
        /// Finds the beyond vertices.
        /// </summary>
        /// <param name="face">The face.</param>
        /// <param name="beyond">The beyond.</param>
        private void FindBeyondVertices(ConvexFaceInternal face, IndexBuffer beyond)
        {
            var beyondVertices = BeyondBuffer;

            MaxDistance    = double.NegativeInfinity;
            FurthestVertex = 0;

            for (var i = 0; i < beyond.Count; i++)
            {
                var v = beyond[i];
                if (v == CurrentVertex)
                {
                    continue;
                }
                IsBeyond(face, beyondVertices, v);
            }

            face.FurthestVertex = FurthestVertex;

            // Pull the old switch a roo (switch the face beyond buffers)
            var temp = face.VerticesBeyond;

            face.VerticesBeyond = beyondVertices;
            if (temp.Count > 0)
            {
                temp.Clear();
            }
            BeyondBuffer = temp;
        }
Пример #5
0
 /// <summary>
 /// Recycle face for future use.
 /// </summary>
 void RecycleFace(ConvexFaceInternal face)
 {
     for (int i = 0; i < Dimension; i++)
     {
         face.AdjacentFaces[i] = null;
     }
 }
Пример #6
0
        /// <summary>
        /// Recursively traverse all the relevant faces.
        /// </summary>
        void TraverseAffectedFaces(ConvexFaceInternal currentFace)
        {
            TraverseStack.Clear();
            TraverseStack.Push(currentFace);
            currentFace.Tag = 1;

            while (TraverseStack.Count > 0)
            {
                var top = TraverseStack.Pop();
                for (int i = 0; i < Dimension; i++)
                {
                    var adjFace = top.AdjacentFaces[i];

                    if (adjFace.Tag == 0 && GetVertexDistance(CurrentVertex, adjFace) >= 0)
                    {
                        AffectedFaceBuffer.Add(adjFace);
                        //TraverseAffectedFaces(adjFace);
                        adjFace.Tag = 1;
                        TraverseStack.Push(adjFace);
                    }
                }
            }

            ////for (int i = 0; i < Dimension; i++)
            ////{
            ////    var adjFace = currentFace.AdjacentFaces[i];

            ////    if (adjFace.Tag == 0 && GetVertexDistance(CurrentVertex, adjFace) >= 0)
            ////    {
            ////        AffectedFaceBuffer.Add(adjFace);
            ////        TraverseAffectedFaces(adjFace);
            ////    }
            ////}
        }
Пример #7
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ConvexFaceInternal"/> class.
 /// </summary>
 public ConvexFaceInternal(int dimension, VertexBuffer beyondList)
 {
     AdjacentFaces  = new ConvexFaceInternal[dimension];
     VerticesBeyond = beyondList;
     Normal         = new double[dimension];
     Vertices       = new VertexWrap[dimension];
 }
Пример #8
0
 public void Add(ConvexFaceInternal face)
 {
     if (face.InList)
     {
         if (this.first.VerticesBeyond.Count < face.VerticesBeyond.Count)
         {
             this.Remove(face);
             this.AddFirst(face);
         }
     }
     else
     {
         face.InList = true;
         if ((this.first != null) && (this.first.VerticesBeyond.Count < face.VerticesBeyond.Count))
         {
             this.first.Previous = face;
             face.Next           = this.first;
             this.first          = face;
         }
         else
         {
             if (this.last != null)
             {
                 this.last.Next = face;
             }
             face.Previous = this.last;
             this.last     = face;
             this.first ??= face;
         }
     }
 }
Пример #9
0
        private void HandleSingular()
        {
            this.RollbackCenter();
            this.SingularVertices.Add(this.CurrentVertex);
            int num = 0;

            while (num < this.AffectedFaceBuffer.Count)
            {
                ConvexFaceInternal face           = this.FacePool[this.AffectedFaceBuffer[num]];
                IndexBuffer        verticesBeyond = face.VerticesBeyond;
                int num2 = 0;
                while (true)
                {
                    if (num2 >= verticesBeyond.Count)
                    {
                        this.ConvexFaces.Add(face.Index);
                        this.UnprocessedFaces.Remove(face);
                        this.ObjectManager.DepositVertexBuffer(face.VerticesBeyond);
                        face.VerticesBeyond = this.EmptyBuffer;
                        num++;
                        break;
                    }
                    this.SingularVertices.Add(verticesBeyond[num2]);
                    num2++;
                }
            }
        }
        /// <summary>
        /// Check whether the vertex v is beyond the given face. If so, add it to beyondVertices.
        /// </summary>
        /// <param name="face">The face.</param>
        /// <param name="beyondVertices">The beyond vertices.</param>
        /// <param name="v">The v.</param>
        private void IsBeyond(ConvexFaceInternal face, IndexBuffer beyondVertices, int v)
        {
            var distance = mathHelper.GetVertexDistance(v, face);

            if (distance >= PlaneDistanceTolerance)
            {
                if (distance > MaxDistance)
                {
                    // If it's within the tolerance distance, use the lex. larger point
                    if (distance - MaxDistance < PlaneDistanceTolerance)
                    { // todo: why is this LexCompare necessary. Would seem to favor x over y over z (etc.)?
                        if (LexCompare(v, FurthestVertex) > 0)
                        {
                            MaxDistance    = distance;
                            FurthestVertex = v;
                        }
                    }
                    else
                    {
                        MaxDistance    = distance;
                        FurthestVertex = v;
                    }
                }
                beyondVertices.Add(v);
            }
        }
Пример #11
0
        private unsafe void InitSingle()
        {
            int[] array = new int[this.Dimension];
            for (int i = 0; i < this.Vertices.Length; i++)
            {
                array[i] = i;
            }
            ConvexFaceInternal face = this.FacePool[this.ObjectManager.GetFace()];

            face.Vertices = array;
            Array.Sort <int>(array);
            this.MathHelper.CalculateFacePlane(face, this.Center);
            if (face.Normal[this.Dimension - 1] >= 0.0)
            {
                int index = 0;
                while (true)
                {
                    if (index >= this.Dimension)
                    {
                        face.Offset          = -face.Offset;
                        face.IsNormalFlipped = !face.IsNormalFlipped;
                        break;
                    }
                    double *numPtr1 = &(face.Normal[index]);
                    numPtr1[0] *= -1.0;
                    index++;
                }
            }
            this.ConvexFaces.Add(face.Index);
        }
Пример #12
0
 /// <summary>
 /// Adds the element to the beginning.
 /// </summary>
 /// <param name="face">The face.</param>
 private void AddFirst(ConvexFaceInternal face)
 {
     face.InList    = true;
     First.Previous = face;
     face.Next      = First;
     First          = face;
 }
Пример #13
0
        /// <summary>
        /// Create the first faces from (dimension + 1) vertices.
        /// </summary>
        /// <returns></returns>
        ConvexFaceInternal[] InitiateFaceDatabase()
        {
            var faces = new ConvexFaceInternal[Dimension + 1];

            for (var i = 0; i < Dimension + 1; i++)
            {
                var vertices = ConvexHull.Where((_, j) => i != j).ToArray(); // Skips the i-th vertex
                var newFace  = new ConvexFaceInternal(Dimension, new VertexBuffer());
                newFace.Vertices = vertices;
                Array.Sort(vertices, VertexWrapComparer.Instance);
                CalculateFacePlane(newFace);
                faces[i] = newFace;
            }

            // update the adjacency (check all pairs of faces)
            for (var i = 0; i < Dimension; i++)
            {
                for (var j = i + 1; j < Dimension + 1; j++)
                {
                    UpdateAdjacency(faces[i], faces[j]);
                }
            }

            return(faces);
        }
        /// <summary>
        /// Used by update faces.
        /// </summary>
        /// <param name="face">The face.</param>
        /// <param name="beyond">The beyond.</param>
        /// <param name="beyond1">The beyond1.</param>
        private void FindBeyondVertices(ConvexFaceInternal face, IndexBuffer beyond, IndexBuffer beyond1)
        {
            var beyondVertices = BeyondBuffer;

            MaxDistance = double.NegativeInfinity;
            FurthestVertex = 0;
            int v;

            for (var i = 0; i < beyond1.Count; i++) VertexVisited[beyond1[i]] = true;
            VertexVisited[CurrentVertex] = false;
            for (var i = 0; i < beyond.Count; i++)
            {
                v = beyond[i];
                if (v == CurrentVertex) continue;
                VertexVisited[v] = false;
                IsBeyond(face, beyondVertices, v);
            }

            for (var i = 0; i < beyond1.Count; i++)
            {
                v = beyond1[i];
                if (VertexVisited[v]) IsBeyond(face, beyondVertices, v);
            }

            face.FurthestVertex = FurthestVertex;

            // Pull the old switch a roo (switch the face beyond buffers)
            var temp = face.VerticesBeyond;
            face.VerticesBeyond = beyondVertices;
            if (temp.Count > 0) temp.Clear();
            BeyondBuffer = temp;
        }
Пример #15
0
        /// <summary>
        /// Removes the element from the list.
        /// </summary>
        /// <param name="face"></param>
        public void Remove(ConvexFaceInternal face)
        {
            if (!face.InList)
            {
                return;
            }

            face.InList = false;

            if (face.Previous != null)
            {
                face.Previous.Next = face.Next;
            }
            else if (/*first == face*/ face.Previous == null)
            {
                this.first = face.Next;
            }

            if (face.Next != null)
            {
                face.Next.Previous = face.Previous;
            }
            else if (/*last == face*/ face.Next == null)
            {
                this.last = face.Previous;
            }

            face.Next     = null;
            face.Previous = null;
        }
Пример #16
0
 /// <summary>
 /// Adds the element to the beginning.
 /// </summary>
 /// <param name="face"></param>
 void AddFirst(ConvexFaceInternal face)
 {
     face.InList = true;
     this.first.Previous = face;
     face.Next = this.first;
     this.first = face;
 }
Пример #17
0
        /// <summary>
        /// Adds a face to the list.
        /// </summary>
        /// <param name="face"></param>
        public void Add(ConvexFaceInternal face)
        {
            if (face.InList)
            {
                if (this.first.VerticesBeyond.Count < face.VerticesBeyond.Count)
                {
                    Remove(face);
                    AddFirst(face);
                }
                return;
            }

            face.InList = true;

            if (first != null && first.VerticesBeyond.Count < face.VerticesBeyond.Count)
            {
                this.first.Previous = face;
                face.Next           = this.first;
                this.first          = face;
            }
            else
            {
                if (this.last != null)
                {
                    this.last.Next = face;
                }
                face.Previous = this.last;
                this.last     = face;
                if (this.first == null)
                {
                    this.first = face;
                }
            }
        }
Пример #18
0
        /// <summary>
        /// Updates the connector.
        /// </summary>
        /// <param name="face"></param>
        /// <param name="edgeIndex"></param>
        /// <param name="dim"></param>
        public void Update(ConvexFaceInternal face, int edgeIndex, int dim)
        {
            this.Face      = face;
            this.EdgeIndex = edgeIndex;

            uint hashCode = 23;

            unchecked
            {
                var vs = face.Vertices;
                int i, c = 0;
                for (i = 0; i < edgeIndex; i++)
                {
                    this.Vertices[c++] = vs[i];
                    hashCode          += 31 * hashCode + (uint)vs[i];
                }
                for (i = edgeIndex + 1; i < vs.Length; i++)
                {
                    this.Vertices[c++] = vs[i];
                    hashCode          += 31 * hashCode + (uint)vs[i];
                }
            }

            this.HashCode = hashCode;
        }
Пример #19
0
        private void IsBeyond(ConvexFaceInternal face, IndexBuffer beyondVertices, int v)
        {
            double vertexDistance = mathHelper.GetVertexDistance(v, face);

            if (vertexDistance >= PlaneDistanceTolerance)
            {
                if (vertexDistance > MaxDistance)
                {
                    if (vertexDistance - MaxDistance < PlaneDistanceTolerance)
                    {
                        if (LexCompare(v, FurthestVertex) > 0)
                        {
                            MaxDistance    = vertexDistance;
                            FurthestVertex = v;
                        }
                    }
                    else
                    {
                        MaxDistance    = vertexDistance;
                        FurthestVertex = v;
                    }
                }
                beyondVertices.Add(v);
            }
        }
Пример #20
0
 /// <summary>
 /// Adds the element to the beginning.
 /// </summary>
 /// <param name="face"></param>
 void AddFirst(ConvexFaceInternal face)
 {
     face.InList         = true;
     this.first.Previous = face;
     face.Next           = this.first;
     this.first          = face;
 }
        /// <summary>
        /// Check if 2 faces are adjacent and if so, update their AdjacentFaces array.
        /// </summary>
        /// <param name="l">The l.</param>
        /// <param name="r">The r.</param>
        private void UpdateAdjacency(ConvexFaceInternal l, ConvexFaceInternal r)
        {
            var lv = l.Vertices;
            var rv = r.Vertices;
            int i;

            // reset marks on the 1st face
            for (i = 0; i < lv.Length; i++)
            {
                VertexVisited[lv[i]] = false;
            }

            // mark all vertices on the 2nd face
            for (i = 0; i < rv.Length; i++)
            {
                VertexVisited[rv[i]] = true;
            }

            // find the 1st false index
            for (i = 0; i < lv.Length; i++)
            {
                if (!VertexVisited[lv[i]])
                {
                    break;
                }
            }

            // no vertex was marked
            if (i == NumOfDimensions)
            {
                return;
            }

            // check if only 1 vertex wasn't marked
            for (var j = i + 1; j < lv.Length; j++)
            {
                if (!VertexVisited[lv[j]])
                {
                    return;
                }
            }

            // if we are here, the two faces share an edge
            l.AdjacentFaces[i] = r.Index;

            // update the adj. face on the other face - find the vertex that remains marked
            for (i = 0; i < lv.Length; i++)
            {
                VertexVisited[lv[i]] = false;
            }
            for (i = 0; i < rv.Length; i++)
            {
                if (VertexVisited[rv[i]])
                {
                    break;
                }
            }
            r.AdjacentFaces[i] = l.Index;
        }
Пример #22
0
        /// <summary>
        /// Check if 2 faces are adjacent and if so, update their AdjacentFaces array.
        /// </summary>
        /// <param name="l"></param>
        /// <param name="r"></param>
        void UpdateAdjacency(ConvexFaceInternal l, ConvexFaceInternal r)
        {
            var lv = l.Vertices;
            var rv = r.Vertices;
            int i;

            // reset marks on the 1st face
            for (i = 0; i < Dimension; i++)
            {
                lv[i].Marked = false;
            }

            // mark all vertices on the 2nd face
            for (i = 0; i < Dimension; i++)
            {
                rv[i].Marked = true;
            }

            // find the 1st false index
            for (i = 0; i < Dimension; i++)
            {
                if (!lv[i].Marked)
                {
                    break;
                }
            }

            // no vertex was marked
            if (i == Dimension)
            {
                return;
            }

            // check if only 1 vertex wasn't marked
            for (int j = i + 1; j < Dimension; j++)
            {
                if (!lv[j].Marked)
                {
                    return;
                }
            }

            // if we are here, the two faces share an edge
            l.AdjacentFaces[i] = r;

            // update the adj. face on the other face - find the vertex that remains marked
            for (i = 0; i < Dimension; i++)
            {
                lv[i].Marked = false;
            }
            for (i = 0; i < Dimension; i++)
            {
                if (rv[i].Marked)
                {
                    break;
                }
            }
            r.AdjacentFaces[i] = l;
        }
Пример #23
0
 public void DepositFace(ConvexFaceInternal face)
 {
     for (int i = 0; i < Dimension; i++)
     {
         face.AdjacentFaces[i] = null;
     }
     RecycledFaceStack.Push(face);
 }
Пример #24
0
 public void DepositFace(ConvexFaceInternal face)
 {
     for (int i = 0; i < Dimension; i++)
     {
         face.AdjacentFaces[i] = null;
     }
     RecycledFaceStack.Push(face);
 }
        /// <summary>
        /// Initializes a new instance of the <see cref="ConvexHullAlgorithm" /> class.
        /// </summary>
        /// <param name="vertices">The vertices.</param>
        /// <param name="lift">if set to <c>true</c> [lift].</param>
        /// <param name="PlaneDistanceTolerance">The plane distance tolerance.</param>
        /// <exception cref="System.InvalidOperationException">Dimension of the input must be 2 or greater.</exception>
        /// <exception cref="System.ArgumentException">There are too few vertices (m) for the n-dimensional space. (m must be greater  +
        /// than the n, but m is  + NumberOfVertices +  and n is  + NumOfDimensions</exception>
        /// <exception cref="InvalidOperationException">PointTranslationGenerator cannot be null if PointTranslationType is enabled.
        /// or
        /// Dimension of the input must be 2 or greater.</exception>
        /// <exception cref="ArgumentException">There are too few vertices (m) for the n-dimensional space. (m must be greater " +
        /// "than the n, but m is " + NumberOfVertices + " and n is " + Dimension</exception>
        internal ConvexHullAlgorithm(IVertex[] vertices, bool lift, double PlaneDistanceTolerance)
        {
            IsLifted         = lift;
            Vertices         = vertices;
            NumberOfVertices = vertices.Length;

            NumOfDimensions = DetermineDimension();
            if (IsLifted)
            {
                NumOfDimensions++;
            }
            if (NumOfDimensions < 2)
            {
                throw new ConvexHullGenerationException(ConvexHullCreationResultOutcome.DimensionSmallerTwo, "Dimension of the input must be 2 or greater.");
            }
            if (NumOfDimensions == 2)
            {
                throw new ConvexHullGenerationException(ConvexHullCreationResultOutcome.DimensionTwoWrongMethod, "Dimension of the input is 2. Thus you should use the Create2D method" +
                                                        " instead of the Create.");
            }
            if (NumberOfVertices <= NumOfDimensions)
            {
                throw new ConvexHullGenerationException(ConvexHullCreationResultOutcome.NotEnoughVerticesForDimension,
                                                        "There are too few vertices (m) for the n-dimensional space. (m must be greater " +
                                                        "than the n, but m is " + NumberOfVertices + " and n is " + NumOfDimensions);
            }
            this.PlaneDistanceTolerance = PlaneDistanceTolerance;
            UnprocessedFaces            = new FaceList();
            ConvexFaces = new IndexBuffer();

            FacePool          = new ConvexFaceInternal[(NumOfDimensions + 1) * 10]; // must be initialized before object manager
            AffectedFaceFlags = new bool[(NumOfDimensions + 1) * 10];
            ObjectManager     = new ObjectManager(this);

            Center             = new double[NumOfDimensions];
            TraverseStack      = new IndexBuffer();
            UpdateBuffer       = new int[NumOfDimensions];
            UpdateIndices      = new int[NumOfDimensions];
            EmptyBuffer        = new IndexBuffer();
            AffectedFaceBuffer = new IndexBuffer();
            ConeFaceBuffer     = new SimpleList <DeferredFace>();
            SingularVertices   = new HashSet <int>();
            BeyondBuffer       = new IndexBuffer();

            ConnectorTable = new ConnectorList[Constants.ConnectorTableSize];
            for (var i = 0; i < Constants.ConnectorTableSize; i++)
            {
                ConnectorTable[i] = new ConnectorList();
            }

            VertexVisited     = new bool[NumberOfVertices];
            Positions         = new double[NumberOfVertices * NumOfDimensions];
            boundingBoxPoints = new List <int> [NumOfDimensions];
            minima            = new double[NumOfDimensions];
            maxima            = new double[NumOfDimensions];
            mathHelper        = new MathHelper(NumOfDimensions, Positions);
        }
Пример #26
0
        private void CreateInitialSimplex()
        {
            List <int> list = FindInitialPoints();

            int[] array = new int[NumOfDimensions + 1];
            for (int i = 0; i < NumOfDimensions + 1; i++)
            {
                int[] array2 = new int[NumOfDimensions];
                int   j      = 0;
                int   num    = 0;
                for (; j <= NumOfDimensions; j++)
                {
                    if (i != j)
                    {
                        if (j == list.Count)
                        {
                            int num2 = 0;
                            num2++;
                        }
                        int num3 = list[j];
                        array2[num++] = num3;
                    }
                }
                ConvexFaceInternal convexFaceInternal = FacePool[ObjectManager.GetFace()];
                convexFaceInternal.Vertices = array2;
                Array.Sort(array2);
                mathHelper.CalculateFacePlane(convexFaceInternal, Center);
                array[i] = convexFaceInternal.Index;
            }
            for (int k = 0; k < NumOfDimensions; k++)
            {
                for (int l = k + 1; l < NumOfDimensions + 1; l++)
                {
                    UpdateAdjacency(FacePool[array[k]], FacePool[array[l]]);
                }
            }
            int[] array3 = array;
            foreach (int num5 in array3)
            {
                ConvexFaceInternal convexFaceInternal2 = FacePool[num5];
                FindBeyondVertices(convexFaceInternal2);
                if (convexFaceInternal2.VerticesBeyond.Count == 0)
                {
                    ConvexFaces.Add(convexFaceInternal2.Index);
                }
                else
                {
                    UnprocessedFaces.Add(convexFaceInternal2);
                }
            }
            foreach (int item in list)
            {
                VertexVisited[item] = false;
            }
        }
        public void DepositFace(int faceIndex)
        {
            ConvexFaceInternal convexFaceInternal = FacePool[faceIndex];

            int[] adjacentFaces = convexFaceInternal.AdjacentFaces;
            for (int i = 0; i < adjacentFaces.Length; i++)
            {
                adjacentFaces[i] = -1;
            }
            FreeFaceIndices.Push(faceIndex);
        }
Пример #28
0
        private DeferredFace MakeDeferredFace(ConvexFaceInternal face, int faceIndex, ConvexFaceInternal pivot, int pivotIndex, ConvexFaceInternal oldFace)
        {
            DeferredFace deferredFace = this.ObjectManager.GetDeferredFace();

            deferredFace.Face       = face;
            deferredFace.FaceIndex  = faceIndex;
            deferredFace.Pivot      = pivot;
            deferredFace.PivotIndex = pivotIndex;
            deferredFace.OldFace    = oldFace;
            return(deferredFace);
        }
Пример #29
0
 /// <summary>
 /// Reallocate the face pool, including the AffectedFaceFlags
 /// </summary>
 void ReallocateFacePool()
 {
     var newPool = new ConvexFaceInternal[2 * FacePoolCapacity];
     var newTags = new bool[2 * FacePoolCapacity];
     Array.Copy(FacePool, newPool, FacePoolCapacity);
     Buffer.BlockCopy(Hull.AffectedFaceFlags, 0, newTags, 0, FacePoolCapacity * sizeof(bool));
     FacePoolCapacity = 2 * FacePoolCapacity;
     Hull.FacePool = newPool;
     this.FacePool = newPool;
     Hull.AffectedFaceFlags = newTags;
 }
Пример #30
0
 private void ReallocateFacePool()
 {
     ConvexFaceInternal[] destinationArray = new ConvexFaceInternal[2 * this.FacePoolCapacity];
     bool[] dst = new bool[2 * this.FacePoolCapacity];
     Array.Copy(this.FacePool, destinationArray, this.FacePoolCapacity);
     Buffer.BlockCopy(this.Hull.AffectedFaceFlags, 0, dst, 0, this.FacePoolCapacity);
     this.FacePoolCapacity       = 2 * this.FacePoolCapacity;
     this.Hull.FacePool          = destinationArray;
     this.FacePool               = destinationArray;
     this.Hull.AffectedFaceFlags = dst;
 }
 private void ReallocateFacePool()
 {
     ConvexFaceInternal[] array = new ConvexFaceInternal[2 * FacePoolCapacity];
     bool[] array2 = new bool[2 * FacePoolCapacity];
     Array.Copy(FacePool, array, FacePoolCapacity);
     Buffer.BlockCopy(Hull.AffectedFaceFlags, 0, array2, 0, FacePoolCapacity);
     FacePoolCapacity       = 2 * FacePoolCapacity;
     Hull.FacePool          = array;
     FacePool               = array;
     Hull.AffectedFaceFlags = array2;
 }
Пример #32
0
        /// <summary>
        /// Check if the vertex is "visible" from the face.
        /// The vertex is "over face" if the return value is &gt; Constants.PlaneDistanceTolerance.
        /// </summary>
        /// <param name="v">The v.</param>
        /// <param name="f">The f.</param>
        /// <returns>The vertex is "over face" if the result is positive.</returns>
        internal double GetVertexDistance(int v, ConvexFaceInternal f)
        {
            var normal   = f.Normal;
            var x        = v * Dimension;
            var distance = f.Offset;

            for (var i = 0; i < normal.Length; i++)
            {
                distance += normal[i] * PositionData[x + i];
            }
            return(distance);
        }
        /// <summary>
        /// Check if the vertex is "visible" from the face.
        /// The vertex is "over face" if the return value is > Constants.PlaneDistanceTolerance.
        /// </summary>
        /// <param name="v"></param>
        /// <param name="f"></param>
        /// <returns>The vertex is "over face" if the result is positive.</returns>
        public double GetVertexDistance(VertexWrap v, ConvexFaceInternal f)
        {
            double[] normal   = f.Normal;
            double[] p        = v.PositionData;
            double   distance = f.Offset;

            for (int i = 0; i < Dimension; i++)
            {
                distance += normal[i] * p[i];
            }
            return(distance);
        }
Пример #34
0
        /// <summary>
        /// Computes the volume of an n-dimensional simplex.
        /// Buffer needs to be array of shape Dimension x Dimension.
        /// </summary>
        /// <param name="cell"></param>
        /// <param name="vertices"></param>
        /// <param name="buffer">Helper for the calculation to avoid unnecessary allocations.</param>
        /// <returns></returns>
        public static double GetSimplexVolume(ConvexFaceInternal cell, IList<IVertex> vertices, SimplexVolumeBuffer buffer)
        {
            var xs = cell.Vertices;
            var pivot = vertices[xs[0]].Position;
            var data = buffer.Data;
            var dim = buffer.Dimension;
            double f = 1.0;
            for (int i = 1; i < xs.Length; i++)
            {
                f *= i + 1;
                var point = vertices[xs[i]].Position;
                for (int j = 0; j < point.Length; j++) data[j * dim + i - 1] = point[j] - pivot[j];
            }

            return Math.Abs(DeterminantDestructive(buffer)) / f;
        }
Пример #35
0
        /// <summary>
        /// Calculates the normal and offset of the hyper-plane given by the face's vertices.
        /// </summary>
        /// <param name="face"></param>
        /// <param name="center"></param>
        /// <returns></returns>
        public bool CalculateFacePlane(ConvexFaceInternal face, double[] center)
        {
            var vertices = face.Vertices;
            var normal = face.Normal;
            FindNormalVector(vertices, normal);

            if (double.IsNaN(normal[0]))
            {
                return false;
            }

            double offset = 0.0;
            double centerDistance = 0.0;
            var fi = vertices[0] * Dimension;
            for (int i = 0; i < Dimension; i++)
            {
                double n = normal[i];
                offset += n * PositionData[fi + i];
                centerDistance += n * center[i];
            }
            face.Offset = -offset;
            centerDistance -= offset;

            if (centerDistance > 0)
            {
                for (int i = 0; i < Dimension; i++) normal[i] = -normal[i];
                face.Offset = offset;
                face.IsNormalFlipped = true;
            }
            else face.IsNormalFlipped = false;

            return true;
        }
Пример #36
0
 /// <summary>
 /// Create a new face and put it in the pool.
 /// </summary>
 /// <returns></returns>
 int CreateFace()
 {
     var index = FacePoolSize;
     var face = new ConvexFaceInternal(Dimension, index, GetVertexBuffer());
     FacePoolSize++;
     if (FacePoolSize > FacePoolCapacity) ReallocateFacePool();
     FacePool[index] = face;
     return index;
 }
Пример #37
0
        /// <summary>
        /// Check if 2 faces are adjacent and if so, update their AdjacentFaces array.
        /// </summary>
        /// <param name="l"></param>
        /// <param name="r"></param>
        void UpdateAdjacency(ConvexFaceInternal l, ConvexFaceInternal r)
        {
            var lv = l.Vertices;
            var rv = r.Vertices;
            int i;

            // reset marks on the 1st face
            for (i = 0; i < lv.Length; i++) VertexMarks[lv[i]] = false;

            // mark all vertices on the 2nd face
            for (i = 0; i < rv.Length; i++) VertexMarks[rv[i]] = true;

            // find the 1st false index
            for (i = 0; i < lv.Length; i++) if (!VertexMarks[lv[i]]) break;

            // no vertex was marked
            if (i == Dimension) return;

            // check if only 1 vertex wasn't marked
            for (int j = i + 1; j < lv.Length; j++) if (!VertexMarks[lv[j]]) return;

            // if we are here, the two faces share an edge
            l.AdjacentFaces[i] = r.Index;

            // update the adj. face on the other face - find the vertex that remains marked
            for (i = 0; i < lv.Length; i++) VertexMarks[lv[i]] = false;
            for (i = 0; i < rv.Length; i++)
            {
                if (VertexMarks[rv[i]]) break;
            }
            r.AdjacentFaces[i] = l.Index;
        }
Пример #38
0
        /// <summary>
        /// Used in the "initialization" code.
        /// </summary>
        void FindBeyondVertices(ConvexFaceInternal face)
        {
            var beyondVertices = face.VerticesBeyond;

            MaxDistance = double.NegativeInfinity;
            FurthestVertex = 0;

            int count = Vertices.Length;
            for (int i = 0; i < count; i++)
            {
                if (VertexMarks[i]) continue;
                IsBeyond(face, beyondVertices, i);
            }

            face.FurthestVertex = FurthestVertex;
        }
Пример #39
0
        /// <summary>
        /// Updates the connector.
        /// </summary>
        /// <param name="face"></param>
        /// <param name="edgeIndex"></param>
        /// <param name="dim"></param>
        public void Update(ConvexFaceInternal face, int edgeIndex, int dim)
        {
            this.Face = face;
            this.EdgeIndex = edgeIndex;

            uint hashCode = 23;

            unchecked
            {
                var vs = face.Vertices;
                int i, c = 0;
                for (i = 0; i < edgeIndex; i++)
                {
                    this.Vertices[c++] = vs[i];
                    hashCode += 31 * hashCode + (uint)vs[i];
                }
                for (i = edgeIndex + 1; i < vs.Length; i++)
                {
                    this.Vertices[c++] = vs[i];
                    hashCode += 31 * hashCode + (uint)vs[i];
                }
            }

            this.HashCode = hashCode;
        }
Пример #40
0
        /// <summary>
        /// Adds a face to the list.
        /// </summary>
        /// <param name="face"></param>
        public void Add(ConvexFaceInternal face)
        {
            if (face.InList)
            {
                //if (this.first.FurthestDistance < face.FurthestDistance)
                if (this.first.VerticesBeyond.Count < face.VerticesBeyond.Count)
                {
                    Remove(face);
                    AddFirst(face);
                }
                return;
            }

            face.InList = true;

            //if (first != null && first.FurthestDistance < face.FurthestDistance)
            if (first != null && first.VerticesBeyond.Count < face.VerticesBeyond.Count)
            {
                this.first.Previous = face;
                face.Next = this.first;
                this.first = face;
            }
            else
            {
                if (this.last != null)
                {
                    this.last.Next = face;
                }
                face.Previous = this.last;
                this.last = face;
                if (this.first == null)
                {
                    this.first = face;
                }
            }
        }
Пример #41
0
        /// <summary>
        /// Removes the element from the list.
        /// </summary>
        /// <param name="face"></param>
        public void Remove(ConvexFaceInternal face)
        {
            if (!face.InList) return;

            face.InList = false;

            if (face.Previous != null)
            {
                face.Previous.Next = face.Next;
            }
            else if (/*first == face*/ face.Previous == null)
            {
                this.first = face.Next;
            }

            if (face.Next != null)
            {
                face.Next.Previous = face.Previous;
            }
            else if (/*last == face*/ face.Next == null)
            {
                this.last = face.Previous;
            }

            face.Next = null;
            face.Previous = null;
        }
Пример #42
0
 /// <summary>
 /// Check if the vertex is "visible" from the face.
 /// The vertex is "over face" if the return value is > Constants.PlaneDistanceTolerance.
 /// </summary>
 /// <param name="v"></param>
 /// <param name="f"></param>
 /// <returns>The vertex is "over face" if the result is positive.</returns>
 public double GetVertexDistance(int v, ConvexFaceInternal f)
 {
     double[] normal = f.Normal;
     int x = v * Dimension;
     double distance = f.Offset;
     for (int i = 0; i < normal.Length; i++) distance += normal[i] * PositionData[x + i];
     return distance;
 }
Пример #43
0
 /// <summary>
 /// Check if the vertex is "visible" from the face.
 /// The vertex is "over face" if the return value is > Constants.PlaneDistanceTolerance.
 /// </summary>
 /// <param name="v"></param>
 /// <param name="f"></param>
 /// <returns>The vertex is "over face" if the result is positive.</returns>
 public double GetVertexDistance(VertexWrap v, ConvexFaceInternal f)
 {
     double[] normal = f.Normal;
     double[] p = v.PositionData;
     double distance = f.Offset;
     for (int i = 0; i < Dimension; i++) distance += normal[i] * p[i];
     return distance;
 }