Beispiel #1
0
        private static Dictionary <int, List <int> > BuildNodeExternalConnections(IStoryGraph sg)
        {
            var result = new Dictionary <int, List <int> >();

            result.GetOrAdd(sg.Leaves.First(), x => new List <int>());
            result.GetOrAdd(sg.Leaves.Last(), x => new List <int>());
            foreach (var edge in sg.Edges)
            {
                var commonParent = sg.GetCommonParent(edge.First, edge.Second);

                var first = edge.First;
                while (sg.Parents[first] != commonParent)
                {
                    var list = result.GetOrAdd(first, x => new List <int>());
                    list.Add(edge.Second);
                    first = sg.Parents[first];
                }

                var second = edge.Second;
                while (sg.Parents[second] != commonParent)
                {
                    var list = result.GetOrAdd(second, x => new List <int>());
                    list.Add(edge.First);
                    second = sg.Parents[second];
                }
            }
            return(result);
        }
Beispiel #2
0
        private void PlaceCorridors()
        {
            var occupiedLanes = new IntSet32[sg.NodeIds.Max() + 1];

            foreach (var edge in sg.Edges)
            {
                laneBuilder.StartLane(edge);
                var disambiguator       = 0;
                var commonOccupiedLanes = new IntSet32();
                if (sg.Parents[edge.First] == sg.Parents[edge.Second])
                {
                    var commonParent = sg.Parents[edge.First];
                    var startPoint   = relPositions[edge.First] + Vector3.UnitX * halfSizes[edge.First].Width;
                    var endPoint     = relPositions[edge.Second] - Vector3.UnitX * halfSizes[edge.Second].Width;

                    if (!IsMultiFloorNode(commonParent))
                    {
                        if (nodeRows[edge.Second] - nodeRows[edge.First] == 1)
                        {
                            laneBuilder.StartLaneSegment(BuildingStoryLayoutLanePartType.Immediate, true);
                            laneBuilder.AddRawPoint(startPoint);
                            laneBuilder.AddRawPoint(startPoint + Vector3.UnitX * BuildingConstants.CorridorBranchingOffset);
                            laneBuilder.AddRawPoint(endPoint - Vector3.UnitX * BuildingConstants.CorridorBranchingOffset);
                            laneBuilder.AddRawPoint(endPoint);
                            laneBuilder.EndLaneSegment(commonParent, true);
                        }
                        else
                        {
                            disambiguator = 1;
                            while (occupiedLanes[commonParent].Contains(disambiguator))
                            {
                                disambiguator++;
                            }

                            var leafChildrenOnly = !sg.Children[commonParent].SelectMany(x => sg.Children[x]).Any();
                            if (leafChildrenOnly)
                            {
                                laneBuilder.StartLaneSegment(BuildingStoryLayoutLanePartType.LongRange, true);
                                laneBuilder.AddRawPoint(startPoint);
                                laneBuilder.AddRawPoint(startPoint + Vector3.UnitX * BuildingConstants.CorridorBranchingOffset);
                                laneBuilder.AddRawPoint(new Vector3(startPoint.X + BuildingConstants.WidthMargin - BuildingConstants.CorridorBranchingOffset, startPoint.Y, 0));
                                laneBuilder.AddRawPoint(new Vector3(endPoint.X - BuildingConstants.WidthMargin + BuildingConstants.CorridorBranchingOffset, startPoint.Y, 0));
                                laneBuilder.AddRawPoint(endPoint - Vector3.UnitX * BuildingConstants.CorridorBranchingOffset);
                                laneBuilder.AddRawPoint(endPoint);
                                laneBuilder.EndLaneSegment(commonParent, true);
                                occupiedLanes[commonParent] = occupiedLanes[commonParent].With(disambiguator);
                            }
                            else
                            {
                                laneBuilder.StartLaneSegment(BuildingStoryLayoutLanePartType.LongRange, true);
                                laneBuilder.AddRawPoint(startPoint);
                                laneBuilder.AddRawPoint(startPoint + Vector3.UnitX * BuildingConstants.CorridorBranchingOffset);
                                laneBuilder.AddRawPoint(new Vector3(startPoint.X + BuildingConstants.WidthMargin - BuildingConstants.CorridorBranchingOffset, startPoint.Y, 0));
                                laneBuilder.AddRawPoint(new Vector3(startPoint.X + BuildingConstants.WidthMargin, startPoint.Y, 0));
                                laneBuilder.EndLaneSegment(commonParent, false);

                                laneBuilder.StartLaneSegment(BuildingStoryLayoutLanePartType.LongRange, false);
                                laneBuilder.AddRawPoint(new Vector3(endPoint.X - BuildingConstants.WidthMargin, startPoint.Y, 0));
                                laneBuilder.AddRawPoint(new Vector3(endPoint.X - BuildingConstants.WidthMargin + BuildingConstants.CorridorBranchingOffset, startPoint.Y, 0));
                                laneBuilder.AddRawPoint(endPoint - Vector3.UnitX * BuildingConstants.CorridorBranchingOffset);
                                laneBuilder.AddRawPoint(endPoint);
                                laneBuilder.EndLaneSegment(commonParent, true);

                                occupiedLanes[commonParent] = occupiedLanes[commonParent].With(disambiguator);
                            }
                        }
                    }
                    else
                    {
                        disambiguator = 1;
                        while (occupiedLanes[commonParent].Contains(disambiguator))
                        {
                            disambiguator++;
                        }

                        var floorDistance = nodeRows[edge.Second] - nodeRows[edge.First];
                        laneBuilder.StartLaneSegment(BuildingStoryLayoutLanePartType.LongRange, true);
                        laneBuilder.AddRawPoint(startPoint);
                        laneBuilder.AddRawPoint(new Vector3(halfSizes[commonParent].Width, startPoint.Y, startPoint.Z));
                        laneBuilder.AddRawPoint(new Vector3(halfSizes[commonParent].Width, startPoint.Y, -halfSizes[commonParent].Depth - BuildingConstants.StairsDistance * (floorDistance + 1)));
                        laneBuilder.AddRawPoint(new Vector3(halfSizes[commonParent].Width, endPoint.Y, -halfSizes[commonParent].Depth - BuildingConstants.StairsDistance * (floorDistance + 1)));
                        laneBuilder.AddRawPoint(new Vector3(halfSizes[commonParent].Width, endPoint.Y, endPoint.Z));
                        laneBuilder.AddRawPoint(endPoint);
                        laneBuilder.EndLaneSegment(commonParent, true);
                    }
                }
                else
                {
                    var commonParent       = sg.GetCommonParent(edge.First, edge.Second);
                    var laneContainerNodes = new List <int>();

                    var descendingNodes = new Stack <int>();
                    {
                        var descNode = edge.Second;
                        while (descNode != commonParent)
                        {
                            descendingNodes.Push(descNode);
                            descNode = sg.Parents[descNode];
                        }
                    }

                    var node = edge.First;
                    while (sg.Parents[node] != commonParent)
                    {
                        var parent = sg.Parents[node];
                        commonOccupiedLanes = commonOccupiedLanes.Union(occupiedLanes[parent]);
                        laneContainerNodes.Add(parent);
                        var nodeLoc         = node;
                        var transitSiblings = sg.Children[parent].Where(x => relPositions[x].Z == 0f && nodeRows[nodeLoc] < nodeRows[x]);
                        foreach (var transitSibling in transitSiblings)
                        {
                            commonOccupiedLanes = commonOccupiedLanes.Union(occupiedLanes[transitSibling]);
                            laneContainerNodes.Add(transitSibling);
                        }
                        var startPoint = relPositions[node] + Vector3.UnitX * halfSizes[node].Width;
                        laneBuilder.StartLaneSegment(BuildingStoryLayoutLanePartType.InterNode, node == edge.First);
                        laneBuilder.AddRawPoint(startPoint);
                        laneBuilder.AddRawPoint(startPoint + Vector3.UnitX * BuildingConstants.CorridorBranchingOffset);
                        laneBuilder.AddRawPoint(new Vector3(startPoint.X + BuildingConstants.WidthMargin - BuildingConstants.CorridorBranchingOffset, startPoint.Y, 0));
                        laneBuilder.AddRawPoint(new Vector3(halfSizes[parent].Width, startPoint.Y, 0));
                        laneBuilder.EndLaneSegment(parent, false);
                        node = sg.Parents[node];
                    }

                    {
                        var topLevelChildFirst  = node;
                        var topLevelChildSecond = descendingNodes.Pop();
                        commonOccupiedLanes = commonOccupiedLanes.Union(occupiedLanes[commonParent]);
                        laneContainerNodes.Add(commonParent);

                        var startPoint = relPositions[topLevelChildFirst] + Vector3.UnitX * halfSizes[topLevelChildFirst].Width;
                        var endPoint   = relPositions[topLevelChildSecond] - Vector3.UnitX * halfSizes[topLevelChildSecond].Width;

                        if (!IsMultiFloorNode(commonParent))
                        {
                            if (nodeRows[topLevelChildSecond] - nodeRows[topLevelChildFirst] == 1)
                            {
                                laneBuilder.StartLaneSegment(BuildingStoryLayoutLanePartType.InterNode, false);
                                laneBuilder.AddRawPoint(startPoint);
                                laneBuilder.AddRawPoint(startPoint + Vector3.UnitX * BuildingConstants.CorridorBranchingOffset);
                                laneBuilder.AddRawPoint(endPoint - Vector3.UnitX * BuildingConstants.CorridorBranchingOffset);
                                laneBuilder.AddRawPoint(endPoint);
                                laneBuilder.EndLaneSegment(commonParent, false);
                            }
                            else
                            {
                                var transitSiblings = sg.Children[commonParent].Where(x => relPositions[x].Z == 0f && nodeRows[topLevelChildFirst] < nodeRows[x] && nodeRows[x] < nodeRows[topLevelChildSecond]);
                                foreach (var transitSibling in transitSiblings)
                                {
                                    commonOccupiedLanes = commonOccupiedLanes.Union(occupiedLanes[transitSibling]);
                                    laneContainerNodes.Add(transitSibling);
                                }

                                laneBuilder.StartLaneSegment(BuildingStoryLayoutLanePartType.InterNode, false);
                                laneBuilder.AddRawPoint(startPoint);
                                laneBuilder.AddRawPoint(startPoint + Vector3.UnitX * BuildingConstants.CorridorBranchingOffset);
                                laneBuilder.AddRawPoint(new Vector3(startPoint.X + BuildingConstants.WidthMargin - BuildingConstants.CorridorBranchingOffset, startPoint.Y, 0));
                                laneBuilder.AddRawPoint(new Vector3(endPoint.X - BuildingConstants.WidthMargin + BuildingConstants.CorridorBranchingOffset, startPoint.Y, 0));
                                laneBuilder.AddRawPoint(endPoint - Vector3.UnitX * BuildingConstants.CorridorBranchingOffset);
                                laneBuilder.AddRawPoint(endPoint);
                                laneBuilder.EndLaneSegment(commonParent, false);
                            }
                        }
                        else
                        {
                            var revStartPoint = new Vector3(-startPoint.X, startPoint.Y, startPoint.Z);
                            var revEndPoint   = new Vector3(-endPoint.X, endPoint.Y, endPoint.Z);

                            var floorDistance = nodeRows[topLevelChildSecond] - nodeRows[topLevelChildFirst];
                            laneBuilder.StartLaneSegment(BuildingStoryLayoutLanePartType.Elevator, false);
                            if (!isReversed[topLevelChildFirst])
                            {
                                laneBuilder.AddRawPoint(startPoint);
                                laneBuilder.AddRawPoint(startPoint + Vector3.UnitX * BuildingConstants.ElevatorOffset);
                            }
                            else
                            {
                                laneBuilder.AddRawPoint(revStartPoint);
                                laneBuilder.AddRawPoint(revStartPoint - Vector3.UnitX * BuildingConstants.ElevatorOffset);
                            }

                            if (!isReversed[topLevelChildSecond])
                            {
                                if (!isReversed[topLevelChildFirst])
                                {
                                    laneBuilder.AddRawPoint(revEndPoint + Vector3.UnitX * BuildingConstants.ElevatorOffset);
                                    laneBuilder.AddRawPoint(revEndPoint);
                                    laneBuilder.AddRawPoint(endPoint);
                                }
                                else
                                {
                                    laneBuilder.AddRawPoint(endPoint - Vector3.UnitX * BuildingConstants.ElevatorOffset);
                                    laneBuilder.AddRawPoint(endPoint);
                                }
                            }
                            else
                            {
                                if (!isReversed[topLevelChildFirst])
                                {
                                    laneBuilder.AddRawPoint(revEndPoint + Vector3.UnitX * BuildingConstants.ElevatorOffset);
                                    laneBuilder.AddRawPoint(revEndPoint);
                                }
                                else
                                {
                                    laneBuilder.AddRawPoint(endPoint - Vector3.UnitX * BuildingConstants.ElevatorOffset);
                                    laneBuilder.AddRawPoint(endPoint);
                                    laneBuilder.AddRawPoint(revEndPoint);
                                }
                            }
                            laneBuilder.EndLaneSegment(commonParent, false);
                        }
                    }

                    while (descendingNodes.Any())
                    {
                        node = descendingNodes.Pop();
                        var parent = sg.Parents[node];
                        commonOccupiedLanes = commonOccupiedLanes.Union(occupiedLanes[parent]);
                        laneContainerNodes.Add(parent);
                        var nodeLoc         = node;
                        var transitSiblings = sg.Children[parent].Where(x => relPositions[x].Z == 0f && nodeRows[x] < nodeRows[nodeLoc]);
                        foreach (var transitSibling in transitSiblings)
                        {
                            commonOccupiedLanes = commonOccupiedLanes.Union(occupiedLanes[transitSibling]);
                            laneContainerNodes.Add(transitSibling);
                        }

                        var endPoint = relPositions[node] - Vector3.UnitX * halfSizes[node].Width;
                        laneBuilder.StartLaneSegment(BuildingStoryLayoutLanePartType.InterNode, false);
                        laneBuilder.AddRawPoint(new Vector3(-halfSizes[parent].Width, endPoint.Y, 0));
                        laneBuilder.AddRawPoint(new Vector3(endPoint.X - BuildingConstants.WidthMargin + BuildingConstants.CorridorBranchingOffset, endPoint.Y, 0));
                        laneBuilder.AddRawPoint(new Vector3(endPoint.X - BuildingConstants.CorridorBranchingOffset, endPoint.Y, endPoint.Z));
                        laneBuilder.AddRawPoint(endPoint);
                        laneBuilder.EndLaneSegment(parent, node == edge.Second);
                    }

                    disambiguator = 1;
                    while (commonOccupiedLanes.Contains(disambiguator))
                    {
                        disambiguator++;
                    }

                    foreach (var laneContainerNode in laneContainerNodes)
                    {
                        occupiedLanes[laneContainerNode] = occupiedLanes[laneContainerNode].With(disambiguator);
                    }
                }
                laneBuilder.EndLane(disambiguator);
            }
        }