Skip to content

Commit

Permalink
Merge branch 'run-mbdyn' of https://github.com/janga1997/blendyn into…
Browse files Browse the repository at this point in the history
… janga1997-run-mbdyn

Conflicts:
	base.py
  • Loading branch information
zanoni-mbdyn committed May 25, 2017
2 parents ccf2fb4 + 19251b1 commit 42a9c7b
Show file tree
Hide file tree
Showing 20 changed files with 1,152 additions and 389 deletions.
411 changes: 321 additions & 90 deletions base.py

Large diffs are not rendered by default.

136 changes: 128 additions & 8 deletions baselib.py
@@ -1,4 +1,4 @@
# --------------------------------------------------------------------------
# --------------------------------------------------------------------------
# Blendyn -- file base.py
# Copyright (C) 2015 -- 2017 Andrea Zanoni -- andrea.zanoni@polimi.it
# --------------------------------------------------------------------------
Expand Down Expand Up @@ -31,21 +31,94 @@
from bpy.props import *
from bpy_extras.io_utils import ImportHelper


import logging

import numpy as np
import ntpath, csv, math

import ntpath, os, csv, math, atexit

from collections import namedtuple

from .nodelib import *
from .elementlib import *
from .logwatcher import *

import os
try:
import pygal
from .plotlib import get_plot_vars_glob
HAVE_PLOT = True
except ImportError:
print("blendyn: could not find pygal module. Plotting "\
+ "will be disabled.")
pass

import os, time
import pdb

try:
from netCDF4 import Dataset
except ImportError:
print("blendyn: could not find netCDF4 module. NetCDF import "\
+ "will be disabled.")
pass

def parse_input_file(context):
mbs = context.scene.mbdyn

out_file = mbs.input_path

with open(out_file) as of:
reader = csv.reader(of, delimiter=' ', skipinitialspace=True)

while True:
rw = next(reader)
print(rw)
if rw:
first = rw[0].strip()

if first == 'final':
time = rw[2]
time = float(time[:-1])
mbs.input_time = time

break

## Function that sets up the data for the import process
def setup_import(filepath, context):
mbs = context.scene.mbdyn
mbs.file_path, mbs.file_basename = path_leaf(filepath)
if filepath[-2:] == 'nc':
try:
nc = Dataset(filepath, "r", format="NETCDF3")
mbs.use_netcdf = True
mbs.num_rows = 0
try:
eig_step = nc.variables['eig.step']
eig_time = nc.variables['eig.time']
eig_dCoef = nc.variables['eig.dCoef']
for ii in range(0, len(eig_step)):
eigsol = mbs.eigensolutions.add()
eigsol.step = eig_step[ii]
eigsol.time = eig_time[ii]
eigsol.dCoef = eig_dCoef[ii]
eigsol.iNVec = nc.dimensions['eig_' + str(ii) + '_iNVec_out'].size
eigsol.curr_eigmode = 1
except KeyError:
print('MBDynSelectOutputFile: no eigenanalysis results found')
pass
if HAVE_PLOT:
get_plot_vars_glob(context)


except NameError:
return {'NETCDF_ERROR'}
else:
mbs.num_rows = file_len(filepath)
return {'FINISHED'}

# -----------------------------------------------------------
# end of setup_import() function

## Function that parses the .log file and calls parse_elements() to add elements
# to the elements dictionary and parse_node() to add nodes to the nodes dictionary
Expand Down Expand Up @@ -291,12 +364,20 @@ def update_label(self, context):
ret_val = update_parametrization(obj)

if ret_val == 'ROT_NOT_SUPPORTED':
self.report({'ERROR'}, "Rotation parametrization not supported, node " \
+ obj.mbdyn.string_label)
message = "Rotation parametrization not supported, node " \
+ obj.mbdyn.string_label
self.report({'ERROR'}, message)
logging.error(message)

elif ret_val == 'LOG_NOT_FOUND':
self.report({'ERROR'}, "MBDyn .log file not found")
message = "MBDyn .log file not found"
self.report({'ERROR'}, message)
logging.error(message)

except KeyError:
self.report({'ERROR'}, "Node not found")
message = "Node not found"
self.report({'ERROR'}, message)
logging.error(message)
pass
return
# -----------------------------------------------------------
Expand All @@ -322,7 +403,7 @@ def remove_oldframes(context):

def hide_or_delete(obj_names, missing):

obj_list = [bpy.data.objects[var] for var in obj_names]
obj_names = list(filter(lambda v: v != 'none', obj_names))
obj_list = [bpy.data.objects[var] for var in obj_names]

if missing == "HIDE":
Expand Down Expand Up @@ -583,3 +664,42 @@ def set_motion_paths_netcdf(context):

# -----------------------------------------------------------
# end of set_motion_paths_netcdf() function
class BlenderHandler(logging.Handler):
def emit(self, record):
log_entry = self.format(record)
editor = bpy.data.texts[os.path.basename(logFile)]
editor.write(log_entry + '\n')

def log_messages(mbs, baseLogger, saved_blend):

blendFile = os.path.basename(bpy.data.filepath) if bpy.data.is_saved \
else 'untitled.blend'
blendFile = os.path.splitext(blendFile)[0]

formatter = '%(asctime)s - %(levelname)s - %(message)s'
datefmt = '%m/%d/%Y %I:%M:%S %p'
global logFile
logFile = ('{0}_{1}.bylog').format(mbs.file_path + blendFile, mbs.file_basename)

fh = logging.FileHandler(logFile)
fh.setFormatter(logging.Formatter(formatter, datefmt))

custom = BlenderHandler()
custom.setFormatter(logging.Formatter(formatter, datefmt))

baseLogger.addHandler(fh)
baseLogger.addHandler(custom)

if not saved_blend:
bpy.data.texts.new(os.path.basename(logFile))

def delete_log():
mbs = bpy.context.scene.mbdyn

if not bpy.data.is_saved:
os.remove(logFile)

elif mbs.del_log:
os.remove(logFile)

atexit.register(delete_log)
124 changes: 51 additions & 73 deletions beamlib.py
Expand Up @@ -26,6 +26,8 @@
import numpy as np
import csv

import logging

from mathutils import *
from math import *

Expand Down Expand Up @@ -553,51 +555,6 @@ def spawn_beam3_element(elem, context):
bpy.ops.object.mode_set(mode = 'OBJECT', toggle = False)

bpy.ops.object.select_all(action = 'DESELECT')

if False: # NOT CORRECT! -- Moved to update_beam3
# P1 driver for bevel section rotation
drv_tilt_P1 = beamOBJ.data.splines[0].points[0].driver_add('tilt')
xrot_P1 = drv_tilt_P1.driver.variables.new()
xrot_P1.name = "xrot_P1"
xrot_P1.type = 'TRANSFORMS'
xrot_P1.targets[0].id = n1OBJ
xrot_P1.targets[0].data_path = 'rotation.x'
xrot_P1.targets[0].transform_type = 'ROT_X'
xrot_P1.targets[0].transform_space = 'WORLD_SPACE'
drv_tilt_P1.driver.expression = "xrot_P1"

# P3 driver for bevel section rotation
drv_tilt_P3 = beamOBJ.data.splines[0].points[3].driver_add('tilt')
xrot_P3 = drv_tilt_P3.driver.variables.new()
xrot_P3.name = "xrot_P3"
xrot_P3.type = 'TRANSFORMS'
xrot_P3.targets[0].id = n3OBJ
xrot_P3.targets[0].data_path = 'rotation.x'
xrot_P3.targets[0].transform_type = 'ROT_X'
xrot_P3.targets[0].transform_space = 'WORLD_SPACE'
drv_tilt_P3.driver.expression = "xrot_P3"

# M1 driver for bevel section rotation (TODO: check correctness)
drv_tilt_M1 = beamOBJ.data.splines[0].points[1].driver_add('tilt')
xrot_P2_1 = drv_tilt_M1.driver.variables.new()
xrot_P2_1.name = "xrot_P2"
xrot_P2_1.type = 'TRANSFORMS'
xrot_P2_1.targets[0].id = n2OBJ
xrot_P2_1.targets[0].data_path = 'rotation.x'
xrot_P2_1.targets[0].transform_type = 'ROT_X'
xrot_P2_1.targets[0].transform_space = 'WORLD_SPACE'
drv_tilt_M1.driver.expression = "xrot_P2"

# M2 driver for bevel section rotation (TODO: check correctness)
drv_tilt_M2 = beamOBJ.data.splines[0].points[2].driver_add('tilt')
xrot_P2_2 = drv_tilt_M2.driver.variables.new()
xrot_P2_2.name = "xrot_P2"
xrot_P2_2.type = 'TRANSFORMS'
xrot_P2_2.targets[0].id = n2OBJ
xrot_P2_2.targets[0].data_path = 'rotation.x'
xrot_P2_2.targets[0].transform_type = 'ROT_X'
xrot_P2_2.targets[0].transform_space = 'WORLD_SPACE'
drv_tilt_M2.driver.expression = "xrot_P2"

beamOBJ.select = True
n1OBJ.select = True
Expand Down Expand Up @@ -640,6 +597,8 @@ def update_beam3(elem, insert_keyframe = False):
f2 = elem.offsets[1].value
f3 = elem.offsets[2].value

bpy.context.scene.update()

# points on beam
P1 = n1.matrix_world*Vector(( f1[0], f1[1], f1[2], 1.0 ))
P2 = n2.matrix_world*Vector(( f2[0], f2[1], f2[2], 1.0 ))
Expand All @@ -665,15 +624,16 @@ def update_beam3(elem, insert_keyframe = False):
t3 = P3.to_3d() - cp2.location
t3.normalize()

phi1, theta1 = n1.matrix_world.to_quaternion().to_axis_angle()
phi2, theta2 = n2.matrix_world.to_quaternion().to_axis_angle()
phi3, theta3 = n3.matrix_world.to_quaternion().to_axis_angle()
phi1, theta1 = n1.matrix_local.to_quaternion().to_axis_angle()
phi2, theta2 = n2.matrix_local.to_quaternion().to_axis_angle()
phi3, theta3 = n3.matrix_local.to_quaternion().to_axis_angle()

cvdata.splines[0].points[0].tilt = t1.to_3d()*(theta1*phi1)
cvdata.splines[0].points[1].tilt = t2.to_3d()*(theta2*phi2)
cvdata.splines[0].points[2].tilt = t2.to_3d()*(theta2*phi2)
cvdata.splines[0].points[3].tilt = t3.to_3d()*(theta3*phi3)


bpy.context.scene.update()

if insert_keyframe:
try:
Expand All @@ -687,7 +647,9 @@ def update_beam3(elem, insert_keyframe = False):
if 'context is incorrect' in str(err):
pass
else:
self.report({'WARNING'}, str(err))
message = str(err)
self.report({'WARNING'}, message)
logging.warning(message)
except TypeError:
pass

Expand All @@ -713,25 +675,31 @@ def execute(self, context):
elem = ed['beam2_' + str(self.int_label)]
retval = spawn_beam2_element(elem, context)
if retval == 'OBJECT_EXISTS':
self.report({'WARNING'}, "Found the Object " + \
elem.blender_object + \
" remove or rename it to re-import the element!")
message = "Found the Object " + elem.blender_object + \
" remove or rename it to re-import the element!"
self.report({'WARNING'}, message)
logging.warning(message)
return {'CANCELLED'}
elif retval == 'NODE1_NOTFOUND':
self.report({'ERROR'}, \
"Could not import element: Blender object \
associated to Node " + str(elem.nodes[0].int_label) \
+ " not found")
message = "Could not import element: Blender object" + \
"associated to Node " + str(elem.nodes[0].int_label) \
+ " not found"
self.report({'ERROR'}, message)
logging.error(message)
return {'CANCELLED'}
elif retval == 'NODE2_NOTFOUND':
self.report({'ERROR'}, "Could not import element: Blender object \
associated to Node " + str(elem.nodes[1].int_label) + " not found")
message = "Could not import element: Blender object" + \
"associated to Node " + str(elem.nodes[1].int_label) + " not found"
self.report({'ERROR'}, message)
logging.error(message)
return {'CANCELLED'}
else:
return retval

except KeyError:
self.report({'ERROR'}, "Element beam2_" + str(elem.int_label) + "not found.")
message = "Element beam2_" + str(elem.int_label) + "not found."
self.report({'ERROR'}, message)
logging.error(message)
return {'CANCELLED'}

return {'FINISHED'}
Expand All @@ -754,29 +722,37 @@ def execute(self, context):
elem = ed['beam3_' + str(self.int_label)]
retval = spawn_beam3_element(elem, context)
if retval == 'OBJECT_EXISTS':
self.report({'WARNING'}, "Found the Object " + \
elem.blender_object + \
" remove or rename it to re-import the element!")
message = "Found the Object " + elem.blender_object + \
" remove or rename it to re-import the element!"
self.report({'WARNING'}, message)
logging.warning(message)
return {'CANCELLED'}
elif retval == 'NODE1_NOTFOUND':
self.report({'ERROR'}, \
"Could not import element: Blender object \
associated to Node " + str(elem.nodes[0].int_label) \
+ " not found")
message = "Could not import element: Blender object " +\
"associated to Node " + str(elem.nodes[0].int_label) \
+ " not found"
self.report({'ERROR'}, message)
logging.error(message)
return {'CANCELLED'}
elif retval == 'NODE2_NOTFOUND':
self.report({'ERROR'}, "Could not import element: Blender object \
associated to Node " + str(elem.nodes[1].int_label) + " not found")
message = "Could not import element: Blender object " +\
"associated to Node " + str(elem.nodes[1].int_label) + " not found"
self.report({'ERROR'}, message)
logging.error(message)
return {'CANCELLED'}
elif retval == 'NODE3_NOTFOUND':
self.report({'ERROR'}, "Could not import element: Blender object \
associated to Node " + str(elem.nodes[2].int_label) + " not found")
message = "Could not import element: Blender object " +\
"associated to Node " + str(elem.nodes[2].int_label) + " not found"
self.report({'ERROR'}, message)
logging.error(message)
return {'CANCELLED'}
else:
return retval

except KeyError:
self.report({'ERROR'}, "Element beam3_" + str(elem.int_label) + "not found.")
message = "Element beam3_" + str(elem.int_label) + "not found."
self.report({'ERROR'}, message)
logging.error(message)
return {'CANCELLED'}

# -----------------------------------------------------------
Expand All @@ -792,7 +768,9 @@ def execute(self, context):
ed = context.scene.mbdyn.elems
ret_val = update_beam3(ed[context.object.name])
if ret_val == 'OBJECTS_NOTFOUND':
self.report({'ERROR'}, "Unable to find Blender objects needed")
message = "Unable to find Blender objects needed"
self.report({'ERROR'}, message)
logging.error(message)
return {'CANCELLED'}
else:
return ret_val
Expand Down

0 comments on commit 42a9c7b

Please sign in to comment.