//returns the highest and lowest point along with indices from a pointlist internal static Dictionary <string, object> ReturnHighestAndLowestPointofBBox(Polygon2d poly) { Range2d range = PolygonUtility.GetRang2DFromBBox(ReadData.FromPointsGetBoundingPoly(poly.Points)); double minX = range.Xrange.Min; double maxX = range.Xrange.Max; double minY = range.Yrange.Min; double maxY = range.Yrange.Max; Point2d lowPt = new Point2d(minX, minY), hipt = new Point2d(maxX, maxY); return(new Dictionary <string, object> { { "LowerPoint", (lowPt) }, { "HigherPoint", (hipt) }, }); }
internal static Dictionary <string, object> ExtLinesAndOffsetsFromBBox(Polygon2d poly, double patientRoomDepth = 16, double recompute = 5) { if (!ValidateObject.CheckPoly(poly)) { return(null); } Polygon2d polyReg = new Polygon2d(poly.Points); List <Line2d> allSplitLines = new List <Line2d>(); Polygon2d polyBBox = Polygon2d.ByPoints(ReadData.FromPointsGetBoundingPoly(polyReg.Points)); allSplitLines = polyBBox.Lines; List <double> splitLineLength = new List <double>(); for (int i = 0; i < allSplitLines.Count; i++) { splitLineLength.Add(allSplitLines[i].Length); } List <int> sortedIndices = BasicUtility.Quicksort(splitLineLength); if (sortedIndices != null) { sortedIndices.Reverse(); } List <Line2d> offsetLines = new List <Line2d>(); List <Point2d> midPtsOffsets = new List <Point2d>(); for (int i = 0; i < allSplitLines.Count; i++) { offsetLines.Add(LineUtility.Offset(allSplitLines[i], patientRoomDepth)); midPtsOffsets.Add(LineUtility.NudgeLineMidPt(allSplitLines[i], poly, patientRoomDepth)); } List <Line2d> offsetSortedLines = new List <Line2d>(); for (int i = 0; i < offsetLines.Count; i++) { offsetSortedLines.Add(offsetLines[sortedIndices[i]]); } return(new Dictionary <string, object> { { "SplittableLines", (allSplitLines) }, { "OffsetLines", (offsetSortedLines) }, { "SortedIndices", (sortedIndices) }, { "OffsetMidPts", (midPtsOffsets) } }); }
//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); }
//Builds Dept Topology Matrix , finds all the shared edges between dept polys, and updates department polygon2d's. /// <summary> /// Builds the department topology matrix internally and finds circulation network lines between department polygon2d's. /// </summary> /// <param name="deptData">DeptData Object</param> /// <param name="leftOverPoly">Polygon2d not assigned to any department.</param> /// <param name="limit">Maximum distance allowed to be considered as a neighbor of a department.</param> /// <returns name="CirculationNetwork">List of line2d geometry representing circulation network between department polygon2d's.</returns> /// <search> /// Department Circulation Network, Shared Edges between departments /// </search> internal static List <Line2d> RemoveNetworkRedundancy(List <Line2d> networkLines, double circulationFrequency = 10) { if (networkLines == null) { return(null); } circulationFrequency = 1 - circulationFrequency; Polygon2d bBox = ReadData.GetBoundingBoxfromLines(networkLines); List <double> spans = PolygonUtility.GetSpansXYFromPolygon2d(bBox.Points);// horizontal span 1st, then vertical span List <Line2d> horizLines = new List <Line2d>(), vertLines = new List <Line2d>(); for (int i = 0; i < networkLines.Count; i++) { if (ValidateObject.CheckLineOrient(networkLines[i]) == 0) { horizLines.Add(networkLines[i]); } else if (ValidateObject.CheckLineOrient(networkLines[i]) == 1) { vertLines.Add(networkLines[i]); } } List <Line2d> selectedHorizLines = new List <Line2d>(), selectedVertLines = new List <Line2d>(); for (int i = 0; i < horizLines.Count; i++) { double thresDistance = circulationFrequency * spans[0]; int a = i, b = i + 1; if (i == horizLines.Count - 1) { b = 0; } Point2d midA = LineUtility.LineMidPoint(horizLines[a]), midB = LineUtility.LineMidPoint(horizLines[b]); double xDist = Math.Abs(midA.Y - midB.Y); if (xDist > thresDistance) { selectedHorizLines.Add(horizLines[a]); } } for (int i = 0; i < vertLines.Count; i++) { double thresDistance = circulationFrequency * spans[1]; int a = i, b = i + 1; if (i == vertLines.Count - 1) { b = 0; } Point2d midA = LineUtility.LineMidPoint(vertLines[a]), midB = LineUtility.LineMidPoint(vertLines[b]); double yDist = Math.Abs(midA.X - midB.X); if (yDist > thresDistance) { selectedVertLines.Add(vertLines[a]); } } List <Line2d> reducedLines = new List <Line2d>(); reducedLines.AddRange(selectedHorizLines); reducedLines.AddRange(selectedVertLines); return(reducedLines); }