« C4D Python R12 テスト:シンプルな入力ダイアログを使ってみる。 | トップページ | C4D Python R12 テスト:オブジェクトのバウンディングBOX »

C4D Python R12 テスト:オブジェクトをスプライン等に配置する。

スプラインやポリゴンオブジェクトに球体プリミティブを配置してみます。
ただし、位置のみです。

プリミティブ等をアロケートする時のタイプは…
http://villager-and-c4d.cocolog-nifty.com/blog/coffee-allocobject.html

オブジェクトのタグの取り付けは…
http://villager-and-c4d.cocolog-nifty.com/blog/2011/02/c4d-python-r-10.html

プリミティブオブジェクトの追加…
http://villager-and-c4d.cocolog-nifty.com/blog/2011/02/c4d-python-r1-4.html

オブジェクトの位置
http://villager-and-c4d.cocolog-nifty.com/blog/2011/02/c4d-python-r-12.html

まずは、スプラインに配置します。

Arrangeobject_01

ポイントは16個あります。
スプライン上の位置は、SplineObject.GetSplinePoint()で、位置(0.0~1.0)とセグメント(省略可)を設定して取得します。
取得する位置の配分は、スプラインのポイントに関係しています。
ポイント間は、1.0 ÷ (16個 - 1) = 0.066...
スプラインの補間法、なし/ナチュラル/均等/最適/細分化には影響されないようです。

Arrangeobject_02

配置の位置関係は上の図のように、均等間隔ではありません。
ポイント間隔が密なほど縮まります。

球体プリミティブを10個配置する事にしました。
入力ダイアログを付けてみましたので、違う数値も入れられます。

Python
'''
スプライン曲線上に球体プリミティブを配置する。
'''



import c4d
from c4d import gui




def main():
    if not isinstance(op, c4d.SplineObject):return

    new_obj_cnt = 10

    #配置するオブジェクトの数の入力ダイアログ 2以上
    ret_val =  gui.InputDialog('配置する個数', new_obj_cnt)
    if ret_val.isdigit():
        new_obj_cnt = int(ret_val)
    else:
        new_obj_cnt = 0

    if new_obj_cnt < 2:new_obj_cnt = 2

    #球体の大きさは、スプラインの大きさの0.05
    size = op.GetRad().GetLength() * 0.05

    for id in xrange(new_obj_cnt):
        pos = op.GetSplinePoint(id / float(new_obj_cnt - 1)) #スプライン上の位置の取得


        obj = c4d.BaseObject(c4d.Osphere) #球体オブジェクトの生成
        obj.MakeTag(c4d.Tphong) #スムーズタグの取り付け
        obj.SetAbsPos(pos) #球体オブジェクトの座標
        obj[c4d.PRIM_SPHERE_RAD] = size #球体オブジェクトの半径

        obj.InsertUnder(op) #シーンへオブジェクトの挿入




if __name__=='__main__':
    main()
    c4d.EventAdd()

Arrangeobject_03

結果は、均等には配置されません。

均等に配置する場合は、utils.SplineLengthDataクラスのUniformToNatural()メソッドを使います。
SplineLengthDataクラスの場合、メソッドを使う前にスプラインを指定してInit()メソッドで初期化を行わなければなりません。

Init()メソッドは、最初のパラメータにスプラインオブジェクト、2番目のパラメータにセグメント(省略可)を設定します。

UniformToNatural()メソッドには、スプライン上の位置(0.0~1.0)を渡します。
その返り値をSplineObject.GetSplinePoint()へ設定します。
要するにUniformToNatural()メソッドは、SplineObject.GetSplinePoint()で均等に分割するために数値を調整する為のものなのだ。

Python
'''
スプライン曲線上に球体プリミティブを均等に配置する。
'''



import c4d
from c4d import gui
from c4d import utils




def main():
    if not isinstance(op, c4d.SplineObject):return

    new_obj_cnt = 10

    #配置するオブジェクトの数の入力ダイアログ 2以上
    ret_val =  gui.InputDialog('配置する個数', new_obj_cnt)
    if ret_val.isdigit():
        new_obj_cnt = int(ret_val)
    else:
        new_obj_cnt = 0

    if new_obj_cnt < 2:new_obj_cnt = 2

    #球体の大きさは、スプラインの大きさの0.05
    size = op.GetRad().GetLength() * 0.05

    #均等配置の為に…
    sld = utils.SplineLengthData()
    sld.Init(op) #SplineLengthDataをスプラインオブジェクトを指定して初期化


    for id in xrange(new_obj_cnt):
        spl_pos = sld.UniformToNatural(id / float(new_obj_cnt - 1)) #均等配置する為の調整された値の取得
        pos = op.GetSplinePoint(spl_pos) #スプライン上の位置の取得


        obj = c4d.BaseObject(c4d.Osphere) #球体オブジェクトの生成
        obj.MakeTag(c4d.Tphong) #スムーズタグの取り付け
        obj.SetAbsPos(pos) #球体オブジェクトの座標
        obj[c4d.PRIM_SPHERE_RAD] = size #球体オブジェクトの半径

        obj.InsertUnder(op) #シーンへオブジェクトの挿入




if __name__=='__main__':
    main()
    c4d.EventAdd()

Arrangeobject_04

長さに対して均等に配置されています。

ポイントに配置するならば…

Python
'''
スプラインやポリゴンオブジェクトのポイントに球体プリミティブを配置する。
'''



import c4d




def main():
    if not isinstance(op, c4d.PointObject):return

    pts = op.GetAllPoints()

    #球体の大きさは、選択オブジェクトの大きさの0.05
    size = op.GetRad().GetLength() * 0.05

    for pos in pts:


        obj = c4d.BaseObject(c4d.Osphere) #球体オブジェクトの生成
        obj.MakeTag(c4d.Tphong) #スムーズタグの取り付け
        obj.SetAbsPos(pos) #球体オブジェクトの座標
        obj[c4d.PRIM_SPHERE_RAD] = size #球体オブジェクトの半径

        obj.InsertUnder(op) #シーンへオブジェクトの挿入




if __name__=='__main__':
    main()
    c4d.EventAdd()

Arrangeobject_05

もちろん、ポイントなのでポリゴンオブジェクトのポイントにも配置できます。

Arrangeobject_06

選択したポイントへ配置するなら…

ポイントのBaseSelectをPointObject.GetPointS()で取得し使います。

Arrangeobject_08

Python
'''
スプラインやポリゴンオブジェクトの選択ポイントに球体プリミティブを配置する。
'''



import c4d




def main():
    if not isinstance(op, c4d.PointObject):return

    #ポイント数/ポイント/ポイントの選択範囲の取得
    pts_cnt = op.GetPointCount()
    pts = op.GetAllPoints()
    sel = op.GetPointS()

    #球体の大きさは、選択オブジェクトの大きさの0.05
    size = op.GetRad().GetLength() * 0.05

    for id in xrange(pts_cnt):
        if not sel.IsSelected(id):continue #選択していないポイントは飛ばす

        pos = pts[id]


        obj = c4d.BaseObject(c4d.Osphere) #球体オブジェクトの生成
        obj.MakeTag(c4d.Tphong) #スムーズタグの取り付け
        obj.SetAbsPos(pos) #球体オブジェクトの座標
        obj[c4d.PRIM_SPHERE_RAD] = size #球体オブジェクトの半径

        obj.InsertUnder(op) #シーンへオブジェクトの挿入




if __name__=='__main__':
    main()
    c4d.EventAdd()

Arrangeobject_09

ポリゴンに配置するなら…
ただし…
ポリゴンへの配置位置は、頂点座標の合計/頂点の数とします。
N-Gonsは考慮しません。

Python
'''
ポリゴンオブジェクトのポリゴンに球体プリミティブを配置する。
'''



import c4d




def main():
    if not isinstance(op, c4d.PolygonObject):return

    pgns = op.GetAllPolygons()
    pts = op.GetAllPoints()

    #球体の大きさは、選択オブジェクトの大きさの0.05
    size = op.GetRad().GetLength() * 0.05

    for pgn in pgns:
        #ポリゴンの位置を求める
        if pgn.c == pgn.d: #三角ポリゴンの場合
            pos = pts[pgn.a] + pts[pgn.b] + pts[pgn.c]
            pos /= 3
        else: #四角ポリゴンの場合
            pos = pts[pgn.a] + pts[pgn.b] + pts[pgn.c] + pts[pgn.d]
            pos /= 4


        obj = c4d.BaseObject(c4d.Osphere) #球体オブジェクトの生成
        obj.MakeTag(c4d.Tphong) #スムーズタグの取り付け
        obj.SetAbsPos(pos) #球体オブジェクトの座標
        obj[c4d.PRIM_SPHERE_RAD] = size #球体オブジェクトの半径

        obj.InsertUnder(op) #シーンへオブジェクトの挿入




if __name__=='__main__':
    main()
    c4d.EventAdd()

Arrangeobject_07

三角ポリゴンにも四角ポリゴンにも配置されています。

選択したポリゴンにも配置してみる。

ポリゴンのBaseSelectをPolygonObject.GetPolygonS()で取得して使います。

Arrangeobject_10

Python
'''
ポリゴンオブジェクトの選択ポリゴンに球体プリミティブを配置する。
'''



import c4d




def main():
    if not isinstance(op, c4d.PolygonObject):return

    #ポリゴン数/ポリゴン/ポイント/ポリゴンの選択範囲の取得
    pgn_cnt = op.GetPolygonCount()
    pgns = op.GetAllPolygons()
    pts = op.GetAllPoints()
    sel = op.GetPolygonS()

    #球体の大きさは、選択オブジェクトの大きさの0.05
    size = op.GetRad().GetLength() * 0.05

    for id in xrange(pgn_cnt):
        if not sel.IsSelected(id):continue #選択されていないポリゴンは飛ばす

        pgn = pgns[id]

        #ポリゴンの位置を求める
        if pgn.c == pgn.d: #三角ポリゴンの場合
            pos = pts[pgn.a] + pts[pgn.b] + pts[pgn.c]
            pos /= 3
        else: #四角ポリゴンの場合
            pos = pts[pgn.a] + pts[pgn.b] + pts[pgn.c] + pts[pgn.d]
            pos /= 4


        obj = c4d.BaseObject(c4d.Osphere) #球体オブジェクトの生成
        obj.MakeTag(c4d.Tphong) #スムーズタグの取り付け
        obj.SetAbsPos(pos) #球体オブジェクトの座標
        obj[c4d.PRIM_SPHERE_RAD] = size #球体オブジェクトの半径

        obj.InsertUnder(op) #シーンへオブジェクトの挿入




if __name__=='__main__':
    main()
    c4d.EventAdd()

Arrangeobject_11

ポリゴンのエッジに配置するには…

ポリゴンの隣接情報を扱うutils.Neighborクラスを使う。
以前のテストは…
http://villager-and-c4d.cocolog-nifty.com/blog/2011/05/c4d-python-r1-2.html

Python
'''
ポリゴンオブジェクトのエッジに球体プリミティブを配置する。
'''



import c4d
from c4d import utils




def main():
    if not isinstance(op, c4d.PolygonObject):return

    #ポリゴン数/ポリゴン/ポイント/ポリゴンの隣接情報の取得
    pgn_cnt = op.GetPolygonCount()
    pgns = op.GetAllPolygons()
    pts = op.GetAllPoints()
    nbor = utils.Neighbor()
    nbor.Init(op)

    #球体の大きさは、選択オブジェクトの大きさの0.05
    size = op.GetRad().GetLength() * 0.05

    for id in xrange(pgn_cnt):
        #処理を単純化するために、ポリゴンのポイントをリストへ格納
        pgn = [pgns[id].a, pgns[id].b, pgns[id].c, pgns[id].d, pgns[id].a]

        #ポリゴンの隣接情報から'face'のデータだけ取得
        nbor_poly = nbor.GetPolyInfo(id)['face']

        for side in xrange(4):
            #三角ポリゴンの場合はエッジbcの処理を飛ばす
            if side == 2 and pgn[2] == pgn[3]:continue

            #隣のポリゴン番号が大きければ処理の対象。そうでなければ飛ばす
            if id < nbor_poly[side]:pos = (pts[pgn[side]] + pts[pgn[side + 1]])/2
            else:continue


            obj = c4d.BaseObject(c4d.Osphere) #球体オブジェクトの生成
            obj.MakeTag(c4d.Tphong) #スムーズタグの取り付け
            obj.SetAbsPos(pos) #球体オブジェクトの座標
            obj[c4d.PRIM_SPHERE_RAD] = size #球体オブジェクトの半径
   
            obj.InsertUnder(op) #シーンへオブジェクトの挿入




if __name__=='__main__':
    main()
    c4d.EventAdd()

Arrangeobject_12

選択されたエッジに配置してみる…

エッジのBaseSelectをPolygonObject.GetEdgeS()で取得して使います。

Arrangeobject_13

Python
'''
ポリゴンオブジェクトの選択エッジに球体プリミティブを配置する。
'''



import c4d
from c4d import utils




def main():
    if not isinstance(op, c4d.PolygonObject):return

    #ポリゴン数/ポリゴン/ポイント/エッジの選択範囲/ポリゴンの隣接情報の取得
    pgn_cnt = op.GetPolygonCount()
    pgns = op.GetAllPolygons()
    pts = op.GetAllPoints()
    sel = op.GetEdgeS()
    nbor = utils.Neighbor()
    nbor.Init(op)

    #球体の大きさは、選択オブジェクトの大きさの0.05
    size = op.GetRad().GetLength() * 0.05

    for id in xrange(pgn_cnt):
        #処理を単純化するために、ポリゴンのポイントをリストへ格納してみる
        pgn = [pgns[id].a, pgns[id].b, pgns[id].c, pgns[id].d, pgns[id].a]

        #ポリゴンの隣接情報から'face'のデータだけ取得
        nbor_poly = nbor.GetPolyInfo(id)['face']

        for side in xrange(4):
            #選択エッジではなければ処理を飛ばす
            if not sel.IsSelected(id * 4 + side):continue

            #三角ポリゴンの場合はエッジbcの処理を飛ばす
            if side == 2 and pgn[2] == pgn[3]:continue

            #隣のポリゴン番号が大きければ処理の対象。そうでなければ飛ばす
            if id < nbor_poly[side]:pos = (pts[pgn[side]] + pts[pgn[side + 1]])/2
            else:continue


            obj = c4d.BaseObject(c4d.Osphere) #球体オブジェクトの生成
            obj.MakeTag(c4d.Tphong) #スムーズタグの取り付け
            obj.SetAbsPos(pos) #球体オブジェクトの座標
            obj[c4d.PRIM_SPHERE_RAD] = size #球体オブジェクトの半径
   
            obj.InsertUnder(op) #シーンへオブジェクトの挿入




if __name__=='__main__':
    main()
    c4d.EventAdd()

Arrangeobject_14

とりあえず、動作しているけど…
半分眠りながらなので… ごめん… ヘロヘロで…

|

« C4D Python R12 テスト:シンプルな入力ダイアログを使ってみる。 | トップページ | C4D Python R12 テスト:オブジェクトのバウンディングBOX »

コメント

コメントを書く



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




« C4D Python R12 テスト:シンプルな入力ダイアログを使ってみる。 | トップページ | C4D Python R12 テスト:オブジェクトのバウンディングBOX »