react-native-rectangle-doc-scanner 1.8.0 → 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -262,9 +262,9 @@ class RNRDocScannerView: UIView, AVCaptureVideoDataOutputSampleBufferDelegate, A
262
262
  effectiveObservation = nil
263
263
  }
264
264
 
265
- updateNativeOverlay(with: effectiveObservation)
266
-
265
+ let overlayStableThreshold = max(2, Int(truncating: detectionCountBeforeCapture) / 2)
267
266
  let payload: [String: Any?]
267
+
268
268
  if let observation = effectiveObservation {
269
269
  let points = [
270
270
  pointForOverlay(from: observation.topLeft, frameSize: frameSize),
@@ -274,6 +274,13 @@ class RNRDocScannerView: UIView, AVCaptureVideoDataOutputSampleBufferDelegate, A
274
274
  ]
275
275
 
276
276
  currentStableCounter = min(currentStableCounter + 1, Int(truncating: detectionCountBeforeCapture))
277
+
278
+ let normalizedArea = observation.boundingBox.width * observation.boundingBox.height
279
+ let meetsArea = normalizedArea >= 0.06 && normalizedArea <= 0.95
280
+ let meetsConfidence = observation.confidence >= 0.65
281
+ let shouldDisplayOverlay = currentStableCounter >= overlayStableThreshold && meetsArea && meetsConfidence
282
+ updateNativeOverlay(with: shouldDisplayOverlay ? observation : nil)
283
+
277
284
  payload = [
278
285
  "rectangleCoordinates": [
279
286
  "topLeft": ["x": points[0].x, "y": points[0].y],
@@ -287,6 +294,7 @@ class RNRDocScannerView: UIView, AVCaptureVideoDataOutputSampleBufferDelegate, A
287
294
  ]
288
295
  } else {
289
296
  currentStableCounter = 0
297
+ updateNativeOverlay(with: nil)
290
298
  payload = [
291
299
  "rectangleCoordinates": NSNull(),
292
300
  "stableCounter": currentStableCounter,
@@ -311,6 +319,7 @@ class RNRDocScannerView: UIView, AVCaptureVideoDataOutputSampleBufferDelegate, A
311
319
  self.gridLayer.path = nil
312
320
  self.outlineLayer.isHidden = true
313
321
  self.gridLayer.isHidden = true
322
+ self.smoothedOverlayPoints = nil
314
323
  return
315
324
  }
316
325
 
@@ -318,13 +327,26 @@ class RNRDocScannerView: UIView, AVCaptureVideoDataOutputSampleBufferDelegate, A
318
327
  return
319
328
  }
320
329
 
321
- let points = [
330
+ let rawPoints = [
322
331
  self.convertToLayerPoint(observation.topLeft, previewLayer: previewLayer),
323
332
  self.convertToLayerPoint(observation.topRight, previewLayer: previewLayer),
324
333
  self.convertToLayerPoint(observation.bottomRight, previewLayer: previewLayer),
325
334
  self.convertToLayerPoint(observation.bottomLeft, previewLayer: previewLayer),
326
335
  ]
327
336
 
337
+ let orderedPoints = self.orderPoints(rawPoints)
338
+
339
+ let points: [CGPoint]
340
+ if let previous = self.smoothedOverlayPoints, previous.count == 4 {
341
+ points = zip(previous, orderedPoints).map { prev, next in
342
+ CGPoint(x: prev.x * 0.85 + next.x * 0.15, y: prev.y * 0.85 + next.y * 0.15)
343
+ }
344
+ } else {
345
+ points = orderedPoints
346
+ }
347
+
348
+ self.smoothedOverlayPoints = points
349
+
328
350
  let outline = UIBezierPath()
329
351
  outline.move(to: points[0])
330
352
  outline.addLine(to: points[1])
@@ -364,6 +386,37 @@ class RNRDocScannerView: UIView, AVCaptureVideoDataOutputSampleBufferDelegate, A
364
386
  CGPoint(x: start.x + (end.x - start.x) * t, y: start.y + (end.y - start.y) * t)
365
387
  }
366
388
 
389
+ private func orderPoints(_ points: [CGPoint]) -> [CGPoint] {
390
+ guard points.count == 4 else { return points }
391
+
392
+ let center = points.reduce(CGPoint.zero) { partial, point in
393
+ CGPoint(x: partial.x + point.x / 4.0, y: partial.y + point.y / 4.0)
394
+ }
395
+
396
+ let angles = points.map { point -> (CGPoint, CGFloat) in
397
+ let angle = atan2(point.y - center.y, point.x - center.x)
398
+ return (point, angle)
399
+ }
400
+
401
+ let sorted = angles.sorted { $0.1 < $1.1 }.map { $0.0 }
402
+
403
+ var startIndex = 0
404
+ for index in 1..<sorted.count {
405
+ let candidate = sorted[index]
406
+ let current = sorted[startIndex]
407
+ if candidate.y < current.y || (candidate.y == current.y && candidate.x < current.x) {
408
+ startIndex = index
409
+ }
410
+ }
411
+
412
+ return [
413
+ sorted[startIndex % 4],
414
+ sorted[(startIndex + 1) % 4],
415
+ sorted[(startIndex + 2) % 4],
416
+ sorted[(startIndex + 3) % 4],
417
+ ]
418
+ }
419
+
367
420
  // MARK: - Capture
368
421
 
369
422
  func capture(completion: @escaping (Result<RNRDocScannerCaptureResult, Error>) -> Void) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-rectangle-doc-scanner",
3
- "version": "1.8.0",
3
+ "version": "1.10.0",
4
4
  "description": "Native-backed document scanner for React Native with customizable overlays.",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",