Пример #1
0
        public static Rect GetSupportRect(FloorPlan floorPlan, IRoomGen oldGen, IRoomGen newGen, Dir4 dir, List <RoomHallIndex> adjacentsInDir)
        {
            bool vertical    = dir.ToAxis() == Axis4.Vert;
            Rect supportRect = newGen.Draw;

            supportRect.Start += dir.GetLoc() * supportRect.Size.GetScalar(dir.ToAxis());
            supportRect.SetScalar(dir, oldGen.Draw.GetScalar(dir));

            IntRange minMax = newGen.Draw.GetSide(dir.ToAxis());

            foreach (RoomHallIndex adj in adjacentsInDir)
            {
                IRoomGen adjGen    = floorPlan.GetRoomHall(adj).RoomGen;
                IntRange adjMinMax = adjGen.Draw.GetSide(dir.ToAxis());
                minMax = new IntRange(Math.Min(adjMinMax.Min, minMax.Min), Math.Max(adjMinMax.Max, minMax.Max));
            }

            IntRange oldMinMax = oldGen.Draw.GetSide(dir.ToAxis());

            minMax = new IntRange(Math.Max(oldMinMax.Min, minMax.Min), Math.Min(oldMinMax.Max, minMax.Max));

            if (vertical)
            {
                supportRect.SetScalar(Dir4.Left, minMax.Min);
                supportRect.SetScalar(Dir4.Right, minMax.Max);
            }
            else
            {
                supportRect.SetScalar(Dir4.Up, minMax.Min);
                supportRect.SetScalar(Dir4.Down, minMax.Max);
            }

            return(supportRect);
        }
Пример #2
0
        protected static ListPathTraversalNode?GetRoomToConnect(FloorPlan floorPlan, RoomHallIndex chosenFrom, Dir4 dir)
        {
            // extend a rectangle to the border of the floor in the chosen direction
            bool     vertical   = dir.ToAxis() == Axis4.Vert;
            int      dirSign    = dir.GetLoc().GetScalar(dir.ToAxis());
            IRoomGen genFrom    = floorPlan.GetRoomHall(chosenFrom).RoomGen;
            Rect     sampleRect = genFrom.Draw;

            // expand from the start of that border direction to the borders of the floor
            sampleRect.Start += dir.GetLoc() * sampleRect.Size.GetScalar(dir.ToAxis());

            // it doesn't have to be exactly the borders so just add the total size to be sure
            sampleRect.Expand(dir, vertical ? floorPlan.Size.Y : floorPlan.Size.X);

            // find the closest room.
            var chosenTo = new RoomHallIndex(-1, false);

            foreach (RoomHallIndex collision in floorPlan.CheckCollision(sampleRect))
            {
                Rect collidedRect = floorPlan.GetRoomHall(collision).RoomGen.Draw;

                // limit the expansion by direction
                int  sampleScalar   = sampleRect.GetScalar(dir);
                int  collidedScalar = collidedRect.GetScalar(dir.Reverse());
                bool limit          = dirSign == Math.Sign(sampleScalar - collidedScalar);
                if (limit)
                {
                    // update the boundaries
                    sampleRect.SetScalar(dir, collidedScalar);
                    chosenTo = collision;
                }
            }

            // if it didn't collide with ANYTHING, then quit
            if (chosenTo.Index == -1)
            {
                return(null);
            }

            IRoomGen genTo = floorPlan.GetRoomHall(chosenTo).RoomGen;

            // narrow the rectangle if touching something on the side
            // widen the rectangle by width
            Rect widthRect = sampleRect;

            widthRect.Inflate(vertical ? 1 : 0, vertical ? 0 : 1);
            bool retractLeft  = false;
            bool retractRight = false;
            Dir4 leftDir      = DirExt.AddAngles(dir, Dir4.Left);
            Dir4 rightDir     = DirExt.AddAngles(dir, Dir4.Right);

            foreach (RoomHallIndex collision in floorPlan.CheckCollision(widthRect))
            {
                Rect collidedRect = floorPlan.GetRoomHall(collision).RoomGen.Draw;
                if (!retractLeft)
                {
                    if (collidedRect.GetScalar(leftDir.Reverse()) == sampleRect.GetScalar(leftDir))
                    {
                        retractLeft = true;
                    }
                }

                if (!retractRight)
                {
                    if (collidedRect.GetScalar(rightDir.Reverse()) == sampleRect.GetScalar(rightDir))
                    {
                        retractRight = true;
                    }
                }
            }

            // retract the rectangle
            if (retractLeft)
            {
                sampleRect.Expand(leftDir, -1);
            }
            if (retractRight)
            {
                sampleRect.Expand(rightDir, -1);
            }

            // if the rectangle has been retracted too much, we can't go on
            if (sampleRect.Area <= 0)
            {
                return(null);
            }

            // check for border availability between start and end
            bool foundFrom = HasBorderOpening(genFrom, sampleRect, dir);
            bool foundTo   = HasBorderOpening(genTo, sampleRect, dir.Reverse());

            // return the expansion if one is found
            if (foundFrom && foundTo)
            {
                return(new ListPathTraversalNode(chosenFrom, chosenTo, sampleRect));
            }
            else
            {
                return(null);
            }
        }