1
+ #![ allow( dead_code) ]
1
2
use num:: integer:: Roots ;
2
3
3
4
use crate :: {
@@ -132,82 +133,84 @@ impl<'a> Circle<'_> {
132
133
}
133
134
134
135
/// detect an ellipse, and try to find defining points of it.
135
- pub fn detect_ellipse ( & self ) -> ( ( f32 , f32 ) , ( ( f32 , f32 ) , ( f32 , f32 ) , ( f32 , f32 ) , ( f32 , f32 ) ) ) {
136
- if ( self . image . get ( self . center . 0 + self . radius , self . center . 1 )
137
- && self . image . get ( self . center . 0 , self . center . 1 + self . radius )
138
- && self . image . get ( self . center . 0 - self . radius , self . center . 1 )
139
- && self . image . get ( self . center . 0 , self . center . 1 - self . radius ) )
140
- || self . horizontal_buckets [ 5 ] == self . vertical_buckets [ 5 ]
141
- {
142
- // probably allready a circle, or we already have true center
143
-
144
- //self.center
145
- todo ! ( )
146
- } else {
147
- // this looks like an ellipse, do ellipse magic
148
- // find semi-major and semi-minor axi
149
- let mut lengths = [ ( 0 , 0.0 , [ ( 0.0_f32 , 0.0 ) ; 2 ] ) ; 72 ] ;
150
- let mut circle_points = Vec :: new ( ) ;
151
- for i_rotation in 0 ..72 {
152
- let rotation = i_rotation as f32 * 5.0 ;
153
- let ( length, points) = self . find_width_at_degree ( rotation) ;
154
- circle_points. extend_from_slice ( & points) ;
155
- lengths[ i_rotation] = ( length, rotation, points) ;
156
- }
157
- lengths. sort_by_key ( |e| e. 0 ) ;
158
- let major_axis = lengths. last ( ) . unwrap ( ) ;
159
- let minor_axis = lengths. first ( ) . unwrap ( ) ;
160
-
161
- // // find foci
162
- let linear_eccentricity =
163
- ( ( major_axis. 0 / 2 ) . pow ( 2 ) - ( minor_axis. 0 / 2 ) . pow ( 2 ) ) . sqrt ( ) ;
136
+ /// returns (ellipse, center, semi_major, semi_minor, linear_eccentricity)
137
+ pub fn detect_ellipse ( & self ) -> ( bool , ( u32 , u32 ) , u32 , u32 , u32 ) {
138
+ // find semi-major and semi-minor axi
139
+ let mut lengths = [ ( 0 , 0.0 , [ ( 0.0_f32 , 0.0 ) ; 2 ] ) ; 72 ] ;
140
+ let mut circle_points = Vec :: new ( ) ;
141
+ for i_rotation in 0 ..72 {
142
+ let rotation = i_rotation as f32 * 5.0 ;
143
+ let ( length, points) = self . find_width_at_degree ( rotation) ;
144
+ circle_points. extend_from_slice ( & points) ;
145
+ lengths[ i_rotation] = ( length, rotation, points) ;
146
+ }
147
+ lengths. sort_by_key ( |e| e. 0 ) ;
148
+ let major_axis = lengths. last ( ) . unwrap ( ) ;
149
+ let minor_axis = lengths. first ( ) . unwrap ( ) ;
164
150
165
- if linear_eccentricity == 0 {
166
- // it's a circle afterall, and we're probably at the center of it
151
+ // // find foci
152
+ let linear_eccentricity = ( ( major_axis . 0 / 2 ) . pow ( 2 ) - ( minor_axis . 0 / 2 ) . pow ( 2 ) ) . sqrt ( ) ;
167
153
168
- //self.center
169
- todo ! ( )
170
- } else {
171
- //it's an elipse, or we're off center, so we need to fix that problem
172
- // let mut good_points = 0;
173
- // let mut bad_points = 0;
174
- let mut found_all_on_ellipse = true ;
175
- for point in & circle_points {
176
- let check_result = Self :: check_ellipse_point (
177
- self . center ,
178
- point,
179
- major_axis. 0 / 2 ,
180
- minor_axis. 0 / 2 ,
181
- ) ;
182
- if check_result > 1.0 {
183
- //&& check_result - Self::ALLOWABLE_ELLIPSE_SLIP > 1.0 {
184
- // a point is off the ellipse
185
- // bad_points += 1;
186
- found_all_on_ellipse = false ;
187
- break ;
188
- } /*else {
189
- good_points += 1;
190
- }*/
191
- }
192
- if !found_all_on_ellipse {
193
- // probably a circle that we wrongly accused of being an ellipse,
194
- // try to find the center of that circle given two points on circumference
195
- // let point_1 = major_axis.2[0];
196
- // let point_2 = minor_axis.2[1];
197
- // let point_3 = circle_points[((major_axis.0 + 3 + minor_axis.0 + 7) / 2) as usize];
198
- let [ point_1, point_2] = self . find_width_at_degree ( 0.0 ) . 1 ;
199
- let point_3 = self . find_width_at_degree ( 90.0 ) . 1 [ 0 ] ;
200
- let guessed_center_point = Self :: find_center ( point_1, point_2, point_3) ;
201
- // (
202
- // guessed_center_point.0.round() as u32,
203
- // guessed_center_point.1.round() as u32,
204
- // )
205
- todo ! ( )
154
+ if linear_eccentricity == 0 {
155
+ // it's a circle afterall, and we're probably at the center of it
156
+ ( false , self . center , self . radius , self . radius , 0 )
157
+ } else {
158
+ //it's an elipse, or we're off center, so we need to fix that problem
159
+ let mut good_points = 0 ;
160
+ let mut bad_points = 0 ;
161
+ let mut found_all_on_ellipse = true ;
162
+ for point in & circle_points {
163
+ let check_result = Self :: check_ellipse_point (
164
+ self . center ,
165
+ point,
166
+ major_axis. 0 / 2 ,
167
+ minor_axis. 0 / 2 ,
168
+ ) ;
169
+ if check_result > 1.0 {
170
+ // a point is off the ellipse
171
+ bad_points += 1 ;
172
+ found_all_on_ellipse = false ;
173
+ // break;
206
174
} else {
207
- // maybe an actual ellipse
208
- todo ! ( )
175
+ good_points += 1 ;
209
176
}
210
177
}
178
+ if !found_all_on_ellipse
179
+ && ( good_points as f32 / ( good_points + bad_points) as f32 ) < 0.8
180
+ {
181
+ // probably a circle that we wrongly accused of being an ellipse,
182
+ // try to find the center of that circle given three points on circumference
183
+ let [ point_1, point_2] = self . find_width_at_degree ( 0.0 ) . 1 ;
184
+ let point_3 = self . find_width_at_degree ( 90.0 ) . 1 [ 0 ] ;
185
+ let guessed_center_point = Self :: find_center ( point_1, point_2, point_3) ;
186
+ (
187
+ false ,
188
+ ( guessed_center_point. 0 as u32 , guessed_center_point. 1 as u32 ) ,
189
+ self . radius ,
190
+ self . radius ,
191
+ 0 ,
192
+ )
193
+ } else {
194
+ // this is a real ellipse
195
+
196
+ // find ellipse center
197
+ let [ point_1, point_2] = self . find_width_at_degree ( 0.0 ) . 1 ;
198
+ let point_3 = self . find_width_at_degree ( 90.0 ) . 1 [ 0 ] ;
199
+ let ellipse_center = Self :: calculate_ellipse_center (
200
+ major_axis. 0 as f32 ,
201
+ minor_axis. 0 as f32 ,
202
+ point_1,
203
+ point_2,
204
+ point_3,
205
+ ) ;
206
+ (
207
+ true ,
208
+ ( ellipse_center. 0 as u32 , ellipse_center. 1 as u32 ) ,
209
+ major_axis. 0 / 2 ,
210
+ minor_axis. 0 / 2 ,
211
+ linear_eccentricity,
212
+ )
213
+ }
211
214
}
212
215
}
213
216
@@ -230,6 +233,32 @@ impl<'a> Circle<'_> {
230
233
( x. abs ( ) , y. abs ( ) )
231
234
}
232
235
236
+ fn calculate_ellipse_center (
237
+ a : f32 ,
238
+ _b : f32 ,
239
+ p1 : ( f32 , f32 ) ,
240
+ p2 : ( f32 , f32 ) ,
241
+ p3 : ( f32 , f32 ) ,
242
+ ) -> ( f32 , f32 ) {
243
+ let x1 = p1. 0 ;
244
+ let y1 = p1. 1 ;
245
+ let x2 = p2. 0 ;
246
+ let y2 = p2. 1 ;
247
+ let x3 = p3. 0 ;
248
+ let y3 = p3. 1 ;
249
+
250
+ let ma = ( x1 * x1 + y1 * y1 - a * a) / 2.0 ;
251
+ let mb = ( x2 * x2 + y2 * y2 - a * a) / 2.0 ;
252
+ let mc = ( x3 * x3 + y3 * y3 - a * a) / 2.0 ;
253
+
254
+ let determinant = ( x1 * y2 + x2 * y3 + x3 * y1) - ( y1 * x2 + y2 * x3 + y3 * x1) ;
255
+
256
+ let x = ( ma * y2 + mb * y3 + mc * y1) / determinant;
257
+ let y = ( x1 * mb + x2 * mc + x3 * ma) / determinant;
258
+
259
+ ( x, y)
260
+ }
261
+
233
262
fn check_ellipse_point (
234
263
center : ( u32 , u32 ) ,
235
264
point : & ( f32 , f32 ) ,
@@ -248,7 +277,7 @@ impl<'a> Circle<'_> {
248
277
// count left
249
278
while {
250
279
let point = get_point ( self . center , ( x, y) , rotation) ;
251
- !self . image . get ( point. 0 as u32 , point. 1 as u32 )
280
+ !self . image . get ( point. 0 as u32 , point. 1 as u32 ) && x > 0
252
281
} {
253
282
x -= 1 ;
254
283
length += 1 ;
@@ -274,67 +303,6 @@ impl<'a> Circle<'_> {
274
303
] ,
275
304
)
276
305
}
277
-
278
- // fn find_cercumference(&self) -> (u32, Vec<(u32, u32)>) {
279
- // let mut x = self.center.0;
280
- // let mut y = self.center.1;
281
- // let mut points = Vec::new();
282
- // let mut circumference = 0;
283
-
284
- // // back up to the left wall
285
- // while !self.image.get(x, y) {
286
- // x -= 1;
287
- // }
288
- // x -= 1;
289
-
290
- // // this is our first point
291
- // points.push((x, y));
292
-
293
- // let start_x = x;
294
- // let start_y = y;
295
-
296
- // loop {
297
-
298
- // if x == start_x && y == start_y {
299
- // break;
300
- // }
301
- // circumference += 1;
302
- // points.push((x, y));
303
- // }
304
-
305
- // (circumference, points)
306
- // }
307
- // fn find_area(&self) -> u32 {
308
- // let mut pixel_area = 0;
309
-
310
- // let mut x = self.center.0;
311
- // let mut y = self.center.1;
312
-
313
- // // move to one end
314
- // while !self.image.get(x, y) {
315
- // y -= 1;
316
- // }
317
-
318
- // // work our way to the opposite side
319
- // while !self.image.get(x, y) {
320
- // // count left
321
- // x = self.center.0;
322
- // while !self.image.get(x, y) {
323
- // x -= 1;
324
- // pixel_area += 1;
325
- // }
326
- // // count right
327
- // x = self.center.0 + 1;
328
- // while !self.image.get(x, y) {
329
- // x += 1;
330
- // pixel_area += 1;
331
- // }
332
-
333
- // y += 1;
334
- // }
335
-
336
- // pixel_area
337
- // }
338
306
}
339
307
340
308
pub fn detect ( image : & BitMatrix , try_harder : bool ) -> Result < MaxicodeDetectionResult , Exceptions > {
@@ -737,20 +705,25 @@ fn box_symbol(image: &BitMatrix, circle: &mut Circle) -> Result<[(f32, f32); 4],
737
705
RXingResultPoint :: new ( right_boundary as f32 , top_boundary as f32 ) ,
738
706
] ;
739
707
708
+ #[ allow( unused_mut) ]
740
709
let mut result_box = naive_box;
741
710
711
+ // check and see if we're dealing with an ellipse
712
+ #[ cfg( feature = "experimental_features" ) ]
713
+ let ( is_ellipse, _, _, _, _) = circle. detect_ellipse ( ) ;
714
+ #[ cfg( feature = "experimental_features" ) ]
715
+ if is_ellipse {
716
+ // we don't deal with ellipses yet
717
+ return Err ( Exceptions :: NotFoundException ( None ) ) ;
718
+ }
719
+
742
720
#[ cfg( feature = "experimental_features" ) ]
743
721
for scale in ACCEPTED_SCALES {
744
722
if let Some ( found_rotation) = attempt_rotation_box ( image, circle, & naive_box, scale) {
745
723
result_box = found_rotation;
746
724
break ;
747
725
}
748
726
}
749
- // let result_box = if let Some(found_rotation) = attempt_rotation_box(image, circle, &naive_box) {
750
- // found_rotation
751
- // } else {
752
- // naive_box
753
- // };
754
727
755
728
Ok ( [
756
729
( result_box[ 0 ] . x , result_box[ 0 ] . y ) ,
0 commit comments