private static bool BisectorSegment(Plan.Vertex vertex, Vector2 segmentA, Vector2 segmentB, out float offset)
        {
            IntersectionRaySegment2 intersection;

            if (Intersect.RaySegment(vertex.position, vertex.bisector, segmentA, segmentB, out intersection))
            {
                if (intersection.type == IntersectionType.Point)
                {
                    Vector2 segmentDirection  = (segmentB - segmentA).normalized;
                    float   toIntersection    = Vector2.Distance(vertex.position, intersection.pointA);
                    float   intersectionAngle = Vector2.Angle(vertex.bisector, segmentDirection);
                    float   intersectionSin   = Mathf.Sin(intersectionAngle * Mathf.Deg2Rad);
                    float   bisectorSin       = Geometry.GetAngleBisectorSin(vertex.angle);
                    offset = toIntersection / (1 / intersectionSin + 1 / bisectorSin);
                    return(true);
                }

                // BEGIN: Modified by Microsoft Corporation for generic logging purposes.
                API.MREAPI.Logger.LogError(string.Format("Invalid bisector intersection\ntype: {0}\npointA: {1} pointB: {2}\nray: {3} segmentA:{4} segmentB:{5}",
                                                         intersection.type, intersection.pointA, intersection.pointB, vertex.bisector, segmentA, segmentB));
                // END: Modified by Microsoft Corporation for generic logging purposes.

                offset = 0;
                return(false);
            }
            offset = 0;
            return(false);
        }
        private void ProcessIntersectionEvent(Plan plan, IntersectionEvent intersectionEvent)
        {
            foreach (var chain in intersectionEvent.chains)
            {
                SimplifyChain(plan, chain);
            }
            intersectionEvent.chains.RemoveAll(c => c.Count == 0);

            if (intersectionEvent.chains.Count >= 2)
            {
                for (var i = 0; i < intersectionEvent.chains.Count; i++)
                {
                    var chain         = intersectionEvent.chains[i];
                    var previousChain = intersectionEvent.chains.GetLooped(i - 1);
                    var vertex        = chain[0];
                    plan.Remove(vertex);
                    skeleton.AddVertex(vertex);

                    var newVertex = new Plan.Vertex(intersectionEvent.position)
                    {
                        previousPolygonIndex = vertex.previousPolygonIndex,
                        nextPolygonIndex     = previousChain[0].nextPolygonIndex
                    };
                    plan.Insert(newVertex, vertex.previous, previousChain[0].next);
                    CalculateBisector(newVertex);
                }
            }
        }
        private static bool BisectorBisector(Plan.Vertex vertexA, Plan.Vertex vertexB, out float offset)
        {
            IntersectionRayRay2 intersection;

            if (Intersect.RayRay(vertexA.position, vertexA.bisector, vertexB.position, vertexB.bisector, out intersection))
            {
                if (intersection.type == IntersectionType.Point)
                {
                    float offsetA = GetBisectorBisectorOffset(vertexA, intersection.pointA);
                    float offsetB = GetBisectorBisectorOffset(vertexB, intersection.pointA);
                    offset = Mathf.Min(offsetA, offsetB);
                    return(true);
                }
                if (intersection.type == IntersectionType.Segment)
                {
                    float toIntersection = Vector2.Distance(vertexA.position, vertexB.position);
                    float offsetA        = GetBisectorBisectorOffset(vertexA, toIntersection) / 2;
                    float offsetB        = GetBisectorBisectorOffset(vertexB, toIntersection) / 2;
                    offset = Mathf.Min(offsetA, offsetB);
                    return(true);
                }

                // BEGIN: Modified by Microsoft Corporation for generic logging purposes.
                API.MREAPI.Logger.LogError(string.Format("Invalid bisector intersection\ntype: {0}\npointA: {1} pointB: {2}\nbisectorA: {3} bisectorB:{4}",
                                                         intersection.type, intersection.pointA, intersection.pointB, vertexA.bisector, vertexB.bisector));
                // END: Modified by Microsoft Corporation for generic logging purposes.

                offset = 0;
                return(false);
            }
            offset = 0;
            return(false);
        }
        private void SimplifyChain(Plan plan, List <Plan.Vertex> chain)
        {
            if (chain.Count == 1)
            {
                return;
            }

            var first    = chain[0];
            var previous = first.previous;
            var last     = chain[chain.Count - 1];
            var next     = last.next;

            foreach (var vertex in chain)
            {
                plan.Remove(vertex);
                skeleton.AddVertex(vertex);
            }
            chain.Clear();
            if (next != first)
            {
                var newVertex = new Plan.Vertex(first.position)
                {
                    previousPolygonIndex = first.previousPolygonIndex,
                    nextPolygonIndex     = last.nextPolygonIndex,
                };
                plan.Insert(newVertex, previous, next);
                chain.Add(newVertex);
                CalculateBisector(newVertex);
            }
        }
        private static void CalculateBisector(Plan.Vertex vertex)
        {
            Plan.Vertex previous = vertex.previous;
            Plan.Vertex next     = vertex.next;
            float       angle;
            Vector2     direction = Geometry.GetAngleBisector(previous.position, vertex.position, next.position, out angle);

            vertex.angle    = angle;
            vertex.bisector = direction;
        }
예제 #6
0
 public void AddVertex(Plan.Vertex vertex)
 {
     if (vertex.previousPolygonIndex == vertex.nextPolygonIndex)
     {
         AddVertex(vertex.previousPolygonIndex, vertex.position);
     }
     else
     {
         AddVertex(vertex.previousPolygonIndex, vertex.position);
         AddVertex(vertex.nextPolygonIndex, vertex.position);
     }
 }
        private Plan.Vertex CreateSplitVertex(Plan plan, Vector2 position, Plan.Vertex segmentA, Plan.Vertex segmentB)
        {
            var newVertex = new Plan.Vertex(position)
            {
                previousPolygonIndex = segmentA.nextPolygonIndex,
                nextPolygonIndex     = segmentB.previousPolygonIndex
            };

            plan.Insert(newVertex, segmentA, segmentB);
            CalculateBisector(newVertex);
            return(newVertex);
        }
        private IntersectionEvent FindIntersectionEvent(Plan.Vertex searchVertex)
        {
            var vertex = searchVertex;

            do
            {
                if (!vertex.inEvent && vertex != searchVertex && IncidentalVertices(searchVertex, vertex))
                {
                    var intersectionEvent = new IntersectionEvent(searchVertex.position);
                    ExpandEvent(intersectionEvent, searchVertex);
                    return(intersectionEvent);
                }
                vertex = vertex.next;
            } while (vertex != searchVertex);
            return(null);
        }
        private void ExpandEvent(IntersectionEvent intersectionEvent, Plan.Vertex startVertex)
        {
            var vertex = startVertex;

            do
            {
                if (!vertex.inEvent && IncidentalVertices(intersectionEvent.position, vertex.position))
                {
                    var chain = FindCollapsedChain(vertex);
                    intersectionEvent.chains.Add(chain);
                    vertex = chain[chain.Count - 1].next;
                }
                else
                {
                    vertex = vertex.next;
                }
            } while (vertex != startVertex);
        }
        private void CreateSplitVertices(Plan plan, Plan.Vertex searchVertex)
        {
            var vertex = searchVertex;

            do
            {
                if (vertex != searchVertex &&
                    vertex.next != searchVertex &&
                    PointSegment(searchVertex.position, vertex.position, vertex.next.position))
                {
                    var newVertex = CreateSplitVertex(plan, searchVertex.position, vertex, vertex.next);
                    vertex = newVertex.next;
                }
                else
                {
                    vertex = vertex.next;
                }
            } while (vertex != searchVertex);
        }
        private List <Plan.Vertex> FindCollapsedChain(Plan.Vertex startVertex)
        {
            startVertex.inEvent = true;
            var chain = new List <Plan.Vertex> {
                startVertex
            };
            var vertex = startVertex;

            do
            {
                if (!vertex.next.inEvent && IncidentalVertices(vertex, vertex.next))
                {
                    vertex.next.inEvent = true;
                    chain.Add(vertex.next);
                    vertex = vertex.next;
                }
                else
                {
                    break;
                }
            } while (vertex != startVertex);
            return(chain);
        }
 private static bool IncidentalVertices(Plan.Vertex a, Plan.Vertex b)
 {
     return(IncidentalVertices(a.position, b.position));
 }
 private static float GetBisectorBisectorOffset(Plan.Vertex vertex, float toIntersection)
 {
     return(toIntersection * Geometry.GetAngleBisectorSin(vertex.angle));
 }
        private static float GetBisectorBisectorOffset(Plan.Vertex vertex, Vector2 intersection)
        {
            float toIntersection = Vector2.Distance(vertex.position, intersection);

            return(GetBisectorBisectorOffset(vertex, toIntersection));
        }