csabau / BTracking

Other
0 stars 0 forks source link

Tidy up #7

Open mhamilt opened 2 years ago

mhamilt commented 2 years ago

You are making it way more difficult for yourself to read and to edit code by taking this approach to style.

https://github.com/csabau/BTracking/blob/fd3a19db2b35466ef02608cdaebd96ce9d592262/BodyTracking-Example/BodyTracking-Example/ARSUIView2D.swift#L1-L314

This is a mess.

I'd recommend going through and cleaning out what isn't necessary.

You shouldn't be leaving that much dead space about. It isn't an effective strategy. I fit was, I'd expect to see a lot more progress.

Tell me this looks worse

//
//  ARView.swift
//  Body Tracking
//
//  Created by Grant Jarvis on 3/25/21.
//
//  What does this file contain?
//  What do the contents do?
//------------------------------------------------------------------------------
import SwiftUI
import UIKit
import ARKit
import RealityKit
import BodyTracking

//------------------------------------------------------------------------------

class ARSUIView2D: BodyARView {    
  //----------------------------------------------------------------------------
  private var bodyTracker: BodyTracker2D!
  //----------------------------------------------------------------------------
  /// Use this to display the angle formed at this joint.
  /// See the call to "angleBetween3Joints" below.
  private var angleLabel: UILabel!
  //----------------------------------------------------------------------------
  private var startJoint1 = CGPoint(x: 0, y: 0)
  private var endJoint1   = CGPoint(x: 40, y: 300)
  private var startJoint2 = CGPoint(x: 500, y: 600)
  private var endJoint2   = CGPoint(x: 200, y: 660)

  //----------------------------------------------------------------------------
  // Track the screen dimensions:
  lazy var windowWidth: CGFloat = {
    return UIScreen.main.bounds.size.width
  }()
  //----------------------------------------------------------------------------
  lazy var windowHeight: CGFloat = {
    return UIScreen.main.bounds.size.height
  }()

  //----------------------------------------------------------------------------
  required init(frame frameRect: CGRect) {
    super.init(frame: frameRect)
    self.bodyTracker = BodyTracker2D(arView: self)
    guard let _ = try? runBodyTrackingConfig2D() else { return }
    self.session.delegate = self

    makeRightElbowJointVisible()    
    makeOtherJointsVisible()
  }
  //----------------------------------------------------------------------------  
  /// This is an example for how to show one joint.
  private func makeRightElbowJointVisible(){
    let rightElbowCircle = makeCircle(circleRadius: 20)
    // ** HERE is the useful code: **
    // How to attach views to the skeleton:
    self.bodyTracker.attach(thisView: rightElbowCircle, 
                         toThisJoint: .right_forearm_joint)

    // Use this to display the angle formed at this joint.
    // See the call to "angleBetween3Joints" below.
    angleLabel = UILabel(frame: CGRect(origin: CGPoint(x: 0, y: 0), 
                                         size: CGSize(width: 100, height: 50)))

    rightElbowCircle.addSubview(angleLabel)
  }

  //----------------------------------------------------------------------------
  /// This is an example for how to show multiple joints, iteratively.
  private func makeOtherJointsVisible(){
    // There are more joints you could attach views to, I'm just using these.
    let jointsToShow : [TwoDBodyJoint] = [
      .right_hand_joint, 
      .right_shoulder_1_joint,
      .left_forearm_joint, 
      .left_hand_joint,
      .left_shoulder_1_joint,
      .head_joint, 
      .neck_1_joint,
      .root, 
      .right_upLeg_joint, 
      .right_leg_joint,
      .right_foot_joint, 
      .left_upLeg_joint, 
      .left_leg_joint,
      .left_foot_joint
    ]

    let bone1 = DrawLine(frame: CGRect(x: 0, y: 0, width: self.windowWidth, height: self.windowHeight), start: startJoint1, end: endJoint1)
    self.bodyTracker.attachLine(thisNewView: bone1)
    let bone2 = DrawLine(frame: CGRect(x: 0, y: 0, width: self.windowWidth, height: self.windowHeight), start: startJoint2, end: endJoint2)
    self.bodyTracker.attachLine(thisNewView: bone2)    
  }
  //----------------------------------------------------------------------------
  ///
  override func stopSession(){
    super.stopSession()
    self.bodyTracker.destroy()
    self.bodyTracker = nil
    self.angleLabel.removeFromSuperview()
  }
  //----------------------------------------------------------------------------
  /// setting the stroke colour to the branded GREEN and circle color to dark grey
  private func makeCircle(circleRadius: CGFloat = 72, 
                                stroke: CGColor = #colorLiteral(red: 0.670588235294118, 
                                                              green: 0.898039215686275,
                                                               blue: 0.12156862745098,
                                                              alpha: 1),
                                 color: CGColor = #colorLiteral(red: 0.250980392156863, 
                                                              green: 0.250980392156863, 
                                                               blue: 0.250980392156863, 
                                                              alpha: 0.5)) -> UIView {                                  
    // Place circle at the center of the screen to start.
    let xStart = floor((windowWidth - circleRadius) / 2)
    let yStart = floor((windowHeight - circleRadius) / 2)
    let frame = CGRect(x: xStart, y: yStart, width: circleRadius, height: circleRadius)

    let circleView = UIView(frame: frame)
    circleView.layer.cornerRadius = circleRadius / 2
    circleView.layer.backgroundColor = color
    circleView.layer.borderColor = stroke
    circleView.layer.borderWidth = 3
    return circleView
  }

  //----------------------------------------------------------------------------
  /// Class for generating simple updaable UI Views that contain a straight line Path
  /// NOTE: Should this be a class within a class? Probably want to have your own .swift file for this.
  class DrawLine: UIView  {

    var path: UIBezierPath!
    var strokeColour: CGColor = #colorLiteral(red: 0.670588235294118, green: 0.898039215686275, blue: 0.12156862745098, alpha: 1)
    var fillColour: CGColor = #colorLiteral(red: 0.250980392156863, green: 0.250980392156863, blue: 0.250980392156863, alpha: 0.0)
    var startPoint: CGPoint?
    var endPoint: CGPoint?

    //----------------------------------------------------------------------
    init(frame: CGRect, start: CGPoint, end: CGPoint){

      self.startPoint = start
      self.endPoint = end
      super.init(frame: frame)          
      simpleShapeLayer()
    }
    //----------------------------------------------------------------------
    required init?(coder aDecoder: NSCoder) {            
      super.init(coder: aDecoder)
    }
    //----------------------------------------------------------------------
    /// simple straight path generator
    func createLine(start: CGPoint, end: CGPoint) {
      path = UIBezierPath()

      path.move(to: start)
      path.addLine(to: end)
    }
    //----------------------------------------------------------------------
    /// create the CAShapeLayer Object because it's more versatile and 
    /// can define stroke width. We assign the path of the BezierPath from above
    func simpleShapeLayer() {
      self.createLine(start: startPoint!, end: endPoint!)

      let shapeLayer = CAShapeLayer()
      shapeLayer.path = self.path.cgPath

      shapeLayer.fillColor = fillColour
      shapeLayer.strokeColor = strokeColour
      shapeLayer.lineWidth = 4.0

      self.layer.addSublayer(shapeLayer)            
    }    
  }
  //--------------------------------------------------------------------------    
  //required function.
  @objc required dynamic init?(coder decoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
  }

} 
//------------------------------------------------------------------------------
///
extension ARSUIView2D: ARSessionDelegate 
{    
  // For RealityKit 2 we should use a RealityKit System instead of this update 
  // function but that would be limited to devices running iOS 15.0+
  func session(_ session: ARSession, didUpdate frame: ARFrame) {

    // The formatting rounds the number.
    if let jointAngle = self.bodyTracker.angleBetween3Joints(.right_hand_joint,
                                                             .right_forearm_joint,
                                                             .right_shoulder_1_joint) {
      self.angleLabel.text = String(format: "%.0f", Float(jointAngle))
    }
  }
}
csabau commented 2 years ago

I see what you mean, it could be a matter of preference really. I prefer to have blank space in between blocks of code and /------ only when it's a new / really important piece of code that I need to draw my attention to - like a highlight. Delimiting the functions with /----- is extremely hard on the eye for me and I lose track even get dizzy! haha

I promise, there's a method to the madness, it may look messy, but's it's an organised mess

mhamilt commented 2 years ago

Delimiting the functions with /----- is extremely hard on the eye for me and I lose track even get dizzy! haha

You should be scanning the right margin / gutter and this will allow quick demarcation between functions. Your eye really only goes to the left or the middle when there is code, in which case you won't be looking at the banners (//----) you'll be looking at code

Also, it isn't just about banners, but the usage of newlines and indentation to make it easy to see what is a cohesive block and what is a new statement e.g.

angleLabel = UILabel(frame: CGRect(origin: CGPoint(x: 0, y: 0), size: CGSize(width: 100, height: 50))) 

vs

    angleLabel = UILabel(frame: CGRect(origin: CGPoint(x: 0, y: 0), 
                                         size: CGSize(width: 100, height: 50)))                                        

and

let jointsToShow : [TwoDBodyJoint] = [.right_hand_joint, .right_shoulder_1_joint, 
                                            .left_forearm_joint, .left_hand_joint, 
                                            .left_shoulder_1_joint, 
                                            .head_joint, .neck_1_joint, 
                                               .root, .right_upLeg_joint, .right_leg_joint, 
                                               .right_foot_joint, .left_upLeg_joint, .left_leg_joint, 
                                            .left_foot_joint] 

vs

    let jointsToShow : [TwoDBodyJoint] = [
      .right_hand_joint, 
      .right_shoulder_1_joint,
      .left_forearm_joint, 
      .left_hand_joint,
      .left_shoulder_1_joint,
      .head_joint, 
      .neck_1_joint,
      .root, 
      .right_upLeg_joint, 
      .right_leg_joint,
      .right_foot_joint, 
      .left_upLeg_joint, 
      .left_leg_joint,
      .left_foot_joint
    ]

By reformatting you also implicitly are required to consider the code and what it does. It should give you a better understanding of what you are dealing with.

I promise, there's a method to the madness, it may look messy, but's it's an organised mess

remember, you might not be the only person reading the code.