//gets list of polygon2ds and find the most closest polygon2d to the center , to place the central stn internal static Dictionary <string, object> MakeCentralStation(List <Polygon2d> polygonsList, Point2d centerPt) { if (polygonsList == null || polygonsList.Count == 0) { return(null); } if (polygonsList.Count < 2) { return(new Dictionary <string, object> { { "PolyCentral", (polygonsList) }, { "IndexInPatientPoly", (0) } }); } List <Polygon2d> newPolyLists = new List <Polygon2d>(); List <double> distanceList = new List <double>(); double minArea = 100, ratio = 0.5, dis = 0;; int dir = 0; List <int> indices = PolygonUtility.SortPolygonsFromAPoint(polygonsList, centerPt); Polygon2d polyToPlace = polygonsList[indices[0]]; double area = PolygonUtility.AreaPolygon(polyToPlace); if (area > minArea) { List <double> spans = PolygonUtility.GetSpansXYFromPolygon2d(polyToPlace.Points); if (spans[0] > spans[1]) { dir = 1; dis = spans[0] / 2; } else { dir = 0; dis = spans[1] / 2; } Random ran = new Random(); //Dictionary<string, object> splittedPoly = BasicSplitPolyIntoTwo(polyToPlace, ratio, dir); //Dictionary<string, object> splittedPoly = SplitByDistanceFromPoint(polyToPlace, dis, dir); Dictionary <string, object> splittedPoly = SplitObject.SplitByDistance(polyToPlace, ran, dis, dir); List <Polygon2d> polyReturnedList = (List <Polygon2d>)splittedPoly["PolyAfterSplit"]; if (!ValidateObject.CheckPolyList(polyReturnedList)) { return(null); } List <int> ind = PolygonUtility.SortPolygonsFromAPoint(polyReturnedList, centerPt); newPolyLists.Add(polyReturnedList[ind[0]]); newPolyLists.Add(polyReturnedList[ind[1]]); } else { newPolyLists.Add(polyToPlace); } return(new Dictionary <string, object> { { "PolyCentral", (newPolyLists) }, { "IndexInPatientPoly", (indices[0]) } }); }
//gets a poly and recursively splits it till acceptabledimension is met and makes a polyorganized list internal static void MakePolysOfProportion(Polygon2d poly, List <Polygon2d> polyOrganizedList, List <Polygon2d> polycoverList, double acceptableWidth, double targetArea) { BuildLayout.RECURSE += 1; List <double> spanListXY = PolygonUtility.GetSpansXYFromPolygon2d(poly.Points); double spanX = spanListXY[0], spanY = spanListXY[1]; double aspRatio = spanX / spanY; double lowRange = 0.3, highRange = 2; double maxValue = 0.70, minValue = 0.35; double threshDistanceX = acceptableWidth; double threshDistanceY = acceptableWidth; Random ran = new Random(); bool square = true; double div; div = BasicUtility.RandomBetweenNumbers(BuildLayout.RANGENERATE, maxValue, minValue); if (spanX > threshDistanceX && spanY > threshDistanceY) { square = false; } else { if (aspRatio > lowRange && aspRatio < highRange) { square = false; } else { square = true; } } if (square) { polyOrganizedList.Add(poly); } else { Dictionary <string, object> splitResult; //poly is rectangle so split it into two and add if (spanX > spanY) { double dis = spanY * div; int dir = 1; //splitResult = BasicSplitPolyIntoTwo(poly, 0.5, dir); splitResult = SplitObject.SplitByDistance(poly, ran, dis, dir, BuildLayout.SPACING2); //splitResult = SplitByDistanceFromPoint(poly, dis, dir); } else { double dis = spanX * div; int dir = 0; //splitResult = BasicSplitPolyIntoTwo(poly, 0.5, dir); splitResult = SplitObject.SplitByDistance(poly, ran, dis, dir, BuildLayout.SPACING2); //splitResult = SplitByDistanceFromPoint(poly, dis, dir); } List <Polygon2d> polyAfterSplit = (List <Polygon2d>)splitResult["PolyAfterSplit"]; if (ValidateObject.CheckPolyList(polyAfterSplit)) { double areaPolA = PolygonUtility.AreaPolygon(polyAfterSplit[0]); double areaPolB = PolygonUtility.AreaPolygon(polyAfterSplit[1]); if (areaPolA > targetArea) { polycoverList.Add(polyAfterSplit[0]); } if (areaPolB > targetArea) { polycoverList.Add(polyAfterSplit[1]); } List <double> spanA = PolygonUtility.GetSpansXYFromPolygon2d(polyAfterSplit[0].Points); List <double> spanB = PolygonUtility.GetSpansXYFromPolygon2d(polyAfterSplit[1].Points); //Trace.WriteLine("RECURSE is : " + RECURSE); if (BuildLayout.RECURSE < 1500) { if ((spanA[0] > 0 && spanA[1] > 0) || (spanB[0] > 0 && spanB[1] > 0)) { if (spanA[0] > acceptableWidth && spanA[1] > acceptableWidth) { MakePolysOfProportion(polyAfterSplit[0], polyOrganizedList, polycoverList, acceptableWidth, targetArea); } else { polyOrganizedList.Add(polyAfterSplit[0]); double areaPoly = PolygonUtility.AreaPolygon(polyAfterSplit[0]); } //end of 1st if if (spanB[0] > acceptableWidth && spanB[1] > acceptableWidth) { MakePolysOfProportion(polyAfterSplit[1], polyOrganizedList, polycoverList, acceptableWidth, targetArea); } else { polyOrganizedList.Add(polyAfterSplit[1]); } //end of 2nd if } else { polyOrganizedList.Add(polyAfterSplit[0]); polyOrganizedList.Add(polyAfterSplit[1]); } } } // end of if loop , checkingpolylists } } // end of function
//subdivide a given poly into smaller parts till acceptable width is met, returns list of polydept grids and list of polys to compute circulation public static List <List <Polygon2d> > SplitRecursivelyToSubdividePoly(List <Polygon2d> polyList, double acceptableWidth = 10, double circulationFreq = 10, double ratio = 0.5, bool tag = false) { if (!ValidateObject.CheckPolyList(polyList)) { return(null); } int count = 0; Queue <Polygon2d> polyQueue = new Queue <Polygon2d>(); List <List <Polygon2d> > polyAllReturn = new List <List <Polygon2d> >(); List <Polygon2d> polyBrokenList = new List <Polygon2d>(), polyCirculationList = new List <Polygon2d>(); double totalArea = 0; // cirFac = Math.Ceiling(acceptableWidth/ circulationFreq); double cirFac = circulationFreq; for (int i = 0; i < polyList.Count; i++) { totalArea += PolygonUtility.AreaPolygon(polyList[i]); polyQueue.Enqueue(polyList[i]); } Random rand = new Random(); double targetArea = totalArea / cirFac; while (polyQueue.Count > 0) { Polygon2d currentPoly = polyQueue.Dequeue(); Dictionary <string, object> splitObj = SplitByRatio(currentPoly, ratio, 0); if (tag) { ratio = BasicUtility.RandomBetweenNumbers(rand, 0.7, 0.35); } if (splitObj == null) { continue; } List <Polygon2d> polySplitList = (List <Polygon2d>)splitObj["PolyAfterSplit"]; if (ValidateObject.CheckPolyList(polySplitList) && polySplitList.Count > 1) { polySplitList = PolygonUtility.SmoothPolygonList(polySplitList, 2); Polygon2d bbox1 = Polygon2d.ByPoints(ReadData.FromPointsGetBoundingPoly(polySplitList[0].Points)); Polygon2d bbox2 = Polygon2d.ByPoints(ReadData.FromPointsGetBoundingPoly(polySplitList[1].Points)); if (!ValidateObject.CheckPoly(bbox1) || !ValidateObject.CheckPoly(bbox2)) { continue; } if (PolygonUtility.AreaPolygon(polySplitList[0]) > targetArea) { polyCirculationList.Add(polySplitList[0]); } if (PolygonUtility.AreaPolygon(polySplitList[1]) > targetArea) { polyCirculationList.Add(polySplitList[1]); } if (bbox1.Lines[0].Length < acceptableWidth || bbox1.Lines[1].Length < acceptableWidth) { polyBrokenList.Add(polySplitList[0]); } else { polyQueue.Enqueue(polySplitList[0]); } if (bbox2.Lines[0].Length < acceptableWidth || bbox2.Lines[1].Length < acceptableWidth) { polyBrokenList.Add(polySplitList[1]); } else { polyQueue.Enqueue(polySplitList[1]); } } if (ValidateObject.CheckPolyList(polySplitList) && polySplitList.Count < 2) { Polygon2d bbox1 = Polygon2d.ByPoints(ReadData.FromPointsGetBoundingPoly(polySplitList[0].Points)); if (!ValidateObject.CheckPoly(bbox1)) { continue; } if (bbox1.Lines[0].Length < acceptableWidth || bbox1.Lines[1].Length < acceptableWidth) { polyBrokenList.Add(polySplitList[0]); } if (PolygonUtility.AreaPolygon(polySplitList[0]) > targetArea) { polyCirculationList.Add(polySplitList[0]); } else { polyQueue.Enqueue(polySplitList[0]); } } count += 1; } for (int i = 0; i < polyQueue.Count; i++) { polyBrokenList.Add(polyQueue.Dequeue()); } polyAllReturn.Add(polyBrokenList); polyAllReturn.Add(polyCirculationList); return(polyAllReturn); }
public static Dictionary <string, object> MakeProgCirculationPolys(List <Line2d> circulationNetwork, List <Polygon2d> polyProgList, double circulationWidth = 8, double circulationFrequency = 0.5, int designSeed = 10) { if (!ValidateObject.CheckPolyList(polyProgList)) { return(null); } if (circulationNetwork == null || circulationNetwork.Count == 0) { return(null); } List <Line2d> flatLineList = new List <Line2d>(); List <bool> IsDuplicateList = new List <bool>(); polyProgList = PolygonUtility.SmoothPolygonList(polyProgList, 5); //flatten all the polys in each depts to make it one list List <Polygon2d> circulationPolyList = new List <Polygon2d>(); List <Polygon2d> updatedProgPolyList = new List <Polygon2d>(); List <int> deptIdList = new List <int>(); double allowedCircRatio = 4; List <double> areaProgPolyList = new List <double>(); for (int i = 0; i < polyProgList.Count; i++) { areaProgPolyList.Add(PolygonUtility.AreaPolygon(polyProgList[i])); } double maxArea = areaProgPolyList.Max(); areaProgPolyList.Sort(); int value = (int)(areaProgPolyList.Count / 3); double areaThresh = areaProgPolyList[value]; Random ran = new Random(designSeed); for (int i = 0; i < circulationNetwork.Count; i++) { Line2d splitter = circulationNetwork[i]; double someNumber = BasicUtility.RandomBetweenNumbers(ran, 1, 0); if (someNumber > circulationFrequency) { continue; } for (int j = 0; j < polyProgList.Count; j++) { Polygon2d progPoly = polyProgList[j]; double areaPoly = PolygonUtility.AreaPolygon(progPoly); Point2d midPt = LineUtility.LineMidPoint(splitter); Point2d nudgedMidPt = LineUtility.NudgeLineMidPt(splitter, progPoly, 0.5); bool checkInside = GraphicsUtility.PointInsidePolygonTest(progPoly, nudgedMidPt); if (checkInside) { Dictionary <string, object> splitResult = SplitObject.SplitByLine(progPoly, splitter, circulationWidth); List <Polygon2d> polyAfterSplit = (List <Polygon2d>)(splitResult["PolyAfterSplit"]); if (ValidateObject.CheckPolyList(polyAfterSplit)) { double areaA = PolygonUtility.AreaPolygon(polyAfterSplit[0]), areaB = PolygonUtility.AreaPolygon(polyAfterSplit[1]); if (areaA < areaB) { if (polyAfterSplit[0].Points != null) { if (ValidateObject.CheckPolyBBox(polyAfterSplit[0], allowedCircRatio)) { circulationPolyList.Add(polyAfterSplit[0]); } } updatedProgPolyList.Add(polyAfterSplit[1]); } else { if (polyAfterSplit[1].Points != null) { if (ValidateObject.CheckPolyBBox(polyAfterSplit[1], allowedCircRatio)) { circulationPolyList.Add(polyAfterSplit[1]); } } updatedProgPolyList.Add(polyAfterSplit[0]); } } // end of if loop checking polylist } // end of check inside } // end of for loop j } // end of for loop i return(new Dictionary <string, object> { { "ProgCirculationPoly", (circulationPolyList) } }); }
public static Dictionary <string, object> FindDeptCirculationNetwork(List <DeptData> deptData, Polygon2d leftOverPoly = null, bool noExternalWall = false, double circulationFrequency = 0.75) { if (deptData == null || deptData.Count == 0) { return(null); } double limit = 0; List <Polygon2d> polygonsAllDeptList = new List <Polygon2d>(); List <DeptData> deptDataAllDeptList = new List <DeptData>(); List <List <string> > deptNamesNeighbors = new List <List <string> >(); List <List <Line2d> > lineCollection = new List <List <Line2d> >(); //make flattened list of all dept data and dept polys for (int i = 0; i < deptData.Count; i++) { List <Polygon2d> polyList = deptData[i].PolyAssignedToDept; if (!ValidateObject.CheckPolyList(polyList)) { continue; } for (int j = 0; j < polyList.Count; j++) { polygonsAllDeptList.Add(polyList[j]); deptDataAllDeptList.Add(deptData[i]); } } if (leftOverPoly != null) { polygonsAllDeptList.Add(leftOverPoly); } //else Trace.WriteLine("leftover poly found null, so not added"); List <Line2d> networkLine = new List <Line2d>(); for (int i = 0; i < polygonsAllDeptList.Count; i++) { Polygon2d polyA = polygonsAllDeptList[i]; for (int j = i + 1; j < polygonsAllDeptList.Count; j++) { Polygon2d polyB = polygonsAllDeptList[j]; Dictionary <string, object> checkNeighbor = PolygonUtility.FindPolyAdjacentEdge(polyA, polyB, limit); if (checkNeighbor != null) { if ((bool)checkNeighbor["Neighbour"] == true) { networkLine.Add((Line2d)checkNeighbor["SharedEdge"]); } } } } // if externalWalls not necessary List <Line2d> extraLines = new List <Line2d>(); List <Polygon2d> polyKeyList = new List <Polygon2d>(); if (noExternalWall) { polyKeyList = deptData[0].PolyAssignedToDept; for (int i = 0; i < polyKeyList.Count; i++) { Polygon2d polyA = polyKeyList[i]; for (int j = i + 1; j < polyKeyList.Count; j++) { Polygon2d polyB = polyKeyList[j]; Dictionary <string, object> checkNeighbor = PolygonUtility.FindPolyAdjacentEdgeEdit(polyA, polyB, 0.05); if (checkNeighbor != null) { if ((bool)checkNeighbor["Neighbour"] == true) { networkLine.Add((Line2d)checkNeighbor["SharedEdge"]); extraLines.Add((Line2d)checkNeighbor["SharedEdge"]); } } } } } List <Line2d> cleanNetworkLines = LineUtility.RemoveDuplicateLines(networkLine); // extend the lines found for (int i = 0; i < cleanNetworkLines.Count; i++) { cleanNetworkLines[i] = LineUtility.ExtendLine(cleanNetworkLines[i], 2000); } cleanNetworkLines = RemoveNetworkRedundancy(cleanNetworkLines, circulationFrequency); //return cleanNetworkLines; return(new Dictionary <string, object> { { "CirculationNetworkLines", (cleanNetworkLines) } }); }
public static Dictionary <string, object> MakeDeptCirculationPolys(List <DeptData> deptData, List <List <Line2d> > circulationNetwork, double circulationWidth = 8) { if (deptData == null || deptData.Count == 0 || circulationNetwork == null || circulationNetwork.Count == 0) { return(null); } List <Line2d> cleanLineList = LineUtility.FlattenLine2dList(circulationNetwork); List <Polygon2d> allDeptPolyList = new List <Polygon2d>(); List <Polygon2d> circulationPolyList = new List <Polygon2d>(); List <Polygon2d> updatedDeptPolyList = new List <Polygon2d>(); List <int> deptIdList = new List <int>(); for (int i = 0; i < deptData.Count; i++) { List <Polygon2d> deptPolyList = deptData[i].PolyAssignedToDept; if (!ValidateObject.CheckPolyList(deptPolyList)) { continue; } for (int j = 0; j < deptPolyList.Count; j++) { deptIdList.Add(i); allDeptPolyList.Add(deptPolyList[j]); } } for (int i = 0; i < cleanLineList.Count; i++) { Line2d splitter = cleanLineList[i]; for (int j = 0; j < allDeptPolyList.Count; j++) { Polygon2d deptPoly = allDeptPolyList[j]; Point2d midPt = LineUtility.LineMidPoint(splitter); Point2d nudgedMidPt = LineUtility.NudgeLineMidPt(splitter, deptPoly, 0.5); if (GraphicsUtility.PointInsidePolygonTest(deptPoly, nudgedMidPt)) { Dictionary <string, object> splitResult = SplitObject.SplitByLine(deptPoly, splitter, circulationWidth); List <Polygon2d> polyAfterSplit = (List <Polygon2d>)(splitResult["PolyAfterSplit"]); if (ValidateObject.CheckPolyList(polyAfterSplit)) { double areaA = PolygonUtility.AreaPolygon(polyAfterSplit[0]); double areaB = PolygonUtility.AreaPolygon(polyAfterSplit[1]); if (areaA < areaB) { circulationPolyList.Add(polyAfterSplit[0]); updatedDeptPolyList.Add(polyAfterSplit[1]); } else { circulationPolyList.Add(polyAfterSplit[1]); updatedDeptPolyList.Add(polyAfterSplit[0]); } } } // end of check inside } // end of for loop j } // end of for loop i List <List <Polygon2d> > deptPolyBranchedInList = new List <List <Polygon2d> >(); List <int> distinctIdList = deptIdList.Distinct().ToList(); for (int i = 0; i < distinctIdList.Count; i++) { List <Polygon2d> polyForDeptBranch = new List <Polygon2d>(); for (int j = 0; j < deptIdList.Count; j++) { if (deptIdList[j] == i) { if (j < updatedDeptPolyList.Count) { polyForDeptBranch.Add(updatedDeptPolyList[j]); } } } deptPolyBranchedInList.Add(polyForDeptBranch); } return(new Dictionary <string, object> { { "DeptCirculationPoly", (circulationPolyList) }, { "UpdatedDeptPolys", (deptPolyBranchedInList) } }); }
[MultiReturn(new[] { "DeptData", "LeftOverPolys" })]//"CirculationPolys", "OtherDeptMainPoly" public static Dictionary <string, object> PlaceDepartments2D(List <DeptData> deptData, List <Polygon2d> buildingOutline, List <double> kpuDepthList, List <double> kpuWidthList, double acceptableWidth, double polyDivision = 8, int designSeed = 50, bool noExternalWall = false, bool unlimitedKPU = true, bool mode3D = false, double totalBuildingHeight = 60, double avgFloorHeight = 15) { if (polyDivision >= 1 && polyDivision < 30) { BuildLayout.SPACING = polyDivision; BuildLayout.SPACING2 = polyDivision; } double circulationFreq = 8; List <DeptData> deptDataInp = deptData; deptData = deptDataInp.Select(x => new DeptData(x)).ToList(); // example of deep copy Dictionary <string, object> deptArrangement = new Dictionary <string, object>(); double count = 0, eps = 5; Random rand = new Random(); bool deptPlaced = false; Random ran = new Random(designSeed); bool stackOptionsDept = deptData[0].StackingOptions; bool stackOptionsProg = deptData[0].ProgramsInDept[0].StackingOptions; while (deptPlaced == false && count < BuildLayout.MAXCOUNT)//MAXCOUNT { double parameter = BasicUtility.RandomBetweenNumbers(ran, 0.9, 0.5); if (!stackOptionsDept) { parameter = 0; } //parameter = 0; Trace.WriteLine("PLACE DEPT STARTS , Lets arrange dept again ++++++++++++++++ : " + count); deptArrangement = BuildLayout.DeptPlacer(deptData, buildingOutline, kpuDepthList, kpuWidthList, acceptableWidth, circulationFreq, designSeed, noExternalWall, unlimitedKPU, stackOptionsDept, stackOptionsProg, parameter); if (deptArrangement != null) { List <DeptData> deptDataUpdated = (List <DeptData>)deptArrangement["DeptData"]; List <List <Polygon2d> > deptAllPolys = new List <List <Polygon2d> >(); for (int i = 0; i < deptDataUpdated.Count; i++) { deptAllPolys.Add(deptDataUpdated[i].PolyAssignedToDept); } List <Polygon2d> deptPolysTogether = new List <Polygon2d>(); for (int i = 0; i < deptAllPolys.Count; i++) { if (ValidateObject.CheckPolyList(deptAllPolys[i])) { deptPolysTogether.AddRange(deptAllPolys[i]); } } if (deptAllPolys.Count > 0) { Trace.WriteLine("dept arrangement not null, lets check further"); } for (int i = 0; i < deptAllPolys.Count; i++) { List <Polygon2d> eachDeptPoly = deptAllPolys[i]; if (ValidateObject.CheckPolyList(eachDeptPoly)) { deptPlaced = true; } else { deptPlaced = false; Trace.WriteLine("dept arrangement bad polys, rejected"); break; } bool orthoResult = ValidateObject.CheckPolygon2dListOrtho(deptPolysTogether, eps); Trace.WriteLine("The poly formed is : " + orthoResult); if (orthoResult) { deptPlaced = true; } else { deptPlaced = false; Trace.WriteLine("dept arrangement non orthogonal, rejected"); break; } } } else { deptPlaced = false; designSeed += 1; Trace.WriteLine("DeptPlacer returned null, rejected for: " + count); } count += 1; Trace.WriteLine(" EXIT PLACE DEPARTMENTS +++++++++++++++++++++++++++++++++"); }// end of while loop return(deptArrangement); }