replate-camera 0.1.7 → 0.1.8

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.
@@ -274,17 +274,17 @@ class ReplateCameraController: RCTEventEmitter {
274
274
 
275
275
  //DEVICE ORIENTATION
276
276
  guard let anchorNode = ReplateCameraView.anchorEntity else {
277
- rejecter("[ReplateCameraController]", "Error saving photo", NSError(domain: "ReplateCameraController", code: 001, userInfo: nil));
277
+ rejecter("[ReplateCameraController]", "No anchor set yet", NSError(domain: "ReplateCameraController", code: 001, userInfo: nil));
278
278
  return
279
279
  }
280
280
 
281
281
  // Assuming you have two points
282
- let point1 = SIMD3<Float>(anchorNode.position.x,
283
- anchorNode.position.y,
284
- anchorNode.position.z)
285
- let point2 = SIMD3<Float>(anchorNode.position.x,
286
- anchorNode.position.y + 0.3,
287
- anchorNode.position.z)
282
+ let point1 = SIMD3<Float>(anchorNode.position(relativeTo: nil).x,
283
+ anchorNode.position(relativeTo: nil).y,
284
+ anchorNode.position(relativeTo: nil).z)
285
+ let point2 = SIMD3<Float>(anchorNode.position(relativeTo: nil).x,
286
+ anchorNode.position(relativeTo: nil).y + 0.3,
287
+ anchorNode.position(relativeTo: nil).z)
288
288
 
289
289
  // Function to calculate the angle between two vectors
290
290
  func angleBetweenVectors(_ vector1: SIMD3<Float>, _ vector2: SIMD3<Float>) -> Float {
@@ -293,22 +293,33 @@ class ReplateCameraController: RCTEventEmitter {
293
293
  }
294
294
 
295
295
  // Threshold angle for considering if the device is pointing towards a point
296
- let thresholdAngle: Float = 0.3 // Adjust this threshold as needed
297
296
  var deviceTargetInFocus = -1
298
297
  // Check if the device is pointing towards one of the two points
299
298
  if let cameraTransform = ReplateCameraView.arView.session.currentFrame?.camera.transform {
300
299
  let deviceDirection = SIMD3<Float>(-cameraTransform.columns.2.x, -cameraTransform.columns.2.y, -cameraTransform.columns.2.z)
301
300
 
302
301
  let cameraPosition = SIMD3<Float>(cameraTransform.columns.3.x, cameraTransform.columns.3.y, cameraTransform.columns.3.z)
303
-
304
302
  let directionToFirstPoint = normalize(point1 - cameraPosition)
305
303
  let directionToSecondPoint = normalize(point2 - cameraPosition)
306
304
 
305
+ let point1Distance = distance(point1, cameraPosition)
306
+ let point2Distance = distance(point2, cameraPosition)
307
+ let averageDistance = (point1Distance + point2Distance) / 2.0
308
+
309
+ let baseThreshold: Float = 0.6 // adjust as needed
310
+ let distanceFactor: Float = 0.2 // adjust as needed
311
+
312
+ let dynamicThreshold = baseThreshold + distanceFactor * sqrt(averageDistance)
313
+
314
+
307
315
  let angleToFirstPoint = angleBetweenVectors(deviceDirection, directionToFirstPoint)
308
316
  let angleToSecondPoint = angleBetweenVectors(deviceDirection, directionToSecondPoint)
309
- print("Camera Y: \(cameraPosition.y)")
310
- let isPointingAtFirstPoint = angleToFirstPoint < thresholdAngle && cameraPosition.y < 0.25
311
- let isPointingAtSecondPoint = angleToSecondPoint < thresholdAngle && cameraPosition.y >= 0.25
317
+ print("Camera: \(cameraPosition)")
318
+ print("Point 1 position: \(point1) Point 2 position: \(point2)")
319
+ print("Angle to first: ", angleToFirstPoint, " Angle to second: ", angleToSecondPoint)
320
+ print("Threshold \(dynamicThreshold)")
321
+ let isPointingAtFirstPoint = angleToFirstPoint < dynamicThreshold && cameraPosition.y < anchorNode.position.y + 0.20
322
+ let isPointingAtSecondPoint = angleToSecondPoint < dynamicThreshold && cameraPosition.y >= anchorNode.position.y + 0.20
312
323
  if (isPointingAtFirstPoint) {
313
324
  deviceTargetInFocus = 0
314
325
  }else if(isPointingAtSecondPoint){
@@ -332,6 +343,18 @@ class ReplateCameraController: RCTEventEmitter {
332
343
  let uiImage = UIImage(cgImage: cgImage)
333
344
  let finImage = uiImage.rotate(radians: .pi/2) // Adjust radians as needed
334
345
 
346
+ guard let components = finImage.averageColor()?.getRGBComponents()
347
+ else {
348
+ rejecter("[ReplateCameraController]", "Cannot get color components", NSError(domain: "ReplateCameraController", code: 003, userInfo: nil))
349
+ return
350
+ }
351
+ let averagePixelColor = components.red + components.blue + components.green / 3
352
+ print("Average pixel color: \(averagePixelColor)")
353
+ if ((components.red + components.blue + components.green) / 3 < 0.15){
354
+ rejecter("[ReplateCameraController]", "Image too dark", NSError(domain: "ReplateCameraController", code: 004, userInfo: nil))
355
+ return
356
+ }
357
+
335
358
  print("Saving photo")
336
359
  if let url = ReplateCameraController.saveImageAsJPEG(finImage) {
337
360
  resolver(url.absoluteString)
@@ -396,6 +419,11 @@ class ReplateCameraController: RCTEventEmitter {
396
419
  self.sendEvent(withName: "arTutorialCompleted", body: true)
397
420
  }
398
421
 
422
+ @objc
423
+ override func supportedEvents() -> [String]! {
424
+ return ["arTutorialCompleted"]
425
+ }
426
+
399
427
 
400
428
  func updateSpheres(deviceTargetInFocus: Int) {
401
429
  guard let anchorNode = ReplateCameraView.anchorEntity else { return }
@@ -405,9 +433,9 @@ class ReplateCameraController: RCTEventEmitter {
405
433
  let cameraTransform = frame.camera.transform
406
434
 
407
435
  // Calculate the angle between the camera and the anchor
408
- let anchorPosition = SCNVector3(anchorNode.position.x,
409
- anchorNode.position.y,
410
- anchorNode.position.z)
436
+ let anchorPosition = SCNVector3(anchorNode.position(relativeTo: nil).x,
437
+ anchorNode.position(relativeTo: nil).y,
438
+ anchorNode.position(relativeTo: nil).z)
411
439
  let cameraPosition = SCNVector3(cameraTransform.columns.3.x,
412
440
  cameraTransform.columns.3.y,
413
441
  cameraTransform.columns.3.z)
@@ -436,9 +464,9 @@ class ReplateCameraController: RCTEventEmitter {
436
464
  }
437
465
  }
438
466
 
439
- func calculateAngle(_ vector1: SCNVector3, _ vector2: SCNVector3) -> Float {
467
+ func calculateAngle(_ camera: SCNVector3, _ anchor: SCNVector3) -> Float {
440
468
  // Calculate the angle in 2D plane (x-z plane) using atan2
441
- let angle = atan2(vector1.z, vector1.x)
469
+ let angle = atan2(camera.z - anchor.z, camera.x - anchor.x)
442
470
 
443
471
  // Convert from radians to degrees
444
472
  var angleInDegrees = GLKMathRadiansToDegrees(Float(angle))
@@ -448,6 +476,14 @@ class ReplateCameraController: RCTEventEmitter {
448
476
  angleInDegrees += 360
449
477
  }
450
478
 
479
+ // Rotate by 2.5 degrees to consider sphere-center, not sphere-begin
480
+ angleInDegrees += 2.5
481
+
482
+ // If rotating resulted in angle > 360 degrees, subtract 360
483
+ if angleInDegrees >= 360 {
484
+ angleInDegrees -= 360
485
+ }
486
+
451
487
  return angleInDegrees
452
488
  }
453
489
 
@@ -491,3 +527,66 @@ extension ARView: ARCoachingOverlayViewDelegate {
491
527
  print("CRASHED")
492
528
  }
493
529
  }
530
+
531
+ extension UIImage {
532
+ func averageColor() -> UIColor? {
533
+ // Convert UIImage to CGImage
534
+ guard let cgImage = self.cgImage else { return nil }
535
+
536
+ // Get width and height of the image
537
+ let width = cgImage.width
538
+ let height = cgImage.height
539
+
540
+ // Create a data provider from CGImage
541
+ guard let dataProvider = cgImage.dataProvider else { return nil }
542
+
543
+ // Access pixel data
544
+ guard let pixelData = dataProvider.data else { return nil }
545
+
546
+ // Create a pointer to the pixel data
547
+ let data: UnsafePointer<UInt8> = CFDataGetBytePtr(pixelData)
548
+
549
+ var totalRed: CGFloat = 0
550
+ var totalGreen: CGFloat = 0
551
+ var totalBlue: CGFloat = 0
552
+
553
+ // Loop through each pixel and calculate sum of RGB values
554
+ for y in 0..<height {
555
+ for x in 0..<width {
556
+ let pixelInfo: Int = ((width * y) + x) * 4
557
+ let red = CGFloat(data[pixelInfo]) / 255.0
558
+ let green = CGFloat(data[pixelInfo + 1]) / 255.0
559
+ let blue = CGFloat(data[pixelInfo + 2]) / 255.0
560
+
561
+ totalRed += red
562
+ totalGreen += green
563
+ totalBlue += blue
564
+ }
565
+ }
566
+
567
+ // Calculate average RGB values
568
+ let count = CGFloat(width * height)
569
+ let averageRed = totalRed / count
570
+ let averageGreen = totalGreen / count
571
+ let averageBlue = totalBlue / count
572
+
573
+ // Create and return average color
574
+ return UIColor(red: averageRed, green: averageGreen, blue: averageBlue, alpha: 1.0)
575
+ }
576
+ }
577
+
578
+ extension UIColor {
579
+ func getRGBComponents() -> (red: CGFloat, green: CGFloat, blue: CGFloat)? {
580
+ var red: CGFloat = 0
581
+ var green: CGFloat = 0
582
+ var blue: CGFloat = 0
583
+ var alpha: CGFloat = 0
584
+
585
+ // Check if the color can be converted to RGB
586
+ guard self.getRed(&red, green: &green, blue: &blue, alpha: &alpha) else {
587
+ return nil
588
+ }
589
+
590
+ return (red, green, blue)
591
+ }
592
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "replate-camera",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "description": "Camera component for Replate Manager",
5
5
  "main": "lib/commonjs/index",
6
6
  "module": "lib/module/index",