Replace self.human.getFaceMask() with humanmesh.getFaceMask()
This snippet is intended as example, not as a guaranteed to be working, maintained plugin. It's possible this breaks when API changes occur.
Moderator: joepal
Could not load weight_estimation
Traceback (most recent call last):
File "c:\jenkins\workspace\Windows_release\buildscripts\win32\build\makehuman\out00-PYZ.pyz\mhmain", line 487, in loadNextPlugin
File "plugins/weight_estimation.py", line 1
Python 3.4.2 (v3.4.2:ab2c023a9432, Oct 6 2014, 22:15:05) [MSC v.1600 32 bit (Intel)] on win32
^
SyntaxError: invalid syntax
Could not load weight_estimation
Traceback (most recent call last):
File "c:\jenkins\workspace\Windows_release\buildscripts\win32\build\makehuman\out00-PYZ.pyz\mhmain", line 487, in loadNextPlugin
File "plugins/weight_estimation.py", line 31, in <module>
import mesh_operations
ImportError: No module named mesh_operations
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
"""
**Project Name:** MakeHuman
**Product Home Page:** http://www.makehuman.org/
**Code Home Page:** https://bitbucket.org/MakeHuman/makehuman/
**Authors:** Jonas Hauquier
**Copyright(c):** MakeHuman Team 2001-2014
**Licensing:** AGPL3 (http://www.makehuman.org/doc/node/the_makehuman_application.html)
This file is part of MakeHuman (www.makehuman.org).
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
**Coding Standards:** See http://www.makehuman.org/node/165
Abstract
--------
Mesh operations such as calculating volume and surface measures.
"""
import numpy as np
import math
def calculateSurface(mesh, vertGroups = None, faceMask = None):
"""
Calculate surface area of a mesh. Specify vertGroups or faceMask to
calculate area of a subset of the mesh and filter out other faces.
"""
if vertGroups != None:
fvert = mesh.getFacesForGroups(vertGroups)
elif faceMask != None:
f_idx = np.argwhere(faceMask)[...,0]
fvert = mesh.fvert[f_idx]
else:
fvert = mesh.fvert
if mesh.vertsPerPrimitive == 4:
# Split quads in triangles (assumes clockwise ordering of verts)
t1 = fvert[:,[0,1,2]]
t2 = fvert[:,[2,3,0]]
v1 = mesh.coord[t1]
v2 = mesh.coord[t2]
l1 = _sideLengthsFromTris(v1)
l2 = _sideLengthsFromTris(v2)
l = np.vstack([l1,l2])
return _surfaceOfTris(l)
elif mesh.vertsPerPrimitive == 3:
v = mesh.coord[fvert]
l = _sideLengthsFromTris(v)
return _surfaceOfTris(l)
else:
raise RuntimeError("Only supports meshes with triangle or quad primitives.")
def calculateVolume(mesh, vertGroups = None, faceMask = None):
"""
Calculate the volume of a mesh.
Mesh is expected to be closed.
"""
if vertGroups != None:
fvert = mesh.getFacesForGroups(vertGroups)
elif faceMask != None:
f_idx = np.argwhere(faceMask)[...,0]
fvert = mesh.fvert[f_idx]
else:
fvert = mesh.fvert
if mesh.vertsPerPrimitive == 4:
# Split quads in triangles (assumes clockwise ordering of verts)
t1 = fvert[:,[0,1,2]]
t2 = fvert[:,[2,3,0]]
v1 = mesh.coord[t1]
v2 = mesh.coord[t2]
v = np.vstack([v1,v2])
return _signedVolumeFromTris(v)
elif mesh.vertsPerPrimitive == 3:
v = mesh.coord[fvert]
return _signedVolumeFromTris(v)
else:
raise RuntimeError("Only supports meshes with triangle or quad primitives.")
def _sideLengthsFromTris(triVects):
"""
Calculate lengths of the sides of triangles specified by their vectors
in clockwise fashion.
triVects = [ [T1V1, T1V2, T1V3], [T2V1, T2V2, T2V3], ... ]
with Ti a triangle, Vi a triange vector, defined in clockwise fashion
and each vector (TiVi) an array [x, y, z] with vector coordinates
Returns a list [ [T1L1, T1L2, T1L3], [T2L1, T2L2, T2L3], ...]
with Ti a triangle (in the same order as in the input), and Li the length of
side i (a float)
"""
v = triVects
s = np.zeros(v.shape, dtype=np.float32)
# Get side vectors
s[:,0] = v[:,1] - v[:,0]
s[:,1] = v[:,2] - v[:,1]
s[:,2] = v[:,0] - v[:,2]
# Calculate lengths of sides
l = s[:,:,0]*s[:,:,0] + s[:,:,1]*s[:,:,1] + s[:,:,2]*s[:,:,2]
l = np.sqrt(l)
return l
def _surfaceOfTris(triSideLengths):
"""
Calculate total surface area of triangles with sides of specified lengths
triSideLengths should be an array of layout
[ [T1L1, T1L2, T1L3], [T2L1, T2L2, T2L3], ... ]
with Ti a triangle, and Li the length of the ith side of the triangle
TiLi should be a float.
Returns a float representing the total surface area.
"""
l = triSideLengths
# Heron's formula
o = ( l[:,0] +l[:,1] +l[:,2]) * \
( l[:,0] +l[:,1] -l[:,2]) * \
(-l[:,0] +l[:,1] +l[:,2]) * \
( l[:,0] -l[:,1] +l[:,2])
o = np.sqrt(o)/4
return np.sum(o)
def _signedVolumeFromTris(triVects):
"""
Calculate volume of a set of triangles by summing signed volumes of
tetrahedrons between those triangles and the origin.
"""
v = triVects
v321 = v[:,2,0] * v[:,1,1] * v[:,0,2]
v231 = v[:,1,0] * v[:,2,1] * v[:,0,2]
v312 = v[:,2,0] * v[:,0,1] * v[:,1,2]
v132 = v[:,0,0] * v[:,2,1] * v[:,1,2]
v213 = v[:,1,0] * v[:,0,1] * v[:,2,2]
v123 = v[:,0,0] * v[:,1,1] * v[:,2,2]
signedVolume = -v321 + v231 + v312 - v132 - v213 + v123
signedVolume /= 6.0
vol = np.sum(signedVolume)
return math.fabs(vol)
def findVertIndex(mesh, vert):
"""
Find the index of specified vertex (as an [x, y, z] array) within mesh.
"""
matches = list(np.where(mesh.coord == vert)[0])
return [idx for idx in set(matches) if matches.count(idx) > 2]
Could not load mesh_operations
Traceback (most recent call last):
File "c:\jenkins\workspace\Windows_release\buildscripts\win32\build\makehuman\out00-PYZ.pyz\mhmain", line 498, in loadNextPlugin
AttributeError: 'module' object has no attribute 'load'
Could not load weight_estimation
Traceback (most recent call last):
File "c:\jenkins\workspace\Windows_release\buildscripts\win32\build\makehuman\out00-PYZ.pyz\mhmain", line 498, in loadNextPlugin
File "plugins/weight_estimation.py", line 82, in load
taskview = category.addTask(WeightTaskView(category))
File "plugins/weight_estimation.py", line 54, in __init__
self.calculateWeight()
File "plugins/weight_estimation.py", line 70, in calculateWeight
bsa = mesh_operations.calculateSurface(humanMesh, faceMask = humanmesh.getFaceMask())/100
NameError: global name 'humanmesh' is not defined
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
"""
**Project Name:** MakeHuman
**Product Home Page:** http://www.makehuman.org/
**Code Home Page:** http://code.google.com/p/makehuman/
**Authors:** Jonas Hauquier
**Copyright(c):** MakeHuman Team 2001-2014
**Licensing:** AGPL3 (see also http://www.makehuman.org/node/318)
**Coding Standards:** See http://www.makehuman.org/node/165
Abstract
--------
Base template for weight calculation experiments
"""
import gui3d
import mh
import gui
import log
import numpy as np
import mesh_operations
class WeightTaskView(gui3d.TaskView):
def __init__(self, category):
"""
Constructor of the Body weight tab (in utilities category)
"""
gui3d.TaskView.__init__(self, category, 'Body weight')
self.human = gui3d.app.selectedHuman
box = self.addLeftWidget(gui.GroupBox('Body weight'))
self.volumeLabel = box.addWidget(gui.TextView(''))
self.surfaceLabel = box.addWidget(gui.TextView(''))
self.heightLabel = box.addWidget(gui.TextView(''))
#self.calculateButton = box.addWidget(gui.Button('Calculate'))
#@self.calculateButton.mhEvent
#def onClicked(event):
#self.calculateWeight()
self.calculateWeight()
def onHumanChanged(self, event):
"""
Update metrics when human mesh is modified
"""
self.calculateWeight()
def calculateWeight(self):
"""
Calculate body metrics
"""
humanMesh = self.human.meshData
# Calculate height, body surface area and volume in m / m^2 / m^3
height = self.human.getHeightCm()/100
bsa = mesh_operations.calculateSurface(humanMesh, faceMask = humanMesh.getFaceMask())/100
vol = mesh_operations.calculateVolume(humanMesh, faceMask = humanMesh.getFaceMask())/1000
self.volumeLabel.setText('Volume %.2f m^3' % vol)
self.surfaceLabel.setText('Surface: %.2f m^2' % bsa)
self.heightLabel.setText('Height: %.2f m' % height)
def load(app):
"""
Initialize plugin
"""
category = app.getCategory('Utilities')
taskview = category.addTask(WeightTaskView(category))
def unload(app):
pass
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
"""
**Project Name:** MakeHuman
**Product Home Page:** http://www.makehuman.org/
**Code Home Page:** https://bitbucket.org/MakeHuman/makehuman/
**Authors:** Marc Flerackers (weight calculation added by madcontra)
**Copyright(c):** MakeHuman Team 2001-2014
**Licensing:** AGPL3 (http://www.makehuman.org/doc/node/the_makehuman_application.html)
This file is part of MakeHuman (www.makehuman.org).
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
**Coding Standards:** See http://www.makehuman.org/node/165
Abstract
--------
TODO
"""
import math
import numpy as np
import guicommon
import module3d
import humanmodifier
import gui
import gui3d
import log
import getpath
from core import G
import guimodifier
import language
import mesh_operations
class MeasureTaskView(guimodifier.ModifierTaskView):
def __init__(self, category, name, label=None, saveName=None, cameraView=None):
super(MeasureTaskView, self).__init__(category, name, label, saveName, cameraView)
self.ruler = Ruler()
self._createMeasureMesh()
self.active_slider = None
self.lastActive = None
self.statsBox = self.addRightWidget(gui.GroupBox('Statistics'))
self.height = self.statsBox.addWidget(gui.TextView('Height: '))
self.chest = self.statsBox.addWidget(gui.TextView('Chest: '))
self.waist = self.statsBox.addWidget(gui.TextView('Waist: '))
self.hips = self.statsBox.addWidget(gui.TextView('Hips: '))
self.whr = self.statsBox.addWidget(gui.TextView('WHR: '))
self.braBox = self.addRightWidget(gui.GroupBox('Bra Size'))
#self.eu = self.braBox.addWidget(gui.TextView('EU: '))
#self.jp = self.braBox.addWidget(gui.TextView('JP: '))
self.us = self.braBox.addWidget(gui.TextView('US: '))
#self.uk = self.braBox.addWidget(gui.TextView(''))
self.weightBox = self.addRightWidget(gui.GroupBox('Weight'))
self.weightLabel = self.weightBox.addWidget(gui.TextView('Weight: '))
self.bmiLabel = self.weightBox.addWidget(gui.TextView('BMI: '))
self.bodyfatLabel = self.weightBox.addWidget(gui.TextView('Body Fat: '))
self.calculateWeight()
def addSlider(self, sliderCategory, slider):
super(MeasureTaskView, self).addSlider(sliderCategory, slider)
slider.valueConverter = MeasurementValueConverter(self, slider.modifier)
@slider.mhEvent
def onBlur(event):
slider = event
self.onSliderBlur(slider)
@slider.mhEvent
def onFocus(event):
slider = event
self.onSliderFocus(slider)
@slider.mhEvent
def onChange(event):
self.syncGUIStats()
self.sliders.append(slider)
def _createMeasureMesh(self):
self.measureMesh = module3d.Object3D('measure', 2)
self.measureMesh.createFaceGroup('measure')
count = max([len(vertIdx) for vertIdx in self.ruler.Measures.values()])
self.measureMesh.setCoords(np.zeros((count, 3), dtype=np.float32))
self.measureMesh.setUVs(np.zeros((1, 2), dtype=np.float32))
self.measureMesh.setFaces(np.arange(count).reshape((-1,2)))
self.measureMesh.setColor([255, 255, 255, 255])
self.measureMesh.setPickable(0)
self.measureMesh.updateIndexBuffer()
self.measureMesh.priority = 50
self.measureObject = self.addObject(guicommon.Object(self.measureMesh))
self.measureObject.setShadeless(True)
self.measureObject.setDepthless(True)
def showGroup(self, name):
self.groupBoxes[name].radio.setSelected(True)
self.groupBox.showWidget(self.groupBoxes[name])
self.groupBoxes[name].children[0].setFocus()
def getMeasure(self, measure):
human = G.app.selectedHuman
measure = self.ruler.getMeasure(human, measure, G.app.settings['units'])
return measure
def hideAllBoxes(self):
for box in self.groupBoxes.values():
box.hide()
def onShow(self, event):
super(MeasureTaskView, self).onShow(event)
if not self.lastActive:
self.lastActive = self.groupBoxes['Neck'].children[0]
self.lastActive.setFocus()
self.syncGUIStats()
self.updateMeshes()
human = G.app.selectedHuman
def onHide(self, event):
human = G.app.selectedHuman
def onSliderFocus(self, slider):
self.lastActive = slider
self.active_slider = slider
self.updateMeshes()
self.measureObject.show()
def onSliderBlur(self, slider):
self.lastActive = slider
if self.active_slider is slider:
self.active_slider = None
self.measureObject.hide()
def updateMeshes(self):
if self.active_slider is None:
return
human = G.app.selectedHuman
vertidx = self.ruler.Measures[self.active_slider.modifier.fullName]
coords = human.meshData.coord[vertidx]
self.measureMesh.coord[:len(vertidx),:] = coords
self.measureMesh.coord[len(vertidx):,:] = coords[-1:]
self.measureMesh.markCoords(coor = True)
self.measureMesh.update()
def onHumanChanged(self, event):
self.calculateWeight()
if G.app.currentTask == self:
self.updateMeshes()
self.syncSliders()
def onHumanTranslated(self, event):
self.measureObject.setPosition(G.app.selectedHuman.getPosition())
def onHumanRotated(self, event):
self.measureObject.setRotation(G.app.selectedHuman.getRotation())
def loadHandler(self, human, values):
if values[0] == 'status':
return
if values[0] == self.saveName:
# TODO temporary backwards compat mapping, to solve in 1.1
mName = 'measure-'+values[1]+'-decrease-increase'
modifier = self.modifiers.get(mName, None)
if modifier:
modifier.setValue(float(values[2]))
def saveHandler(self, human, file):
for name, modifier in self.modifiers.iteritems():
if name is None:
continue
value = modifier.getValue()
# TODO backwards compat mapping
name = name.replace('-decrease-increase', '')
name = name.replace('measure-', '')
if value or isinstance(modifier, humanmodifier.MacroModifier):
file.write('%s %s %f\n' % (self.saveName, name, value))
def syncGUIStats(self):
self.syncStatistics()
self.syncBraSizes()
def syncStatistics(self):
human = G.app.selectedHuman
height = human.getHeightCm()
if G.app.settings['units'] == 'metric':
height = '%.2f cm' % height
else:
heightInch = height*(1/2.54)
heightFeet = heightInch//12
height = '%.0f ft' % heightFeet + ' %.1f in' % (heightInch - (heightFeet*12))
lang = language.language
self.height.setTextFormat(lang.getLanguageString('Height') + ': %s', height)
if G.app.settings['units'] == 'metric':
self.chest.setTextFormat(lang.getLanguageString('Chest') + ': %.1f cm', self.getMeasure('measure/measure-bust-decrease|increase'))
self.waist.setTextFormat(lang.getLanguageString('Waist') + ': %.1f cm', self.getMeasure('measure/measure-waist-decrease|increase'))
self.hips.setTextFormat(lang.getLanguageString('Hips') + ': %.1f cm', self.getMeasure('measure/measure-hips-decrease|increase'))
else:
self.chest.setTextFormat(lang.getLanguageString('Chest') + ': %.1f in', self.getMeasure('measure/measure-bust-decrease|increase'))
self.waist.setTextFormat(lang.getLanguageString('Waist') + ': %.1f in', self.getMeasure('measure/measure-waist-decrease|increase'))
self.hips.setTextFormat(lang.getLanguageString('Hips') + ': %.1f in', self.getMeasure('measure/measure-hips-decrease|increase'))
waistHipRatio = self.getMeasure('measure/measure-waist-decrease|increase')/self.getMeasure('measure/measure-hips-decrease|increase')
self.whr.setText('WHR: %.2f' % waistHipRatio)
def syncBraSizes(self):
# TODO unused
human = G.app.selectedHuman
bust = self.ruler.getMeasure(human, 'measure/measure-bust-decrease|increase', 'metric')
underbust = self.ruler.getMeasure(human, 'measure/measure-underbust-decrease|increase', 'metric')
#eucups = ['AA', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K']
#mod = int(underbust)%5
#band = underbust - mod if mod < 2.5 else underbust - mod + 5
#cup = min(max(0, int(round(((bust - underbust - 10) / 2)))), len(eucups)-1)
#self.eu.setTextFormat('EU: %d%s', band, eucups[cup])
#jpcups = ['AAA', 'AA', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K']
#mod = int(underbust)%5
#band = underbust - mod if mod < 2.5 else underbust - mod + 5
#cup = min(max(0, int(round(((bust - underbust - 5) / 2.5)))), len(jpcups)-1)
#self.jp.setTextFormat('JP: %d%s', band, jpcups[cup])
uscups = ['AA', 'A', 'B', 'C', 'D', 'DD', 'F', 'FF', 'G', 'GG', 'H']
band = underbust * 0.393700787
band = band + 1 if int(band)%2 else band
cup = min(max(0, int(round((bust - underbust - 10) / 2))), len(uscups)-1)
self.us.setTextFormat('US: %d%s', band, uscups[cup])
#ukcups = ['AA', 'A', 'B', 'C', 'D', 'DD', 'E', 'F', 'FF', 'G', 'GG', 'H']
#self.uk.setTextFormat('UK: %d%s', band, ukcups[cup])
def calculateWeight(self):
"""
Calculate body metrics
"""
self.human = gui3d.app.selectedHuman
humanMesh = self.human.meshData
# Calculate height, body surface area and volume in m / m^2 / m^3
height = self.human.getHeightCm()/100
bsa = mesh_operations.calculateSurface(humanMesh, faceMask = humanMesh.getFaceMask())/100
vol = mesh_operations.calculateVolume(humanMesh, faceMask = humanMesh.getFaceMask())/1000
if G.app.settings['units'] == 'metric':
bfWaist = self.getMeasure('measure/measure-waist-decrease|increase')
bfNeck = self.getMeasure('measure/measure-neckcirc-decrease|increase')
bfHips = self.getMeasure('measure/measure-hips-decrease|increase')
else:
bfWaist = self.getMeasure('measure/measure-waist-decrease|increase')*2.54
bfNeck = self.getMeasure('measure/measure-neckcirc-decrease|increase')*2.54
bfHips = self.getMeasure('measure/measure-hips-decrease|increase')*2.54
bfMale = (86.010*np.log10(bfWaist-bfNeck))-(70.041*np.log10(height*100))+30.3
bfFemale = (163.205*np.log10(bfWaist+bfHips-bfNeck))-(97.684*np.log10(height*100))-104.912
gen = self.human.getGender()
bf = ((bfMale*gen)+(bfFemale*(1-gen)))/100
densBone = 1750
densMuscle = 1050
densFat = 900
massBoneMale = (.07*(height*100)**2.33)/1000
massBoneFemale = (.03*(height*100)**2.48)/1000
massBone = (massBoneMale*gen)+(massBoneFemale*(1-gen))
volBone = massBone/densBone
volMuscle = (((bf-1)*vol*densFat)+(volBone*(densFat-bf*densFat))+(bf*volBone*densBone))/(((bf-1)*densFat)-(bf*densMuscle))
volFat = vol-volMuscle-volBone
massFat = volFat*densFat
massMuscle = volMuscle*densMuscle
wei = (massBone+massFat+massMuscle)
bmi = (wei)/(height**2)
if G.app.settings['units'] == 'metric':
self.weightLabel.setText('Weight: %.1f kg' % wei)
else:
self.weightLabel.setText('Weight: %.1f lb' % (wei*2.20462))
self.bmiLabel.setText('BMI: %.1f' % bmi)
self.bodyfatLabel.setText('Body Fat: %.1f %%' % (bf*100))
class MeasurementValueConverter(object):
def __init__(self, task, modifier):
self.task = task
self.modifier = modifier
self.value = 0.0
@property
def units(self):
return 'cm' if G.app.settings['units'] == 'metric' else 'in'
@property
def measure(self):
return self.modifier.fullName
def dataToDisplay(self, value):
self.value = value
return self.task.getMeasure(self.measure)
def displayToData(self, value):
goal = float(value)
measure = self.task.getMeasure(self.measure)
minValue = -1.0
maxValue = 1.0
if math.fabs(measure - goal) < 0.01:
return self.value
else:
tries = 10
while tries:
if math.fabs(measure - goal) < 0.01:
break;
if goal < measure:
maxValue = self.value
if value == minValue:
break
self.value = minValue + (self.value - minValue) / 2.0
self.modifier.updateValue(self.value, 0)
measure = self.task.getMeasure(self.measure)
else:
minValue = self.value
if value == maxValue:
break
self.value = self.value + (maxValue - self.value) / 2.0
self.modifier.updateValue(self.value, 0)
measure = self.task.getMeasure(self.measure)
tries -= 1
return self.value
class Ruler:
"""
This class contains ...
"""
def __init__(self):
# these are tables of vertex indices for each body measurement of interest
# TODO define in data file?
self.Measures = {}
self.Measures['measure/measure-neckcirc-decrease|increase'] = [7514,10358,7631,7496,7488,7489,7474,7475,7531,7537,7543,7549,7555,7561,7743,7722,856,1030,1051,850,844,838,832,826,820,756,755,770,769,777,929,3690,804,800,808,801,799,803,7513,7515,7521,7514]
self.Measures['measure/measure-neckheight-decrease|increase'] = [853,854,855,856,857,858,1496,1491]
self.Measures['measure/measure-upperarm-decrease|increase']=[8383,8393,8392,8391,8390,8394,8395,8399,10455,10516,8396,8397,8398,8388,8387,8386,10431,8385,8384,8389]
self.Measures['measure/measure-upperarmlenght-decrease|increase'] = [8274,10037]
self.Measures['measure/measure-lowerarmlenght-decrease|increase'] = [10040,10548]
self.Measures['measure/measure-wrist-decrease|increase']=[10208,10211,10212,10216,10471,10533,10213,10214,10215,10205,10204,10203,10437,10202,10201,10206,10200,10210,10209,10208]
self.Measures['measure/measure-frontchest-decrease|increase']=[1437,8125]
self.Measures['measure/measure-bust-decrease|increase']=[8439,8455,8462,8446,8478,8494,8557,8510,8526,8542,10720,10601,10603,10602,10612,10611,10610,10613,10604,10605,10606,3942,3941,3940,3950,3947,3948,3949,3938,3939,3937,4065,1870,1854,1838,1885,1822,1806,1774,1790,1783,1767,1799,8471]
self.Measures['measure/measure-underbust-decrease|increase'] = [10750,10744,10724,10725,10748,10722,10640,10642,10641,10651,10650,10649,10652,10643,10644,10645,10646,10647,10648,3988,3987,3986,3985,3984,3983,3982,3992,3989,3990,3991,3980,3981,3979,4067,4098,4073,4072,4094,4100,4082,4088, 4088]
self.Measures['measure/measure-waist-decrease|increase'] = [4121,10760,10757,10777,10776,10779,10780,10778,10781,10771,10773,10772,10775,10774,10814,10834,10816,10817,10818,10819,10820,10821,4181,4180,4179,4178,4177,4176,4175,4196,4173,4131,4132,4129,4130,4128,4138,4135,4137,4136,4133,4134,4108,4113,4118,4121]
self.Measures['measure/measure-napetowaist-decrease|increase']=[1491,4181]
self.Measures['measure/measure-waisttohip-decrease|increase']=[4121,4341]
self.Measures['measure/measure-shoulder-decrease|increase'] = [7478,8274]
self.Measures['measure/measure-hips-decrease|increase'] = [4341,10968,10969,10971,10970,10967,10928,10927,10925,10926,10923,10924,10868,10875,10861,10862,4228,4227,4226,4242,4234,4294,4293,4296,4295,4297,4298,4342,4345,4346,4344,4343,4361,4341]
self.Measures['measure/measure-upperlegheight-decrease|increase'] = [10970,11230]
self.Measures['measure/measure-thighcirc-decrease|increase'] = [11071,11080,11081,11086,11076,11077,11074,11075,11072,11073,11069,11070,11087,11085,11084,12994,11083,11082,11079,11071]
self.Measures['measure/measure-lowerlegheight-decrease|increase'] = [11225,12820]
self.Measures['measure/measure-calf-decrease|increase'] = [11339,11336,11353,11351,11350,13008,11349,11348,11345,11337,11344,11346,11347,11352,11342,11343,11340,11341,11338,11339]
self.Measures['measure/measure-ankle-decrease|increase'] = [11460,11464,11458,11459,11419,11418,12958,12965,12960,12963,12961,12962,12964,12927,13028,12957,11463,11461,11457,11460]
self.Measures['measure/measure-kneecirc-decrease|increase'] = [11223,11230,11232,11233,11238,11228,11229,11226,11227,11224,11225,11221,11222,11239,11237,11236,13002,11235,11234,11223]
self._validate()
def _validate(self):
"""
Verify currectness of ruler specification
"""
names = []
for n,v in self.Measures.items():
if len(v) % 2 != 0:
names.append(n)
if len(names) > 0:
raise RuntimeError("One or more measurement rulers contain an uneven number of vertex indices. It's required that they are pairs indicating the begin and end point of every line to draw. Rulers with uneven index count: %s" % ", ".join(names))
def getMeasure(self, human, measurementname, mode):
measure = 0
vindex1 = self.Measures[measurementname][0]
for vindex2 in self.Measures[measurementname]:
vec = human.meshData.coord[vindex1] - human.meshData.coord[vindex2]
measure += math.sqrt(vec.dot(vec))
vindex1 = vindex2
if mode == 'metric':
return 10.0 * measure
else:
return 10.0 * measure * 0.393700787
def load(app):
"""
Plugin load function, needed by design.
"""
category = app.getCategory('Modelling')
humanmodifier.loadModifiers(getpath.getSysDataPath('modifiers/measurement_modifiers.json'), app.selectedHuman)
guimodifier.loadModifierTaskViews(getpath.getSysDataPath('modifiers/measurement_sliders.json'), app.selectedHuman, category, taskviewClass=MeasureTaskView)
# TODO ??
#taskview.showGroup('neck')
def unload(app):
pass
Users browsing this forum: No registered users and 1 guest