« C4D Python R13 テスト:storageモジュールのファイルを開く/保存ダイアログ | トップページ | C4D Python R13 テスト:クローナーで複製したオブジェクトをブールで合体… »

C4D Python R13 テスト:テキストファイルを試行錯誤で読み込んでみた…

あまり参考にはならないと思うのだ…

今回はテキストファイルを読み込んでみる。
と、言ってもC4Dから出力された、ポリゴンオブジェクトのポイントデータを読み込んで、ポリゴンオブジェクトのポイントに設定してみる。

ポイント X Y Z
0 0 50 -80.902
1 0 -50 -80.902
2 80.902 0 -50
3 80.902 0 50
4 0 50 80.902
5 0 -50 80.902
6 -80.902 0 50
7 -80.902 0 -50
8 50 80.902 0
9 -50 80.902 0
10 -50 -80.902 0
11 50 -80.902 0

「PointData.ZIP」

スペース区切りのように見えるけど、実はタブ区切り…
C4Dからエクスポートしたデータで、TSVだね。

これを読み込んで、ポリゴンオブジェクトのポイントのみを生成してみます。
ポリゴンは生成しません。

えぇ…
ファイルの開く/保存ダイアログは、使えそうなものの…
ファイルを開いて読み込むには、どうするんだぁ…

c4d Pythonのモジュールなのかなぁ… 違うのかなぁ…
Pyhonのファイル用のモジュールなのかは… 実は知らん…

試したことも無いのに、いきなり記事を書いてみた…
Win XPで行っているので、Macでは違うかもね… ごめんね…

ボチボチ進めていこう…

とりあえず、前回の記事のファイルのオープンダイアログを使うのだ。
http://villager-and-c4d.cocolog-nifty.com/blog/2011/10/c4d-python-r1-2.html

オープンダイアログは、c4d Python のstorageモジュールの関数だね。

Python
import c4d
from c4d import storage


def main():
    #オープンダイアログを使ってファイルパスを取得
    path = storage.LoadDialog(title = 'ファイルを開きたい')
    if not path:return
    print path
    print type(path)


if __name__=='__main__':
    main()

先ほどのデータファイルは…
G:\テストフォルダ
に、置いてみた。

Textfileopen_01

これで、とりあえずPythonスクリプトを実行してみる。

Textfileopen_02

G:\テストフォルダ\PointData.txt
<type 'str'>

コンソールにも表示され、問題ないようだ…

では、Pythonでファイルを開くには…
調べてみる…

Pythonの組込み関数に…

open(path, mode)
ファイルパスとモード('w' : 書き込み、'r' : 読み込み、等)を指定してファイルを開き、ファイルオブジェクトを返す。

file.close()
書き込みの場合ファイル用のバッファに残っているデータを書き出し、ファイルオブジェクトを閉じる。

file.read()
ファイルオブジェクトから、全てを読み込み文字列を返す。

ファイルを開いて読み込み、閉じるという作業は、この3つがあれば出来そうだ…
スクリプトは以下の様に書いてみた。

Python
import c4d
from c4d import storage


def main():
    #オープンダイアログを使ってファイルパスを取得
    path = storage.LoadDialog(title = 'ファイルを開きたい')
    if not path:return
    print path
    print type(path)


    #ファイルを開いてデータを読み込む
    data_file = open(path, 'r')
    data = data_file.read()
    data_file.close()
    print data


if __name__=='__main__':
    main()

それ程、複雑な事ではないので問題ないと思う…
スクリプトを実行し、ファイルを選択してみる。

G:\テストフォルダ\PointData.txt
<type 'str'>
Traceback (most recent call last):
  File "'scriptmanager'", line 21, in <module>
  File "'scriptmanager'", line 14, in main
IOError: [Errno 2] No such file or directory: 'G:\\\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88\xe3\x83\x95\xe3\x82\xa9\xe3\x83\xab\xe3\x83\x80\\PointData.txt'

そんな、バカな…
ファイルパスの取得は問題なくできているはずなのに…
ちゃんと、コンソールに表示されてるし…

open()でエラーが起きているのだ。
そんなファイルやディレクトリは無い!? だって…
ファイルパスが、G:\\\xe3\x83\x86\xe3\x82…
文字化けして…日本語含みのファイルパスが使えないと言うのかい?

試しにフォルダ名を「test_folder」に変更して…

Textfileopen_03

もう一度、スクリプトを実行してみた。

G:\test_folder\PointData.txt
<type 'str'>
_|_C___gXYZ
0050-80.902
10-50-80.902
280.9020-50
380.902050
405080.902
50-5080.902
6-80.902050
7-80.9020-50
85080.9020
9-5080.9020
10-50-80.9020
1150-80.9020

一応、ファイルは読み込めた…
読み込める事には間違えない。
内容が一部文字化けしていますが…

日本語含みのパスが使えないのか…?
そんなの不便だな…

そう言えば何処かに、ユニコードがどうのこうのと、書いてあったなぁ…
2バイト文字の事だ。
今までスルーしていたけど…
確か、エンコードがどうの… デコードがどうの… コーディングが… Shift-JIS/UTF-8等が、とか…

何か面倒だなぁ…

フォルダ名を元の「テストフォルダ」に戻して…

文字列には、シングルバイトのstrオブジェクトとマルチバイトのunicodeオブジェクトの2種類あるそうで…
strオブジェクトをunicodeオブジェクトへ変換する関数…

unicode(strオブジェクト, コーデック)

だったかな…
とりあえず、コーデックはUTF-8を指定してみる。

Python
import c4d
from c4d import storage


def main():
    #オープンダイアログを使ってファイルパスを取得
    path = storage.LoadDialog(title = 'ファイルを開きたい')
    if not path:return
    path = unicode(path, 'UTF-8')
    print path
    print type(path)


    #ファイルを開いてデータを読み込む
    data_file = open(path, 'r')
    data = data_file.read()
    data_file.close()
    print data


if __name__=='__main__':
    main()

これで実行してみると…

Textfileopen_02

G:\テストフォルダ\PointData.txt
<type 'unicode'>
_|_C___gXYZ
0050-80.902
10-50-80.902
280.9020-50
380.902050
405080.902
50-5080.902
6-80.902050
7-80.9020-50
85080.9020
9-5080.9020
10-50-80.9020
1150-80.9020

ようやく、読み込むことができた。
でも、読み込んだテキストも文字化けしているね…

今回読み込んでいるテキストファイルは、Shift-JISなので、unicode()関数のコーデックはshift-jisを指定する。
大文字/小文字は関係ないようだ…

Python
import c4d
from c4d import storage


def main():
    #オープンダイアログを使ってファイルパスを取得
    path = storage.LoadDialog(title = 'ファイルを開きたい')
    if not path:return
    path = unicode(path, 'UTF-8')
    print path
    print type(path)


    #ファイルを開いてデータを読み込む
    data_file = open(path, 'r')
    data = data_file.read()
    data_file.close()
    print unicode(data, 'shift-jis')


if __name__=='__main__':
    main()

実行結果は問題なく、文字化けは無くなった。

G:\テストフォルダ\PointData.txt
<type 'unicode'>
ポイントXYZ
0050-80.902
10-50-80.902
280.9020-50
380.902050
405080.902
50-5080.902
6-80.902050
7-80.9020-50
85080.9020
9-5080.9020
10-50-80.9020
1150-80.9020

さてと…
読み込んだテキストデータをポイントデータ(ベクトル型)のリストへ変換してみよう。

まずは、読み込んだテキストを改行毎に区切ってリストに変換してみる。
文字列を任意の文字列で区切ってリストにするには、以前にも書いたね。
http://villager-and-c4d.cocolog-nifty.com/blog/2011/06/c4d-python-r1-6.html

Python
import c4d
from c4d import storage


def main():
    #オープンダイアログを使ってファイルパスを取得
    path = storage.LoadDialog(title = 'ファイルを開きたい')
    if not path:return
    path = unicode(path, 'UTF-8')
    print path
    print type(path)


    #ファイルを開いてデータを読み込む
    data_file = open(path, 'r')
    data = data_file.read()
    data_file.close()
    data = unicode(data, 'shift-jis')


    #読み込んだ文字列を改行で区切ってリストにする。
    data = data.split('\n')
    print data


if __name__=='__main__':
    main()

実行すると下のように表示される。
リストに変換されているようだね。

G:\テストフォルダ\PointData.txt
<type 'unicode'>
[u'\u30dd\u30a4\u30f3\u30c8\tX\tY\tZ', u'0\t0\t50\t-80.902', u'1\t0\t-50\t-80.902', u'2\t80.902\t0\t-50', u'3\t80.902\t0\t50', u'4\t0\t50\t80.902', u'5\t0\t-50\t80.902', u'6\t-80.902\t0\t50', u'7\t-80.902\t0\t-50', u'8\t50\t80.902\t0', u'9\t-50\t80.902\t0', u'10\t-50\t-80.902\t0', u'11\t50\t-80.902\t0', u'']

ユニコードのリストなのは分かりますが…
わかりづらいから、リストの要素を1個づつ表示してみる。

Python
import c4d
from c4d import storage


def main():
    #オープンダイアログを使ってファイルパスを取得
    path = storage.LoadDialog(title = 'ファイルを開きたい')
    if not path:return
    path = unicode(path, 'UTF-8')
    print path
    print type(path)


    #ファイルを開いてデータを読み込む
    data_file = open(path, 'r')
    data = data_file.read()
    data_file.close()
    data = unicode(data, 'shift-jis')


    #読み込んだ文字列を改行で区切ってリストにする。
    data = data.split('\n')


    #変換したリストの要素を1個づつ表示する。
    for lines in data:
        print lines


if __name__=='__main__':
    main()
G:\テストフォルダ\PointData.txt
<type 'unicode'>
ポイントXYZ
0050-80.902
10-50-80.902
280.9020-50
380.902050
405080.902
50-5080.902
6-80.902050
7-80.9020-50
85080.9020
9-5080.9020
10-50-80.9020
1150-80.9020

問題ないようだ。

タブ区切りのはずなのに、コンソールはタブを表示できないのか詰まって表示されたいる。
この分割されたテキストのリストを更にタブで区切ってみる。

Python
import c4d
from c4d import storage


def main():
    #オープンダイアログを使ってファイルパスを取得
    path = storage.LoadDialog(title = 'ファイルを開きたい')
    if not path:return
    path = unicode(path, 'UTF-8')
    print path
    print type(path)


    #ファイルを開いてデータを読み込む
    data_file = open(path, 'r')
    data = data_file.read()
    data_file.close()
    data = unicode(data, 'shift-jis')


    #読み込んだ文字列を改行で区切ってリストにする。
    data = data.split('\n')


    #1行単位で、タブで区切って更にリストにする。
    for id in xrange(len(data)):
        data[id] = data[id].split('\t')


    #変換したリストの要素を1個づつ表示する。
    for lines in data:
        print lines


if __name__=='__main__':
    main()

実行すると以下のように表示される。

G:\テストフォルダ\PointData.txt
<type 'unicode'>
[u'\u30dd\u30a4\u30f3\u30c8', u'X', u'Y', u'Z']
[u'0', u'0', u'50', u'-80.902']
[u'1', u'0', u'-50', u'-80.902']
[u'2', u'80.902', u'0', u'-50']
[u'3', u'80.902', u'0', u'50']
[u'4', u'0', u'50', u'80.902']
[u'5', u'0', u'-50', u'80.902']
[u'6', u'-80.902', u'0', u'50']
[u'7', u'-80.902', u'0', u'-50']
[u'8', u'50', u'80.902', u'0']
[u'9', u'-50', u'80.902', u'0']
[u'10', u'-50', u'-80.902', u'0']
[u'11', u'50', u'-80.902', u'0']
[u'']

1行目と最後の行は必要ないね。
それ以外は、ポイントID/X/Y/Zの順で並んでいる。
このポイントIDも必要ない。X/Y/Zのみが必要だ。

とりあえず例外処理を使って、それぞれを数値に変換しベクトル型のリストを作成してみる。
変換に失敗したら飛ばして次に行くことにしてみる。

Python
import c4d
from c4d import storage


def main():
    #オープンダイアログを使ってファイルパスを取得
    path = storage.LoadDialog(title = 'ファイルを開きたい')
    if not path:return
    path = unicode(path, 'UTF-8')
    print path
    print type(path)


    #ファイルを開いてデータを読み込む
    data_file = open(path, 'r')
    data = data_file.read()
    data_file.close()
    data = unicode(data, 'shift-jis')


    #読み込んだ文字列を改行で区切ってリストにする。
    data = data.split('\n')


    #1行単位で、タブで区切って更にリストにする。
    for id in xrange(len(data)):
        data[id] = data[id].split('\t')


    #変換したリストの要素を1個づつ表示する。
    for lines in data:
        print lines


    #ベクトル型のリストの作成
    pt_data = []
    for lines in data:
        try:
            pt_data.append(c4d.Vector(float(lines[1]), float(lines[2]), float(lines[3])))
        except:
            pass

    print pt_data


if __name__=='__main__':
    main()

結果は以下のとおり。
間違いなくベクトルのリストへ変換されていると思う。

G:\テストフォルダ\PointData.txt
<type 'unicode'>
[u'\u30dd\u30a4\u30f3\u30c8', u'X', u'Y', u'Z']
[u'0', u'0', u'50', u'-80.902']
[u'1', u'0', u'-50', u'-80.902']
[u'2', u'80.902', u'0', u'-50']
[u'3', u'80.902', u'0', u'50']
[u'4', u'0', u'50', u'80.902']
[u'5', u'0', u'-50', u'80.902']
[u'6', u'-80.902', u'0', u'50']
[u'7', u'-80.902', u'0', u'-50']
[u'8', u'50', u'80.902', u'0']
[u'9', u'-50', u'80.902', u'0']
[u'10', u'-50', u'-80.902', u'0']
[u'11', u'50', u'-80.902', u'0']
[u'']
[Vector(0, 50, -80.902), Vector(0, -50, -80.902), Vector(80.902, 0, -50), Vector(80.902, 0, 50), Vector(0, 50, 80.902), Vector(0, -50, 80.902), Vector(-80.902, 0, 50), Vector(-80.902, 0, -50), Vector(50, 80.902, 0), Vector(-50, 80.902, 0), Vector(-50, -80.902, 0), Vector(50, -80.902, 0)]

では、ベクトル型のリストができたので、ポリゴンオブジェクトを作成しポイントを設定。
最後に、シーンへこのポリゴンオブジェクトを追加したら、今回の作業は完了する。

ポリゴンオブジェクトの生成は以前に書きました。
http://villager-and-c4d.cocolog-nifty.com/blog/2011/02/c4d-python-r1-7.html

Python
import c4d
from c4d import storage


def main():
    #オープンダイアログを使ってファイルパスを取得
    path = storage.LoadDialog(title = 'ファイルを開きたい')
    if not path:return
    path = unicode(path, 'UTF-8')
    print path
    print type(path)


    #ファイルを開いてデータを読み込む
    data_file = open(path, 'r')
    data = data_file.read()
    data_file.close()
    data = unicode(data, 'shift-jis')


    #読み込んだ文字列を改行で区切ってリストにする。
    data = data.split('\n')


    #1行単位で、タブで区切って更にリストにする。
    for id in xrange(len(data)):
        data[id] = data[id].split('\t')


    #変換したリストの要素を1個づつ表示する。
    for lines in data:
        print lines


    #ベクトル型のリストの作成
    pt_data = []
    for lines in data:
        try:
            pt_data.append(c4d.Vector(float(lines[1]), float(lines[2]), float(lines[3])))
        except:
            pass

    print pt_data


    #ポリゴンオブジェクトを作成しシーンに追加する。
    obj = c4d.BaseObject(c4d.Opolygon)
    obj.ResizeObject(len(pt_data), 0)
    for id in xrange(len(pt_data)):
        obj.SetPoint(id, pt_data[id])
    obj.Message(c4d.MSG_UPDATE)

    doc.InsertObject(obj, None, None, True)
    obj.SetBit(c4d.BIT_AOBJ)

    doc.SetMode(c4d.Mpoints)
    c4d.EventAdd()


if __name__=='__main__':
    main()

実行するとテキストファイルからポイントデータを読み取り、ポリゴンなしのポリゴンオブジェクトを生成してシーンに追加。
C4Dの編集モードをポイントモードへ変更します。

Textfileopen_04

これで今回の作業は終了です。
スクリプトは、確認しながら追加したので無駄があります。
一応、自前のPCでは動作していますが、他のPCでの動作はわかりません。
ごめんね…

今回のテストスクリプト「test_textfile_read.py」です。

そう言えば…
ユニコードをソースで使う場合、1行目か2行目に…
# coding: UTF-8
を入れないとエラーが出るとか、どこかに書いてあったんだけど…
いまいち分からん…

作業の進め方は、参考にしない方が良いかもね…

|

« C4D Python R13 テスト:storageモジュールのファイルを開く/保存ダイアログ | トップページ | C4D Python R13 テスト:クローナーで複製したオブジェクトをブールで合体… »

コメント

コメントを書く



(ウェブ上には掲載しません)




« C4D Python R13 テスト:storageモジュールのファイルを開く/保存ダイアログ | トップページ | C4D Python R13 テスト:クローナーで複製したオブジェクトをブールで合体… »