...

Source file src/gonum.org/v1/plot/tools/bezier/bezier.go

Documentation: gonum.org/v1/plot/tools/bezier

     1  // Copyright ©2013 The Gonum Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Package bezier implements 2D Bézier curve calculation.
     6  package bezier // import "gonum.org/v1/plot/tools/bezier"
     7  
     8  import "gonum.org/v1/plot/vg"
     9  
    10  type point struct {
    11  	Point, Control vg.Point
    12  }
    13  
    14  // Curve implements Bezier curve calculation according to the algorithm of Robert D. Miller.
    15  //
    16  // Graphics Gems 5, 'Quick and Simple Bézier Curve Drawing', pages 206-209.
    17  type Curve []point
    18  
    19  // NewCurve returns a Curve initialized with the control points in cp.
    20  func New(cp ...vg.Point) Curve {
    21  	if len(cp) == 0 {
    22  		return nil
    23  	}
    24  	c := make(Curve, len(cp))
    25  	for i, p := range cp {
    26  		c[i].Point = p
    27  	}
    28  
    29  	var w vg.Length
    30  	for i, p := range c {
    31  		switch i {
    32  		case 0:
    33  			w = 1
    34  		case 1:
    35  			w = vg.Length(len(c)) - 1
    36  		default:
    37  			w *= vg.Length(len(c)-i) / vg.Length(i)
    38  		}
    39  		c[i].Control.X = p.Point.X * w
    40  		c[i].Control.Y = p.Point.Y * w
    41  	}
    42  
    43  	return c
    44  }
    45  
    46  // Point returns the point at t along the curve, where 0 ≤ t ≤ 1.
    47  func (c Curve) Point(t float64) vg.Point {
    48  	c[0].Point = c[0].Control
    49  	u := t
    50  	for i, p := range c[1:] {
    51  		c[i+1].Point = vg.Point{
    52  			X: p.Control.X * vg.Length(u),
    53  			Y: p.Control.Y * vg.Length(u),
    54  		}
    55  		u *= t
    56  	}
    57  
    58  	var (
    59  		t1 = 1 - t
    60  		tt = t1
    61  	)
    62  	p := c[len(c)-1].Point
    63  	for i := len(c) - 2; i >= 0; i-- {
    64  		p.X += c[i].Point.X * vg.Length(tt)
    65  		p.Y += c[i].Point.Y * vg.Length(tt)
    66  		tt *= t1
    67  	}
    68  
    69  	return p
    70  }
    71  
    72  // Curve returns a slice of vg.Point, p, filled with points along the Bézier curve described by c.
    73  // If the length of p is less than 2, the curve points are undefined. The length of p is not
    74  // altered by the call.
    75  func (c Curve) Curve(p []vg.Point) []vg.Point {
    76  	for i, nf := 0, float64(len(p)-1); i < len(p); i++ {
    77  		p[i] = c.Point(float64(i) / nf)
    78  	}
    79  	return p
    80  }
    81  

View as plain text