C4D测量脚本:Python : Aire et volume
Copier le dossier « vonc_airevol » dans le dossier « plugins » du répertoire de Cinéma 4D.
v 1.3 :
- Calcul de multiples objets.
- Mise à jour auto.
- Traduction tchèque par Lubo Bezek.
v 1.2 :
- Corrections mineures.
v 1.1 :
- Possibilité de changer l'unité.
- Prise en compte de l'échelle du document.
Calcule l'aire et le volume :
- d'objets fermés,
- d'objets ouverts,
- de sélections de polygones,
- de tracés (splines).
Fichier .PYP
- import os
- import c4d
- from c4d import gui, plugins, utils, bitmaps, Vector
- from c4d.utils import SendModelingCommand, Neighbor
- from c4d.plugins import GeLoadString as txt
- # César Vonc - code.vonc.fr
- MODULE_ID = 1030057
- VONC_AIRVOL_NOM = 1000
- VONC_AIRVOL_ETAT_0 = 1001
- VONC_AIRVOL_ETAT_1 = 1002
- VONC_AIRVOL_AIRE = 1003
- VONC_AIRVOL_VOLUME = 1004
- VONC_AIRVOL_CALCULER = 1005
- VONC_AIRVOL_POLSEL = 1006
- VONC_AIRVOL_LICENCE = 1007
- VONC_AIRVOL_CLEF = 1008
- VONC_AIRVOL_INFO = 1009
- VONC_AIRVOL_AIDE = 1010
- VONC_AIRVOL_OBJSEL = 1011
- VONC_AIRVOL_SOUSOBJ = 1012
- VONC_AIRVOL_TOTAL = 1013
- VONC_AIRVOL_TOTALE = 1014
- VONC_AIRVOL_MAJ = 1015
- VERSION = "1.3"
- class Airevolume() :
-
- def __init__(self, so) :
- self.objs = None
- self.sousObj = so
- self.aire = 0
- self.volume = 0
- self.sel = 0
- self.nbObj = 0
- self.liObjs = []
- self.liVol = []
- self.liAire = []
-
- self.doc = c4d.documents.GetActiveDocument()
- self.op = self.doc.GetActiveObject()
-
- if so :
- self.objs = self.doc.GetActiveObjects(c4d.GETACTIVEOBJECTFLAGS_0)
- else :
- self.objs = self.doc.GetActiveObjects(c4d.GETACTIVEOBJECTFLAGS_CHILDREN)
-
- def fermeTrous(self, obj, mat) :
- obj.SetMg(mat)
- doc = self.doc
- doc.InsertObject(obj)
- polys = obj.GetAllPolygons()
- n = Neighbor()
- n.Init(obj)
- params = c4d.BaseContainer()
- params[c4d.MDATA_CLOSEHOLE_INDEX] = obj
- params[c4d.MDATA_CLOSEHOLE_TRI] = True
- mode = c4d.MODELINGCOMMANDMODE_EDGESELECTION
- commande = c4d.ID_MODELING_CLOSEHOLE_TOOL
-
- for i, pol in enumerate(polys):
- nab = n.GetNeighbor(pol.a, pol.b, i)
- nbc = n.GetNeighbor(pol.b, pol.c, i)
- ncd = n.GetNeighbor(pol.c, pol.d, i)
- nda = n.GetNeighbor(pol.d, pol.a, i)
- cotes = n.GetPolyInfo(i)["edge"]
-
- if nab == -1:
- params[c4d.MDATA_CLOSEHOLE_EDGE] = cotes[0]
- SendModelingCommand(command=commande, list=[obj], mode=mode, bc=params, doc=doc)
- n.Init(obj)
- if nbc == -1:
- params[c4d.MDATA_CLOSEHOLE_EDGE] = cotes[1]
- SendModelingCommand(command=commande, list=[obj], mode=mode, bc=params, doc=doc)
- n.Init(obj)
- if ((ncd == -1) and (pol.c != pol.d)):
- params[c4d.MDATA_CLOSEHOLE_EDGE] = cotes[2]
- SendModelingCommand(command=commande, list=[obj], mode=mode, bc=params, doc=doc)
- n.Init(obj)
- if nda == -1:
- params[c4d.MDATA_CLOSEHOLE_EDGE] = cotes[3]
- SendModelingCommand(command=commande, list=[obj], mode=mode, bc=params, doc=doc)
- n.Init(obj)
-
- obj.Remove()
- c4d.EventAdd()
- return obj
- def volumeTetraedre(self, p1, p2, p3) :
- return p1.Dot(p2.Cross(p3)) / 6.0
- def aireTriangle(self, A, B, C) :
- vAB = A - B
- vAC = A - C
- return vAB.Cross(vAC).GetLength() * 0.5
-
- def Calcule(self) :
- self.aire = 0
- self.volume = 0
- self.sel = 0
- tab3 = []
- for obj in self.objs :
- conv = SendModelingCommand(command=c4d.MCOMMAND_CURRENTSTATETOOBJECT, list=[obj], doc=self.doc)
- if not conv : continue
- conv = conv[0]
- conv.SetMg(obj.GetMg())
- cache = conv.GetDeformCache() or conv.GetCache() or conv
- cache = cache.GetDeformCache() or cache
- if cache : tab3.append(cache)
-
- self.objs = tab3
-
- if self.sousObj :
- tab = []
- tab2 = []
- for obj in self.objs :
- tab2.append(obj)
- sobj = obj.GetDown()
- if sobj : tab.append(sobj)
- for obj in tab :
- while obj :
- objs = [obj]
- for o in objs :
- tab2.append(o)
- objs.extend(o.GetChildren())
- obj = obj.GetNext()
-
- self.objs = tab2
-
- for obj in self.objs :
- aire, volume = self.CalculeObj(obj)
- self.aire += aire
- self.volume += volume
- if aire or volume :
- self.liObjs.append(obj.GetName())
- self.liAire.append(aire)
- self.liVol.append(volume)
-
- # self.nbObj = len(self.objs)
- self.nbObj = len(self.liObjs)
-
-
- def CalculeObj(self, obj):
- if not obj : return 0, 0
- doc = self.doc
-
- # Si cerce
- if obj.CheckType(c4d.Ospline) :
- peau = c4d.BaseObject(c4d.Oloft)
- obj.GetClone().InsertUnder(peau)
- retour = SendModelingCommand(command=c4d.MCOMMAND_CURRENTSTATETOOBJECT, list=[peau], doc=doc)
- if not retour : return 0, 0
- if retour[0].CheckType(c4d.Opolygon) : obj = retour[0]
- else : obj = retour[0].GetDown()
- if not obj : return 0, 0
-
- if not obj.CheckType(c4d.Opolygon) :
- return 0, 0
-
- # Détache la sélection
- if obj.GetBit(c4d.BIT_ACTIVE) :
- if doc.GetMode() == c4d.Mpolygons :
- bs = obj.GetPolygonS()
- self.sel += bs.GetCount()
- retour = SendModelingCommand(command=c4d.MCOMMAND_SPLIT, list=[obj],
- mode=c4d.MODELINGCOMMANDMODE_POLYGONSELECTION, doc=doc)
- if not retour : return 0, 0
- obj = retour[0]
-
- # Optimise
- params = c4d.BaseContainer()
- params[c4d.MDATA_OPTIMIZE_TOLERANCE] = 0.001
- params[c4d.MDATA_OPTIMIZE_POINTS] = False
- params[c4d.MDATA_OPTIMIZE_POLYGONS] = True
- params[c4d.MDATA_OPTIMIZE_UNUSEDPOINTS] = True
- SendModelingCommand(command=c4d.MCOMMAND_OPTIMIZE, list=[obj], bc=params, doc=doc)
-
- # Ferme les trous
- objVol = self.fermeTrous(obj.GetClone(), obj.GetMg())
-
- # Aligne les normales
- SendModelingCommand(command=c4d.MCOMMAND_ALIGNNORMALS, list=[obj], doc=doc)
- SendModelingCommand(command=c4d.MCOMMAND_ALIGNNORMALS, list=[objVol], doc=doc)
-
- # Triangule
- SendModelingCommand(command=c4d.MCOMMAND_TRIANGULATE, list=[obj], doc=doc)
- SendModelingCommand(command=c4d.MCOMMAND_TRIANGULATE, list=[objVol], doc=doc)
-
- # --
-
- polys = obj.GetAllPolygons()
- pts = obj.GetAllPoints()
- polysVol = objVol.GetAllPolygons()
- ptsVol = objVol.GetAllPoints()
-
- ech = Vector(obj.GetMg().v1.GetLength(), obj.GetMg().v2.GetLength(), obj.GetMg().v3.GetLength())
- pts = [pt.__rxor__(ech) for pt in pts]
- ech = Vector(objVol.GetMg().v1.GetLength(), objVol.GetMg().v2.GetLength(), objVol.GetMg().v3.GetLength())
- # ech = objVol.GetAbsScale()
- ptsVol = [pt.__rxor__(ech) for pt in ptsVol]
-
- aire = 0.0
- for pol in polys :
- aire += self.aireTriangle(pts[pol.a], pts[pol.b], pts[pol.c])
-
- volume = 0.0
- for pol in polysVol :
- volume += self.volumeTetraedre(ptsVol[pol.a], ptsVol[pol.b], ptsVol[pol.c])
-
- volume = abs(volume)
- return aire, volume
-
- class Dialogue(gui.GeDialog):
-
- def __init__(self) :
- self.airevol = None
- self.uniteFin = 0
- self.sousObj = True
- self.majAuto = True
- self.caches = [[],0,0,0,0]
- self.airevol = Airevolume(self.sousObj)
- self.airevol.Calcule()
-
- prefs = c4d.GetWorldContainer()
- unitePref = prefs[c4d.WPREF_UNITS_BASIC]
- self.uniteFin = unitePref
-
- def unite(self, v, valeur) :
- doc = c4d.documents.GetActiveDocument()
-
- donneesDoc = doc.GetData()[c4d.DOCUMENT_DOCUNIT]
- ech, uniteDoc = donneesDoc.GetUnitScale()
-
- uniteFin = self.uniteFin
-
- ufin = ""
- if uniteFin == c4d.UNIT_NONE : ufin = ""
- elif uniteFin == c4d.UNIT_KM : ufin = "km"
- elif uniteFin == c4d.UNIT_M : ufin = "m"
- elif uniteFin == c4d.UNIT_CM : ufin = "cm"
- elif uniteFin == c4d.UNIT_MM : ufin = "mm"
- elif uniteFin == c4d.UNIT_UM : ufin = "µm"
- elif uniteFin == c4d.UNIT_NM : ufin = "nm"
- elif uniteFin == c4d.UNIT_MILE : ufin = "mi"
- elif uniteFin == c4d.UNIT_YARD : ufin = "yd"
- elif uniteFin == c4d.UNIT_FEET : ufin = "ft"
- elif uniteFin == c4d.UNIT_INCH : ufin = "in"
-
- valeur *= ech**v
-
- fac = 1.0
- if uniteDoc == c4d.UNIT_KM : fac *= 10.0**(3*v)
- elif uniteDoc == c4d.UNIT_CM : fac *= 10.0**(-2*v)
- elif uniteDoc == c4d.UNIT_MM : fac *= 10.0**(-3*v)
- elif uniteDoc == c4d.UNIT_UM : fac *= 10.0**(-6*v)
- elif uniteDoc == c4d.UNIT_NM : fac *= 10.0**(-9*v)
- elif uniteDoc == c4d.UNIT_MILE : fac *= 1609.344**v
- elif uniteDoc == c4d.UNIT_YARD : fac *= 0.9144**v
- elif uniteDoc == c4d.UNIT_FEET : fac *= 0.3048**v
- elif uniteDoc == c4d.UNIT_INCH : fac *= 0.0254**v
-
- if ufin == "km" : fac *= 10.0**(-3*v)
- elif ufin == "cm" : fac *= 10.0**(2*v)
- elif ufin == "mm" : fac *= 10.0**(3*v)
- elif ufin == "µm" : fac *= 10.0**(6*v)
- elif ufin == "nm" : fac *= 10.0**(9*v)
- elif ufin == "mi" : fac /= 1609.344**v
- elif ufin == "yd" : fac /= 0.9144**v
- elif ufin == "ft" : fac /= 0.3048**v
- elif ufin == "in" : fac /= 0.0254**v
-
- valeur *= fac
-
- if v == 2 : v = "²"
- elif v == 3 : v = "³"
- if valeur > 10.0 : valeur = round(valeur, 4)
- retour = str(valeur) + " " + ufin + v
- return retour
-
- def rapport(self) :
- chn = ""
- chn += txt(VONC_AIRVOL_POLSEL) + " : " + str(self.airevol.sel) + "\r\n"
- chn += txt(VONC_AIRVOL_OBJSEL) + " : " + str(self.airevol.nbObj) + "\r\n"
- chn += "\r\n"
-
- liNb = len(self.airevol.liObjs)
-
- if liNb > 1 : chn += txt(VONC_AIRVOL_AIRE) + " : " + self.unite(2, self.airevol.aire) + "\r\n"
- else : chn += txt(VONC_AIRVOL_AIRE) + " : \r\n"
- for i in xrange(liNb) :
- chn += " " + self.airevol.liObjs[i] + " : " + self.unite(2, self.airevol.liAire[i]) + "\r\n"
- chn += "\r\n"
-
- if liNb > 1 : chn += txt(VONC_AIRVOL_VOLUME) + " : " + self.unite(3, self.airevol.volume) + "\r\n"
- else : chn += txt(VONC_AIRVOL_VOLUME) + " : \r\n"
- for i in xrange(liNb) :
- if i : chn += "\r\n"
- chn += " " + self.airevol.liObjs[i] + " : " + self.unite(3, self.airevol.liVol[i])
-
- return chn
-
- def opere(self, force=False) :
- self.sousObj = self.GetBool(23)
- self.majAuto = self.GetBool(24)
-
- doc = c4d.documents.GetActiveDocument()
- if self.sousObj :
- objs = doc.GetActiveObjects(c4d.GETACTIVEOBJECTFLAGS_0)
- else :
- objs = doc.GetActiveObjects(c4d.GETACTIVEOBJECTFLAGS_CHILDREN)
- caches = [objs, 0, 0, 0, 0]
- if objs :
- tabobjs = objs[:]
- for obj in tabobjs :
- caches[1] += obj.GetDirty(c4d.DIRTY_SELECT)
- caches[2] += obj.GetDirty(c4d.DIRTY_MATRIX)
- caches[3] += obj.GetDirty(c4d.DIRTY_DATA)
- caches[4] += obj.GetDirty(c4d.DIRTY_CHILDREN)
- tabobjs.extend(obj.GetChildren())
- if not force :
- if caches == self.caches :
- self.caches = caches
- return
-
- self.caches = caches
- self.airevol = Airevolume(self.sousObj)
- self.airevol.Calcule()
- self.uniteFin = self.GetLong(41)
- self.SetString(26, self.rapport())
-
- def CreateLayout(self) :
- self.GroupBegin(40, c4d.BFH_SCALEFIT, 2, 1)
- self.GroupBorderSpace(5, 0, 5, 0)
- self.AddButton(21, c4d.BFH_SCALE|c4d.BFH_RIGHT, initw=150, inith=20, name=txt(VONC_AIRVOL_CALCULER))
- self.AddComboBox(41, c4d.BFH_SCALE|c4d.BFH_CENTER, initw=60)
- # self.AddChild(41, c4d.UNIT_NONE, "")
- self.AddChild(41, c4d.UNIT_KM, "km")
- self.AddChild(41, c4d.UNIT_M, "m")
- self.AddChild(41, c4d.UNIT_CM, "cm")
- self.AddChild(41, c4d.UNIT_MM, "mm")
- self.AddChild(41, c4d.UNIT_UM, "µm")
- self.AddChild(41, c4d.UNIT_NM, "nm")
- self.AddChild(41, c4d.UNIT_MILE, "mi")
- self.AddChild(41, c4d.UNIT_YARD, "yd")
- self.AddChild(41, c4d.UNIT_FEET, "ft")
- self.AddChild(41, c4d.UNIT_INCH, "in")
- self.GroupEnd()
-
- self.GroupBegin(20, c4d.BFH_SCALEFIT, 1, 1)
- self.GroupBorderSpace(5, 0, 5, 0)
- self.AddCheckbox(23, c4d.BFH_SCALEFIT, 0, 0, txt(VONC_AIRVOL_SOUSOBJ))
- self.AddCheckbox(24, c4d.BFH_SCALEFIT, 0, 0, txt(VONC_AIRVOL_MAJ))
- self.GroupEnd()
-
- self.GroupBegin(25, c4d.BFH_SCALEFIT|c4d.BFV_SCALEFIT, 1, 1)
- self.GroupBorderSpace(5, 0, 5, 0)
- self.GroupBorderNoTitle(c4d.BORDER_THIN_IN)
- self.AddMultiLineEditText(26, c4d.BFH_SCALEFIT|c4d.BFV_SCALEFIT)
- self.GroupEnd()
-
- self.GroupBegin(30, c4d.BFH_SCALEFIT, 1, 1)
- self.GroupBorderSpace(5, 5, 5, 5)
- self.AddStaticText(31, c4d.BFH_SCALEFIT, name="v "+VERSION+" - "+txt(VONC_AIRVOL_INFO))
- self.GroupEnd()
- return True
-
- def InitValues(self) :
- self.SetTitle(txt(VONC_AIRVOL_NOM))
- self.SetLong(41, self.uniteFin)
- self.SetBool(23, self.sousObj)
- self.SetBool(24, self.majAuto)
- self.SetString(26, self.rapport())
- return True
-
- def Command(self, id, msg) :
- if id == 21 or id == 23 or id == 24 :
- self.opere(True)
- elif id == 41 :
- self.uniteFin = self.GetLong(41)
- self.SetString(26, self.rapport())
-
- return True
-
- def CoreMessage(self, id, msg) :
-
- if self.majAuto and id == c4d.EVMSG_CHANGE :
- self.opere()
-
- return True
- class AirevolumeCommande(c4d.plugins.CommandData):
- dialog = None
-
- def Execute(self, doc):
- if self.dialog is None:
- self.dialog = Dialogue()
- return self.dialog.Open(dlgtype=c4d.DLG_TYPE_ASYNC, pluginid=MODULE_ID, defaulth=300, defaultw=100)
- def RestoreLayout(self, sec_ref):
- if self.dialog is None:
- self.dialog = Dialogue()
- return self.dialog.Restore(pluginid=MODULE_ID, secret=sec_ref)
- if __name__ == "__main__":
- bmp = bitmaps.BaseBitmap()
- dir, f = os.path.split(__file__)
- fn = os.path.join(dir, "res", "vonc_airevol.tif")
- bmp.InitWith(fn)
- c4d.plugins.RegisterCommandPlugin(id=MODULE_ID, str=txt(VONC_AIRVOL_NOM),
- help=txt(VONC_AIRVOL_AIDE),info=0,
- dat=AirevolumeCommande(), icon=bmp)
复制代码
Fichier .H
- enum
- {
- VONC_AIRVOL_NOM = 1000,
- VONC_AIRVOL_ETAT_0 = 1001,
- VONC_AIRVOL_ETAT_1 = 1002,
- VONC_AIRVOL_AIRE = 1003,
- VONC_AIRVOL_VOLUME = 1004,
- VONC_AIRVOL_CALCULER = 1005,
- VONC_AIRVOL_POLSEL = 1006,
- VONC_AIRVOL_LICENCE = 1007,
- VONC_AIRVOL_CLEF = 1008,
- VONC_AIRVOL_INFO = 1009,
- VONC_AIRVOL_AIDE = 1010,
- VONC_AIRVOL_OBJSEL = 1011,
- VONC_AIRVOL_SOUSOBJ = 1012,
- VONC_AIRVOL_TOTAL = 1013,
- VONC_AIRVOL_TOTALE = 1014,
- VONC_AIRVOL_MAJ = 1015,
-
- _DUMMY_ELEMENT_
- };
复制代码
Fichier .STR
- STRINGTABLE
- {
- VONC_AIRVOL_NOM "Aire et Volume";
- VONC_AIRVOL_AIRE "Aire totale";
- VONC_AIRVOL_VOLUME "Volume total";
- VONC_AIRVOL_CALCULER "Calculer";
- VONC_AIRVOL_POLSEL "Polygones s\u00E9lectionn\u00E9s";
- VONC_AIRVOL_OBJSEL "Objets";
- VONC_AIRVOL_INFO "C\u00E9sar Vonc - http://code.vonc.fr";
- VONc_AIRVOL_AIDE "Calcule l'aire et le volume d'objets, de s\u00E9lections de polygones ou de splines.";
- VONC_AIRVOL_SOUSOBJ "Inclure les sous-objets";
- VONC_AIRVOL_MAJ "Mise \u00E0 jour auto";
- }
复制代码
|
|
Comment :1