iosは簡単に自由に動くAR機能を実現します。

3852 ワード

最後の効果動態図を先に示します。

1、まず私達はカメラのインターフェイスをカスタマイズしたいです。AVCaptureSessionでカスタマイズできます。他のボタンはいらないです。プレビューの画面だけあります。
2、簡単なレーダー図を描きたいです。CGContactextRefで簡単に実現できます。レーダー図はあなたの近くのユーザ(物体)との距離を表示します。実際の物体との経緯度で2点の距離を計算します。一定の比率でレーダー図に写ります。2点の距離計算式は以下の通りです。

//           
-(float) DistanceFromCoordinates:(CLLocationCoordinate2D) myDot other:(CLLocationCoordinate2D)otherDot 
{ 
  
 double EARTH_RADIUS = 6378137.0; 
  
 double radLat1 = (myDot.latitude * M_PI / 180.0); 
 double radLat2 = (otherDot.latitude * M_PI / 180.0); 
 double a = radLat1 - radLat2; 
 double b = (myDot.longitude - otherDot.longitude) * M_PI / 180.0; 
 double s = 22 * asin(sqrt(pow(sin(a / 2), 2) 
        + cos(radLat1) * cos(radLat2) 
        * pow(sin(b / 2), 2))); 
 s = s * EARTH_RADIUS; 
 s = round(s * 10000) / 10000; 
  
 return s; 
  
} 
物体のレーダー図上の表示位置を計算するには、三角関数によって、sinA=対辺/斜辺、cos A=隣/斜辺、斜辺があります。私達はすでに2点の間の距離があります。角度を知る必要があります。この辺と半径の加減で、この物体のレーダー図上の位置を計算できます。まず2時の方位角を計算して、下の図を見ます。

このウィキペディアの方位角の説明図は、tan 2関数で計算できます。公式は以下の通りです。

- (float)getHeadingForDirectionFromCoordinate:(CLLocationCoordinate2D)fromLoc toCoordinate:(CLLocationCoordinate2D)toLoc 
{ 
 float fLat = DegreesToRadians(fromLoc.latitude); 
 float fLng = DegreesToRadians(fromLoc.longitude); 
 float tLat = DegreesToRadians(toLoc.latitude); 
 float tLng = DegreesToRadians(toLoc.longitude); 
  
 float degree = RadiansToDegrees(atan2(sin(tLng-fLng)*cos(tLat), cos(fLat)*sin(tLat)-sin(fLat)*cos(tLat)*cos(tLng-fLng))); 
  
 if (degree >= 0) { 
  return degree; 
 } else { 
  return (360+degree); 
 } 
 
} 
3、レーダー図が携帯電話に従って回転することを実現するために、ここでは羅針盤の原理を使って、CLLocationManager管理類を通じて、中にCLHeading類があります。羅針盤を実現できます。このような構造を見てください。

中には真北、磁石北、そして磁力値がx、y、zの3軸の磁力値がありますが、この3つの値を使った時、問題がありました。携帯を前後に移動した時、この値の変化が止まっていることに気づきました。この値を使って移動がスムーズにならないため、ジャイロデータを使いました。携帯電話の動きの角度をCMMotionManagerという管理部門で取得し、携帯電話の前後に移動する際の物体の携帯画面の上下の位置を計算します。

-(void) startMotion 
{ 
  
 if (![_mgr isDeviceMotionActive] && [_mgr isDeviceMotionAvailable]) 
 { 
   
 //       
  _mgr.deviceMotionUpdateInterval = 0.1; 
 
 NSOperationQueue *queue = [[NSOperationQueue alloc] init]; 
 
  [_mgr startDeviceMotionUpdatesToQueue:queue 
   withHandler:^(CMDeviceMotion * _Nullable motion, 
      NSError * _Nullable error) { 
          
      double gravityX = motion.gravity.x; 
      double gravityY = motion.gravity.y; 
      double gravityZ = motion.gravity.z; 
          
          
   if (gravityY<=0 && gravityY>=-1) 
   { 
           
 //         (zTheta          , xyTheta           ): 
  zTheta = atan2(gravityZ,sqrtf(gravityX*gravityX+gravityY*gravityY))/M_PI*180.0; 
 
} 
  [[NSOperationQueue mainQueue] addOperationWithBlock:^{     
    [self updataPoint]; 
 
    }]; 
       
  //[self performSelectorOnMainThread:@selector(updataPoint) withObject:nil waitUntilDone:NO]; 
      
  }]; 
     
 } 
} 


4、角度区間を計算して携帯電話に表示される物体の表示はまだ隠れています。つまりレーダー図の点が扇形で見える領域に入ると物体が表示されて移動し、それを超えると隠れてしまいます。もう一つは、衝突検査の携帯電話の中の物体と物体が多すぎると畳めなくなります。位置をずらすことによって、CGRect Intersects Rectによって、二つの長方形が接触したかどうかを計算します。
簡単に言えば、私が実現した原理はもちろん実際にやる時に多くの問題が発生します。
以上が本文の全部です。皆さんの勉強に役に立つように、私たちを応援してください。