finished candybox
This commit is contained in:
@@ -13,19 +13,140 @@ using OpenCvSharp;
|
||||
using OpenCvSharp.Extensions;
|
||||
using Point = System.Drawing.Point;
|
||||
|
||||
|
||||
namespace Lindt.Candybox.Demo
|
||||
{
|
||||
public enum EditMode
|
||||
{
|
||||
Brush,
|
||||
DrawLine,
|
||||
RemoveLine,
|
||||
MoveLine,
|
||||
MoveVertices
|
||||
}
|
||||
|
||||
public class VectorLine
|
||||
{
|
||||
public Point StartPoint { get; set; }
|
||||
public Point EndPoint { get; set; }
|
||||
public bool Selected { get; set; }
|
||||
|
||||
public VectorLine()
|
||||
{
|
||||
}
|
||||
|
||||
public VectorLine Scale(float sX, float sY)
|
||||
{
|
||||
return new VectorLine(new Point((int)(StartPoint.X * sX), (int)(StartPoint.Y * sY)),
|
||||
new Point((int)(EndPoint.X * sX), (int)(EndPoint.Y * sY)));
|
||||
}
|
||||
|
||||
public VectorLine(Point start, Point end)
|
||||
{
|
||||
StartPoint = start;
|
||||
EndPoint = end;
|
||||
Selected = false;
|
||||
}
|
||||
|
||||
public bool IsPointOnLine(Point point, int tolerance = 10)
|
||||
{
|
||||
// Calculate distance from point to line segment
|
||||
double A = point.X - StartPoint.X;
|
||||
double B = point.Y - StartPoint.Y;
|
||||
double C = EndPoint.X - StartPoint.X;
|
||||
double D = EndPoint.Y - StartPoint.Y;
|
||||
|
||||
double dot = A * C + B * D;
|
||||
double lenSq = C * C + D * D;
|
||||
|
||||
if (lenSq == 0) return Math.Sqrt(A * A + B * B) <= tolerance;
|
||||
|
||||
double param = dot / lenSq;
|
||||
|
||||
double xx, yy;
|
||||
if (param < 0)
|
||||
{
|
||||
xx = StartPoint.X;
|
||||
yy = StartPoint.Y;
|
||||
}
|
||||
else if (param > 1)
|
||||
{
|
||||
xx = EndPoint.X;
|
||||
yy = EndPoint.Y;
|
||||
}
|
||||
else
|
||||
{
|
||||
xx = StartPoint.X + param * C;
|
||||
yy = StartPoint.Y + param * D;
|
||||
}
|
||||
|
||||
double dx = point.X - xx;
|
||||
double dy = point.Y - yy;
|
||||
return Math.Sqrt(dx * dx + dy * dy) <= tolerance;
|
||||
}
|
||||
|
||||
public bool IsPointNearVertex(Point point, out bool isStartVertex, int tolerance = 15)
|
||||
{
|
||||
isStartVertex = false;
|
||||
double distToStart = Math.Sqrt(Math.Pow(point.X - StartPoint.X, 2) + Math.Pow(point.Y - StartPoint.Y, 2));
|
||||
double distToEnd = Math.Sqrt(Math.Pow(point.X - EndPoint.X, 2) + Math.Pow(point.Y - EndPoint.Y, 2));
|
||||
|
||||
if (distToStart <= tolerance)
|
||||
{
|
||||
isStartVertex = true;
|
||||
return true;
|
||||
}
|
||||
if (distToEnd <= tolerance)
|
||||
{
|
||||
isStartVertex = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public partial class MaskControl : UserControl
|
||||
{
|
||||
private Bitmap _backBuffer;
|
||||
private GrahamConvexHull _hull;
|
||||
private List<VectorLine> _vectorLines;
|
||||
private EditMode _currentMode = EditMode.Brush;
|
||||
private bool _isDrawingLine = false;
|
||||
private Point _lineStartPoint;
|
||||
private VectorLine _selectedLine;
|
||||
private bool _isDraggingLine = false;
|
||||
private bool _isDraggingVertex = false;
|
||||
private bool _isDraggingStartVertex = false;
|
||||
private Point _dragOffset;
|
||||
|
||||
public MaskControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
_backBuffer = new Bitmap(1800, 1408);
|
||||
_hull = new GrahamConvexHull();
|
||||
_vectorLines = new List<VectorLine>();
|
||||
}
|
||||
|
||||
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public EditMode CurrentMode
|
||||
{
|
||||
get => _currentMode;
|
||||
set
|
||||
{
|
||||
_currentMode = value;
|
||||
// Clear any ongoing operations when mode changes
|
||||
_isDrawingLine = false;
|
||||
_isDraggingLine = false;
|
||||
_isDraggingVertex = false;
|
||||
_selectedLine = null;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public List<VectorLine> VectorLines
|
||||
{
|
||||
get => _vectorLines;
|
||||
set => _vectorLines = value;
|
||||
}
|
||||
|
||||
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
|
||||
@@ -41,55 +162,138 @@ namespace Lindt.Candybox.Demo
|
||||
private bool _isDown = false;
|
||||
private Point _lastMouse;
|
||||
|
||||
|
||||
protected override void OnMouseDown(MouseEventArgs e)
|
||||
{
|
||||
_isDown = true;
|
||||
_lastMouse = ConvertCoordinates(new Point(e.X, e.Y));
|
||||
|
||||
switch (_currentMode)
|
||||
{
|
||||
case EditMode.DrawLine:
|
||||
if (!_isDrawingLine)
|
||||
{
|
||||
_isDrawingLine = true;
|
||||
_lineStartPoint = _lastMouse;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Finish drawing line
|
||||
var newLine = new VectorLine(_lineStartPoint, _lastMouse);
|
||||
_vectorLines.Add(newLine);
|
||||
_isDrawingLine = false;
|
||||
Invalidate();
|
||||
}
|
||||
break;
|
||||
|
||||
case EditMode.RemoveLine:
|
||||
var lineToRemove = _vectorLines.FirstOrDefault(line => line.IsPointOnLine(_lastMouse));
|
||||
if (lineToRemove != null)
|
||||
{
|
||||
_vectorLines.Remove(lineToRemove);
|
||||
Invalidate();
|
||||
}
|
||||
break;
|
||||
|
||||
case EditMode.MoveLine:
|
||||
_selectedLine = _vectorLines.FirstOrDefault(line => line.IsPointOnLine(_lastMouse));
|
||||
if (_selectedLine != null)
|
||||
{
|
||||
_isDraggingLine = true;
|
||||
_dragOffset = new Point(_lastMouse.X - _selectedLine.StartPoint.X, _lastMouse.Y - _selectedLine.StartPoint.Y);
|
||||
}
|
||||
break;
|
||||
|
||||
case EditMode.MoveVertices:
|
||||
foreach (var line in _vectorLines)
|
||||
{
|
||||
if (line.IsPointNearVertex(_lastMouse, out bool isStartVertex))
|
||||
{
|
||||
_selectedLine = line;
|
||||
_isDraggingVertex = true;
|
||||
_isDraggingStartVertex = isStartVertex;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnMouseUp(MouseEventArgs e)
|
||||
{
|
||||
_isDown = false;
|
||||
_isDraggingLine = false;
|
||||
_isDraggingVertex = false;
|
||||
}
|
||||
|
||||
private Pen _pen = new Pen(Color.White, 30);
|
||||
private Pen _penBlack = new Pen(Color.Black, 30);
|
||||
|
||||
protected override void OnMouseMove(MouseEventArgs e)
|
||||
{
|
||||
var currentPoint = ConvertCoordinates(new Point(e.X, e.Y));
|
||||
|
||||
if (_isDown&&e.Button==MouseButtons.Left)
|
||||
// Handle brush mode (existing functionality)
|
||||
if (_currentMode == EditMode.Brush)
|
||||
{
|
||||
var curPoint = ConvertCoordinates(new Point(e.X, e.Y));
|
||||
using (Graphics g = Graphics.FromImage(Mask))
|
||||
if (_isDown && e.Button == MouseButtons.Left)
|
||||
{
|
||||
g.DrawLine(_pen, curPoint.X, curPoint.Y,_lastMouse.X,_lastMouse.Y);
|
||||
g.FillEllipse(Brushes.White, _lastMouse.X - 15, _lastMouse.Y - 15, 30,30);
|
||||
using (Graphics g = Graphics.FromImage(Mask))
|
||||
{
|
||||
g.DrawLine(_pen, currentPoint.X, currentPoint.Y, _lastMouse.X, _lastMouse.Y);
|
||||
g.FillEllipse(Brushes.White, _lastMouse.X - 15, _lastMouse.Y - 15, 30, 30);
|
||||
}
|
||||
}
|
||||
if (_isDown && e.Button == MouseButtons.Right)
|
||||
{
|
||||
using (Graphics g = Graphics.FromImage(Mask))
|
||||
{
|
||||
g.DrawLine(_penBlack, currentPoint.X, currentPoint.Y, _lastMouse.X, _lastMouse.Y);
|
||||
g.FillEllipse(Brushes.Black, _lastMouse.X - 15, _lastMouse.Y - 15, 30, 30);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (_isDown && e.Button == MouseButtons.Right)
|
||||
// Handle line dragging
|
||||
else if (_currentMode == EditMode.MoveLine && _isDraggingLine && _selectedLine != null)
|
||||
{
|
||||
var curPoint = ConvertCoordinates(new Point(e.X, e.Y));
|
||||
using (Graphics g = Graphics.FromImage(Mask))
|
||||
var deltaX = currentPoint.X - _lastMouse.X;
|
||||
var deltaY = currentPoint.Y - _lastMouse.Y;
|
||||
|
||||
_selectedLine.StartPoint = new Point(_selectedLine.StartPoint.X + deltaX, _selectedLine.StartPoint.Y + deltaY);
|
||||
_selectedLine.EndPoint = new Point(_selectedLine.EndPoint.X + deltaX, _selectedLine.EndPoint.Y + deltaY);
|
||||
}
|
||||
// Handle vertex dragging
|
||||
else if (_currentMode == EditMode.MoveVertices && _isDraggingVertex && _selectedLine != null)
|
||||
{
|
||||
if (_isDraggingStartVertex)
|
||||
{
|
||||
g.DrawLine(_penBlack, curPoint.X, curPoint.Y, _lastMouse.X, _lastMouse.Y);
|
||||
g.FillEllipse(Brushes.Black, _lastMouse.X - 15, _lastMouse.Y - 15, 30, 30);
|
||||
_selectedLine.StartPoint = currentPoint;
|
||||
}
|
||||
else
|
||||
{
|
||||
_selectedLine.EndPoint = currentPoint;
|
||||
}
|
||||
}
|
||||
_lastMouse = ConvertCoordinates(new Point(e.X, e.Y));
|
||||
|
||||
_lastMouse = currentPoint;
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
private Pen _contourPen = new Pen(Color.GreenYellow, 3);
|
||||
private Pen _vectorLinePen = new Pen(Color.DeepPink, 12);
|
||||
private Brush _vertexBrush = new SolidBrush(Color.Orange);
|
||||
|
||||
protected override void OnPaint(PaintEventArgs e)
|
||||
{
|
||||
var mat = Mask.ToMat().CvtColor(ColorConversionCodes.BGR2GRAY);
|
||||
var contours = mat.FindContoursAsArray(RetrievalModes.External, ContourApproximationModes.ApproxNone);
|
||||
LastContours = contours;
|
||||
|
||||
using (Graphics g = Graphics.FromImage(_backBuffer))
|
||||
{
|
||||
g.Clear(Color.Transparent);
|
||||
g.DrawImage(Original, 0, 0);
|
||||
|
||||
// Draw contours
|
||||
for (int i = 0; i < contours.Length; i++)
|
||||
{
|
||||
if (contours[i].Length > 1)
|
||||
@@ -98,10 +302,46 @@ namespace Lindt.Candybox.Demo
|
||||
g.DrawPolygon(_contourPen, points);
|
||||
}
|
||||
}
|
||||
g.DrawEllipse(Pens.Gray,_lastMouse.X-15, _lastMouse.Y - 15,30,30);
|
||||
|
||||
// Draw vector lines
|
||||
foreach (var line in _vectorLines)
|
||||
{
|
||||
// Convert coordinates back to display coordinates
|
||||
var startDisplay = new Point(line.StartPoint.X , line.StartPoint.Y );
|
||||
var endDisplay = new Point(line.EndPoint.X , line.EndPoint.Y );
|
||||
|
||||
g.DrawLine(_vectorLinePen, startDisplay, endDisplay);
|
||||
|
||||
// Draw vertices when in move vertices mode
|
||||
if (_currentMode == EditMode.MoveVertices)
|
||||
{
|
||||
g.FillEllipse(_vertexBrush, startDisplay.X - 5, startDisplay.Y - 5, 10, 10);
|
||||
g.FillEllipse(_vertexBrush, endDisplay.X - 5, endDisplay.Y - 5, 10, 10);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw temporary line when drawing
|
||||
if (_currentMode == EditMode.DrawLine && _isDrawingLine)
|
||||
{
|
||||
var startDisplay = new Point(_lineStartPoint.X , _lineStartPoint.Y );
|
||||
var endDisplay = new Point(_lastMouse.X , _lastMouse.Y );
|
||||
using (var tempPen = new Pen(Color.DeepPink, 12) { DashStyle = System.Drawing.Drawing2D.DashStyle.Dash })
|
||||
{
|
||||
g.DrawLine(tempPen, startDisplay, endDisplay);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw mouse cursor indicator for brush mode
|
||||
if (_currentMode == EditMode.Brush)
|
||||
{
|
||||
var cursorDisplay = new Point(_lastMouse.X , _lastMouse.Y );
|
||||
g.DrawEllipse(Pens.Gray, cursorDisplay.X - 15, cursorDisplay.Y - 15, 30, 30);
|
||||
}
|
||||
}
|
||||
e.Graphics.DrawImage(_backBuffer,0, 0,Width,Height);
|
||||
|
||||
e.Graphics.DrawImage(_backBuffer, 0, 0, Width, Height);
|
||||
}
|
||||
|
||||
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public OpenCvSharp.Point[][] LastContours { get; set; }
|
||||
|
||||
@@ -113,7 +353,6 @@ namespace Lindt.Candybox.Demo
|
||||
protected override void OnResize(EventArgs e)
|
||||
{
|
||||
base.OnResize(e);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user