private void TwoEdgedThickening(Node node, float thickness) { var newBlockNodes = GetTwoEdgedThickenedNodes(node, thickness); var blockNode1 = newBlockNodes[0]; var blockNode2 = newBlockNodes[1]; blockNode1.Edges.Add(node.Edges[0]); blockNode1.Edges.Add(node.Edges[1]); blockNode2.Edges.Add(node.Edges[0]); blockNode2.Edges.Add(node.Edges[1]); node.BlockNodes.Add(blockNode1); node.BlockNodes.Add(blockNode2); BlockNodes.Add(blockNode1); BlockNodes.Add(blockNode2); }
/** * THICKENER FUNCTIONS */ private void OneEdgedThickening(Node node, float thickness) { //this only work for nodes, which has only one edge if (node.Edges.Count != 1) { throw new ArgumentException("Parameter node doesn't have exactly one edges", nameof(node)); } //Calculate float dirRadian; if (node.Edges[0].NodeA == node) { dirRadian = node.Edges[0].DirRadianFromA; } else { dirRadian = node.Edges[0].DirRadianFromB; } Vector2 leftForward = new Vector2( Mathf.Cos(dirRadian + 1.5f * Mathf.PI / 2) * thickness * 1f / Mathf.Sin(Mathf.PI / 4), Mathf.Sin(dirRadian + 1.5f * Mathf.PI / 2) * thickness * 1f / Mathf.Sin(Mathf.PI / 4)); Vector2 rightForward = new Vector2( Mathf.Cos(dirRadian - 1.5f * Mathf.PI / 2) * thickness * 1f / Mathf.Sin(Mathf.PI / 4), Mathf.Sin(dirRadian - 1.5f * Mathf.PI / 2) * thickness * 1f / Mathf.Sin(Mathf.PI / 4)); //Then store it BlockNode blockNode1 = new BlockNode(node.X + leftForward.x, node.Y + leftForward.y); BlockNode blockNode2 = new BlockNode(node.X + rightForward.x, node.Y + rightForward.y); blockNode1.Edges.Add(node.Edges[0]); blockNode2.Edges.Add(node.Edges[0]); node.BlockNodes.Add(blockNode1); node.BlockNodes.Add(blockNode2); BlockNodes.Add(blockNode1); BlockNodes.Add(blockNode2); }
private void FourEdgedThickening(Node node, float thickness) { //this only work for nodes, which has four edges if (node.Edges.Count != 4) { throw new ArgumentException("Parameter node doesn't have exactly four edges", nameof(node)); } bool majorWithMinor = false; //FIRST CALCULATE Edge edge1 = node.Edges[0]; Edge edge2 = node.Edges[1]; Edge edge3 = node.Edges[2]; Edge edge4 = node.Edges[3]; if (!( graph.MajorEdges.Contains(edge1) && graph.MajorEdges.Contains(edge2) && graph.MajorEdges.Contains(edge3) && graph.MajorEdges.Contains(edge4)) && !( graph.MinorEdges.Contains(edge1) && graph.MinorEdges.Contains(edge2) && graph.MinorEdges.Contains(edge3) && graph.MinorEdges.Contains(edge4))) { majorWithMinor = true; } //radians from node float radian1 = edge1.NodeA == node ? edge1.DirRadianFromA : edge1.DirRadianFromB; float radian2 = edge2.NodeA == node ? edge2.DirRadianFromA : edge2.DirRadianFromB; float radian3 = edge3.NodeA == node ? edge3.DirRadianFromA : edge3.DirRadianFromB; float radian4 = edge4.NodeA == node ? edge4.DirRadianFromA : edge4.DirRadianFromB; List <float> radians = new List <float> { radian1, radian2, radian3, radian4 }; List <Edge> edges = new List <Edge> { edge1, edge2, edge3, edge4 }; List <Edge> sortedEdges = new List <Edge>(); for (int i = radians.Count - 1; i > -1; i--) //Get the edges sorted by their radians { float smallest = radians.Min(); int idx = radians.IndexOf(smallest); sortedEdges.Add(edges[idx]); edges.RemoveAt(idx); radians.RemoveAt(idx); } //After sorting, we can determine the role of every edge Edge baseEdge1 = sortedEdges[0]; Edge baseEdge2 = sortedEdges[2]; Edge commonEdge1 = sortedEdges[1]; Edge commonEdge2 = sortedEdges[3]; float averageRadBase1Common1 = AverageRadianFromTwoEdges(baseEdge1, commonEdge1, node); float averageRadBase1Common2 = AverageRadianFromTwoEdges(baseEdge1, commonEdge2, node); float averageRadBase2Common1 = AverageRadianFromTwoEdges(baseEdge2, commonEdge1, node); float averageRadBase2Common2 = AverageRadianFromTwoEdges(baseEdge2, commonEdge2, node); if (!CorrectFourEdgedAverage( averageRadBase1Common1, baseEdge1, baseEdge2, commonEdge2, node)) { averageRadBase1Common1 += Mathf.PI; } if (!CorrectFourEdgedAverage( averageRadBase1Common2, baseEdge1, baseEdge2, commonEdge1, node)) { averageRadBase1Common2 += Mathf.PI; } if (!CorrectFourEdgedAverage( averageRadBase2Common1, baseEdge2, baseEdge1, commonEdge2, node)) { averageRadBase2Common1 += Mathf.PI; } if (!CorrectFourEdgedAverage( averageRadBase2Common2, baseEdge2, baseEdge1, commonEdge1, node)) { averageRadBase2Common2 += Mathf.PI; } //4 final vectors to use for thickening Vector2 vecB1C1; Vector2 vecB1C2; Vector2 vecB2C1; Vector2 vecB2C2; float radianDiffB1C1 = RadianDifferenceFromTwoEdges(baseEdge1, commonEdge1, node); float radianDiffB1C2 = RadianDifferenceFromTwoEdges(baseEdge1, commonEdge2, node); float radianDiffB2C1 = RadianDifferenceFromTwoEdges(baseEdge2, commonEdge1, node); float radianDiffB2C2 = RadianDifferenceFromTwoEdges(baseEdge2, commonEdge2, node); //If one of the crossing is a Major-Minor crossing, make the vectors in a different way: if ((graph.MajorEdges.Contains(baseEdge1) && graph.MinorEdges.Contains(commonEdge1)) || (graph.MajorEdges.Contains(commonEdge1) && graph.MinorEdges.Contains(baseEdge1))) { vecB1C1 = MajorMinorCrossingThickening(baseEdge1, commonEdge1, node, radianDiffB1C1); } else { if (majorWithMinor && graph.MinorEdges.Contains(baseEdge1) && graph.MinorEdges.Contains(commonEdge1)) { vecB1C1 = new Vector2( Mathf.Cos(averageRadBase1Common1) * thickness / 2 * (1f / Mathf.Sin(radianDiffB1C1 / 2)), Mathf.Sin(averageRadBase1Common1) * thickness / 2 * (1f / Mathf.Sin(radianDiffB1C1 / 2))); } else { vecB1C1 = new Vector2( Mathf.Cos(averageRadBase1Common1) * thickness * (1f / Mathf.Sin(radianDiffB1C1 / 2)), Mathf.Sin(averageRadBase1Common1) * thickness * (1f / Mathf.Sin(radianDiffB1C1 / 2))); } } if ((graph.MajorEdges.Contains(baseEdge1) && graph.MinorEdges.Contains(commonEdge2)) || (graph.MajorEdges.Contains(commonEdge2) && graph.MinorEdges.Contains(baseEdge1))) { vecB1C2 = MajorMinorCrossingThickening(baseEdge1, commonEdge2, node, radianDiffB1C2); } else { if (majorWithMinor && graph.MinorEdges.Contains(baseEdge1) && graph.MinorEdges.Contains(commonEdge2)) { vecB1C2 = new Vector2( Mathf.Cos(averageRadBase1Common2) * thickness / 2 * (1f / Mathf.Sin(radianDiffB1C2 / 2)), Mathf.Sin(averageRadBase1Common2) * thickness / 2 * (1f / Mathf.Sin(radianDiffB1C2 / 2))); } else { vecB1C2 = new Vector2( Mathf.Cos(averageRadBase1Common2) * thickness * (1f / Mathf.Sin(radianDiffB1C2 / 2)), Mathf.Sin(averageRadBase1Common2) * thickness * (1f / Mathf.Sin(radianDiffB1C2 / 2))); } } if ((graph.MajorEdges.Contains(baseEdge2) && graph.MinorEdges.Contains(commonEdge1)) || (graph.MajorEdges.Contains(commonEdge1) && graph.MinorEdges.Contains(baseEdge2))) { vecB2C1 = MajorMinorCrossingThickening(baseEdge2, commonEdge1, node, radianDiffB2C1); } else { if (majorWithMinor && graph.MinorEdges.Contains(baseEdge2) && graph.MinorEdges.Contains(commonEdge1)) { vecB2C1 = new Vector2( Mathf.Cos(averageRadBase2Common1) * thickness / 2 * (1f / Mathf.Sin(radianDiffB2C1 / 2)), Mathf.Sin(averageRadBase2Common1) * thickness / 2 * (1f / Mathf.Sin(radianDiffB2C1 / 2))); } else { vecB2C1 = new Vector2( Mathf.Cos(averageRadBase2Common1) * thickness * (1f / Mathf.Sin(radianDiffB2C1 / 2)), Mathf.Sin(averageRadBase2Common1) * thickness * (1f / Mathf.Sin(radianDiffB2C1 / 2))); } } if ((graph.MajorEdges.Contains(baseEdge2) && graph.MinorEdges.Contains(commonEdge2)) || (graph.MajorEdges.Contains(commonEdge2) && graph.MinorEdges.Contains(baseEdge2))) { vecB2C2 = MajorMinorCrossingThickening(baseEdge2, commonEdge2, node, radianDiffB2C2); } else { if (majorWithMinor && graph.MinorEdges.Contains(baseEdge2) && graph.MinorEdges.Contains(commonEdge2)) { vecB2C2 = new Vector2( Mathf.Cos(averageRadBase2Common2) * thickness / 2 * (1f / Mathf.Sin(radianDiffB2C2 / 2)), Mathf.Sin(averageRadBase2Common2) * thickness / 2 * (1f / Mathf.Sin(radianDiffB2C2 / 2))); } else { vecB2C2 = new Vector2( Mathf.Cos(averageRadBase2Common2) * thickness * (1f / Mathf.Sin(radianDiffB2C2 / 2)), Mathf.Sin(averageRadBase2Common2) * thickness * (1f / Mathf.Sin(radianDiffB2C2 / 2))); } } //THEN STORE IT BlockNode blockNodeB1C1 = new BlockNode(node.X + vecB1C1.x, node.Y + vecB1C1.y); BlockNode blockNodeB1C2 = new BlockNode(node.X + vecB1C2.x, node.Y + vecB1C2.y); BlockNode blockNodeB2C1 = new BlockNode(node.X + vecB2C1.x, node.Y + vecB2C1.y); BlockNode blockNodeB2C2 = new BlockNode(node.X + vecB2C2.x, node.Y + vecB2C2.y); blockNodeB1C1.Edges.Add(baseEdge1); blockNodeB1C1.Edges.Add(commonEdge1); blockNodeB1C2.Edges.Add(baseEdge1); blockNodeB1C2.Edges.Add(commonEdge2); blockNodeB2C1.Edges.Add(baseEdge2); blockNodeB2C1.Edges.Add(commonEdge1); blockNodeB2C2.Edges.Add(baseEdge2); blockNodeB2C2.Edges.Add(commonEdge2); node.BlockNodes.Add(blockNodeB1C1); node.BlockNodes.Add(blockNodeB1C2); node.BlockNodes.Add(blockNodeB2C1); node.BlockNodes.Add(blockNodeB2C2); BlockNodes.Add(blockNodeB1C1); BlockNodes.Add(blockNodeB1C2); BlockNodes.Add(blockNodeB2C1); BlockNodes.Add(blockNodeB2C2); }
private void ThreeEdgedThickening(Node node, float thickness) { //this only work for nodes, which has three edges if (node.Edges.Count != 3) { throw new ArgumentException("Parameter node doesn't have exactly three edges", nameof(node)); } bool majorWithMinor = false; //First Calculate Edge edge1 = node.Edges[0]; Edge edge2 = node.Edges[1]; Edge edge3 = node.Edges[2]; if (!( graph.MajorEdges.Contains(edge1) && graph.MajorEdges.Contains(edge2) && graph.MajorEdges.Contains(edge3)) && !( graph.MinorEdges.Contains(edge1) && graph.MinorEdges.Contains(edge2) && graph.MinorEdges.Contains(edge3))) { majorWithMinor = true; } float averageRad12 = AverageRadianFromTwoEdges(edge1, edge2, node); float averageRad13 = AverageRadianFromTwoEdges(edge1, edge3, node); float averageRad23 = AverageRadianFromTwoEdges(edge2, edge3, node); float radianDiff12 = RadianDifferenceFromTwoEdges(edge1, edge2, node); float radianDiff13 = RadianDifferenceFromTwoEdges(edge1, edge3, node); float radianDiff23 = RadianDifferenceFromTwoEdges(edge2, edge3, node); if (radianDiff12 > Mathf.PI / 2 && !CorrectThreeEdgedAverage(averageRad12, edge3, node)) { averageRad12 += Mathf.PI; } if (radianDiff13 > Mathf.PI / 2 && !CorrectThreeEdgedAverage(averageRad13, edge2, node)) { averageRad13 += Mathf.PI; } if (radianDiff23 > Mathf.PI / 2 && !CorrectThreeEdgedAverage(averageRad23, edge1, node)) { averageRad23 += Mathf.PI; } Vector2 vec12; Vector2 vec13; Vector2 vec23; //If one of the crossing is a Major-Minor crossing, make the vectors in a different way. if ((graph.MajorEdges.Contains(edge1) && graph.MinorEdges.Contains(edge2)) || (graph.MajorEdges.Contains(edge2) && graph.MinorEdges.Contains(edge1))) { vec12 = MajorMinorCrossingThickening(edge1, edge2, node, radianDiff12); } else { if (majorWithMinor && graph.MinorEdges.Contains(edge1) && graph.MinorEdges.Contains(edge2)) { vec12 = new Vector2( Mathf.Cos(averageRad12) * thickness / 2 * (1f / Mathf.Sin(radianDiff12 / 2)), Mathf.Sin(averageRad12) * thickness / 2 * (1f / Mathf.Sin(radianDiff12 / 2))); } else { vec12 = new Vector2( Mathf.Cos(averageRad12) * thickness * (1f / Mathf.Sin(radianDiff12 / 2)), Mathf.Sin(averageRad12) * thickness * (1f / Mathf.Sin(radianDiff12 / 2))); } } if ((graph.MajorEdges.Contains(edge1) && graph.MinorEdges.Contains(edge3)) || (graph.MajorEdges.Contains(edge3) && graph.MinorEdges.Contains(edge1))) { vec13 = MajorMinorCrossingThickening(edge1, edge3, node, radianDiff13); } else { if (majorWithMinor && graph.MinorEdges.Contains(edge1) && graph.MinorEdges.Contains(edge3)) { vec13 = new Vector2( Mathf.Cos(averageRad13) * thickness / 2 * (1f / Mathf.Sin(radianDiff13 / 2)), Mathf.Sin(averageRad13) * thickness / 2 * (1f / Mathf.Sin(radianDiff13 / 2))); } else { vec13 = new Vector2( Mathf.Cos(averageRad13) * thickness * (1f / Mathf.Sin(radianDiff13 / 2)), Mathf.Sin(averageRad13) * thickness * (1f / Mathf.Sin(radianDiff13 / 2))); } } if ((graph.MajorEdges.Contains(edge2) && graph.MinorEdges.Contains(edge3)) || (graph.MajorEdges.Contains(edge3) && graph.MinorEdges.Contains(edge2))) { vec23 = MajorMinorCrossingThickening(edge2, edge3, node, radianDiff23); } else { if (majorWithMinor && graph.MinorEdges.Contains(edge2) && graph.MinorEdges.Contains(edge3)) { vec23 = new Vector2( Mathf.Cos(averageRad23) * thickness / 2 * (1f / Mathf.Sin(radianDiff23 / 2)), Mathf.Sin(averageRad23) * thickness / 2 * (1f / Mathf.Sin(radianDiff23 / 2))); } else { vec23 = new Vector2( Mathf.Cos(averageRad23) * thickness * (1f / Mathf.Sin(radianDiff23 / 2)), Mathf.Sin(averageRad23) * thickness * (1f / Mathf.Sin(radianDiff23 / 2))); } } //Then store it BlockNode blockNode12 = new BlockNode(node.X + vec12.x, node.Y + vec12.y); BlockNode blockNode13 = new BlockNode(node.X + vec13.x, node.Y + vec13.y); BlockNode blockNode23 = new BlockNode(node.X + vec23.x, node.Y + vec23.y); blockNode12.Edges.Add(edge1); blockNode12.Edges.Add(edge2); blockNode13.Edges.Add(edge1); blockNode13.Edges.Add(edge3); blockNode23.Edges.Add(edge2); blockNode23.Edges.Add(edge3); node.BlockNodes.Add(blockNode12); node.BlockNodes.Add(blockNode13); node.BlockNodes.Add(blockNode23); BlockNodes.Add(blockNode12); BlockNodes.Add(blockNode13); BlockNodes.Add(blockNode23); }