private void MenuRemovePoint(object sender, RoutedEventArgs e) { RemovePoint(selectedLinePoint); selectedLinePoint = null; selectedPoint = null; UpdateRawPoints(); }
private void GraphControl_KeyDown(object sender, KeyEventArgs e) { switch (e.Key) { case Key.LeftShift: currentMode = ManipulateMode.Vertical; Cursor = Cursors.SizeNS; break; case Key.LeftCtrl: currentMode = ManipulateMode.Horizontal; Cursor = Cursors.SizeWE; break; case Key.Delete: { if (selectedLinePoint != null) { RemovePoint(selectedLinePoint); selectedLinePoint = null; } } break; } }
private void MainWindow_MouseDoubleClick(object sender, MouseButtonEventArgs e) { CustomPoint point = GetPointAt(e.GetPosition(this)); if (point == null) { AddPoint(e.GetPosition(this)); } }
CustomPoint GetClosestLinePoint(CustomPoint controlPoint) { int i = points.IndexOf(controlPoint); if (points[i - 1].isLinePoint) { return(points[i - 1]); } else { return(points[i + 1]); } }
List <CustomPoint> GetControlPoints(CustomPoint linePoint) { int i = points.IndexOf(linePoint); List <CustomPoint> cpPoints = new List <CustomPoint>(); if (i > 0) { cpPoints.Add(points[i - 1]); } if (i < points.Count - 1) { cpPoints.Add(points[i + 1]); } return(cpPoints); }
CustomPoint GetMirrorControlPoint(CustomPoint controlPoint) { int i = points.IndexOf(controlPoint); if (points[i + 1].isLinePoint && points.Count > i + 2) { return(points[i + 2]); } else if (i > 1 && !points[i - 2].isLinePoint) { return(points[i - 2]); } else { return(null); } }
void SelectPointAt(Point position) { CustomPoint point = GetPointAt(position); foreach (CustomPoint p in points) { if (!p.isLinePoint) { p.visible = false; } } selectedPoint = null; selectedLinePoint = null; if (point != null) { int i = points.IndexOf(point); if (point.isLinePoint) { if (points.Count > i + 1) { points[i + 1].visible = true; } if (i > 1) { points[i - 1].visible = true; } selectedLinePoint = point; } else { point.visible = true; CustomPoint mirror = GetMirrorControlPoint(point); if (mirror != null) { mirror.visible = true; } selectedLinePoint = GetClosestLinePoint(point); } selectedPoint = point; } }
CustomPoint GetLinePointToTheRight(CustomPoint controlPoint) { int i = points.IndexOf(controlPoint); i++; while (i < points.Count) { if (points[i].isLinePoint) { return(points[i]); } else { i++; } } return(null); }
CustomPoint GetLinePointToTheLeft(CustomPoint controlPoint) { int i = points.IndexOf(controlPoint); i--; while (i >= 0) { if (points[i].isLinePoint) { return(points[i]); } else { i--; } } return(null); }
public void AddPoints(List <Point> newPoints) { ClearList(); for (int i = 0; i < newPoints.Count; ++i) { Point point = newPoints[i]; CustomPoint cp = new CustomPoint(point.X * gridSpacing, point.Y * gridSpacing); if (points.Count == 0) { points.Add(cp); } else { points.Add(cp); rawPoints.Add(cp.p); } if (i % 3 == 0) { cp.visible = true; cp.isLinePoint = true; } } }
void RemovePoint(CustomPoint point) { int pointIndex = points.IndexOf(point); bool lastPoint = pointIndex == points.Count - 1; foreach (CustomPoint cp in GetControlPoints(point)) { points.Remove(cp); } points.Remove(point); if (pointIndex == 0 && points.Count > 0) { points.RemoveAt(0); } else if (lastPoint && points.Count > 0) { points.RemoveAt(points.Count - 1); } UpdateRawPoints(); InvalidateVisual(); }
private void MainWindow_MouseMove(object sender, MouseEventArgs e) { if (currentMode == ManipulateMode.All) { Cursor = Cursors.Arrow; } CustomPoint over = GetPointAt(e.GetPosition(this)); if (over != null) { Cursor = Cursors.SizeAll; } if (e.LeftButton == MouseButtonState.Pressed) { if (selectedPoint != null) { Cursor = Cursors.SizeAll; HandleMovement(e.GetPosition(this)); InvalidateVisual(); OnPointsChanged?.Invoke(); UpdateRawPoints(); } else { double deltaX = e.GetPosition(this).X - prevMouseX; double deltaY = e.GetPosition(this).Y - prevMouseY; Cursor = Cursors.Hand; translateTransform.X += deltaX; translateTransform.Y -= deltaY; InvalidateVisual(); } } prevMouseX = e.GetPosition(this).X; prevMouseY = e.GetPosition(this).Y; }
private void HandleMovement(Point targetPoint) { Point validPos = GetValidPosition(selectedPoint, targetPoint); Point deltaMovement = new Point(selectedPoint.p.X - validPos.X, selectedPoint.p.Y - validPos.Y); if (selectedPoint == selectedLinePoint) { foreach (CustomPoint cp in GetControlPoints(selectedLinePoint)) { Point newPos = new Point(cp.p.X - deltaMovement.X, cp.p.Y - deltaMovement.Y); cp.MoveTo(GetValidPosition(cp, newPos)); } validPos = GetValidPosition(selectedPoint, targetPoint); selectedPoint.MoveTo(validPos); } else //is a control point { selectedPoint.MoveTo(validPos); CustomPoint mirror = GetMirrorControlPoint(selectedPoint); if (mirror != null && !selectedLinePoint.unlockedControlPoints) { Point cpDelta = new Point(selectedPoint.p.X - selectedLinePoint.p.X, selectedPoint.p.Y - selectedLinePoint.p.Y); Point newPos = new Point(selectedLinePoint.p.X - cpDelta.X, selectedLinePoint.p.Y - cpDelta.Y); mirror.MoveTo(GetValidPosition(mirror, newPos)); int i = points.IndexOf(selectedPoint) % 3; if ((i == 1 && selectedPoint.X <= mirror.X) || (i == 2 && selectedPoint.X >= mirror.X)) { int a = points.IndexOf(selectedPoint); int b = points.IndexOf(mirror); points[a] = mirror; points[b] = selectedPoint; } } } }
public void OnLostFocus() { selectedLinePoint = null; selectedPoint = null; InvalidateVisual(); }
protected override void OnRender(DrawingContext drawingContext) { if (points.Count > 0) { start.StartPoint = points[0].p; } int dynamicGridSpacingX = (int)(gridSpacing / scaleTransform.ScaleX); int dynamicGridSpacingY = (int)(gridSpacing / scaleTransform.ScaleY); double width = RenderSize.Width != 0 ? RenderSize.Width : 1000; double height = RenderSize.Height != 0 ? RenderSize.Height : 1000; int startX = (int)(Math.Round((-translateTransform.X) / dynamicGridSpacingX) * dynamicGridSpacingX) - dynamicGridSpacingX; int endX = (int)(Math.Round(((-translateTransform.X + width)) / dynamicGridSpacingX) * dynamicGridSpacingX) + dynamicGridSpacingX; int startY = (int)(Math.Round((-translateTransform.Y) / dynamicGridSpacingY) * dynamicGridSpacingY) - dynamicGridSpacingY; int endY = (int)(Math.Round(((-translateTransform.Y + height)) / dynamicGridSpacingY) * dynamicGridSpacingY) + dynamicGridSpacingY; drawingContext.PushTransform(new ScaleTransform(1, -1)); drawingContext.DrawRectangle(Brushes.Gray, null, new Rect(startX - gridSpacing, startY - gridSpacing, Math.Abs(endX - startX) + gridSpacing, Math.Abs(endY - startY) + gridSpacing)); //grid double largestScale = (scaleTransform.ScaleX + scaleTransform.ScaleY) / 2; for (int x = startX; x < endX; x += dynamicGridSpacingX) // x-axis { drawingContext.DrawLine(new Pen(Brushes.DimGray, 1.0 / scaleTransform.ScaleX), new Point(x, startY), new Point(x, endY)); drawingContext.PushTransform(new ScaleTransform(scaleTransform.ScaleY, scaleTransform.ScaleX)); if (x != 0) { FormattedText ft = new FormattedText((x / (float)gridSpacing).ToString(), CultureInfo.GetCultureInfo("en-us"), FlowDirection.LeftToRight, new Typeface("Verdana"), 12 / Math.Pow(largestScale, 2), System.Windows.Media.Brushes.Black); ft.TextAlignment = TextAlignment.Center; drawingContext.DrawText(ft, new System.Windows.Point(x / scaleTransform.ScaleY, 1.0 / scaleTransform.ScaleX)); } drawingContext.PushTransform(new ScaleTransform(1 / scaleTransform.ScaleY, 1 / scaleTransform.ScaleX)); } for (int y = startY; y < endY; y += (int)(gridSpacing / scaleTransform.ScaleY)) //y-axis { drawingContext.DrawLine(new Pen(Brushes.DimGray, 1.0 / scaleTransform.ScaleY), new Point(startX, y), new Point(endX, y)); drawingContext.PushTransform(new ScaleTransform(scaleTransform.ScaleY, scaleTransform.ScaleX)); if (y != 0) { FormattedText ft = new FormattedText((-y / (float)gridSpacing).ToString(), CultureInfo.GetCultureInfo("en-us"), FlowDirection.LeftToRight, new Typeface("Verdana"), 12 / Math.Pow(largestScale, 2), System.Windows.Media.Brushes.Black); ft.TextAlignment = TextAlignment.Right; drawingContext.DrawText(ft, new System.Windows.Point(-1.0 / scaleTransform.ScaleY, (y / scaleTransform.ScaleX))); } //else //{ // FormattedText ft = new FormattedText("0", // CultureInfo.GetCultureInfo("en-us"), // FlowDirection.LeftToRight, // new Typeface("Verdana"), // 1.0/ avgScale, System.Windows.Media.Brushes.Black); // ft.TextAlignment = TextAlignment.Right; // drawingContext.DrawText(ft, new System.Windows.Point(-1.0/ scaleTransform.ScaleY, 2.0/ scaleTransform.ScaleX)); //} drawingContext.PushTransform(new ScaleTransform(1 / scaleTransform.ScaleY, 1 / scaleTransform.ScaleX)); } // drawingContext.PushTransform(new ScaleTransform(1/scaleTransform.ScaleY, 1/scaleTransform.ScaleX)); //axis drawingContext.DrawLine(new Pen(Brushes.Black, 1.0 / largestScale), new Point(startX, 0), new Point(endX, 0)); drawingContext.DrawLine(new Pen(Brushes.Black, 1.0 / largestScale), new Point(0, startY), new Point(0, endY)); //unselected points drawingContext.PushTransform(new ScaleTransform(1, -1)); foreach (CustomPoint point in points) { if (point.isLinePoint && point != selectedLinePoint) { drawingContext.DrawRectangle(Brushes.Red, null, point.GetOffsetRect(scaleTransform)); } } //selected point if (selectedLinePoint != null) { CustomPoint point = selectedLinePoint; drawingContext.DrawRectangle(Brushes.Green, null, point.GetOffsetRect(scaleTransform)); foreach (CustomPoint cpPoint in GetControlPoints(selectedLinePoint)) { point = cpPoint; Rect offsetRect = point.GetOffsetRect(scaleTransform); drawingContext.DrawEllipse(Brushes.Green, null, point.p, offsetRect.Width / 2, offsetRect.Height / 2); drawingContext.DrawLine(new Pen(Brushes.Teal, 2 / scaleTransform.ScaleX), selectedLinePoint.p, cpPoint.p); } } base.OnRender(drawingContext); }
private void GraphControl_MouseUp(object sender, MouseButtonEventArgs e) { selectedPoint = null; }
Point GetValidPosition(CustomPoint targetPoint, Point TargetPos) { int i = points.IndexOf(targetPoint); float mouseX = (float)TargetPos.X; bool movingLeft = targetPoint.p.X > mouseX; if (!targetPoint.isLinePoint) //control point { if (movingLeft) { CustomPoint leftPoint = GetLinePointToTheLeft(targetPoint); if (leftPoint.p.X > mouseX) { TargetPos.X = leftPoint.X; } } else { CustomPoint rightPoint = GetLinePointToTheRight(targetPoint); if (rightPoint.p.X < mouseX) { TargetPos.X = rightPoint.X; } } } else { if (movingLeft && i != 0) { CustomPoint leftCP = points[i - 1]; if (leftCP.p.X > mouseX) { TargetPos.X = leftCP.X; } if (i - 2 > 0) { CustomPoint leftLineRCP = points[i - 2]; if (leftLineRCP.p.X > mouseX) { TargetPos.X = leftLineRCP.X; } } } else if (i < points.Count - 1) { CustomPoint rightCP = points[i + 1]; if (rightCP.p.X < mouseX) { TargetPos.X = rightCP.X; } if (i + 2 < points.Count) { CustomPoint RightLineLCP = points[i + 2]; if (RightLineLCP.p.X < mouseX) { TargetPos.X = RightLineLCP.X; } } } } return(TargetPos); }
private void AddPoint(Point pos) { CustomPoint linePoint = new CustomPoint(pos.X, pos.Y); if (points.Count == 0) { points.Add(linePoint); } else { CustomPoint prevPoint = null; int i; for (i = 0; i < points.Count; i += 3) { if (linePoint.X < points[i].X) { break; } prevPoint = points[i]; } if (prevPoint == null) { prevPoint = points[0]; Vector dir = new Vector(prevPoint.X - pos.X, prevPoint.Y - pos.Y); CustomPoint cp1 = new CustomPoint(pos.X + dir.X * 0.45, pos.Y); CustomPoint cp2 = new CustomPoint(prevPoint.X - dir.X * 0.45, prevPoint.Y); points.Insert(0, cp2); points.Insert(0, cp1); points.Insert(0, linePoint); } else if (prevPoint != points[points.Count - 1]) { CustomPoint nextPoint = points[i]; Vector dir1 = new Vector(prevPoint.X - pos.X, prevPoint.Y - pos.Y); Vector dir2 = new Vector(nextPoint.X - pos.X, nextPoint.Y - pos.Y); Vector dir = dir1.Length > dir2.Length ? dir2 : dir1; CustomPoint cp1 = new CustomPoint(pos.X - Math.Abs(dir.X) * 0.45, pos.Y); CustomPoint cp2 = new CustomPoint(pos.X + Math.Abs(dir.X) * 0.45, pos.Y); //Update previousPoint's right CP Vector prevCPvec = new Vector(points[i - 2].X - prevPoint.X, points[i - 2].Y - prevPoint.Y); Point tempCP = new Point(points[i - 2].X, points[i - 2].Y); Point prevAsPoint = new Point(prevPoint.X, prevPoint.Y); Vector tempUnit = (prevCPvec / prevCPvec.Length); double scalar = (-dir1 * tempUnit); tempCP = prevAsPoint + tempUnit * scalar * 0.45; points[i - 2] = new CustomPoint(tempCP.X, tempCP.Y); //Update nextPoint's left CP Vector nextCPvec = new Vector(points[i - 1].X - nextPoint.X, points[i - 1].Y - nextPoint.Y); tempCP = new Point(points[i - 1].X, points[i - 1].Y); Point nextAsPoint = new Point(nextPoint.X, nextPoint.Y); tempUnit = (prevCPvec / prevCPvec.Length); scalar = (-dir2 * tempUnit); tempCP = nextAsPoint + tempUnit * scalar * 0.45; points[i - 1] = new CustomPoint(tempCP.X, tempCP.Y); points.Insert(i - 1, cp2); points.Insert(i - 1, linePoint); points.Insert(i - 1, cp1); } else { Vector dir = new Vector(pos.X - prevPoint.X, pos.Y - prevPoint.Y); CustomPoint cp1 = new CustomPoint(prevPoint.X + dir.X * 0.45, prevPoint.Y); CustomPoint cp2 = new CustomPoint(pos.X - dir.X * 0.45, pos.Y); points.Add(cp1); points.Add(cp2); points.Add(linePoint); } } UpdateRawPoints(); linePoint.visible = true; linePoint.isLinePoint = true; InvalidateVisual(); }