0

How can I draw a bezier curve in Direct2D that accepts N points as control points? As far as I understand, only bezier curves that pass through 4 points can be drawn. If I'm wrong, please correct it. What I want to do is draw a Bezier curve that takes an arbitrary number of points as control points. Is this possible or not? I'm new to Direct2D. I am working in C# but, it would be nice if you can give an example in C# or C++.

This is what I am currently trying. I can't get a smooth curve after the drawing is finished.

using System; 
using System.Windows.Forms;
using JeremyAnsel.DirectX.D2D1;

namespace ShakeAlgorithm
{
    public class Form1 : Form
    {
        public Form1()
        {
            SetStyle(ControlStyles.Opaque, true);
            for (int i = 0; i < count; i++)
            {
                points[i] = new D2D1Point2F(0, 0);
            }
        }
        [STAThread]
        static void Main()
        {
            Application.Run(new Form1());
        }
        private D2D1Factory factory;
        private D2D1HwndRenderTarget hwndRenderTarget;
        private D2D1SolidColorBrush d2D1Brush;
        private D2D1PathGeometry d2D1Geometry;
        private D2D1GeometrySink d2D1GeometrySink;
        private const int count = 10;
        private D2D1Point2F[] points = new D2D1Point2F[count];
        protected override void OnHandleCreated(EventArgs e)
        { 
            factory = D2D1Factory.Create(D2D1FactoryType.SingleThreaded);
            D2D1RenderTargetProperties renderTargetProperties = new D2D1RenderTargetProperties();
            renderTargetProperties.RenderTargetType = D2D1RenderTargetType.Hardware;
            renderTargetProperties.Usage = D2D1RenderTargetUsages.None;
            renderTargetProperties.PixelFormat = new D2D1PixelFormat() { AlphaMode = D2D1AlphaMode.Premultiplied, Format = JeremyAnsel.DirectX.Dxgi.DxgiFormat.B8G8R8A8UNorm };

            D2D1HwndRenderTargetProperties hwndRenderTargetProperties = new D2D1HwndRenderTargetProperties();
            hwndRenderTargetProperties.Hwnd = Handle;
            hwndRenderTargetProperties.PixelSize = new D2D1SizeU((uint)ClientSize.Width, (uint)ClientSize.Height);
            hwndRenderTargetProperties.PresentOptions = D2D1PresentOptions.Immediately;

            hwndRenderTarget = factory.CreateHwndRenderTarget(renderTargetProperties, hwndRenderTargetProperties);
            hwndRenderTarget.AntialiasMode = D2D1AntialiasMode.PerPrimitive;
            d2D1Brush = hwndRenderTarget.CreateSolidColorBrush(new D2D1ColorF(D2D1KnownColor.Yellow));

            base.OnHandleCreated(e);
        }

        protected override void OnPaintBackground(PaintEventArgs e)
        {
            Invalidate();
        }
        protected override void OnPaint(PaintEventArgs e)
        {
            hwndRenderTarget.BeginDraw();
            hwndRenderTarget.Clear(new D2D1ColorF(D2D1KnownColor.White));

            if (points != null)
                if (index < count)
                {
                    d2D1Brush.Color = new D2D1ColorF(D2D1KnownColor.Blue);
                    for (int i = 0; i < index - 1; i++)
                    {
                        D2D1Point2F p1 = points[i];
                        D2D1Point2F p2 = points[i + 1];
                        hwndRenderTarget.DrawLine(p1, p2, d2D1Brush);
                    }
                }
                else
                {
                    d2D1Brush.Color = new D2D1ColorF(D2D1KnownColor.Red);
                    d2D1Geometry = factory.CreatePathGeometry();
                    d2D1GeometrySink = d2D1Geometry.Open();

                    for (int i = 0; i < count - 3; i += 3)
                    {
                        D2D1Point2F p1 = points[i];
                        D2D1Point2F p2 = points[i + 1];
                        D2D1Point2F p3 = points[i + 2];
                        D2D1Point2F p4 = points[i + 3];
                        d2D1GeometrySink.BeginFigure(p1, D2D1FigureBegin.Hollow);

                        d2D1GeometrySink.AddBezier(new D2D1BezierSegment(p2, p3, p4));

                        d2D1GeometrySink.EndFigure(D2D1FigureEnd.Open);

                    }
                    d2D1GeometrySink.Close();
                    hwndRenderTarget.DrawGeometry(d2D1Geometry, d2D1Brush, 3f);


                    d2D1GeometrySink.Dispose();
                    d2D1Geometry.Dispose();
                    d2D1Brush.Color = new D2D1ColorF(D2D1KnownColor.Black);
                    for (int i = 0; i < count; i++)
                    {
                        D2D1Point2F p1 = points[i];


                        hwndRenderTarget.FillEllipse(new D2D1Ellipse(p1, 2, 2), d2D1Brush);
                    }
                }
            hwndRenderTarget.EndDraw();
        } 
        private int index = 0;
        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);
            if (e.Button == MouseButtons.Left)
            {
                if (index < count && points != null)
                {
                    points[index++] = new D2D1Point2F(e.X, e.Y);
                }
                else
                {
                    index = 0;
                    points[index++] = new D2D1Point2F(e.X, e.Y);
                }
            }
            Invalidate();
        }
        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
            if (IsHandleCreated)
            {
                hwndRenderTarget.Resize(new D2D1SizeU((uint)ClientSize.Width, (uint)ClientSize.Height));
                Invalidate();
            }
        }
    }
}

This is a screenshot of the demo.

enter image description here

jtxkopt
  • 916
  • 1
  • 8
  • 21
  • What Direct2D library are you using? It doesn’t look like you’re using an official library and the type-names don’t match Direct2D’s documented types - I think that’s part of your problem. – Dai Jan 09 '21 at 15:24
  • Hello, I am using JeremyAnsel.DirectX.D2D1 library. It is a managed wrapper and yes,it not official. Is there a official library you know? – jtxkopt Jan 09 '21 at 15:28
  • With Direct2D you can use AddBezier https://learn.microsoft.com/en-us/windows/win32/api/d2d1/nf-d2d1-id2d1geometrysink-addbezier(constd2d1_bezier_segment_) or AddQuadraticBezier https://learn.microsoft.com/en-us/windows/win32/api/d2d1/nf-d2d1-id2d1geometrysink-addquadraticbezier(constd2d1_quadratic_bezier_segment) or AddQuadraticBeziers https://learn.microsoft.com/en-us/windows/win32/api/d2d1/nf-d2d1-id2d1geometrysink-addquadraticbeziers that's it. – Simon Mourier Jan 09 '21 at 15:57
  • @SimonMourier I get only a number of discrete bezier curves. That is the problem. – jtxkopt Jan 09 '21 at 16:01
  • Have you tried AddQuadraticBeziers – Simon Mourier Jan 09 '21 at 16:10
  • @SimonMourier Yes, I have but, the same result. AFAIK, Direct2D support only quadratic and qubic forms. I want to draw bezier curve of any order. – jtxkopt Jan 09 '21 at 16:21
  • https://stackoverflow.com/questions/41663348/bezier-curve-of-n-order – Simon Mourier Jan 09 '21 at 16:37
  • So, is it not possible with the built-in functions? – jtxkopt Jan 09 '21 at 16:39

0 Answers0