예제 #1
0
        public MergedEvent CreateMergeEvent(Node[] nodes, Vector2 atPoint, float eventPercent, Vector2 calculationPoint)
        {
            OffsetShapeLog.AddLine("Merge event detected");
            OffsetShapeLog.Add(nodes);
            MergedEvent mergeEvent = new MergedEvent();

            mergeEvent.mergeNodes.AddRange(nodes);
            mergeEvent.point = atPoint;
            float height = 0;

            //            float eventPercent = 1;
            foreach (Node node in nodes)
            {
                height += node.height;

                //                float pointDistance = Vector2.Distance(atPoint, node.previousPosition);
                //                float pointPercent = pointDistance / node.distance;
                //                eventPercent = Mathf.Min(eventPercent, pointPercent);
            }
            mergeEvent.height  = height / nodes.Length;
            mergeEvent.percent = eventPercent;
            //            AddEvent(mergeEvent);
            return(mergeEvent);
        }
예제 #2
0
        /// <summary>
        /// Merge the two specified events
        /// </summary>
        /// <param name="eventA"></param>
        /// <param name="eventB"></param>
        /// <returns></returns>
        private MergedEvent MergeEvent(IEvent eventA, IEvent eventB)
        {
            OffsetShapeLog.AddLine(_events.Count);
            eventA.Log();
            eventB.Log();
            if (eventA.GetType() == typeof(MergedEvent))
            {
                if (eventA == eventB)
                {
                    return((MergedEvent)eventA);
                }
                MergedEvent mergeEvent = (MergedEvent)eventA;
                mergeEvent.Merge(eventB);
                _events.Remove(eventB);
                if (!_events.Contains(eventA))
                {
                    _events.Add(eventA);
                }
                OffsetShapeLog.AddLine("Event B merged into A");
                return(mergeEvent);
            }
            if (eventB.GetType() == typeof(MergedEvent))
            {
                if (eventA == eventB)
                {
                    return((MergedEvent)eventB);
                }
                MergedEvent mergeEvent = (MergedEvent)eventB;
                mergeEvent.Merge(eventA);
                _events.Remove(eventA);
                if (!_events.Contains(eventB))
                {
                    _events.Add(eventB);
                }
                OffsetShapeLog.AddLine("Event A merged into B");
                return(mergeEvent);
            }

            OffsetShapeLog.AddLine(_events.Count);
            //create the merge event and merge into it the two events
            MergedEvent mergedEvent = new MergedEvent();

            OffsetShapeLog.Add("merge percent ", mergedEvent.percent);
            mergedEvent.Merge(eventA);
            OffsetShapeLog.Add("merge percent ", mergedEvent.percent);
            mergedEvent.Merge(eventB);
            OffsetShapeLog.Add("merge percent ", mergedEvent.percent);
            eventA.Log();
            eventB.Log();
            mergedEvent.Log();
            _events.Remove(eventA);
            _events.Remove(eventB);
            if (_allEvents.Contains(eventA))
            {
                _allPoints.RemoveAt(_allEvents.IndexOf(eventA));
            }
            _allEvents.Remove(eventA);
            if (_allEvents.Contains(eventB))
            {
                _allPoints.RemoveAt(_allEvents.IndexOf(eventB));
            }
            _allEvents.Remove(eventB);

            OffsetShapeLog.AddLine("Current Events");
            foreach (IEvent evt in _events)
            {
                evt.Log();
            }

            OffsetShapeLog.AddLine(_events.Count);
            if (!_events.Contains(mergedEvent))
            {
                _events.Add(mergedEvent);
            }
            OffsetShapeLog.AddLine(_events.Count);
            return(mergedEvent);
        }
예제 #3
0
        public void CollapseNodes(List <Node> nodes, Vector2 toPoint, float height)
        {
            OffsetShapeLog.AddLine("Collapse Nodes:");
            foreach (Node node in nodes)
            {
                OffsetShapeLog.Add(node.id + " ");
            }
            OffsetShapeLog.AddLine("to point: ", toPoint);
            Node newStaticNode = new Node(toPoint, height); //new static node to mark point of collapse

            _shape.AddStaticNode(newStaticNode);            //add static node to node array
            OffsetShapeLog.AddLine("new static node added ", newStaticNode.id);

            int         liveEdgeCount = _shape.liveEdges.Count;
            List <Edge> liveEdges     = new List <Edge>();
            Node        newLiveNode   = new Node(toPoint, height);//new live node to continue shape forming

            int   nodeCount = nodes.Count;
            float minHeight = nodes[0].height;
            float maxHeight = nodes[0].height;

            for (int n = 1; n < nodeCount; n++)
            {
                minHeight = Mathf.Min(minHeight, nodes[n].height);
                maxHeight = Mathf.Min(maxHeight, nodes[n].height);
            }
            for (int n = 0; n < nodeCount; n++)
            {
                nodes[n].position = toPoint;
                nodes[n].height   = maxHeight;
            }

            for (int e = 0; e < liveEdgeCount; e++)
            {
                Edge edge = _shape.liveEdges[e];
                if (!nodes.Contains(edge.nodeA) || !nodes.Contains(edge.nodeB))
                {
                    continue;
                }
                edge.UpdateValues();
                if (edge.length < pointAccuracy)//when the edge reaches 0 length it has flipped and should be collapsed
                {
                    OffsetShapeLog.AddLine(edge.ToString(), "has collapsed", edge.length, pointAccuracy);
                    //                    _shape.mesh.CollapseEdge(edge, newLiveNode, newStaticNode);
                    OffsetShapeLog.AddLine("Remove edge ", edge.ToString());
                    _shape.liveEdges.Remove(edge);//remove collapsed edge - from length reaching zero
                    liveEdgeCount--;
                    e--;
                    if (!nodes.Contains(edge.nodeA))
                    {
                        nodes.Add(edge.nodeA);
                    }
                    if (!nodes.Contains(edge.nodeB))
                    {
                        nodes.Add(edge.nodeB);
                    }
                }
            }

            OffsetShapeLog.AddLine("find live node edges");
            for (int e = 0; e < liveEdgeCount; e++)
            {
                Edge edge = _shape.liveEdges[e];
                if (!edge.Contains(nodes))
                {
                    continue;
                }
                //                if(edge.length < pointAccuracy) continue;
                if (nodes.Contains(edge.nodeA) && nodes.Contains(edge.nodeB))
                {
                    OffsetShapeLog.AddLine("Remove collapsed edge ", edge.ToString());
                    _shape.liveEdges.Remove(edge); //remove collapsed edge - likely from parallel
                                                   //                    _shape.mesh.EdgeComplete(edge);
                    liveEdgeCount--;
                    e--;
                    continue;
                }
                if (nodes.Contains(edge.nodeA) || newLiveNode == edge.nodeA)
                {
                    OffsetShapeLog.AddLine("replace node a");
                    edge.ReplaceNode(edge.nodeA, newLiveNode); //replace old live node reference to new one
                                                               //                    _shape.mesh.ReplaceNode(edge.nodeA, newLiveNode);
                    liveEdges.Add(edge);
                    continue;
                }
                if (nodes.Contains(edge.nodeB) || newLiveNode == edge.nodeB)
                {
                    OffsetShapeLog.AddLine("replace node b");
                    edge.ReplaceNode(edge.nodeB, newLiveNode); //replace old live node reference to new one
                                                               //                    _shape.mesh.ReplaceNode(edge.nodeB, newLiveNode);
                    liveEdges.Add(edge);
                }
            }

            for (int n = 0; n < nodeCount; n++)
            {
                Node node = nodes[n];
                Utils.RetireFormingEdge(_shape, node, newStaticNode);
                _shape.liveNodes.Remove(node);
            }

            Utils.CheckParrallel(_shape);

            OffsetShapeLog.AddLine("Live edges: ", liveEdges.Count);
            if (liveEdges.Count > 0)             //deal with left live edges after the collapse
            {
                _shape.AddLiveNode(newLiveNode); //new live node from collapse
                Edge edgeA = null, edgeB = null;
                liveEdgeCount = _shape.liveEdges.Count;
                for (int e = 0; e < liveEdgeCount; e++)//find the two edges left from the collapse
                {
                    Edge edge = _shape.liveEdges[e];
                    if (!_shape.liveEdges.Contains(edge))
                    {
                        continue;
                    }
                    if (edge.nodeA == newLiveNode)
                    {
                        edgeA = edge;
                    }
                    if (edge.nodeB == newLiveNode)
                    {
                        edgeB = edge;
                    }
                }

                if (edgeA != null && edgeB != null)//if there is a live edge
                {
                    Node x = edgeA.GetOtherNode(newLiveNode);
                    Node y = edgeB.GetOtherNode(newLiveNode);
                    Utils.CalculateNodeDirAng(newLiveNode, x, y);             //recalculate node angle
                    Utils.NewFormingEdge(_shape, newStaticNode, newLiveNode); //add new forming edge
                }
                else
                {
                    OffsetShapeLog.AddLine("New live node has not been calculted ", newLiveNode.id);
                }
            }

            //            foreach (Node node in nodes)
            //                _data.mesh.ReplaceNode(node, newStaticNode);
        }
예제 #4
0
        private void CollapseNodes(List <Node> nodes, Vector2 toPoint, float height, BaseEvent evt)
        {
            if (nodes.Count < 2)
            {
                return;
            }
            OffsetShapeLog.AddLine("Collapse Nodes:");
            foreach (Node node in nodes)
            {
                OffsetShapeLog.Add(node.id + " ");
            }
            OffsetShapeLog.AddLine("to point: ", toPoint);
            Node newStaticNode = (evt.newStaticNode == null) ? new Node(toPoint, height) : evt.newStaticNode;//new static node to mark point of collapse

            evt.newStaticNode = newStaticNode;
            _core.shape.AddStaticNode(newStaticNode);//add static node to node array

            int         liveEdgeCount = _core.shape.liveEdges.Count;
            List <Edge> liveEdges     = new List <Edge>();
            //            Node newLiveNode = new Node(toPoint, nodes[0].height);//new live node to continue shape forming

            int nodeCount = nodes.Count;

            for (int n = 0; n < nodeCount; n++)
            {
                nodes[n].position = toPoint;
            }

            for (int e = 0; e < liveEdgeCount; e++)
            {
                Edge edge = _core.shape.liveEdges[e];
                if (!nodes.Contains(edge.nodeA) || !nodes.Contains(edge.nodeB))
                {
                    continue;
                }
                edge.UpdateValues();
                if (edge.length < pointAccuracy)//when the edge reaches 0 length it has flipped and should be collapsed
                {
                    OffsetShapeLog.AddLine(edge.ToString(), "has collapsed", edge.length, pointAccuracy);
                    OffsetShapeLog.AddLine("Remove edge ", edge.ToString());
                    _core.shape.liveEdges.Remove(edge);//remove collapsed edge - from length reaching zero
                    _collapsedEdges.Add(edge, newStaticNode);
                    liveEdgeCount--;
                    e--;
                    if (!nodes.Contains(edge.nodeA))
                    {
                        nodes.Add(edge.nodeA);
                    }
                    if (!nodes.Contains(edge.nodeB))
                    {
                        nodes.Add(edge.nodeB);
                    }
                }
            }

            OffsetShapeLog.AddLine("find live node edges");
            Dictionary <Node, int> nodeOccurances = new Dictionary <Node, int>();//check parallel collapses

            for (int e = 0; e < liveEdgeCount; e++)
            {
                Edge edge = _core.shape.liveEdges[e];
                if (!edge.Contains(nodes))
                {
                    continue;                                                 //unaffected edge
                }
                if (nodes.Contains(edge.nodeA) && nodes.Contains(edge.nodeB)) //edge is completely affected by the merge and has collapsed
                {
                    OffsetShapeLog.AddLine("Remove collapsed edge ", edge.ToString());
                    _core.shape.liveEdges.Remove(edge);//remove collapsed edge
                    _collapsedEdges.Add(edge, newStaticNode);
                    liveEdgeCount--;
                    e--;
                    continue;
                }
                if (nodes.Contains(edge.nodeA))// || newLiveNode == edge.nodeA)
                {
                    //                    edge.ReplaceNode(edge.nodeA, newLiveNode);//replace old live node reference to new one //TODO
                    liveEdges.Add(edge);
                    OffsetShapeLog.AddLine("Live edges: ", edge);
                    if (nodeOccurances.ContainsKey(edge.nodeB))
                    {
                        nodeOccurances[edge.nodeB]++;
                    }
                    else
                    {
                        nodeOccurances.Add(edge.nodeB, 1);
                    }
                    continue;
                }
                if (nodes.Contains(edge.nodeB))// || newLiveNode == edge.nodeB)
                {
                    //                    edge.ReplaceNode(edge.nodeB, newLiveNode);//replace old live node reference to new one //TODO
                    liveEdges.Add(edge);
                    OffsetShapeLog.AddLine("Live edges: ", edge);
                    if (nodeOccurances.ContainsKey(edge.nodeA))
                    {
                        nodeOccurances[edge.nodeA]++;
                    }
                    else
                    {
                        nodeOccurances.Add(edge.nodeA, 1);
                    }
                }
            }

            int affectedLiveEdges = liveEdges.Count;

            foreach (KeyValuePair <Node, int> kv in nodeOccurances)
            {
                OffsetShapeLog.AddLine("node occured: ", kv.Key.id, kv.Value);
                if (kv.Value > 1)
                {
                    Node pinchedNode = kv.Key;
                    OffsetShapeLog.AddLine("Pinched node: ", pinchedNode.id);
                    pinchedNode.position = toPoint;
                    for (int a = 0; a < affectedLiveEdges; a++)
                    {
                        shape.formingEdges[kv.Key].ReplaceNode(kv.Key, newStaticNode);
                        if (liveEdges[a].Contains(kv.Key))//any live edges that contains the node should be culled - it has collapsed
                        {
                            Edge edge = liveEdges[a];
                            OffsetShapeLog.AddLine("Collapsed Edge: ", edge);
                            liveEdges.Remove(edge);
                            _core.shape.liveEdges.Remove(edge);//remove collapsed edge
                            affectedLiveEdges--;
                            a--;
                        }
                    }
                    Utils.RetireFormingEdge(shape, kv.Key, newStaticNode);
                    _core.shape.liveNodes.Remove(kv.Key);
                }
            }

            //            for (int n = 0; n < nodeCount; n++)
            //            {
            //                Node node = nodes[n];
            //                Utils.RetireFormingEdge(_core.shape, node, newStaticNode);
            //                _core.shape.liveNodes.Remove(node);
            ////                _substitutions.Add(node, newLiveNode); TODO EEK!
            //            }

            OffsetShapeLog.AddLine("Live edges: ", liveEdges.Count);
            if (affectedLiveEdges > 0)//deal with left live edges after the collapse - calculate the angle the new node needs to move into
            {
                float[] angles             = new float[affectedLiveEdges];
                int     smallestAngleIndex = 0;//keep this for when we need to loop the angle comparison
                float   smallestAngle      = Mathf.Infinity;
                for (int a = 0; a < affectedLiveEdges; a++)
                {
                    Node    from  = liveEdges[a].GetEdgeNode(nodes);
                    Node    to    = liveEdges[a].GetOtherNode(from);
                    Vector2 dir   = (to.position - from.position).normalized;
                    float   angle = Utils.SignAngle(dir);
                    angles[a] = angle;
                    OffsetShapeLog.AddLine(liveEdges[a], angle);
                    if (angle < smallestAngle)
                    {
                        smallestAngle      = angle;
                        smallestAngleIndex = a;
                    }
                }

                Edge startEdge = null;
                for (int a = 0; a < affectedLiveEdges; a++)
                {
                    if (nodes.Contains(liveEdges[a].nodeA))
                    {
                        startEdge = liveEdges[a];
                        break;
                    }
                }
                if (startEdge != null)
                {
                    Edge[] orderedEdges = new Edge[affectedLiveEdges];
                    orderedEdges[0] = startEdge;
                    Edge  currentEdge  = startEdge;
                    float currentAngle = angles[liveEdges.IndexOf(currentEdge)];
                    int   orderIndex   = 1;

                    OffsetShapeLog.AddLine("order edges by angle");
                    OffsetShapeLog.AddLine(0, startEdge);
                    while (orderIndex < affectedLiveEdges)
                    {
                        Edge  candidate      = null;
                        float candidateAngle = Mathf.Infinity;
                        for (int a = 0; a < affectedLiveEdges; a++)
                        {
                            Edge nextEdge = liveEdges[a];
                            if (currentEdge == nextEdge)
                            {
                                continue;
                            }
                            float nextAngle = angles[liveEdges.IndexOf(nextEdge)];
                            if (nextAngle > currentAngle)
                            {
                                if (nextAngle < candidateAngle)
                                {
                                    candidateAngle = nextAngle;
                                    candidate      = nextEdge;
                                }
                            }
                        }

                        if (candidate == null)
                        {
                            candidate = liveEdges[smallestAngleIndex];
                        }

                        if (candidate != null)
                        {
                            OffsetShapeLog.AddLine(orderIndex, candidate);
                            orderedEdges[orderIndex] = candidate;
                            orderIndex++;
                            currentEdge  = candidate;
                            currentAngle = angles[liveEdges.IndexOf(currentEdge)];
                        }
                    }

                    OffsetShapeLog.AddLine("affected Live Edge count" + affectedLiveEdges);
                    List <Node> newLiveNodes = new List <Node>();
                    if (affectedLiveEdges % 2 != 0)
                    {
                        //                        Debug.LogError("affected Live Edge count uneven: "+ affectedLiveEdges);
                        //                        Debug.LogError("");
                        return;
                    }
                    for (int o = 0; o < affectedLiveEdges; o += 2)
                    {
                        Edge splitEdgeA = orderedEdges[o];
                        Edge splitEdgeB = orderedEdges[o + 1];
                        OffsetShapeLog.AddLine("split Edge A", splitEdgeA);
                        OffsetShapeLog.AddLine("split Edge B", splitEdgeB);

                        Node newLiveNode = new Node(toPoint, nodes[0].height); //new live node to continue shape forming
                        _core.shape.AddLiveNode(newLiveNode);                  //new live node from collapse
                        newLiveNodes.Add(newLiveNode);

                        if (nodes.Contains(splitEdgeA.nodeA))
                        {
                            splitEdgeA.ReplaceNode(splitEdgeA.nodeA, newLiveNode);//replace old live node reference to new one
                        }
                        else
                        {
                            splitEdgeA.ReplaceNode(splitEdgeA.nodeB, newLiveNode);//replace old live node reference to new one
                        }
                        if (nodes.Contains(splitEdgeB.nodeA))
                        {
                            splitEdgeB.ReplaceNode(splitEdgeB.nodeA, newLiveNode);//replace old live node reference to new one
                        }
                        else
                        {
                            splitEdgeB.ReplaceNode(splitEdgeB.nodeB, newLiveNode);//replace old live node reference to new one
                        }
                        Node x = splitEdgeA.GetOtherNode(newLiveNode);
                        Node y = splitEdgeB.GetOtherNode(newLiveNode);
                        Utils.CalculateNodeDirAng(newLiveNode, x, y);                  //recalculate node angle
                        Utils.NewFormingEdge(_core.shape, newStaticNode, newLiveNode); //add new forming edge
                    }

                    int newLiveNodeCount = newLiveNodes.Count;
                    for (int l = 0; l < newLiveNodeCount; l++)
                    {
                        Node lNode = newLiveNodes[l];
                        if (!_core.currentSplits.ContainsKey(lNode.id))
                        {
                            _core.currentSplits.Add(lNode.id, new List <int>());
                        }

                        for (int lb = 0; lb < newLiveNodeCount; lb++)
                        {
                            if (l == lb)
                            {
                                continue;
                            }
                            Node lbNode = newLiveNodes[lb];
                            _core.currentSplits[lNode.id].Add(lbNode.id);
                        }
                    }
                }



                //                Edge edgeA = null, edgeB = null;
                //                liveEdgeCount = _core.shape.liveEdges.Count;
                //                for (int e = 0; e < liveEdgeCount; e++)//find the two edges left from the collapse
                //                {
                //                    Edge edge = _core.shape.liveEdges[e];
                //                    if (!_core.shape.liveEdges.Contains(edge)) continue;//not a live edge
                //                    if (edge.nodeA == newLiveNode) edgeA = edge;
                //                    if (edge.nodeB == newLiveNode) edgeB = edge;
                //                }
                //
                //                if (edgeA != null && edgeB != null)//if there is a live edge
                //                {
                //                    Node x = edgeA.GetOtherNode(newLiveNode);
                //                    Node y = edgeB.GetOtherNode(newLiveNode);
                //                    Utils.CalculateNodeDirAng(newLiveNode, x, y);//recalculate node angle
                //                    Utils.NewFormingEdge(_core.shape, newStaticNode, newLiveNode);//add new forming edge
                //                }
                //                else
                //                {
                //                    OffsetShapeLog.AddLine("New live node has not been calculted ", newLiveNode.id);
                //                }
            }


            for (int n = 0; n < nodeCount; n++)
            {
                Node node = nodes[n];
                Utils.RetireFormingEdge(_core.shape, node, newStaticNode);
                _core.shape.liveNodes.Remove(node);
                //                _substitutions.Add(node, newLiveNode); TODO EEK!
            }

            Utils.CheckParrallel(_core.shape);
        }