選択した、頂点、ポリゴン、エッジが入っちゃっているクラスタを調査する

Twitterでふられたので、Pythonで作ってみました。
選択した頂点等、コンポーネントがちょっとでもかすっているクラスタを調査し、選択します。
名付けて、「出てこいクラスター」もしくは「表に出ろやクラスター」

内容は雑ですが、大体こんな感じかと・・・。
SIのコンポーネントを探したいときに階層のいちいち深いところまでいかないといけない典型的な例でした。

なんで横のつながりでサクッといかないんでしょうかねぇ・・・。

どっかの大きな組織のようですねぇ。w

それにしても、Pythonまじ便利。

import win32com.client
from win32com.client import constants

try:

	# Applicationを短縮
	app = Application
	selist = []

	oCmp = app.GetValue("SelectionList")
	clstype = ''

	# 選択したオブジェクト分だけ回す
	for oSel in oCmp:
		oObj = oSel.SubComponent.Parent3DObject
		# print oSel.SubComponent.Parent3DObject
		# 選択された頂点毎に調査
		for oSubcmp in oSel.SubComponent.ComponentCollection:
			# print oSubcmp.index

			# 選択対象のタイプを絞る(ていうかサブコンポーネントクラスタのタイプ名が違うのはなんで??)
			if str(oSubcmp) == 'Vertex':
				clstype = 'pnt'
			elif str(oSubcmp) == 'PolygonFace':
				clstype = 'poly'
			elif str(oSubcmp) == 'Edge':
				clstype = 'edge'
				
			# 選択した頂点がクラスタの中に存在しているか調査
			for oCls in oObj.ActivePrimitive.Geometry.Clusters:
				# クラスタタイプ調査
				if clstype == oCls.type:
					# リストに調査クラスタが入っていないか?
					if selist.count(str(oCls)) == 0:
						myElem = oCls.Elements
						a = 0
						# print '-cluster elements ' + oCls.type
						while a < len(myElem):
							# print myElem(a)
							if oSubcmp.index == myElem(a):
								# print clstype + '==' + oCls.type
								print oCls
								selist.append(str(oCls))
								break
							a = a + 1
							
	# print '選択対象確認 ' + selist
	app.SelectObj(selist, "", "")
	
except:
	print 'エラー!'

デュプリケイトシンメトリーフロムオブジェクトPythonソン

JunkiTheJunkieさんの「SIのシンメトリコピーってローカルが無いのか?」という呟きを元に、折角なのでPythonScriptの勉強をかねて作ってみました。
っていうかPython勉強用の備忘録ではじめたの忘れてたw
内容は対象複製したものをピックしたオブジェクトとの座標別の距離を測って反対側に持っていく・・・っていうだけですが、SIのPythonの癖が少し入っているので参考までに…。

import win32com.client
from win32com.client import constants

# Applicationを短縮
app = Application

# XSIDialogをPythonで使える形に
xsidial = win32com.client.Dispatch( "XSIDial.XSIDialog" )
res = xsidial.ComboEx( 'title', ["XY Plane (z=0)","XZ Plane (y=0)","YZ Plane (x=0)"], 2 )

# キャンセルだとresに-1が入るのでその際は終了
if res is not -1:
	oColl = app.GetValue("SelectionList")
	
	# DuplicateSymmetryの基点Planeの設定を決定
	cp = [0,0,1]
	if res == 1:
		cp = [0,1,0]
	elif res == 2:
		cp = [1,0,0]
		
	# Pythonでは出力引数をサポートしていないのでタプルを利用して変数を組む(クリックされたボタン、修飾キー、ピックオブジェクト)
	# 対象基点にするオブジェクトをピックで選択させる
	oBtn,oMod,oPicked = app.PickObject( 'Pick CenterObject...', 'Pick CenterObject...' )
	# 基点オブジェクトのGlobalのポジションを取得
	ctrgpos = [ app.GetValue(oPicked.Kinematics.Global.Parameters("posx")),
				app.GetValue(oPicked.Kinematics.Global.Parameters("posy")),
				app.GetValue(oPicked.Kinematics.Global.Parameters("posz"))]
	# app.Logmessage( 'Picked : ' + str(oPicked) )
	# app.Logmessage( 'Modify Key : ' + str(oMod) )
	# 基点オブジェクトをピック時にCtrlを押していたら親共有モード
	pmod = ""
	if oMod == 2:
		pmod = True
	
	# 選択オブジェクトを繰り返す
	for oSel in oColl:
		# 複製オブジェクトのGlobalのポジションを取得
		orggpos = [ app.GetValue(oSel.Kinematics.Global.Parameters("posx")),
					app.GetValue(oSel.Kinematics.Global.Parameters("posy")),
					app.GetValue(oSel.Kinematics.Global.Parameters("posz"))]
		# DuplicateSymmetryはそのまま使用
		oDup = app.DuplicateSymmetry(oSel, "", pmod, cp[0], cp[1], cp[2], 0, "")
		app.Logmessage( 'Picked : ' + str(oDup) )
		if cp[0] == 1:
			app.SetValue(str(oDup)+'.kine.global.posx',(ctrgpos[0] - (orggpos[0] - ctrgpos[0])))
		elif cp[1] == 1:
			app.SetValue(str(oDup)+'.kine.global.posy',(ctrgpos[1] - (orggpos[1] - ctrgpos[1])))
		elif cp[2] == 1:
			app.SetValue(str(oDup)+'.kine.global.posz',(ctrgpos[2] - (orggpos[2] - ctrgpos[2])))

・・とまぁ観てお分かりかとおもいますが、SIでのPythonはコマンドの出力引数をサポートしていないので、変わりにタプル変数を使うとか、XSIDialogを使うときはwin32com.clientをインポートしてDspatchするとかあたりがVBSやJAVAスクリプトとかと勝手が違うところかな??

Shatterもどき??

今日Twitterを通じてほろにがさんの記事を読んで、ふむふむ、前半はこういうことかな?

http://www.dfx.co.jp/dftalk/?p=757

とSoftimage用のスクリプトで起こしてみました。
これを切り刻む分だけ繰り返せばいいのかな?

今回はVBSですが・・・w

Dim ret
Dim oCol, oSel
' オブジェクトを選択
Set oCol = GetValue("SelectionList")

for each oSel in oCol
	Logmessage "Cutting : " & oSel
	' 選択オブジェクトのバウンディングボックス座標を取得
	GetBBox oSel, FALSE, xmin, ymin, zmin, xmax, ymax, zmax
	
	' 選択オブジェクトのXYZそれぞれの長さを計算
	Dim xLen, yLen, zLen 
		ret = Abs(xmax - xmin)
		if ret = 0 then ret = 0.1
		xLen = ret
		ret = Abs(ymax - ymin)
		if ret = 0 then ret = 0.1
		yLen = ret
		ret = Abs(zmax - zmin)
		if ret = 0 then ret = 0.1
		zLen = ret
	 
	Logmessage "BBoox : " & xmin&", "&ymin&", "&zmin&", "&xmax&", "&ymax&", "&zmax
	
	' スライス用のGridを生成
	Dim oSliceGrid
	Set oSliceGrid = CreatePrim( "Grid", "MeshSurface" )
	GetBBox oSliceGrid, FALSE, sxmin, symin, szmin, sxmax, symax, szmax

	' スライス用のGridのサイズを計算して、選択オブジェクトのサイズより大きくなるようにする(2倍ぐらい?)
	Dim sXlen, sYlen, sZlen, sclX, sclY, sclZ
		ret = Abs(sxmax - sxmin)
		if ret = 0 then ret = xLen
		sXlen = ret
		ret = Abs(symax - symin)
		if ret = 0 then ret = yLen
		sYlen = ret
		ret = Abs(szmax - szmin)
		if ret = 0 then ret = zLen
		sZlen = ret
		 
		sclX = (xLen / sXlen) * 2
		sclY = (yLen / sYlen) * 2
		sclZ = (zLen / sZlen) * 2
	 
	Scale oSliceGrid ,sclX,sclY,sclZ, siRelative, siLocal, siObj, siXYZ, , , , , , , , 0
	' ブーリアンを安定化するためにGridを三角形化
	ApplyTopoOp "TriangulatePolygons", oSliceGrid, siUnspecified, siPersistentOperation
	
	' Gridの頂点をランダマイズで波打たせ〜
	Dim oP
	Set oP = ApplyOp("Randomize", oSliceGrid, 3, siPersistentOperation, , 0)
	Logmessage oP
	SetValue oP & ".amply", 0.01
	SetValue oP & ".amply", 1
	SetValue oP & ".amplz", 1

	' Gridを使って選択をブーリアン、法線を反転させ、ブーリアン
	ApplyTopoOp "BooleanDifference", oSel & ";" & oSliceGrid, 3, siPersistentOperation
	Set oDup = Duplicate( oSel, , 2, 1, 1, 0, 0, 1, 0, 1, , , , , , , , , , , 0 )
	FreezeModeling oDup
	ApplyTopoOp "Inverse", oSliceGrid, 3, siPersistentOperation
	Set oDup = Duplicate( oSel, , 2, 1, 1, 0, 0, 1, 0, 1, , , , , , , , , , , 0 )
	FreezeModeling oDup

next

IllustratorでVBS2

TextFramesの動作がおかしいって今まで悩んでいたのがバカみたいです・・・

こっちの方が確実で、効果的でした。orz...

Set appRef = CreateObject("Illustrator.Application.4") 

For Each pItem in appRef.ActiveDocument.PageItems
	If pItem.PageItemType = 10 Then
		pItem.CreateOutline
	End If
Next

ActiveDocument.PageItemsプロパティを使うと、ドキュメント内のオブジェクトを階層関係なしにごっそり取得できます。
その中からPageItemTypeで検査をかけて、文字オブジェクトを判別し、アウトライン化すればよかった…。

※それにしても、ForでItemsのコレクションを回した時に、ループ処理の途中で個数の整合性が合わなくなる?(もしくは入れ替わる?)
結果処理が不明のエラーでとまってしまうのをうまく回避するコツってあるのかナァ・・・

IllustratorでVBS

しばらく家ではIllustratorVBScriptを書いているのでPythonは一旦休止。
といっても1ヶ月くらいで再開するけど・・・w

とりあえず長い間なぞの動作をしていたTextFramesからTextFrameを取得すると、取得できない(処理から飛ばされる)TextFrameが存在するバグの回避策が分かりました。
:例

For Each oTxt in oLayer.TextFrames
	If oTxt.Contents <> "" Then
	flag = true
	for each t in colTxtFrames
		if t.Contents = oTxt.Contents then
			flag = false
		end if
	next
	if flag then
		Redim Preserve colTxtFrames(i)
			Set colTxtFrames(i) = oTxt
			i = i + 1
	end if
	End If
Next

といった感じで配列に一度テキストフレームを全て入れてから(内容が同じのを引っ張ってくることがあるので、内容が同じだったらいらないってする)、外でその配列をもう一回Forで回して例えばOutlineにするとか・・・・。