...

視空間・認知空間への拡張

by user

on
Category: Documents
2

views

Report

Comments

Transcript

視空間・認知空間への拡張
視空間・認知空間への拡張
視空間・認知空間への拡張
-双曲幾何ツールの試作に向けて-
双曲幾何ツ ルの試作に向けて
2011年 12月 20日
筑波大学システム情報系
渡辺 俊
地理情報科学と都市工学を融合した空間解析手法の新展開
Page 1
視空間・認知空間への拡張
活動 概要
活動の概要
• 仮想空間・実空間の一体化
– AR技術を利用した実空間GISの開発
– 3次元都市モデルの整備・SketchUpの活用
• e-Learningコンテンツの更新
– ArcGIS10・Pythonへの対応
– アルゴリズム教材の開発
• 視空間・認知空間への拡張
視空間 認知空間への拡張
– 双曲幾何ツールの試作に向けて
地理情報科学と都市工学を融合した空間解析手法の新展開
Page 2
視空間・認知空間への拡張
はじめに
(距離空間)
• 図面(建築空間)
– ユークリッド距離
• 地図(都市空間)
– 球面距離(大円距離)・......
• 時間軸変形地図(1969:杉浦康平)
– 時間距離
• 空間的相互作用モデル(アクティビティのマクロな視点)
– 距離減衰関数(冪乗関数・指数関数)
• 視空間・認知空間のモデル(アクティビティのミクロな視点)
– 双曲的距離(?)
地理情報科学と都市工学を融合した空間解析手法の新展開
Page 3
重力モデル
地理情報科学と都市工学を融合した空間解析手法の新展開
視空間・認知空間への拡張
Page 4
ArcGISによる正距方位図
地理情報科学と都市工学を融合した空間解析手法の新展開
視空間・認知空間への拡張
Page 5
ポアンカレ円板の双曲タイル張り
地理情報科学と都市工学を融合した空間解析手法の新展開
視空間・認知空間への拡張
Page 6
視空間・認知空間への拡張
幾何学と プリケ
幾何学とアプリケーション
• ユークリッド幾何学
– 初等幾何学(CAD)
• 非ユークリッド幾何学
非
クリ ド幾何学
– 楕円幾何学(GIS?)
幾
(
)
• 球面幾何学
– 双曲幾何学
– 射影幾何学(CG)
地理情報科学と都市工学を融合した空間解析手法の新展開
Page 7
コンパスと定規による描画方法(Chaim Goodman-Strauss)
地理情報科学と都市工学を融合した空間解析手法の新展開
視空間・認知空間への拡張
Page 8
視空間・認知空間への拡張
双曲タイル貼り
(双曲幾何学への招待:複素数で視る)
地理情報科学と都市工学を融合した空間解析手法の新展開
Page 9
アルゴリズムによる描画方法
地理情報科学と都市工学を融合した空間解析手法の新展開
視空間・認知空間への拡張
Page 10
双曲タイル貼りのプログラム
from math import *
from Tkinter import *
class Point:
def __init__(self, x1, y1):
self.x = float(x1)
self.y = float(y1)
def __repr__(self):
return "Point(%f, %f)¥n" % (self.x, self.y)
def __eq__(self, pt):
return (self.x == pt.x and self.y == pt.y)
def __add__(self, pt):
return Point(self.x + pt.x, self.y + pt.y)
def __sub__(self,
sub (self, pt):
return Point(self.x - pt.x, self.y - pt.y)
def __mul__(self, n):
return Point(self.x * n, self.y * n)
def __div__(self, n):
return Point(self.x / n, self.y / n)
def sq_sum(self):
return self.x**2 + self.y**2
def pro_sum(self, pt):
return self.x * pt.x + self.y * pt.y
def ex_pro(self, pt):
return self.x * pt.y - self.y * pt.x
def normal(self):
d = sqrt(self.sq_sum())
return Point(self.x / d, self.y / d)
def rotate(self, t):
u = self.x * cos(t) - self.y * sin(t)
v = self.x * sin(t) + self.y * cos(t)
return Point(u,v)
class Line:
def __init__(self, start, end):
self.p1 = start
self.p2
lf 2 = end
d
def __repr__(self):
return "Line((%f, %f), (%f, %f))¥n"¥
% (self.p1.x, self.p1.y, self.p2.x, self.p2.y)
class Circle:
def __init__(self, center, radius):
self.c = center
self.r = float(radius)
def __repr__(self):
return "Circle((%f, %f),%f)¥n" % (self.c.x, self.c.y, self.r)
def clip(self,
clip(self circle):
d = sqrt((self.c - circle.c).sq_sum())
phi = acos((d**2 + self.r**2 - circle.r**2)/(2*d*self.r))
theta = atan2(circle.c.y - self.c.y, circle.c.x - self.c.x)
return [(theta - phi)*180/pi, (phi*180/pi) * 2]
class Arc(Circle):
def __init__(self, center, radius, p1, p2):
Circle.__init__(self, center, radius)
self.p1 = p1
self.p2 = p2
def __repr__(self):
repr (self):
ag = self.angle()
return "Arc((%f, %f),%f, %f, %f)¥n"¥
% (self.c.x, self.c.y, self.r, ag[0], ag[1])
def angle(self):
theta1 = atan2(self.p1.y - self.c.y, self.p1.x - self.c.x)
theta2 = atan2(self.p2.y - self.c.y, self.p2.x - self.c.x)
phi = abs(theta2 - theta1)
if phi <= pi:
return [min(theta1, theta2)*180/pi, phi*180/pi]
else:
return [max(theta1, theta2)*180/pi, (2*pi - phi)*180/pi]
def circleInversion(axis, target):
# point on circle
if isinstance(axis,
isinstance(axis Circle) and isinstance(target,
isinstance(target Point):
v = target - axis.c
return axis.c + v/v.sq_sum()*axis.r**2
# point on line
if isinstance(axis, Line) and isinstance(target, Point):
unitv = (axis.p2 - axis.p1).normal()
par = unitv*((target - axis.p1).pro_sum(unitv))
perp = (target - axis.p1) - par
return axis.p1 + par - perp
# line on circle
if isinstance(axis, Circle) and isinstance(target, Line):
s = (target.p2
(target p2 - target.p1).ex_pro(target.p2
target p1) ex pro(target p2 - axis.c)
axis c)
if abs(s) > (10**-8):
v = target.p1 - target.p2
cx = (2*s*axis.c.x + v.y*axis.r**2)/(2*s)
cy = (2*s*axis.c.y - v.x*axis.r**2)/(2*s)
r = axis.r**2*sqrt((v.sq_sum())/s**2)/2
p1 = circleInversion(axis, target.p1)
p2 = circleInversion(axis, target.p2)
return Arc(Point(cx,cy), r, p2, p1)
else:
p1 = circleInversion(axis, target.p1)
p2 = circleInversion(axis, target.p2)
return Line(p2, p1)
# circle on circle
if isinstance(axis, Circle) and isinstance(target, Arc):
if axis.c == target.c and axis.r == target.r:
return Circle(axis.c, axis.r)
elif abs((axis.c - target.c).sq_sum() - target.r**2) > (10**-8):
dis = sqrt((target.c - axis.c).sq_sum())
ri = (target.c - axis.c)/dis
c1 = axis.r**2/(dis + target.r)
c2 = axis.r**2/(dis - target.r)
p1 = circleInversion(axis, target.p1)
p2
2 = circleInversion(axis,
l I
(
target.p2)
2)
return Arc((axis.c + ri*(c1 + c2)/2),abs(c1 - c2)/2, p2, p1)
else:
p1 = circleInversion(axis, target.p1)
p2 = circleInversion(axis, target.p2)
return Line(p2, p1)
# circle on line
if isinstance(axis, Line) and isinstance(target, Arc):
unitv = (axis.p2 - axis.p1).normal()
par = unitv*(target.c - axis.p1).pro_sum(unitv)
perp = (target.c - axis.p1) - par
a1 = circleInversion(axis,
circleInversion(axis target.p1)
target p1)
a2 = circleInversion(axis, target.p2)
return Arc(axis.p1 + par - perp, target.r, a2, a1)
#line on line
if isinstance(axis, Line) and isinstance(target, Line):
if axis.p1 == target.p1 and axis.p2 == target.p2:
return Line(target.p1, target.p2)
else:
unitv = (axis.p2 - axis.p1).normal()
par = unitv*(target.p1 - axis.p1).pro_sum(unitv)
perp = (target.p1 - axis.p1) - par
pars = unitv*(target.p2
unitv*(target p2 - target.p1).pro_sum(unitv)
target p1) pro sum(unitv)
perps = (target.p2 - target.p1) - pars
p1 = axis.p1 + par - perp
return Line(p1, p1 + pars - perps)
視空間・認知空間への拡張
def hyperbolicTriangle(p, q, r):
if (1.0/p + 1.0/q + 1.0/r) < 1:
a = pi / p
b = pi / q
c = pi / r
rB = tanh(1.0/2*acosh((cos(a)*cos(b)+cos(c))/(sin(a)*sin(b))))
rC = tanh(1.0/2*acosh((cos(a)*cos(c)+cos(b))/(sin(a)*sin(c))))
p2 = Point(sin(a), cos(a))*rC/rB
mp = Point(((rB*(1.0 + rC**2)/sin(a)-rC*(1.0 + rB**2)/tan(a))/rC),
(1+rB**2))/(2*rB)
ro = sqrt((mp - Point(0,rB)).sq_sum())/rB
mp = mp/rB
p0 = Point(0, 0)
p1 = Point(0, 1)
return [[p0,p2,p1],[Line(p0,p2),Arc(mp,ro,p1,p2),Line(p0,p1)],[p,q,r]]
def hyperbolicTransform(triangle):
neighbors = []
for i in [[0,2,1],[1,0,2],[2,1,0]]:
p0 = triangle[0][i[0]]
p1 = circleInversion(triangle[1][i[0]],triangle[0][i[1]])
p2 = triangle[0][i[2]]
e0 = circleInversion(triangle[1][i[0]],triangle[1][i[1]])
e1 = circleInversion(triangle[1][i[0]],triangle[1][i[2]])
e2 = triangle[1][i[0]]
neighbors.append([[p0,p1,p2],[e0,e1,e2]])
return neighbors
def recursion(n):
if n == 0:
global mplist
global layers
points = startTriangle[0]
mplist = [(points[0] + points[1] + points[2])/3]
layers = [[startTriangle]]
return layers
else:
l
angle = tan(pi/2 - 2*pi/startTriangle[2][0])
inverse = []
for piece in recursion(n - 1)[-1]:
inverse = inverse + hyperbolicTransform(piece)
select = []
for piece in inverse:
points = piece[0]
mp = (points[0] + points[1] + points[2])/3
if mp.y / mp.x < angle:
continue
if include(mp):
continue
mplist.append(mp)
select.append(piece)
layers.append(select)
return layers
def include(np):
for p in mplist:
if (np - p).sq_sum() < (10**-8):
return True
return False
地理情報科学と都市工学を融合した空間解析手法の新展開
def show(tesserae, size):
c = Canvas(width=size, height=size)
c.pack()
sc = startTriangle[1][1].c
sr = startTriangle[1][1].r
lr = sqrt(sc.sq_sum()-sr**2)
q
q_
scale = (size/2 - 50) / lr
unitc = Circle(Point(0,0),lr*scale)
x1 = -lr*scale + size/2
y1 = size/2 + lr*scale
x2 = lr*scale + size/2
y2 = size/2 - lr*scale
c.create_oval(x1, y1, x2, y2)
for i in range(startTriangle[2][0]):
for layer in tesserae:
for j in range(len(layer)):
( (
))
for shape in layer[j][1]:
if isinstance(shape, Arc):
nc = shape.c.rotate(i*2*pi / startTriangle[2][0])
ag = (Circle(nc*scale, shape.r*scale)).clip(unitc)
x1 = (nc.x - shape.r)*scale + size/2
y1 = size/2 - (nc.y - shape.r)*scale
x2 = (nc.x + shape.r)*scale + size/2
y2 = size/2 - (nc.y + shape.r)*scale
c.create_arc(x1, y1, x2, y2,¥
start=ag[0], extent=ag[1], style='arc')
n2 = Point(0,
Point(0 lr).rotate((i*2-1)*pi/startTriangle[2][0])
lr) rotate((i*2 1)*pi/startTriangle[2][0])
x2 = n2.x*scale + size/2
y2 = size/2 - n2.y*scale
c.create_line(size/2, size/2, x2, y2, width=1)
n2 = Point(0, lr).rotate(i*2*pi/startTriangle[2][0])
x2 = n2.x*scale + size/2
y2 = size/2 - n2.y*scale
c.create_line(size/2, size/2, x2, y2)
mainloop()
def hypergolicTessellation(p, q, r, n):
global startTriangle
startTriangle = hyperbolicTriangle(p, q, r)
show(recursion(n), 700)
Page 11
ArcGIS上での実装
地理情報科学と都市工学を融合した空間解析手法の新展開
視空間・認知空間への拡張
Page 12
バリエーション
地理情報科学と都市工学を融合した空間解析手法の新展開
視空間・認知空間への拡張
Page 13
情報化と都市の将来
参考文献
• 双曲幾何学への招待
―複素数で視る
谷口雅彦・奥村善英 著 培風館 (1996/10)
• 双曲幾何
(現代数学への入門)
深谷賢治 著 岩波書店 (2004/9/7)
• Compass
C
and
d straightedge
t i ht d
iin th
the P
Poincare
i
di
disk
k
Chaim Goodman-Strauss, Amer. Math. Monthly 108
(2001), 38–49
38 49.
• M. C. Escher’s Legacy
A Centennial Celebration
D. Schattschneider and M. Emmer(eds.), Springer(2003)
• The Mathematica GuideBook for Graphics
Michael Trott, Springer (2004)
地理情報科学と都市工学を融合した空間解析手法の新展開
Page 14
Fly UP