ViewBase.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. using Resources;
  2. using SmartCoalApplication.Annotation.Enum;
  3. using SmartCoalApplication.Base.CommTool;
  4. using SmartCoalApplication.Base.SettingModel;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.Drawing;
  8. using System.Drawing.Drawing2D;
  9. using System.Windows.Forms;
  10. /*
  11. * 视场,
  12. * 全部图形构成基于点阵(Points)拟合.
  13. * 图形变换,对外属性均依赖于点阵的换算.
  14. * 点阵集合继承DrawObject 的 pointArrayList 字段
  15. * 全部接口数值皆为原始数值并未进行缩放处理.
  16. */
  17. namespace SmartCoalApplication.Annotation.FieldView
  18. {
  19. public abstract class ViewBase : DrawObject
  20. {
  21. /// <summary>
  22. /// 鼠标形状
  23. /// </summary>
  24. public static Cursor m_rotateCursor = new Cursor(PdnResources.GetResourceStream("Cursors.AnnotationRotateHandle.cur"));
  25. public static Cursor m_resizeCursor = new Cursor(PdnResources.GetResourceStream("Cursors.AnnotationResizeHandle.cur"));
  26. protected MeasureAreaModel measureAreaModel;
  27. #region Points
  28. public virtual List<PointF> Points
  29. {
  30. get
  31. {
  32. if (pointArrayList == null)
  33. pointArrayList = new List<PointF>();
  34. return pointArrayList;
  35. }
  36. set
  37. {
  38. pointArrayList = new List<PointF>();
  39. foreach (var p in value)
  40. {
  41. pointArrayList.Add(p);
  42. }
  43. }
  44. }
  45. public void AddPoint(int x, int y)
  46. {
  47. AddPoint(new PointF(x, y));
  48. }
  49. protected void AddPoint(PointF point)
  50. {
  51. Points.Add(point);
  52. }
  53. public override List<PointF> GetPoints()
  54. {
  55. return Points;
  56. }
  57. #endregion
  58. #region Bounding Rectangle
  59. public override RectangleF Rectangle
  60. {
  61. get
  62. {
  63. return GetBoundingBox();
  64. }
  65. }
  66. /// <summary>
  67. /// 外接矩形
  68. /// </summary>
  69. public override RectangleF GetBoundingBox()
  70. {
  71. int minx = 0, maxx = 0, miny = 0, maxy = 0;
  72. for (int i = 0; i < Points.Count; i++)
  73. {
  74. if (i == 0)
  75. {
  76. minx = maxx = (int)(Points[i].X);
  77. miny = maxy = (int)(Points[i].Y);
  78. }
  79. else
  80. {
  81. if (Points[i].X > maxx) maxx = (int)(Points[i].X);
  82. if (Points[i].X < minx) minx = (int)(Points[i].X);
  83. if (Points[i].Y > maxy) maxy = (int)(Points[i].Y);
  84. if (Points[i].Y < miny) miny = (int)(Points[i].Y);
  85. }
  86. }
  87. return new Rectangle(minx, miny, maxx - minx, maxy - miny);
  88. }
  89. #endregion
  90. #region Draw
  91. /// <summary>
  92. /// 指定如何组合不同的剪辑区域
  93. /// 用于存储是合并视场、还是剪切视场
  94. /// </summary>
  95. public CombineMode combineMode;
  96. /// <summary>
  97. /// Draw rectangle
  98. /// </summary>
  99. /// <param name="g"></param>
  100. public override void Draw(Graphics g)
  101. {
  102. Region reg = g.Clip;
  103. ViewBase view = null;
  104. for (int i = ISurfaceBox.GraphicsList.Count - 1; ;)
  105. {
  106. if (ISurfaceBox.GraphicsList[i].objectType == DrawClass.View)
  107. {
  108. view = (ViewBase)ISurfaceBox.GraphicsList[i];
  109. if (view.combineMode == CombineMode.Union)
  110. {
  111. break;
  112. }
  113. }
  114. i--;
  115. if (i < 0)
  116. {
  117. view.combineMode = CombineMode.Union;
  118. break;
  119. }
  120. }
  121. //获取所有合并的视场
  122. Region union = GetUnionOrDeleteView(CombineMode.Union);
  123. //获取所有删除的视场
  124. Region delete = GetUnionOrDeleteView(CombineMode.Complement);
  125. if (union != null)
  126. {
  127. reg.Xor(union);
  128. }
  129. if (delete != null)
  130. {
  131. reg.Union(delete);
  132. }
  133. SolidBrush sb = new SolidBrush(Color.FromArgb(127, 255, 255, 255));
  134. g.FillRegion(sb, reg);
  135. #region [画边框]
  136. measureAreaModel = ISurfaceBox.GetMeasureAreaModel();
  137. Pen pen = new Pen(Color.FromArgb(measureAreaModel.lineColor), measureAreaModel.lineWidth);
  138. pen.DashStyle = (DashStyle)measureAreaModel.lineStyle;
  139. g.DrawRectangle(pen, new Rectangle((int)view.Rectangle.X, (int)view.Rectangle.Y, (int)view.Rectangle.Width, (int)view.Rectangle.Height));
  140. #endregion
  141. }
  142. /// <summary>
  143. /// Draw rectangle
  144. /// </summary>
  145. /// <param name="g"></param>
  146. public override void DrawPicture(Graphics g, RectangleF rectangle)
  147. {
  148. #region [画边框]
  149. measureAreaModel = ISurfaceBox.GetMeasureAreaModel();
  150. Pen pen = new Pen(Color.FromArgb(measureAreaModel.lineColor), measureAreaModel.lineWidth);
  151. pen.DashStyle = (DashStyle)measureAreaModel.lineStyle;
  152. g.DrawRectangle(pen, new Rectangle((int)rectangle.X, (int)rectangle.Y, (int)rectangle.Width, (int)rectangle.Height));
  153. #endregion
  154. }
  155. /// <summary>
  156. /// 获取所有合并或删除的视场
  157. /// </summary>
  158. /// <returns></returns>
  159. private Region GetUnionOrDeleteView(CombineMode combineMode)
  160. {
  161. Region region = null;
  162. if (ISurfaceBox.GraphicsList != null && ISurfaceBox.GraphicsList.Count > 0)
  163. {
  164. for (int i = 0; i < ISurfaceBox.GraphicsList.Count; i++)
  165. {
  166. if (ISurfaceBox.GraphicsList[i].objectType == DrawClass.View)
  167. {
  168. ViewBase view = (ViewBase)ISurfaceBox.GraphicsList[i];
  169. GraphicsPath path = new GraphicsPath();
  170. switch (view.drawToolType)
  171. {
  172. case DrawToolType.ViewOval:
  173. case DrawToolType.ViewCircle:
  174. path.AddClosedCurve(ISurfaceBox.GraphicsList[i].GetPoints().ToArray());
  175. break;
  176. case DrawToolType.ViewSquare:
  177. case DrawToolType.ViewRectangle:
  178. case DrawToolType.ViewTriangle:
  179. case DrawToolType.ViewPolygon:
  180. case DrawToolType.ViewTriangleEx:
  181. case DrawToolType.ViewRectangleEx:
  182. if ((ISurfaceBox.GraphicsList[i]).GetPoints().Count > 2)
  183. {
  184. path.AddPolygon((ISurfaceBox.GraphicsList[i]).GetPoints().ToArray());
  185. }
  186. break;
  187. }
  188. if (view.combineMode == combineMode)
  189. {
  190. if (region == null)
  191. region = new Region(path);
  192. else
  193. region.Union(path);
  194. }
  195. }
  196. }
  197. }
  198. return region;
  199. }
  200. public override void DrawTracker(Graphics g)
  201. {
  202. if (!Selected || !canMove)
  203. return;
  204. SolidBrush brush = new SolidBrush(Color.FromArgb(184, Color.Black));
  205. if (Rotatable && Points.Count > 2)
  206. {
  207. for (int i = 1; i <= HandleCount - 1; i++)
  208. {
  209. g.FillRectangle(brush, GetHandleRectangle(i));
  210. }
  211. brush = new SolidBrush(Color.Red);
  212. g.FillEllipse(brush, GetHandleRectangle(HandleCount));
  213. brush.Dispose();
  214. }
  215. else
  216. {
  217. for (int i = 1; i <= HandleCount; i++)
  218. {
  219. g.FillRectangle(brush, GetHandleRectangle(i));
  220. }
  221. }
  222. }
  223. #endregion
  224. #region Rotate
  225. protected PointF _lastPoint;
  226. protected PointF _lastCenter;
  227. protected bool _isRotating;
  228. /// <summary>
  229. /// 设置可旋转性,用于显示旋转Handle
  230. /// </summary>
  231. public bool Rotatable = false;
  232. /// <summary>
  233. /// 图形斜率,用于旋转
  234. /// </summary>
  235. public double K
  236. {
  237. get;
  238. set;
  239. } = 0;
  240. public virtual void SetK() { }
  241. public virtual PointF Center
  242. {
  243. get
  244. {
  245. var centerX = Rectangle.X + Math.Abs(Rectangle.Width / 2);
  246. var centerY = Rectangle.Y + Math.Abs(Rectangle.Height / 2);
  247. return new PointF(centerX, centerY);
  248. }
  249. set { }
  250. }
  251. protected virtual void StartRotate()
  252. {
  253. _isRotating = true;
  254. _lastCenter = Center;
  255. }
  256. protected virtual void EndRotate()
  257. {
  258. _isRotating = false;
  259. SetK();
  260. }
  261. protected virtual void MoveRotate(PointF point)
  262. {
  263. if (!_isRotating)
  264. {
  265. StartRotate();
  266. _lastPoint = point;
  267. }
  268. double angle = BasicCalculationHelper.CalculateAngle(_lastCenter.X, _lastCenter.Y, _lastPoint.X, _lastPoint.Y, point.X, point.Y);
  269. _lastPoint = point;
  270. for (int i = 0; i < Points.Count; i++)
  271. {
  272. Points[i] = BasicCalculationHelper.GetAnglePoint(Points[i], _lastCenter, angle);
  273. }
  274. }
  275. /// <summary>
  276. /// 标准化外接矩形
  277. /// </summary>
  278. public override void Normalize()
  279. {
  280. if (_isRotating)
  281. EndRotate();
  282. }
  283. #endregion
  284. #region Select
  285. /// <summary>
  286. /// Hit test.
  287. /// Return value: -1 - no hit
  288. /// 0 - hit anywhere
  289. /// > 1 - handle number
  290. /// </summary>
  291. /// <param name="pointscroll"></param>
  292. /// <returns></returns>
  293. public override int HitTest(Point point)
  294. {
  295. if (Selected)
  296. {
  297. for (int i = 1; i <= HandleCount; i++)
  298. {
  299. if (GetHandleRectangle(i).Contains(point))
  300. return i;
  301. }
  302. }
  303. if (PointInObject(point))
  304. return 0;
  305. return -1;
  306. }
  307. protected override bool PointInObject(Point point)
  308. {
  309. int counter = 0;
  310. int i;
  311. double xinters;
  312. PointF p1, p2;
  313. int pointCount = Points.Count;
  314. p1 = Points[0];
  315. for (i = 1; i <= pointCount; i++)
  316. {
  317. p2 = Points[i % pointCount];
  318. if (point.Y > Math.Min(p1.Y, p2.Y)//校验点的Y大于线段端点的最小Y
  319. && point.Y <= Math.Max(p1.Y, p2.Y))//校验点的Y小于线段端点的最大Y
  320. {
  321. if (point.X <= Math.Max(p1.X, p2.X))//校验点的X小于等线段端点的最大X(使用校验点的左射线判断).
  322. {
  323. if (p1.Y != p2.Y)//线段不平行于X轴
  324. {
  325. xinters = (point.Y - p1.Y) * (p2.X - p1.X) / (p2.Y - p1.Y) + p1.X;
  326. if (p1.X == p2.X || point.X <= xinters)
  327. {
  328. counter++;
  329. }
  330. }
  331. }
  332. }
  333. p1 = p2;
  334. }
  335. return counter % 2 != 0;
  336. }
  337. public override bool IntersectsWith(Rectangle rectangle)
  338. {
  339. return Rectangle.IntersectsWith(rectangle);
  340. }
  341. #endregion
  342. public override void Move(int deltaX, int deltaY)
  343. {
  344. for (int i = 0; i < Points.Count; i++)
  345. {
  346. PointF p = Points[i];
  347. p.X += ISurfaceBox.UnscaleScalar(deltaX);
  348. p.Y += ISurfaceBox.UnscaleScalar(deltaY);
  349. Points[i] = p;
  350. }
  351. OnPropertyChanged();
  352. }
  353. /// <summary>
  354. /// 获取视场面积
  355. /// </summary>
  356. /// <returns></returns>
  357. public virtual double Getacreage()
  358. {
  359. var count = Points.Count;
  360. double area0 = 0;
  361. double area1 = 0;
  362. for (int i = 0; i < count; i++)
  363. {
  364. var x = Points[i].X;
  365. var y = i + 1 < count ? Points[i + 1].Y : Points[0].Y;
  366. area0 += x * y;
  367. x = Points[i].Y;
  368. y = i + 1 < count ? Points[i + 1].X : Points[0].X;
  369. area1 += x * y;
  370. }
  371. return Math.Abs(0.5 * (area0 - area1));
  372. }
  373. }
  374. }