Для первой части вашего вопроса посмотрите на этот пост , который имеет функцию сокращения для List<Point>
.Обратите внимание, что коллекция GraphicsPath.PathPoints
доступна только для чтения, поэтому вам придется заново создать путь из списка сокращенных точек.
Несколько замечаний ко второй части:
Нет встроенной подпрограммы для создания дескрипторов.Ни заставлять их делать что-либо.Поэтому вам нужно написать для них код.
Я добавляю простой класс MoveLabel
, который можно использовать для этого.Его можно поместить на элемент управления или добавить в его коллекцию Controls
.Тогда вы можете переместить его.Я добавил функцию обратного вызова MoveAction
для обработки результата при отпускании мыши.
Вы можете добавить ..
public delegate void Moved(MoveLabel sender);
.. к классу формы, или, чтобы избежать ссылки Form1
, вне класса формыно в области действия MoveLabel
.
. Может использоваться непосредственно для перемещения точек в списке точек:
Создать его на панели:
var lab= new MoveLabel(Color.CadetBlue, 9, Point.Round(points[i]), i);
lab.Parent = panel;
lab.MoveAction = moved;
Простойфункция обработки:
void moved(MoveLabel sender)
{
points[sender.PointIndex] =
new Point(sender.Left - sender.Width / 2, sender.Top - sender.Height / 2);
panel.Invalidate();
}
Обратите внимание, что GraphicsPath.PathPoints
только для чтения, поэтому мы должны заново создать путь из нового списка точек!На самом деле можно изменить индивидуальный PathPoints
в коде, но результат не прилипает;поэтому нужно скопировать PathPoints
в PointF[]
, изменить их там и заново создать путь.Для сложных путей лучше всего использовать эту перегрузку ..
Если вы хотите реализовать вращение (или другие преобразования), вы можете использовать функцию GraphicsPath.Transform .Вы можете использовать подвижные метки для определения данных поворота или масштабирования. Вот мой минимальный класс MoveLabel
:
public class MoveLabel : Label
{
public Form1.Moved MoveAction { get; set; }
public int PointIndex { get; set; }
private Point mDown = Point.Empty;
public MoveLabel()
{
MouseDown += (ss, ee) => { mDown = ee.Location; };
MouseMove += (ss, ee) => {
if (ee.Button.HasFlag(MouseButtons.Left))
{
Location = new Point(Left + ee.X - Width / 2, Top + ee.Y - Height / 2);
mDown = Location;
}
};
MouseUp += (ss, ee) => { if (MoveAction != null) MoveAction(this); };
}
public MoveLabel(Color c, int size, Point location, int pointIndex) : this()
{
BackColor = Color.CadetBlue;
Size = new Size(size, size);
Location = location;
PointIndex = pointIndex;
}
}
Это также будет хорошо работать для перемещения точек из кривых Безье.Добавив вызов MoveAction(this);
к коду MouseMove
linq, вы можете получать живые обновления. Убедитесь, что Panels
DoubleBuffered для этого: -)
Пример:
Кстати: я только что натолкнулся на этот пост , который показывает, насколько легко можно нарисовать кривую или любую другую векторную графику GDI +сохранено в emf
, сохраняя качество вектора!
Обновление: Вместо Panel
, который является элементом управления Container
и не предназначен для рисования на вас.можно использовать Picturebox
или Label
(с Autosize=false
);оба имеют свойство DoubleBuffered
, включенное из коробки, и поддерживают рисование лучше, чем Panels
do.