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); }
/// <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)); }