//Note: Corner vertices must be ordered correctly. See below where - = low and + = high along directions 0, 1, and 2 respectively.
        // [0] = +++, [1] = +-+, [2] = +--, [3] = ++-, [4] = -++, [5] = --+, [6] = ---, [7] = -+-
        public static BoundingBox FromCornerVertices(double[][] directions, Vertex[] cornerVertices, bool areVerticesInCorrectOrder)
        {
            if (!areVerticesInCorrectOrder)
            {
                throw new Exception("Not implemented exception. Vertices must be in correct order for OBB");
            }
            if (cornerVertices.Length != 8)
            {
                throw new Exception("Must set Bounding Box using eight corner vertices in correct order");
            }

            var dimensions = new[] { 0.0, 0.0, 0.0 };

            dimensions[0] = MinimumEnclosure.GetLengthAndExtremeVertices(directions[0], cornerVertices, out _, out _);
            dimensions[1] = MinimumEnclosure.GetLengthAndExtremeVertices(directions[1], cornerVertices, out _, out _);
            dimensions[2] = MinimumEnclosure.GetLengthAndExtremeVertices(directions[2], cornerVertices, out _, out _);

            //Add in the center
            var centerPosition = new[] { 0.0, 0.0, 0.0 };

            centerPosition = cornerVertices.Aggregate(centerPosition, (c, v) => c.add(v.Position, 3))
                             .divide(cornerVertices.Count(), 3);

            return(new BoundingBox
            {
                Center = new Vertex(centerPosition),
                Volume = dimensions[0] * dimensions[1] * dimensions[2],
                Dimensions = dimensions,
                Directions = directions,
                PointsOnFaces = null,
                CornerVertices = cornerVertices
            });
        }
Example #2
0
        /// <summary>
        /// Gets the silhouette of a solid along a given normal.
        /// </summary>
        /// <param name="ts"></param>
        /// <param name="normal"></param>
        /// <param name="minAngle"></param>
        /// <returns></returns>
        public static List <List <PointLight> > Run(TessellatedSolid ts, double[] normal, double minAngle = 0.1)
        {
            var depthOfPart = MinimumEnclosure.GetLengthAndExtremeVertices(normal, ts.Vertices, out _, out _);

            return(Run(ts.Faces, normal, ts, minAngle, ts.SameTolerance, depthOfPart));
        }
        /// <summary>
        ///     Adds the corner vertices to the bounding box.
        ///     This method is used when the face vertices are not known.
        ///     The dimensions are also updated, in the event that the points of faces were altered (replaced or shifted).
        /// </summary>
        /// <returns>BoundingBox.</returns>
        public void SetCornerVertices(List <Vertex> verticesOfInterest)
        {
            var cornerVertices = new Vertex[8];

            //Get the low extreme vertices along each direction
            List <Vertex> vLows, vHighs;

            Dimensions[0] = MinimumEnclosure.GetLengthAndExtremeVertices(Directions[0], verticesOfInterest, out vLows, out vHighs);
            var v0 = new Vertex(vLows.First().Position);

            Dimensions[1] = MinimumEnclosure.GetLengthAndExtremeVertices(Directions[1], verticesOfInterest, out vLows, out vHighs);
            var v1 = new Vertex(vLows.First().Position);

            Dimensions[2] = MinimumEnclosure.GetLengthAndExtremeVertices(Directions[2], verticesOfInterest, out vLows, out vHighs);
            var v2 = new Vertex(vLows.First().Position);

            //Start with v0 and move along direction[1] by projection
            var vector0To1       = v1.Position.subtract(v0.Position, 3);
            var projectionOntoD1 = Directions[1].multiply(Directions[1].dotProduct(vector0To1, 3));
            var v4 = v0.Position.add(projectionOntoD1, 3);

            //Move along direction[2] by projection
            var vector4To2       = v2.Position.subtract(v4, 3);
            var projectionOntoD2 = Directions[2].multiply(Directions[2].dotProduct(vector4To2, 3));
            var bottomCorner     = new Vertex(v4.add(projectionOntoD2, 3));

            //Double Check to make sure it is the bottom corner
            verticesOfInterest.Add(bottomCorner);
            MinimumEnclosure.GetLengthAndExtremeVertices(Directions[0], verticesOfInterest, out vLows, out vHighs);
            if (!vLows.Contains(bottomCorner))
            {
                throw new Exception("Error in defining bottom corner");
            }
            MinimumEnclosure.GetLengthAndExtremeVertices(Directions[1], verticesOfInterest, out vLows, out vHighs);
            if (!vLows.Contains(bottomCorner))
            {
                throw new Exception("Error in defining bottom corner");
            }
            MinimumEnclosure.GetLengthAndExtremeVertices(Directions[2], verticesOfInterest, out vLows, out vHighs);
            if (!vLows.Contains(bottomCorner))
            {
                throw new Exception("Error in defining bottom corner");
            }

            //Create the vertices that make up the box and add them to the corner vertices array
            for (var i = 0; i < 2; i++)
            {
                var d0Vector = i == 0 ? new[] { 0.0, 0.0, 0.0 } : Directions[0].multiply(Dimensions[0]);
                for (var j = 0; j < 2; j++)
                {
                    var d1Vector = j == 0 ? new[] { 0.0, 0.0, 0.0 } : Directions[1].multiply(Dimensions[1]);
                    for (var k = 0; k < 2; k++)
                    {
                        var d2Vector  = k == 0 ? new[] { 0.0, 0.0, 0.0 } : Directions[2].multiply(Dimensions[2]);
                        var newVertex = new Vertex(bottomCorner.Position.add(d0Vector, 3).add(d1Vector, 3).add(d2Vector, 3));

                        //
                        var b = k == 0 ? 0 : 4;
                        if (j == 0)
                        {
                            if (i == 0)
                            {
                                cornerVertices[b] = newVertex;         //i == 0 && j== 0 && k == 0 or 1
                            }
                            else
                            {
                                cornerVertices[b + 1] = newVertex;  //i == 1 && j == 0 && k == 0 or 1
                            }
                        }
                        else
                        {
                            if (i == 0)
                            {
                                cornerVertices[b + 3] = newVertex;         //i == 0 && j== 1 && k == 0 or 1
                            }
                            else
                            {
                                cornerVertices[b + 2] = newVertex;  //i == 1 && j == 1 && k == 0 or 1
                            }
                        }
                    }
                }
            }

            //Add in the center
            var centerPosition = new[] { 0.0, 0.0, 0.0 };

            foreach (var vertex in cornerVertices)
            {
                centerPosition[0] += vertex.Position[0];
                centerPosition[1] += vertex.Position[1];
                centerPosition[2] += vertex.Position[2];
            }
            centerPosition[0] = centerPosition[0] / cornerVertices.Count();
            centerPosition[1] = centerPosition[1] / cornerVertices.Count();
            centerPosition[2] = centerPosition[2] / cornerVertices.Count();

            CornerVertices = cornerVertices;
            Center         = new Vertex(centerPosition);
        }