private void AddMember(Fitting newMember)
        {
            newMember.ChangePlacementUnit(this);

            Members.Add(newMember);

            foreach (ParticularFace face in newMember.Faces)
            {
                TestForExtremePositions(face.FaceCenterPosition + face.NormalVector * face.Fitting.FittingModel.GetClearanceAreaLength(face.Face.Facing));
            }
        }
        // Constructor

        public ParticularFace(Fitting fitting, Face face, float sideLength)
        {
            Fitting    = fitting;
            Face       = face;
            SideLength = sideLength;
        }
        // Constructor

        public PlacementUnit(Fitting member)
        {
            Members = new List <Fitting>();
            AddMember(member);
        }
Exemplo n.º 4
0
        /// <summary>Generate fitting layout consisting of the fittings and their placements</summary>
        private FittingLayout GenerateFittingLayout(Room room, List <FittingModel> fittingModelsToBePlaced, int randomizationSeed = 0)
        {
            // Make sure fitting semantics are loaded
            if (!hasSemanticsLoaded)
            {
                LoadFittingSemantics(DefaultSemanticsFilePath);
            }

            // Start a Random instance
            Random globalRandom;

            if (randomizationSeed == 0)
            {
                // Base randomization on time seed, if no seed given
                globalRandom = new Random();
            }
            else
            {
                globalRandom = new Random(randomizationSeed);
            }


            // Solve placements

            // Register fittings and their faces
            List <Fitting>        fittingsToBePlaced = new List <Fitting>();
            List <ParticularFace> fittingsFaces      = new List <ParticularFace>();

            foreach (FittingModel fittingModelToBePlaced in fittingModelsToBePlaced)
            {
                Fitting fittingToBePlaced = new Fitting(fittingModelToBePlaced);
                fittingsToBePlaced.Add(fittingToBePlaced);

                foreach (ParticularFace fittingFace in fittingToBePlaced.Faces)
                {
                    fittingsFaces.Add(fittingFace);
                }
            }


            // Assign attacher faces to compatible support faces

            // List to be filled with up to one face with wall relation per fitting, that is selected to be satisfied
            List <Tuple <ParticularFace, SpatialRelation> > selectedAttacherFacesAndWallRelations = new List <Tuple <ParticularFace, SpatialRelation> >();

            foreach (Fitting fittingToBePlaced in fittingsToBePlaced)
            {
                // List to be filled with faces with fitting relations that can be satisfied
                List <Tuple <ParticularFace, ParticularFace, SpatialRelation> > attacherFacesAndSupportFacesAndRelations = new List <Tuple <ParticularFace, ParticularFace, SpatialRelation> >();
                int fittingRelationCount = 0;

                // List to be filled with faces with wall relations
                List <Tuple <ParticularFace, SpatialRelation> > attacherFacesAndWallRelations = new List <Tuple <ParticularFace, SpatialRelation> >();

                // Go through every relation in the fitting's faces, and register satisfiable ones
                foreach (ParticularFace aFace in fittingToBePlaced.Faces)
                {
                    foreach (SpatialRelation relation in aFace.Face.Type.SpatialRelations)
                    {
                        if (relation.SupportFaceType == wallFaceType || relation.SupportFaceType == doorFaceType || relation.SupportFaceType == windowFaceType)
                        {
                            if (relation.SupportFaceType == wallFaceType)
                            {
                                // Register wall related face
                                attacherFacesAndWallRelations.Add(new Tuple <ParticularFace, SpatialRelation>(aFace, relation));
                            }
                        }
                        else
                        {
                            fittingRelationCount++;

                            // Register found support faces
                            List <ParticularFace> supportFaces = new List <ParticularFace>();
                            foreach (ParticularFace sFace in fittingsFaces)
                            {
                                if (sFace.Face.Type == relation.SupportFaceType)
                                {
                                    supportFaces.Add(sFace);
                                }
                            }

                            // Assign support faces to fulfill relation
                            if (supportFaces.Count > 0)
                            {
                                // Pick a random support face as the default and check if there are less occupied ones
                                int            startIndex             = globalRandom.Next() % supportFaces.Count;
                                ParticularFace minOccupiedSupportFace = supportFaces[startIndex];
                                foreach (ParticularFace supportFace in supportFaces)
                                {
                                    if (supportFace.ReservedLength < minOccupiedSupportFace.ReservedLength)
                                    {
                                        minOccupiedSupportFace = supportFace;
                                    }
                                }

                                if (minOccupiedSupportFace.CanAttachFace(aFace, relation))
                                {
                                    // Register face pair that satisfies relation
                                    attacherFacesAndSupportFacesAndRelations.Add(new Tuple <ParticularFace, ParticularFace, SpatialRelation>(aFace, minOccupiedSupportFace, relation));
                                }
                                else
                                {
                                    // Pick a random support face as the default and check if there are freer ones
                                    startIndex = globalRandom.Next() % supportFaces.Count;
                                    ParticularFace mostFreeSupportFace = supportFaces[startIndex];
                                    foreach (ParticularFace supportFace in supportFaces)
                                    {
                                        if (supportFace.SideLength - supportFace.ReservedLength > mostFreeSupportFace.SideLength - mostFreeSupportFace.ReservedLength)
                                        {
                                            mostFreeSupportFace = supportFace;
                                        }
                                    }

                                    if (mostFreeSupportFace.CanAttachFace(aFace, relation))
                                    {
                                        // Register face pair that satisfies relation
                                        attacherFacesAndSupportFacesAndRelations.Add(new Tuple <ParticularFace, ParticularFace, SpatialRelation>(aFace, mostFreeSupportFace, relation));
                                    }
                                }
                            }
                        }
                    }
                }

                // Assign one fitting attacher face to its support face
                if (attacherFacesAndSupportFacesAndRelations.Count() > 0)
                {
                    // Pick only one fitting relation to fulfill per fitting
                    int pickedIndex = globalRandom.Next() % attacherFacesAndSupportFacesAndRelations.Count;
                    Tuple <ParticularFace, ParticularFace, SpatialRelation> attacherFaceAndSupportFaceAndRelation = attacherFacesAndSupportFacesAndRelations[pickedIndex];
                    attacherFaceAndSupportFaceAndRelation.Item2.AttachFace(attacherFaceAndSupportFaceAndRelation.Item1, attacherFaceAndSupportFaceAndRelation.Item3);
                }
                else if (fittingRelationCount > 0)
                {
                    Console.WriteLine("No fitting support face with capacity could be found for a {0} {1}. ", fittingToBePlaced.FittingModel.Id, fittingToBePlaced.FittingModel.FittingType.Id);
                }

                // Pick only one wall relation to fulfill per fitting
                if (attacherFacesAndWallRelations.Count > 0)
                {
                    int selectedIndex = globalRandom.Next() % attacherFacesAndWallRelations.Count;
                    selectedAttacherFacesAndWallRelations.Add(attacherFacesAndWallRelations[selectedIndex]);
                }
            }

            // Place attacher faces (and their fittings with them) in relation to support faces, in grouping placement units
            foreach (ParticularFace sFace in fittingsFaces)
            {
                foreach (Tuple <ParticularFace, SpatialRelation> aFaceAndRelation in sFace.attacherFacesAndRelations)
                {
                    ParticularFace  aFace    = aFaceAndRelation.Item1;
                    SpatialRelation relation = aFaceAndRelation.Item2;

                    // Rotate objects to match faces
                    aFace.RotateToFace(sFace.Direction);

                    // Move objects to match face distance
                    aFace.TranslateToDistanceFromFace(relation.Distance, sFace);

                    // Merge placement units
                    sFace.Fitting.PlacementUnit.AbsorbPlacementUnit(aFace.Fitting.PlacementUnit);
                }
            }

            // Register wall-attacher faces to placement units
            foreach (Tuple <ParticularFace, SpatialRelation> attacherFaceAndWallRelation in selectedAttacherFacesAndWallRelations)
            {
                attacherFaceAndWallRelation.Item1.Fitting.PlacementUnit.AddWallConstraint(attacherFaceAndWallRelation.Item1, attacherFaceAndWallRelation.Item2.Distance);
            }

            // Register all consolidated placement units
            List <PlacementUnit> placementUnits = new List <PlacementUnit>();

            foreach (Fitting fitting in fittingsToBePlaced)
            {
                if (!placementUnits.Contains(fitting.PlacementUnit))
                {
                    placementUnits.Add(fitting.PlacementUnit);
                }
            }

            // Set placement domains for the placement units
            foreach (PlacementUnit placementUnit in placementUnits)
            {
                // Set placement domain
                placementUnit.SetDomain(room);

                // Shuffle placement domain
                placementUnit.ShuffleDomain(globalRandom);
            }

            // Test placements for all placement units
            if (!TestPlacements(ref placementUnits, room.Clone()))
            {
                // No possible fitting layout could be found
                Console.WriteLine("No possible fitting layout could be found. ");
                return(new FittingLayout(room, new List <Fitting>()));
            }

            // Return finished list of placed fittings
            return(new FittingLayout(room, fittingsToBePlaced));
        }