Ejemplo n.º 1
0
        //This function checks the orientation of a BlockNode compared to and edge
        private int Orientation(Edge baseEdge, BlockNode testNode)
        {
            //Orientation can be calculated with the cross product of two Vectors made from the 3 Nodes
            float val = (baseEdge.NodeA.Y - testNode.Y) * (baseEdge.NodeB.X - testNode.X) - (baseEdge.NodeA.X - testNode.X) * (baseEdge.NodeB.Y - testNode.Y);

            if (val > 0.00001f)
            {
                return(1);                //clockwise
            }
            if (val < -0.00001f)
            {
                return(-1);                 //anticlockwise
            }
            else
            {
                Debug.Log("BlockNode Collinear to it's Edge");
                return(0); //collinear, shouldn't really happen with BlockNodes that uses this edge
            }
        }
Ejemplo n.º 2
0
        /**
         * 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);
        }
Ejemplo n.º 3
0
 public bool Equals(BlockNode otherNode)
 {
     return(Math.Abs(X - otherNode.X) < 0.0001f && Math.Abs(Y - otherNode.Y) < 0.0001f);
 }
Ejemplo n.º 4
0
        /**
         * BLOCK FORMING
         */

        //Recursive function, which forms a new Block from a starting BlockNode. Returns true if forming finished. Returns false if forming failed.
        private bool FormBlock(BlockNode node, Edge edgeToSearch, Block blockToBuild, int iteration)
        {
            if (blockToBuild.Nodes.Contains(node))
            {
                return(true);                                   //We got around
            }
            if (node.Block != null)
            {
                return(false);                    //Node already has a Block
            }
            if (iteration > 100)
            {
                return(false);            //Recursive function iteration is too high
            }
            blockToBuild.Nodes.Add(node); //First add current node to the Block
            node.Block = blockToBuild;

            Node nextNode = edgeToSearch.NodeA.BlockNodes.Contains(node) ? edgeToSearch.NodeB : edgeToSearch.NodeA;

            //Special case: One edged node
            if (node.Edges.Count == 1)
            {
                Node      currentNode    = edgeToSearch.NodeA.BlockNodes.Contains(node) ? edgeToSearch.NodeA : edgeToSearch.NodeB;
                BlockNode otherBlockNode = currentNode.BlockNodes[0] == node ? currentNode.BlockNodes[1] : currentNode.BlockNodes[0];

                if (!blockToBuild.Nodes.Contains(otherBlockNode))
                {
                    if (FormBlock(otherBlockNode, edgeToSearch, blockToBuild, iteration + 1)) //If it's the first blockNode, go for 2nd node, if it's the second, operate normally
                    {
                        return(true);
                    }
                    else
                    {
                        return(false);
                    }
                }
            }

            //Check which is the next blockNode
            BlockNode nextBlockNode = null;
            int       currentBlockOrientationToEdge = Orientation(edgeToSearch, node);

            foreach (BlockNode blockNode in nextNode.BlockNodes)
            {
                if (blockNode.Edges.Contains(edgeToSearch))
                {
                    if (Orientation(edgeToSearch, blockNode) == currentBlockOrientationToEdge)
                    {
                        nextBlockNode = blockNode;
                    }
                }
            }

            if (nextBlockNode == null) //Next BlockNode not found, forming failed
            {
                return(false);
            }

            Edge nextEdgeToSearch;

            if (nextBlockNode.Edges.Count == 1) //Special case: One edged node
            {
                nextEdgeToSearch = edgeToSearch;
            }
            else
            {
                nextEdgeToSearch = nextBlockNode.Edges[0] == edgeToSearch ? nextBlockNode.Edges[1] : nextBlockNode.Edges[0];
            }

            //Recursive call to the next node
            if (FormBlock(nextBlockNode, nextEdgeToSearch, blockToBuild, iteration + 1))
            {
                return(true);
            }
            else
            {
                return(false);
            }
        }
Ejemplo n.º 5
0
        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);
        }
Ejemplo n.º 6
0
        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);
        }