http://www.finds.jp/docs/pgisman/1.5.1/
postgisのリファレンスを読んで、perlやjava、c等言語を問わず、幾何学計算を実現できそうな気がしたので試してみました。
(postgisのinstallは別のエントリをご覧下さい)
回転や拡大縮小、移動は、html5 canvasでも容易に実現できますが、postgisを使えば、図形のマージ(和・合成)や差分、積 も次のようなsrcで実現できます。
#!/usr/local/bin/perl use strict; use DBI; use Math::Trig qw/pi deg2rad rad2deg/; use Data::Dumper; main(); sub main { my $dbh = connect_db(); #元の図形 my $polygon_txt = 'POLYGON((-0.2 -0.2, 0.2 -0.2, 0.2 0.2, -0.2 0.2, -0.2 -0.2))'; #text -> geometry my $geom = test_ST_GeomFromText($dbh,$polygon_txt); my $geom_ret; #回転(rad指定) $geom_ret = test_ST_RotateZ($dbh,$geom, deg2rad(45) ); #拡大縮小 $geom_ret = test_ST_Scale($dbh,$geom, 0.5,0.5); print "ST_Scale : ",test_ST_AsText($dbh,$geom_ret),"\n"; #移動 $geom_ret = test_ST_Translate($dbh,$geom, 0.2,0.2); print "ST_Translate : ",test_ST_AsText($dbh,$geom_ret),"\n"; #重心算出 $geom_ret = test_ST_Centroid($dbh,$geom); print "ST_Centroid : ",test_ST_AsText($dbh,$geom_ret),"\n"; #距離算出 my $polygon_txt_2 = 'POLYGON((0.3 0.0, 0.4 0.0, 0.4 0.1, 0.3 0.1, 0.3 0.0))'; my $geom_2 = test_ST_GeomFromText($dbh,$polygon_txt_2); my $ret = test_ST_Distance($dbh,$geom,$geom_2); print "ST_Distance : $ret\n"; #合成(和) $polygon_txt_2 = 'POLYGON((0.0 -0.2, 0.3 -0.2, 0.3 0.2, 0.0 0.2, 0.0 -0.2))'; $geom_2 = test_ST_GeomFromText($dbh,$polygon_txt_2); $geom_ret = test_ST_Union($dbh,$geom,$geom_2); print "ST_Union : ",test_ST_AsText($dbh,$geom_ret),"\n"; #差分 $geom_ret = test_ST_Difference($dbh,$geom,$geom_2); print "ST_Difference : ",test_ST_AsText($dbh,$geom_ret),"\n"; #積 $geom_ret = test_ST_Intersection($dbh,$geom,$geom_2); print "ST_Intersection : ",test_ST_AsText($dbh,$geom_ret),"\n"; $dbh->disconnect(); } sub test_ST_Union { my ($dbh,$geom_1,$geom_2) = @_; my $sth = $dbh->prepare("select ST_Union(?,?)"); $sth->execute($geom_1,$geom_2); return $sth->fetchrow_array(); } sub test_ST_Intersection { my ($dbh,$geom_1,$geom_2) = @_; my $sth = $dbh->prepare("select ST_Intersection(?,?)"); $sth->execute($geom_1,$geom_2); return $sth->fetchrow_array(); } sub test_ST_Difference { my ($dbh,$geom_1,$geom_2) = @_; my $sth = $dbh->prepare("select ST_Difference(?,?)"); $sth->execute($geom_1,$geom_2); return $sth->fetchrow_array(); } sub test_ST_Distance { my ($dbh,$geom_1,$geom_2) = @_; my $sth = $dbh->prepare("select ST_Distance(?,?)"); $sth->execute($geom_1,$geom_2); return $sth->fetchrow_array(); } sub test_ST_Translate { my ($dbh,$geom,$dx,$dy) = @_; my $sth = $dbh->prepare("select ST_Translate(?,?,?)"); $sth->execute($geom,$dx,$dy); return $sth->fetchrow_array(); } sub test_ST_Centroid { my ($dbh,$geom) = @_; my $sth = $dbh->prepare("select ST_Centroid(?)"); $sth->execute($geom); return $sth->fetchrow_array(); } sub test_ST_Scale { my ($dbh,$geom,$scale_x,$scale_y) = @_; my $sth = $dbh->prepare("select ST_Scale(?,?,?)"); $sth->execute($geom,$scale_x,$scale_y); return $sth->fetchrow_array(); } sub test_ST_RotateZ { my ($dbh,$geom,$rad) = @_; my $sth = $dbh->prepare("select ST_RotateZ(?,?)"); $sth->execute($geom,$rad); return $sth->fetchrow_array(); } sub test_ST_GeomFromText { my ($dbh,$txt) = @_; my $sth = $dbh->prepare("SELECT ST_GeomFromText(?)"); $sth->execute($txt); return $sth->fetchrow_array(); } sub test_ST_AsText { my ($dbh,$geom) = @_; my $sth = $dbh->prepare("SELECT ST_AsText(?)"); $sth->execute($geom); return $sth->fetchrow_array(); } sub connect_db { my $dbh = DBI->connect('DBI:Pg:dbname=postgis;host=localhost', 'postgres', ''); return $dbh; } 1;
実行結果
$ ./gis.pl ST_Scale : POLYGON((-0.1 -0.1,0.1 -0.1,0.1 0.1,-0.1 0.1,-0.1 -0.1)) ST_Translate : POLYGON((0 0,0.4 0,0.4 0.4,0 0.4,0 0)) ST_Centroid : POINT(-0 -0) ST_Distance : 0.1 ST_Union : POLYGON((0 -0.2,-0.2 -0.2,-0.2 0.2,0 0.2,0.2 0.2,0.3 0.2,0.3 -0.2,0.2 -0.2,0 -0.2)) ST_Difference : POLYGON((0 -0.2,-0.2 -0.2,-0.2 0.2,0 0.2,0 -0.2)) ST_Intersection : POLYGON((0.2 -0.2,0 -0.2,0 0.2,0.2 0.2,0.2 -0.2))
精度(丸め誤差)や、座標→メートル変換等の課題はありますが、使える気がします。