/// <summary> /// 解析直线 /// </summary> /// <param name="line"></param> private void ParseLine(Point2d ptStart, Point2d ptEnd) { if (!CommandUtils.IsOrthogonalLine(ptStart, ptEnd)) { //表格里会有斜线代表空格,直接跳过 //throw new AcTableParseException(string.Format("只支持正交的直线 {0:s} {1:s}", ptStart.ToString(), ptEnd.ToString())); return; } List <AcTableLine> list; if (CommandUtils.Compare(ptStart.X, ptEnd.X) == 0) { list = _tableVLines; } else { list = _tableHLines; } bool add = false; foreach (AcTableLine tl in list) { if (tl.AcceptSegment(ptStart, ptEnd)) { tl.AddSegment(ptStart, ptEnd); add = true; break; } } if (!add) { list.Add(new AcTableLine(ptStart, ptEnd)); } }
/// <summary> /// 构造器 /// 这里默认线段已经是正交的,应在调用之前做好判断 /// </summary> /// <param name="start"></param> /// <param name="end"></param> public AcTableLine(Point2d pt1, Point2d pt2) { if (CommandUtils.Compare(pt1.X, pt2.X) == 0) { _direction = AcTableLineDirection.V; _xory = pt1.X; } else { _direction = AcTableLineDirection.H; _xory = pt2.Y; } Point2d start, end; if (CommandUtils.Compare(pt1.Y, pt2.Y) > 0 || CommandUtils.Compare(pt1.X, pt2.X) < 0) { start = pt1; end = pt2; } else { start = pt2; end = pt1; } _start = start; _end = end; _segments.Add(new AcLineSegment(start, end)); }
/// <summary> /// 是否接受一个线段,即该线段是否可以归到这条格线中 /// 这里默认线段已经是正交的,应在调用之前做好判断 /// </summary> /// <param name="start"></param> /// <param name="end"></param> /// <returns></returns> public bool AcceptSegment(Point2d pt1, Point2d pt2) { AcTableLineDirection direction; double xory = 0; if (CommandUtils.Compare(pt1.X, pt2.X) == 0) { direction = AcTableLineDirection.V; xory = pt1.X; } else { direction = AcTableLineDirection.H; xory = pt1.Y; } return(direction == _direction && (_segments.Count == 0 || CommandUtils.Compare(xory, _xory) == 0)); }
/// <summary> /// 清理无效的格线 /// 有时候表格里会有非格线的直线或多段线(比如钢筋图样),需要清理掉 /// 清理的原则是要求格线的头或尾,必须在某个正交方向的格线上 /// </summary> private void CleanLines() { //清理横线 AcTableLine preHLine = null; foreach (AcTableLine hLine in _tableHLines.ToArray()) { hLine.CrossPointCount = 0; foreach (AcTableLine vLine in _tableVLines) { Point2d pt = new Point2d(vLine.XorY, hLine.XorY); if (hLine.HasSegmentOn(pt, _tolerance) && vLine.HasSegmentOn(pt, _tolerance)) { hLine.CrossPointCount += 1; } } if (hLine.CrossPointCount <= 1) { _tableHLines.Remove(hLine); } else if (preHLine != null && preHLine.XorY - hLine.XorY <= _tolerance) //表格容错,挨的太近的格线,删除掉一根交叉点小的 { //string s = string.Format("{0:f3},{1:f3},{2:f3},{3:f3}", preHLine.XorY, hLine.XorY, preHLine.XorY - hLine.XorY, _tolerance); //System.Windows.Forms.MessageBox.Show(s); if (preHLine.CrossPointCount < hLine.CrossPointCount) { _tableHLines.Remove(preHLine); preHLine = hLine; } else { _tableHLines.Remove(hLine); } } else { preHLine = hLine; } } //清理竖线 AcTableLine preVLine = null; foreach (AcTableLine vLine in _tableVLines.ToArray()) { vLine.CrossPointCount = 0; foreach (AcTableLine hLine in _tableHLines) { Point2d pt = new Point2d(vLine.XorY, hLine.XorY); if (hLine.HasSegmentOn(pt, _tolerance) && vLine.HasSegmentOn(pt, _tolerance)) { vLine.CrossPointCount += 1; } } if (vLine.CrossPointCount <= 1) { _tableVLines.Remove(vLine); } else if (preVLine != null && vLine.XorY - preVLine.XorY < _tolerance) //表格容错,挨的太近的格线,删除掉一根交叉点小的 { if (preVLine.CrossPointCount < vLine.CrossPointCount) { _tableVLines.Remove(preVLine); preVLine = vLine; } else { _tableVLines.Remove(vLine); } } else { preVLine = vLine; } } //有时候表格会有双层外框,清理外层 if (_tableHLines.Count > 2 || _tableVLines.Count > 2) { if (_tableHLines[0].CrossPointCount <= 2 && _tableHLines.Last().CrossPointCount <= 2 && _tableVLines[0].CrossPointCount <= 2 && _tableVLines.Last().CrossPointCount <= 2) { _tableHLines.RemoveAt(0); _tableHLines.RemoveAt(_tableHLines.Count - 1); _tableVLines.RemoveAt(0); _tableVLines.RemoveAt(_tableVLines.Count - 1); } } //清理只有2个交点并且不等于表格宽和高的格线 double tableWidth = _tableHLines.Max(line => line.Length); foreach (AcTableLine hLine in _tableHLines.ToArray()) { if (hLine.CrossPointCount <= 2 && CommandUtils.Compare(hLine.Length, tableWidth) < 0) { //System.Windows.Forms.MessageBox.Show(hLine.Length.ToString()); _tableHLines.Remove(hLine); } } double tableHeight = _tableVLines.Max(line => line.Length); foreach (AcTableLine vLine in _tableVLines.ToArray()) { if (vLine.CrossPointCount <= 2 && CommandUtils.Compare(vLine.Length, tableHeight) < 0) { _tableVLines.Remove(vLine); } } }
/// <summary> /// 向格线中添加一段 /// 应提前调用Accept方法判断是否应该属于该格线,本方法中不再判断 /// </summary> /// <param name="pt1"></param> /// <param name="pt2"></param> public void AddSegment(Point2d pt1, Point2d pt2) { Point2d start, end; if (CommandUtils.Compare(pt1.Y, pt2.Y) > 0 || CommandUtils.Compare(pt1.X, pt2.X) < 0) { start = pt1; end = pt2; } else { start = pt2; end = pt1; } if (_direction == AcTableLineDirection.H) { if (_segments.Count == 0) { _xory = start.Y; _segments.Add(new AcLineSegment(start, end)); } bool add = false; for (int i = 0; i < _segments.Count; i++) { if (start.X < _segments[i].Start.X) { _segments.Insert(i, new AcLineSegment(start, end)); add = true; break; } } if (!add) { _segments.Add(new AcLineSegment(start, end)); } if (_start.X > start.X) { _start = start; } if (_end.X < end.X) { _end = end; } } else { if (_segments.Count == 0) { _xory = start.X; _segments.Add(new AcLineSegment(start, end)); } bool add = false; for (int i = 0; i < _segments.Count; i++) { if (start.Y > _segments[i].Start.Y) { _segments.Insert(i, new AcLineSegment(start, end)); add = true; break; } } if (!add) { _segments.Add(new AcLineSegment(start, end)); } if (_start.Y < start.Y) { _start = start; } if (_end.Y > end.Y) { _end = end; } } }