#!BPY
import bpy
import glob
import struct
#
# 試しに1地域の浮き出し地図(シェープファイル)
#
ShpName = "N03-*.shp" # 収録されているshpファイルを指定
AreaCode = "13101" # 地方公共団体コードを文字列型で指定
#
def GetBinDword(Item):
return struct.unpack( "L", Item )[ 0 ]
#
def GetBinDouble(Item):
return struct.unpack( "d", Item )[ 0 ]
#
def GetBinDwordRev(Item):
return struct.unpack( "L", Item[::-1] )[ 0 ]
#
class CDbfFieldRec:
def __init__(self):
self.name = ""
self.Top = 0
self.Btm = 0
#
print( '\nStart Script' )
#
# 既存カーブとメッシュの削除
for item in bpy.context.scene.objects:
if item.type == "CURVE" or item.type == "MESH":
bpy.context.scene.objects.unlink( item )
for item in bpy.data.objects:
if item.type == "CURVE" or item.type == "MESH":
bpy.data.objects.remove( item )
for item in bpy.data.curves:
bpy.data.curves.remove( item )
for item in bpy.data.meshes:
bpy.data.meshes.remove( item )
#
files = glob.glob( ShpName )
if files:
file = files[ 0 ] # きりがないので処理は1ファイルに限る
fshp = open( file, "rb" )
temp = file.split( "." )
fshx = open( temp[ 0 ] + ".shx", "rb" )
fdbf = open( temp[ 0 ] + ".dbf", "rb" )
fdbf.read( 4 ) # skip
tempbin = fdbf.read( 4 )
DbfRecCount = struct.unpack( "L", tempbin )[ 0 ]
tempbin = fdbf.read( 2 )
DbfHeaderSize = struct.unpack( "H", tempbin )[ 0 ]
tempbin = fdbf.read( 2 )
DbfRecSize = struct.unpack( "H", tempbin )[ 0 ]
DbfFieldCount = int( ( DbfHeaderSize - 33 ) / 32 )
# フィールドのレコード内位置を割り出す
fdbf.seek( 32, 0 )
DbfField = []
CodePosE = 1
for fldptr in range( 0, DbfFieldCount ):
DbfFieldRec = CDbfFieldRec()
tempbin = fdbf.read( 32 )
temp = tempbin[:10]
temp = temp.decode('shift_jis')
DbfFieldRec.name = temp.rstrip( ' \0' )
temp = tempbin[16:17]
temp = struct.unpack( "B", temp )
temp = temp[ 0 ]
CodePosE = CodePosE + temp
CodePosS = CodePosE - temp
DbfFieldRec.Top = CodePosS
DbfFieldRec.Btm = CodePosE
DbfField.append( DbfFieldRec )
#
for fldptr in range( 0, DbfFieldCount ):
temp = DbfField[ fldptr ].name
if temp == "N03_001":
DbfPref = fldptr
elif temp == "N03_003":
DbfCounty = fldptr
elif temp == "N03_004":
DbfCity = fldptr
elif temp == "N03_007":
DbfArea = fldptr
#
# ここから本番。レコードごとに図形を作る
fdbf.read( 1 )
for RecNo in range( 0, DbfRecCount ):
# dbfを1レコード読む
tempbin = fdbf.read( DbfRecSize )
temp = tempbin[ DbfField[ DbfArea ].Top : DbfField[ DbfArea ].Btm ]
temp = temp.decode('shift_jis')
if( temp == AreaCode ):
# ↓ オブジェクト名を作る
RecName = AreaCode
temp = tempbin[ DbfField[ DbfPref ].Top : DbfField[ DbfPref ].Btm ]
temp = temp.rstrip( b' ' )
temp = temp.decode('shift_jis')
RecName = RecName + "_" + temp
temp = tempbin[ DbfField[ DbfCounty ].Top : DbfField[ DbfCounty ].Btm ]
temp = temp.rstrip( b' ' )
temp = temp.decode('shift_jis')
if len( temp ):
RecName = RecName + "_" + temp
temp = tempbin[ DbfField[ DbfCity ].Top : DbfField[ DbfCity ].Btm ]
temp = temp.rstrip( b' ' )
temp = temp.decode('shift_jis')
if len( temp ):
RecName = RecName + "_" + temp
# ↑ オブジェクト名を作る
#
fshx.seek( RecNo * 8 + 100, 0 )
tempbin = fshx.read( 8 )
shppos = GetBinDwordRev( tempbin[:4] ) * 2
shplen = GetBinDwordRev( tempbin[4:8] ) * 2
#
fshp.seek( shppos + 8, 0 )
tempbin = fshp.read( shplen )
shptype = GetBinDword( tempbin[:4] )
if shptype == 5: # polygon is 5
NumParts = GetBinDword( tempbin[36:40] )
NumPoints = GetBinDword( tempbin[40:44] )
parts = []
ptr = 44
for temp in range( 0, NumParts ):
NowPart = GetBinDword( tempbin[ptr:ptr+4] )
parts.append( NowPart )
ptr = ptr + 4
parts.append( NumPoints )
#
Count = parts[ 1 ] - parts[ 0 ] - 1
curvedata = bpy.data.curves.new(name=RecName, type='CURVE')
curvedata.dimensions = '2D'
objectdata = bpy.data.objects.new(RecName, curvedata)
objectdata.location = (0,0,0)
bpy.context.scene.objects.link(objectdata)
polyline = curvedata.splines.new('POLY')
#
polyline.points.add( Count - 1 )
for xyptr in range( 0, Count ):
posX = GetBinDouble( tempbin[ptr:ptr+8] )
ptr = ptr + 8
posY = GetBinDouble( tempbin[ptr:ptr+8] )
ptr = ptr + 8
polyline.points[xyptr].co = ( posX, posY, 0, 0 )
polyline.use_cyclic_u = True
#
# ↓ 複数レコードを1つにまとめたいなら実行
for Code in AreaCode:
bpy.ops.object.select_all(action='DESELECT')
for curve in bpy.data.objects:
if curve.type == 'CURVE':
NowName = curve.name
NowCode = NowName[:5]
if NowCode == AreaCode:
curve.select = True
bpy.context.scene.objects.active = curve
bpy.ops.object.join()
bpy.ops.object.select_all(action='DESELECT')
objectdata.name = RecName
# ↑ 複数レコードを1つにまとめたいなら実行
#
fdbf.close()
fshx.close()
fshp.close()
#
print( '\nEnd Script' )
|