SplitAt splits the path into separate paths at the specified intervals (given in millimeters) along the path.
(ts ...float64)
| 1592 | |
| 1593 | // SplitAt splits the path into separate paths at the specified intervals (given in millimeters) along the path. |
| 1594 | func (p *Path) SplitAt(ts ...float64) []*Path { |
| 1595 | if len(ts) == 0 { |
| 1596 | return []*Path{p} |
| 1597 | } |
| 1598 | |
| 1599 | sort.Float64s(ts) |
| 1600 | if ts[0] == 0.0 { |
| 1601 | ts = ts[1:] |
| 1602 | } |
| 1603 | |
| 1604 | j := 0 // index into ts |
| 1605 | T := 0.0 // current position along curve |
| 1606 | |
| 1607 | qs := []*Path{} |
| 1608 | q := &Path{} |
| 1609 | push := func() { |
| 1610 | qs = append(qs, q) |
| 1611 | q = &Path{} |
| 1612 | } |
| 1613 | |
| 1614 | if 0 < len(p.d) && p.d[0] == MoveToCmd { |
| 1615 | q.MoveTo(p.d[1], p.d[2]) |
| 1616 | } |
| 1617 | for _, ps := range p.Split() { |
| 1618 | var start, end Point |
| 1619 | for i := 0; i < len(ps.d); { |
| 1620 | cmd := ps.d[i] |
| 1621 | switch cmd { |
| 1622 | case MoveToCmd: |
| 1623 | end = Point{p.d[i+1], p.d[i+2]} |
| 1624 | case LineToCmd, CloseCmd: |
| 1625 | end = Point{p.d[i+1], p.d[i+2]} |
| 1626 | |
| 1627 | if j == len(ts) { |
| 1628 | q.LineTo(end.X, end.Y) |
| 1629 | } else { |
| 1630 | dT := end.Sub(start).Length() |
| 1631 | Tcurve := T |
| 1632 | for j < len(ts) && T < ts[j] && ts[j] <= T+dT { |
| 1633 | tpos := (ts[j] - T) / dT |
| 1634 | pos := start.Interpolate(end, tpos) |
| 1635 | Tcurve = ts[j] |
| 1636 | |
| 1637 | q.LineTo(pos.X, pos.Y) |
| 1638 | push() |
| 1639 | q.MoveTo(pos.X, pos.Y) |
| 1640 | j++ |
| 1641 | } |
| 1642 | if Tcurve < T+dT { |
| 1643 | q.LineTo(end.X, end.Y) |
| 1644 | } |
| 1645 | T += dT |
| 1646 | } |
| 1647 | case QuadToCmd: |
| 1648 | cp := Point{p.d[i+1], p.d[i+2]} |
| 1649 | end = Point{p.d[i+3], p.d[i+4]} |
| 1650 | |
| 1651 | if j == len(ts) { |