//sorts a list of points form a polyline public static List <Point2d> SortPoints(List <Point2d> pointList) { if (!ValidateObject.CheckPointList(pointList)) { return(null); } Point2d cen = PolygonUtility.CentroidOfPoly(Polygon2d.ByPoints(pointList)); Vector2d vecX = new Vector2d(0, 100); List <double> angList = new List <double>(); int[] indList = new int[pointList.Count]; for (int i = 0; i < pointList.Count; i++) { Vector2d CenterToPt = new Vector2d(cen, pointList[i]); double dotValue = vecX.Dot(CenterToPt); double angValue = Math.Atan2(CenterToPt.Y - vecX.Y, CenterToPt.X - vecX.X); angList.Add(angValue); indList[i] = i; } List <int> newIndexList = new List <int>(); newIndexList = BasicUtility.SortIndex(angList); List <Point2d> sortedPointList = new List <Point2d>(); for (int i = 0; i < pointList.Count; i++) { sortedPointList.Add(pointList[newIndexList[i]]); } return(sortedPointList); }
//check if a given polygon2d has any of its longer edges aligned with any edge of the containerpolygon2d internal static bool CheckLineGetsExternalWall(Line2d lineA, Polygon2d containerPoly) { bool check = false; if (!ValidateObject.CheckPoly(containerPoly)) { return(check); } Polygon2d containerPolyReg = new Polygon2d(containerPoly.Points); for (int i = 0; i < containerPoly.Points.Count; i++) { int a = i, b = i + 1; if (i == containerPolyReg.Points.Count - 1) { b = 0; } Line2d lineB = Line2d.ByStartPointEndPoint(containerPolyReg.Points[a], containerPolyReg.Points[b]); check = GraphicsUtility.LineAdjacencyCheck(lineA, lineB); if (check) { break; } } return(check); }
//checks if two lines are collinear or not public static bool LineAdjacencyCheck(Line2d lineA, Line2d lineB, double eps = 0) { Point2d pA = lineA.StartPoint, qA = lineA.EndPoint; Point2d pB = lineB.StartPoint, qB = lineB.EndPoint; Vector2d vecA = new Vector2d(pA, qA), vecB = new Vector2d(pB, qB); double crossMag = vecA.Cross(vecB); if (crossMag != 0) { return(false); } bool checkA1 = ValidateObject.CheckOnSegment(lineB, pA), checkA2 = ValidateObject.CheckOnSegment(lineB, qA); bool checkB1 = ValidateObject.CheckOnSegment(lineA, pB), checkB2 = ValidateObject.CheckOnSegment(lineA, qB); if (checkA1 || checkA2) { return(true); } if (checkB1 || checkB2) { return(true); } return(false); }
public static Dictionary <string, object> SplitByDistance(Polygon2d polyOutline, Random ran, double distance = 10, int dir = 0, double spacing = 0) { if (!ValidateObject.CheckPoly(polyOutline)) { return(null); } double extents = 5000, spacingProvided; List <Point2d> polyOrig = polyOutline.Points; if (spacing == 0) { spacingProvided = BuildLayout.SPACING; } else { spacingProvided = spacing; } List <Point2d> poly = PolygonUtility.SmoothPolygon(polyOrig, spacingProvided); if (!ValidateObject.CheckPointList(poly)) { return(null); } Dictionary <int, object> obj = PointUtility.PointSelector(ran, poly); Point2d pt = (Point2d)obj[0]; int orient = (int)obj[1]; Line2d splitLine = new Line2d(pt, extents, dir); // push this line right or left or up or down based on ratio if (dir == 0) { splitLine = LineUtility.Move(splitLine, 0, orient * distance); } else { splitLine = LineUtility.Move(splitLine, orient * distance, 0); } Dictionary <string, object> intersectionReturn = MakeIntersections(poly, splitLine, spacingProvided); List <Point2d> intersectedPoints = (List <Point2d>)intersectionReturn["IntersectedPoints"]; List <Polygon2d> splittedPoly = (List <Polygon2d>)intersectionReturn["PolyAfterSplit"]; List <Point2d> ptA = (List <Point2d>)intersectionReturn["PointASide"]; List <Point2d> ptB = (List <Point2d>)intersectionReturn["PointBSide"]; Polygon2d polyA = new Polygon2d(ptA, 0), polyB = new Polygon2d(ptB, 0); //List<Polygon2d> splittedPoly = new List<Polygon2d>(); //splittedPoly.Add(polyA); splittedPoly.Add(polyB); return(new Dictionary <string, object> { { "PolyAfterSplit", (splittedPoly) }, { "SplitLine", (splitLine) }, { "IntersectedPoints", (intersectedPoints) }, { "PointASide", (ptA) }, { "PointBSide", (ptB) } }); }
//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]) } }); }
//check if a given polygon2d has any of its longer edges aligned with any edge of the containerpolygon2d internal static bool CheckPolyGetsExternalWall(Polygon2d poly, Polygon2d containerPoly, double shortEdgeDist = 16, bool tag = true) { bool check = false; if (!ValidateObject.CheckPoly(poly)) { return(check); } Polygon2d polyReg = new Polygon2d(null); //make given polys reduce number of points if (tag) { polyReg = new Polygon2d(poly.Points); } else { polyReg = poly; } Polygon2d containerPolyReg = new Polygon2d(containerPoly.Points); for (int i = 0; i < polyReg.Points.Count; i++) { int a = i, b = i + 1; double eps = 0; if (i == polyReg.Points.Count - 1) { b = 0; } double distance = PointUtility.DistanceBetweenPoints(polyReg.Points[a], polyReg.Points[b]); List <double> spansSorted = PolygonUtility.GetPolySpan(containerPolyReg); if (distance <= spansSorted[0] * 0.75) { continue; } Line2d lineA = Line2d.ByStartPointEndPoint(polyReg.Points[a], polyReg.Points[b]); for (int j = 0; j < containerPolyReg.Points.Count; j++) { int c = j, d = j + 1; if (j == containerPolyReg.Points.Count - 1) { d = 0; } Line2d lineB = Line2d.ByStartPointEndPoint(containerPolyReg.Points[c], containerPolyReg.Points[d]); check = GraphicsUtility.LineAdjacencyCheck(lineA, lineB, eps); if (check) { break; } } if (check) { break; } } return(check); }
//offsets an input line by a given distance inside a poly public static Line2d OffsetLineInsidePoly(Line2d lineInp, Polygon2d poly, double distance) { if (lineInp == null || !ValidateObject.CheckPoly(poly)) { return(null); } Point2d ptStart = OffsetLinePointInsidePoly(lineInp, lineInp.StartPoint, poly, distance); Vector2d vec = new Vector2d(lineInp.StartPoint, ptStart); Point2d ptEnd = VectorUtility.VectorAddToPoint(lineInp.EndPoint, vec); return(new Line2d(ptStart, ptEnd)); }
//offsets an input point by a given distance inside a poly internal static Point2d OffsetLinePointInsidePoly(Line2d lineInp, Point2d testPoint, Polygon2d poly, double distance) { if (lineInp == null || !ValidateObject.CheckPoly(poly)) { return(null); } int dir = DirectionForPointInPoly(lineInp, poly, distance); if (dir == 0) { return(null); } return(OffsetLinePoint(lineInp, testPoint, dir * distance)); }
//returns the points on the required side of a given line, 0 is left or up, 1 is right or down internal static List <Point2d> PointOnSide(Line2d line, List <Point2d> ptList, int side) { if (line == null || !ValidateObject.CheckPointList(ptList)) { return(null); } List <Point2d> selectedPts = new List <Point2d>(); if (side == 0) { } return(selectedPts); }
//offsets an input point by a given distance internal static Point2d OffsetLinePoint(Line2d lineInp, Point2d testPoint, double distance) { double newX1 = 0, newY1 = 0; if (ValidateObject.CheckLineOrient(lineInp) == 0) // horizontal line { newX1 = testPoint.X; newY1 = testPoint.Y + distance; } else // vertical line { newX1 = testPoint.X + distance; newY1 = testPoint.Y; } return(new Point2d(newX1, newY1)); }
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) } }); }
public static Dictionary <string, object> SplitByLine(Polygon2d polyOutline, Line2d inputLine, double distance = 5) { if (!ValidateObject.CheckPoly(polyOutline)) { return(null); } List <Point2d> polyOrig = polyOutline.Points; List <Point2d> poly = PolygonUtility.SmoothPolygon(polyOrig, BuildLayout.SPACING); Line2d splitLine = new Line2d(inputLine); Point2d centerPoly = PointUtility.CentroidInPointLists(poly); bool checkSide = ValidateObject.CheckPointSide(splitLine, centerPoly); int orient = ValidateObject.CheckLineOrient(splitLine); if (orient == 0) { if (!checkSide) { splitLine = LineUtility.Move(splitLine, 0, -1 * distance); } else { splitLine = LineUtility.Move(splitLine, 0, 1 * distance); } } else { if (checkSide) { splitLine = LineUtility.Move(splitLine, -1 * distance, 0); } else { splitLine = LineUtility.Move(splitLine, 1 * distance, 0); } } Dictionary <string, object> intersectionReturn = MakeIntersections(poly, splitLine, BuildLayout.SPACING); List <Polygon2d> splittedPoly = (List <Polygon2d>)intersectionReturn["PolyAfterSplit"]; return(new Dictionary <string, object> { { "PolyAfterSplit", (splittedPoly) }, { "SplitLine", (splitLine) } }); }
} // end of function //makes intersections and returns the two polygon2ds after intersection internal static Dictionary <string, object> MakeIntersections(List <Point2d> poly, Line2d splitLine, double space = 0) { List <Point2d> intersectedPoints = GraphicsUtility.LinePolygonIntersection(poly, splitLine); //List<Point2d> intersectedPoints = TestGraphicsUtility.LinePolygonIntersectionIndex(poly, splitLine); // find all points on poly which are to the left or to the right of the line List <int> pIndexA = new List <int>(); List <int> pIndexB = new List <int>(); for (int i = 0; i < poly.Count; i++) { bool check = ValidateObject.CheckPointSide(splitLine, poly[i]); if (check) { pIndexA.Add(i); } else { pIndexB.Add(i); } } //organize the points to make closed poly List <Point2d> sortedA = PointUtility.DoSortClockwise(poly, intersectedPoints, pIndexA); List <Point2d> sortedB = PointUtility.DoSortClockwise(poly, intersectedPoints, pIndexB); /*List<Polygon2d> splittedPoly = new List<Polygon2d>(); * if (space == 0) splittedPoly = new List<Polygon2d> { new Polygon2d(sortedA, 0), new Polygon2d(sortedB, 0) }; * else * { * sortedA = PolygonUtility.SmoothPolygon(new Polygon2d(sortedA,0).Points, space); * sortedB = PolygonUtility.SmoothPolygon(new Polygon2d(sortedB,0).Points, space); * splittedPoly = new List<Polygon2d> { new Polygon2d(sortedA, 0), new Polygon2d(sortedB, 0) }; * } */ List <Polygon2d> splittedPoly = new List <Polygon2d> { new Polygon2d(sortedA, 0), new Polygon2d(sortedB, 0) }; return(new Dictionary <string, object> { { "PolyAfterSplit", (splittedPoly) }, { "IntersectedPoints", (intersectedPoints) }, { "PointASide", (sortedA) }, { "PointBSide", (sortedB) } }); }
//################################################################################################################ //this class stores methods realted to GraphicsUtility class which needs to be tested further for reliability //################################################################################################################ // checks if two lines are collinear - not using internal static bool CheckLineCollinear(Line2d lineA, Line2d lineB) { Point2d p1 = lineA.StartPoint; Point2d p2 = lineA.EndPoint; Point2d q1 = lineB.StartPoint; Point2d q2 = lineB.EndPoint; // Find the four orientations needed for general and special cases int o1 = GraphicsUtility.Orientation(p1, q1, p2); int o2 = GraphicsUtility.Orientation(p1, q1, q2); int o3 = GraphicsUtility.Orientation(p2, q2, p1); int o4 = GraphicsUtility.Orientation(p2, q2, q1); // General case if (o1 != o2 && o3 != o4) { return(false); } // p1, q1 and p2 are colinear and p2 lies on segment p1q1 if (o1 == 0 && ValidateObject.CheckOnSegment(p1, p2, q1)) { return(true); } // p1, q1 and p2 are colinear and q2 lies on segment p1q1 if (o2 == 0 && ValidateObject.CheckOnSegment(p1, q2, q1)) { return(true); } // p2, q2 and p1 are colinear and p1 lies on segment p2q2 if (o3 == 0 && ValidateObject.CheckOnSegment(p2, p1, q2)) { return(true); } // p2, q2 and q1 are colinear and q1 lies on segment p2q2 if (o4 == 0 && ValidateObject.CheckOnSegment(p2, q1, q2)) { return(true); } return(false); // Doesn't fall in any of the above cases }
//offsets an input line by a given distance internal static int DirectionForPointInPoly(Line2d lineInp, Polygon2d poly, double distance) { if (lineInp == null || !ValidateObject.CheckPoly(poly)) { return(0); } Point2d midPt = LineMidPoint(lineInp); Point2d pt1 = OffsetLinePoint(lineInp, midPt, distance); Point2d pt2 = OffsetLinePoint(lineInp, midPt, -1 * distance); if (GraphicsUtility.PointInsidePolygonTest(poly, pt1)) { return(1); } else { return(-1); } }
internal static Polygon2d AddpointToPoly(Polygon2d poly, int lineId = 0) { if (!ValidateObject.CheckPoly(poly)) { return(null); } List <Point2d> ptList = new List <Point2d>(); for (int i = 0; i < poly.Points.Count; i++) { if (i == lineId) { Line2d line = poly.Lines[lineId]; } ptList.Add(poly.Points[i]); } return(null); }
//returns the point having lowest x,y value from a list using now internal static int LowestPointFromList(List <Point2d> ptList) { if (!ValidateObject.CheckPointList(ptList)) { return(-1); } Point2d lowestPoint = ptList[0]; int size = ptList.Count; int index = 0; for (int i = 0; i < size; i++) { if ((lowestPoint.X > ptList[i].X) || (lowestPoint.X == ptList[i].X && lowestPoint.Y > ptList[i].Y)) { lowestPoint = ptList[i]; index = i; } } return(index); }
//checks if a point is inside a polygon or not public static bool PointInsidePolygonTest(Polygon2d poly, Point2d testPoint) { if (!ValidateObject.CheckPoly(poly) || testPoint == null) { return(false); } bool check = false; List <Point2d> pointsPolygon = poly.Points; int numPolyPts = pointsPolygon.Count; for (int i = 0, j = numPolyPts - 1; i < numPolyPts; j = i++) { if (((pointsPolygon[i].Y > testPoint.Y) != (pointsPolygon[j].Y > testPoint.Y)) && (testPoint.X < (pointsPolygon[j].X - pointsPolygon[i].X) * (testPoint.Y - pointsPolygon[i].Y) / (pointsPolygon[j].Y - pointsPolygon[i].Y) + pointsPolygon[i].X)) { check = !check; } } return(check); }
//returns the point having highest x,y value from a list - using now internal static int ReturnHighestPointFromList(List <Point2d> ptList) { if (!ValidateObject.CheckPointList(ptList)) { return(-1); } Point2d highestPoint = ptList[0]; int size = ptList.Count; int index = 0; for (int i = 0; i < size; i++) { if ((highestPoint.Y < ptList[i].Y) || (highestPoint.Y == ptList[i].Y && highestPoint.X > ptList[i].X)) { highestPoint = ptList[i]; index = i; } } return(index); }
//sort point array for Grahams scan algo to find convex hull internal static void SortedPoint2dListForGrahamScan(ref List <Point2d> ptList, int size) { for (int i = 1; i < size; ++i) { for (int j = i + 1; j < size; ++j) { int order = ValidateObject.CheckPointOrder(ptList[0], ptList[i], ptList[j]); // collinear if (order == 0) { if (DistanceBetweenPoints(ptList[0], ptList[0]) <= DistanceBetweenPoints(ptList[0], ptList[j])) { ChangePlaces(ref ptList, i, j); } } else if (order == 1) { ChangePlaces(ref ptList, i, j); } } } }
//removes duplicate lines from a list, based on the lines from another list internal static List <Line2d> RemoveDuplicateLinesBasedOnMidPt(List <Line2d> lineListOrig, List <Line2d> otherLineList) { List <Line2d> lineEditedList = new List <Line2d>(); for (int i = 0; i < lineListOrig.Count; i++) { lineEditedList.Add(lineListOrig[i]); } List <bool> duplicateTagList = new List <bool>(); for (int i = 0; i < lineListOrig.Count; i++) { bool duplicate = false; for (int j = 0; j < otherLineList.Count; j++) { Point2d midPtOrig = LineUtility.LineMidPoint(lineListOrig[i]); Point2d midPtOther = LineUtility.LineMidPoint(otherLineList[j]); //if (midPtOrig.Compare(midPtOther)) { duplicate = true; break; } if (ValidateObject.CheckPointsWithinRange(midPtOrig, midPtOther, 4)) { duplicate = true; break; } } duplicateTagList.Add(duplicate); } int count = 0; for (int i = 0; i < duplicateTagList.Count; i++) { if (duplicateTagList[i]) { lineEditedList.RemoveAt(i - count); count += 1; } } return(lineEditedList); }
//extends both ends of a line public static Line2d ExtendLine(Line2d line, double extend = 0) { if (extend == 0) { extend = 10000; } double startPtX = 0, startPtY = 0, endPtX = 0, endPtY = 0; if (ValidateObject.CheckLineOrient(line) == 1) { startPtX = line.StartPoint.X; startPtY = line.StartPoint.Y - extend; endPtX = line.EndPoint.X; endPtY = line.EndPoint.Y + extend; } else { startPtX = line.StartPoint.X - extend; startPtY = line.StartPoint.Y; endPtX = line.EndPoint.X + extend; endPtY = line.EndPoint.Y; } return(new Line2d(new Point2d(startPtX, startPtY), new Point2d(endPtX, endPtY))); }
public static Dictionary <string, object> SplitByOffsetFromLine(Polygon2d polyOutline, int lineId, double distance = 10, double minDist = 0) { if (!ValidateObject.CheckPoly(polyOutline)) { return(null); } Polygon2d poly = new Polygon2d(polyOutline.Points, 0); List <Point2d> pointForBlock = new List <Point2d>(); List <Point2d> polyPtsCopy = poly.Points.Select(pt => new Point2d(pt.X, pt.Y)).ToList();//deep copy for (int i = 0; i < poly.Points.Count; i++) { int a = i, b = i + 1, c = i - 1; if (c < 0) { c = poly.Points.Count - 1; } if (i == poly.Points.Count - 1) { b = 0; } Line2d prevLine = poly.Lines[c]; Line2d currLine = poly.Lines[a]; Line2d nextLine = poly.Lines[b]; if (i == lineId) { Line2d line = new Line2d(poly.Points[a], poly.Points[b]); if (line.Length < minDist) { continue; } Line2d offsetLine = LineUtility.OffsetLineInsidePoly(line, poly, distance); pointForBlock.Add(poly.Points[a]); pointForBlock.Add(poly.Points[b]); pointForBlock.Add(offsetLine.EndPoint); pointForBlock.Add(offsetLine.StartPoint); int orientPrev = ValidateObject.CheckLineOrient(prevLine); int orientCurr = ValidateObject.CheckLineOrient(currLine); int orientNext = ValidateObject.CheckLineOrient(nextLine); // case 1 if (orientPrev == orientCurr && orientCurr == orientNext) { polyPtsCopy.Insert(b, offsetLine.EndPoint); polyPtsCopy.Insert(b, offsetLine.StartPoint); } // case 2 if (orientPrev != orientCurr && orientCurr == orientNext) { polyPtsCopy[a] = offsetLine.StartPoint; polyPtsCopy.Insert(b, offsetLine.EndPoint); } // case 3 if (orientPrev == orientCurr && orientCurr != orientNext) { polyPtsCopy.Insert(b, offsetLine.StartPoint); polyPtsCopy[b + 1] = offsetLine.EndPoint; } // case 4 if (orientPrev != orientCurr && orientCurr != orientNext) { polyPtsCopy[a] = offsetLine.StartPoint; polyPtsCopy[b] = offsetLine.EndPoint; } } } Polygon2d polySplit = new Polygon2d(pointForBlock, 0); Polygon2d leftPoly = new Polygon2d(polyPtsCopy, 0); //poly.Points return(new Dictionary <string, object> { { "PolyAfterSplit", (polySplit) }, { "LeftOverPoly", (leftPoly) }, }); }
internal static Dictionary <string, object> FindOuterLinesAndOffsets(Polygon2d poly, double patientRoomDepth = 16, double extension = 8000, double recompute = 5) { if (!ValidateObject.CheckPoly(poly)) { return(null); } Polygon2d polyReg = new Polygon2d(poly.Points); List <Line2d> hLines = new List <Line2d>(); List <Line2d> vLines = new List <Line2d>(); List <Point2d> hMidPt = new List <Point2d>(); List <Point2d> vMidPt = new List <Point2d>(); List <Line2d> nonOrthoLines = new List <Line2d>(); int countOrtho = 0, countNonOrtho = 0; for (int i = 0; i < polyReg.Points.Count; i++) { int a = i, b = i + 1; if (i == polyReg.Points.Count - 1) { b = 0; } Line2d line = new Line2d(polyReg.Points[a], polyReg.Points[b]); int lineType = ValidateObject.CheckLineOrient(line); if (lineType > -1) { if (lineType == 0) { Line2d extendedLine = LineUtility.ExtendLine(line, extension); hLines.Add(extendedLine); hMidPt.Add(LineUtility.LineMidPoint(line)); } if (lineType == 1) { Line2d extendedLine = LineUtility.ExtendLine(line, extension); vLines.Add(extendedLine); vMidPt.Add(LineUtility.LineMidPoint(line)); } countOrtho += 1; } else { countNonOrtho += 1; nonOrthoLines.Add(line); } } List <Line2d> selectedHLines = new List <Line2d>(); List <Line2d> selectedVLines = new List <Line2d>(); int hIndLow = CodeToBeTested.ReturnLowestPointFromList(hMidPt); int hIndHigh = CodeToBeTested.ReturnHighestPointFromList(hMidPt); int vIndLow = PointUtility.LowestPointFromList(vMidPt); int vIndHigh = PointUtility.HighestPointFromList(vMidPt); if (hIndLow > -1) { selectedHLines.Add(hLines[hIndLow]); } if (hIndHigh > -1) { selectedHLines.Add(hLines[hIndHigh]); } if (vIndLow > -1) { selectedVLines.Add(vLines[vIndLow]); } if (vIndHigh > -1) { selectedVLines.Add(vLines[vIndHigh]); } List <Line2d> allSplitLines = new List <Line2d>(); allSplitLines.AddRange(selectedHLines); allSplitLines.AddRange(selectedVLines); 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) }, { "NonOrthoLines", (nonOrthoLines) } }); }
internal static Dictionary <string, object> AddPointToFitPoly(Polygon2d poly, Polygon2d containerPoly, double distance = 16, double area = 0, double thresDistance = 10, double recompute = 5) { if (!ValidateObject.CheckPoly(poly)) { return(null); } if (distance < 1) { return(null); } Dictionary <string, object> lineOffsetCheckObj = ValidateObject.CheckLinesOffsetInPoly(poly, containerPoly, distance); List <int> indicesFalse = (List <int>)lineOffsetCheckObj["IndicesFalse"]; List <List <Point2d> > pointsFalse = (List <List <Point2d> >)lineOffsetCheckObj["PointsOutside"]; List <Point2d> probPointList = new List <Point2d>(); List <Point2d> polyNewPoints = new List <Point2d>(); List <Line2d> falseLines = new List <Line2d>(); Point2d ptNewEnd = new Point2d(0, 0); Point2d otherPt = new Point2d(0, 0); Point2d probPt = new Point2d(0, 0); Line2d line = new Line2d(ptNewEnd, otherPt); int count = 0, maxTry = 50; double ratio = 0, increment = .25; bool added = false, checkOffPtNew = false; for (int i = 0; i < poly.Points.Count; i++) { int a = i, b = i + 1; if (i == poly.Points.Count - 1) { b = 0; } polyNewPoints.Add(poly.Points[a]); if (indicesFalse[i] > -1) { falseLines.Add(poly.Lines[i]); } if (poly.Lines[i].Length > thresDistance && indicesFalse[i] > -1 && pointsFalse[i] != null && pointsFalse[i].Count == 1 && !added && LayoutUtility.CheckLineGetsExternalWall(poly.Lines[i], containerPoly)) { probPointList.AddRange(pointsFalse[i]); probPt = pointsFalse[i][0]; line = poly.Lines[i]; Point2d midPt = LineUtility.LineMidPoint(line); if (line.StartPoint.Compare(probPt)) { otherPt = line.EndPoint; } else { otherPt = line.StartPoint; } Vector2d vecToOther = new Vector2d(probPt, otherPt); while (!checkOffPtNew && count < maxTry && ratio < 0.9) { ratio += increment; ptNewEnd = VectorUtility.VectorAddToPoint(probPt, vecToOther, ratio); Point2d offPtNew = LineUtility.OffsetLinePointInsidePoly(line, ptNewEnd, poly, distance); checkOffPtNew = GraphicsUtility.PointInsidePolygonTest(poly, offPtNew); count += 1; } polyNewPoints.Add(ptNewEnd); added = true; } } Polygon2d polyAdded = new Polygon2d(polyNewPoints, 0); return(new Dictionary <string, object> { { "PolyAddedPts", (polyAdded) }, { "ProblemPoint", (probPt) }, { "IsAdded", (added) }, { "PointAdded", (ptNewEnd) }, { "Trials", (count) }, { "FinalRatio", (ratio) }, { "ProblemLine", (line) }, { "ProblemPtsList", (probPointList) }, { "FalseLineList", (falseLines) } }); }
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) } }); }
//make the given poly all points orthonogonal to each other internal static Polygon2d MakePolyPointsOrtho(Polygon2d poly) { Polygon2d polyReg = new Polygon2d(poly.Points); List <Point2d> ptForOrthoPoly = new List <Point2d>(); for (int i = 0; i < polyReg.Points.Count; i++) { Point2d pt = Point2d.ByCoordinates(polyReg.Points[i].X, polyReg.Points[i].Y); ptForOrthoPoly.Add(pt); } for (int i = 0; i < polyReg.Points.Count; i++) { int a = i, b = i + 1; double eps = 50; if (i == polyReg.Points.Count - 1) { b = 0; } Line2d line = new Line2d(polyReg.Points[a], polyReg.Points[b]); if (ValidateObject.CheckLineOrient(line) == -1) { //double diffX = Math.Abs(line.StartPoint.X - line.EndPoint.X); //double diffY = Math.Abs(line.StartPoint.Y - line.EndPoint.Y); Point2d cenPoly = PolygonUtility.CentroidOfPoly(polyReg); Point2d ptEndA = Point2d.ByCoordinates(polyReg.Points[a].X + eps, polyReg.Points[a].Y); Line2d refLineA = Line2d.ByStartPointEndPoint(polyReg.Points[a], ptEndA); Point2d ptEndB = Point2d.ByCoordinates(polyReg.Points[b].X + eps, polyReg.Points[b].Y); Line2d refLineB = Line2d.ByStartPointEndPoint(polyReg.Points[b], ptEndB); Point2d projectedPtA = GraphicsUtility.ProjectedPointOnLine(refLineB, polyReg.Points[a]); Point2d projectedPtB = GraphicsUtility.ProjectedPointOnLine(refLineA, polyReg.Points[b]); Vector2d vecA = new Vector2d(projectedPtA, cenPoly); Vector2d vecB = new Vector2d(projectedPtB, cenPoly); double vecALength = vecA.Length; double vecBLength = vecB.Length; if (vecALength > vecBLength) { //ptForOrthoPoly[i] = projectedPtA; ptForOrthoPoly.Insert(b, projectedPtB); } else { //ptForOrthoPoly[i] = projectedPtB; ptForOrthoPoly.Insert(b, projectedPtA); } /* * if (diffX > diffY) * { * Point2d ptEndA = Point2d.ByCoordinates(polyReg.Points[a].X, polyReg.Points[a].Y + eps); * Line2d refLineA = Line2d.ByStartPointEndPoint(polyReg.Points[a], ptEndA); * refLineA = LineUtility.extend(refLineA); * * Point2d ptEndB = Point2d.ByCoordinates(polyReg.Points[b].X, polyReg.Points[b].Y + eps); * Line2d refLineB = Line2d.ByStartPointEndPoint(polyReg.Points[b], ptEndB); * refLineB = LineUtility.extend(refLineB); * * Point2d projectedPtA = GraphicsUtility.ProjectedPointOnLine(refLineB, polyReg.Points[a]); * Point2d projectedPtB = GraphicsUtility.ProjectedPointOnLine(refLineA, polyReg.Points[b]); * * Vector2d vecA = new Vector2d(projectedPtA, cenPoly); * Vector2d vecB = new Vector2d(projectedPtB, cenPoly); * double vecALength = vecA.Length; * double vecBLength = vecB.Length; * if(vecALength < vecBLength) * { * //ptForOrthoPoly[i] = projectedPtA; * ptForOrthoPoly.Insert(b, projectedPtB); * } * else * { * //ptForOrthoPoly[i] = projectedPtB; * ptForOrthoPoly.Insert(b, projectedPtA); * } * } * else * { * * Point2d ptEndA = Point2d.ByCoordinates(polyReg.Points[a].X + eps, polyReg.Points[a].Y); * Line2d refLineA = Line2d.ByStartPointEndPoint(polyReg.Points[a], ptEndA); * refLineA = LineUtility.extend(refLineA); * * Point2d ptEndB = Point2d.ByCoordinates(polyReg.Points[b].X + eps, polyReg.Points[b].Y); * Line2d refLineB = Line2d.ByStartPointEndPoint(polyReg.Points[b], ptEndB); * refLineB = LineUtility.extend(refLineB); * * Point2d projectedPtA = GraphicsUtility.ProjectedPointOnLine(refLineB, polyReg.Points[a]); * Point2d projectedPtB = GraphicsUtility.ProjectedPointOnLine(refLineA, polyReg.Points[b]); * * Vector2d vecA = new Vector2d(projectedPtA, cenPoly); * Vector2d vecB = new Vector2d(projectedPtB, cenPoly); * double vecALength = vecA.Length; * double vecBLength = vecB.Length; * if (vecALength < vecBLength) * { * //ptForOrthoPoly[i] = projectedPtA; * ptForOrthoPoly.Insert(b, projectedPtB); * } * else * { * //ptForOrthoPoly[i] = projectedPtB; * ptForOrthoPoly.Insert(b, projectedPtB); * } * } */ } } return(new Polygon2d(ptForOrthoPoly)); }
//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); }
//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> 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) } }); }