/// <summary> /// Подключаем к фигуре геометрию полигона /// </summary> /// <param name="figure"></param> /// <param name="vertexCount">Количество вершин</param> public static void BuildRegularGeometry(Figure figure, int vertexCount) { if (vertexCount < 3) { throw new ArgumentOutOfRangeException("vertexCount", "Количество вершин должно быть три и более."); } const float radius = 0.5f; var points = new List <PointF>(); var stepAngle = Math.PI * 2 / vertexCount; var angle = -Math.PI * 2; for (var i = 0; i < vertexCount; i++) { points.Add(new PointF((float)(radius * Math.Cos(angle)), (float)(radius * Math.Sin(angle)))); angle += stepAngle; } var path = new SerializableGraphicsPath(); path.Path.AddPolygon(points.ToArray()); var names = new[] { "Nothing", "Circle", "Line", "Triangle", "Romb", "Pentagon", "Gexagon" }; figure.Geometry = new PrimitiveGeometry(path, AllowedOperations.All ^ (AllowedOperations.Vertex | AllowedOperations.Size | AllowedOperations.Skew)) { Name = vertexCount <= 6 ? names[vertexCount] : "Regular" + vertexCount }; }
public GroupFigure(List <Figure> figures = null) { if (figures == null) { _placeHolder = new Placeholder(); figures = new List <Figure> { _placeHolder }; } Style.BorderStyle = null; var path = new SerializableGraphicsPath(); path.Path.AddRectangle(new RectangleF(-0.5f, -0.5f, 1, 1)); foreach (var figure in figures) { var fig = figure.DeepClone(); fig.Transform.Matrix.Multiply(Transform, MatrixOrder.Append); _figures.Add(fig); } Geometry = new PrimitiveGeometry(path, AllowedOperations.All ^ (AllowedOperations.Vertex | AllowedOperations.Pathed)) { Name = "Group" }; Renderer = new GroupRenderer(); Transform = new SerializableGraphicsMatrix(); }
/// <summary> /// Копирование геометрий выделенных фигур в свою геометрию /// </summary> private void GrabGeometry() { // захватываем геометрию выбранных фигур var path = new SerializableGraphicsPath(); foreach (var fig in _selected) { path.Path.SetMarkers(); path.Path.AddPath(fig.GetTransformedPath(), false); } // нарисовать рамку вокруг выбранных фигур if (IsFrameVisible) { var bounds = path.Path.GetBounds(); path.Path.AddRectangle(bounds); } // выбираем разрешённые операции // если выбрана только одна фигура - просто используем её AllowedOperations // иначе - разрешаем все операции var allowedOperations = _selected.Count == 1 ? _selected.First().Geometry.AllowedOperations : AllowedOperations.All; // присваиваем геометрию Geometry = new PrimitiveGeometry(path, allowedOperations); // сбрасываем преобразование в единичную матрицу Transform = new SerializableGraphicsMatrix(); }
/// <summary> /// Конструктор, недоступный вне проекта EditorModel /// (только для внутреннего использования) /// </summary> /// <param name="path">Закрепляемый путь для примитивной геометрии</param> /// <param name="allowed">набор прав для операций</param> internal PrimitiveGeometry(SerializableGraphicsPath path, AllowedOperations allowed) { Name = "Primitive"; // запоминаем переданный в конструкторе путь в локальном поле _path = path; // запоминаем ограничения для операций в локальном поле _allowedOperations = allowed; }
/// <summary> /// Построение пути для эллипса /// </summary> /// <param name="figure">Фигура для присвоения геометрии</param> public static void BuildEllipseGeometry(Figure figure) { var path = new SerializableGraphicsPath(); path.Path.AddEllipse(new RectangleF(-0.5f, -0.5f, 1, 1)); figure.Geometry = new PrimitiveGeometry(path, AllowedOperations.All ^ AllowedOperations.Vertex) { Name = "Ellipse" }; }
/// <summary> /// Построение пути для прямоугольника со скругленными углами /// </summary> /// <param name="figure">Фигура для присвоения геометрии</param> /// <param name="radius">Радиус скругления (от 0 до 0.5)</param> public static void BuildRoundedRectangleGeometry(Figure figure, float radius) { var path = new SerializableGraphicsPath(); path.Path.AddPath(RoundedRectangle.Create(new RectangleF(-0.5f, -0.5f, 1, 1), radius <0 ? 0 : radius> 0.5f ? 0.5f : radius), false); figure.Geometry = new PrimitiveGeometry(path, AllowedOperations.All ^ AllowedOperations.Vertex) { Name = "RoundedRectangle" }; }
/// <summary> /// Построение пути для маркера /// </summary> /// <param name="marker"></param> public static void BuildMarkerGeometry(Figure marker) { var path = new SerializableGraphicsPath(); marker.Style.BorderStyle.Width = 0; // здесь задаём размер макера в 5 единиц и смешение от центра маркера в -2 единицы path.Path.AddRectangle(new RectangleF(-MARKER_SIZE / 2f, -MARKER_SIZE / 2f, MARKER_SIZE, MARKER_SIZE)); marker.Geometry = new PrimitiveGeometry(path, AllowedOperations.All ^ (AllowedOperations.Size | AllowedOperations.Rotate | AllowedOperations.Select | AllowedOperations.Skew | AllowedOperations.Vertex | AllowedOperations.Pathed | AllowedOperations.Warp)) { Name = "Marker" }; }
/// <summary> /// Подключаем к фигуре геометрию и рендерер внешнего графического файла /// </summary> /// <param name="figure"></param> /// <param name="image"></param> public static void BuildImageRenderGeometry(Figure figure, Bitmap image) { var path = new SerializableGraphicsPath(); path.Path.AddRectangle(new RectangleF(-0.5f, -0.5f, 1, 1)); figure.Geometry = new PrimitiveGeometry(path, AllowedOperations.All ^ (AllowedOperations.Vertex | AllowedOperations.Pathed)) { Name = "Image" }; figure.Style.BorderStyle = null; // отключение рамки для рендера figure.Style.FillStyle = null; // отключение заливки для рендера figure.Renderer = new ImageRenderer(image); }
/// <summary> /// Предоставление трансформированной геометрии для рисования /// </summary> /// <returns>Путь для рисования</returns> public override SerializableGraphicsPath GetTransformedPath() { // создаём копию геометрии фигуры var path = new SerializableGraphicsPath { Path = { FillMode = FillMode.Winding } }; foreach (var figure in _figures) { path.Path.AddPath(figure.GetTransformedPath().Path, false); } // трансформируем её при помощи Трансформера path.Path.Transform(Transform); return(path); }
/// <summary> /// Подключаем к фигуре геометрию текстового блока /// </summary> /// <param name="figure">Фигура для присвоения геометрии</param> /// <param name="text">Текстовая строка</param> public static void BuildTextRenderGeometry(Figure figure, string text) { var path = new SerializableGraphicsPath(); path.Path.AddRectangle(new RectangleF(-0.5f, -0.5f, 1, 1)); figure.Geometry = new PrimitiveGeometry(path, AllowedOperations.All ^ (AllowedOperations.Vertex | AllowedOperations.Pathed)) { Name = "TextBlock" }; figure.Style.BorderStyle = null; // отключение рамки для рендера figure.Style.FillStyle = new DefaultFill(AllowedFillDecorators.All ^ AllowedFillDecorators.RadialGradient) { Color = Color.Black }; figure.Renderer = new TextRenderer(text); }
/// <summary> /// Подключаем к фигуре геометрию текста на кривой /// </summary> /// <param name="figure">Фигура для присвоения геометрии</param> /// <param name="text">Текстовая строка</param> public static void BuildBezierTextGeometry(Figure figure, string text) { var path = new SerializableGraphicsPath(); path.Path.AddBezier(-0.5f, -0.5f, 0, 1, 0.5f, -0.5f, 1, 1); figure.Geometry = new PrimitiveBezier(path, AllowedOperations.All ^ (AllowedOperations.Pathed | AllowedOperations.Skew)) { Name = "BezierText" }; figure.Style.BorderStyle = null; // отключение рамки для рендера figure.Style.FillStyle = new DefaultFill(AllowedFillDecorators.All ^ AllowedFillDecorators.RadialGradient) { Color = Color.Black }; figure.Renderer = new BezierTextRenderer(text) { FontSize = 14f }; }
/// <summary> /// Построение пути для маркера /// </summary> /// <param name="marker"></param> public static void BuildMarkerGeometry(Figure marker) { var path = new SerializableGraphicsPath(); marker.Style.BorderStyle.Width = 0; switch (((Marker)marker).MarkerType) { case MarkerType.ControlBezier: // управляющие маркеры Безье рисуем круглыми path.Path.AddEllipse(new RectangleF(-MARKER_SIZE / 2f, -MARKER_SIZE / 2f, MARKER_SIZE, MARKER_SIZE)); break; default: // здесь задаём размер макера в 5 единиц и смешение от центра маркера в -2 единицы path.Path.AddRectangle(new RectangleF(-MARKER_SIZE / 2f, -MARKER_SIZE / 2f, MARKER_SIZE, MARKER_SIZE)); break; } marker.Geometry = new PrimitiveGeometry(path, AllowedOperations.All ^ (AllowedOperations.Size | AllowedOperations.Rotate | AllowedOperations.Select | AllowedOperations.Skew | AllowedOperations.Vertex | AllowedOperations.Pathed | AllowedOperations.Warp)) { Name = "Marker" }; }
internal PrimitiveBezier(SerializableGraphicsPath path, AllowedOperations allowed) : base(path, allowed) { Name = "Bezier"; _points = path.Path.PathPoints; _types = path.Path.PathTypes; }
internal PrimitiveGeometry(SerializableGraphicsPath path, AllowedOperations allowed) { Name = "Primitive"; _path = path; _allowedOperations = allowed; }