title: Swift- change star map view according to coordinate and time
body: <p>i am trying to figure out the way to correct my star map view according to user's time and coordinate, but it's not really accurate so i'm wondering which part is wrong.</p>
  
  <p>i have two nodes, star map node and camera node, and the camera node is inside the star map node to make it like 360 view. 
  here is my way to make it:</p>
  
  <p>1.get the acceleration data</p>
  
  <pre><code>motionManager.startAccelerometerUpdatesToQueue(NSOperationQueue.currentQueue()!, withHandler: {(accelerometerData, error) -&gt; Void in
  
      self.outputAccelerationData(accelerometerData!.acceleration)
  
      if(error != nil) {
          print("\(error)")
      }
  })
  
  func outputAccelerationData(acceleration: CMAcceleration) {
  
      let accZ: Double = fabs(acceleration.z)
      rotateDegreeCameraX = acos(accZ) * 180 / M_PI
  
  }
  </code></pre>
  
  <ol start="2">
  <li>correct the camera node to where it's looking at</li>
  </ol>
  
  <p>// let the camera node start from looking at vernal equinox //</p>
  
  <pre><code>  private func orientationFromCMQuaternion(attitudeQuaternion: CMQuaternion, trueHeading: Float) -&gt; SCNVector4 { 
      let gq1 = GLKQuaternionMakeWithAngleAndAxis(GLKMathDegreesToRadians(Float(rotateDegreeCameraX) - 90), 1, 0, 0)
      let gq2 = GLKQuaternionMakeWithAngleAndAxis(GLKMathDegreesToRadians(180), 0, 0, 1)
      let gq3 = GLKQuaternionMakeWithAngleAndAxis(GLKMathDegreesToRadians(trueHeading), 0, 0, 1)       
      let gq4 = GLKQuaternionMake(Float(attitudeQuaternion.x), Float(attitudeQuaternion.y), Float(attitudeQuaternion.z), Float(attitudeQuaternion.w))
  
      let qp = GLKQuaternionMultiply(gq1, gq2)
      let qp2 = GLKQuaternionMultiply(qp, gq3)
      let qp3 = GLKQuaternionMultiply(qp2, gq4)
      let rq = CMQuaternion(x: Double(qp3.x), y: Double(qp3.y), z: Double(qp3.z), w: Double(qp3.w))
      return SCNVector4Make(Float(rq.x), Float(rq.y), Float(rq.z), Float(rq.w))
  }
  </code></pre>
  
  <ol start="3">
  <li><p>correct the star map (SCNshpere) according to user's time and coordinate</p>
  
  <p>func correctOfSkyMap(revolution: Float, rotation: Float, latitude: Float) -> SCNVector4  {</p>
  
  <pre><code> // rotate the sphere, making Equatorial plane is now same position with Ecliptic plane. (degrees: 23.4397) //
   let gq = GLKQuaternionMakeWithAngleAndAxis(GLKMathDegreesToRadians(-23.4397), 0, 0, 1)
  
   // rotate the sphere according to the gap between current date and the date vernal equinox pass 0 longitude //
   let gq2 = GLKQuaternionMakeWithAngleAndAxis(GLKMathDegreesToRadians(-revolution), 0, 1, 0)
   let qp = GLKQuaternionMultiply(gq, gq2)
  
   // rotate sphere back to where Equatorial plane is //
   let gq3 = GLKQuaternionMakeWithAngleAndAxis(GLKMathDegreesToRadians(-23.4397), 0, 0, 1)
   let qp2 = GLKQuaternionMultiply(qp, gq3)
  
   // rotate the sphere according to current time //
   let gq4 = GLKQuaternionMakeWithAngleAndAxis(GLKMathDegreesToRadians(-rotation), 0, 1, 0)
   let qp3 = GLKQuaternionMultiply(qp2, gq4)
  
   // rotate sphere according to user's latitude (adjust the degree of polaris) //
   let gq5 = GLKQuaternionMakeWithAngleAndAxis(GLKMathDegreesToRadians(latitude - 90), 1, 0, 0)
   let qp4 = GLKQuaternionMultiply(qp3, gq5)
  
   // after comparing with other star gazing app, finding the map needs to rotate 90 degrees to make it more accurate. //
   let gq6 = GLKQuaternionMakeWithAngleAndAxis(GLKMathDegreesToRadians(90), 0, 0, 1)
   let qp5 = GLKQuaternionMultiply(qp4, gq6)
  
   return SCNVector4Make(qp5.x, qp5.y, qp5.z, qp5.w)   }
  </code></pre></li>
  <li><p>Here are methods to calculate revolution and rotation:</p>
  
  <p>func calculateRevolution() -> Float  {</p>
  
  <pre><code>let degreePerDay: Double = 0.9656112744
  let originalDate = NSDate()
  let dateFormatter = NSDateFormatter()
  dateFormatter.dateFormat = "yyyy-MM-dd HH:mm"
  dateFormatter.timeZone = NSTimeZone(abbreviation: "UTC")
  let currentDateStr = dateFormatter.stringFromDate(originalDate)
  if let currentDate = dateFormatter.dateFromString(currentDateStr),
      let vernalEquinox = dateFormatter.dateFromString("2016-03-20 04:30") {
  
      let currentDateInSecs = currentDate.timeIntervalSinceDate(vernalEquinox)
      let currentDateInDays = currentDateInSecs / (60 * 60 * 24)
      let rotateDegreesDouble = currentDateInDays * degreePerDay
      let rotateDegrees = Float(rotateDegreesDouble)
  
      return rotateDegrees
  
  } else { return 0.0 }}
  </code></pre>
  
  <p>func calculateEarthRotation() -> Float {</p>
  
  <pre><code>let degreePerMinute: Double = 0.25
  let originalDate = NSDate()
  let dateFormatter = NSDateFormatter()
  dateFormatter.timeZone = NSTimeZone(abbreviation: "UTC")
  dateFormatter.dateFormat = "yyyy-MM-dd HH:mm"
  let originalDateStr = dateFormatter.stringFromDate(originalDate)
  if let currentDate = dateFormatter.dateFromString(originalDateStr) {
      let calendar = NSCalendar.currentCalendar()
      let hours = Double(calendar.component(.Hour, fromDate: currentDate))
      let minutes = Double(calendar.component(.Minute, fromDate: currentDate))
  
      print("pass time: \(hours * 60 + minutes)")
      print("Local date: \(originalDate)")
      print("Date in UTC: \(currentDate)")
  
      return Float((hours * 60 + minutes) * degreePerMinute)
  
  } else {return 0.0}}
  </code></pre></li>
  </ol>
  
  <p>Could anyone give me some advice to accurate it? thanks in advance.</p>