« C4D Python R12 テスト:2個のスプラインを連結する。 | トップページ | C4D Python R12 テスト:前回諦めてしまった、スプラインのセグメントをSetSegment()で再設定する »

C4D Python R12 テスト:セグメントに分断されているスプラインを全部連結させようと…

1つのスプラインにセグメントが複数あって…
それをセグメント順に連結して、1本のスプラインにしたいなぁ C4D Pythonスクリプトでね
なんて思って…試行錯誤

Python_splinsegalljoin_01_2

こんな具合に、複数のセグメントに分かれているスプラインを連結して1本のスプラインにしようと、SplineObject.SetSegment()を使ってセグメントを編集してみた。

Python
'''
スプラインの最初のセグメントを全てのポイント数にして、残りのセグメントをカラにする。
'''


import c4d


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

    seg_cnt = op.GetSegmentCount()
    if seg_cnt < 2:return

    pnt_cnt = op.GetPointCount()

    op.SetSegment(0, pnt_cnt, False)
    for id in xrange(1, seg_cnt):
        op.SetSegment(id, 0, False)



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

セグメント0:総ポイント数の12
セグメント1:0
セグメント2:0
セグメント3:0
を設定してみた…

Python_splinsegalljoin_02

確かに、1本のスプラインになったようだけど…

ポイントモードなのにポイントが表示されていない。

オブジェクトモードにしてみたら…

Python_splinsegalljoin_03

まだセグメントになっている。
データとして良くない状態にあるんだろうね…

試しに、セグメントをコンソールに表示してみる。

Python
'''
スプラインのセグメントをコンソールに表示。
'''


import c4d


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

    seg_cnt = op.GetSegmentCount()
    if seg_cnt == 0:return

    for id in xrange(seg_cnt):
        print id, op.GetSegment(id)


if __name__=='__main__':
    main()
    c4d.EventAdd()
0 {'cnt': 12, 'closed': False}
1 {'cnt': 0, 'closed': False}
2 {'cnt': 0, 'closed': False}
3 {'cnt': 0, 'closed': False}

確かに、セグメント0に全てのポイントが設定され、残りのセグメントは0ポイントだ…
と言うか… 自動的には、セグメント1,2,3は消えないんだね。

多分、セグメントにポイント数0を設定してはよろしくないんだね…

でも、ポイントの無いセグメントは、どうやって削除するのかな…?
わからないな…

もしかして、セグメントは編集してはいけないのか?
そんな分けないよね…GetSegment()/SetSegment()があるんだから…

1つのセグメントには、最低限ポイントは1個ないといけない規則なのだろう…

最初のセグメント以外を1に設定してみる。

Python
'''
スプラインの最初のセグメント以外のポイント数を1にする。
'''


import c4d


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

    seg_cnt = op.GetSegmentCount()
    if seg_cnt < 2:return

    pnt_cnt = op.GetPointCount()

    op.SetSegment(0, pnt_cnt - (seg_cnt - 1), False)
    for id in xrange(1, seg_cnt):
        op.SetSegment(id, 1, False)


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

Python_splinsegalljoin_04

ポイントは表示が戻ってきたね。

セグメントをコンソールに表示して確かめてみる。

0 {'cnt': 9, 'closed': False}
1 {'cnt': 1, 'closed': False}
2 {'cnt': 1, 'closed': False}
3 {'cnt': 1, 'closed': False}

じゃあ何かい?
このセグメント編集の方法じゃダメなのかい?

じゃあ…
セグメントの切れ目のポイントを選択して「セグメントを連結」
これを繰り返すのかい?

Python_splinsegalljoin_05

そうすると…
BaseSelectとSendModelingCommand()を使って…

[[2, 3], [5, 6], [8, 9]]とポイントを抽出して…
それぞれを繋ぐ…

Python
'''
スプラインのセグメントを全て連結。
'''


import c4d
from c4d import utils


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

    seg_cnt = op.GetSegmentCount()
    if seg_cnt < 2:return

    sel = op.GetPointS()

    settings = c4d.BaseContainer()

    #連結ポイントを記録
    sum = 0
    joint_pnt = []
    for id in xrange(seg_cnt - 1):
        sum += op.GetSegment(id)['cnt']
        joint_pnt.append([sum - 1, sum])

    #連結する
    for pt in joint_pnt:
        sel.DeselectAll()
        sel.Select(pt[0])
        sel.Select(pt[1])

        utils.SendModelingCommand(c4d.MCOMMAND_SPLINE_JOINSEGMENT, [op],
                    c4d.MODELINGCOMMANDMODE_POINTSELECTION, settings, doc)

    sel.DeselectAll()


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

わざわざ、繋ぐポイントをリストに記録しなくても良いよね…
セグメントが無くなるまで、セグメント0とセグメント1を連結し続ければ良いのだ…

Python
'''
スプラインのセグメントを全て連結-2
'''


import c4d
from c4d import utils


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

    seg_cnt = op.GetSegmentCount()
    if seg_cnt < 2:return

    sel = op.GetPointS()

    settings = c4d.BaseContainer()

    #連結
    while op.GetSegmentCount() > 1:
        pt = op.GetSegment(0)['cnt']

        sel.DeselectAll()
        sel.Select(pt - 1)
        sel.Select(pt)

        utils.SendModelingCommand(c4d.MCOMMAND_SPLINE_JOINSEGMENT, [op],
                    c4d.MODELINGCOMMANDMODE_POINTSELECTION, settings, doc)

    sel.DeselectAll()


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

あ…
間抜けだった事に今気付いた…

全てのセグメントを連結するのに、ポイントを選択しなくても良いんだったよね…
SendModelingCommand(c4d.MCOMMAND_SPLINE_JOINSEGMENT,,,)で、一発でできるじゃないか…

Python
'''
スプラインのセグメントを全て連結-3
'''


import c4d
from c4d import utils


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

    seg_cnt = op.GetSegmentCount() #これも要らないよね
    if seg_cnt < 2:return #これも要らないよね

    settings = c4d.BaseContainer()

    utils.SendModelingCommand(c4d.MCOMMAND_SPLINE_JOINSEGMENT, [op],
                    c4d.MODELINGCOMMANDMODE_ALL, settings, doc)



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

わざわざ複雑に考える事も無かったね…
簡単だね…

Undoは書いてないけど…

でもね…

セグメントの最終端と次のセグメントの開始端が重なっていたら…

Python_splinsegalljoin_06

ポイント3と4が重なっている。
接線ハンドルの向きや長さは違いますけど…

これを「セグメントを連結」すると…

Python_splinsegalljoin_07_2

こんな具合になる場合がある。
「セグメントを連結」だけでは、ダブっているポイントは統合されないので、「最適化...」を行う必要があるね。

C4dpythonsendmodelingcommand_034

Python
'''
SendModelingCommand()
「最適化...」
'''


import c4d
from c4d import utils


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

    bc = c4d.BaseContainer()
    bc.SetData(c4d.MDATA_OPTIMIZE_POLYGONS, True) #ポリゴン
    bc.SetData(c4d.MDATA_OPTIMIZE_UNUSEDPOINTS, True) #不使用ポイント
    bc.SetData(c4d.MDATA_OPTIMIZE_POINTS, True) #重なったポイント
    bc.SetData(c4d.MDATA_OPTIMIZE_TOLERANCE, 0.01) #許容値

    doc.StartUndo()

    utils.SendModelingCommand(c4d.MCOMMAND_OPTIMIZE, [op],
                    c4d.MODELINGCOMMANDMODE_ALL, bc, doc,
                    c4d.MODELINGCOMMANDFLAGS_CREATEUNDO)

    doc.EndUndo()


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

で…

Python
'''
スプラインのセグメントを全て連結-4
'''


import c4d
from c4d import utils


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

    #セグメントを連結
    join_set = c4d.BaseContainer()

    utils.SendModelingCommand(c4d.MCOMMAND_SPLINE_JOINSEGMENT, [op],
                    c4d.MODELINGCOMMANDMODE_ALL, join_set, doc)

    #最適化...
    optim_set = c4d.BaseContainer()

    optim_set.SetData(c4d.MDATA_OPTIMIZE_UNUSEDPOINTS, True) #不使用ポイント
    optim_set.SetData(c4d.MDATA_OPTIMIZE_POINTS, True) #重なったポイント
    optim_set.SetData(c4d.MDATA_OPTIMIZE_TOLERANCE, 0.01) #許容値

    utils.SendModelingCommand(c4d.MCOMMAND_OPTIMIZE, [op],
                    c4d.MODELINGCOMMANDMODE_ALL, optim_set, doc)


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

Python_splinsegalljoin_08

これで、問題は無さそうだ…

Undoは書いていないけど…

最後に…
セグメントタグを削除すれば、セグメントは繋がると思うけどね…

|

« C4D Python R12 テスト:2個のスプラインを連結する。 | トップページ | C4D Python R12 テスト:前回諦めてしまった、スプラインのセグメントをSetSegment()で再設定する »

コメント

コメントを書く



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




« C4D Python R12 テスト:2個のスプラインを連結する。 | トップページ | C4D Python R12 テスト:前回諦めてしまった、スプラインのセグメントをSetSegment()で再設定する »