Пример #1
0
        private UniversalFaceSpatialPartitioning Initialize(Surface surface, Topology topology, IVertexAttribute <Vector3> vertexPositions)
        {
            _surface  = surface;
            _topology = topology;

            var edges = _topology.faceEdges;

            _partitionBinaryTree = new Partition[edges.Count];

            int edgesProcessed = 0;
            int increment      = 1;

            if (edges.Count % 23 != 0)
            {
                increment = 23;
            }
            else if (edges.Count % 19 != 0)
            {
                increment = 19;
            }
            else if (edges.Count % 17 != 0)
            {
                increment = 17;
            }
            else if (edges.Count % 13 != 0)
            {
                increment = 13;
            }
            else if (edges.Count % 11 != 0)
            {
                increment = 11;
            }
            else if (edges.Count % 7 != 0)
            {
                increment = 7;
            }
            else if (edges.Count % 5 != 0)
            {
                increment = 5;
            }
            else if (edges.Count % 3 != 0)
            {
                increment = 3;
            }
            else if (edges.Count % 2 != 0)
            {
                increment = 2;
            }

            int edgeIndex = (edges.Count * 7) / 16;

            // Find the first edge that will work as the root.  It must be the earlier twin, and should not
            // have any face-to-face wrapping or be on the boundary between an internal face and external faces.
            while (edgesProcessed < edges.Count)
            {
                ++edgesProcessed;
                var edge = edges[edgeIndex];
                if (edgeIndex < edge.twinIndex && (edge.wrap & EdgeWrap.FaceToFace) == EdgeWrap.None && edge.isNonBoundary)
                {
                    _partitionBinaryTree[0] = Partition.Create(edge, vertexPositions, surface);
                    edgeIndex = (edgeIndex + increment) % edges.Count;
                    break;
                }
                edgeIndex = (edgeIndex + increment) % edges.Count;
            }

            int nextPartitionIndex = 1;

            // Process all remaining non-wrapping non-boundary edges.  As above, only concentrate on the earlier twins.
            while (edgesProcessed < edges.Count)
            {
                ++edgesProcessed;
                var edge = edges[edgeIndex];
                if (edgeIndex < edge.twinIndex && (edge.wrap & EdgeWrap.FaceToFace) == EdgeWrap.None && edge.isNonBoundary)
                {
                    PartitionEdge(edge, vertexPositions, ref nextPartitionIndex);
                }
                edgeIndex = (edgeIndex + increment) % edges.Count;
            }

            edgesProcessed = 0;

            // Process all wrapping edges, which should be at or near the leaves of the tree.
            while (edgesProcessed < edges.Count)
            {
                ++edgesProcessed;
                var edge = edges[edgeIndex];
                // If the edge has face-to-face wrapping, then don't restrict to only the earlier twin.
                // Both twins should be processed.
                if ((edge.wrap & EdgeWrap.FaceToFace) != EdgeWrap.None && edge.isNonBoundary)
                {
                    PartitionEdge(edge, vertexPositions, ref nextPartitionIndex);
                }
                edgeIndex = (edgeIndex + increment) % edges.Count;
            }

            edgesProcessed = 0;

            // Process all external edges, which should be at or near the leaves of the tree.
            // Note that it is critical that boundary edges occur after all wrapping edges.
            // Otherwise, false negatives (hitting an external face when a wrap should have
            // led to an internal face instead) or even infinite loops are possible.
            while (edgesProcessed < edges.Count)
            {
                ++edgesProcessed;
                var edge = edges[edgeIndex];
                // If the edge is a boundary edge, then only process it if it's the external
                // edge.  The internal half doesn't need to be processed at all.
                if (edge.isBoundary && edge.isExternal)
                {
                    PartitionEdge(edge, vertexPositions, ref nextPartitionIndex);
                }
                edgeIndex = (edgeIndex + increment) % edges.Count;
            }

            if (nextPartitionIndex < _partitionBinaryTree.Length)
            {
                TruncateBinaryTree(nextPartitionIndex);
            }

            return(this);
        }
Пример #2
0
            public static Partition Create(Topology.FaceEdge edge, IVertexAttribute <Vector3> vertexPositions, Surface surface)
            {
                var prevEdge    = edge.prev;
                var vPos0       = vertexPositions[prevEdge];
                var vPos1       = vertexPositions[edge];
                var edgeVector  = vPos1 - vPos0;
                var edgeNormal  = surface.GetNormal(vPos0);
                var planeNormal = Vector3.Cross(edgeVector, edgeNormal).normalized;

                return(new Partition(planeNormal, vPos0, edge.twinIndex, edge.index));
            }
Пример #3
0
 /// <summary>
 /// Creates a spatial partitioning for the given manifold.
 /// </summary>
 /// <param name="surface">The surface describing the overall shape of the manifold.</param>
 /// <param name="topology">The topological relations of vertices, edges, and faces of the manifold.</param>
 /// <param name="vertexPositions">The positions of the manifold's vertices.</param>
 /// <returns>A spatial partitioning for the given manifold.</returns>
 public static UniversalFaceSpatialPartitioning Create(Surface surface, Topology topology, IVertexAttribute <Vector3> vertexPositions)
 {
     return(CreateInstance <UniversalFaceSpatialPartitioning>().Initialize(surface, topology, vertexPositions));
 }