agg_rust/
conv_segmentator.rs1use crate::basics::VertexSource;
8use crate::conv_adaptor_vpgen::ConvAdaptorVpgen;
9use crate::vpgen_segmentator::VpgenSegmentator;
10
11pub struct ConvSegmentator<VS> {
16 inner: ConvAdaptorVpgen<VS, VpgenSegmentator>,
17}
18
19impl<VS: VertexSource> ConvSegmentator<VS> {
20 pub fn new(source: VS) -> Self {
21 Self {
22 inner: ConvAdaptorVpgen::new(source, VpgenSegmentator::new()),
23 }
24 }
25
26 pub fn approximation_scale(&self) -> f64 {
27 self.inner.vpgen().approximation_scale()
28 }
29
30 pub fn set_approximation_scale(&mut self, s: f64) {
31 self.inner.vpgen_mut().set_approximation_scale(s);
32 }
33
34 pub fn source(&self) -> &VS {
35 self.inner.source()
36 }
37
38 pub fn source_mut(&mut self) -> &mut VS {
39 self.inner.source_mut()
40 }
41}
42
43impl<VS: VertexSource> VertexSource for ConvSegmentator<VS> {
44 fn rewind(&mut self, path_id: u32) {
45 self.inner.rewind(path_id);
46 }
47
48 fn vertex(&mut self, x: &mut f64, y: &mut f64) -> u32 {
49 self.inner.vertex(x, y)
50 }
51}
52
53#[cfg(test)]
54mod tests {
55 use super::*;
56 use crate::basics::{is_stop, PATH_CMD_LINE_TO, PATH_CMD_MOVE_TO, PATH_CMD_STOP};
57
58 struct SquareSource {
60 idx: usize,
61 }
62
63 impl SquareSource {
64 fn new() -> Self {
65 Self { idx: 0 }
66 }
67 }
68
69 impl VertexSource for SquareSource {
70 fn rewind(&mut self, _path_id: u32) {
71 self.idx = 0;
72 }
73
74 fn vertex(&mut self, x: &mut f64, y: &mut f64) -> u32 {
75 self.idx += 1;
76 match self.idx {
77 1 => {
78 *x = 0.0;
79 *y = 0.0;
80 PATH_CMD_MOVE_TO
81 }
82 2 => {
83 *x = 100.0;
84 *y = 0.0;
85 PATH_CMD_LINE_TO
86 }
87 3 => {
88 *x = 100.0;
89 *y = 100.0;
90 PATH_CMD_LINE_TO
91 }
92 4 => {
93 *x = 0.0;
94 *y = 100.0;
95 PATH_CMD_LINE_TO
96 }
97 _ => PATH_CMD_STOP,
98 }
99 }
100 }
101
102 #[test]
103 fn test_conv_segmentator_passthrough() {
104 let mut seg = ConvSegmentator::new(SquareSource::new());
105 seg.set_approximation_scale(1.0);
106 seg.rewind(0);
107
108 let (mut x, mut y) = (0.0, 0.0);
109 let mut count = 0;
110 loop {
111 let cmd = seg.vertex(&mut x, &mut y);
112 if is_stop(cmd) {
113 break;
114 }
115 count += 1;
116 }
117 assert!(count >= 4, "Expected at least 4 vertices, got {count}");
119 }
120
121 #[test]
122 fn test_conv_segmentator_subdivides() {
123 let mut seg = ConvSegmentator::new(SquareSource::new());
124 seg.set_approximation_scale(10.0); seg.rewind(0);
126
127 let (mut x, mut y) = (0.0, 0.0);
128 let mut count = 0;
129 loop {
130 let cmd = seg.vertex(&mut x, &mut y);
131 if is_stop(cmd) {
132 break;
133 }
134 count += 1;
135 }
136 assert!(
137 count > 10,
138 "With scale=10, square should have many vertices: got {count}"
139 );
140 }
141
142 #[test]
143 fn test_approximation_scale_accessors() {
144 let seg = ConvSegmentator::new(SquareSource::new());
145 assert!((seg.approximation_scale() - 1.0).abs() < 1e-10);
146
147 let mut seg = seg;
148 seg.set_approximation_scale(5.0);
149 assert!((seg.approximation_scale() - 5.0).abs() < 1e-10);
150 }
151}