Skip to main content

astroimsim_geometry/
grid2d.rs

1use plotpy::{Curve, Plot, Text};
2use crate::coordinate_system::{CoordinateSystem, Coordinates};
3use rand::RngExt;
4use crate::points::{Point};
5
6
7pub enum Corners{
8    Four(usize,usize,usize,usize),
9    Two(usize,usize),
10    One(usize),
11}
12#[derive(Debug)]
13pub enum Location{
14    Outside,
15    Inside,
16}
17pub enum Bin{
18    Binned(usize,usize),
19    Outside,
20}
21
22
23#[derive(Debug,Clone)]
24pub struct GRID2D {
25    pub coordinates: Coordinates,
26
27    pub x_num: usize,
28    pub y_num: usize,
29
30    pub x_step_size: f64, //In coordinate system
31    pub y_step_size: f64, //In coordinate system
32
33    pub x_size: f64,
34    pub y_size: f64,
35
36    pub num_points: usize,
37
38    pub center: (f64,f64),
39    pub corner: (f64,f64),
40
41    pub snap_precision: f64, //In coordinat sytstem
42
43    pub label: String,
44
45}
46
47impl GRID2D {
48    pub fn new_empty((x_num,y_num): (usize,usize),
49                     (x_step_size,y_step_size): (f64,f64), //TODO have units for this length
50                     center: (f64,f64),
51                     snap_precision: f64,
52                     coordinates: Coordinates,
53    ) -> GRID2D {
54        let x_size = x_step_size*(x_num-1)as f64;
55        let y_size = y_step_size*(y_num-1)as f64;
56        let num_points = x_num*y_num;
57        let (x_0,y_0) = center;
58        let corner = (x_0 - x_size/2.0,y_0 - y_size/2.0);
59        // println!("Huh?");
60        //  println!("CORNER IS {:?} for {x_num}",Point::new(corner.0,corner.1,coordinates.clone()).to_absolute());
61        //  println!("Center is {:?}",(x_0,y_0));
62        assert!(snap_precision<0.5);
63        GRID2D {
64            coordinates,
65            x_num,
66            x_step_size,
67            x_size,
68            y_num,
69            y_step_size,
70            y_size,
71            num_points,
72            center,
73            corner,
74            snap_precision:snap_precision*f64::min(y_step_size,x_step_size),
75            label: "".to_string(),
76        }
77    }
78
79
80    pub fn new_from_width((x_num,y_num): (usize,usize),
81                     (x_width,y_width): (f64,f64), //TODO have units for this length
82                     center: (f64,f64),
83                     snap_precision: f64,
84                     coordinates: Coordinates,
85    ) -> GRID2D {
86        let x_step_size = x_width/(x_num-1)as f64;
87        let y_step_size = y_width/(y_num-1)as f64;
88        let num_points = x_num*y_num;
89        let (x_0,y_0) = center;
90        let corner = (x_0 - x_width/2.0,y_0 - y_width/2.0);
91        // println!("Huh?");
92        //  println!("CORNER IS {:?} for {x_num}",Point::new(corner.0,corner.1,coordinates.clone()).to_absolute());
93        //  println!("Center is {:?}",(x_0,y_0));
94        assert!(snap_precision<0.5);
95        GRID2D {
96            coordinates,
97            x_num,
98            x_step_size,
99            x_size:x_width,
100            y_num,
101            y_step_size,
102            y_size:y_width,
103            num_points,
104            center,
105            corner,
106            snap_precision:snap_precision*f64::min(y_step_size,x_step_size),
107            label: "".to_string(),
108        }
109    }
110
111
112
113
114    pub fn xy_indices(&self, grid_number:usize) -> (usize,usize){
115        assert!((grid_number <= self.num_points - 1)&&(grid_number >= 0));
116        let x_index = grid_number % self.x_num;
117        let y_index = (grid_number - x_index)/self.y_num;
118        (x_index,y_index)
119    }
120
121    pub fn grid_number(&self, x_index:usize,y_index:usize) -> usize{
122        assert!(x_index <= self.x_num-1);
123        assert!(y_index <= self.y_num-1);
124        y_index*self.x_num + x_index
125    }
126
127    pub fn locate(&self, grid_number:usize) -> Point {
128
129        assert!((grid_number <= self.x_num*self.y_num-1)&&(grid_number >= 0));
130        let (x_corner,y_corner) = self.corner;
131        let (x_index,y_index) = self.xy_indices(grid_number);
132        let (x,y) = (x_corner + x_index as f64 *self.x_step_size, y_corner + y_index as f64 *self.y_step_size);
133        //println!("relatice location is {:?}",(x,y));
134        Point::new(x,y,self.coordinates.clone())
135    }
136
137
138
139    pub fn snap(&self,point:Point)-> usize{
140        let (x_mod,y_mod,x_residual,y_residual) = self.fit_grid(&point);
141        if (x_residual.abs() >= self.snap_precision)  | (y_residual.abs() >= self.snap_precision){
142            panic!("Couldn't snap point")
143        };
144        self.grid_number(x_mod,y_mod)
145    }
146
147    pub fn random(&self)-> Point{
148        let mut rng = rand::rng();
149        let x_scale: f64 = rng.random();
150        let y_scale: f64 = rng.random();
151        let (x,y) = (self.corner.0 + self.x_size*x_scale, self.corner.1 + self.y_size*y_scale);
152        //println!("Randomly generating point {:?} within the grid",(x,y));
153        let point = Point::new(x,y,self.coordinates.clone());
154        // println!("RANDOM:  {:?}",self.inside_or_outside(&point));
155        point
156    }
157
158    pub fn fit_grid(&self, point:&Point)->(usize,usize,f64,f64){
159        //ensure that the point is within the grid
160        match self.inside_or_outside(&point) {
161            Location::Outside => {
162                println!("Tried to grid point {:?}",point);
163                panic!("Tried to grid a point that was outside of the grid")}
164            Location::Inside => {}
165        }
166        //find the nearest point and then return the residuals to it
167
168        let (x,y) = point.convert(&self.coordinates).values();
169      //  println!("{x} {y}");
170
171        let (corner_x,corner_y) = self.corner;
172
173        let delta_x = x - corner_x;
174        let delta_y = y - corner_y;
175        //  println!("delta x and delta y are {:?}, {:?}",delta_x,delta_y);
176        let x_scaled_residual = delta_x/self.x_step_size - (delta_x/self.x_step_size).floor();
177        let y_scaled_residual = delta_y/self.y_step_size - (delta_y/self.y_step_size).floor();
178
179        // println!("residuals are {:?}, {:?}",x_scaled_residual,y_scaled_residual);
180
181        let (x_mod, x_residual) = if x_scaled_residual <= 0.5{
182            let x_mod = (delta_x/self.x_step_size).floor() as usize;
183            let x_residual = x_scaled_residual*self.x_step_size;
184
185            (x_mod,x_residual)
186
187        }else{
188            let x_mod = (delta_x/self.x_step_size).floor() as usize + 1;
189            let x_residual = (x_scaled_residual-1.0)*self.x_step_size;
190            (x_mod,x_residual)
191        };
192
193        let (y_mod,y_residual) = if y_scaled_residual <=0.5{
194            let y_mod = (delta_y/self.y_step_size).floor() as usize;
195            let y_residual = y_scaled_residual*self.y_step_size;
196            (y_mod,y_residual)
197        }else{
198            let y_mod = (delta_y/self.y_step_size).floor() as usize + 1;
199            let y_residual = (y_scaled_residual-1.0)*self.y_step_size;
200            (y_mod,y_residual)
201        };
202
203        //   println!("{:?}",(x_mod,y_mod,x_residual,y_residual));
204        //residuals should be between -0.5 and 0.5 times the grid width
205
206        (x_mod,y_mod,x_residual,y_residual)
207    }
208    //TODO remove redundancey of these two functions
209    pub fn fit_grid_unscaled(&self, point:Point)->(usize,usize,f64,f64){
210        //ensure that the point is within the grid
211        match self.inside_or_outside(&point) {
212            Location::Outside => {
213                println!("Tried to grid point {:?}",point);
214                panic!("Tried to grid a point that was outside of the grid")}
215            Location::Inside => {}
216        }
217        //find the nearest point and then return the residuals to it
218
219        let (x,y) = point.convert(&self.coordinates).values();
220        //println!("{:?}corner {:?}",(x,y),(self.corner));
221        let (corner_x,corner_y) = self.corner;
222
223        let delta_x = x - corner_x;
224        let delta_y = y - corner_y;
225        //println!("DELTAS ARE {:?}",(delta_x,delta_y));
226        //  println!("delta x and delta y are {:?}, {:?}",delta_x,delta_y);
227        let x_scaled_residual = delta_x/self.x_step_size - (delta_x/self.x_step_size).floor();
228        let y_scaled_residual = delta_y/self.y_step_size - (delta_y/self.y_step_size).floor();
229
230        // println!("residuals are {:?}, {:?}",x_scaled_residual,y_scaled_residual);
231
232        let (x_mod, x_residual) = if x_scaled_residual <= 0.5{
233            let x_mod = (delta_x/self.x_step_size).floor() as usize;
234            let x_residual = x_scaled_residual;
235
236            (x_mod,x_residual)
237
238        }else{
239            let x_mod = (delta_x/self.x_step_size).floor() as usize + 1;
240            let x_residual = (x_scaled_residual-1.0);
241            (x_mod,x_residual)
242        };
243
244        let (y_mod,y_residual) = if y_scaled_residual <=0.5{
245            let y_mod = (delta_y/self.y_step_size).floor() as usize;
246            let y_residual = y_scaled_residual;
247            (y_mod,y_residual)
248        }else{
249            let y_mod = (delta_y/self.y_step_size).floor() as usize + 1;
250            let y_residual = (y_scaled_residual-1.0);
251            (y_mod,y_residual)
252        };
253
254        //   println!("{:?}",(x_mod,y_mod,x_residual,y_residual));
255        //residuals should be between -0.5 and 0.5 times the grid width
256        // println!("{:?} ",(x_mod,y_mod));
257        (x_mod,y_mod,x_residual,y_residual)
258    }
259
260    pub fn bin_up_patch(&self, center_of_the_corner_pixel:Point,psf:&Vec<Vec<f64>>,scale:usize)-> ((usize,usize),Vec<Vec<f64>>){ //TODO make this grid dependent
261
262
263
264        let (x_mod,y_mod,x_residual,y_residual) = self.fit_grid_unscaled(center_of_the_corner_pixel);
265        //unscaled returns the raction of the pixel
266        //TODO remove assumption that the psf is sven by even!!!
267        //TODO remove the assumption that the scale is an intege
268        //scale is the number of little pixels of the psf that fit into one big Detector pixel
269        //x direction
270        let x_pixels = 64; //TODO
271        let y_pixels = 64;
272        let scale = scale as f64;
273        let x_tail_end_in_pixels = x_residual*scale + scale/2.0 - 1.0;
274        let y_tail_end_in_pixels = y_residual*scale + scale/2.0 - 1.0;
275        let x_offset = if x_tail_end_in_pixels < 0.0{ 0 }else{
276            x_tail_end_in_pixels.ceil() as usize
277        };
278        let y_offset = if y_tail_end_in_pixels < 0.0{ 0 }else{
279            y_tail_end_in_pixels.ceil() as usize
280        };
281
282        let binned_x_size = if x_offset > 0{
283            (x_pixels as f64/scale + 1.0) as usize
284        }else{
285            (x_pixels as f64/scale)  as usize
286        };
287
288        let binned_y_size = if y_offset > 0{
289            (y_pixels as f64/scale + 1.0) as usize
290        }else{
291            (y_pixels as f64/scale)  as usize
292        };
293        //  println!("Binned x size, y size is {:?}",((x_pixels as f64/scale).ceil() as usize + 1,(y_pixels as f64/scale).ceil() as usize + 1));
294
295        let mut binned_psf = vec![vec![0.0;(x_pixels as f64/scale).ceil() as usize + 1];(y_pixels as f64/scale).ceil() as usize + 1];
296        for y in 0..y_pixels{
297            for x in 0..x_pixels{
298                let binned_x_index:usize = ((x + x_offset) as f64/scale).floor() as usize;
299                let binned_y_index:usize = ((y + y_offset) as f64/scale).floor() as usize;
300                binned_psf[binned_y_index][binned_x_index] += psf[y][x];
301            }
302        }
303        //  println!(" {:?} MODULUSES ER {:?}",center_of_the_corner_pixel,(x_mod,y_mod));
304        ((x_mod,y_mod),binned_psf)
305
306    }
307
308
309
310
311
312    pub fn inside_or_outside(&self, point:&Point) -> Location{
313        let (x,y) = point.convert(&self.coordinates).values();
314       // println!("POint in values: {:?}", (x,y));
315        let epsilon = self.snap_precision;
316        let (corner_x,corner_y) = self.corner;
317        let (grid_x_min, grid_x_max) = (corner_x, corner_x + self.x_size);
318        let (grid_y_min, grid_y_max) = (corner_y, corner_y + self.y_size);
319
320        if (x < grid_x_min - epsilon) | (x > grid_x_max + epsilon) | (y < grid_y_min - epsilon) | (y > grid_y_max + epsilon){
321            //println!("Point was outside of the grid, min x is {grid_x_min}, max x is {grid_x_max}, min y is {grid_y_min}, max y is {grid_y_max}");
322            return Location::Outside
323        };
324        Location::Inside
325    }
326
327    pub fn project(&self, point:&Point) -> Point{
328        //The idea is that we may want to get a value from a data grid or something, but we try to acces
329        //a poitn outside of the grid - we want to return a point which is the "projection" of that point on to the grid.
330        //So if the x value is too low, we want to return the minimum x, if the x value is too high, we want to return the maximum x
331        //same with y. In this way, the point location is "clipped" to fit the grid so that we can get the corresponding data.
332        //in order to find interpolation coefficients, we can first project the point into the grid and then preform the interpolation at that point.
333        //simple!
334        //This requires less shuffling around of the architecture.
335
336        let (x,y) = point.convert(&self.coordinates).values();
337        let (corner_x,corner_y) = self.corner;
338        let (grid_x_min, grid_x_max) = (corner_x, corner_x + self.x_size);
339        let (grid_y_min, grid_y_max) = (corner_y, corner_y + self.y_size);
340        
341        let new_x = if x < grid_x_min{ 
342            grid_x_min 
343        } else if x > grid_x_max{
344            grid_x_max
345        } else {
346            x
347        };
348        let new_y = if y < grid_y_min{
349            grid_y_min
350        } else if y > grid_y_max{
351            grid_y_max
352        } else {
353            y
354        };
355        Point::new(new_x,new_y,self.coordinates.clone())
356        
357
358    }
359
360
361
362    pub fn find_corners(&self,point:Point) -> Corners{
363        let epsilon = self.snap_precision;
364
365
366        let (x_mod,y_mod,x_residual,y_residual)  = self.fit_grid(&point);
367
368        //first we check to see if it is most appropriate to snap this point to a grid point:
369        if (x_residual.abs() <= epsilon) && (y_residual.abs() <= epsilon) {
370            // println!("Snapped to grid point");
371            return Corners::One(self.grid_number(x_mod,y_mod))
372        };
373        //Is the point between two vertical grid points?
374        if (x_residual.abs() <= epsilon) {
375            //println!("Snapped between vertical points");
376            if y_residual < 0.0{
377                return Corners::Two(self.grid_number(x_mod,y_mod),self.grid_number(x_mod,y_mod-1));
378            }else{
379                return Corners::Two(self.grid_number(x_mod,y_mod+1),self.grid_number(x_mod,y_mod));
380            }
381        };
382        //Is the point between two horizontal grid points?
383        if (y_residual.abs() <= epsilon) {
384            //  println!("Snapped between horizontal points");
385            if x_residual < 0.0{
386                return Corners::Two(self.grid_number(x_mod,y_mod),self.grid_number(x_mod-1,y_mod));
387            }else{
388                return Corners::Two(self.grid_number(x_mod+1,y_mod),self.grid_number(x_mod,y_mod));
389            }
390        };
391        //The point must be in the middle
392
393        let (upper_x,lower_x) = if x_residual < 0.0{ (x_mod,x_mod-1) }else{ (x_mod+1, x_mod)};
394        let (upper_y,lower_y) = if y_residual < 0.0{ (y_mod,y_mod-1) }else{ (y_mod+1, y_mod)};
395
396        // println!("Finding four corners, enumerated clockwise starting top left");
397        Corners::Four(self.grid_number(lower_x,upper_y),
398                      self.grid_number(upper_x,upper_y),
399                      self.grid_number(upper_x,lower_y),
400                      self.grid_number(lower_x,lower_y))
401
402    }
403
404    pub fn plot_points(&self, plot:&mut Plot, add_point:PlotPoint){
405        //self.coordinates.plot(plot, )
406
407        let mut grid_points = Curve::new();
408        grid_points.set_line_style("none")
409            .set_label(format!("Grid points: {:?}",self.label).as_str())
410            .set_marker_color("blue")
411            .set_marker_every(1)
412            .set_marker_size(7.0)
413            .set_marker_style(".");
414
415        let mut corner = Curve::new();
416        corner
417            .set_label("Corner")
418            .set_line_style("none")
419            .set_marker_color("#eeea83")
420            .set_marker_every(1)
421            .set_marker_size(10.0)
422            .set_marker_style(".");
423
424        let mut frame = Curve::new();
425        frame.set_line_width(1.0)
426            .set_label("Frame")
427            .set_line_style("solid")
428            .set_line_width(1.0)
429            .set_marker_color("purple")
430            .set_marker_every(1)
431            .set_marker_size(10.0)
432            .set_marker_style(".");
433
434        let mut extra_point = Curve::new();
435        extra_point.set_marker_color("#eeea83")
436            .set_marker_every(1)
437            .set_marker_size(10.0)
438            .set_line_style("none")
439            .set_marker_style("*");
440
441
442
443        let mut grid_numbers = Text::new();
444        grid_numbers.set_color("purple")
445            .set_fontsize(5.0);
446
447
448        grid_points.points_begin();
449        for point in 0..self.num_points{
450            let point_location = self.locate(point).to_absolute();
451            grid_points.points_add(point_location.x, point_location.y);
452            let label = format!("{}",point);
453            grid_numbers.draw(point_location.x, point_location.y, label.as_str());
454        }
455        grid_points.points_end();
456
457
458
459        corner.points_begin();
460        let corner_location = self.locate(0).to_absolute().values();
461        let corner_label = format!("Corner: ({:.3},{:.3})",corner_location.0,corner_location.1);
462        corner.points_add(corner_location.0,corner_location.1).set_label(corner_label.as_str());
463        corner.points_end();
464
465        let mut example_point = Vec::new();
466
467        match add_point {
468            PlotPoint::No => {}
469            PlotPoint::Given(point) => { example_point.push(point)}
470            PlotPoint::Random => {
471                let random = self.random();
472                example_point.push(random); }
473        };
474
475        for point in example_point{
476            let (_,_, x_res, y_res) = self.fit_grid(&point);
477            extra_point.points_begin();
478            extra_point.points_add(point.to_absolute().values().0,point.to_absolute().clone().values().1).set_label(format!("x, y residuals: {:.3}, {:.3}", x_res, y_res).as_str());
479            extra_point.points_end();
480
481            let corners  = self.find_corners(point);
482            let mut frame_points = Vec::new();
483            match corners{
484                Corners::Four(a, b, c, d) => {
485                    frame_points.push(a);
486                    frame_points.push(b);
487                    frame_points.push(c);
488                    frame_points.push(d);
489                    frame_points.push(a);
490                }
491                Corners::Two(a,b) => {
492                    frame_points.push(a);
493                    frame_points.push(b);}
494                Corners::One(a) => { frame_points.push(a); }
495            }
496            frame.points_begin();
497            for point in frame_points{
498                //println!("point {point}");
499                let point = self.locate(point).to_absolute();
500                frame.points_add(point.x,point.y);
501            }
502
503            frame.points_end();
504        }
505
506        plot.add(&frame);
507        plot.add(&grid_numbers);
508        plot.add(&grid_points);
509        plot.add(&extra_point);
510        plot.add(&corner)
511            .set_figure_size_inches(10.0,10.0)
512            .set_num_ticks_y(self.y_num+1)
513            .set_num_ticks_x(self.x_num+1)
514            .grid_labels_legend("x", "y");
515
516
517    }
518
519    pub fn outer_boarder(&self) -> (Point,Point, Point, Point){
520        let (c1x,c1y) = (self.corner.0 -self.x_step_size/2.0, self.corner.1-self.y_step_size/2.0);
521
522        let (c2x,c2y) = (c1x + self.x_size + self.x_step_size, c1y);
523        let (c3x,c3y) = (c1x + self.x_size + self.x_step_size, c1y + self.y_size + self.y_step_size);
524        let (c4x,c4y) = (c1x , c1y + self.y_size + self.y_step_size);
525
526        let point = Point::new(c1x,c1y,self.coordinates.clone());
527        // println!("CORNER IS AT {:?}",(self.corner,point.to_absolute()));
528        (Point::new(c1x,c1y,self.coordinates.clone()),
529         Point::new(c2x,c2y,self.coordinates.clone()),
530         Point::new(c3x,c3y,self.coordinates.clone()),
531         Point::new(c4x,c4y,self.coordinates.clone()))
532
533    }
534
535    pub fn plot_outline(&self, plot:&mut Plot, color: &str){
536        self.coordinates.plot(plot,color);
537
538        //let color = match &self.coordinates{ Coordinates::ABSOLUTE => "black", Coordinates::RELATIVE(c)=> c.color.as_str()};
539
540
541        let mut outline = Curve::new();
542        outline.set_line_width(1.0)
543            .set_label(format!("Frame of {:?}",self.label).as_str())
544            .set_line_style("solid")
545            .set_line_width(1.0)
546            .set_marker_color(color)
547            .set_line_color(color)
548            .set_marker_every(1)
549            .set_marker_size(10.0)
550            .set_marker_style(".");
551
552
553
554
555        outline.points_begin();
556
557        let (p0,p1,p2,p3) = self.outer_boarder();
558        let p0 = p0.to_absolute();
559        let p1 = p1.to_absolute();
560        let p2 = p2.to_absolute();
561        let p3 = p3.to_absolute();
562        outline.points_add(p0.x,p0.y);
563        outline.points_add(p1.x,p1.y);
564        outline.points_add(p2.x,p2.y);
565        outline.points_add(p3.x,p3.y);
566        outline.points_add(p0.x,p0.y);
567
568        outline.points_end();
569
570
571        plot.add(&outline);
572
573
574    }
575    
576    pub fn projected_interpolation_coefficients(&self, point:&Point)-> InterpolationData{
577        self.interpolation_coefficients(&self.project(point))
578    }
579
580
581    pub fn interpolation_coefficients(&self, point:&Point) -> InterpolationData{
582
583        match self.find_corners(point.clone()){
584            Corners::Four(Q12, Q22, Q21, Q11) => { // using the wikipedia convention https://en.wikipedia.org/wiki/Bilinear_interpolation
585
586                let Q11point = self.locate(Q11);
587                let Q22point = self.locate(Q22);
588
589                let (x1,y1) = (Q11point.x,Q11point.y);
590                let (x2,y2) = (Q22point.x,Q22point.y);
591                let (x,y) = point.convert(&self.coordinates).values();
592                let c11 = (x2-x)*(y2-y);
593                let c12 = (x2-x)*(y-y1);
594                let c21 = (x-x1)*(y2-y);
595                let c22 = (x-x1)*(y-y1);
596              //  println!("The coefficients are {:?}",(c11,c12,c21,c22));
597                let normalization = (x2-x1)*(y2-y1);
598                InterpolationData{
599                    corners: Corners::Four(Q12, Q22, Q21, Q11) ,
600                    coefficients:vec![c11,c12,c21,c22],
601                    normalization
602                }
603            }
604            Corners::Two(Q1, Q2) => {
605
606                let Q1point = self.locate(Q1);
607                let Q2point = self.locate(Q2);
608
609                let (x1,y1) = (Q1point.x,Q1point.y);
610                let (x2,y2) = (Q2point.x,Q2point.y);
611                let (x,y) = point.convert(&self.coordinates).values();
612
613                if ((x1-x2) < 2.0*self.snap_precision) && ((y1-y2) > 2.0*self.snap_precision){
614                    //the corners are above and below the point
615                    let c1 = (y1-y).abs();
616                    let c2 = (y2-y).abs();
617                    let normalization = self.y_step_size;
618                    return InterpolationData{
619                        corners: Corners::Two(Q1, Q2),
620                        coefficients:vec![c1,c2],
621                        normalization
622                    }
623                }else if ((x1-x2) > 2.0*self.snap_precision) && ((y1-y2) < 2.0*self.snap_precision){
624                    //the corners are to the sides of the point
625                    let c1 = (x1-x).abs();
626                    let c2 = (x2-x).abs();
627                    let normalization = self.x_step_size;
628                    return InterpolationData{
629                        corners: Corners::Two(Q1, Q2),
630                        coefficients:vec![c1,c2],
631                        normalization
632                    }
633                }else{
634                    panic!("Unreachable")
635                }
636
637            }
638            Corners::One(Q1) => {
639                InterpolationData{
640                    corners: Corners::One(Q1),
641                    coefficients:vec![1.0],
642                    normalization:1.0,
643                }
644            }
645        }
646
647    }
648
649
650}
651
652pub struct InterpolationData{
653    pub corners: Corners,
654    pub coefficients: Vec<f64>,
655    pub normalization:f64,
656}
657
658
659pub enum PlotPoint{
660    No,
661    Given(Point),
662    Random,
663}
664
665
666