//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]) } }); }
//checks a polygon2d to have min Area and min dimensions internal static bool CheckPolyDimension(Polygon2d poly, double minArea = 6, double side = 2) { if (!CheckPoly(poly)) { return(false); } if (PolygonUtility.AreaPolygon(poly) < minArea) { return(false); } List <double> spans = PolygonUtility.GetSpansXYFromPolygon2d(poly.Points); if (spans[0] < side) { return(false); } if (spans[1] < side) { return(false); } return(true); }
//checsk the aspect ratio of polygons internal static bool CheckPolyAspectRatio(Polygon2d poly, double minDimensionAllowed = 5) { if (!CheckPoly(poly)) { return(false); } List <double> spans = PolygonUtility.GetSpansXYFromPolygon2d(poly.Points); if (spans.Count > 1) { if (spans[0] < minDimensionAllowed || spans[1] < minDimensionAllowed) { return(false); } double aspectRatio = spans[0] / spans[1]; if (aspectRatio < 1) { aspectRatio = 1 / aspectRatio; } if (aspectRatio > 5) { return(false); } if (aspectRatio > 1.5) { double areaShouldBe = spans[0] * spans[1]; double areaPoly = PolygonUtility.AreaPolygon(poly); if (areaPoly / areaShouldBe < 0.9) { return(false); } } } return(true); }
//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
public static Dictionary <string, object> SplitByRatio(Polygon2d polyOutline, double ratio = 0.5, int dir = 0) { if (polyOutline == null) { return(null); } if (polyOutline != null && polyOutline.Points == null) { return(null); } double extents = 5000; double minimumLength = 2, minWidth = 10, aspectRatio = 0, eps = 0.1; List <Point2d> polyOrig = polyOutline.Points; List <Point2d> poly = PolygonUtility.SmoothPolygon(polyOrig, BuildLayout.SPACING); List <double> spans = PolygonUtility.GetSpansXYFromPolygon2d(poly); double horizontalSpan = spans[0], verticalSpan = spans[1]; Point2d polyCenter = PolygonUtility.CentroidOfPoly(Polygon2d.ByPoints(poly)); if (horizontalSpan < minimumLength || verticalSpan < minimumLength) { return(null); } if (horizontalSpan > verticalSpan) { dir = 1; aspectRatio = horizontalSpan / verticalSpan; } else { dir = 0; aspectRatio = verticalSpan / horizontalSpan; } // adjust ratio if (ratio < 0.15) { ratio = ratio + eps; } if (ratio > 0.85) { ratio = ratio - eps; } if (horizontalSpan < minWidth || verticalSpan < minWidth) { ratio = 0.5; } Line2d splitLine = new Line2d(polyCenter, extents, dir); double shift = ratio - 0.5; if (dir == 0) { splitLine = LineUtility.Move(splitLine, 0, shift * verticalSpan); } else { splitLine = LineUtility.Move(splitLine, shift * horizontalSpan, 0); } Dictionary <string, object> intersectionReturn = MakeIntersections(poly, splitLine, BuildLayout.SPACING); List <Point2d> intersectedPoints = (List <Point2d>)intersectionReturn["IntersectedPoints"]; List <Polygon2d> splittedPoly = (List <Polygon2d>)intersectionReturn["PolyAfterSplit"]; return(new Dictionary <string, object> { { "PolyAfterSplit", (splittedPoly) }, { "SplitLine", (splitLine) }, { "IntersectedPoints", (intersectedPoints) } }); }
//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); }