path_traits/transform/
concat.rs1use crate::{Path, PathSegment, SegmentedPath};
10
11pub struct Concat<A, B> {
17 first: A,
19 second: B,
21}
22
23impl<A, B> Concat<A, B> {
24 pub fn new(first: A, second: B) -> Self {
26 Self { first, second }
27 }
28}
29
30impl<A: Path, B: Path<Scalar = A::Scalar, Point = A::Point, Error = A::Error>> Path
31 for Concat<A, B>
32{
33 type Scalar = A::Scalar;
34 type Point = A::Point;
35 type Error = A::Error;
36
37 fn length(&self) -> Self::Scalar {
38 self.first.length() + self.second.length()
39 }
40
41 fn sample_at(&self, s: Self::Scalar) -> Result<Self::Point, Self::Error> {
42 let first_len = self.first.length();
43 if s <= first_len {
44 self.first.sample_at(s)
45 } else {
46 self.second.sample_at(s - first_len)
47 }
48 }
49}
50
51impl<A: SegmentedPath, B: SegmentedPath<Segment = A::Segment>> SegmentedPath for Concat<A, B>
52where
53 A: Path,
54 B: Path<Scalar = A::Scalar, Point = A::Point, Error = A::Error>,
55 A::Segment: PathSegment<Scalar = A::Scalar, Point = A::Point, Error = A::Error>,
56{
57 type Segment = A::Segment;
58
59 fn segment_count(&self) -> usize {
60 self.first.segment_count() + self.second.segment_count()
61 }
62
63 fn segments(&self) -> impl Iterator<Item = &Self::Segment> + '_ {
64 self.first.segments().chain(self.second.segments())
65 }
66
67 fn locate(&self, s: Self::Scalar) -> Result<(usize, Self::Scalar), Self::Error> {
68 let first_len = self.first.length();
69 if s <= first_len {
70 self.first.locate(s)
71 } else {
72 let (idx, local) = self.second.locate(s - first_len)?;
73 Ok((self.first.segment_count() + idx, local))
74 }
75 }
76}