Home > Net >  C# Rotate polygon inside graphics path by 45
C# Rotate polygon inside graphics path by 45

Time:12-07

enter image description here

First of all big thank you to the person who answered this question How to drag and move shapes in C# and this is all based off that. I'm only starting to work with c# and WinForms so I would really appreciate any advice.

I have interface IShape and classes that implement it(Star, Rhombus). I need to display shapes on the form and move, rotate and scale them. So far I have this. I can select and move shapes. I'm not sure how to rotate a polygon using matrix, since my draw method uses GetPath() and it creates a new path every time a redraw the image and I can not modify points inside that path.

Should I create another graphics path from the original one and rotate it or do something else? Any help would be greatly appreciated.

IShape

using System;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Threading.Tasks;
using System.Drawing.Drawing2D;
using System.Collections.Generic;

namespace GSC_LR4
{
    interface IShape
    {
        GraphicsPath GetPath();
        bool Selected(PointF p);
        void Draw(Graphics g);
        void Move(PointF m);
         PointF Min();
         PointF Max();
        PointF Center();

        //void Zoom(PointF z);
        //void Mirrored(PointF h);
        GraphicsPath GetRotatedPath();
        void GetBorders();
        //void Delete(PointF s);
        void VertexClear();
        void DrawSelection(Graphics e)
    }
}

Rhombus

using System;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Threading.Tasks;
using System.Drawing.Drawing2D;
using System.Collections.Generic;

namespace GSC_LR4
{
    class Rhombus : IShape
    {
        List<PointF> VertexList { get; set; }
        public PointF maxPoint;
        public PointF minPoint;
        public PointF center;
        public Color oColor { get; set; }

        public Rhombus(PointF p)
        {
            VertexList = new List<PointF>();
            maxPoint = new PointF();
            minPoint = new PointF();
            center = p;           
        }

        public Rhombus(List<PointF> vertexes, Color color)
        {
            VertexList = vertexes.ConvertAll(item => new PointF(item.X, item.Y));
            maxPoint = new PointF();
            minPoint = new PointF();
            oColor = color;
        }

        public Rhombus(Color Color)
        {
            center = new PointF(150, 150);
            oColor = Color;
        }

        public GraphicsPath GetPath()
        {
            var path = new GraphicsPath();
            PointF[] VertexRhomb = new PointF[4];
            VertexRhomb[0].X = center.X - 80;
            VertexRhomb[0].Y = center.Y;
            VertexRhomb[1].X = center.X;
            VertexRhomb[1].Y = center.Y - 100;
            VertexRhomb[2].X = center.X   80;
            VertexRhomb[2].Y = center.Y;
            VertexRhomb[3].X = center.X;
            VertexRhomb[3].Y = center.Y   100;
           // VertexList.AddRange(VertexRhomb.ToArray());
            path.AddPolygon(VertexRhomb.ToArray());
            return path;
        }

        public GraphicsPath GetRotatedPath()
        {
            var path = new GraphicsPath();
            List<PointF> temp = new List<PointF>();
            temp.AddRange(GetPath().PathPoints);
            path.AddPolygon(temp.ToArray());
            Matrix rotateMtx = new Matrix();
            //rotateMtx.Translate(center.X, center.Y);
            rotateMtx.RotateAt(45f, center);
            //rotateMtx.Translate(-center.X, -center.Y);
            path.Transform(rotateMtx);
            return path;
        }

        public void Draw(Graphics g)
        {
            using(var path = GetPath())
            using (var brush = new SolidBrush(oColor))
                g.FillPath(brush, path);
        }

        public void Move(PointF d)
        {
            center = new PointF(center.X   d.X, center.Y   d.Y);
        }

        public bool Selected(PointF p)
        {
            bool selected = false;
            using (var path = GetPath())
                selected = path.IsVisible(p);
            return selected;
        }

        public void GetBorders()
        {
            minPoint.X = VertexList.Min(item => item.X);
            minPoint.Y = VertexList.Min(item => item.Y);
            maxPoint.X = VertexList.Max(item => item.X);
            maxPoint.Y = VertexList.Max(item => item.Y);
        }

        public PointF Min()
        {
            PointF p = new PointF();
            p.X = GetPath().PathPoints.Min(item => item.X);
            p.Y = GetPath().PathPoints.Min(item => item.Y);
            //p.X = VertexList.Min(item => item.X);
            //p.Y = VertexList.Min(item => item.Y);
            return p;
        }

        public PointF Max()
        {
            PointF p = new PointF();
            //p.X = VertexList.Max(item => item.X);
            //p.Y = VertexList.Max(item => item.Y);
            p.X = GetPath().PathPoints.Max(item => item.X);
            p.Y = GetPath().PathPoints.Max(item => item.Y);
            return p;
        }

        public PointF Center()
        {
            PointF Pmin = Min();
            PointF Pmax = Max();
            return new PointF((Pmax.X   Pmin.X) / 2, (Pmax.Y   Pmin.Y) / 2);
        }

        public void VertexClear()
        {
            VertexList.Clear();
        }

        public void DrawSelection(Graphics e)
        {
            int Xmin = (int)Min().X,
                  Ymin = (int)Min().Y;
            int Xmax = (int)Max().X,
                Ymax = (int)Max().Y;

            Pen pen = new Pen(Color.Gray);
            pen.DashStyle = DashStyle.Dash; // штрихованная линия
            e.DrawRectangle(pen, new Rectangle(Xmin, Ymin, Xmax - Xmin, Ymax - Ymin));
        }

        //public void Rotate()
        //{
            //double cos = Math.Cos(45 * Math.PI / 180); //maybe refactor 
            //double sin = Math.Sin(45 * Math.PI / 180);
            //PointF[] VertexRhomb = new PointF[4];
            //for (int i = 0; i < GetPath().PointCount; i  ) //sides = 6? 
            //{
            //    PointF p = new PointF();
            //    p.X = (float)((VertexRhomb[i].X - center.X) * cos - (VertexRhomb[i].Y - center.Y) * sin   center.X);
            //    p.Y = (float)((VertexRhomb[i].X - center.X) * sin   (VertexRhomb[i].Y - center.Y) * cos   center.Y);
            //    VertexRhomb[i] = new PointF(p.X, p.Y);
            //    //p.X = (float)(cos * ((GetPath().PathPoints[i].X) - Center().X) - sin * ((GetPath().PathPoints[i].Y) - Center().Y)   (Center().X));
            //    //p.Y = (float)(sin * ((GetPath().PathPoints[i].X) - Center().X)   cos * ((GetPath().PathPoints[i].Y) - Center().Y)   (Center().Y))

           //}
            //GetPath().AddPolygon(VertexRhomb.ToArray());
            //Matrix rotateMtx = new Matrix();
            //rotateMtx.Translate(center.X, center.Y);
            //rotateMtx.RotateAt(45f, center);
            //rotateMtx.Translate(-center.X, -center.Y);
            //using (var path = GetPath())
            //GetPath().Transform(rotateMtx);
        //}
    }
}

The code is messy I'm sorry about it but you can look at me attempts.

CodePudding user response:

Have a single method to create and return the GraphicsPath object and add properties to the interface or the implement class (depending on the shape) that defines how the path should be created and what translation and/or transformations should be applied if any.

Since any shape can be rotated, scaled, and translated, then the IShape interface is the right place to have abstract properties for these operations.

IShape

Covering here the rotation as requested.

public interface IShape
{
    GraphicsPath GetPath();
    float RotationAngle { get; set; }

    // ...etc.
}

Rhombus

The relevant implementation.

public class Rhombus : IShape
{
    //...

    public float RotationAngle { get; set; }

    public GraphicsPath GetPath()
    {
        var path = new GraphicsPath();
        var VertexRhomb = new[]
        {
            new PointF(center.X - 80, center.Y),
            new PointF(center.X, center.Y - 100),
            new PointF(center.X   80, center.Y),
            new PointF(center.X, center.Y   100)
        };
        path.AddPolygon(VertexRhomb.ToArray());

        if (RotationAngle != 0)
        {
            var mx = new Matrix();
            mx.RotateAt(RotationAngle, center);
            path.Transform(mx);
        }

        return path;
    }

    public void Draw(Graphics g)
    {
        using (var path = GetPath())
        using (var brush = new SolidBrush(oColor))
            g.FillPath(brush, path);
    }
}

Don't forget to call yourDrawingCanvas.Invalidate(); when you set a new rotation value.

  • Related