using PaintDotNet.Annotation.Enum; using PaintDotNet.Base.SettingModel; using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Drawing2D; using System.Globalization; using System.Windows.Forms; namespace PaintDotNet.Annotation.ImageCollect { using static PaintDotNet.Base.SettingModel.LabelStyleModel; /// /// 图像拼接->多边形 /// public class DrawStitchingPolygon : DrawStithchingBase { /// /// 鼠标形状 /// private static Cursor handleCursor = new Cursor(PdnResources.GetResourceStream("Cursors.AnnotationPolyHandle.cur")); /// /// 点集合 /// private List pointArray = new List(); /// /// 标注样式信息model /// public PolygonPolygon polygonStyle; private RectangleF rectangleF; public DrawStitchingPolygon() : base() { this.objectType = DrawClass.Stitch; this.drawToolType = DrawToolType.DrawStitchingPolygon; Initialize(); } public DrawStitchingPolygon(ISurfaceBox surfaceBox, int x1, int y1) : base() { this.objectType = DrawClass.Stitch; this.drawToolType = DrawToolType.DrawStitchingPolygon; polygonStyle = surfaceBox.GetLabelStyleModel().polygonPolygon; startPoint.X = x1; startPoint.Y = y1; pointArray.Add(new PointF(x1, y1)); Initialize(); } public DrawStitchingPolygon(ISurfaceBox surfaceBox, List points, ParentStyleModel parentStyleModel, Object content) : base() { this.objectType = DrawClass.Stitch; this.drawToolType = DrawToolType.DrawStitchingPolygon; this.ISurfaceBox = surfaceBox; polygonStyle = (PolygonPolygon)parentStyleModel; pointArray = points; startPoint = points[points.Count - 2]; endPoint = points[points.Count - 1]; } /// /// Clone this instance /// public override DrawObject Clone() { DrawStitchingPolygon drawPolygon = new DrawStitchingPolygon(); drawPolygon.objectType = DrawClass.Stitch; drawPolygon.drawToolType = DrawToolType.DrawStitchingPolygon; drawPolygon.ISurfaceBox = this.ISurfaceBox; foreach (PointF p in this.pointArray) { drawPolygon.pointArray.Add(p); } drawPolygon.polygonStyle = this.polygonStyle; drawPolygon.startPoint = this.startPoint; drawPolygon.endPoint = this.endPoint; FillDrawObjectFields(drawPolygon); return drawPolygon; } public override DrawObject Clone(ISurfaceBox surfaceBox) { DrawStitchingPolygon drawPolygon = new DrawStitchingPolygon(); drawPolygon.objectType = DrawClass.Stitch; drawPolygon.drawToolType = DrawToolType.DrawStitchingPolygon; drawPolygon.ISurfaceBox = surfaceBox; foreach (PointF p in this.pointArray) { drawPolygon.pointArray.Add(p); } drawPolygon.startPoint = this.startPoint; drawPolygon.endPoint = this.endPoint; drawPolygon.polygonStyle = this.polygonStyle; FillDrawObjectFields(drawPolygon); return drawPolygon; } public override void Draw(Graphics g) { if (HandleCount >= 3) { g.SmoothingMode = SmoothingMode.AntiAlias; //Color color = Color.FromArgb(this.polygonStyle.lineColor); Color color = Color.Gray; Pen pen = new Pen(color, PenWidth); int penWidth = 1; //this.polygonStyle.lineWidth; pen.DashStyle = DashStyle.Solid; // (DashStyle)this.polygonStyle.lineStyle; pen.Width = penWidth; g.DrawPolygon(pen, pointArray.ToArray()); pen.Color = Color.FromArgb(this.polygonStyle.lineColor); float halfW = rectangleF.Width / 2; float halfH = rectangleF.Height / 2; int xNum = CalGridNum(rectangleF.Width, ViewWidth); int yNum = CalGridNum(rectangleF.Height, ViewHeight); if (xNum != tiles[0] || yNum != tiles[1]) { tiles[0] = xNum; tiles[1] = yNum; this.deletedPointId.Clear(); this.zscan.Clear(); for (int j = 0; j < tiles[1]; j++) { for (int i = 0; i < tiles[0]; i++) { zscan.Add(new ZScanParameter()); } } } PointF centerPoint = new PointF(); centerPoint.X = rectangleF.X + halfW; centerPoint.Y = rectangleF.Y + halfH; PointF startPoint = new PointF(); if (tiles[0] % 2 == 0) { startPoint.X = (float)centerPoint.X - ViewWidth * (tiles[0] / 2 - Interval / 2 - (tiles[0] / 2 - 1) * Interval); } else { int n = (tiles[0] - 1) / 2; startPoint.X = (float)centerPoint.X - ViewWidth / 2 - n * ViewWidth * (1 - Interval); } if (tiles[1] % 2 == 0) { startPoint.Y = (float)centerPoint.Y - ViewHeight * (tiles[1] / 2 - Interval / 2 - (tiles[1] / 2 - 1) * Interval); } else { int n = (tiles[1] - 1) / 2; startPoint.Y = (float)centerPoint.Y - ViewHeight / 2 - n * ViewHeight * (1 - Interval); } rectangleMax = new RectangleF(startPoint, new SizeF(ViewWidth * (tiles[0] - (tiles[0] - 1) * Interval), ViewHeight * (tiles[1] - (tiles[1] - 1) * Interval))); _points.Clear(); int index = 0; List tmpList; for (int j = 0; j < tiles[1]; j++) { tmpList = new List(); for (int i = 0; i < tiles[0]; i++) { float x = startPoint.X + i * (ViewWidth * (1 - Interval)); float y = startPoint.Y + j * (ViewHeight * (1 - Interval)); tmpList.Add(new PointF(x, y)); } if (j % 2 == 1) { for (int m = tmpList.Count - 1; m >= 0; m--) { Dictionary myDictionary = new Dictionary(); myDictionary.Add(0, this.ISurfaceBox.ScalePointToRulerPoint(new PointF(tmpList[m].X, tmpList[m].Y))); if (!deletedPointId.Contains(index)) { g.DrawRectangle(pen, tmpList[m].X, tmpList[m].Y, ViewWidth, ViewHeight); myDictionary.Add(1, 0); } else { myDictionary.Add(1, 1); } _points.Add(myDictionary); index++; } } else { for (int m = 0; m < tmpList.Count; m++) { Dictionary myDictionary = new Dictionary(); myDictionary.Add(0, this.ISurfaceBox.ScalePointToRulerPoint(new PointF(tmpList[m].X, tmpList[m].Y))); if (!deletedPointId.Contains(index)) { g.DrawRectangle(pen, tmpList[m].X, tmpList[m].Y, ViewWidth, ViewHeight); myDictionary.Add(1, 0); } else { myDictionary.Add(1, 1); } _points.Add(myDictionary); index++; } } } pen.Dispose(); } } private int CalGridNum(float width, int side) { for (int i = 0; i <= 10000; i++) { if ((i - (i + 1) * Interval) * side > width) { return i; } } return 0; } public void AddPoint(PointF point) { pointArray.Add(point); } public override Rectangle GetHandleRectangle(int handleNumber) { if (lockType != LockType.NULL) { return new Rectangle(); } PointF point = GetHandle(handleNumber); return new Rectangle((int)(point.X - 100), (int)(point.Y - 100), 201, 201); } public override int HandleCount { get { return pointArray.Count; } } /// /// Get handle pointscroll by 1-based number /// /// /// public override PointF GetHandle(int handleNumber) { if (handleNumber < 1) handleNumber = 1; if (handleNumber > pointArray.Count) handleNumber = pointArray.Count; return pointArray[handleNumber - 1]; } public override Cursor GetHandleCursor(int handleNumber) { return handleCursor; } public override void MoveHandleTo(Point point, int handleNumber) { if (handleNumber < 1) handleNumber = 1; if (handleNumber > pointArray.Count) handleNumber = pointArray.Count; pointArray[handleNumber - 1] = point; } public override void Move(int deltaX, int deltaY) { int n = pointArray.Count; PointF point; for (int i = 0; i < n; i++) { point = new PointF(pointArray[i].X + ISurfaceBox.UnscaleScalar(deltaX), pointArray[i].Y + ISurfaceBox.UnscaleScalar(deltaY)); pointArray[i] = point; } } /// /// Draw tracker for selected object /// /// public override void DrawTracker(Graphics g) { if (!Selected) return; SolidBrush brush = new SolidBrush(Color.Black); for (int i = 1; i <= HandleCount; i++) { g.FillRectangle(brush, GetHandleRectangle(i)); } brush.Dispose(); rectangleF = GetBoundingBox(); g.DrawRectangle(new Pen(Color.White), rectangleF.X, rectangleF.Y, rectangleF.Width, rectangleF.Height); } /// /// Hit test. /// Return value: -1 - no hit /// 0 - hit anywhere /// > 1 - handle number /// /// /// public override int HitTest(Point point) { if (Selected) { for (int i = 1; i <= HandleCount; i++) { if (GetHandleRectangle(i).Contains(point)) return i; } } if (PointInObject(point)) return 0; return -1; } protected override bool PointInObject(Point point) { int counter = 0; int i; double xinters; PointF p1, p2; int pointCount = pointArray.Count; p1 = pointArray[0]; for (i = 1; i <= pointCount; i++) { p2 = pointArray[i % pointCount]; if (point.Y > Math.Min(p1.Y, p2.Y)//校验点的Y大于线段端点的最小Y && point.Y <= Math.Max(p1.Y, p2.Y))//校验点的Y小于线段端点的最大Y { if (point.X <= Math.Max(p1.X, p2.X))//校验点的X小于等线段端点的最大X(使用校验点的左射线判断). { if (p1.Y != p2.Y)//线段不平行于X轴 { xinters = (point.Y - p1.Y) * (p2.X - p1.X) / (p2.Y - p1.Y) + p1.X; if (p1.X == p2.X || point.X <= xinters) { counter++; } } } } p1 = p2; } if (counter % 2 == 0) { return false; } else { return true; } } public override bool IntersectsWith(Rectangle rectangle) { return rectangleF.IntersectsWith(rectangle); } public override RectangleF GetBoundingBox() { RectangleF rectangle; float minx = 0, maxx = 0, miny = 0, maxy = 0; for (int i = 0; i < pointArray.Count; i++) { if (i == 0) { minx = maxx = pointArray[i].X; miny = maxy = pointArray[i].Y; } else { if (pointArray[i].X > maxx) maxx = pointArray[i].X; if (pointArray[i].X < minx) minx = pointArray[i].X; if (pointArray[i].Y > maxy) maxy = pointArray[i].Y; if (pointArray[i].Y < miny) miny = pointArray[i].Y; } } rectangle = new RectangleF(minx, miny, maxx - minx, maxy - miny); return rectangle; } internal void setNextPoint(PointF p) { AddPoint(p); startPoint = endPoint; endPoint = p; } internal void setEndPoint(PointF p) { endPoint = p; } public override List GetPoints() { return pointArray; } public override ParentStyleModel GetStyle() { return polygonStyle; } } }