付け焼き刃的なスクリプトのままメモ
とりあえず、円周上に等間隔に整列するようにしてみました。

ズレる時はローカルで回転させてあわせてます。
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 件のコメント:
コメントを投稿