DrawClosedCurve.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. using PaintDotNet.Annotation.Enum;
  2. using PaintDotNet.Base.SettingModel;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Drawing;
  6. using System.Drawing.Drawing2D;
  7. using System.Globalization;
  8. using System.Windows.Forms;
  9. namespace PaintDotNet.Annotation.Label
  10. {
  11. using PointList = List<PointF>;
  12. /// <summary>
  13. /// 标注->曲线->闭合曲线
  14. /// </summary>
  15. public class DrawClosedCurve : DrawObject
  16. {
  17. private PointList pointArray;
  18. private static Cursor handleCursor = new Cursor(PdnResources.GetResourceStream("Cursors.AnnotationPolyHandle.cur"));
  19. /// <summary>
  20. /// Graphic objects for hit test
  21. /// </summary>
  22. private GraphicsPath areaPath = null;
  23. private Pen areaPen = null;
  24. private Region areaRegion = null;
  25. /// <summary>
  26. /// 标注样式信息model
  27. /// </summary>
  28. public LabelStyleModel.ClosedCurve labelClosedCurveStyleModel;
  29. public DrawClosedCurve() : base()
  30. {
  31. this.objectType = DrawClass.Label;
  32. this.drawToolType = DrawToolType.DrawClosedCurve;
  33. pointArray = new PointList();
  34. Initialize();
  35. }
  36. public DrawClosedCurve(ISurfaceBox surfaceBox, int x1, int y1) : base()
  37. {
  38. this.objectType = DrawClass.Label;
  39. this.drawToolType = DrawToolType.DrawClosedCurve;
  40. labelClosedCurveStyleModel = surfaceBox.GetLabelStyleModel().closedCurveModel;
  41. pointArray = new PointList();
  42. startPoint.X = x1;
  43. startPoint.Y = y1;
  44. pointArray.Add(new PointF(x1, y1));
  45. Initialize();
  46. }
  47. public DrawClosedCurve(ISurfaceBox surfaceBox, List<PointF> points, ParentStyleModel parentStyleModel, Object content) : base()
  48. {
  49. this.objectType = DrawClass.Label;
  50. this.drawToolType = DrawToolType.DrawClosedCurve;
  51. this.ISurfaceBox = surfaceBox;
  52. labelClosedCurveStyleModel = (LabelStyleModel.ClosedCurve)parentStyleModel;
  53. pointArray = points;
  54. startPoint = points[points.Count - 2];
  55. endPoint = points[points.Count - 1];
  56. }
  57. /// <summary>
  58. /// Clone this instance
  59. /// </summary>
  60. public override DrawObject Clone()
  61. {
  62. DrawClosedCurve drawClosedCurve = new DrawClosedCurve(ISurfaceBox, 0, 0);
  63. drawClosedCurve.objectType = DrawClass.Label;
  64. drawClosedCurve.drawToolType = DrawToolType.DrawClosedCurve;
  65. drawClosedCurve.ISurfaceBox = this.ISurfaceBox;
  66. drawClosedCurve.pointArray.Clear();
  67. foreach (PointF p in this.pointArray)
  68. {
  69. drawClosedCurve.pointArray.Add(new PointF(p.X, p.Y));
  70. }
  71. drawClosedCurve.startPoint = this.startPoint;
  72. drawClosedCurve.endPoint = this.endPoint;
  73. drawClosedCurve.labelClosedCurveStyleModel = this.labelClosedCurveStyleModel;
  74. FillDrawObjectFields(drawClosedCurve);
  75. return drawClosedCurve;
  76. }
  77. public override DrawObject Clone(ISurfaceBox surfaceBox)
  78. {
  79. DrawClosedCurve drawClosedCurve = new DrawClosedCurve(surfaceBox, 0, 0);
  80. drawClosedCurve.objectType = DrawClass.Label;
  81. drawClosedCurve.drawToolType = DrawToolType.DrawClosedCurve;
  82. drawClosedCurve.ISurfaceBox = surfaceBox;
  83. drawClosedCurve.pointArray.Clear();
  84. foreach (PointF p in this.pointArray)
  85. {
  86. drawClosedCurve.pointArray.Add(new PointF(p.X, p.Y));
  87. }
  88. drawClosedCurve.startPoint = this.startPoint;
  89. drawClosedCurve.endPoint = this.endPoint;
  90. drawClosedCurve.labelClosedCurveStyleModel = this.labelClosedCurveStyleModel;
  91. FillDrawObjectFields(drawClosedCurve);
  92. return drawClosedCurve;
  93. }
  94. public override void Draw(Graphics g)
  95. {
  96. if (HandleCount >= 3)
  97. {
  98. g.SmoothingMode = SmoothingMode.AntiAlias;
  99. Color color = Color.FromArgb(labelClosedCurveStyleModel.lineColor);
  100. int lineWidth = labelClosedCurveStyleModel.lineWidth;
  101. Color fillColor = Color.FromArgb(labelClosedCurveStyleModel.fillColor);
  102. Pen pen = new Pen(color, lineWidth);
  103. pen.DashStyle = (DashStyle)this.labelClosedCurveStyleModel.lineStyle;
  104. g.DrawClosedCurve(pen, pointArray.ToArray());
  105. // 填充封闭曲线
  106. float tension = 1.0F;
  107. // 设置填充模式交替模式
  108. FillMode flMode = FillMode.Alternate;
  109. SolidBrush fillBrush = new SolidBrush(fillColor);
  110. // 绘制填充曲线
  111. g.FillClosedCurve(fillBrush, pointArray.ToArray(), flMode, tension);
  112. // 释放对象
  113. fillBrush.Dispose();
  114. pen.Dispose();
  115. }
  116. }
  117. public void AddPoint(PointF point)
  118. {
  119. pointArray.Add(point);
  120. }
  121. public override int HandleCount
  122. {
  123. get
  124. {
  125. return pointArray.Count;
  126. }
  127. }
  128. /// <summary>
  129. /// Get handle pointscroll by 1-based number
  130. /// </summary>
  131. /// <param name="handleNumber"></param>
  132. /// <returns></returns>
  133. public override PointF GetHandle(int handleNumber)
  134. {
  135. if (handleNumber < 1)
  136. handleNumber = 1;
  137. if (handleNumber > pointArray.Count)
  138. handleNumber = pointArray.Count;
  139. return pointArray[handleNumber - 1];
  140. }
  141. public override Cursor GetHandleCursor(int handleNumber)
  142. {
  143. return handleCursor;
  144. }
  145. public override void MoveHandleTo(Point point, int handleNumber)
  146. {
  147. if (handleNumber < 1)
  148. handleNumber = 1;
  149. if (handleNumber > pointArray.Count)
  150. handleNumber = pointArray.Count;
  151. pointArray[handleNumber - 1] = point;
  152. Invalidate();
  153. }
  154. public override void Move(int deltaX, int deltaY)
  155. {
  156. int n = pointArray.Count;
  157. PointF point;
  158. for (int i = 0; i < n; i++)
  159. {
  160. point = new PointF(pointArray[i].X + ISurfaceBox.UnscaleScalar(deltaX), pointArray[i].Y + ISurfaceBox.UnscaleScalar(deltaY));
  161. pointArray[i] = point;
  162. }
  163. Invalidate();
  164. }
  165. /// <summary>
  166. /// 用于创建一个路径或者是闭合的范围
  167. /// 用于响应点击选中
  168. /// 需要咨询用户是仅点击线还是矩形选择
  169. /// </summary>
  170. protected virtual void CreateObjects()
  171. {
  172. if (AreaPath != null)
  173. return;
  174. AreaPath = new GraphicsPath();
  175. AreaPath.AddRectangle(GetBoundingBox());
  176. AreaPath.CloseFigure();
  177. AreaRegion = new Region(AreaPath);
  178. }
  179. /// <summary>
  180. /// Invalidate object.
  181. /// When object is invalidated, path used for hit test
  182. /// is released and should be created again.
  183. /// </summary>
  184. protected void Invalidate()
  185. {
  186. if (AreaPath != null)
  187. {
  188. AreaPath.Dispose();
  189. AreaPath = null;
  190. }
  191. if (AreaPen != null)
  192. {
  193. AreaPen.Dispose();
  194. AreaPen = null;
  195. }
  196. if (AreaRegion != null)
  197. {
  198. AreaRegion.Dispose();
  199. AreaRegion = null;
  200. }
  201. }
  202. protected GraphicsPath AreaPath
  203. {
  204. get
  205. {
  206. return areaPath;
  207. }
  208. set
  209. {
  210. areaPath = value;
  211. }
  212. }
  213. protected Pen AreaPen
  214. {
  215. get
  216. {
  217. return areaPen;
  218. }
  219. set
  220. {
  221. areaPen = value;
  222. }
  223. }
  224. protected Region AreaRegion
  225. {
  226. get
  227. {
  228. return areaRegion;
  229. }
  230. set
  231. {
  232. areaRegion = value;
  233. }
  234. }
  235. /// <summary>
  236. /// Draw tracker for selected object
  237. /// </summary>
  238. /// <param name="g"></param>
  239. public override void DrawTracker(Graphics g)
  240. {
  241. if (!Selected)
  242. return;
  243. SolidBrush brush = new SolidBrush(Color.FromArgb(MarkpointAreaColor));
  244. Pen pen = new Pen(Color.FromArgb(MarkpointLineColor), MarkpointLineWidth);
  245. for (int i = 1; i <= HandleCount; i++)
  246. {
  247. switch (MarkpointStyle)
  248. {
  249. case 0:
  250. g.FillRectangle(brush, GetHandleRectangle(i));
  251. g.DrawRectangle(pen, GetHandleRectangle(i));
  252. break;
  253. case 1:
  254. g.FillEllipse(brush, GetHandleRectangle(i));
  255. g.DrawEllipse(pen, GetHandleRectangle(i));
  256. break;
  257. case 2:
  258. g.FillPolygon(brush, GetHandlePoint(i));
  259. g.DrawPolygon(pen, GetHandlePoint(i));
  260. break;
  261. }
  262. }
  263. brush.Dispose();
  264. pen.Dispose();
  265. RectangleF rectangleF = GetBoundingBox();
  266. g.DrawRectangle(new Pen(Color.White), rectangleF.X, rectangleF.Y, rectangleF.Width, rectangleF.Height);
  267. }
  268. /// <summary>
  269. /// Hit test.
  270. /// Return value: -1 - no hit
  271. /// 0 - hit anywhere
  272. /// > 1 - handle number
  273. /// </summary>
  274. /// <param name="pointscroll"></param>
  275. /// <returns></returns>
  276. public override int HitTest(Point point)
  277. {
  278. if (Selected)
  279. {
  280. for (int i = 1; i <= HandleCount; i++)
  281. {
  282. if (GetHandleRectangle(i).Contains(point))
  283. return i;
  284. }
  285. }
  286. if (PointInObject(point))
  287. return 0;
  288. return -1;
  289. }
  290. protected override bool PointInObject(Point point)
  291. {
  292. CreateObjects();
  293. return AreaRegion.IsVisible(point);
  294. }
  295. public override bool IntersectsWith(Rectangle rectangle)
  296. {
  297. CreateObjects();
  298. return AreaRegion.IsVisible(rectangle);
  299. }
  300. public override RectangleF GetBoundingBox()
  301. {
  302. RectangleF rectangle;
  303. float minx = 0, maxx = 0, miny = 0, maxy = 0;
  304. for (int i = 0; i < pointArray.Count; i++)
  305. {
  306. if (i == 0)
  307. {
  308. minx = maxx = pointArray[i].X;
  309. miny = maxy = pointArray[i].Y;
  310. }
  311. else
  312. {
  313. if (pointArray[i].X > maxx) maxx = pointArray[i].X;
  314. if (pointArray[i].X < minx) minx = pointArray[i].X;
  315. if (pointArray[i].Y > maxy) maxy = pointArray[i].Y;
  316. if (pointArray[i].Y < miny) miny = pointArray[i].Y;
  317. }
  318. }
  319. rectangle = new RectangleF(minx, miny, maxx - minx, maxy - miny);
  320. return rectangle;
  321. }
  322. internal void setNextPoint(PointF p)
  323. {
  324. AddPoint(p);
  325. startPoint = endPoint;
  326. endPoint = p;
  327. }
  328. internal void setEndPoint(PointF p)
  329. {
  330. endPoint = p;
  331. }
  332. public override List<PointF> GetPoints()
  333. {
  334. return pointArray;
  335. }
  336. public override ParentStyleModel GetStyle()
  337. {
  338. return labelClosedCurveStyleModel;
  339. }
  340. }
  341. }