//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)); }
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) } }); }
//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))); }
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) } }); }
//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)); }
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) }, }); }
//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); }
//removes duplicates lines from a list of lines public static List <Line2d> CleanLines(List <Line2d> lineList) { List <Line2d> cleanList = new List <Line2d>(); List <bool> taggedList = new List <bool>(); for (int i = 0; i < lineList.Count; i++) { Line2d lin = new Line2d(lineList[i].StartPoint, lineList[i].EndPoint); cleanList.Add(lin); taggedList.Add(false); } for (int i = 0; i < lineList.Count; i++) { double eps = 1; Line2d lineA = lineList[i]; for (int j = i + 1; j < lineList.Count; j++) { Line2d lineB = lineList[j]; int orientA = ValidateObject.CheckLineOrient(lineA); int orientB = ValidateObject.CheckLineOrient(lineB); if (orientA != orientB) { continue; } else { Point2d midA = LineUtility.LineMidPoint(lineA); Point2d midB = LineUtility.LineMidPoint(lineB); if (orientA == 0) { //lines are horizontal if ((midA.Y - eps < midB.Y && midB.Y < midA.Y + eps) || (midB.Y - eps < midA.Y && midA.Y < midB.Y + eps)) { // lines are duplicate check length, whichever has longer length will be added to list double lenA = lineA.Length; double lenB = lineB.Length; if (lenA > lenB) { taggedList[i] = true; } else { taggedList[j] = true; } }// end of if statement } else { //lines are vertical if ((midA.X - eps < midB.X && midB.X < midA.X + eps) || (midB.X - eps < midA.X && midA.X < midB.X + eps)) { double lenA = lineA.Length; double lenB = lineB.Length; if (lenA > lenB) { cleanList.Add(lineA); } else { cleanList.Add(lineB); } }// end of if statement } } } } return(cleanList); }