protected override DrawObject[] TrimDrawObject(Line line, DrawObjectTrimingInfo trimingInfo) { Vector2D[] intersectPositions = trimingInfo.IntersectPositions; Rectangle2D2 trimArea = trimingInfo.TrimArea; if (line == null) { return(null); } if (intersectPositions == null) { return(null); } if (trimArea == null) { return(null); } //将交点集合筛选(需在线段上,不包括端点),并沿线段起始到终止方向进行排序; intersectPositions = intersectPositions. Where(p => p.IsInLine(line.Line2D)). OrderBy(p => p.Distance(line.Line2D.Start)). ToArray(); ///得到矩形与线段的所有交点(最多两个),通过该交点集合的与<param name="intersectPositions"/>的关系,进行裁剪; var rectInserserctPositions = trimArea.GetLines(). Select(p => p.Intersect(line.Line2D)). Where(p => p != null). Distinct(Vector2DEqualityComparer.StaticInstance). ToArray(); return(GetTrimedLineWithIntersectPositions(line, intersectPositions, rectInserserctPositions)); }
public override bool ObjectInRectangle(Rectangle2D2 rect, ICanvasScreenConvertable canvasProxy, bool anyPoint) { if (rect == null) { throw new ArgumentNullException(nameof(rect)); } if (Ellipse2D == null) { return(false); } //无论是否为任意选中,若包含了,则能够选中; if (rect.Contains(Ellipse2D.Center) && rect.GetLines().All(p => p.Distance(Ellipse2D.Center) >= Ellipse2D.RadiusX)) { return(true); } //若为任意点选中,矩形的四个顶点中,存在任意两点任意一点在椭圆内即可; if (anyPoint && rect.GetLines().Any(p => { var intersectPoints = Extension.IntersectWithLine(Ellipse2D, p); return((intersectPoints?.Length ?? 0) != 0); })) { return(rect.GetVertexes().Any(p => Ellipse2D.Contains(p))); } return(false); }
public Rectangle(Rectangle2D2 rectangle2D) { if (rectangle2D == null) { throw new ArgumentNullException(nameof(rectangle2D)); } this.Rectangle2D = rectangle2D; }
/// <summary> /// 绘制矩形; /// </summary> /// <param name="brush">填充颜色</param> /// <param name="pen"></param> /// <param name="rectangle"></param> public void DrawRectangle(Rectangle2D2 rectangle, Brush brush, Pen pen) { if (rectangle == null) { throw new ArgumentNullException(nameof(rectangle)); } ValidateDrawingContext(); DrawFill(rectangle.GetVertexes(), brush, pen); }
/// <summary> /// 设定矩形数据核心; /// </summary> /// <param name="rectangle2D"></param> private void SetRetangle2DCore(Rectangle2D2 rectangle2D) { if (rectangle2D == null) { throw new ArgumentNullException(nameof(rectangle2D)); } _rectangle2D = rectangle2D; RaiseVisualChanged(); }
protected override void OnMouseDown(MouseDownEventArgs e) { if (e == null) { throw new ArgumentNullException(nameof(e)); } if (e.Position == null) { throw new ArgumentException($"The {e.Position} of {nameof(MouseDownEventArgs)} can't be null."); } e.Handled = true; if (CanvasContext.ActiveLayer == null) { throw new InvalidOperationException($"The {CanvasContext.ActiveLayer} of {nameof(ICanvasContextEx )} can't be null."); } var thisPosition = e.Position; if (thisPosition == null) { return; } //若上次按下位置为空,则记录新的点; if (_lastMouseDownPosition == null) { _lastMouseDownPosition = thisPosition; } //否则将创建一个新的矩形; else { //若对角线两端的横坐标或纵坐标相等,将不能构成一个矩形; if (_lastMouseDownPosition.X == thisPosition.X || _lastMouseDownPosition.Y == thisPosition.Y) { return; } //根据四个顶点创建矩形; var middleLineY = (thisPosition.Y + _lastMouseDownPosition.Y) / 2; var rect2D = new Rectangle2D2( new Line2D( new Vector2D(_lastMouseDownPosition.X, middleLineY), new Vector2D(thisPosition.X, middleLineY) ), Math.Abs(thisPosition.Y - _lastMouseDownPosition.Y) ); var rect = new Rectangle(rect2D); AddDrawObjectToUndoStack(rect); _lastMouseDownPosition = null; } }
/// <summary> /// 得到以某视图坐标为中心的视图矩形; /// </summary> /// <param name="nativeCenterRectPoint">以视图为准的中心坐标</param> /// <param name="width">宽度</param> /// <param name="height">高度</param> /// <returns></returns> public static Rectangle2D2 GetNativeSuroundingScreenRect(Vector2D nativeCenterRectPoint, double width, double height) { if (nativeCenterRectPoint == null) { throw new ArgumentNullException(nameof(nativeCenterRectPoint)); } var surroundingRect = Rectangle2D2.CreateEmpty(); GetNativeSuroundingScreenRect(nativeCenterRectPoint, width, height, surroundingRect); return(surroundingRect); }
/// <summary> /// 检查某个坐标是否处于某个矩形内部; /// </summary> /// <param name="rect"></param> /// <param name="point"></param> /// <returns></returns> public static bool Contains(this Rectangle2D2 rect, Vector2D point) { if (rect == null) { throw new ArgumentNullException(nameof(rect)); } if (point == null) { throw new ArgumentNullException(nameof(point)); } return(point.IsInRegion(rect.GetLines().ToList())); }
/// <summary> /// 以视图坐标为标准,绘制矩形; /// </summary> /// <param name="rectangle">以视图坐标为准的矩形</param> /// <param name="brush">填充色</param> /// <param name="pen">笔</param> public void NativeDrawRectangle(Rectangle2D2 rectangle, Brush brush, Pen pen) { if (rectangle == null) { throw new ArgumentNullException(nameof(rectangle)); } ValidateDrawingContext(); var vertexes = rectangle.GetVertexes(); NativeDrawFill( vertexes.Select(p => Vector2DAdapter.ConvertToSystemPoint(p)), BrushAdapter.ConvertToSystemBrush(brush), PenAdapter.ConverterToSystemPen(pen) ); }
public ISnapShape MatchSnapShape(DrawObject[] drawObjects, Vector2D position, ICanvasContext canvasContext) { if (drawObjects == null) { return(null); } #if DEBUG //position = new Vector2D(0, 0); #endif var screenPosition = canvasContext.CanvasProxy.ToScreen(position); var rect = Rectangle2D2.CreateEmpty(); //双游标两两遍历; for (int i = 0; i < drawObjects.Length - 1; i++) { for (int j = i + 1; j < drawObjects.Length; j++) { var intersectPositions = DrawObjectIntersectRule.GetIntersectPositions(drawObjects[i], drawObjects[j]); if (intersectPositions == null) { continue; } foreach (var intersectPosition in intersectPositions) { NativeGeometryExtensions.GetNativeSuroundingScreenRect( canvasContext.CanvasProxy.ToScreen(intersectPosition), TolerantedScreenLength, TolerantedScreenLength, rect ); if (rect.Contains(screenPosition)) { return(new IntersectSnapPoint(intersectPosition)); } } } } return(null); }
/// <summary> /// 判断某个矩形与某个线段的包含或相交(当<paramref name="anyPoint"/>为真时)关系; /// </summary> /// <param name="line2D"></param> /// <param name="rect"></param> /// <param name="anyPoint"></param> /// <returns></returns> public static bool LineInRectangle(Line2D line2D, Rectangle2D2 rect, bool anyPoint) { if (line2D == null) { return(false); } //若在完全在矩形内部,则返回为真; if (rect.Contains(line2D.Start) && rect.Contains(line2D.End)) { return(true); } //若任意可选为真,则矩形任意一条边与之存在相交即可; else if (anyPoint) { return(rect.GetLines()?.Any(p => p.Intersect(line2D) != null) ?? false); } return(false); }
public override bool ObjectInRectangle(Rectangle2D2 rect, ICanvasScreenConvertable canvasProxy, bool anyPoint) { if (rect == null) { throw new ArgumentNullException(nameof(rect)); } if (Rectangle2D == null) { return(false); } //根据四个顶点的位置判断与指定矩形的包含关系; if (anyPoint) { return(Rectangle2D.GetVertexes()?.Any(p => rect.Contains(p)) ?? false); } else { return(Rectangle2D.GetVertexes()?.All(p => rect.Contains(p)) ?? false); } }
public override void Draw(ICanvas canvas, ICanvasScreenConvertable canvasProxy) { if (canvas == null) { throw new ArgumentNullException(nameof(canvas)); } base.Draw(canvas, canvasProxy); if (_lastMouseDownPosition == null || _currentMousePosition == null) { return; } //若对角线的两端纵坐标或横坐标相等,则不进行绘制; if (_currentMousePosition.X == _lastMouseDownPosition.X || _lastMouseDownPosition.Y == _currentMousePosition.Y) { return; } //绘制编辑的矩形的预览状态; var middleLineY = (_currentMousePosition.Y + _lastMouseDownPosition.Y) / 2; var rect2D = new Rectangle2D2( new Line2D( new Vector2D(_lastMouseDownPosition.X, middleLineY), new Vector2D(_currentMousePosition.X, middleLineY) ), Math.Abs(_currentMousePosition.Y - _lastMouseDownPosition.Y) ); canvas.DrawRectangle( rect2D, NormalRectColorBrush, NormalRectPen ); }
/// <summary> /// 根据裁剪对象<paramref name="trimingDrawObjects"/>和裁剪区域<paramref name="trimArea"/>, /// 对被裁剪对象<paramref name="toBeTrimedDrawObject"/>进行裁剪, /// 返回裁剪后的对象; /// </summary> /// <param name="canvasContext"></param> /// <param name="trimArea"></param> private DrawObject[] GetTrimedOrExtendedDrawObjects( DrawObject toBeTrimedDrawObject, IEnumerable <DrawObject> trimingDrawObjects, Rectangle2D2 trimArea ) { if (toBeTrimedDrawObject == null) { throw new ArgumentNullException(nameof(toBeTrimedDrawObject)); } if (trimingDrawObjects == null) { throw new ArgumentNullException(nameof(trimingDrawObjects)); } ///得到所有被裁剪绘制对象与裁剪对象的交点; var thisIntersectPositions = trimingDrawObjects.SelectMany( p => DrawObjectIntersectRules.SelectMany( q => q.GetIntersectPositions(toBeTrimedDrawObject, p, IsExtendMode) ?? Enumerable.Empty <Vector2D>() ) ).ToArray(); if (thisIntersectPositions.Length == 0) { return(null); } DrawObject[] thisCreatedDrawObjects = null; //若非延伸模式,则进行裁剪计算; if (!IsExtendMode) { //找到对应的裁剪工具; var trimTool = DrawObjectTrimTools.FirstOrDefault(p => p.CheckIsValidDrawObject(toBeTrimedDrawObject)); if (trimTool == null) { return(null); } //进行裁剪; thisCreatedDrawObjects = trimTool.TrimDrawObject( new DrawObjectTrimingInfo { TrimedDrawObject = toBeTrimedDrawObject, TrimingDrawObjects = trimingDrawObjects.ToArray(), IntersectPositions = thisIntersectPositions, TrimArea = trimArea } ); } //否则延伸计算; else { var extendTool = DrawObjectExtendTools.FirstOrDefault(p => p.CheckIsValidDrawObject(toBeTrimedDrawObject)); if (extendTool == null) { return(null); } //进行延伸; var createdDrawObject = extendTool.ExtendDrawObject( new DrawObjectExtendInfo { ExtendedDrawObject = toBeTrimedDrawObject, ExtendingDrawObjects = trimingDrawObjects.ToArray(), ExtendArea = trimArea, IntersectPositions = thisIntersectPositions } ); if (createdDrawObject == null) { return(null); } thisCreatedDrawObjects = new DrawObject[] { createdDrawObject }; } //返回裁剪后的绘制对象; return(thisCreatedDrawObjects); }
/// <summary> /// 将线段限制到可见范围内; /// </summary> /// <param name="line">原坐标</param> /// <returns>返回可见的线段</returns> private static Line2D GetLimitedLine2D(Line2D line, Rectangle2D2 rect) { var visibleLine = new Line2D(line.Start, line.End); return(visibleLine); }
public static Line2D GetExtendLineWithIntersectPositions(Line2D line2D, Line2D[] extendLines, Vector2D[] intersectPositions, Rectangle2D2 rectIntersect) { if (extendLines.Length == 0) { return(null); } if (rectIntersect == null) { return(null); } if (intersectPositions.Length == 0) { return(null); } if (rectIntersect.Contains(line2D.Start) && rectIntersect.Contains(line2D.End) && intersectPositions.Length == 2) { var p1 = intersectPositions[0]; var p2 = intersectPositions[1]; if (line2D.Start.IsInLine(Line2D.Create(p1, line2D.End))) { return(Line2D.Create(p1, p2)); } return(Line2D.Create(p2, p1)); } if (rectIntersect.Contains(line2D.Start)) { return(Line2D.Create(intersectPositions.First(), line2D.End)); } if (rectIntersect.Contains(line2D.End)) { return(Line2D.Create(line2D.Start, intersectPositions.First())); } return(null); }
public DragSelectMouseMoveEventArgs(Rectangle2D2 rectangle2D, Vector2D position) : base(position) { }
/// <summary> /// 判定绘制对象是否在某个矩形区域内; /// </summary> /// <param name="rect">区域(工程数学坐标为准)</param> /// <param name="anyPoint">是否模糊匹配,即判定相交是否满足条件</param> /// <param name="canvasProxy">视图单位转化器,可用于内部进行误差判断</param> /// <returns></returns> public abstract bool ObjectInRectangle(Rectangle2D2 rect, ICanvasScreenConvertable canvasProxy, bool anyPoint);
public static Line2D GetExtendMemberWithIntersectPositions(Line2D line2D, Line2D[] extendLines, Vector2D[] intersectPositions, Rectangle2D2 rectIntersect, double width, double gap) { if (extendLines.Length == 0) { return(null); } if (rectIntersect == null) { return(null); } if (intersectPositions.Length == 0) { return(null); } if (rectIntersect.Contains(line2D.Start) && rectIntersect.Contains(line2D.End) && intersectPositions.Length == 2) { var p1 = intersectPositions[0]; var p2 = intersectPositions[1]; var line1 = extendLines.First(x => p1.IsInLine(x)); var angle1 = line1.Direction.AngleWith(line2D.Direction); var newP1 = GetExtendPoint(p1, -line2D.Direction, angle1, width, gap); var line2 = extendLines.First(x => p2.IsInLine(x)); var angle2 = line2.Direction.AngleWith(line2D.Direction); var newP2 = GetExtendPoint(p2, line2D.Direction, angle2, width, gap); if (line2D.Start.IsInLine(Line2D.Create(p1, line2D.End))) { return(Line2D.Create(newP1, newP2)); } return(Line2D.Create(newP2, newP1)); } if (rectIntersect.Contains(line2D.Start) && line2D.Start.IsInLine(Line2D.Create(intersectPositions.First(), line2D.End))) { var angle = line2D.Direction.AngleWith(extendLines[0].Direction); var newEndPoint = GetExtendPoint(intersectPositions.First(), -line2D.Direction, angle, width, gap); return(Line2D.Create(newEndPoint, line2D.End)); } if (rectIntersect.Contains(line2D.End) && line2D.End.IsInLine(Line2D.Create(intersectPositions.First(), line2D.Start))) { var angle = line2D.Direction.AngleWith(extendLines[0].Direction); var newEndPoint = GetExtendPoint(intersectPositions.First(), line2D.Direction, angle, width, gap); return(Line2D.Create(line2D.Start, newEndPoint)); } return(null); }
public override bool ObjectInRectangle(Rectangle2D2 rect, ICanvasScreenConvertable canvasProxy, bool anyPoint) { return(LineHitUtils.LineInRectangle(MeasureLineP, rect, anyPoint) || LineHitUtils.LineInRectangle(MeasureLineV0, rect, anyPoint) || LineHitUtils.LineInRectangle(MeasureLineV1, rect, anyPoint)); }
/// <summary> /// 得到以某视图坐标为中心的视图矩形; /// </summary> /// <param name="nativeCenterRectPoint">以视图为准的中心坐标</param> /// <param name="width">宽度</param> /// <param name="height">高度</param> /// <param name="rectangle2D2">用于写入的矩形实例</param> /// <returns></returns> public static void GetNativeSuroundingScreenRect(Vector2D nativeCenterRectPoint, double width, double height, Rectangle2D2 rectangle2D2) { if (nativeCenterRectPoint == null) { throw new ArgumentNullException(nameof(nativeCenterRectPoint)); } if (rectangle2D2 == null) { throw new ArgumentNullException(nameof(rectangle2D2)); } rectangle2D2.MiddleLine2D = new Line2D( new Vector2D(nativeCenterRectPoint.X - width / 2, nativeCenterRectPoint.Y), new Vector2D(nativeCenterRectPoint.X + width / 2, nativeCenterRectPoint.Y) ); rectangle2D2.Width = height; }
/// <summary> /// 判定绘制对象是否在某个矩形区域内; /// </summary> /// <param name="rect">区域(工程数学坐标为准)</param> /// <param name="anyPoint">是否模糊匹配,即判定相交是否满足条件</param> /// <param name="canvasProxy">视图单位转化器,可用于内部进行误差判断</param> /// <returns></returns> public virtual bool ObjectInRectangle(Rectangle2D2 rect, ICanvasScreenConvertable canvasProxy, bool anyPoint) => false;
public DragSelectEventArgs(Vector2D position, Rectangle2D2 rectangle2D, DrawObject[] hitedDrawObjects) { Position = position ?? throw new ArgumentNullException(nameof(position)); Rectangle2D = rectangle2D ?? throw new ArgumentNullException(nameof(rectangle2D)); HitedDrawObjects = hitedDrawObjects ?? throw new ArgumentNullException(nameof(hitedDrawObjects)); }
public override bool ObjectInRectangle(Rectangle2D2 rect, ICanvasScreenConvertable canvasProxy, bool anyPoint) { return(false); }