SIを使う人はもうないだろうから、
付け焼き刃的なスクリプトのままメモ
とりあえず、円周上に等間隔に整列するようにしてみました。
ズレる時はローカルで回転させてあわせてます。
Sorce
#AligenCircle
#
# 02 28 2015 ver 0.1
#
# 選択がまだ甘いがポイント選択状態だと動く
#
# ベクトルは選択したポイントの平均
# 中心はBBOX ,半径は一番遠いポイントまでの距離の設定になっている
app = Application; log = app.LogMessage
oCmdLog = app.Dictionary.GetObject( "preferences.scripting" )
userPref = oCmdLog.cmdlog.value
oCmdLog.cmdlog.value = False
import math
from win32com.client import constants as c
DEBUG = True
CUSTOM_RAD = False
CUSTOM_CENTER = False
CUSTOM_NORMAL = False
NORMAL = [1,0,0]
#Select
#Application.SelectGeometryComponents("grid.pnt[30-32,39-41,48-50]")
CENTER = (3,0,-1)
def vLog(v):
return str(str(v.X) + ", " + str(v.Y) + ", " + str(v.Z) + "")
def dLog( str ):
if DEBUG == True:
log(str)
#サークルデータのソート
#---------------------------------------------------
# circleSort
#---------------------------------------------------
def circleSort(Center,pnts):
o = XSIMath.CreateVector3(CENTER[0],CENTER[1],CENTER[2])
v = XSIMath.CreateVector3()
idRad = []
for pnt in pnts:
p = pnt.Position
#中心点からのベクトル
v.Sub(p,o)
#vlog(v)
r = math.atan2(-v.Z,v.X)
if DEBUG:#Debg時にはわかりやすいように度表記で
r = int( r / 3.141519 * 180)
idRad.append( [r, pnt.Index] )
idRad.sort()
sortedIDs = []
for i in idRad:
sortedIDs.append(i[1])
dLog(str(i))
dLog("circleSortIDs : " + str(sortedIDs))
return sortedIDs
#---------------------------------------------------
# getWorldPos
#---------------------------------------------------
def getWorldPos( pts, m4 ):
posArray = []
for pnt in pts:
p = pnt.Position
p.MulByMatrix4InPlace(m4)
posArray.append([p.X,p.Y,p.Z])
return posArray
#---------------------------------------------------
# getAveNormal
#---------------------------------------------------
def getAveNormal(pts,m4):
n = XSIMath.CreateVector3()
x = 0
y = 0
z = 0
for pnt in pts:
n = pnt.Normal
#ノーマル座標(逆行列の転地をつかう)
#m4.InvertInPlace()
m4.TransposeInverseInPlace()
n.MulByMatrix4InPlace(m4)
x = x + n.X
y = y + n.Y
z = z + n.Z
num = pts.Count
n.Set( x / num, y / num, z / num)
n.NormalizeInPlace()
return n
#---------------------------------------------------
# getCenter
#---------------------------------------------------
def getCenter():
center = XSIMath.CreateVector3()
bbox = Application.GetBBox()
rad = 0.01
xLength = bbox(3) - bbox(0)
yLength = bbox(4) - bbox(1)
zLength = bbox(5) - bbox(2)
xMid = xLength / 2 + bbox(0)
yMid = yLength / 2 + bbox(1)
zMid = zLength / 2 + bbox(2)
center.Set(xMid,yMid,zMid)
return center
#---------------------------------------------------
# getBBOXRadius
#---------------------------------------------------
def getBBOXRadius():
bbox = Application.GetBBox()
tmp = 0.01
xLength = bbox(3) - bbox(0)
yLength = bbox(4) - bbox(1)
zLength = bbox(5) - bbox(2)
if xLength > tmp:
tmp = xLength
if yLength > tmp:
tmp = yLength
if zLength > tmp:
tmp = zLength
rad = tmp * 0.5
return rad
#---------------------------------------------------
# createCircleMatrix
#---------------------------------------------------
def createCircleMatrix(aID,aPos,normal,center):
circleMatrix = XSIMath.CreateMatrix4()
p = XSIMath.CreateVector3()
v = XSIMath.CreateVector3()
farPos = XSIMath.CreateVector3()
offsetCount = 0
maxLength = 0
for i in range(len(aID)):
p.Set(aPos[i][0],aPos[i][1],aPos[i][2])
v.Sub(p,center)
if maxLength < v.Length():
maxLength = v.Length()
farPos = p
offsetCount = i
x = XSIMath.CreateVector3()
y = XSIMath.CreateVector3()
x.Sub(p,center)
x.NormalizeInPlace()
y.Cross(normal,x)
y.NormalizeInPlace()
circleMatrix.Set(
x.X, x.Y, x.Z, 0,
y.X, y.Y, y.Z, 0,
normal.X, normal.Y, normal.Z, 0,
center.X, center.Y, center.Z, 1)
return circleMatrix,offsetCount
def circleSort2(aID,aPos):
xID = 0
yID = 1
zID = 2
idRad = []
for i in range(len(aID)):
r = math.atan2(aPos[i][yID],aPos[i][xID]) #y,x
r += 0.01
if DEBUG:#Debg時にはわかりやすいように度表記で
r = int( r / 3.141519 * 180)
idRad.append( [r, aID[i],i] )
idRad.sort()
sortedIDs = []
for i in idRad:
sortedIDs.append(i[2])
dLog(str(i))
dLog("circleSortIDs : " + str(sortedIDs))
return sortedIDs
#---------------------------------------------------
# getWorldCirclePointsPositionArray
#---------------------------------------------------
def getWorldCirclePointsPositionArray(aID,aPos,center,radius,circleMatrix,offset):
m4 = XSIMath.CreateMatrix4()
im = XSIMath.CreateMatrix4()
p = XSIMath.CreateVector3()
m4.Invert(circleMatrix)
im.Invert(m4)
circlePositionArray = []
#world to circle
for i in aPos:
p.Set(i[0],i[1],i[2])
p.MulByMatrix4InPlace(m4)
circlePositionArray.append([p.X,p.Y,p.Z])
sortedID = circleSort2(aID,circlePositionArray)
#AligenToLocalCircle
dLog(offset)
segment = len(aID)
for i in range(len(sortedID)):
j = (i + len(sortedID) / 2 ) % len(sortedID)
x = radius * math.cos( j * 1.0 / segment * 2 * math.pi)
y = radius * math.sin( j * 1.0 / segment * 2 * math.pi)
z = 0.0
circlePositionArray[sortedID[i]] = [x,y,z]
#Circle to World
newCirclePositionArray = []
for i in circlePositionArray:
p.Set(i[0],i[1],i[2])
p.MulByMatrix4InPlace(im)
newCirclePositionArray.append([p.X,p.Y,p.Z])
return newCirclePositionArray
#---------------------------------------------------
# main
#---------------------------------------------------
def main():
#Defalt
radius = 1.0
center = XSIMath.CreateVector3(0,0,0)
#if app.Selection().Count < 0:
# return
oSel = app.Selection(0)
oSub = oSel.Subcomponent
obj = oSub.Parent3DObject
oColl = oSub.ComponentCollection
#VertexCollectionから、IndexArrayを取得できないので一度ポイント選択にする
if oSub.Type != "pntSubComponent":#point#
Application.SelectFilter("Edge")
Application.SelectAdjacent("", "Point", False)
oSel = app.Selection(0)
oSub = oSel.Subcomponent
obj = oSub.Parent3DObject
pts = oSub.ComponentCollection
else :
pts = oColl
if pts.Count < 3:
log("selection error")
return
aID = pts.IndexArray
pointNum = pts.Count
normal = XSIMath.CreateVector3(NORMAL[0],NORMAL[1],NORMAL[2])
circleMatrix = XSIMath.CreateMatrix4()
m4 = XSIMath.CreateMatrix4()
im4 = XSIMath.CreateMatrix4()
tm4 = XSIMath.CreateMatrix4()
objectMatrix = obj.Kinematics.Global.Transform.GetMatrix4(m4)
im4.Invert(m4)
offsetCount = 0
#Center
if CUSTOM_CENTER == False:
center = getCenter()
dLog("Center : " + vLog(center))
#Radius
if CUSTOM_RAD == False:
radius = getBBOXRadius()
#Local to Global
aPos = getWorldPos(pts,m4)
#Normal)
if CUSTOM_NORMAL == False:
normal = getAveNormal(pts,m4)
#CircleMatrix,offdetCount(IndexArray)
circleMatrix,offsetCount = createCircleMatrix(aID,aPos,normal,center)
dLog("offsetCount : " + str(offsetCount))
#getNewWorldPos newPositionArray[[x,y,z],[x,y,z]///]
newPosA = getWorldCirclePointsPositionArray(aID,aPos,center,radius,circleMatrix,offsetCount)
#setNewPosition
for i in range(pointNum):
app.Translate(oSel.Name + ".pnt[" + str(aID[i]) + "]", newPosA[i][0], newPosA[i][1], newPosA[i][2], 0, "siView", "siObj", "siXYZ", "", "", "", "", "", "", "", "", "", 0, "")
#dLog(str(aPos))
#dLog("Normal : " + vLog(normal))
return
main()
近況
仕事
・リダクション作業が半分終わり
・キャラクター遅延気味
スクリプト挫折中
・屋根の処理
・電線の処理(カテナリー曲線)
心うきうき成分が足りない :p
0 件のコメント:
コメントを投稿