//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 }); }
/// <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); }
/// <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; }