1use crate::basics::iround;
7use crate::dda_line::Dda2LineInterpolator;
8use crate::trans_affine::TransAffine;
9use crate::trans_bilinear::TransBilinear;
10use crate::trans_perspective::TransPerspective;
11
12pub const SUBPIXEL_SHIFT: u32 = 8;
14pub const SUBPIXEL_SCALE: i32 = 1 << SUBPIXEL_SHIFT;
15
16pub trait Transformer {
22 fn transform(&self, x: &mut f64, y: &mut f64);
23}
24
25impl<T: Transformer> Transformer for &T {
28 fn transform(&self, x: &mut f64, y: &mut f64) {
29 (*self).transform(x, y);
30 }
31}
32
33impl Transformer for TransAffine {
34 fn transform(&self, x: &mut f64, y: &mut f64) {
35 self.transform(x, y);
36 }
37}
38
39impl Transformer for TransBilinear {
40 fn transform(&self, x: &mut f64, y: &mut f64) {
41 self.transform(x, y);
42 }
43}
44
45impl Transformer for TransPerspective {
46 fn transform(&self, x: &mut f64, y: &mut f64) {
47 self.transform(x, y);
48 }
49}
50
51pub trait SpanInterpolator {
60 fn begin(&mut self, x: f64, y: f64, len: u32);
61 fn next(&mut self);
62 fn coordinates(&self, x: &mut i32, y: &mut i32);
63}
64
65pub struct SpanInterpolatorLinear<T = TransAffine> {
77 trans: T,
78 li_x: Dda2LineInterpolator,
79 li_y: Dda2LineInterpolator,
80}
81
82impl<T: Transformer> SpanInterpolatorLinear<T> {
83 pub fn new(trans: T) -> Self {
84 Self {
85 trans,
86 li_x: Dda2LineInterpolator::new_forward(0, 0, 1),
87 li_y: Dda2LineInterpolator::new_forward(0, 0, 1),
88 }
89 }
90
91 pub fn new_begin(trans: T, x: f64, y: f64, len: u32) -> Self {
92 let mut s = Self::new(trans);
93 s.begin(x, y, len);
94 s
95 }
96
97 pub fn transformer(&self) -> &T {
98 &self.trans
99 }
100
101 pub fn set_transformer(&mut self, trans: T) {
102 self.trans = trans;
103 }
104
105 pub fn begin(&mut self, x: f64, y: f64, len: u32) {
107 let mut tx = x;
108 let mut ty = y;
109 self.trans.transform(&mut tx, &mut ty);
110 let x1 = iround(tx * SUBPIXEL_SCALE as f64);
111 let y1 = iround(ty * SUBPIXEL_SCALE as f64);
112
113 let mut tx2 = x + len as f64;
114 let mut ty2 = y;
115 self.trans.transform(&mut tx2, &mut ty2);
116 let x2 = iround(tx2 * SUBPIXEL_SCALE as f64);
117 let y2 = iround(ty2 * SUBPIXEL_SCALE as f64);
118
119 self.li_x = Dda2LineInterpolator::new_forward(x1, x2, len as i32);
120 self.li_y = Dda2LineInterpolator::new_forward(y1, y2, len as i32);
121 }
122
123 pub fn resynchronize(&mut self, mut xe: f64, mut ye: f64, len: u32) {
125 self.trans.transform(&mut xe, &mut ye);
126 self.li_x = Dda2LineInterpolator::new_forward(
127 self.li_x.y(),
128 iround(xe * SUBPIXEL_SCALE as f64),
129 len as i32,
130 );
131 self.li_y = Dda2LineInterpolator::new_forward(
132 self.li_y.y(),
133 iround(ye * SUBPIXEL_SCALE as f64),
134 len as i32,
135 );
136 }
137
138 #[inline]
140 pub fn next(&mut self) {
141 self.li_x.inc();
142 self.li_y.inc();
143 }
144
145 #[inline]
147 pub fn coordinates(&self, x: &mut i32, y: &mut i32) {
148 *x = self.li_x.y();
149 *y = self.li_y.y();
150 }
151}
152
153impl<T: Transformer> SpanInterpolator for SpanInterpolatorLinear<T> {
154 fn begin(&mut self, x: f64, y: f64, len: u32) {
155 self.begin(x, y, len);
156 }
157 fn next(&mut self) {
158 self.next();
159 }
160 fn coordinates(&self, x: &mut i32, y: &mut i32) {
161 self.coordinates(x, y);
162 }
163}
164
165pub struct SpanInterpolatorLinearSubdiv<T = TransAffine> {
176 subdiv_shift: u32,
177 subdiv_size: u32,
178 trans: T,
179 li_x: Dda2LineInterpolator,
180 li_y: Dda2LineInterpolator,
181 src_x: i32,
182 src_y: f64,
183 pos: u32,
184 len: u32,
185}
186
187impl<T: Transformer> SpanInterpolatorLinearSubdiv<T> {
188 pub fn new(trans: T, subdiv_shift: u32) -> Self {
189 Self {
190 subdiv_shift,
191 subdiv_size: 1 << subdiv_shift,
192 trans,
193 li_x: Dda2LineInterpolator::new_forward(0, 0, 1),
194 li_y: Dda2LineInterpolator::new_forward(0, 0, 1),
195 src_x: 0,
196 src_y: 0.0,
197 pos: 1,
198 len: 0,
199 }
200 }
201
202 pub fn new_default(trans: T) -> Self {
203 Self::new(trans, 4)
204 }
205
206 pub fn transformer(&self) -> &T {
207 &self.trans
208 }
209
210 pub fn set_transformer(&mut self, trans: T) {
211 self.trans = trans;
212 }
213
214 pub fn subdiv_shift(&self) -> u32 {
215 self.subdiv_shift
216 }
217
218 pub fn set_subdiv_shift(&mut self, shift: u32) {
219 self.subdiv_shift = shift;
220 self.subdiv_size = 1 << shift;
221 }
222
223 pub fn begin(&mut self, x: f64, y: f64, len: u32) {
225 self.pos = 1;
226 self.src_x = iround(x * SUBPIXEL_SCALE as f64) + SUBPIXEL_SCALE;
227 self.src_y = y;
228 self.len = len;
229
230 let sub_len = if len > self.subdiv_size {
231 self.subdiv_size
232 } else {
233 len
234 };
235
236 let mut tx = x;
237 let mut ty = y;
238 self.trans.transform(&mut tx, &mut ty);
239 let x1 = iround(tx * SUBPIXEL_SCALE as f64);
240 let y1 = iround(ty * SUBPIXEL_SCALE as f64);
241
242 let mut tx2 = x + sub_len as f64;
243 let mut ty2 = y;
244 self.trans.transform(&mut tx2, &mut ty2);
245
246 self.li_x = Dda2LineInterpolator::new_forward(
247 x1,
248 iround(tx2 * SUBPIXEL_SCALE as f64),
249 sub_len as i32,
250 );
251 self.li_y = Dda2LineInterpolator::new_forward(
252 y1,
253 iround(ty2 * SUBPIXEL_SCALE as f64),
254 sub_len as i32,
255 );
256 }
257
258 pub fn next(&mut self) {
260 self.li_x.inc();
261 self.li_y.inc();
262 if self.pos >= self.subdiv_size {
263 let mut sub_len = self.len;
264 if sub_len > self.subdiv_size {
265 sub_len = self.subdiv_size;
266 }
267 let mut tx = self.src_x as f64 / SUBPIXEL_SCALE as f64 + sub_len as f64;
268 let mut ty = self.src_y;
269 self.trans.transform(&mut tx, &mut ty);
270 self.li_x = Dda2LineInterpolator::new_forward(
271 self.li_x.y(),
272 iround(tx * SUBPIXEL_SCALE as f64),
273 sub_len as i32,
274 );
275 self.li_y = Dda2LineInterpolator::new_forward(
276 self.li_y.y(),
277 iround(ty * SUBPIXEL_SCALE as f64),
278 sub_len as i32,
279 );
280 self.pos = 0;
281 }
282 self.src_x += SUBPIXEL_SCALE;
283 self.pos += 1;
284 self.len = self.len.saturating_sub(1);
285 }
286
287 #[inline]
289 pub fn coordinates(&self, x: &mut i32, y: &mut i32) {
290 *x = self.li_x.y();
291 *y = self.li_y.y();
292 }
293}
294
295impl<T: Transformer> SpanInterpolator for SpanInterpolatorLinearSubdiv<T> {
296 fn begin(&mut self, x: f64, y: f64, len: u32) {
297 self.begin(x, y, len);
298 }
299 fn next(&mut self) {
300 self.next();
301 }
302 fn coordinates(&self, x: &mut i32, y: &mut i32) {
303 self.coordinates(x, y);
304 }
305}
306
307#[cfg(test)]
312mod tests {
313 use super::*;
314 use std::f64::consts::PI;
315
316 #[test]
317 fn test_identity_transform() {
318 let trans = TransAffine::new();
319 let mut interp = SpanInterpolatorLinear::new(trans);
320 interp.begin(10.0, 20.0, 5);
321
322 let mut x = 0;
323 let mut y = 0;
324 interp.coordinates(&mut x, &mut y);
325 assert_eq!(x, 10 * SUBPIXEL_SCALE);
326 assert_eq!(y, 20 * SUBPIXEL_SCALE);
327 }
328
329 #[test]
330 fn test_translation() {
331 let trans = TransAffine::new_translation(100.0, 200.0);
332 let mut interp = SpanInterpolatorLinear::new(trans);
333 interp.begin(10.0, 20.0, 5);
334
335 let mut x = 0;
336 let mut y = 0;
337 interp.coordinates(&mut x, &mut y);
338 assert_eq!(x, 110 * SUBPIXEL_SCALE);
339 assert_eq!(y, 220 * SUBPIXEL_SCALE);
340 }
341
342 #[test]
343 fn test_scaling() {
344 let trans = TransAffine::new_scaling(2.0, 3.0);
345 let mut interp = SpanInterpolatorLinear::new(trans);
346 interp.begin(10.0, 20.0, 5);
347
348 let mut x = 0;
349 let mut y = 0;
350 interp.coordinates(&mut x, &mut y);
351 assert_eq!(x, 20 * SUBPIXEL_SCALE);
352 assert_eq!(y, 60 * SUBPIXEL_SCALE);
353 }
354
355 #[test]
356 fn test_interpolation_advances() {
357 let trans = TransAffine::new();
358 let mut interp = SpanInterpolatorLinear::new(trans);
359 interp.begin(0.0, 0.0, 10);
360
361 let mut x = 0;
362 let mut y = 0;
363 interp.coordinates(&mut x, &mut y);
364 assert_eq!(x, 0);
365
366 for _ in 0..10 {
368 interp.next();
369 }
370 interp.coordinates(&mut x, &mut y);
371 assert!((x - 10 * SUBPIXEL_SCALE).abs() <= 1);
373 }
374
375 #[test]
376 fn test_rotation_90_degrees() {
377 let trans = TransAffine::new_rotation(PI / 2.0);
378 let mut interp = SpanInterpolatorLinear::new(trans);
379 interp.begin(10.0, 0.0, 1);
380
381 let mut x = 0;
382 let mut y = 0;
383 interp.coordinates(&mut x, &mut y);
384 assert!(x.abs() <= 1, "x={} should be ~0", x);
386 assert!(
387 (y - 10 * SUBPIXEL_SCALE).abs() <= 1,
388 "y={} should be ~{}",
389 y,
390 10 * SUBPIXEL_SCALE
391 );
392 }
393
394 #[test]
395 fn test_resynchronize() {
396 let trans = TransAffine::new();
397 let mut interp = SpanInterpolatorLinear::new(trans);
398 interp.begin(0.0, 0.0, 10);
399 for _ in 0..5 {
400 interp.next();
401 }
402 interp.resynchronize(15.0, 0.0, 5);
404
405 let mut x = 0;
406 let mut y = 0;
407 interp.coordinates(&mut x, &mut y);
408 assert!(
410 (x - 5 * SUBPIXEL_SCALE).abs() <= 1,
411 "x={} should be ~{}",
412 x,
413 5 * SUBPIXEL_SCALE
414 );
415 }
416
417 #[test]
418 fn test_new_begin() {
419 let trans = TransAffine::new();
420 let interp = SpanInterpolatorLinear::new_begin(trans, 5.0, 10.0, 3);
421 let mut x = 0;
422 let mut y = 0;
423 interp.coordinates(&mut x, &mut y);
424 assert_eq!(x, 5 * SUBPIXEL_SCALE);
425 assert_eq!(y, 10 * SUBPIXEL_SCALE);
426 }
427
428 #[test]
429 fn test_subdiv_identity() {
430 let trans = TransAffine::new();
431 let mut interp = SpanInterpolatorLinearSubdiv::new_default(trans);
432 interp.begin(10.0, 20.0, 100);
433
434 let mut x = 0;
435 let mut y = 0;
436 interp.coordinates(&mut x, &mut y);
437 assert_eq!(x, 10 * SUBPIXEL_SCALE);
438 assert_eq!(y, 20 * SUBPIXEL_SCALE);
439
440 for _ in 0..50 {
442 interp.next();
443 }
444 interp.coordinates(&mut x, &mut y);
445 assert!(
446 (x - 60 * SUBPIXEL_SCALE).abs() <= 2,
447 "x={} should be ~{}",
448 x,
449 60 * SUBPIXEL_SCALE
450 );
451 }
452
453 #[test]
454 fn test_subdiv_translation() {
455 let trans = TransAffine::new_translation(50.0, 100.0);
456 let mut interp = SpanInterpolatorLinearSubdiv::new_default(trans);
457 interp.begin(0.0, 0.0, 20);
458
459 let mut x = 0;
460 let mut y = 0;
461 interp.coordinates(&mut x, &mut y);
462 assert_eq!(x, 50 * SUBPIXEL_SCALE);
463 assert_eq!(y, 100 * SUBPIXEL_SCALE);
464 }
465
466 #[test]
467 fn test_subdiv_shift_setter() {
468 let trans = TransAffine::new();
469 let mut interp = SpanInterpolatorLinearSubdiv::new(trans, 4);
470 assert_eq!(interp.subdiv_shift(), 4);
471 interp.set_subdiv_shift(6);
472 assert_eq!(interp.subdiv_shift(), 6);
473 }
474}