Пример #1
0
        private Space.RoomRelationShip CreateWaitingList <Initial>(List <Guid> PlacedRelList, Dictionary <Space.RelationLevel, List <Space.RoomRelationShip> > NotPlacedRelList, Space.RelationLevel lv)
        {
            Space.RoomRelationShip init = new Space.RoomRelationShip(new Space.Room(), lv);
            foreach (Space.RoomRelationShip rel in Relationships.Values)
            {
                if (rel.Level == lv && rel.Origin is Initial)
                {
                    init = rel;
                }
            }

            if (init.Relations.Count == 0)
            {
                throw new System.Exception("Not Found initial start point at func CreateWaitingList");
            }

            PlacedRelList.Add(init.Origin.id);

            foreach (Guid id in init.Relations.Keys)
            {
                if (Relationships[id].Level == lv)
                {
                    NotPlacedRelList[lv].Add(Relationships[id]);
                }
            }
            NotPlacedRelList[lv].Sort();

            return(init);
        }
Пример #2
0
 private void HelpToGeneareteBlueprint(List <List <Blueprint> > results, Space.RoomRelationShip target)
 {
     if (results.Count == 0)
     {
         Blueprint Origin = new Blueprint(Conditions.WorldStdLocation);
         Space.RoomRelationShip Enterence = new Space.RoomRelationShip(new Space.Room(), Space.RelationLevel.First);
         //현관을 찾아, Origin에 배치하여 RootCase를 만듬.
         foreach (Space.RoomRelationShip rel in Relationships.Values)
         {
             if (rel.Origin is Space.Entrance)
             {
                 Enterence = rel;
                 //배치를 시작하는 지점을 찾았고, Results에 저장
                 results.Add(Blueprint.AddNewRoom(Origin, rel, Conditions));
                 break;
             }
         }
     }
     else
     {
         List <Blueprint>[] rootCase = results.ToArray();
         results.Clear();
         foreach (List <Blueprint> cases in rootCase)
         {
             foreach (Blueprint blue in cases)
             {
                 results.Add(Blueprint.AddNewRoom(blue, target, Conditions));
             }
         }
     }
 }
Пример #3
0
        private Space.RoomRelationShip PlanSecondLevel(Space.RoomRelationShip connRel)
        {
            //계단 정의
            Space.Room             stair    = new Space.Stair(connRel.Origin.Size, connRel.Origin.Materials, Conditions.StaticComponents);
            Space.RoomRelationShip stairRel = new Space.RoomRelationShip(stair, Space.RelationLevel.Second);

            this.ConnectRelation(stairRel, connRel, Space.ConnectionType.Level);

            this.Register(stairRel);

            //가족실(거실) 정의
            Space.Room             family    = new Space.Living(new Data.Size(360, 400, Data.Config.RoomHeight), GetMaterials(Space.RoomType.Living), Conditions.StaticComponents);
            Space.RoomRelationShip familyRel = new Space.RoomRelationShip(family, Space.RelationLevel.Second);

            this.ConnectRelation(stairRel, familyRel, Space.ConnectionType.Open);

            this.Register(familyRel);

            //침실 정의
            Space.Room             bed    = new Space.Bed(new Data.Size(350, 380, Data.Config.RoomHeight), GetMaterials(Space.RoomType.Bed), Conditions.StaticComponents);
            Space.RoomRelationShip bedRel = new Space.RoomRelationShip(bed, Space.RelationLevel.Second);

            this.ConnectRelation(bedRel, familyRel, Space.ConnectionType.Door);
            this.Register(bedRel);

            //화장실 정의
            Space.Room             rest    = new Space.Rest(new Data.Size(260, 300, Data.Config.RoomHeight), GetMaterials(Space.RoomType.Rest), Conditions.StaticComponents);
            Space.RoomRelationShip restRel = new Space.RoomRelationShip(rest, Space.RelationLevel.Second);

            this.ConnectRelation(restRel, familyRel, Space.ConnectionType.Door);
            this.Register(restRel);

            return(stairRel);
        }
Пример #4
0
        public void CreateEnterence() //Interpreter로 부터 받을 변수가 있다면 추가
        {
            //1층에서만 현관을 찾는다.
            foreach (Space.RoomRelationShip rel in this.Relations[Space.RelationLevel.First])
            {
                if (rel.Origin is Space.Entrance)
                {
                    Space.RoomRelationShip Ent = rel;
                    bool placed = false;

                    //어느 Side부터 탐색할지를 랜덤하게 결정하는 과정
                    List <Data.SideCardinalDirection> search = new List <Data.SideCardinalDirection>();
                    foreach (Data.SideCardinalDirection elem in Enum.GetValues(typeof(Data.SideCardinalDirection)))
                    {
                        search.Add(elem);
                    }

                    int n = search.Count;
                    while (n > 1)
                    {
                        n--;
                        int k = rng.Next(n + 1);
                        Data.SideCardinalDirection value = search[k];
                        search[k] = search[n];
                        search[n] = value;
                    }

                    foreach (Data.SideCardinalDirection relsideDirection in search)
                    {
                        foreach (Data.Side relSide in rel.Origin.Sides[relsideDirection])
                        {
                            if (relSide.Type == Data.SideType.Wall && relSide.GetLength() > Data.Config.DoorLength && this.IsOutterSide(rel.Origin.id, relSide, rel.Level))
                            {
                                relSide.Type = Data.SideType.Door;
                                placed       = true;
                                break;
                            }
                        }

                        if (placed)
                        {
                            break;
                        }
                    }

                    break;
                }
            }
        }
Пример #5
0
 private void ConnectRelation(Space.RoomRelationShip a, Space.RoomRelationShip b, Space.ConnectionType type)
 {
     a.AddRelation(b.Origin, type);
     b.AddRelation(a.Origin, type);
 }
Пример #6
0
 private void Register(Space.RoomRelationShip rel)
 {
     Rooms.Add(rel.Origin.id, rel.Origin);
     Relationships.Add(rel.Origin.id, rel);
 }
Пример #7
0
        public List <List <Blueprint> > GenerateBlueprints() //배치순서를 결정할 수 있는 변수들을 입력
        {
            //리턴할 준비
            List <List <Blueprint> > Results = new List <List <Blueprint> >();

            //Coditions을 활용하여 Rooms과 관계도를 생성하여, 객체에 저장
            GenerateRoomsAndRel();

            //배치과정을 기록하는 과정
            Dictionary <Space.RelationLevel, Space.RoomRelationShip> StartPoint = new Dictionary <Space.RelationLevel, Space.RoomRelationShip>();
            List <Guid> PlacedRelList = new List <Guid>();
            Dictionary <Space.RelationLevel, List <Space.RoomRelationShip> > NotPlacedRelList = new Dictionary <Space.RelationLevel, List <Space.RoomRelationShip> >();

            //초기화
            foreach (Space.RelationLevel lv in Enum.GetValues(typeof(Space.RelationLevel)))
            {
                NotPlacedRelList.Add(lv, new List <Space.RoomRelationShip>());

                //찾는 타입의 방으로 시작할 지점을 찾아, List를 만든다.
                if (lv == Space.RelationLevel.First)
                {
                    StartPoint.Add(lv, CreateWaitingList <Space.Entrance>(PlacedRelList, NotPlacedRelList, lv));
                }
                else if (lv == Space.RelationLevel.Second)
                {
                    StartPoint.Add(lv, CreateWaitingList <Space.Stair>(PlacedRelList, NotPlacedRelList, lv));
                }
            }

            //실제로 배치가 진행되는 과정. (모든 룸이 배치될 때까지 배치)
            foreach (Space.RelationLevel lv in Enum.GetValues(typeof(Space.RelationLevel)))
            {
                //StartPoint를 배치한다.
                HelpToGeneareteBlueprint(Results, StartPoint[lv]);

                while (NotPlacedRelList[lv].Count != 0)
                {
                    //새로 배치할 대상
                    Space.RoomRelationShip target = NotPlacedRelList[lv][0];

                    //실제로 배치가 진행되는 함수
                    HelpToGeneareteBlueprint(Results, target); //Results에 포함된 가능성을 새로운 가능성으로 전환

                    //배치완료를 기록
                    PlacedRelList.Add(target.Origin.id);
                    //Wating 리스트에서 제거
                    NotPlacedRelList[lv].Remove(target);

                    foreach (Guid id in target.Relations.Keys)
                    {
                        if (!(PlacedRelList.Contains(id) || NotPlacedRelList[lv].Contains(Relationships[id])) && target.Level == Relationships[id].Level)
                        {
                            NotPlacedRelList[lv].Add(Relationships[id]);
                        }
                    }
                    //관계 수에 따라 다시 정렬!
                    NotPlacedRelList[lv].Sort();
                }
            }

            //모든 배치가 완료된 상황에서, 창문과 현관문을 배치하기 위해서 외곽선을 파악하고 각 공간마다 창문 타입의 Side를 지정할 수 있도록 한다.
            foreach (List <Blueprint> bps in Results)
            {
                foreach (Blueprint bp in bps)
                {
                    bp.CreateEnterence();
                    bp.CreateWindows();
                    //TODO: 현재 계단작업은 잠시 중단되었다.
                    //bp.CreateStair();
                }
            }
            return(Results);
        }
Пример #8
0
        private Space.RoomRelationShip PlanFirstLevel()
        {
            //현관 정의
            Space.Room             enterence    = new Space.Entrance(Conditions.RoomSize.EnterenceSize, GetMaterials(Space.RoomType.Entrance), Conditions.StaticComponents);
            Space.RoomRelationShip enterenceRel = new Space.RoomRelationShip(enterence, Space.RelationLevel.First);
            this.Register(enterenceRel);

            //거실 정의
            Space.Room             living    = new Space.Living(Conditions.RoomSize.LivingSize, GetMaterials(Space.RoomType.Living), Conditions.StaticComponents);
            Space.RoomRelationShip livingRel = new Space.RoomRelationShip(living, Space.RelationLevel.First);

            //거실 남향을 통창으로 바꿈
            living.Sides[Data.SideCardinalDirection.South][0].Type = Data.SideType.WindowWall;

            this.ConnectRelation(livingRel, enterenceRel, Space.ConnectionType.Door);
            this.Register(livingRel);

            //주방 정의
            Space.Room             kitchen    = new Space.Kitchen(Conditions.RoomSize.KitchenSize, GetMaterials(Space.RoomType.Kitchen), Conditions.StaticComponents);
            Space.RoomRelationShip kitchenRel = new Space.RoomRelationShip(kitchen, Space.RelationLevel.First);

            this.ConnectRelation(livingRel, kitchenRel, Space.ConnectionType.Open);
            this.Register(kitchenRel);

            //침실 정의
            List <Space.Room> beds = new List <Space.Room>();

            foreach (Data.Size size in Conditions.RoomSize.BedSizes)
            {
                Space.Room             bed    = new Space.Bed(size, GetMaterials(Space.RoomType.Bed), Conditions.StaticComponents);
                Space.RoomRelationShip bedRel = new Space.RoomRelationShip(bed, Space.RelationLevel.First);

                this.ConnectRelation(livingRel, bedRel, Space.ConnectionType.Door);
                this.Register(bedRel);

                beds.Add(bed);
            }

            beds.Sort(); //침실을 크기에 따라 정렬

            //화장실 정의

            for (int i = 0; i < Conditions.RoomSize.RestSizes.Count; i++)
            {
                Space.Room             rest    = new Space.Rest(Conditions.RoomSize.RestSizes[i], GetMaterials(Space.RoomType.Rest), Conditions.StaticComponents);
                Space.RoomRelationShip restRel = new Space.RoomRelationShip(rest, Space.RelationLevel.First);

                if (i == 0)
                {
                    this.ConnectRelation(livingRel, restRel, Space.ConnectionType.Door);
                }
                else
                {
                    if (beds.Count != 0)
                    {
                        Space.Room target = beds.First();
                        this.ConnectRelation(this.Relationships[target.id], restRel, Space.ConnectionType.Door);
                        beds.Remove(target);
                    }
                }

                this.Register(restRel);
            }

            //계단 정의
            Space.Room             stair    = new Space.Stair(new Data.Size(260, 400, Data.Config.RoomHeight), GetMaterials(Space.RoomType.Stair), Conditions.StaticComponents);
            Space.RoomRelationShip stairRel = new Space.RoomRelationShip(stair, Space.RelationLevel.First);

            this.ConnectRelation(livingRel, stairRel, Space.ConnectionType.Open);

            this.Register(stairRel);

            return(stairRel);
        }
Пример #9
0
        //배치의 기준을 잡는 핵심적인 논리파트
        private void GenerateRoomsAndRel()                        //관계를 정의하기 위한 변수를 추가하려면 여기에 추가할 것!
        {
            Space.RoomRelationShip connection = PlanFirstLevel(); //1층을 설계하는데 필요한 변수는 여기에 추가할 것!

            connection = PlanSecondLevel(connection);             //2층을 설계하는데 필요한 변수는 여기에 추가할 것!
        }
Пример #10
0
        //관계도 구분을 고려하며 배치할 수 있도록 개선했다.
        public static List <Blueprint> AddNewRoom(Blueprint blueprint, Space.RoomRelationShip newRelation, Variables conditions)
        {
            Blueprint        PreviousBlueprint = (Blueprint)blueprint.Clone();
            List <Blueprint> PossiblBlueprint  = new List <Blueprint>();

            if (newRelation.Level == Space.RelationLevel.First)
            {
                //1층에 기준 방 배치가 안되어 있으므로, 맵 기준점에 배치한다.
                if (PreviousBlueprint.Relations[newRelation.Level].Count == 0)
                {
                    if (newRelation.Origin is Space.Entrance)
                    {
                        newRelation.Origin.ChangeLocation(PreviousBlueprint.WorldLocation);
                        PreviousBlueprint.Relations[newRelation.Level].Add(newRelation);
                        PossiblBlueprint.Add(PreviousBlueprint);

                        return(PossiblBlueprint);
                    }
                    else
                    {
                        throw new NotImplementedException("Error");
                    }
                }
            }
            else if (newRelation.Level == Space.RelationLevel.Second)
            {
                if (PreviousBlueprint.Relations[newRelation.Level].Count == 0)
                {
                    if (newRelation.Origin is Space.Stair)
                    {
                        //1층에 있던 계단을 찾는다.
                        foreach (Space.RoomRelationShip level in PreviousBlueprint.Relations[Space.RelationLevel.First])
                        {
                            if (level.Origin is Space.Stair)
                            {
                                newRelation.Origin.ChangeLocation(new Data.Cord(level.Origin.Location.X, level.Origin.Location.Y, level.Origin.Location.Z + Data.Config.RoomHeight));

                                foreach (Data.SideCardinalDirection sideDirection in Enum.GetValues(typeof(Data.SideCardinalDirection)))
                                {
                                    foreach (Data.Side levelOneSide in level.Origin.Sides[sideDirection])
                                    {
                                        if (levelOneSide.Type == Data.SideType.Wall)
                                        {
                                            foreach (Data.Side levelTwoSide in newRelation.Origin.Sides[sideDirection])
                                            {
                                                //단순히 타입을 Block으로 바꾸는 것보다는 괜찮은 방법이 필요함.
                                                levelTwoSide.Type = Data.SideType.Window;
                                            }
                                        }
                                    }
                                }

                                PreviousBlueprint.Relations[newRelation.Level].Add((Space.RoomRelationShip)newRelation.Clone());
                                break;
                            }
                        }

                        PossiblBlueprint.Add(PreviousBlueprint);
                        return(PossiblBlueprint);
                    }
                    else
                    {
                        throw new NotImplementedException("Error");
                    }
                }
            }
            else
            {
                throw new NotImplementedException("New Relation Level does not handled.");
            }

            #region 설명

            /*
             *   배치에 제일 핵심이 되는 부분!
             *   1) 배치가능한 SidePart를 검색한다. (현재는 MinimalOverlap보다 긴 Side)
             *   2) 배치가 가능한지 판단을 한다. (Overlap이 되지 않았는지, 관계에 맞게 Cotact하게 배치되었는지)
             *
             *   3) 배치가 가능하면,
             *      (Room의 OccupySide)
             *          - Side를 Occupy한다.
             *          - 새로운 Side 상태를 기록한다.
             *          - 이전 Side 상태도 남긴다.
             *
             *          - Relation에 배치된 공간을 추가한다.
             *          - 새로운 공간이 추가된 도면을 반환할 도면리스트에 추가한다.
             *
             *   4) 배치가 불가능하다면, 다른 SidePart를 탐색하고, 다른 Side와의 가능성도 계산한다.
             *
             *   5) 만약 배치되어 있던 모든 공간의 모든 Side가 불가능하다면,
             *         - NULL 값을 반환한다.
             *   6) 모든 가능성을 탐구하였다면, 가능한 모든 도면리스트를 반환한다.
             *
             */
            #endregion

            //TODO: 1층이라도 Boundary를 체크할 수 있도록 개선할 필요가 있다.
            foreach (Space.RoomRelationShip rel in PreviousBlueprint.Relations[newRelation.Level].ToArray())
            {
                //현재까지 배치된 공간 중, 배치할 공간과 관련이 있는 공간만 해당
                if (newRelation.Relations.ContainsKey(rel.Origin.id))
                {
                    foreach (Data.SideCardinalDirection sidePos in Enum.GetValues(typeof(Data.SideCardinalDirection)))
                    {
                        foreach (Data.Side side in rel.Origin.Sides[sidePos].ToArray())
                        {
                            if (side.IsAvailable(Data.Config.MinimalOverlap))
                            {
                                //sidepart 중 배치가 가능한 부분을 순차적으로 검색하며 찾는 것이 중요.
                                //(2진 검색을 하듯이, Start와 End의 중간값 찾기와 같이 배치할 위치를 찾는다.)
                                List <Data.Cord> avalCords = PreviousBlueprint.GetPosibleCords(newRelation.Origin, side, conditions.is_simple);
                                foreach (Data.Cord cord in avalCords)
                                {
                                    //TODO: Rotate를 한 뒤에도 배치 테스트를 할 수 있도록 개선이 필요하다.

                                    //새로 배치될 수 있는 위치를 시도!
                                    Space.RoomRelationShip CloneRel = (Space.RoomRelationShip)newRelation.Clone();
                                    CloneRel.Origin.ChangeLocation((Data.Cord)cord.Clone()); // 위치를 바꾸기 전에, Side 정보를 복구 또는 저장해놓을 필요가 있다.

                                    //배치 이후에 기존의 공간과의 모순이 없는지 테스트 (Contact와 Overlap 체크)
                                    bool failed = false;

                                    #region CheckOverlap
                                    foreach (Space.RoomRelationShip test in PreviousBlueprint.Relations[newRelation.Level])
                                    {
                                        //이미 배치된 공간과 겹치는지 확인
                                        if (Space.Room.IsOverlap(test.Origin, CloneRel.Origin))
                                        {
                                            failed = true;
                                            break;
                                        }
                                    }
                                    #endregion

                                    #region CheckBoundary
                                    if (!failed)
                                    {
                                    }
                                    #endregion

                                    #region CheckConnect
                                    if (!failed)
                                    {
                                        foreach (Space.RoomRelationShip test in PreviousBlueprint.Relations[newRelation.Level])
                                        {
                                            //새로운 공간과 관계가 있는 공간이 연결되었는지 확인
                                            if (CloneRel.Relations.ContainsKey(test.Origin.id))
                                            {
                                                if (Space.Room.IsContact(CloneRel.Origin, test.Origin, Data.Config.MinimalOverlap))
                                                {
                                                    //Room의 함수로 들어가야 하는 부분
                                                    //겹치게 된 라인을 찾아 점령
                                                    Space.Room.OccupySides(test.Origin, CloneRel.Origin, CloneRel.Relations[test.Origin.id]);
                                                }
                                                else
                                                {
                                                    failed = true;
                                                    break;
                                                }
                                            }
                                        }
                                    }
                                    #endregion

                                    //모든 테스트를 통과했다면,
                                    //  1) 관계도에 포함시킨다.
                                    //  2) 새로운 도면을 출력 리스트에 추가시킨다.
                                    if (!failed)
                                    {
                                        PreviousBlueprint.Relations[newRelation.Level].Add((Space.RoomRelationShip)CloneRel.Clone());
                                        PossiblBlueprint.Add(PreviousBlueprint);
                                        PreviousBlueprint = (Blueprint)blueprint.Clone();
                                    }
                                }
                            }
                        }
                    }
                }
            }

            return(PossiblBlueprint);
        }