PHP のGDをビルド

PHP をビルドしたとき、–with-gd-sharedで拡張モジュールに追加したつもりでした、がphpinfo を確認するとGDがインストールされていないようでした。(apache error.log がImageCreateFromJpeg()でエラーを出すので。)改めてGDをビルドしました。

wget https://github.com/libgd/libgd/releases/download/gd-2.2.3/libgd-2.2.3.tar.gz
./configure --prefix=/usr/local
make && make install

してGDをビルド、PHPを–with-gd(=shared では上手く行かなかった)オプションでビルドしましたがlibwebp、gd-lastでコケます。yum でgdのパッケージが足りないのだろうと思い、remi リポジトリを導入

wget http://rpms.famillecollet.com/enterprise/remi-release-6.rpm
rpm -Uvh remi-release-6.rpm

して

yum --enablerepo=epel,remi install libwebp
yum install gd-last-2.2.3-1.el6.remi.x86_64
yum install gd-devel
yum --enablerepo=remi install php56-php-gd.x86_64

して再びビルドしたところ phpinfo でGDを確認できました。

回線工事、完了です・・・。

今日は朝からNTTの人が来てフレッツ光を上位スループットの光ネクストに工事をしました。光ファイバーケーブルを宅内配線して古いCTUの代わりにモデムを設置しました。

ファイアウォール設定、静的IPマスカレード、サーバーやひかりTVのポート開放などの設定をして1日が終わりました。3台が1台になってかなりスッキリですね。

リンク速度は無線ルーターから飛ばして15Mbps、

LANケーブルからモデム直結で33Mbpsでした。

pushとpop

配列に要素を追加したり、追加した要素を取り出す配列操作のメソッドにpush と popがあります。組み合わせると先入れ後出し(first in, last out)のスタックが実現します。

var stack = [];

stack.push('Lightning Bolt');
 // スタックの内容:['Lightning Bolt'] 1 を返す
stack.push('Brainstorm');
 // スタックのの内容:['Lightning Bolt', 'Brainstorm'] 2を返す
stack.pop();
 // スタックの内容 ['Lightning Bolt'] Brainstorm を返す
stack.push('Counterspell','Price of Progress');
 // スタックの内容['Lightning Bolt','Counterspell','Price of Progress'] 3を返す
stack.pop();
 // スタックの内容['Lightning Bolt','Counterspell'] Price of Progress を返す

stack.pop();
 // スタックの内容['Lightning Bolt']  Counterspellを返す

Counterspell されてもpop() しない限りstack の’Lightning Bolt’ は取り出せませんけど・・・ね。

JavaScriptでCSVファイルを読む

XMLHttpRequest を使って外部CSVファイルを2次元配列として読み込み、テーブルとして出力しています。

.open メソッドの第1引数は、HTTPメソッドを指定します。通常のリクエストにはGETが使われます。URLでリクエストするリソースをすべて表せて、リクエストによりサーバー側に副作用がなく、サーバーのレスポンスがキャッシュ可能であればGETリクエストを使うのが適切です。POSTはフォームデータの送信をするときに使います。
第2引数は、ファイルのURLを指定します。
第3引数は省略可能ですが true で非同期通信、false で同期通信をします。リクエストが完了して、成功した場合 .responseText メソッドを使ってテーブル出力関数に渡しています。

loadCSV.js

window.onload = function() {
  function getText(path) {
    var request = new XMLHttpRequest();  // 新しいリクエストを作成する
    request.open("GET", path, true);    // 取得するファイルパスを指定する
    request.onreadystatechange = function() { // イベントリスナーを定義
      // リクエストが完了し、成功した場合。
      if (request.readyState === 4 && request.status === 200) {
        var type = request.getResponseHeader("Content-Type");
        if (type.match(/^text/))
          parseCSV(request.responseText); // コールバック関数に渡す
      }
    };
    request.send(null);  // ここでリクエストを送信する
  }
  function parseCSV(str) {
    var CR = String.fromCharCode(13);
    var LF = String.fromCharCode(10);
    var csvData = new Array();
    var lines = str.split(LF);
    for (var i = 0; i < lines.length; i++) {
      var cells = lines[i].split(",");
     if( cells.length != 1 ) csvData.push(cells);
    }
    var result = "<table>";
    for (var i = 0; i < csvData.length; i++) {
      result += "<tr>";
      for (var j = 0; j < csvData[i].length; j++) {
        result += "<td>";
        result += csvData[i][j];
        result += "</td>";
      }
      result += "</tr>";
    }
    result += "</table>";
    document.getElementById("result").innerHTML = result;
  }
  getText('./example.csv');
}
<html>
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
 <script type="text/javascript" src="./loadCSV.js"></script>
 </head>
 <body>
 <div id="result"></div>
 </body>
 </html>

CSVファイルは文字化けしないように保存形式によって文字コードを指定しています。

参考URL:http://blog.cles.jp/item/2691

JavaScriptの座標変換の例

今回はJavaScriptの座標変換を使って正五角形をCanvasに描画してみました。

半径 r の円に内接する正五角形の円の中心から各辺に下した垂線の長さ [pmath]ay={{1+sqrt{5}}/{4}}r [/pmath] , 円の中心を原点として各辺の一辺の長さ[pmath]a=2ax={{sqrt{10-2sqrt{5}}}/{2}}r[/pmath] が既知としています。

https://stuffy.mydns.jp/~gusachan/javascript/pentagon.html

var c=document.getElementById("graph");
var ctx=c.getContext("2d");
var dgr =  Math.PI/180;
function pentagon() {
  var r = 160, ax, ay, bx, by;
  ax = -(Math.sqrt(10 - 2*Math.sqrt(5)))*r/4;
  ay = (1 + Math.sqrt(5))*r/4;
  bx = -ax;
  by = ay;
  ctx.beginPath();
  ctx.save();
  ctx.translate(200 + ax, 200 + ay);
  ctx.moveTo(0,0);
  leg();
  ctx.rotate(-72*dgr);
  leg();
  ctx.rotate(-72*dgr);
  leg();
  ctx.rotate(-72*dgr);
  leg();
  ctx.rotate(-72*dgr);
  leg();
  ctx.closePath();
  ctx.restore();
  function leg() {
    ctx.save();
    ctx.lineTo(2*bx,0);
    ctx.restore();
    ctx.translate(2*bx,0);
  }
}
pentagon();
ctx.stroke();
beginPath();
ctx.arc(200,200,160,0,360*dgr,false);
ctx.stroke();

円の中心を原点として五角形の左下隅の角の座標(ax, ay) =(-(Math.sqrt(10 – 2*Math.sqrt(5)))*r/4, -(1 + Math.sqrt(5))*r/4) をCanvasの座標の(左上隅を(0,0)とする)原点からtranslate(200 + ax, 200 + ay)) して始点とし、leg() 関数を呼び出して底辺を一回描画したのち、restore()で座標系変換を元に戻しtranslate(2*bx, 0)でレグの終点を(0,0) になるように移動してrotate(-72*dgr)で72°反時計回りに回転 、次の底辺の再描画~を4回繰り返してstroke()しています。

テキストではフラクタル雪片を再帰レベル4で描画していました。

振り子

回転関数の応用で振り子を作ってみました。振り子 の初期角度 rads(init)=π/6 に対して角運動量 rads(init)*Math.cos(rads(d)), (ただし角振動数、d = +5[°/100ms] )です。ここの所はアバウトにして正確な物理計算はしていません。

https://stuffy.mydns.jp/~gusachan/javascript/pendulum.html

var d = 0;
var c=document.getElementById("graph");
var ctx=c.getContext("2d");
var init = Number(document.getElementById('degree').value);
window.onload = function() {
  function rads(x) {
    return Math.PI*x/180;
  }
  function coordinate() {
    ctx.beginPath();
    ctx.moveTo(0,200);
    ctx.lineTo(400,200);
    ctx.moveTo(200,0);
    ctx.lineTo(200,400);
    ctx.closePath();
    ctx.stroke();
    ctx.beginPath();
    ctx.arc(200,200,150,0,rads(360),false);
    ctx.stroke();
  }
  function furiko() {
    var init = Number(document.getElementById('degree').value);
    d += 5;
    arg = rads(init)*Math.cos(rads(d))+rads(-90);
    ctx.clearRect(0,0,400,400);
    coordinate();
    ctx.beginPath();
    ctx.moveTo(200,200);
    ctx.lineTo(200 + 150*Math.cos(arg), 200 - 150*Math.sin(arg));
    ctx.closePath();
    ctx.stroke();
  }
  coordinate();
  setInterval(furiko, 100);
}

参考URL: http://www.daido-it.ac.jp/~harashin/pdf/note/10riki2_note9.pdf

pendulum_

 

アナログ時計

コードは以下。ポイントは、時刻を取得するvar now = new date(); をローカル関数のdgr() とdraw() の2か所で宣言、hand(d, r, w) 関数で針の角度と長さと太さの引数を渡して、短針と長針、秒針を描き分けています。それと前回の回転関数から x → 90-d と回転角を変換しています。setInterval(draw,1000) で1秒ごとに再描画しています。

https://stuffy.mydns.jp/~gusachan/javascript/clock.html

var c=document.getElementById("clock");
var ctx=c.getContext("2d");
window.onload = function() {
  var rads =  function(x) {
    return Math.PI*x/180;
  }
  var coordinate = function () {
    ctx.beginPath();
    ctx.lineWidth = 1;
    ctx.arc(200,200,150,0,rads(360),false);
    ctx.stroke();
  }
  var hand = function(d,r,w) {
    ctx.beginPath();
    ctx.moveTo(200,200);
    ctx.lineTo(200 + r*Math.cos(rads(90-d)), 200 - r*Math.sin(rads(90-d)));
    ctx.closePath();
    ctx.lineWidth = w;
    ctx.stroke();
  }
  var dgr = function(needle) {
      var now = new Date(); 
      if (needle == 'hours') {
        var arg = 30*((now.getHours()%12) + (now.getMinutes()/60));
      }
      else if (needle =='minutes') {
        var arg = 6*now.getMinutes();
      }
      else if (needle =='seconds') {
        var arg = 6*now.getSeconds();
      }
      return arg;
  }
  function draw() {
    var now = new Date();   // (追記:ここの宣言はなくても動いた
    ctx.clearRect(0,0,400,400);
    hand(dgr('hours'),110,4);
    hand(dgr('minutes'),140,2);
    hand(dgr('seconds'),130,1);
    coordinate();
  }
  setInterval(draw,1000);
}

clock

ひかりTVのチューナー交換

先週、ひかりTVのチューナーを交換しました。古いチューナー(PM-700)で録画したUSB-HDDを新しいチューナー(ST-3200)に接続すると、「引き継ぎ処理実行中です。処理完了までこのまましばらくお待ちください。」の画面のまま1時間たっても終わりません。電源を切ろうとしても切れないので、USBケーブルを引き抜いたところ、正常終了しました。恐る恐る、USBケーブルを挿したところ今度はUSB-HDDを認識したようでした。録画した番組を確認したところデータも読み取り可能なようで一安心です。(汗

値の変換

JavaScript では、Number()で数値以外の文字列を数値に変換しようとすると、関数はNaNを返します。NaNをtypeof演算子で判定しようとしても’number’と判定されて上手く行きません。テキストボックスから入力された値をgetElementByIdで受け取るときに、数値か文字列かを判定するには isFinite関数を使って

if (isFinite(arg)) {
  (処理)
}
else {
  alert('半角数値を入力してください!');
  return false;
}

と例外処理します。

変換先
文字列 数値 論理値 オブジェクト
undifined
null
“undifined”
“null”
NaN
0
false
false
TypeError 例外
TypeError 例外
true
false
“true”
“false”
1
0
new Boolean(true)
new Boolean(false)
“”(空文字列)
“1.2”(数値文字列)
“one”
(数値以外の文字列)
0
1.2
NaN
false
true
true
new String(“”)
new String(“1.2”)
new String(“one”)
0
-0
NaN
Infinity
-Infinity
1(有限値, 0以外)
“0”
“0”
“NaN”
“Infinity”
“-Infinity”
“1”
false
false
false
true
true
true
new Number(0)
new Number(-0)
new Number(NaN)
new Number(Infinity)
new Number(-Infinity)
new Number(1)

追記)JavaScript Good Parts 「良いパーツによるベストプラクティス」に興味深い記述がありましたので転載します。
JavaScript は、isNaN 関数を提供しており、これを使えば数値とNaN を区別することができる。

isNaN(NaN)  // true
isNaN(0)    // false
isNaN(‘oops’)  // true
isNaN(‘0’)   // false

isFinite 関数は値が利用可能な数値であるかを調べるもっともよい方法だ。なぜならこの関数は、NaN と Infinity をどちらも false と判断してくれるからである。しかし、残念なことに、isFinite は与えられたオペランドをまず数値に変換しようとしてしまう。したがって調べたい値が数値型ではなかった場合には、これは良いテスト方法とは言えない。もしかしたらあなたは、isNumber 関数を自分で定義したくなるかもしれない。

var isNumber = function isNumber(value) {
  return typeof value === 'number' && isFinite(value);
};

回転の実装

前回の続きです。回転を実装するにあたり、kaiten関数でcanvas をclearRect してテキストボックスに入力した数値を配列にメモ、var draw = function(x)を呼び出して再描画しています。

https://stuffy.mydns.jp/~gusachan/javascript/rotate.html

<body>
<th>rotate 関数</th><br>
<canvas id="graph" width="400" height="400"> </canvas><br>
<form>回転角度: <input type="text" id='degree'> <button type='button' onclick="kaiten();">回転</button></form>
<script type="text/javascript">
var i = 0, dgr = [0];
var c=document.getElementById("graph");
var ctx=c.getContext("2d"); 

function rads(x) {
  return Math.PI*x/180;
}
function coordinate() {
  ctx.beginPath();
  ctx.moveTo(0,200);
  ctx.lineTo(400,200);
  ctx.moveTo(200,0);
  ctx.lineTo(200,400);
  ctx.closePath();
  ctx.stroke();
  ctx.beginPath();
  ctx.arc(200,200,150,0,rads(360),false);
  ctx.stroke();
}
var draw = function(x) {
  ctx.beginPath();
  ctx.moveTo(200,200);
  ctx.lineTo(200 + 150*Math.cos(rads(x)), 200 - 150*Math.sin(rads(x)));
  ctx.closePath();
  ctx.stroke();
};
var sum = function(arr) {
  var sum = 0;
  arr.forEach(function(elm) {
    sum += elm;
  });
  return sum;
};
function kaiten() {
  var e = document.getElementById('degree');
  var arg = Number(e.value);
  i += 1;
  dgr[i] = arg;
  ctx.clearRect(0,0,400,400);
  coordinate();
  draw(sum(dgr));
}
coordinate();
</script>
</body>

追記)

var c=document.getElementById("graph");
var ctx=c.getContext("2d");

上記のコンストラクタ変数オブジェクト宣言は、coordinate, draw 関数のローカル内で宣言していましたが、グローバルオブジェクト(正確にはwindowオブジェクトのプロパティ)として宣言しても問題なかったようです。