static ImageCellCollection DetectRawCells(CrossPoints crossPoints, int[,] crossPointIndexes, int spacingMin, double widthRatio, double heightRatio) { ImageCellCollection rawCells = new ImageCellCollection(); if (crossPoints.Count > 0) { int rowIndex, columnIndex, leftColumnIndex, topRowIndex, leftTopIndex; int leftX, rightX, topY, bottomY, width, height, rowSize, columnSize, index = 0; CrossPoint leftTop; foreach (CrossPoint current in crossPoints) { if (current.RowIndex > 0 && current.ColumnIndex > 0 && current.ExistLeftLine && current.ExistTopLine) { leftColumnIndex = FindLeftColumnIndex(rowIndex: current.RowIndex, columnIndex: current.ColumnIndex, crossPointIndexes: ref crossPointIndexes, rawCrossPoints: ref crossPoints); topRowIndex = FindTopRowIndex(rowIndex: current.RowIndex, columnIndex: current.ColumnIndex, crossPointIndexes: ref crossPointIndexes, rawCrossPoints: ref crossPoints); if (leftColumnIndex > -1 && topRowIndex > -1) { leftTopIndex = crossPointIndexes[topRowIndex, leftColumnIndex]; if (leftTopIndex > -1) { leftTop = crossPoints[leftTopIndex]; leftX = leftTop.X; rightX = current.X; topY = leftTop.Y; bottomY = current.Y; width = rightX - leftX; height = bottomY - topY; // 가로 간격이나 세로 간격이 최소 간격 작은 것은 cell로 인정하지 않는다. // 셀의 가로, 세로가 모두 페이지의 절반을 넘어서면 cell로 인정하지 않는다. if (width > spacingMin && height > spacingMin && !(width * widthRatio > LIMIT_CELL_WIDTH && height * heightRatio > LIMIT_CELL_HEIGHT)) { rowIndex = leftTop.RowIndex; columnIndex = leftTop.ColumnIndex; columnSize = current.ColumnIndex - leftTop.ColumnIndex; rowSize = current.RowIndex - leftTop.RowIndex; // 최종적으로 좌표는 백분율로 된 상대값이기 때문에 여기서 바꿔줘야 한다. rawCells.Add(new ImageCell(index: index++, rowIndex: rowIndex, columnIndex: columnIndex, rowSize: rowSize, columnSize: columnSize, topY: topY, bottomY: bottomY, leftX: leftX, rightX: rightX)); } } } } } } // 병합된 경우 index가 뒤죽박죽이 되므로 여기서 정렬한다. return(new ImageCellCollection(rawCells.OrderBy(cell => cell.RowIndex).ThenBy(cell => cell.ColumnIndex))); }
static CrossPoints DetectRawCrossPoints(CellLines horizontals, CellLines verticals, int lineDistance, out int[,] crossPointIndexes) { crossPointIndexes = new int[horizontals.Count, verticals.Count]; CrossPoints rawCrossPoints = new CrossPoints(); bool existTopLine, existLeftLine; int index = 0; CellLine horizontal, vertical; for (int i = 0; i < horizontals.Count; i++) { horizontal = horizontals[i]; for (int j = 0; j < verticals.Count; j++) { vertical = verticals[j]; // 두선이 교차하는지 확인 if (horizontal.StartX <= vertical.StartX && horizontal.EndX >= vertical.EndX && horizontal.StartY >= vertical.StartY && horizontal.EndY <= vertical.EndY) { // 현재 점이 위로 선이 있는지, 좌로 선이 있는지 확인. 향후 cell 구성할 때 사용 existTopLine = Math.Abs(vertical.StartY - horizontal.StartY) > lineDistance; existLeftLine = Math.Abs(horizontal.StartX - vertical.StartX) > lineDistance; rawCrossPoints.Add(new CrossPoint(index: index, existTopLine: existTopLine, existLeftLine: existLeftLine, rowIndex: i, columnIndex: j, x: vertical.StartX, y: horizontal.StartY, horizontal: horizontal, vertical: vertical)); crossPointIndexes[i, j] = index; index++; } else { crossPointIndexes[i, j] = -1; } } } return(rawCrossPoints); }
static int FindTopRowIndex(int rowIndex, int columnIndex, ref int[,] crossPointIndexes, ref CrossPoints rawCrossPoints) { CrossPoint topPoint; int index = 0; for (int i = rowIndex - 1; i > -1; i--) { index = crossPointIndexes[i, columnIndex]; if (index > -1) { topPoint = rawCrossPoints[index]; if (topPoint.ExistLeftLine) { return(topPoint.RowIndex); } } } return(-1); }
static int FindLeftColumnIndex(int rowIndex, int columnIndex, ref int[,] crossPointIndexes, ref CrossPoints rawCrossPoints) { CrossPoint leftPoint; int index; for (int i = columnIndex - 1; i > -1; i--) { index = crossPointIndexes[rowIndex, i]; if (index > -1) { leftPoint = rawCrossPoints[index]; if (leftPoint.ExistTopLine) { return(leftPoint.ColumnIndex); } } } return(-1); }