direction returns the direction of the path at the given index into Path.d and t in [0.0,1.0]. Path must not contain subpaths, and will return the path's starting direction when i points to a MoveToCmd, or the path's final direction when i points to a CloseCmd of zero-length.
(i int, t float64)
| 672 | |
| 673 | // direction returns the direction of the path at the given index into Path.d and t in [0.0,1.0]. Path must not contain subpaths, and will return the path's starting direction when i points to a MoveToCmd, or the path's final direction when i points to a CloseCmd of zero-length. |
| 674 | func (p *Path) direction(i int, t float64) Point { |
| 675 | last := len(p.d) |
| 676 | if p.d[last-1] == CloseCmd && (Point{p.d[last-cmdLen(CloseCmd)-3], p.d[last-cmdLen(CloseCmd)-2]}).Equals(Point{p.d[last-3], p.d[last-2]}) { |
| 677 | // point-closed |
| 678 | last -= cmdLen(CloseCmd) |
| 679 | } |
| 680 | |
| 681 | if i == 0 { |
| 682 | // get path's starting direction when i points to MoveTo |
| 683 | i = 4 |
| 684 | t = 0.0 |
| 685 | } else if i < len(p.d) && i == last { |
| 686 | // get path's final direction when i points to zero-length Close |
| 687 | i -= cmdLen(p.d[i-1]) |
| 688 | t = 1.0 |
| 689 | } |
| 690 | if i < 0 || len(p.d) <= i || last < i+cmdLen(p.d[i]) { |
| 691 | return Point{} |
| 692 | } |
| 693 | |
| 694 | cmd := p.d[i] |
| 695 | var start Point |
| 696 | if i == 0 { |
| 697 | start = Point{p.d[last-3], p.d[last-2]} |
| 698 | } else { |
| 699 | start = Point{p.d[i-3], p.d[i-2]} |
| 700 | } |
| 701 | |
| 702 | i += cmdLen(cmd) |
| 703 | end := Point{p.d[i-3], p.d[i-2]} |
| 704 | switch cmd { |
| 705 | case LineToCmd, CloseCmd: |
| 706 | return end.Sub(start).Norm(1.0) |
| 707 | case QuadToCmd: |
| 708 | cp := Point{p.d[i-5], p.d[i-4]} |
| 709 | return quadraticBezierDeriv(start, cp, end, t).Norm(1.0) |
| 710 | case CubeToCmd: |
| 711 | cp1 := Point{p.d[i-7], p.d[i-6]} |
| 712 | cp2 := Point{p.d[i-5], p.d[i-4]} |
| 713 | return cubicBezierDeriv(start, cp1, cp2, end, t).Norm(1.0) |
| 714 | case ArcToCmd: |
| 715 | rx, ry, phi := p.d[i-7], p.d[i-6], p.d[i-5] |
| 716 | large, sweep := toArcFlags(p.d[i-4]) |
| 717 | _, _, theta0, theta1 := ellipseToCenter(start.X, start.Y, rx, ry, phi, large, sweep, end.X, end.Y) |
| 718 | theta := theta0 + t*(theta1-theta0) |
| 719 | return ellipseDeriv(rx, ry, phi, sweep, theta).Norm(1.0) |
| 720 | } |
| 721 | return Point{} |
| 722 | } |
| 723 | |
| 724 | // Direction returns the direction of the path at the given segment and t in [0.0,1.0] along that path. The direction is a vector of unit length. |
| 725 | func (p *Path) Direction(seg int, t float64) Point { |
no test coverage detected