• 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
 
 

2次関数 f(x) = pK ( x - pX ) ^ 2 + pY の定義域 [ pP, pQ ] で描かれる曲線を3次ベジエで近似しようとするとき、 2つのコントロールポイントの座標を以下のプログラムのように求めればよい。 x1, y1 と x2, y2

   1  double wPQ = pP * pQ;
   2  double wPP = pP * pP;
   3  double wQQ = pQ * pQ;
   4  double x1 = ( ( wPQ - 2 * wPP + wQQ ) / 3 ) / ( pQ - pP );
   5  double x2 = ( ( wPQ + wPP - 2 * wQQ ) / 3 ) / ( pP - pQ );
   6  double wA = pK * ( pQ + pP - 2 * pX );
   7  double wB = pY + pK * ( pX * pX - ( wPP + wPQ + wQQ ) / 3 );
   8  double y1 = x1 * wA + wB;
   9  double y2 = x2 * wA + wB;

考え方 線分 p->q を L とする。( wA は L の傾き) L に平行な直線で、f(x)に接する直線を M とする。 L からみて M 側にあり、L と M の距離の 4/3 倍の距離にある L に平行な直線を N とする。 ( y = wA * x + wB ) この N の上に2つのコントロールポイントをおく。 N と x = pP における接線との交点が1つめのコントロールポイント N と x = pQ における接線との交点が2つめのコントロールポイント である。

pP = 0, pQ = 1 のとき、

   1  double x1 = 1. / 3.;
   2  double x2 = 2. / 3.;
   3  double wN = pY + pK * ( pX * pX - 1. / 3. );
   4  double y1 = x1 * pK + wN;
   5  double y2 = x2 * pK + wN;

posted by Face Saturn on Thu 19 Sep 2013 at 17:55

   1  inline	CAAnimation*
   2  BounceAnimationElement( CGPoint pFrom, CGPoint pTo, double pBeginTime, double pDuration, CAMediaTimingFunction* pMTF )
   3  {	CABasicAnimation* v = [ CABasicAnimation animationWithKeyPath:@"position" ];
   4  	v.fromValue = [ NSValue valueWithCGPoint:pFrom ];
   5  	v.toValue = [ NSValue valueWithCGPoint:pTo ];
   6  	v.beginTime = pBeginTime;
   7  	v.duration  = pDuration;
   8  	v.timingFunction = pMTF;
   9  	return v;
  10  }
  11  
  12  inline	CAAnimation*
  13  BounceAnimation( CALayer* pL, CGPoint pDest, double pInitialDuration = 1, double pK = .3, size_t pRepeat = 10 )
  14  {	CAMediaTimingFunction* wMTF_D = [ CAMediaTimingFunction functionWithControlPoints:1./3. :0 :2./3. :1./3. ];
  15  	CAMediaTimingFunction* wMTF_U = [ CAMediaTimingFunction functionWithControlPoints:1./3. :2./3. :2./3. :1 ];
  16  
  17  	CGPoint wOrigin = pL.position;
  18  
  19  	NSMutableArray* wAnimationArray = NSMutableArray.array;
  20  	[ wAnimationArray addObject:BounceAnimationElement( pL.position, pDest, 0, pInitialDuration, wMTF_D ) ];
  21  
  22  	double	wBeginTime = pInitialDuration;
  23  
  24  	double	wK = 1;
  25  	while ( pRepeat-- )
  26  	{	wK *= pK;
  27  		CGPoint wPoint = CGPointMake
  28  		(	wOrigin.x * wK + pDest.x * ( 1 - wK )
  29  		,	wOrigin.y * wK + pDest.y * ( 1 - wK )
  30  		);
  31  		double wDuration = pInitialDuration * wK * ( 1 / sqrt( wK ) );
  32  		[ wAnimationArray addObject:BounceAnimationElement( pDest, wPoint, wBeginTime, wDuration, wMTF_U ) ];
  33  		wBeginTime += wDuration;
  34  		[ wAnimationArray addObject:BounceAnimationElement( wPoint, pDest, wBeginTime, wDuration, wMTF_D ) ];
  35  		wBeginTime += wDuration;
  36  	}
  37  
  38  	pL.position = pDest;
  39  
  40  	CAAnimationGroup* v = CAAnimationGroup.animation;
  41  	v.duration = wBeginTime;
  42  	v.animations = wAnimationArray;
  43  
  44  	return v;
  45  }
  46  
  47  -	(IBAction)
  48  Group
  49  {	[ mL addAnimation:BounceAnimation( mL, CGPointMake( 160, 240 ) ) forKey:nil ];
  50  }
  51  

posted by Face Saturn on Thu 19 Sep 2013 at 11:18

CATimingFunction は 0 ~ 1 の範囲の x を3次ベジエで表現する必要があるので、

落下のアニメーションをするためには、放物線 y = x^2 (以下 PB )を3次ベジエで近似する必要がある。

y = x で表される直線に平行な直線上に2つのコントロールポイント(以下 CP )を持つ3次ベジエで近似することにした場合、その座標の求め方は以下のとおり。

3次ベジエの以下の特性を利用する

t = 0 における接線は始点と1つめの CP がなす直線。
t = 1 における接線は終点と2つめの CP がなす直線。

このことから

PB の x = 0 における接線の方程式は y = 0 である。すなわち1つめの CP は X 軸上にある。
PB の x = 1 における接線の方程式は y = 2 x - 1 である。2つめの CP はこの式の上にある。

y = x に平行で PB に接する直線 y = x + n の n は x + n = x^2 の解が1つの時なので

y = x - 1/4

2つの CP がなす直線( L1 )が始点と終点がなす直線( L0 )と平行なとき、t = 1/2 のときに頂点が L1 - L0 の 3/4 の距離にあるという3次ベジエの性質から2つの CP がなす直線は

y = x - 1/3

これと y = 0 から1つめの CP は

( 1/3, 0 )

これと y = 2x - 1 から2つめの CP は

( 2/3, 1/3 )

なので、以下のように生成する。

[ CAMediaTimingFunction functionWithControlPoints:1./3. :0 :2./3. :1./3. ];

posted by Face Saturn on Thu 19 Sep 2013 at 11:18

さくらクラウドを使い始めて1週間程度、気づいたことをメモしておきます。

良い所

  • 安い(EC2に比べると半額以下のイメージ)
  • トラフィックに課金されない
  • GUIが使いやすい

悪いところ

  • 2〜3日経つと突然SSDにアクセスできなくなり、再起動を余儀なくされた(この一週間の間に2度)
  • diskの追加にrebootが必要

障害レポートを見ると、SSD関連の緊急メンテナンスがちょこちょこ入っているので、まだ熟れていない感じなのかも。 SSDが悪いなら標準ディスクに切り替えて検証してみようと思ったのですが、 再起動しないとdiskをアタッチできずに残念な感じ。 別サーバを立ててそっちに乗り換えるにしても、累積課金じゃなくて別課金になるので割高になる。

ともあれ、ec2の1強時代にあって、適正な競争が行われるためにもうちょっと応援していきたい。

posted by Png genki on Mon 16 Sep 2013 at 09:48

top コマンドでいうところの %sy、つまりカーネルプロセスによる CPU使用率が高まってきた場合、以下の様な方法で原因を調査することができます。

   1  # strace -c -p <PID>

CPU使用率が高くなっているプロセスのPIDを指定します。 これにより、指定のプロセスから呼び出される system call の回数や消費CPU時間の集計が始まります。 10〜30秒程度たったら、Ctrl+Cで集計を終了します。 そうすると、以下の様な集計結果が得られます。

   1  % time     seconds  usecs/call     calls    errors syscall
   2  ------ ----------- ----------- --------- --------- ----------------
   3  100.00    1.470463       63933        23           munmap
   4    0.00    0.000000           0        12           read
   5    0.00    0.000000           0        24           write
   6    0.00    0.000000           0        23           mmap
   7    0.00    0.000000           0        24           rt_sigprocmask
   8    0.00    0.000000           0         6           writev
   9    0.00    0.000000           0        36           gettimeofday
  10    0.00    0.000000           0         6           getppid
  11    0.00    0.000000           0        18           clock_gettime
  12    0.00    0.000000           0        12           epoll_wait
  13    0.00    0.000000           0        12           epoll_ctl
  14    0.00    0.000000           0        12           ppoll
  15  ------ ----------- ----------- --------- --------- ----------------
  16  100.00    1.470463                   208           total

munmap 遅いですね。

それから、munmap の内部のどこが遅いのか、更に細かい粒度で原因をしらべるには、ftrace が使えます。

ftrace が利用可能かどうかは以下のようにして調べられます。

   1  cat /proc/sys/kernel/ftrace_enabled
   2  1

ftraceはソースコードで配布されているので、以下から git clone してきます。

   1  cd /usr/local/src
   2  git clone git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/trace-cmd.git
   3  cd trace-cmd
   4  make
   5  make install

例えば、以下のようにls コマンドを実行してkernel関数がどのように呼ばれているかを調べられます。

   1  # trace-cmd record -p function_graph ls

実行が終了するとカレントディレクトリに trace.dat が作成されます。 これを

   1  trace-cmd report | less

のようにして確認します。

posted by Png genki on Sun 25 Aug 2013 at 00:38

Are there the servers at home, or the on-premise servers at office? If no, the mosh is your best friend and this article is just a waste of time.

But if yes, the Rosh might help your life. Rosh is the roaming shell like the mosh. But it can track the server even if its IP address change. It reconnects to the server by resolving the hostname each time.

You can use the local DNS such as the dnsmasq for your on-premise servers so that you can resolve the server by same name no matter where you are.

The usage of Rosh is simple, like this

   1  gem install rosh
   2  rosh yourserver.com session-name

It installs the nested GNU screen session remotely at the given server. You can omit the session-name, "default" is used as the name. Then, Rosh connects to the session via the SSH.

If you want to detach the session, type Ctrl+t d. On the second time you connect, Rosh reuses the remote session.

Requirements

  • SSH
  • Ruby at your machine (2.0.0 or later. Sorry, I don't have 1.9.x or older)
  • GNU screen at remote servers
posted by Png genki on Thu 22 Aug 2013 at 17:49

普通にscreenを使っていると、detachしてからattach した場合に、 split状態を忘却してしまうのがやや煩わしいです。

以下のようにして2重にscreenを起動し、

   1  screen -c /dev/null -e "^t^t" -S name
   2  STY=
   3  screen

外側のscreen を ^td で detach してから screen -r name で attachすると、split状態を擬似的に保持できます。

^tname はおこのみで。

posted by Png genki on Wed 21 Aug 2013 at 02:15

   1  -	(void)
   2  viewWillAppear:(BOOL)p
   3  {	[	NSNotificationCenter.defaultCenter
   4  		addObserverForName:UIKeyboardWillShowNotification
   5  		object:self.view.window
   6  		queue:nil
   7  		usingBlock:^( NSNotification* p )
   8  		{	[	UIView
   9  				animateWithDuration:[ [ p.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey ] doubleValue ]
  10  				animations:
  11  				^{	self.view.frame = CGRectMake
  12  					(	self.view.frame.origin.x
  13  					,	self.view.frame.origin.y
  14  					,	self.view.frame.size.width
  15  					,	self.view.frame.size.height - [ [ p.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey ] CGRectValue ].size.height
  16  					);
  17  
  18  				}
  19  			];
  20  		}
  21  	];
  22  	[	NSNotificationCenter.defaultCenter
  23  		addObserverForName:UIKeyboardWillHideNotification
  24  		object:self.view.window
  25  		queue:nil
  26  		usingBlock:^( NSNotification* p )
  27  		{	[	UIView
  28  				animateWithDuration:[ [ p.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey ] doubleValue ]
  29  				animations:
  30  				^{	self.view.frame = CGRectMake
  31  					(	self.view.frame.origin.x
  32  					,	self.view.frame.origin.y
  33  					,	self.view.frame.size.width
  34  					,	self.view.frame.size.height + [ [ p.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey ] CGRectValue ].size.height
  35  					);
  36  
  37  				}
  38  			];
  39  		}
  40  	];
  41   }
  42  
  43  -	(void)
  44  viewDidDisappear:(BOOL)p
  45  {	[ NSNotificationCenter.defaultCenter removeObserver:self ];
  46  }
  47  
  48  

posted by Face Saturn on Tue 20 Aug 2013 at 13:58

Ruby には empty?nil? など、接尾辞"?"がつくメソッドを使えるので直感的にわかりやすい場合が多いのですが、三項演算子 ?: の条件に使う時だけは

   1  foo.empty? ? bar : baz

のように ? ? が連続してなんだか気に入りません。 なので、こういう場合には三項演算子の代わりに

   1  foo.empty? and bar or baz

と書くことが多いかも。これだとスッキリします

posted by Png genki on Sun 11 Aug 2013 at 17:01

git でリモートに push したコミットが間違いだったと気づいた場合、

   1  git reset --hard <戻したいコミット>

で一旦手元の環境を正しい状態に戻し、あとは

   1  git push -f origin HEAD:master

でリモートに反映さればok

posted by Png genki on Fri 9 Aug 2013 at 21:38