#!BPY """ Registration info for Blender menus: Name: 'Kloputils 3' Blender: 234 Group: 'Wizards' Tip: 'Set of object aligning, modifying tools' """ __author__ = "Carlos López (klopez)" __url__ = ("elysiun", "Author's web page, http://klopes.tk", "Script's homepage, http://www.iespana.es/klopes/enchufes-guiri.htm", "Thread on elYsiun with links to English and Spanish webpage and pdf docs,\ http://www.elysiun.com/forum/viewtopic.php?t=25736") __version__ = "3.1" __bpydoc__ = """\ This Wizard script contains customizable tools to align and modify mesh objects. Edited freely from a post by the author to elYsiun (last link button above): These tools are initially oriented as a help for the general design of objects in 2D and 3D (architecture, industrial...), and this is the paradigm the program will be developed around. The utilities in the program are separated in 4 areas, accessible through the top menu in the GUI: - Alignment:
+ fitting an object between two others;
+ setting to an object the absolute size of another one;
+ aligning selected objects, according to several criteria: location, rotation, scale (scale can be changed either additive or multiplicatively);
+ location separation can be referenced either by centers, baricenters, origins or limits. - Object creation:
+ circunference passing through 3 points;
+ arc passing through 3 points;
+ arc based on angles and radius (interactive). - Mesh modification (affects vertices, faces and edges):
+ edges subdivision in any number of parts;
+ projection onto an arbitrary plane, in an arbitrary direction;
+ transformation of position, rotation, scale values (new matrix) of an object, though it looks unaffected. - 3D objects modifications (affects transform matrices):
+ translating / rotating / scaling randomly the selected objects;
+ moving selected objects closer or away from the active one, setting them at a fixed distance or translating by a fixed or proportional value. Notes:
All numeric / vectorial values used during the program can be copied and pasted with the help of a buffer, which can contain: a position vector, an Euler list or a scaling vector and can store: numbers entered by user, values acquired from objects (matrices averages, distances, differences of position or rotation angles between two objects). Buffer contents can also be pasted to the console window as text. Usage: Open the script from the "Scripts->Wizards" menu of the Scripts window, then one choose from the available languages. The script has a GUI where specific tools can be selected and configured before being applied. Notes:
Kloputils has many useful tools. To get a better idea of what it can do, besides reading the tooltips for each button, users can check its online documentation. """ # $Id$ # ################################################## # # # KLOPUTILES v3.1 para Blender v2.33 # # multilingue # # # ################################################## # Pulsa Alt+P para ejecutar el script # Improved: use of Mathutils # Feature: actualize objects on ApplyLRS # Improved: Project onto planes # Feature: mover/rotar/escalar objetos al azar # Feature: acercar objs al activo (fijo, abs, rel) # Improved: Fit/Embrace # TODO: subdividir solo aristas seleccionadas (NO FUNCIONA) # TODO: Elipses # ################################################## # # -------------------------------------------------------------------------- # Kloputils by Carlos López (klopez) # -------------------------------------------------------------------------- # ***** BEGIN GPL LICENSE BLOCK ***** # # Copyright (C) 2004: Carlos López, http://klopes.tk # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software Foundation, # Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # ***** END GPL LICENCE BLOCK ***** # -------------------------------------------------------------------------- import Blender from Blender.Mathutils import * from Blender.NMesh import * from Blender.BGL import * from Blender.Draw import * from Blender.sys import * from Blender.Noise import random from math import * #path=dirname(progname) #path=[dirname(progname),'.blender','bpydata'] path=Blender.Get("datadir") if not path: errmsg = "\nNo bpydata/ dir found! It should be in Blender's home dir." raise IOError, errmsg sc=Blender.Scene.GetCurrent() MId=Matrix([1,0],[0,1]) MId.resize4x4() coo=['X','Y','Z'] l=PupMenu('Choose language%t|Espanol%x1|English%x2|Catala%x3') Lang=['Espanol','English','Catala'][l-1] #Buffer: BfL=[0.,0.,0.] BfR=[0.,0.,0.] BfS=[1.,1.,1.] pagina=Create(1) creake=Create(1) editake=Create(2) moveke=Create(1) numReal=Create(0.) movekomo=Create(1) menuLRS=Create(1) ndiv=Create(3) akeplano=Create(2) akeplanoXYZ=Create(3) enkedir=Create(3) nLocX=Create(1.0) nLocY=Create(2.0) nLocZ=Create(3.0) nRotX=Create(0.0) nRotY=Create(0.0) nRotZ=Create(0.0) nSizX=Create(1.0) nSizY=Create(1.0) nSizZ=Create(1.0) other=Create(1) ang1=Create(0.0) ang2=Create(30.0) angulo=Create(30.0) radio=Create(1.0) pts=Create(10) ctro=Create(0) meTx=Create('Arc') arcorden=Create(0) CreaNew=Create(1) Cuantos=Create(2) toBuffer=Create(0) menueqiX=Create(1) sepX=Create(0.5) aliX=Create(1) menueqiY=Create(1) sepY=Create(0.0) aliY=Create(0) menueqiZ=Create(2) sepZ=Create(1.0) aliZ=Create(0) girX=Create(0) incX=Create(0.0) girY=Create(0) incY=Create(0.0) girZ=Create(1) incZ=Create(5.0) scaX=Create(1) iScaX=Create(.5) scaY=Create(1) iScaY=Create(.5) scaZ=Create(1) iScaZ=Create(.5) encX=Create(1) encY=Create(0) encZ=Create(0) en2X=Create(1) en2Y=Create(0) en2Z=Create(0) def CreaObjDeMalla(mm,o,nombre): oo=Blender.Object.New('Mesh') oo.link(mm) oo.setName(nombre) oo.LocX,oo.LocY,oo.LocZ=o.LocX,o.LocY,o.LocZ oo.RotX,oo.RotY,oo.RotZ=o.RotX,o.RotY,o.RotZ oo.SizeX,oo.SizeY,oo.SizeZ=o.SizeX,o.SizeY,o.SizeZ sc.link(oo) return oo def rectang(x,y,l,h,r,g,b): glColor3f(r,g,b) glBegin(GL_POLYGON) glVertex2i(x, y) glVertex2i(l, y) glVertex2i(l, h) glVertex2i(x, h) glEnd() def SituaL(objeto,coord,X): if coord==0: objeto.LocX=X elif coord==1: objeto.LocY=X elif coord==2: objeto.LocZ=X def SituaR(objeto,coord,X): if coord==0: objeto.RotX=X elif coord==1: objeto.RotY=X elif coord==2: objeto.RotZ=X def SituaS(objeto,coord,X): if coord==0: objeto.SizeX=X elif coord==1: objeto.SizeY=X elif coord==2: objeto.SizeZ=X def mallaScan(o): return o.getType()=='Mesh' def Sistema(MM,D): MM.invert() return MatMultVec(MM,D) def GloVrt((x,y,z),M): # Devuelve (vector) coords globs de v v=Vector([x,y,z,1]) v=VecMultMat(v,M) v.resize3D() return v def Extremo(lista,M=MId): # Devuelve extremos y pto medio de lista de vectores o1=GloVrt(lista[0],M) o2=GloVrt(lista[0],M) for v in lista: va=Vector(list(v)) va.resize4D() va=VecMultMat(va,M) for c in range(3): o1[c]=min(va[c],o1[c]) o2[c]=max(va[c],o2[c]) return [o1,(o1+o2)/2,o2] def Media(lista): #Media ctr=Vector([0,0,0]) for c in range(3): for l in lista: ctr[c]=ctr[c]+l[c] ctr[c]=ctr[c]/len(lista) return ctr def draw(): global pagina, toBuffer glClearColor(0.4,0.2,0.2,0.0) glClear(GL_COLOR_BUFFER_BIT) pagina=Menu(menu0,98,20,370,170,28,pagina.val,"Select page") toBuffer=Menu(menu4,80,200,370,20,15,toBuffer.val,"Copy values to the internal buffer") glColor3f(0.6,0.6,0.2) glRasterPos2i(198,388) Text("Copy",'small') if (pagina.val==1): draw1() elif (pagina.val==2): draw2() elif (pagina.val==3): draw3() elif (pagina.val==4): draw4() Button(menuExit,99,20,5,200,18) def draw4(): global moveke,o global aliX,aliY,aliZ,numReal,movekomo,menuLRS,menuPaste rectang(15,38,225,264,0.2,0.,0.) moveke=Menu(menu5,98,10,248,200,20,moveke.val,"Modify the matrices of selected objects") if moveke.val==2: aliX=Toggle("X",0, 50,160,45,30,aliX.val,"Activate modification in X") aliY=Toggle("Y",0, 95,160,45,30,aliY.val,"Activate modification in Y") aliZ=Toggle("Z",0,140,160,45,30,aliZ.val,"Activate modification in Z") menuLRS=Menu("Loc%x1|Rot%x2|Size%x3",98,20,110,50,20,menuLRS.val) if moveke.val==1: movekomo=Menu(menu5a,98,20,225,200,20,movekomo.val,"Transformation type") m,M,tip= -100,100,"Quantity" else: if menuLRS.val==1: m,M,tip= -1000, 1000, "Distance" elif menuLRS.val==2: m,M,tip= 0, 360, "Angle" elif menuLRS.val==3: m,M,tip= 0, 100, "Scale" if moveke.val==1 and movekomo.val==3: tip=tip+"Multiplier " if moveke.val==2: tip=tip+" (max)" numReal=Number("",0,20,140,178,18,numReal.val,m,M,tip) glColor3f(0.6,0.6,0.2) glRasterPos2i(200,156) Text("Paste",'small') menuPaste=Menu("Paste...%t|LocX%x1|LocY%x2|LocZ%x3|\Loc\%x4|RotX%x5|RotY%x6|RotZ%x7|SizeX%x8|SizeY%x9|SizeZ%x10" ,88,202,140,20,12,0,"Paste what?") ok=Button("OK",50,80,110,80,20) def draw3(): global editake,ndiv,akeplano,akeplanoXYZ,enkedir,ok global other global getlocrotsiz,ok,nLocX,nLocY,nLocZ global nRotX,nRotY,nRotZ,nSizX,nSizY,nSizZ global Cloc,Ploc,Crot,Prot,Csiz,Psiz rectang(15,38,225,264,0.3,0.7,0.5) editake=Menu(menu3,98,10,248,143,20,editake.val,"Mesh editing menu") if(editake.val==1): ndiv=Number(menu3a,98,20,200,150,18,ndiv.val,2,1000) ok=Button("OK",20,172,200,32,18) elif(editake.val==2): akeplano=Menu(menu3b,98,20,200,140,20,akeplano.val) if akeplano.val in [1,2]: akeplanoXYZ=Menu(menu3c,98,162,200,55,20,akeplanoXYZ.val) enkedir=Menu(menu3d,98,20,100,140,20,enkedir.val) ok=Button("OK",40,162,100,55,20) elif(editake.val==3): Button("P",87,192,222,30,18,"Paste buffer matrix") nLocX=Number("LocX:",98,20,200,170,19,nLocX.val,-1000.,1000.) nLocY=Number("LocY:",98,20,180,170,19,nLocY.val,-1000.,1000.) nLocZ=Number("LocZ:",98,20,160,170,19,nLocZ.val,-1000.,1000.) nRotX=Number("RotX:",98,20,140,170,19,nRotX.val,-1000.,1000.) nRotY=Number("RotY:",98,20,120,170,19,nRotY.val,-1000.,1000.) nRotZ=Number("RotZ:",98,20,100,170,19,nRotZ.val,-1000.,1000.) nSizX=Number("SizeX:",98,20, 80,170,19,nSizX.val,-1000.,1000.) nSizY=Number("SizeY:",98,20, 60,170,19,nSizY.val,-1000.,1000.) nSizZ=Number("SizeZ:",98,20, 40,170,19,nSizZ.val,-1000.,1000.) other=Toggle("Refresh others",98,20,222,170,18,other.val) oklocrotsiz=Button("OK",30,192,40,30,179) def draw2(): global creake,ang1,ang2,angulo,radio,pts,ctro,meTx,arcorden rectang(15,65,224,257,0.7,0.5,0.65) creake=Menu(menu2,98,10,248,143,20,creake.val,"Object type") if(creake.val==1): pts=Number(menu2a[0],98,20,115,80,18,pts.val,2,1000) ctro=Toggle(menu2a[1],98,102,115,50,18,ctro.val,"Close the arc with a vertex on its center") arcorden=Menu(menu2a[2]+"%t|1-2-3%x1|2-3-1%x2|3-1-2%x3",17,155,115,65,18,arcorden.val,"Vertices order (arc is created when this is chosen)") meTx=String("Object: ",98,20,70,200,22,meTx.val,30,"New object's name") if(creake.val==2): ang1=Slider(menu2a[4],10,20,220,200,18,ang1.val,-360,360,0,"Initial angle in degrees") ang2=Slider(menu2a[5],11,20,200,200,18,ang2.val,ang1.val,ang1.val+360,0,"Final angle in degress") angulo=Slider(menu2a[6],12,20,170,200,18,angulo.val,-360,360,0,"Arc's angle in degress") radio=Slider(menu2a[7],13,20,140,200,18,radio.val,0,1,0) pts=Number(menu2a[8],14,20,115,80,18,pts.val,2,1000) ctro=Toggle(menu2a[9],15,102,115,50,18,ctro.val,"Close the arc with a vertex on its center") meTx=String(menu2a[10],16,20,70,200,22,meTx.val,30,"Name of the mesh to substitute") if(creake.val==3): pts=Number("Pts:",98,20,115,80,18,pts.val,2,1000) ok=Button("OK",18,102,115,120,36) meTx=String("Object: ",98,20,70,200,22,meTx.val,30,"New object's name") def draw1(): global menueqiX,sepX,aliX,menueqiY,sepY,aliY,menueqiZ,sepZ,aliZ global girX,incX,girY,incY,girZ,incZ global encX,encY,encZ,en2X,en2Y,en2Z global scaX,scaY,scaZ,iScaX,iScaY,iScaZ global CreaNew,Cuantos,toBuffer ######################### ALINEACIONES ##################### rectang(5,167,254,292,0.7,0.5,0.65) Button("C",81,194,270,25,18,"Copy") Button("P",82,220,270,25,18,"Paste buffer Loc") aliX=Toggle("X",0,10,270,30,18,aliX.val,"Activate X alignment") menueqiX=Menu(menu1b,98,41,270,148,18,menueqiX.val,"Separation extremes") sepX=Number(menu1a[4],0,10,250,179,18,sepX.val,-1000,1000,"X separation distance") aliY=Toggle("Y",0,10,230,30,18,aliY.val,"Activate Y alignment") menueqiY=Menu(menu1b,98,41,230,148,18,menueqiY.val,"Separation extremes") sepY=Number(menu1a[4],0,10,210,179,18,sepY.val,-1000,1000,"Y separation distance") aliZ=Toggle("Z",0,10,190,30,18,aliZ.val,"Activate Z alignment") menueqiZ=Menu(menu1b,98,41,190,148,18,menueqiZ.val,"Separation extremes") sepZ=Number(menu1a[4],0,10,170,179,18,sepZ.val,-1000,1000,"Y separation distance") ########################## GIROS ############################## rectang(5,97,254,162,0.67,0.54,0.1) Button("C",83,194,140,25,18,"Copy") Button("P",84,220,140,25,18,"Paste buffer Rot") girX=Toggle("X",0,10,140,30,18,girX.val,"Increment RotX values") incX=Number("X: ",0,42,140,147,18,incX.val,-180,180,"X increment in degress") girY=Toggle("Y",0,10,120,30,18,girY.val,"Increment RotY values") incY=Number("Y: ",0,42,120,147,18,incY.val,-180,180,"Y increment in degrees") girZ=Toggle("Z",0,10,100,30,18,girZ.val,"Increment RotZ values") incZ=Number("Z: ",0,42,100,147,18,incZ.val,-180,180,"Z increment in degrees") ######################### ESCALADOS ########################## rectang(5,27,254,92,0.27,0.54,0.4) Button("C",85,194,70,25,18,"Copy") Button("P",86,220,70,25,18,"Paste buffer Sca") scaX=Toggle("X",0,10,70,30,18,scaX.val) iScaX=Number(menu1a[7],0,42,70,147,18,iScaX.val,-180,180,"X scale increment") scaY=Toggle("Y",0,10,50,30,18,scaY.val) iScaY=Number(menu1a[7],0,42,50,147,18,iScaY.val,-180,180,"Y scale increment") scaZ=Toggle("Z",0,10,30,30,18,scaZ.val) iScaZ=Number(menu1a[7],0,42,30,147,18,iScaZ.val,-180,180,"Z scale increment") ########################## ENCAJES ########################## rectang(5,317,254,363,0.1,0.5,0.6) encX=Toggle(menu1a[0]+"X",0,10,340,43,18,encX.val,"Move object in X") encY=Toggle(menu1a[0]+"Y",0,55,340,43,18,encY.val,"Move object in Y") encZ=Toggle(menu1a[0]+"Z",0,100,340,43,18,encZ.val,"Move object in Z") en2X=Toggle(menu1a[1]+"X",0,10,320,43,18,en2X.val,"Adjust X size") en2Y=Toggle(menu1a[1]+"Y",0,55,320,43,18,en2Y.val,"Adjust Y size") en2Z=Toggle(menu1a[1]+"Z",0,100,320,43,18,en2Z.val,"Adjust Z size") ###################################################### CreaNew=Toggle(menu1a[8],98,10,295,129,18,CreaNew.val,"Create new objects or just modify selected?") if CreaNew.val: Cuantos=Number('',98,139,295,30,18,Cuantos.val,1,999,"Number of copies") Button(menu1a[5],1,190,170,60,98,"Align") #Alinea Button(menu1a[6],2,190,100,60,38,"Rotate") #Gira Button(menu1a[9],3,190,30,29,38,"Scale +") #Escala+ Button(menu1a[10],7,220,30,30,38,"Scale *") #Escala* Button(menu1a[2],6,147,320,45,38,"Fit active in one or two others using max limits (creates new object)") #Encaja Button(menu1a[3],5,195,320,55,38,"Fit active in one or two others using min limits (creates new object)") #Abarca def HaceArco(pts,ang1,angul,ctro,R): me=New() for c in range(pts): alfa=(ang1+angul*c/(pts-1))*pi/180 if (c): v1=v v=Vert() v.co[0]=R*cos(alfa) v.co[1]=R*sin(alfa) v.co[2]=0 me.verts.append(v) if (c): f=Face() f.v=[v1] f.v.append(v) me.faces.append(f) if (c==0): v0=v if(ctro): v1=v v=Vert() me.verts.append(v) f=Face() f.v=[v1,v] me.faces.append(f) f=Face() f.v=[v,v0] me.faces.append(f) return me def Exec_align(os,c,ali,eqi,sep): coor=os[0].loc[c] ademas=0 flag=0 for o in os: m=o.data #Maya del objeto ctr=[0,0,0] if(eqi[c]==2): for d in range(3): ctr[d]=Extremo(m.verts,o.matrix)[1][d] elif(eqi[c]==3 or eqi[c]==6): ctr=Extremo(m.verts,o.matrix)[0] elif(eqi[c]==4): ctr=Extremo(m.verts,o.matrix)[2] elif(eqi[c]==5): ctr=Media(m.verts) ctr=GloVrt(ctr,o.matrix) if (eqi[c]>1): ademas=ctr[c]-o.loc[c] if (flag): coor=coor-ademas else: flag=1 SituaL(o,c,coor) if(eqi[c]==6): ademas=Extremo(m.verts,o.matrix)[2][c]-o.loc[c] coor=coor+sep[c]+ademas def event(evt,val): if (evt==ESCKEY and not val): print "Bye..." Exit() #@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@22# def bevent(evt): global me global BfL,BfR,BfS #print "Event:",evt os=Blender.Object.GetSelected() if os: oa=os[0] ##########MENU BUFFER if evt==80: copi=toBuffer.val if copi==1: if len(os)==2: for c in range(3): BfL[c]=os[1].loc[c]-os[0].loc[c] print "Copied to Loc buffer:",BfL else: PupMenu('ERROR%t|Selecciona 2 objetos|Just select 2 objects!') if copi==2: if len(os)==2: BfL=3*[sqrt((os[1].loc[0]-os[0].loc[0])**2+ (os[1].loc[1]-oa.loc[1])**2+ (os[1].loc[2]-oa.loc[2])**2)] print "Copied to Loc buffer:",BfL else: PupMenu('ERROR%t|Selecciona 2 objetos|Just select 2 objects!') if copi==3: if len(os)==2: for c in range(3): BfR[c]=os[1].rot[c]-oa.rot[c] print "Copied to Rot buffer:",BfR else: PupMenu('ERROR%t|Selecciona 2 objetos|Just select 2 objects!') if copi==4 and len(os): lista=[] for o in os: lista.append(o.loc) BfL=Media(lista) print "Copied to Loc buffer:",BfL lista=[] for o in os: lista.append(o.rot) BfR=Media(lista) for c in range(3): BfR[c]*=180/pi print "Copied to Rot buffer:",BfR lista=[] for o in os: lista.append(o.size) BfS=Media(lista) print "Copiado to Size buffer:",BfS if copi==5: print"\n_Buffer contents_\n" for c in range(3): print "Loc",coo[c]," :",BfL[c] for c in range(3): print "Rot",coo[c]," :",BfR[c] for c in range(3): print "Size",coo[c],":",BfS[c] print "______________________" ##########COPY if evt==81: X =[sepX.val,sepY.val,sepZ.val] ali =[aliX.val,aliY.val,aliZ.val] for c in range(3): if ali[c]: BfL[c]=X[c] print"Copying to Loc buffer",coo[c],"value", BfL[c] if evt==83: X =[incX.val,incY.val,incZ.val] ali =[girX.val,girY.val,girZ.val] for c in range(3): if ali[c]: BfR[c]=X[c] print"Copying to Rot buffer",coo[c],"value", BfR[c] if evt==85: X =[iScaX.val,iScaY.val,iScaZ.val] ali =[scaX.val,scaY.val,scaZ.val] for c in range(3): if ali[c]: BfS[c]=X[c] print"Copying to Size buffer",coo[c],"value", BfS[c] ##########PASTE if evt==82: X =[sepX.val,sepY.val,sepZ.val] ali =[aliX.val,aliY.val,aliZ.val] for c in range(3): if ali[c]: X[c]=BfL[c] print"Retrieving from buffer Loc",coo[c],"value", BfL[c] sepX.val,sepY.val,sepZ.val=X if evt==84: X =[incX.val,incY.val,incZ.val] ali =[girX.val,girY.val,girZ.val] for c in range(3): if ali[c]: X[c]=BfR[c] print"Retrieving from buffer Rot",coo[c],"value", BfR[c] incX.val,incY.val,incZ.val=X if evt==86: X =[iScaX.val,iScaY.val,iScaZ.val] ali =[scaX.val,scaY.val,scaZ.val] for c in range(3): if ali[c]: X[c]=BfS[c] print"Retrieving from buffer Size",coo[c],"value", BfS[c] iScaX.val,iScaY.val,iScaZ.val=X if evt==87: print"Retrieving matrix" nLocX.val,nLocY.val,nLocZ.val=BfL nRotX.val,nRotY.val,nRotZ.val=BfR nSizX.val,nSizY.val,nSizZ.val=BfS if evt==88: print"Retrieving float number to button" x=[BfL[0],BfL[1],BfL[2], sqrt(BfL[0]**2+BfL[1]**2+BfL[2]**2), BfR[0],BfR[1],BfR[2], BfS[0],BfS[1],BfS[2]] numReal.val = x[menuPaste.val-1] if evt==50: if moveke.val==1: # MOVER HACIA EL O.ACTIVO oaV=Vector(list(oa.loc)) for o in os[1:]: oV=Vector(list(o.loc)) v=oV-oaV #Calculo del vector final d=sqrt(DotVecs(v,v)) v1=v*numReal.val if movekomo.val==1: v1 = oaV+v1/d elif movekomo.val==2: v1 = oV+v1/d elif movekomo.val==3: v1 = oaV+v1 o.setLocation(v1) if moveke.val==2: # MOVER AL AZAR n=numReal.val if menuLRS.val==2: n=n*pi/180 for o in os: v1=Vector([ aliX.val * (2*n*random() - n), aliY.val * (2*n*random() - n), aliZ.val * (2*n*random() - n)]) if menuLRS.val==1: #Uso del vector final oV=Vector(list(o.loc)) o.setLocation(oV+v1) elif menuLRS.val==2: v=Vector(list(o.getEuler()))+v1 o.setEuler(v) else: oV=Vector(list(o.size)) o.setSize(oV+v1) if evt==40: # PROYECTA EN PLANOS n=Vector([0.,0.,0.]) numObjs=-len(os)+1 if akeplano.val==1: #plano global n[akeplanoXYZ.val-1]=1. numObjs=-len(os) elif akeplano.val==2: n=oa.matrix[akeplanoXYZ.val-1] #plano local n.resize3D() d=Vector([0.,0.,0.]) if enkedir.val<4: d[enkedir.val-1]=1. #direccion global elif enkedir.val==4: d=n #direc. ortog. al plano n1 = Vector([-n[2],n[0],n[1]]) N1 = CrossVecs (n,n1) N2 = CrossVecs (n,N1) n.normalize(), N1.normalize(), N2.normalize() #print"productos escalares (deben ser 0):",DotVecs(N1,n),DotVecs(N2,n),DotVecs(N2,N1) p=oa.loc N=Matrix( [N1[0],N1[1],N1[2],0], [N2[0],N2[1],N2[2],0], [ n[0], n[1], n[2],0], [ p[0], p[1], p[2],1]) NI=CopyMat(N) NI.invert() dN=VecMultMat(d,NI.rotationPart()) if dN[2]==0: PupMenu('Error%t|Operacion no permitida: la direccion esta en el plano%x1|Illegal operation: plane contains direction%x2') return print"Absolute direction:",d,"\nPlane normal:",n,"\nRelative direction:",dN for o in filter(mallaScan,os[numObjs:]): me=Blender.NMesh.GetRawFromObject(o.name) M=o.matrix for v in me.verts: v0=Vector([v[0],v[1],v[2]]) v0=GloVrt(v0,M) v0.resize4D() v0=VecMultMat(v0,NI) v[0] = v0[0] - v0[2]/dN[2] * dN[0] v[1] = v0[1] - v0[2]/dN[2] * dN[1] v[2] = 0 oo=Blender.Object.New('Mesh') oo.setName(o.name+'Proy') oo.link(me) sc.link(oo) oo.setMatrix(N) if(evt>9 and evt<17): # HACE ARCO INTERACTIV. GetRaw(meTx.val) if(evt==11): angulo.val=ang2.val-ang1.val if(evt==12 or evt==10): ang2.val=(ang1.val+angulo.val) m=HaceArco(pts.val,ang1.val,angulo.val,ctro.val,radio.val) PutRaw(m,meTx.val) if evt in [17,18]: # HACE ARCO CON 3 PTS. o=oa m=o.getData() M=o.matrix if arcorden.val==1 or evt==18: p1,p2,p3=m.verts[0],m.verts[1],m.verts[2] elif arcorden.val==2: p1,p2,p3=m.verts[1],m.verts[2],m.verts[0] elif arcorden.val==3: p1,p2,p3=m.verts[2],m.verts[0],m.verts[1] p1=GloVrt(p1,M) p2=GloVrt(p2,M) p3=GloVrt(p3,M) print "Points:\n ",p1,p2,p3 p21=p2-p1 p31=p3-p1 M1=CrossVecs(p21,p31) D=DotVecs(M1,p1) D2=DotVecs(p21,p1+p2)/2 D3=DotVecs(p31,p1+p3)/2 SS=Matrix( [M1[0],M1[1],M1[2]], [p21[0],p21[1],p21[2]], [p31[0],p31[1],p31[2]], ) O=Sistema(SS,Vector([D,D2,D3])) v2=p2-O b3=p3-O vN=CrossVecs(v2,b3) v3=CrossVecs(v2,vN) #Terna ortogonal: v2,vN,v3 R=sqrt(DotVecs(v2,v2)) RN=sqrt(DotVecs(vN,vN)) R3=sqrt(DotVecs(v3,v3)) if evt==18: angul=2*pi else: angul=AngleBetweenVecs(v2,b3) print "Center:",O print "Radius :",R,"RN:",RN,"R3:",R3 print "Angle:",angul M2=Matrix([v2[0]/R,v2[1]/R,v2[2]/R],[-v3[0]/R3,-v3[1]/R3,-v3[2]/R3],[vN[0]/RN,vN[1]/RN,vN[2]/RN]) arco=HaceArco(pts.val,0,angul,ctro.val,1) oo=CreaObjDeMalla(arco,o,meTx.val+'.In') EU=M2.toEuler() EU=EU[0]*pi/180,EU[1]*pi/180,EU[2]*pi/180 oo.RotX,oo.RotY,oo.RotZ=EU[0],EU[1],EU[2] oo.setLocation(O) oo.setSize(R,R,R) if evt==17: angul=angul-360 arco=HaceArco(pts.val,0,angul,ctro.val,1) oo=CreaObjDeMalla(arco,o,meTx.val+'.Ex') oo.RotX,oo.RotY,oo.RotZ=EU[0],EU[1],EU[2] oo.setLocation(O) oo.setSize(R,R,R) if(evt==20): # SUBDIVIDE for o in filter(mallaScan,os): m=o.data mm=New() mm.name=m.name+'.Subdiv' for v in m.verts: mm.verts.append(v) N=ndiv.val NV=len(m.verts)-1 for k1 in range(NV+1): v1=m.verts[k1] for k2 in range(NV-k1): v2=m.verts[NV-k2] for f in m.faces: if (v1 in f.v) and (v2 in f.v): # SI... dif=abs(f.v.index(v2)-f.v.index(v1)) if dif==1 or dif==len(f.v)-1: #...entonces f contiene la arista v1-v2 v=v1 for K in range(N): cara=Face() cara.v.append(v) if K1): n1=Extremo(os[1].data.verts,os[1].matrix)[0][c] m1=Extremo(os[1].data.verts,os[1].matrix)[2][c] if (len(os)>2): n2=Extremo(os[2].data.verts,os[2].matrix)[0][c] m2=Extremo(os[2].data.verts,os[2].matrix)[2][c] n0=Extremo(meVs)[0] [c] m0=Extremo(meVs)[2] [c] ancho=m0-n0 pm=(m0+n0)/2 if (len(os)==1): n1,m1=n0,m0 if (len(os)<3): n2,m2=n1,m1 if (n2