//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
            });
        }
Exemple #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);
        }
Exemple #4
0
        /// <summary>
        /// Sets the corner points and center position for the bounding rectangle
        /// </summary>
        /// <exception cref="Exception"></exception>
        public void SetCornerPoints()
        {
            var cornerPoints  = new Point[4];
            var dir0          = Directions2D[0];
            var dir1          = Directions2D[1];
            var extremePoints = new List <Point>();

            foreach (var pair in PointsOnSides)
            {
                extremePoints.AddRange(pair);
            }

            //Lower left point
            List <Point> bottomPoints, topPoints;

            MinimumEnclosure.GetLengthAndExtremePoints(dir0, extremePoints, out bottomPoints, out topPoints);
            var bp = bottomPoints.First().Position;
            var p0 = new [] { bp[0], bp[1] };

            MinimumEnclosure.GetLengthAndExtremePoints(dir1, extremePoints, out bottomPoints, out topPoints);
            bp = bottomPoints.First().Position;
            var p1 = new[] { bp[0], bp[1] };

            //Start with v0 and move along direction[1] by projection
            var vector0To1       = p1.subtract(p0, 2);
            var projectionOntoD1 = dir1.multiply(dir1.dotProduct(vector0To1, 2));
            var p2           = p0.add(projectionOntoD1, 2);
            var bottomCorner = new Point(p2);

            //Double Check to make sure it is the bottom corner
            extremePoints.Add(bottomCorner);
            MinimumEnclosure.GetLengthAndExtremePoints(dir0, extremePoints, out bottomPoints, out topPoints);
            if (!bottomPoints.Contains(bottomCorner))
            {
                throw new Exception("Error in defining bottom corner");
            }
            MinimumEnclosure.GetLengthAndExtremePoints(dir1, extremePoints, out bottomPoints, out topPoints);
            if (!bottomPoints.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 } : dir0.multiply(Dimensions[0]);
                for (var j = 0; j < 2; j++)
                {
                    var d1Vector = j == 0 ? new[] { 0.0, 0.0 } : dir1.multiply(Dimensions[1]);
                    var newPoint = new Point(bottomCorner.Position.add(d0Vector, 2).add(d1Vector, 2));
                    //Put the points in the correct position to be ordered CCW, starting with the bottom corner
                    if (i == 0)
                    {
                        if (j == 0)
                        {
                            cornerPoints[0] = newPoint;         // i == 0, j == 0
                        }
                        else
                        {
                            cornerPoints[1] = newPoint;  // i == 0, j == 1
                        }
                    }
                    else if (j == 1)
                    {
                        cornerPoints[2] = newPoint;              //i == 1, j ==1
                    }
                    else
                    {
                        cornerPoints[3] = newPoint; //i == 1, j == 0
                    }
                }
            }

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

            foreach (var vertex in cornerPoints)
            {
                centerPosition[0] += vertex.X;
                centerPosition[1] += vertex.Y;
            }
            centerPosition[0] = centerPosition[0] / cornerPoints.Count();
            centerPosition[1] = centerPosition[1] / cornerPoints.Count();

            //Check to make sure the points are ordered correctly (within 1 %)
            if (!MiscFunctions.AreaOfPolygon(cornerPoints).IsPracticallySame(Area, 0.01 * Area))
            {
                throw new Exception("Points are ordered incorrectly");
            }

            CornerPoints   = new List <Point>(cornerPoints);
            CenterPosition = centerPosition;
        }