public SplitEvent CreateSplitEvent(Shape data, Node node, Edge edge, Vector2 point, float eventPercent, Vector2 calculationPoint) { OffsetShapeLog.AddLine("Split event detected"); SplitEvent splitEvent = new SplitEvent(); splitEvent.node = node; splitEvent.edge = edge; OffsetShapeLog.AddLine(eventPercent.ToString("P")); OffsetShapeLog.AddLine("node " + node.id); OffsetShapeLog.AddLine("splits edge " + edge); Vector2 a = node.previousPosition; Vector2 b = node.position; // Vector2 x = point;//intersectionInfo.Point0; // float movementMag = nodeMovement.magnitude; // float intersectionMag = (x - a).magnitude; // float eventPercent = intersectionMag / movementMag; Vector2 actualIntersectionPoint = Vector2.Lerp(a, b, eventPercent);//translate the point to the real movement point splitEvent.point = actualIntersectionPoint; splitEvent.percent = eventPercent; splitEvent.height = node.height; splitEvent.nodeMovementStart = node.previousPosition; //movementSegment.P0; splitEvent.nodeMovementEnd = node.position; //calculationPoint;//movementSegment.P1; Edge[] edges = Utils.GetABEdge(data, node); if (edges[0] == null || edges[1] == null) { return(null); } splitEvent.nodeEdgeA = edges[0]; splitEvent.nodeEdgeB = edges[1]; if (splitEvent.ContainsNode(splitEvent.nodeEdgeA.GetOtherNode(node))) { OffsetShapeLog.AddLine("Split event collapses shape"); } if (splitEvent.ContainsNode(splitEvent.nodeEdgeB.GetOtherNode(node))) { OffsetShapeLog.AddLine("Split event collapses shape"); } // AddEvent(splitEvent); return(splitEvent); }
public void SplitEvent(SplitEvent sEvent) { if (_substitutions.ContainsKey(sEvent.node)) { OffsetShapeLog.AddLine(sEvent.node + " is replaced with " + _substitutions[sEvent.node]); sEvent.node = _substitutions[sEvent.node];//replce any modified node values } if (sEvent.edge.Contains(sEvent.node))//edge splitting itself { return; } if (_collapsedEdges.ContainsKey(sEvent.edge)) { CollapseNodes(new List <Node> { sEvent.node, _collapsedEdges[sEvent.edge] }, sEvent.point, sEvent.height, sEvent); OffsetShapeLog.AddLine("Split event falls on edge collapse."); return;//if the edge we were splitting already collaped - merge it } if (_splitEdges.ContainsKey(sEvent.edge)) { SplitEvent previousSplit = _splitEdges[sEvent.edge]; float sqrMagA = Vector2.SqrMagnitude(sEvent.edge.nodeA.position - sEvent.point); float sqrMagB = Vector2.SqrMagnitude(previousSplit.edge.nodeA.position - previousSplit.point); if (sqrMagA < sqrMagB) { OffsetShapeLog.AddLine(sEvent.edge.ToString() + " is replaced with " + previousSplit.newLiveEdgeA.ToString()); sEvent.edge = previousSplit.newLiveEdgeA; } else { OffsetShapeLog.AddLine(sEvent.edge.ToString() + " is replaced with " + previousSplit.newLiveEdgeB.ToString()); sEvent.edge = previousSplit.newLiveEdgeB; } } SplitEdge(sEvent); }
// public void CollapseEdge(Edge edge, Vector2 toPoint, float height) // { // List<Node> nodes = new List<Node>(); // nodes.Add(edge.nodeA); // nodes.Add(edge.nodeB); // CollapseNodes(nodes, toPoint, height); // } public void MergeEvent(MergedEvent mEvent) { OffsetShapeLog.AddLine("Complex merge event gynastics ahead"); CollapseNodes(mEvent.mergeNodes, mEvent.point, mEvent.height, mEvent); int splitCount = mEvent.splitEvents.Count; OffsetShapeLog.AddLine("Do the splits - in percent order"); float currentPercent = -1; for (int s = 0; s < splitCount; s++) { float minimumPercent = 1; SplitEvent candidate = null; for (int so = 0; so < splitCount; so++) { SplitEvent sEvent = mEvent.splitEvents[so]; // OffsetShapeLog.AddLine(sEvent.ToString()); // OffsetShapeLog.AddLine(sEvent.percent, currentPercent); if (sEvent.percent > currentPercent) { // OffsetShapeLog.AddLine(sEvent.percent, minimumPercent); if (sEvent.percent < minimumPercent) { minimumPercent = sEvent.percent; candidate = sEvent; } } } if (candidate != null) { SplitEvent(candidate); currentPercent = candidate.percent; } // mEvent.splitEvents[s].point = mEvent.point; } }
private void OnSplit(SplitEvent sEvent) { SplitEdge(sEvent); }
public void SplitEdge(SplitEvent e) { e.node.position = e.point; e.node.earlyTemination = true; return; // OffsetShapeLog.AddLine("Split event"); // OffsetShapeLog.AddLine("by node ", e.node.id); // OffsetShapeLog.AddLine(e.edge.ToString()); // //nodes // Node nodeStatic = new Node(e.point, e.height); // Node newLiveNodeA = new Node(e.point, e.height); // Node newLiveNodeB = new Node(e.point, e.height); // // e.newLiveNodeA = newLiveNodeA; // e.newLiveNodeB = newLiveNodeB; // e.newStaticNode = nodeStatic; // // // Node nodeOldA = e.edge.nodeA; // Node nodeOldB = e.edge.nodeB; // // Edge byEdgeA = e.nodeEdgeA; // Edge byEdgeB = e.nodeEdgeB; // if (byEdgeA == null || byEdgeB == null) // { // //TODO work out what to really do here. // return; // } // Node byNodeA = byEdgeA.GetOtherNode(e.node); // Node byNodeB = byEdgeB.GetOtherNode(e.node); // // OffsetShapeLog.AddLine("by node a", byNodeA.id); // OffsetShapeLog.AddLine("by node b", byNodeB.id); // // if (byNodeA == null || byNodeB == null) // return; // // //calculate new node directions // Utils.CalculateNodeDirAng(newLiveNodeA, byNodeA, nodeOldA); // Utils.CalculateNodeDirAng(newLiveNodeB, nodeOldB, byNodeB); // // _core.shape.AddLiveNode(newLiveNodeA); // _core.shape.AddLiveNode(newLiveNodeB); // _core.shape.AddStaticNode(nodeStatic); // _core.shape.liveNodes.Remove(e.node); // // //discard the old edge // OffsetShapeLog.AddLine("Discard old edge ", e.edge.ToString()); // _core.shape.liveEdges.Remove(e.edge);// // byEdgeA.ReplaceNode(e.node, newLiveNodeA); // byEdgeB.ReplaceNode(e.node, newLiveNodeB); // //create the two new edges from the split // Edge newEdgeA = new Edge(nodeOldA, newLiveNodeA); // _core.shape.liveEdges.Add(newEdgeA); // e.newLiveEdgeA = newEdgeA; // Edge newEdgeB = new Edge(newLiveNodeB, nodeOldB); // _core.shape.liveEdges.Add(newEdgeB); // e.newLiveEdgeB = newEdgeB; //forming edges // Utils.RetireFormingEdge(_core.shape, e.node, nodeStatic); // Edge formingEdgeA = Utils.NewFormingEdge(_core.shape, nodeStatic, newLiveNodeA); // Edge formingEdgeB = Utils.NewFormingEdge(_core.shape, nodeStatic, newLiveNodeB); // int aIndex = data.liveNodes.IndexOf(nodeLiveA); // int bIndex = data.liveNodes.IndexOf(nodeLiveB); // if (!_core.currentSplits.ContainsKey(newLiveNodeA.id)) // _core.currentSplits.Add(newLiveNodeA.id, new List<int>()); // _core.currentSplits[newLiveNodeA.id].Add(newLiveNodeB.id); // if (!_core.currentSplits.ContainsKey(newLiveNodeB.id)) // _core.currentSplits.Add(newLiveNodeB.id, new List<int>()); // _core.currentSplits[newLiveNodeB.id].Add(newLiveNodeA.id); // _shape.mesh.SplitEdge(e); // OffsetShapeLog.AddLine("new live nodes"); // OffsetShapeLog.AddLine(newLiveNodeA.id); // OffsetShapeLog.AddLine(newLiveNodeB.id); // OffsetShapeLog.AddLine("new edges - old edge - forming edge a"); // OffsetShapeLog.AddLine(newEdgeA.ToString()); // OffsetShapeLog.AddLine(byEdgeA.ToString()); // // OffsetShapeLog.AddLine(formingEdgeA.ToString()); // // OffsetShapeLog.AddLine("new edges - old edge - forming edge b"); // OffsetShapeLog.AddLine(byEdgeB.ToString()); // OffsetShapeLog.AddLine(newEdgeB.ToString()); // // OffsetShapeLog.AddLine(formingEdgeB.ToString()); // // Utils.CheckParrallel(_core.shape); }
private void Merge(SplitEvent e) { // bool proximity = Vector2.Distance(e.point, point) < EventLog._pointAccuracy; OffsetShapeLog.AddLine("merging split event", e); // if (proximity) // { // splitEvents.Add(e); // int splitCount = splitEvents.Count; // for(int s = 0; s < splitCount; s++) // { // if(Vector2.Distance(splitEvents[s].point, point) < EventLog._pointAccuracy) // { // if (!mergeNodes.Contains(splitEvents[s].node)) // mergeNodes.Add(splitEvents[s].node); //// if (!mergeNodes.Contains(splitEvents[s].edge.nodeA)) //// mergeNodes.Add(splitEvents[s].edge.nodeA); //// if (!mergeNodes.Contains(splitEvents[s].edge.nodeB)) //// mergeNodes.Add(splitEvents[s].edge.nodeB); // } // } // point = e.point; // percent = Mathf.Min(percent, e.percent); // } // else // { int splitCount = splitEvents.Count; bool addSplit = true; for (int s = 0; s < splitCount; s++) { SplitEvent os = splitEvents[s]; OffsetShapeLog.AddLine("checking against split event node", os.node); if (os.node == e.node) { addSplit = false; OffsetShapeLog.AddLine("new merged split conflicts with internal splits - disolving into collapsing node"); splitEvents.RemoveAt(s); if (!mergeNodes.Contains(e.node)) { mergeNodes.Add(e.node); } if (!mergeNodes.Contains(os.node)) { mergeNodes.Add(os.node); } if (e.edge.nodeA == os.edge.nodeA || e.edge.nodeA == os.edge.nodeB && !mergeNodes.Contains(e.edge.nodeA)) { mergeNodes.Add(e.edge.nodeA); } if (e.edge.nodeB == os.edge.nodeA || e.edge.nodeB == os.edge.nodeB && !mergeNodes.Contains(e.edge.nodeB)) { mergeNodes.Add(e.edge.nodeB); } point = e.point; percent = Mathf.Min(percent, e.percent); s--; splitCount--; } } if (!addSplit) { return; } point = e.point; splitEvents.Add(e); percent = Mathf.Min(percent, e.percent); // } }
public void SplitEdge(SplitEvent e) { OffsetShapeLog.AddLine("Split event"); OffsetShapeLog.AddLine("by node ", e.node.id); OffsetShapeLog.AddLine(e.edge.ToString()); //nodes Node nodeStatic = new Node(e.point, e.height); Node newLiveNodeA = new Node(e.point, e.height); Node newLiveNodeB = new Node(e.point, e.height); e.newLiveNodeA = newLiveNodeA; e.newLiveNodeB = newLiveNodeB; e.newStaticNode = nodeStatic; Node nodeOldA = e.edge.nodeA; Node nodeOldB = e.edge.nodeB; Edge byEdgeA = e.nodeEdgeA; Edge byEdgeB = e.nodeEdgeB; if (byEdgeA == null || byEdgeB == null) { //TODO work out what to really do here. return; } Node byNodeA = byEdgeA.GetOtherNode(e.node); Node byNodeB = byEdgeB.GetOtherNode(e.node); OffsetShapeLog.AddLine("by node a", byNodeA.id); OffsetShapeLog.AddLine("by node b", byNodeB.id); if (byNodeA == null || byNodeB == null) { return; } //calculate new node directions Utils.CalculateNodeDirAng(newLiveNodeA, byNodeA, nodeOldA); Utils.CalculateNodeDirAng(newLiveNodeB, nodeOldB, byNodeB); _shape.AddLiveNode(newLiveNodeA); _shape.AddLiveNode(newLiveNodeB); _shape.AddStaticNode(nodeStatic); _shape.liveNodes.Remove(e.node); //discard the old edge OffsetShapeLog.AddLine("Discard old edge ", e.edge.ToString()); _shape.liveEdges.Remove(e.edge);// byEdgeA.ReplaceNode(e.node, newLiveNodeA); byEdgeB.ReplaceNode(e.node, newLiveNodeB); //create the two new edges from the split Edge newEdgeA = new Edge(nodeOldA, newLiveNodeA); _shape.liveEdges.Add(newEdgeA); e.newLiveEdgeA = newEdgeA; Edge newEdgeB = new Edge(newLiveNodeB, nodeOldB); _shape.liveEdges.Add(newEdgeB); e.newLiveEdgeB = newEdgeB; //forming edges Utils.RetireFormingEdge(_shape, e.node, nodeStatic); Edge formingEdgeA = Utils.NewFormingEdge(_shape, nodeStatic, newLiveNodeA); Edge formingEdgeB = Utils.NewFormingEdge(_shape, nodeStatic, newLiveNodeB); // int aIndex = data.liveNodes.IndexOf(nodeLiveA); // int bIndex = data.liveNodes.IndexOf(nodeLiveB); newLiveNodeA.MoveForward(0.1f, 1); newLiveNodeB.MoveForward(0.1f, 1); if (!currentSplits.ContainsKey(newLiveNodeA.id)) { currentSplits.Add(newLiveNodeA.id, new List <int>()); } currentSplits[newLiveNodeA.id].Add(newLiveNodeB.id); if (!currentSplits.ContainsKey(newLiveNodeB.id)) { currentSplits.Add(newLiveNodeB.id, new List <int>()); } currentSplits[newLiveNodeB.id].Add(newLiveNodeA.id); // _shape.mesh.SplitEdge(e); OffsetShapeLog.AddLine("new live nodes"); OffsetShapeLog.AddLine(newLiveNodeA.id); OffsetShapeLog.AddLine(newLiveNodeB.id); OffsetShapeLog.AddLine("new edges - old edge - forming edge a"); OffsetShapeLog.AddLine(newEdgeA.ToString()); OffsetShapeLog.AddLine(byEdgeA.ToString()); OffsetShapeLog.AddLine(formingEdgeA.ToString()); OffsetShapeLog.AddLine("new edges - old edge - forming edge b"); OffsetShapeLog.AddLine(byEdgeB.ToString()); OffsetShapeLog.AddLine(newEdgeB.ToString()); OffsetShapeLog.AddLine(formingEdgeB.ToString()); Utils.CheckParrallel(_shape); }
public void OffsetPoly(float direction) { if (!_init) { return; } float amount = _shape.shrinkLength * SHINK_MULTIPLIER * Mathf.Sign(direction); int liveEdgeCount = _shape.liveEdges.Count; int liveNodeCount = _shape.liveNodes.Count; if (liveNodeCount == 0 || liveEdgeCount == 0)//nothing more to calculate { OffsetShapeLog.AddLine("Skeleton Complete"); _complete = true; if (OnCompleteEvent != null) { OnCompleteEvent(); } return; } bool earlyTermination = false; float directionSign = Mathf.Sign(direction); float maxOffsetSign = Mathf.Sign(maxOffset); float useMaxOffset = (directionSign == maxOffsetSign) ? maxOffset : -maxOffset; for (int l = 0; l < liveNodeCount; l++) { Node node = _shape.liveNodes[l]; // if(l==0)Debug.Log(node.height+" "+amount+" "+useMaxOffset); if (useMaxOffset > 0) { if (node.height + amount >= useMaxOffset)//terminate nodes that have reached a defined maximum { amount = useMaxOffset - node.height; earlyTermination = true; } } else if (useMaxOffset < 0) { if (node.height + amount <= useMaxOffset)//terminate nodes that have reached a defined maximum { amount = useMaxOffset - node.height; earlyTermination = true; } } } float maxMovement = 0; liveNodeCount = _shape.liveNodes.Count; float[] angleNodeMovements = new float[liveNodeCount]; for (int l = 0; l < _shape.liveNodes.Count; l++) { // Debug.Log(l); Node node = _shape.liveNodes[l];//TODO out of range error angleNodeMovements[l] = amount / Mathf.Sin(node.angle * 0.5f * Mathf.Deg2Rad); if (Mathf.Abs(angleNodeMovements[l]) > Mathf.Abs(maxMovement) && Mathf.Abs(angleNodeMovements[l]) > 0) { maxMovement = angleNodeMovements[l]; if (node.angle > 350) { Edge[] edges = Utils.GetABEdge(shape, node); if (edges[0] == null || edges[1] == null) { continue; } float shortestLength = (edges[0].length + edges[1].length) * 0.5f; // Debug.Log(Mathf.Abs(shortestLength / amount)); maxMovement /= Mathf.Abs(shortestLength / amount); } // Debug.Log(node.id+" "+node.angle); } } float angleScale = amount / maxMovement; if (angleScale == Mathf.Infinity) { angleScale = 1; } OffsetShapeLog.AddLine(angleScale); for (int l = 0; l < _shape.liveNodes.Count; l++) { Node node = _shape.liveNodes[l]; if (node.direction.magnitude < Mathf.Epsilon)//directionless node { _shape.liveNodes.Remove(node); liveNodeCount--; l--; continue; } node.MoveForward(angleNodeMovements[l] * angleScale, amount * angleScale); } Vector2[] edgeMovements = new Vector2[liveEdgeCount]; if (calculateInteractions) { //Event log will collect all events and sort them for us for use once we're happy everything has been processed EventLog eventLog = new EventLog(); EventLog.pointAccuracy = pointAccuracy; EventLog.percentAccuracy = percentAccuracy; //flip events for (int e = 0; e < liveEdgeCount; e++)//TODO check laters { Edge edge = _shape.liveEdges[e]; edge.DebugDraw(Color.cyan); edge.UpdateValues();//update the edge values to reflect the new node positions Node nodeA = edge.nodeA; Node nodeB = edge.nodeB; edgeMovements[e] = (nodeA.movement + nodeB.movement) * 0.5f; Vector2 intersectionPoint; if (Utils.Intersects(edge.nodeA.previousPosition, edge.nodeA.position, edge.nodeB.previousPosition, edge.nodeB.position, out intersectionPoint)) { eventLog.AddEvent(eventLog.CreateFlipEvent(edge, intersectionPoint)); } } // //split events for (int n = 0; n < _shape.liveNodeCount; n++) { Node node = _shape.liveNodes[n]; int nodeID = node.id; //find connecting nodes of splitting node Node nodeA = null, nodeB = null; for (int e = 0; e < liveEdgeCount; e++) { Edge edge = _shape.liveEdges[e]; if (edge.Contains(node)) { if (edge.nodeA == node) { nodeB = edge.nodeB; } if (edge.nodeB == node) { nodeA = edge.nodeA; } } } for (int e = 0; e < liveEdgeCount; e++) { Edge edge = _shape.liveEdges[e]; if (edge.Contains(node)) { continue; //nodes can't split their own edges - carry on! } if (nodeA != null && edge.Contains(nodeA)) { continue; //nodes can't split adjacent edges - carry on! } if (nodeB != null && edge.Contains(nodeB)) { continue; //nodes can't split adjacent edges - carry on! } if (currentSplits.ContainsKey(nodeID)) //previous splits should never intersect - ingore { if (currentSplits[nodeID].Contains(edge.nodeA.id)) { continue; } if (currentSplits[nodeID].Contains(edge.nodeB.id)) { continue; } } // if(!isPartOfShape(node, edge)) continue; Vector2 edgeMovement = edgeMovements[e]; Vector2 nodeMovement = node.direction * node.distance - edgeMovement; //simulate collision by moving the point by the vectors of both the point and the edge, //note: collisions are simpler if only one body is moving so we're going to add the edge vector onto the point vector, making the edge remain stationary Vector2 calculationPoint = node.previousPosition + nodeMovement; //calculate the point vector by adding the edge one to it Vector2 edgePosA = edge.nodeA.previousPosition; Vector2 edgePosB = edge.nodeB.previousPosition; // float intersectionalDot = Vector2.Dot(edgeMovement.normalized, node.direction.normalized); // OffsetShapeLog.DrawLine(node.previousPosition, calculationPoint,new Color(1,0,0,0.4f)); // OffsetShapeLog.DrawLine(edgePosA, edgePosB, new Color(1, 0, 1, 0.4f)); Vector2 intersectionPoint; float percent = 0; bool intersects = false; // if (intersectionalDot < -10.75f) // { // Debug.DrawLine(Utils.ToV3(node.previousPosition), Utils.ToV3(calculationPoint), Color.red); // intersects = Utils.Intersects(node.previousPosition, calculationPoint, edgePosA, edgePosB, out intersectionPoint); // if (intersects) // { // Debug.DrawLine(Utils.ToV3(calculationPoint), Utils.ToV3(calculationPoint) + Vector3.up * 5, Color.magenta); // } // Vector2 a = node.previousPosition; // Vector2 b = node.position; // float movementMag = nodeMovement.magnitude; // float intersectionMag = (intersectionPoint - a).magnitude; // percent = intersectionMag / movementMag; // intersectionPoint = Vector2.Lerp(a, b, percent);//translate the point to the real movement point // } // else // { bool dbi = false;//node.id == 14; intersects = Utils.SweepIntersects2(edge.nodeA.previousPosition, edge.nodeB.previousPosition, edge.nodeA.position, edge.nodeB.position, node.previousPosition, node.position, out intersectionPoint, out percent, 0.1f, dbi); calculationPoint = node.position; // } // if(Utils.Intersects(node.previousPosition, calculationPoint, edgePosA, edgePosB, out intersectionPoint)) // if (Utils.SweepIntersects(edge.nodeA.previousPosition , edge.nodeB.previousPosition, edge.nodeA.position, edge.nodeB.position, node.previousPosition, node.position, out intersectionPoint, out percent)) if (intersects) { for (int be = 0; be < shape.baseEdges.Count; be++) { Edge baseEdge = shape.edges[be]; if (Utils.FastLineIntersection(node.previousPosition, node.position, baseEdge.positionA, baseEdge.positionB)) { intersects = false; } if (Utils.FastLineIntersection(edge.nodeA.position, edge.nodeB.position, baseEdge.positionA, baseEdge.positionB)) { intersects = false; } } } if (intersects) { OffsetShapeLog.AddLine("Split event detected"); SplitEvent splitEvent = new SplitEvent(); splitEvent.node = node; splitEvent.edge = edge; OffsetShapeLog.AddLine("node " + node.id); OffsetShapeLog.AddLine("splits edge " + edge.ToString()); OffsetShapeLog.DrawLine(node.previousPosition, calculationPoint, Color.red); OffsetShapeLog.DrawLine(edgePosA, edgePosB, Color.magenta); // Vector2 a = node.previousPosition; // Vector2 b = node.position; // Vector2 x = intersectionPoint;//intersectionInfo.Point0; // float movementMag = nodeMovement.magnitude; // float intersectionMag = (x - a).magnitude; // float percent = intersectionMag / movementMag; OffsetShapeLog.AddLine("at percent " + percent); // Vector2 actualIntersectionPoint = Vector2.Lerp(a, b, percent);//translate the point to the real movement point float newLengthA = (intersectionPoint - edge.positionA).magnitude; float newLengthB = (intersectionPoint - edge.positionB).magnitude; OffsetShapeLog.AddLine("line a length ", newLengthA); OffsetShapeLog.AddLine("line b length ", newLengthB); SplitEvent sEvent = eventLog.CreateSplitEvent(_shape, node, edge, intersectionPoint, percent, calculationPoint); if (sEvent == null) { continue; } if (newLengthA > pointAccuracy && newLengthB > pointAccuracy) { eventLog.AddEvent(sEvent);//can split - split point not close to either edge nodes } else { Node[] nodes = null; if (newLengthA < pointAccuracy && newLengthB < pointAccuracy) { nodes = new[] { node, edge.nodeA, edge.nodeB } } ; //point will split the edge into two edges that can't exist - collapse all nodes else if (newLengthA < pointAccuracy) { nodes = new[] { node, edge.nodeA } } ; //split point close to node a - collapse split node into edge.nodea else if (newLengthB < pointAccuracy) { nodes = new[] { node, edge.nodeB } } ; //split point close to node b - collapse split node into edge.nodeb if (nodes != null) { MergedEvent mEvent = eventLog.CreateMergeEvent(nodes, intersectionPoint, percent, calculationPoint); mEvent.Merge(sEvent); eventLog.AddEvent(mEvent); } } } } } currentSplits.Clear(); int eventCount = eventLog.count; OffsetShapeLog.AddLine("event count: ", eventCount); if (eventCount > 0) { float percent = eventLog.percent; earlyTermination = false; foreach (Node node in _shape.liveNodes) { node.MoveBack(percent);//move all nodes back to the position of the event } foreach (Edge edge in _shape.liveEdges) { edge.UpdateValues();//update all edges to reflect this } foreach (Node node in _shape.liveNodes) { if (_shape.formingEdges.ContainsKey(node)) { _shape.formingEdges[node].UpdateValues(); } } for (int e = 0; e < eventCount; e++) { IEvent sevent = eventLog[e]; sevent.DrawDebug(); OffsetShapeLog.AddLine(string.Format("Event {0} of type {4} at {1} percent and {2},{3}", e, sevent.percent, sevent.point.x, sevent.point.y, sevent.GetType())); switch (sevent.GetType().ToString()) { case "BuildR2.ShapeOffset.FlipEvent": FlipEvent fEvent = (FlipEvent)sevent; OffsetShapeLog.AddLine(fEvent.ToString()); if (OnFlipEvent != null) { OnFlipEvent(fEvent); } // CollapseEdge(fEvent.edge, fEvent.point, fEvent.height); break; case "BuildR2.ShapeOffset.SplitEvent": SplitEvent sEvent = (SplitEvent)sevent; OffsetShapeLog.AddLine(sevent.ToString()); if (OnSplitEvent != null) { OnSplitEvent(sEvent); } // SplitEdge(sEvent); break; case "BuildR2.ShapeOffset.MergedEvent": MergedEvent mEvent = (MergedEvent)sevent; OffsetShapeLog.AddLine(mEvent.ToString()); if (OnMergedEvent != null) { OnMergedEvent(mEvent); } // MergeEvent(mEvent); break; } } } else { if (!earlyTermination) { float percent = 1.0f - percentAccuracy; earlyTermination = false; foreach (Node node in _shape.liveNodes) { node.MoveBack(percent);//move all nodes back to the position of the event } foreach (Edge edge in _shape.liveEdges) { edge.UpdateValues();//update all edges to reflect this } } foreach (Node node in _shape.liveNodes) { if (_shape.formingEdges.ContainsKey(node)) { _shape.formingEdges[node].UpdateValues(); } } } } if (earlyTermination) { _complete = true; _shape.TerminateAllNodes(); if (OnCompleteEvent != null) { OnCompleteEvent(); } return; } else { //recalculate node directions foreach (Node node in _shape.liveNodes) { Utils.CalculateNodeDirAng(_shape, node); } } }
public void SplitEdge(SplitEvent e) { Edge oldLiveEdge = e.edge; Vector3 splitTangent = Utils.ToV3(oldLiveEdge.direction); SkeletonFace oldFace = _nodeDic[oldLiveEdge]; Node staticNode = e.newStaticNode; Edge newLiveEdgeA = e.newLiveEdgeA; Edge newLiveEdgeB = e.newLiveEdgeB; Node oldNode = e.node; Node newLiveNodeA = e.newLiveNodeA; Node newLiveNodeB = e.newLiveNodeB; //centre tri SkeletonTri newTriangle = new SkeletonTri(oldFace[0], oldFace[1], staticNode, splitTangent); AddTriangle(newTriangle); if (!_nodeDic.ContainsKey(e.nodeEdgeA)) { return; } SkeletonFace faceA = _nodeDic[e.nodeEdgeA]; faceA.ReplaceNode(oldNode, newLiveNodeA); //left tri SkeletonTri newTriangleA = new SkeletonTri(staticNode, faceA[0], newLiveNodeA, splitTangent); AddTriangle(newTriangleA); if (!_nodeDic.ContainsKey(e.nodeEdgeB)) { return; } SkeletonFace faceB = _nodeDic[e.nodeEdgeB]; faceB.ReplaceNode(oldNode, newLiveNodeB); //right tri SkeletonTri newTriangleB = new SkeletonTri(faceB[1], staticNode, newLiveNodeB, splitTangent); AddTriangle(newTriangleB); RemoveFace(oldFace); AddFace(newLiveEdgeA, oldFace[0], staticNode); AddFace(newLiveEdgeB, staticNode, oldFace[1]); int oldNodeReferenceCount = 0; if (_edgeDic.ContainsKey(oldNode)) { oldNodeReferenceCount = _edgeDic[oldNode].Count; } for (int r = 0; r < oldNodeReferenceCount; r++) { SkeletonFace face = _edgeDic[oldNode][r]; Edge liveEdge = face.liveEdge; if (liveEdge.Contains(newLiveNodeA)) { if (!_edgeDic.ContainsKey(newLiveNodeA)) { _edgeDic.Add(newLiveNodeA, new List <SkeletonFace>()); } _edgeDic[newLiveNodeA].Add(face); } if (liveEdge.Contains(newLiveNodeB)) { if (!_edgeDic.ContainsKey(newLiveNodeB)) { _edgeDic.Add(newLiveNodeB, new List <SkeletonFace>()); } _edgeDic[newLiveNodeB].Add(face); } } }
public void SplitEdge(SplitEvent e) { OffsetShapeLog.AddLine("Split event"); OffsetShapeLog.AddLine("by node ", e.node.id); OffsetShapeLog.AddLine(e.edge.ToString()); //nodes float realHeight = e.node.height; Node nodeStatic = (e.newStaticNode == null) ? new Node(e.point, realHeight) : e.newStaticNode; e.newStaticNode = nodeStatic; Node nodeOldA = e.edge.nodeA; Node nodeOldB = e.edge.nodeB; Edge[] edges = Utils.GetABEdge(shape, e.node); if (edges[0] == null || edges[1] == null) { //TODO work out what to really do here. return; } Edge byEdgeA = edges[0]; Edge byEdgeB = edges[1]; Node byNodeA = byEdgeA.GetOtherNode(e.node); Node byNodeB = byEdgeB.GetOtherNode(e.node); OffsetShapeLog.AddLine("by node a", byNodeA.id); OffsetShapeLog.AddLine("by node b", byNodeB.id); if (byNodeA == null || byNodeB == null) { return; } int insertionIndex = _core.shape.LiveIndex(e.node); _core.shape.AddStaticNode(nodeStatic); _core.shape.liveNodes.Remove(e.node); //discard the old edge OffsetShapeLog.AddLine("Discard old edge ", e.edge.ToString()); _core.shape.liveEdges.Remove(e.edge);// if (!_splitEdges.ContainsKey(e.edge)) { _splitEdges.Add(e.edge, e); } Utils.RetireFormingEdge(_core.shape, e.node, nodeStatic); Node newLiveNodeA = null; Node newLiveNodeB = null; //node a if (!e.edge.Contains(byNodeA)) { newLiveNodeA = new Node(e.point, realHeight); e.newLiveNodeA = newLiveNodeA; //calculate new node directions Utils.CalculateNodeDirAng(newLiveNodeA, byNodeA, nodeOldA); _core.shape.InsertLiveNode(insertionIndex, newLiveNodeA); byEdgeA.ReplaceNode(e.node, newLiveNodeA); //create the two new edges from the split Edge newEdgeA = new Edge(nodeOldA, newLiveNodeA); _core.shape.liveEdges.Add(newEdgeA); e.newLiveEdgeA = newEdgeA; Edge formingEdgeA = Utils.NewFormingEdge(_core.shape, nodeStatic, newLiveNodeA); OffsetShapeLog.AddLine("new live node a"); OffsetShapeLog.AddLine(newLiveNodeA.id); OffsetShapeLog.AddLine("new edges - old edge - forming edge a"); OffsetShapeLog.AddLine(newEdgeA.ToString()); OffsetShapeLog.AddLine(byEdgeA.ToString()); OffsetShapeLog.AddLine(formingEdgeA.ToString()); } else { Utils.RetireFormingEdge(_core.shape, byNodeA, nodeStatic); _core.shape.liveNodes.Remove(byNodeA); } //node b if (!e.edge.Contains(byNodeB)) { newLiveNodeB = new Node(e.point, realHeight); e.newLiveNodeB = newLiveNodeB; Utils.CalculateNodeDirAng(newLiveNodeB, nodeOldB, byNodeB); _core.shape.InsertLiveNode(insertionIndex, newLiveNodeB); byEdgeB.ReplaceNode(e.node, newLiveNodeB); Edge newEdgeB = new Edge(newLiveNodeB, nodeOldB); _core.shape.liveEdges.Add(newEdgeB); e.newLiveEdgeB = newEdgeB; Edge formingEdgeB = Utils.NewFormingEdge(_core.shape, nodeStatic, newLiveNodeB); OffsetShapeLog.AddLine("new live node b"); OffsetShapeLog.AddLine(newLiveNodeB.id); OffsetShapeLog.AddLine("new edges - old edge - forming edge b"); OffsetShapeLog.AddLine(byEdgeB.ToString()); OffsetShapeLog.AddLine(newEdgeB.ToString()); OffsetShapeLog.AddLine(formingEdgeB.ToString()); } else { Utils.RetireFormingEdge(_core.shape, byNodeB, nodeStatic); _core.shape.liveNodes.Remove(byNodeB); } if (newLiveNodeA != null && newLiveNodeB != null) { if (!_core.currentSplits.ContainsKey(newLiveNodeA.id)) { _core.currentSplits.Add(newLiveNodeA.id, new List <int>()); } _core.currentSplits[newLiveNodeA.id].Add(newLiveNodeB.id); if (!_core.currentSplits.ContainsKey(newLiveNodeB.id)) { _core.currentSplits.Add(newLiveNodeB.id, new List <int>()); } _core.currentSplits[newLiveNodeB.id].Add(newLiveNodeA.id); } }
private void OnSplit(SplitEvent sEvent) { sEvent.DrawDebug(); SplitEvent(sEvent); Utils.CheckParrallel(_core.shape); }