Каким образом можно построить на C# изображение шара как многогранника?

Узнай цену своей работы

Формулировка задачи:

Какие средства можно использовать в Visual Studio? И как можно это реализовать?

Должно выйти нечто из разряда трёхмерных объектов!!!

Решение задачи: «Каким образом можно построить на C# изображение шара как многогранника?»

textual
Листинг программы
class Triangle
{
    public IList<Vector3> Vertices = new Vector3[3];
    
    public IList<Triangle> ApplyBisection()
    {
        var middles = Vertices.Select((v, i) => (v + Vertices[(i + 1) % 3]) / 2).ToList();
        
        var res = new List<Triangle>();
        
        for (int i = 0; i < 3; i++)
        {
            var triangle = new Triangle();
            
            triangle.Vertices[0] = Vertices[i];
            triangle.Vertices[1] = middles[i];
            triangle.Vertices[2] = middles[(i - 1 + 3) % 3];
            
            res.Add(triangle);
        }
 
        res.Add(new Triangle { Vertices = middles });
        
        return res;
    }
 
    public Vector3 Middle => Vertices.Aggregate((r, v) => r + v) / 3;
}
 
static class FloatExtentions
{
    public static float ToDegrees(this float radians)
    {
        return (float)(radians * 180 / Math.PI);
    }
    
    public static float ToRadians(this float degrees)
    {
        return (float)(degrees * Math.PI / 180);
    }
}
 
class IcosahedronBuilder
{
    private IList<Vector3> _topRing = new List<Vector3>();
    private IList<Vector3> _bottomRing = new List<Vector3>();
    
    private Vector3 _top = new Vector3(0, 1, 0);
    private Vector3 _bottom = new Vector3(0, -1, 0);
    
    private IList<Vector3> BuildTopRing()
    {
        var result = new List<Vector3>();
        
        var basis = new Vector3(0, 0, -1);
        
        float pitch = 30f.ToRadians();
        
        for (int i = 0; i < 5; i++)
        {
            float yaw = -(360f / 5f * i).ToRadians();
            
            var transform = Matrix4x4.CreateFromYawPitchRoll(yaw, pitch, 0);
            result.Add(Vector3.Transform(basis, transform));
        }
        
        return result;
    }
    
    private IList<Vector3> BuildBottomRing(IList<Vector3> topRing)
    {
        var transform = Matrix4x4.CreateFromYawPitchRoll((360f / 10f).ToRadians(), 0, 0f.ToRadians());
        transform = transform * Matrix4x4.CreateScale(1, -1, 1);
        
        return topRing.Select(p => Vector3.Transform(p, transform)).ToList();
    }
    
    public List<Triangle> Build()
    {
        _topRing = BuildTopRing();
        _bottomRing = BuildBottomRing(_topRing);
        
        var result = new List<Triangle>();
        
        for (int i = 0; i < _topRing.Count; i++)
        {
            var triangle = new Triangle();
            
            triangle.Vertices[0] = _top;
            triangle.Vertices[1] = _topRing[i];
            triangle.Vertices[2] = _topRing[(i + 1) % _topRing.Count];
            
            result.Add(triangle);
        }
 
        for (int i = 0; i < _topRing.Count; i++)
        {
            var triangle = new Triangle();
 
            triangle.Vertices[0] = _topRing[i];
            triangle.Vertices[1] = _bottomRing[i];
            triangle.Vertices[2] = _bottomRing[(i + 1) % _bottomRing.Count];
 
            result.Add(triangle);
        }
 
        for (int i = 0; i < _bottomRing.Count; i++)
        {
            var triangle = new Triangle();
 
            triangle.Vertices[0] = _bottomRing[i];
            triangle.Vertices[1] = _topRing[i];
            triangle.Vertices[2] = _topRing[(i - 1 + _topRing.Count) % _topRing.Count];
 
            result.Add(triangle);
        }
 
        for (int i = 0; i < _bottomRing.Count; i++)
        {
            var triangle = new Triangle();
 
            triangle.Vertices[0] = _bottom;
            triangle.Vertices[1] = _bottomRing[i];
            triangle.Vertices[2] = _bottomRing[(i - 1 + _bottomRing.Count) % _bottomRing.Count];
 
            result.Add(triangle);
        }
        
        return result;
    }
}
 
class Model
{
    public IList<Triangle> Triangles = new List<Triangle>();
}
 
class MainForm : Form
{
    private Model _model = new Model();
    
    public MainForm()
    {
        base.DoubleBuffered = true;
        base.WindowState = FormWindowState.Maximized;
        
        _model.Triangles = new IcosahedronBuilder().Build();
            
        for (int i = 0; i < 2; i++)
        {
            _model.Triangles = _model.Triangles.SelectMany(t =>
            {
                IList<Triangle> derivatives = t.ApplyBisection();
                foreach (var triangle in derivatives)
                {
                    triangle.Vertices = triangle.Vertices.Select(v => Vector3.Normalize(v)).ToList();
                }
                return derivatives;
            }).ToList();
        }
 
        var scale = Matrix4x4.CreateScale(200, -200, 200);
        var translate = Matrix4x4.CreateTranslation(500, 500, 0);
        var transform = scale * translate;
 
        foreach (var triangle in _model.Triangles)
            triangle.Vertices = triangle.Vertices.Select(v => Vector3.Transform(v, transform)).ToList();
    }
 
    protected override void OnPaint(PaintEventArgs e)
    {
        var g = e.Graphics;
        g.SmoothingMode = SmoothingMode.HighQuality;
 
        using (var gp = new GraphicsPath())
        using (var brush = new SolidBrush(Color.Black))
        {
            foreach (var triangle in _model.Triangles.OrderByDescending(t => t.Middle.Z))
            {
                gp.AddPolygon(triangle.Vertices.Select(v => new PointF(v.X, v.Y)).ToArray());
                
                var n = Vector3.Cross(triangle.Vertices[2] - triangle.Vertices[1], triangle.Vertices[1] - triangle.Vertices[0]);
                n = 10 * Vector3.Normalize(n);
                var light = 1 - 0.8f * new Vector3(n.X, n.Y, 0).Length()/n.Length();//1 - cos(a)
                int gray = (int)(light * 255);
                
                brush.Color = Color.FromArgb(gray, gray, gray);
                
                g.FillPath(brush, gp);
                //g.DrawPath(Pens.Red, gp);
 
                gp.Reset();
            }
        }
    }
}
 
void Main()
{
    Application.Run(new MainForm());
}

Оцени полезность:

7   голосов , оценка 3.429 из 5