private static double UpdateBackAngle(BoundingBoxData boxData)
        {
            Edge nextEdge = null;
            var  yDir     = boxData.RotatorVector.Cross(boxData.Direction);
            var  minSlope = double.PositiveInfinity;

            foreach (var edge in boxData.BackVertex.Edges)
            {
                var otherVertex = edge.OtherVertex(boxData.BackVertex);
                var vector      = otherVertex.Coordinates.Subtract(boxData.BackVertex.Coordinates);
                var y           = yDir.Dot(vector);
                if (y < 0)
                {
                    // the x-value is boxData.Direction.Dot(vector) and it's positive for all edges since it's the back vertex
                    var slope = -boxData.Direction.Dot(vector) / y;
                    if (slope < minSlope)
                    {
                        minSlope = slope;
                        nextEdge = edge;
                    }
                }
            }
            if (minSlope < 0)
            {
                return(double.PositiveInfinity);
            }
            boxData.BackVertex = nextEdge.OtherVertex(boxData.BackVertex);
            boxData.BackEdge   = nextEdge;
            return(Math.Atan(minSlope));
        }
        private static double UpdateOrthAngle(BoundingBoxData boxData)
        {
            GaussSphereArc arcToRemove = null;
            var            minSlope    = double.PositiveInfinity;

            boxData.PosYDir = boxData.RotatorVector.Cross(boxData.Direction).Normalize();
            foreach (var arc in boxData.OrthGaussSphereArcs)
            {
                var x = boxData.Direction.Dot(arc.ToFace.Normal);
                var y = boxData.PosYDir.Dot(arc.ToFace.Normal);
                if (y == 0.0)
                {
                    continue;
                }
                var tempSlope = -x / y;
                if (!(tempSlope < minSlope))
                {
                    continue;
                }
                minSlope    = tempSlope;
                arcToRemove = arc;
            }
            if (minSlope < 0)
            {
                return(double.PositiveInfinity);
            }
            var edgesAtJunction = new List <Edge>(arcToRemove.ToFace.Edges);

            for (var i = boxData.OrthGaussSphereArcs.Count - 1; i >= 0; i--)
            {
                var index = edgesAtJunction.FindIndex(boxData.OrthGaussSphereArcs[i].Edge);
                if (index >= 0)
                {
                    boxData.OrthGaussSphereArcs.RemoveAt(i);
                    boxData.OrthVertices.Remove(edgesAtJunction[index].From);
                    boxData.OrthVertices.Remove(edgesAtJunction[index].To);
                    edgesAtJunction.RemoveAt(index);
                }
            }
            foreach (var edge in edgesAtJunction)
            {
                if (!boxData.OrthVertices.Contains(edge.From))
                {
                    boxData.OrthVertices.Add(edge.From);
                }
                if (!boxData.OrthVertices.Contains(edge.To))
                {
                    boxData.OrthVertices.Add(edge.To);
                }
                boxData.OrthGaussSphereArcs.Add(new GaussSphereArc(edge, edge.OwnedFace == arcToRemove.ToFace
                    ? edge.OtherFace
                    : edge.OwnedFace));
            }
            return(Math.Atan(minSlope));
        }
        private static bool DifferentMembershipInExtrema(BoundingBoxData boxDataA, BoundingBoxData boxDataB)
        {
            var boxASides = boxDataA.Box.PointsOnFaces.Skip(2);
            var boxBSides = boxDataB.Box.PointsOnFaces.Skip(2).ToList();

            foreach (var boxASide in boxASides)
            {
                if (!boxBSides.Any(boxBSide => boxASide.Intersect(boxBSide).Any()))
                {
                    return(true);
                }
            }
            return(false);
        }
Exemplo n.º 4
0
        /// <summary>
        ///     Finds the obb along direction.
        /// </summary>
        /// <param name="boxData">The box data.</param>
        private static void FindOBBAlongDirection(BoundingBoxData boxData)
        {
            var direction0 = boxData.Direction = boxData.Direction.normalize(3);
            var height     = direction0.dotProduct(boxData.RotatorEdge.From.Position.subtract(boxData.BackVertex.Position, 3), 3);

            double[,] backTransform;
            var points            = MiscFunctions.Get2DProjectionPoints(boxData.OrthVertices, direction0, out backTransform, false);
            var boundingRectangle = RotatingCalipers2DMethod(points);
            //Get the Direction vectors from rotating caliper and projection.
            var tempDirection = new[]
            {
                boundingRectangle.Directions2D[0][0], boundingRectangle.Directions2D[0][1],
                0.0, 1.0
            };
            var direction1 = backTransform.multiply(tempDirection).Take(3).ToArray();

            tempDirection = new[]
            {
                boundingRectangle.Directions2D[1][0], boundingRectangle.Directions2D[1][1],
                0.0, 1.0
            };
            var direction2 = backTransform.multiply(tempDirection).Take(3).ToArray();

            boxData.Box =
                new BoundingBox
            {
                Dimensions    = new[] { height, boundingRectangle.Dimensions[0], boundingRectangle.Dimensions[1] },
                Directions    = new[] { direction0, direction1, direction2 },
                PointsOnFaces = new[]
                {
                    new List <Vertex> {
                        boxData.RotatorEdge.From, boxData.RotatorEdge.To
                    },
                    new List <Vertex> {
                        boxData.BackVertex
                    },
                    boundingRectangle.PointsOnSides[0].SelectMany(p => p.References).ToList(),
                    boundingRectangle.PointsOnSides[1].SelectMany(p => p.References).ToList(),
                    boundingRectangle.PointsOnSides[2].SelectMany(p => p.References).ToList(),
                    boundingRectangle.PointsOnSides[3].SelectMany(p => p.References).ToList()
                },
                Volume = height * boundingRectangle.Dimensions[0] * boundingRectangle.Dimensions[1]
            };
        }
Exemplo n.º 5
0
        public void SerializeBoundingBoxData_ValidObjectsGiven_ShouldPass()
        {
            const string expectedXml = @"<?xml version=""1.0"" encoding=""utf-8""?><wps:BoundingBoxData xmlns:ows=""http://www.opengis.net/ows/2.0"" xmlns:xli=""http://www.w3.org/1999/xlink"" xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:wps=""http://www.opengis.net/wps/2.0""><wps:Format mimeType=""test"" maximumMegabytes=""0"" default=""false"" /><wps:Format mimeType=""test"" maximumMegabytes=""0"" default=""false"" /><wps:SupportedCRS default=""true"">test-uri-1</wps:SupportedCRS><wps:SupportedCRS default=""true"">test-uri-1</wps:SupportedCRS><wps:SupportedCRS default=""true"">test-uri-1</wps:SupportedCRS></wps:BoundingBoxData>";

            // Remove white spaces and new line characters for XML comparison.
            var trimmedExpectedXml = Regex.Replace(expectedXml, @"\s+", string.Empty);

            var boundingBoxData = new BoundingBoxData
            {
                Formats = new[]
                {
                    new Format {
                        MimeType = "test"
                    },
                    new Format {
                        MimeType = "test"
                    },
                },
                SupportedCrs = new[]
                {
                    new CoordinateReferenceSystem {
                        IsDefault = true, Uri = "test-uri-1"
                    },
                    new CoordinateReferenceSystem {
                        IsDefault = true, Uri = "test-uri-1"
                    },
                    new CoordinateReferenceSystem {
                        IsDefault = true, Uri = "test-uri-1"
                    },
                }
            };

            var resultXml     = _serializer.Serialize(boundingBoxData);
            var trimmedResult = Regex.Replace(resultXml, @"\s+", string.Empty);

            trimmedResult.Should().Be(trimmedExpectedXml);
        }
 //void Update()
 //{
 //    if(Input.GetKeyUp(KeyCode.Alpha1))
 //    {
 //        Play("sayHi", 1, 1);
 //    }
 //}
 public Rect GetRectColider(string name)
 {
     if (dragonBonesCom != null && dragonBonesCom.animation != null)
     {
         Slot slot = dragonBonesCom.armature.GetSlot(name);
         if (slot != null)
         {
             BoundingBoxData boundingBoxData = slot.boundingBoxData;
             if (boundingBoxData != null)
             {
                 var tx = slot.globalTransformMatrix.tx;
                 var ty = slot.globalTransformMatrix.ty;
                 var boundingBoxWidth  = boundingBoxData.width;
                 var boundingBoxHeight = boundingBoxData.height;
                 //var leftTopPos = new Vector3(tx - boundingBoxWidth * 0.5f, ty + boundingBoxHeight * 0.5f, 0.0f);
                 //var leftBottomPos = new Vector3(tx - boundingBoxWidth * 0.5f, ty - boundingBoxHeight * 0.5f, 0.0f);
                 //var rightTopPos = new Vector3(tx + boundingBoxWidth * 0.5f, ty + boundingBoxHeight * 0.5f, 0.0f);
                 //var rightBottomPos = new Vector3(tx + boundingBoxWidth * 0.5f, ty - boundingBoxHeight * 0.5f, 0.0f);
                 return(new Rect(tx, ty, boundingBoxWidth, boundingBoxHeight));
             }
         }
     }
     return(new Rect(0, 0, 0, 0));
 }
        /// <summary>
        ///     The MC_ApproachOne rotates around each edge of the convex hull between the owned and
        ///     other faces. In this way, it guarantees a much more optimal solution than the flat
        ///     with face algorithm, but is, therefore, slower.
        /// </summary>
        /// <timeDomain>
        ///     Since the computation cost for each Bounding Box is linear O(n),
        ///     and the approximate worse case number of normals considered is n*PI/maxDeltaAngle,
        ///     Lower Bound O(n^2). Upper Bound O(n^(2)*PI/maxDeltaAngle). [ex.  upper bound is O(36*n^2) when MaxDeltaAngle = 5
        ///     degrees.]
        /// </timeDomain>
        /// <accuracy>
        ///     Garantees the optimial orientation is within maxDeltaAngle error.
        /// </accuracy>
        private static BoundingBox OrientedBoundingBox(TVGLConvexHull convexHull)
        {
            var minBox = new BoundingBox(
                new Vector3(double.PositiveInfinity, double.PositiveInfinity, double.PositiveInfinity),
                new[] { Vector3.UnitX, Vector3.UnitY, Vector3.UnitZ },
                new Vector3(double.NegativeInfinity, double.NegativeInfinity, double.NegativeInfinity));

            foreach (var rotateEdge in convexHull.Edges)
            {
                #region Initialize variables

                //Initialize variables
                //rotatorVector is basically the edge in question - the vector that is being rotated about
                var rotatorVector = rotateEdge.Vector.Normalize();
                // startDir is the starting Direction - based on the OtherFace
                var startDir = rotateEdge.OtherFace.Normal;
                // endDir is the OwnedFace final Direction - we go from Other to Owned since in order to be about
                // the positive Direction of the rotatorVector
                var endDir = rotateEdge.OwnedFace.Normal;
                // posYDir is the vector for the positive y-Direction. Well, this is a simplification of the
                //gauss sphere to a 2D circle. The Direction (such as startDir) represents the x-axis and this
                //, which is the orthogonal is the y Direction
                var origPosYDir = rotatorVector.Cross(startDir).Normalize();
                var totalAngle  = Math.PI - rotateEdge.InternalAngle;
                var thisBoxData = new BoundingBoxData(startDir, origPosYDir, rotateEdge, rotatorVector, convexHull);

                #endregion

                FindOBBAlongDirection(thisBoxData);
                if (thisBoxData.Box.Volume < minBox.Volume)
                {
                    minBox = thisBoxData.Box;
                }
                var             angle = 0.0;
                var             deltaAngleToBackChange = 0.0;
                var             deltaAngleOrthSet      = 0.0;
                BoundingBoxData backChangeBox          = null;
                BoundingBoxData sideChangeBox          = null;
                do
                {
                    if (deltaAngleToBackChange <= 0)
                    {
                        backChangeBox          = thisBoxData.Copy();
                        deltaAngleToBackChange = UpdateBackAngle(backChangeBox);
                    }
                    if (deltaAngleOrthSet <= 0)
                    {
                        sideChangeBox     = thisBoxData.Copy();
                        deltaAngleOrthSet = UpdateOrthAngle(sideChangeBox);
                    }
                    BoundingBoxData nextBoxData;
                    if (deltaAngleOrthSet < deltaAngleToBackChange)
                    {
                        deltaAngleToBackChange -= deltaAngleOrthSet;
                        angle            += deltaAngleOrthSet;
                        deltaAngleOrthSet = 0;
                        nextBoxData       = sideChangeBox;
                    }
                    else if (deltaAngleToBackChange < deltaAngleOrthSet)
                    {
                        deltaAngleOrthSet     -= deltaAngleToBackChange;
                        angle                 += deltaAngleToBackChange;
                        deltaAngleToBackChange = 0;
                        nextBoxData            = backChangeBox;
                    }
                    else // if they are equal to each other
                    {
                        angle            += deltaAngleToBackChange;
                        deltaAngleOrthSet = deltaAngleToBackChange = 0;
                        nextBoxData       = backChangeBox;
                    }
                    if (angle > totalAngle)
                    {
                        // nextBoxData = new BoundingBoxData(endDir, rotatorVector.Cross(endDir).Normalize(), rotateEdge, rotatorVector, convexHull);
                        nextBoxData.Angle     = totalAngle;
                        nextBoxData.Direction = endDir;
                    }
                    else
                    {
                        nextBoxData.Angle     = angle;
                        nextBoxData.Direction = UpdateDirection(startDir, rotatorVector, origPosYDir, angle);
                    }
                    nextBoxData.PosYDir = nextBoxData.RotatorVector.Cross(nextBoxData.Direction).Normalize();

                    /****************/
                    FindOBBAlongDirection(nextBoxData);
                    /****************/
                    if (DifferentMembershipInExtrema(thisBoxData, nextBoxData))
                    {
                        var lowerBox = thisBoxData;
                        var upperBox = nextBoxData;
                        var midBox   = thisBoxData.Copy();
                        while (!lowerBox.Angle.IsPracticallySame(upperBox.Angle, Constants.OBBTolerance))
                        {
                            midBox.Direction = (lowerBox.Direction + upperBox.Direction).Divide(2).Normalize();
                            midBox.Angle     = (lowerBox.Angle + upperBox.Angle) / 2.0;
                            FindOBBAlongDirection(midBox);
                            if (midBox.Box.Volume > lowerBox.Box.Volume && midBox.Box.Volume > upperBox.Box.Volume)
                            {
                                break;
                            }
                            if (!DifferentMembershipInExtrema(lowerBox, midBox))
                            {
                                lowerBox = midBox;
                            }
                            else if (!DifferentMembershipInExtrema(upperBox, midBox))
                            {
                                upperBox = midBox;
                            }
                            else
                            {
                                throw new Exception("new midbox is different from BOTH neighbors!");
                            }
                        }
                        if (thisBoxData.Box.Volume < minBox.Volume)
                        {
                            minBox = midBox.Box;
                        }
                    }
                    thisBoxData = nextBoxData;
                    if (thisBoxData.Box.Volume < minBox.Volume)
                    {
                        minBox = thisBoxData.Box;
                    }
                } while (angle < totalAngle);
            }
            return(minBox);
        }