#!BPY
import bpy
import math
from xml.etree.ElementTree import ElementTree
import glob
#
# 穴の開いた浮き出し地図を作る(xml)
# main003.py
# 2016/11/17 Shizuka-Toikanbetsu
#
XmlName = "N03-??_13_*.xml" # 収録されているxmlファイルを指定
AreaCode = "13223" # 地方公共団体コードを文字列型で指定
ObjScale = 0.001 # 原寸では大きいので1000分の1
#
# 世界座標の基準緯度と世界座標の目標座標の距離をメートル単位で返す
def GetLatOffset(pBaseLat, pLat):
return ( pLat - pBaseLat ) * 40007000.0 / 360.0
#
# 世界座標の基準経度と世界座標の目標座標の距離をメートル単位で返す
def GetLonOffset(pBaseLon, pLat, pLon):
return ( pLon - pBaseLon ) * 40075000.0 * math.cos( math.radians( pLat ) ) / 360.0
#
# namespace
ns = { "ksj": "http://nlftp.mlit.go.jp/ksj/schemas/ksj-app",
"gml": "http://www.opengis.net/gml/3.2",
"xlink": "http://www.w3.org/1999/xlink" }
#
def CreateRecName(pAreaCode, pAdministrativeBoundary): # オブジェクト名を作る
RecName = pAreaCode
tempstr = pAdministrativeBoundary.find( "ksj:prefectureName", ns ).text
if tempstr:
RecName = RecName + "_" + tempstr
tempstr = pAdministrativeBoundary.find( "ksj:countyName", ns ).text
if tempstr:
RecName = RecName + "_" + tempstr
tempstr = AdministrativeBoundary.find( "ksj:cityName", ns ).text
if tempstr:
RecName = RecName + "_" + tempstr
return RecName
#
def MergeRecName():
Buff = []
for item in bpy.data.objects:
if item.type == "MESH":
temp = item.name
Buff.append( temp[ 0 : 5 ] )
Buff.sort()
AreaCode = []
OldCode = ""
for temp in Buff:
if temp != OldCode:
AreaCode.append( temp )
OldCode = temp
#
for Code in AreaCode:
bpy.ops.object.select_all(action='DESELECT')
flag = True
for curve in bpy.data.objects:
if curve.type == 'MESH':
NowName = curve.name
NowCode = NowName[:5]
if NowCode == Code:
if flag:
RecName = NowName
flag = False
curve.select = True
bpy.context.scene.objects.active = curve
bpy.ops.object.join()
bpy.ops.object.select_all(action='DESELECT')
# 小数点の付く名前は書き換える
for item in bpy.data.objects:
if item.type == "MESH":
temp = item.name
try:
item.name = temp[ 0 : temp.index( "." ) ]
except ValueError:
pass
#
bpy.context.scene.objects.active = None
#
def CreateSegVert(pText):
LineData = pText.split( "\n" )
XY = []
for LineStr in LineData:
if LineStr:
buff = []
temp = LineStr.lstrip( " \t" )
if len( temp ):
temp = temp.split( " " )
dy = float( temp[ 0 ] )
dx = float( temp[ 1 ] )
buff.append( dx )
buff.append( dy )
XY.append( buff )
btm = len( XY )
if btm:
btm = btm - 1
if XY[ 0 ] == XY[ btm ]:
del XY[ btm ]
return XY
#
def CreateCurve(pName, pTree, pCurveID, pInterior):
xpath = ".//*/..[@gml:id='" + pCurveID + "']"
Curve = pTree.find( xpath, ns )
posList = Curve.find( './/gml:posList', ns )
verts = CreateSegVert( posList.text ) # セグメント用の座標点リスト
#
CvData = bpy.data.curves.new( name = pName, type = "CURVE" )
CvData.dimensions = "2D"
ObjData = bpy.data.objects.new( pName, CvData )
if pInterior:
ObjData.location = ( 0, 0, 1 )
else:
ObjData.location = ( 0, 0, 0 )
ObjData.scale[0] = ObjScale
ObjData.scale[1] = ObjScale
ObjData.scale[2] = ObjScale
bpy.context.scene.objects.link( ObjData )
polyline = CvData.splines.new( "POLY" )
#
Count = len( verts )
polyline.points.add( Count - 1 )
for ptr in range( 0, Count ):
posX = verts[ ptr ][ 0 ]
posY = verts[ ptr ][ 1 ]
posX = GetLonOffset( wx, posY, posX )
posY = GetLatOffset( wy, posY )
Point = polyline.points[ptr]
Point.co = ( posX, posY, 0, 0 )
polyline.use_cyclic_u = True
ObjData.select = True
if pInterior:
bpy.context.scene.objects.active = ObjData
bpy.ops.object.modifier_add(type='SOLIDIFY') # 厚み付け
bpy.context.object.modifiers["Solidify"].thickness = 5.0 / ObjScale
# カーブをメッシュオブジェクトに変換
bpy.context.scene.objects.active = ObjData
bpy.ops.object.convert( target = "MESH" )
ObjData.select = False
return ObjData
#
print( '\nStart Script' )
#
# 既存メッシュの削除
for item in bpy.context.scene.objects:
if item.type == "MESH":
bpy.context.scene.objects.unlink( item )
for item in bpy.data.objects:
if item.type == "MESH":
bpy.data.objects.remove( item )
for item in bpy.data.meshes:
bpy.data.meshes.remove( item )
#
files = glob.glob( XmlName )
if files:
file = files[ 0 ] # きりがないので処理は1ファイルに限る
tree = ElementTree()
tree.parse( file )
# 事前にセンターの位置を割り出す
Xmin = 100000000.0
Ymin = Xmin
Xmax = -Xmin
Ymax = Xmax
#
xpath = ".//*/..[ksj:administrativeAreaCode='" + AreaCode + "']"
for AdministrativeBoundary in tree.findall( xpath, ns ):
# 面の定義を探す
bounds = AdministrativeBoundary.find( 'ksj:bounds', ns )
href = bounds.get('{http://www.w3.org/1999/xlink}href')
NowSf = href.lstrip('#')
# 面の定義情報からカーブを取り出す
xpath = ".//*/..[@gml:id='" + NowSf + "']"
Surface = tree.find( xpath, ns )
exterior = Surface.find( ".//gml:exterior", ns )
temp = exterior.find( ".//gml:curveMember", ns )
href = temp.get( "{http://www.w3.org/1999/xlink}href" )
NowCv = href.lstrip('#')
# 座標定義位置を探す
xpath = ".//*/..[@gml:id='" + NowCv + "']"
Curve = tree.find( xpath, ns )
posList = Curve.find( './/gml:posList', ns )
LineData = posList.text.split( '\n' )
Buff = []
for temp in LineData:
if temp:
Buff.append( temp )
Count = len( Buff ) - 1
for ptr in range( 0, Count ):
NowText = Buff[ ptr ].lstrip( ' \t' )
xyStr = NowText.split( ' ' )
posY = float( xyStr[ 0 ] )
posX = float( xyStr[ 1 ] )
Xmin = min( posX, Xmin )
Xmax = max( posX, Xmax )
Ymin = min( posY, Ymin )
Ymax = max( posY, Ymax )
#
# ↓ こんなにやって結局欲しかったのはこの2行
wx = ( Xmin + Xmax ) / 2.0
wy = ( Ymin + Ymax ) / 2.0
#
xpath = ".//*/..[ksj:administrativeAreaCode='" + AreaCode + "']"
for AdministrativeBoundary in tree.findall( xpath, ns ):
RecName = CreateRecName( AreaCode, AdministrativeBoundary )
# 面の定義を探す
bounds = AdministrativeBoundary.find( 'ksj:bounds', ns )
href = bounds.get('{http://www.w3.org/1999/xlink}href')
NowSf = href.lstrip('#')
# 面の定義情報からカーブを取り出す
xpath = ".//*/..[@gml:id='" + NowSf + "']"
Surface = tree.find( xpath, ns )
exterior = Surface.find( ".//gml:exterior", ns )
temp = exterior.find( ".//gml:curveMember", ns )
href = temp.get( "{http://www.w3.org/1999/xlink}href" )
NowCv = href.lstrip('#')
#
objectdata = CreateCurve( RecName, tree, NowCv, False )
#
# 穴をあける処理を追加
for interior in Surface.findall( ".//gml:interior", ns ):
for cv in interior.findall( ".//gml:curveMember", ns ):
href = cv.get( "{http://www.w3.org/1999/xlink}href" )
NowCv = href.lstrip('#')
objectdata2 = CreateCurve( "temp", tree, NowCv, True )
#
objectdata.select = True
bpy.context.scene.objects.active = objectdata
bpy.ops.object.modifier_add(type='BOOLEAN')
bpy.context.object.modifiers["Boolean"].operation = 'DIFFERENCE'
bpy.context.object.modifiers["Boolean"].object = bpy.data.objects["temp"]
bpy.context.object.modifiers["Boolean"].double_threshold = 0.0
bpy.ops.object.modifier_apply(apply_as='DATA', modifier="Boolean")
objectdata.select = False
objectdata2.select = True
bpy.ops.object.delete(use_global=False)
bpy.context.scene.objects.active = None
#
tree = None # どうせ終わるので無くてもよい
#
MergeRecName() # 複数レコードを1つにまとめたいなら実行
#
print( '\nEnd Script' )
|