12

I have three known positions, and currently I am driving two lines like so:

Line line = new Line
{
    StrokeThickness = 3,
    Stroke = lineColor,
    X1 = MyX,
    Y1 = MyY,
    X2 = MyX,
    Y2 = MiddleY
};

Graph.Children.Add(line);

line = new Line
{
    StrokeThickness = 3,
    Stroke = lineColor,
    X1 = MyX,
    Y1 = MiddleY,
    X2 = TargetX,
    Y2 = TargetY
};

Graph.Children.Add(line);

Here's the result:

enter image description here

So, as you can see, this is almost what I want except that I want it to be more smoothed out, just a little bit.

Now I'm looking for any way I could set three points, set some smooth/curvy level to the middle point and then draw a line with a solid color on it. Much like how I can do this in Photoshop:

enter image description here

Or at least get a similar kind of smoothness.

Tower
  • 98,741
  • 129
  • 357
  • 507
  • 2
    Start here: https://www.google.cz/search?q=spline+wpf – Euphoric May 07 '12 at 18:12
  • http://stackoverflow.com/questions/9801524/how-to-make-the-brush-smooth-without-lines-in-the-middle – HB MAAM May 07 '12 at 18:18
  • 4
    @HBMAAM: Your link is to a completely unrelated question. This question is about drawing curves and your linked question is about gradients. – Gabe May 07 '12 at 19:09

3 Answers3

15

I think you are looking for splines

http://msdn.microsoft.com/en-us/library/554h284b.aspx

Gabe is correct that is from Forms

Under WPF you could try a PolyBezierSegment but it require 4 points. Possible you could put in three points and 1 more to shape it.

<Canvas>
    <Path Stroke="Black" StrokeThickness="10">
        <Path.Data>
            <PathGeometry>
                <PathGeometry.Figures>
                    <PathFigureCollection>    
                        <PathFigure StartPoint="100,80">
                            <PathFigure.Segments>
                                <PathSegmentCollection>
                                    <PolyBezierSegment Points="90,200 140,200 160,200 180,200 430,190 430,280" />
                                </PathSegmentCollection>
                            </PathFigure.Segments>
                        </PathFigure>
                    </PathFigureCollection>
                </PathGeometry.Figures>
            </PathGeometry>
        </Path.Data>
    </Path>
</Canvas>

This results in the following curve

enter image description here

paparazzo
  • 44,497
  • 23
  • 105
  • 176
2

You want to use a PathFigure, specifically with a set of BezierSegments.

plinth
  • 48,267
  • 11
  • 78
  • 120
0

To achieve the smooth curve we can use cubic bezier curves, as shown on the above answer, with the PolyBezierSegment class.

How it works

A cubic Bezier curve is defined by four points: a start point, an end point and two control points.

For every three points in the collection, the first and second points specify the two control points of the curve and the third point specifies the end point. Note that no start point for the curve is specified because start point is the same as the end point of the last segment.

If you want to specify only the start and end points of each segment you need to calculate the control points dynamically, that will depend on the kind of curvature you need.

On the following example I will define 3 points, then I will hardcode the control points to define the curvature, this should be made with an algorithm that calculates the curvature according to your needs.

Note that I am adding the start point to the points collection, although the path figure class needs one point for start position and the PolyBezierSegment class needs a collection with multiples of 3 (2 controls and an end point)

//create 3 positions
Point start = new(50, 50),
    mid = new(80, 100),
    end = new(200, 150);

Point[] _points = new[]
{
    //start of line (and first segment)
    start,
    //First control point:
    new(start.X, start.Y + (mid.Y - start.Y) / 2),
    //Second control point:
    new(mid.X - (mid.X - start.X) / 2, mid.Y),
    //end of first segment and start of second.
    mid,
    new(mid.X + (end.X - mid.X) / 2, mid.Y),
    new(end.X, end.Y - (end.Y - mid.Y) / 2),
    end
;

//Create the segment connectors
PathGeometry connectorGeometry = new()
{
    Figures = new PathFigureCollection()
    {
        new PathFigure()
        {
            //define the start of the smooth line
            StartPoint = _points[0],
            //define the coordinates of the smooth line
            Segments = new PathSegmentCollection()
            {
                new PolyBezierSegment(
                    //in this example I added the start to the collection,
                    //so we skip the first coordinate already used on "StartPoint"
                    points: _points.Skip(1),
                    isStroked: true)
            }
        }
    }
};

Path smoothCurve = new()
{
    Stroke = Brushes.Black,
    StrokeThickness = 3,
    Data = connectorGeometry
};

Graph.Children.Add(smoothCurve);

Result:

Example

Barreto
  • 374
  • 2
  • 14