public PlacementEngine(List <SmSpace> spaces, double leaseDepth, List <SmLevel> levels, double splitInterval, IList <Polygon> corePolys = null) { _leaseOffset = leaseDepth * _worldScale; medOffset = _leaseOffset * 0.5; splitInterval *= _worldScale; inLvls = levels; coreCrvs = new List <Polygon>(); if (corePolys != null) { foreach (var p in corePolys) { var c = p; coreCrvs.Add(c); } } firstLevel = inLvls.OrderBy(l => l._elevation).ToList()[0]; firstLevel._index = 0; boundary = firstLevel._boundaries[0].mainPoly; // System.IO.File.WriteAllText( "D:/Hypar/offsetTest.json", Newtonsoft.Json.JsonConvert.SerializeObject(boundary)); // var orientation = boundary.ClosedCurveOrientation(Vector3d.ZAxis); var ssspaces = SmSpace.Jitter(spaces, 0.99).ToList(); distinctSpaces = ssspaces.GroupBy(x => x.type).Select(y => y.First()).ToList(); _areas = ssspaces.OrderBy(s => s.sorter).Select(s => s.designArea).ToList(); _spaces = ssspaces.OrderBy(s => s.sorter).Select(s => s.roomNumber.ToString()).ToList(); _PlaceableSpaces = ssspaces; Polyline tempPoly = boundary.ToPolyline(); _boundaryPoly = tempPoly; _BoundaryCurve = boundary.ToPolyline(); Console.WriteLine(boundary.ToString()); _Core = InitCoreCrv(boundary); _SplitInterval = splitInterval; _GlobalIndex = 0; _MainFace = boundary.Difference(_Core); InitWalls(); _PlacedProgramSpaces = new List <SmSpace>(); }
public bool TrimKeep(Polygon trimCrv, Polygon toTrim, SmLevel level, out Polygon crvOut) { bool trimmed = false; crvOut = null; var diffResults = toTrim.Intersection(trimCrv); if (diffResults == null) { return(false); } var findInsidePoly = ReturnInsidePoly(diffResults.ToList(), trimCrv); if (findInsidePoly != null) { trimmed = true; crvOut = findInsidePoly; } return(trimmed); }
/// <summary> /// Adds 'placed spaces' to PlacedSpaces list. /// </summary> /// <param name="firstLvlUnits"></param> /// <param name="offCrv"></param> /// <param name="mainCrv"></param> /// <param name="level"></param> /// <returns></returns> public bool TryProject(List <SmSpace> firstLvlUnits, Polygon offCrv, Polygon mainCrv, SmLevel level) { bool worked = false; for (int i = 0; i < firstLvlUnits.Count; i++) { var dupCrv = new Polygon(firstLvlUnits[i].poly.Vertices); var movedCrv = dupCrv.TransformedPolygon(new Transform(new Vector3(0, 0, offCrv.Centroid().Z))); var pts = movedCrv.Vertices.ToList(); // getting unit crv poly pts string mess; bool inBool = AllPtsIn(offCrv, pts, out mess); int s = -1; var newRmNum = firstLvlUnits[i].roomNumber.ToString().Remove(0, 1).Insert(0, level._index.ToString()); int parsedRmNum; if (Int32.TryParse(newRmNum, out parsedRmNum)) { s = parsedRmNum; } if (inBool) { var unitN = new SmSpace(firstLvlUnits[i].type, s, true, firstLvlUnits[i].designArea, movedCrv); unitN.roomLevel = level; PlacedSpaces.Add(unitN); worked = true; } else if (inBool == false && mess == "trim") { Polygon crvOut; if (TrimKeep(mainCrv, movedCrv, level, out crvOut)) { var designArea = firstLvlUnits[i].designArea; //if it is roughly the same size as the planned unit: if (Math.Abs(crvOut.Area() / designArea) >= 0.75) { var unitN = new SmSpace(firstLvlUnits[i].type, s, true, firstLvlUnits[i].designArea, crvOut); unitN.roomLevel = level; PlacedSpaces.Add(unitN); worked = true; } // else //try finding a closest best unit fit // { // var closestDistinctUnit = FindClosestUnitType(crvOut, distinctSpaces); // if (Math.Abs(crvOut.Area() / closestDistinctUnit.designArea) >= 0.75) // { // var unitN = new SmSpace(closestDistinctUnit.type, s, true, closestDistinctUnit.designArea, crvOut); // unitN.roomLevel = level; // PlacedSpaces.Add(unitN); // worked = true; // } // } } } } return(worked); }
/// <summary> /// Places an apartment mix in a procedurally generated mass. /// </summary> /// <param name="model">The input model.</param> /// <param name="input">The arguments to the execution.</param> /// <returns>A MJProceduralApartmentPlacerOutputs instance containing computed results and the model with any new elements.</returns> public static MJProceduralApartmentPlacerOutputs Execute(Dictionary <string, Model> inputModels, MJProceduralApartmentPlacerInputs input) { if (!inputModels.TryGetValue("Floors", out var levelsModel)) { throw new Exception("No floors created. Please create those first."); } if (!inputModels.TryGetValue("Envelope", out var envelopesss)) { throw new Exception("No envelopes available. Please make sure MJ_ProceduralMass is outputting envelopes."); } var proceduralMassData = envelopesss.AllElementsOfType <ProceduralMassData>().ToArray()[0]; var proceduralCellSize = proceduralMassData.CellSize; //debuggin/ viz things List <ModelCurve> coreSketch = new List <ModelCurve>(); List <SmSpace> placedSpaces = new List <SmSpace>(); List <SmLevel> _levels = new List <SmLevel>(); PlacementEngine engine; //process levels & floor boundary crvs var allFloorProfiles = levelsModel.AllElementsOfType <Floor>().OrderBy(f => f.Elevation).ToList(); var distinctHeights = allFloorProfiles.Select(s => s.Elevation).Distinct(); foreach (var h in distinctHeights) { var lvl = new SmLevel(h); var boundaries = new List <SmFloorBoundary>(); foreach (var fl in allFloorProfiles) { var sBoundary = new SmFloorBoundary(fl.Profile.Perimeter); if (fl.Elevation == h) { boundaries.Add(sBoundary); } } lvl._boundaries = boundaries; _levels.Add(lvl); } ///create unplaced spaces List <SmSpace> allUnitsPreplaced = new List <SmSpace>(); int count = 0; for (int i = 0; i < input.UnitMix.Nodes.Count; i++) { for (int j = 0; j < input.UnitMix.Nodes[i].UnitCount; j++) { allUnitsPreplaced.Add(new SmSpace(i, count, false, input.UnitMix.Nodes[i].UnitArea)); //check to see if 'i' corresponds to the right unit type... count++; } } try { engine = new PlacementEngine(allUnitsPreplaced, (proceduralCellSize - 2.0) * 0.5, _levels, 1.0, input.CorePolygons); Console.WriteLine("cell size: " + proceduralCellSize); var wallCrvs = engine._Walls.Select(s => new ModelCurve(s._curve)).ToList(); var coreCrvs = engine.coreLinesViz.Select(s => new ModelCurve(s._curve)).ToList(); coreSketch.AddRange(coreCrvs); string feedbackString = "No feedback yet..."; engine.RunFirstFloor(input.Seam, out feedbackString); Console.WriteLine($"Main feedback: {feedbackString}"); List <string> debugStack; engine.TryStackBuilding(out debugStack); placedSpaces = engine.PlacedSpaces.ToList(); Console.WriteLine("rooms should be: " + placedSpaces.Count.ToString()); } catch (Exception e) { Console.WriteLine(e.ToString()); } var output = new MJProceduralApartmentPlacerOutputs(placedSpaces.Count, allUnitsPreplaced.Count - placedSpaces.Count); var materials = new Material[input.UnitMix.Nodes.Count]; for (int i = 0; i < input.UnitMix.Nodes.Count; i++) { var col = input.UnitMix.Nodes[i].Color; col.Alpha = 1.0; materials[i] = new Material(input.UnitMix.Nodes[i].SpaceType, col, 0.0f, 0.0f); } for (int i = 0; i < placedSpaces.Count; i++) { var representation = new Representation(new SolidOperation[] { new Extrude(placedSpaces[i].poly.Offset(-0.15)[0], placedSpaces[i].roomLevel._levelHeightToNext - 0.25, Vector3.ZAxis, false) }); var room = new Room(placedSpaces[i].poly.Offset(-0.15)[0], Vector3.ZAxis, $"Unit {placedSpaces[i].roomNumber}", $"{placedSpaces[i].roomNumber}", $"Type {placedSpaces[i].type}", $"{placedSpaces[i].roomNumber}", placedSpaces[i].designArea, 1.0, 0.0, placedSpaces[i].roomLevel._index.ToString(), placedSpaces[i].roomLevel._elevation, placedSpaces[i].roomLevel._levelHeightToNext - 0.25, placedSpaces[i].area, new Transform(0, 0, placedSpaces[i].roomLevel._elevation), materials[placedSpaces[i].type], representation, false, Guid.NewGuid(), ""); output.Model.AddElement(room); } output.Model.AddElements(coreSketch); return(output); }