小さなエンドウ豆

まだまだいろいろ勉強中

topojsonへの変換と鉄道データの描画

geojson から topojson への変換

geojsonからtopojsonへの変換はググったらたくさん出てきてどれもnodejsのパッケージのtopojsonを使ったものが多かった。今回もそれを使います。

$ npm i -g topojson

$ geo2topo -q 1e6 railroad=N02-15_RailroadSection.json > N02-15_RailroadSection.topojson

-q 1e6というオプションが変換時に大切なものらしく ほぼ常時つけた方がよいらしい

railroadとはtopojsonでのオブジェクト名になるらしい。

D3.jsによるtopojsonの描画

変換したtopojsonファイルを描画していきます。
使うライブラリはみんな大好きD3です。

<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
  <meta charset="utf-8" />
  <title></title>
  <style>
  </style>
</head>
<body>
  <h1>Rail Road Test</h1>
  <script src="//d3js.org/d3.v3.min.js" charset="utf-8"></script>
  <script src="//d3js.org/topojson.v0.min.js" charset="utf-8"></script>
  <script src="test.js"></script>
</body>

次にtest.jsについて

var width = 800;
var height = 800;

var svg = d3.select("body")
  .append("svg")
  .attr("width", width)
  .attr("height", height);

d3.json("rail_road.topojson", function(error, topo){

  var data = topojson.object(topo, topo.objects.railroad)
  var projection = d3.geo.mercator()
    .center(d3.geo.centroid(data))
    .scale(1200)
    .translate([width/2, height/2])

  var path = d3.geo.path().projection(projection);

  svg.selectAll("path")
    .data(data.geometries)
    .enter()
    .append("path")
    .attr("d", path);
});

dataの受け渡しの際にさっき設定したオブジェクト名"railroad"を指定して行っています。

上記のhtmlをブラウザで表示すると

f:id:h-piiice16:20170527225844p:plain

とまあわかりにくい

しかし描画できてるっぽいので今日はここまで!

次はこのsvg要素をオーバーレイとして、leaflet.jsなどを使い地図上に鉄道データをのせていきたいとおもいます。

国土数値情報の鉄道データ(shp)をgeojsonへ変換

手順

  1. データ のダウンロード
  2. QGISのインストー
  3. .shp -> .json の変換

それぞれ説明します。

データのダウンロード

データはこちらです。
このページの下の方からダウンロードしてきます。
データが年度で分かれているのですが、27年をダウンロードしました。

QGISのインストー

Macの場合、ここから
今回はおそらく最新のQGISのバージョン2.18.7-1 をダウンロードしました。
DLが済むとzipファイルを展開して、GDALとmatplotlib、QGISインストーラを起動します。

開発元が未確認のため開けません についての解決法

単にクリックしてインストールしようとしたところ「開発元が未確認のため開けません」というメッセージが出てインストールできませんでした。
解決策として、右クリックで「このアプリケーションで開く」を押すと開くの選択肢ができるので、このやり方でインストールを行いました。

インストールが終わると以下の1行をPATHに追加します。

/Library/Frameworks/GDAL.framework/Programs

.shp -> .json の変換

この変換は以下のコマンドで行えます。

ogr2ogr -f GeoJSON N02-15_RailroadSection.json N02-15_RailroadSection.shp

React-Dropzoneが便利

ドラックアンドドロップでファイルをアップロードしたい

最近?のWEBサービスではよくファイルをアップロードする際ドラックアンドドロップで行う場合が多い。
今回はそれを自分のサービスの中にも使いたいと思い実装してみました。

Reactにはそんな願いを叶える便利なコンポーネントとしてreact-dropzoneというものがある。
今回はこれを使って手っ取り早く実装することにしました。

React-Dropzone

実装したサービスの画面はこれです。 f:id:h-piiice16:20170423212401p:plain

ここにファイルをドラックアンドドロップで持っていくと、デベロッパーツールのコンソールにファイル名が表示されるサンプルを作りました。

実装のためにまずはreact-dropzoneをnpm経由でインストールします

npm install --save-dev react-dropzone

そして以下のようにコンポーネントを作成します。

import Dropzone from 'react-dropzone';
import React, {Component} from 'react';
import {render} from 'react-dom';

export default class UploadFile extends Component {

  handleOnDrop(files) {
    files.map(file => console.log(file.name))
  }

  render() {
    return( 
      <Dropzone
        onDrop={this.handleOnDrop}
        accept="image/gif,image/jpeg,image/png,image/jpg" >
          <div>
            Drag and Drop files Here!
            <p>format: gif/png/jpeg/jpg</p>
          </div>
      </Dropzone>
    );
  }
}

にはいろいろなアトリビュートが設定できるらしく、デフォで必要そうなonDrop(アップロード時の振る舞い)にコールバック関数としてhandleDrop()を、accept(受け入れるファイルの形式)に画像ファイルの形式を記述しました。

次回はアップロードされたファイルをサーバサイドにpostして保存するところまで行きたいと思います。

SQL小技集

SQL小技

最近SQLを書くことが多いので学んだことをまとめたいと思います。

2つのテーブルを更新したい

勝手な認識でupdate文は1つのテーブルに対し行うものだと思ってました。
しかし以下のように2つのテーブルに対して実行することができます。

update users u, players p
set u.id=1, p.user_id=1
where u.name="piiice" and p.name="piiice"

こんな感じです。

SQLを間違えてしまった…

間違いは誰にでもある。にんげんだもの

とはいえ、SQLの間違いはとってもやばいです。(語彙力)
こんな時に役に立つのがbegin, rollback, commitです。

begin, rollback, commitは制御構文といってcrud操作の中でもupdate, deleteで使うことが多いです。
これを用いるとsqlで加えた変更をなしにできることができます。 例はこちらです。

-- 1
begin;

-- 2
update user
set id=1, name="piiice";

-- 3
select *
from user;

-- rollback; -- 4
-- commit; -- 5

まず1を実行します。
次に2のupdateを実行します。この時点でDB自体の値は変わっていません。
3で2のupdateが正しいかどうか確認します。<- ここ小技!
もし間違いがあれば4を実行し、updateをなかったことにします。
間違がなければ5を実行し、値の更新を受け入れます。

これでSQLコワクナイ

servletのコンパイル2

modelパッケージの指定の仕方

servletコンパイルする際
modelがインポートできない問題に直面し なんとか解決出来たので忘れないように書いておく

構成はこんなかんじ

webapps/
└── example
    └── WEB-INF
        ├── classes
        │   ├── model
        │   └── servlet
        └── jsp

クラスパスを':'でつなげるところがコツらしい

javac -classpass /usr/share/tomcat7/lib/servlet-api.jar:./webapps/example/WEB-INF/classes webapps/example/WEB-INF/classes/servlet/Test.java

Servletのコンパイル

Servletコンパイル

Servletを使ってアプリケーションを開発してみた。
ソースはこんな感じです。

package servlet;                                                                                                                            

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/FowardServlet")
public class FowardServlet extends HttpServlet {
  private static final long serialVersionUID = 1L; 
  
  protected void doGet (HttpServletRequest request,
    HttpServletResponse response)
    throws ServletException, IOException {

      // forward
      RequestDispatcher dispatcher =
        request.getRequestDispatcher("/WEB-INF/jsp/forward.jsp");
      dispatcher.forward(request, response);
    }   
}

前に書いたJSPファイルをサーブレットから呼び出すアプリケーションである。

さーコンパイル

$ javac FowardServlet.java
FowardServlet.java:5: エラー: パッケージjavax.servletは存在しません
import javax.servlet.RequestDispatcher;
                    ^
FowardServlet.java:6: エラー: パッケージjavax.servletは存在しません
import javax.servlet.ServletException;
                    ^
FowardServlet.java:7: エラー: パッケージjavax.servlet.annotationは存在しません
import javax.servlet.annotation.WebServlet;
                               ^
FowardServlet.java:8: エラー: パッケージjavax.servlet.httpは存在しません
import javax.servlet.http.HttpServlet;
                         ^
FowardServlet.java:9: エラー: パッケージjavax.servlet.httpは存在しません
import javax.servlet.http.HttpServletRequest;
                         ^
FowardServlet.java:10: エラー: パッケージjavax.servlet.httpは存在しません
import javax.servlet.http.HttpServletResponse;
                         ^
FowardServlet.java:13: エラー: シンボルを見つけられません
public class FowardServlet extends HttpServlet {
                                   ^
  シンボル: クラス HttpServlet
FowardServlet.java:12: エラー: シンボルを見つけられません
@WebServlet("/FowardServlet")

...

あれ??

たくさんエラーたちが出てきました。

どうやらいろいろとインポートできていないらしい…

調べるとクラスパスでservlet-api.jarをささなければならなかった。

探すこと1時間ありました。 Tomcat7をインストールした時に一緒に落ちてきたみたい。

今度はクラスパスを指定して挑戦

$ javac -classpath /usr/share/tomcat7/lib/servlet-api.jar FowardServlet.java

うまくいきました!
環境変数にTomcat7の場所を設定する方法が一般的らしいですね。 この後すぐに行いました。

自分のツイートをダウンロードする

自分のツイートをダウンロード

今年も残すところあと3週間。2016年の自分は一体何をつぶやいているのか…

気になって自分のツイートを簡単に見る機能があればよいなーと探してみると、一括でダウンロードできるサービスがあるらしい。

今回はやり方を記していきます!

手順

手順は以下のとおりです。

  1. Twitterの設定から全ツイートダウンロードをクリック f:id:h-piiice16:20161213081100p:plain 僕は押しちゃったのでダウンロード待ちの状態になっていますが、本来は「全ツイート履歴をリクエストする」というボタンがありますのでそれをクリックします。
  2. Twitterのアカウントを登録する際に使ったメールアドレスにダウンロード用のURLが届くのでそれを待つ。
  3. ダウンロードを行う f:id:h-piiice16:20161213081541p:plain 届いたメールにあるダウンロードのボタンをクリックすると、こういったページにアクセスします。ここでダウンロードのボタンをクリックします。

  4. ダウンロードされたzipファイルを解凍し、tweets.csvというファイルを見つける このファイルがツイート履歴の記されたファイルとなります!

これで完了です

これと合わせて

h-piiice16.hatenablog.com

こんなのをやってみると面白いかもしれません。