Skip to content

Commit

Permalink
some work from long ago
Browse files Browse the repository at this point in the history
  • Loading branch information
Rostislav V. Rjabow committed Apr 10, 2023
1 parent a2f1a33 commit 2671b11
Show file tree
Hide file tree
Showing 10 changed files with 157 additions and 100 deletions.
56 changes: 56 additions & 0 deletions backend.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
from abc import ABC, abstractmethod, abstractproperty
from collections import namedtuple
from pathlib import Path


PackageBrief = namedtuple('PackageBrief', ['name', 'probe_fun'])


M_SCRIPTS = Path(__file__).parent / 'script'
OUTPUT_DIR = Path(__file__).parent / 'out'
GATEWAY_DIR = Path(__file__).parent / 'gateway'
PACKAGES = [PackageBrief(name='jsonlab', probe_fun='loadjson'),
PackageBrief(name='iso2mesh', probe_fun='s2m')]


class BackendABC(ABC):
@abstractmethod
def __init__(self, engine_type: str):
pass

@

class OctaveBackend(BackendABC):
def __init__(self, engine_type: str):
self.engine_type = engine_type.lower()
if self.engine_type == 'octave':
self.EngineError2 = self.EngineError1 = __import__('oct2py.utils', globals(), locals(), ['Oct2PyError'], 0)
self.engine = __import__('oct2py', globals(), locals(), ['Oct2Py'], 0)
else:
matlab_stuff = __import__('matlab.engine', globals(), locals(), ['MatlabEngine',
'MatlabExecutionError',
'RejectedExecutionError'], 0)
self.EngineError1 = matlab_stuff.MatlabExecutionError
self.EngineError1 = matlab_stuff.RejectedExecutionError
self.engine = matlab_stuff.MatlabEngine

def __getattr__(self, item):
def inner(*args, nout: int = 0):
with self.engine() as engine:
# import
engine.addpath(M_SCRIPTS)
try:
packages_to_load = filter(lambda p: p['name'] in PACKAGES, engine.pkg('list').tolist()[0])
for package in packages_to_load:
engine.addpath(str(Path(package['dir'])))
except IndexError:
raise ImportError('No local packages installed for Octave') # TODO: another exception type
try:
return engine.feval(item, *args, nargout=nout)
except self.EngineError1:
return engine.feval(item, *args, nout=nout)
return inner


def get_backend(engine_type='octave'):
return Backend(engine_type)
39 changes: 9 additions & 30 deletions blender2mesh.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import jdata as jd
import os
from bpy.utils import register_class, unregister_class
from .backend import get_backend
from .utils import *

G_MAXVOL = 1.0
Expand Down Expand Up @@ -75,7 +76,7 @@ def description(cls, context, properties):
return [desc for idx, _, desc in ENUM_ENDSTEP if idx == properties.endstep][0]

def func(self):
outputdir = GetBPWorkFolder()
outputdir = get_bp_work_folder()
if not os.path.isdir(outputdir):
os.makedirs(outputdir)

Expand Down Expand Up @@ -166,30 +167,8 @@ def func(self):
if self.endstep < '6':
return

try:
if bpy.context.scene.blender_photonics.backend == "octave":
import oct2py as op
from oct2py.utils import Oct2PyError as OcError1
OcError2 = OcError1
oc = op.Oct2Py()
else:
import matlab.engine as op
from matlab.engine import MatlabExecutionError as OcError1, RejectedExecutionError as OcError2
oc = op.start_matlab()
except ImportError:
raise ImportError(
'To run this feature, you must install the oct2py or matlab.engine Python modulem first, based on '
'your choice of the backend')

oc.addpath(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'script'))

try:
oc.feval('blender2mesh', os.path.join(outputdir, 'blendermesh.jmsh'), nargout=0)
except OcError1 as e:
if 'too many outputs' in e.args[0]:
oc.feval('blender2mesh', os.path.join(outputdir, 'blendermesh.jmsh'), nout=0)
else:
raise
backend = get_backend(bpy.context.scene.blender_photonics.backend)
backend.blender2mesh(os.path.join(outputdir, 'blendermesh.jmsh'))

# import volume mesh to blender(just for user to check the result)
bpy.ops.object.mode_set(mode='OBJECT')
Expand All @@ -198,12 +177,12 @@ def func(self):

if not self.onlysurf:
outputmesh = jd.load(os.path.join(outputdir, 'volumemesh.jmsh'))
LoadTetMesh(outputmesh, 'Iso2Mesh')
load_tet_mesh(outputmesh, 'Iso2Mesh')
bpy.context.view_layer.objects.active = bpy.data.objects['Iso2Mesh']
else:
regiondata = jd.load(os.path.join(outputdir, 'regionmesh.jmsh'))
if len(regiondata.keys()) > 0:
LoadReginalMesh(regiondata, 'region_')
load_regional_mesh(regiondata, 'region_')
bpy.context.view_layer.objects.active = bpy.data.objects['region_1']

bpy.context.space_data.shading.type = 'WIREFRAME'
Expand All @@ -212,7 +191,7 @@ def func(self):
if self.endstep < '7':
return

ShowMessageBox(
show_message_box(
"Mesh generation is complete. The combined tetrahedral mesh is imported for inspection. To set optical "
"properties for each region, please click 'Load mesh and setup simulation'",
"BlenderPhotonics")
Expand Down Expand Up @@ -252,9 +231,9 @@ def execute(self, context):
print(self.filepath)
if not (self.filepath == ""):
if os.name == 'nt':
os.popen("copy '" + os.path.join(GetBPWorkFolder(), 'blendermesh.jmsh') + "' '" + self.filepath + "'")
os.popen("copy '" + os.path.join(get_bp_work_folder(), 'blendermesh.jmsh') + "' '" + self.filepath + "'")
else:
os.popen("cp '" + os.path.join(GetBPWorkFolder(), 'blendermesh.jmsh') + "' '" + self.filepath + "'")
os.popen("cp '" + os.path.join(get_bp_work_folder(), 'blendermesh.jmsh') + "' '" + self.filepath + "'")
return {'FINISHED'}

def invoke(self, context, event):
Expand Down
14 changes: 14 additions & 0 deletions exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
class BlenderPhotonicsError(Exception):
pass


class BlenderPhotonicsDependencyError(BlenderPhotonicsError):
"""Errors concerning missing system or Python utilities/modules/packages"""
def __init__(self, dep: str, *args, **kwargs):
self.missing_dep = dep
super().__init__(f'Required dependency not found: {dep}', *args)


class BlenderPhotonicsMeshingError(BlenderPhotonicsError):
"""Meshing failure, typically a forwarding of some backend error"""
pass
4 changes: 2 additions & 2 deletions mesh2blender.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,10 @@ def importmesh(self):
bpy.ops.object.delete()

# folder path for importing .jmsh files
outputdir = GetBPWorkFolder()
outputdir = get_bp_work_folder()

regiondata = jd.load(os.path.join(outputdir, 'regionmesh.jmsh'))
bbx = LoadReginalMesh(regiondata, 'region_')
bbx = load_regional_mesh(regiondata, 'region_')

# add properties
for obj in bpy.data.objects:
Expand Down
8 changes: 4 additions & 4 deletions nii2mesh.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class nii2mesh(bpy.types.Operator):

def vol2mesh(self):
# Remove last .jmsh file
outputdir = GetBPWorkFolder()
outputdir = get_bp_work_folder()
if not os.path.isdir(outputdir):
os.makedirs(outputdir)
if os.path.exists(os.path.join(outputdir, 'regionmesh.jmsh')):
Expand Down Expand Up @@ -106,7 +106,7 @@ def vol2mesh(self):
bpy.ops.object.delete()

regiondata = jd.load(os.path.join(outputdir, 'regionmesh.jmsh'))
regiondata = JMeshFallback(regiondata)
regiondata = jmesh_fallback(regiondata)
n = len(regiondata.keys()) - 1

# To import mesh.ply in batches
Expand All @@ -115,11 +115,11 @@ def vol2mesh(self):
if not isinstance(regiondata[surfkey], np.ndarray):
regiondata[surfkey] = np.asarray(regiondata[surfkey], dtype=np.uint32)
regiondata[surfkey] -= 1
AddMeshFromNodeFace(regiondata['MeshVertex3'], regiondata[surfkey].tolist(), 'region_' + str(i + 1))
add_mesh_from_node_face(regiondata['MeshVertex3'], regiondata[surfkey].tolist(), 'region_' + str(i + 1))

bpy.context.space_data.shading.type = 'WIREFRAME'

ShowMessageBox(
show_message_box(
"Mesh generation is complete. The combined tetrahedral mesh is imported for inspection. To set optical "
"properties for each region, please click 'Load mesh and setup simulation'",
"BlenderPhotonics")
Expand Down
20 changes: 10 additions & 10 deletions obj2surf.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,15 @@ def description(cls, context, properties):
return [desc for idx, _, desc in ENUM_ACTION if idx == properties.action][0]

def func(self):
outputdir = GetBPWorkFolder()
outputdir = get_bp_work_folder()
if not os.path.isdir(outputdir):
os.makedirs(outputdir)

if os.path.exists(os.path.join(outputdir, 'surfacemesh.jmsh')):
os.remove(os.path.join(outputdir, 'surfacemesh.jmsh'))

if len(bpy.context.selected_objects) < 1:
ShowMessageBox("Must select at least one object (for Boolean operations, select two)", "BlenderPhotonics")
show_message_box("Must select at least one object (for Boolean operations, select two)", "BlenderPhotonics")
return

# remove camera and light objects
Expand All @@ -97,7 +97,7 @@ def func(self):
bpy.ops.mesh.quads_convert_to_tris(quad_method='BEAUTY', ngon_method='BEAUTY')

if len(bpy.context.selected_objects) < 1:
ShowMessageBox("No mesh-like object was selected, skip", "BlenderPhotonics")
show_message_box("No mesh-like object was selected, skip", "BlenderPhotonics")
return

bpy.ops.object.mode_set(mode='OBJECT')
Expand All @@ -107,7 +107,7 @@ def func(self):
'http://mcx.space/BlenderPhotonics)'},
'MeshGroup': []}
for ob in bpy.context.selected_objects:
objsurf = GetNodeFacefromObject(ob, self.convtri)
objsurf = get_node_face_from_object(ob, self.convtri)
surfdata['MeshGroup'].append(objsurf)

surfdata['param'] = {'action': self.action, 'level': self.actionparam}
Expand Down Expand Up @@ -156,20 +156,20 @@ def func(self):
if 'MeshVertex3' in ob:
if ('_DataInfo_' in ob) and ('BlenderObjectName' in ob['_DataInfo_']):
objname = ob['_DataInfo_']['BlenderObjectName']
AddMeshFromNodeFace(ob['MeshVertex3'], (np.array(ob['MeshTri3']) - 1).tolist(), objname)
add_mesh_from_node_face(ob['MeshVertex3'], (np.array(ob['MeshTri3']) - 1).tolist(), objname)
bpy.context.view_layer.objects.active = bpy.data.objects[objname]
else:
for ob in surfdata['MeshGroup']:
objname = 'surf_' + str(idx)
if ('_DataInfo_' in ob) and ('BlenderObjectName' in ob['_DataInfo_']):
objname = ob['_DataInfo_']['BlenderObjectName']
AddMeshFromNodeFace(ob['MeshVertex3'], (np.array(ob['MeshTri3']) - 1).tolist(), objname)
add_mesh_from_node_face(ob['MeshVertex3'], (np.array(ob['MeshTri3']) - 1).tolist(), objname)
bpy.context.view_layer.objects.active = bpy.data.objects[objname]
idx += 1

bpy.context.space_data.shading.type = 'WIREFRAME'

ShowMessageBox("Mesh generation is complete. The combined surface mesh is imported for inspection.",
show_message_box("Mesh generation is complete. The combined surface mesh is imported for inspection.",
"BlenderPhotonics")

def execute(self, context):
Expand Down Expand Up @@ -211,9 +211,9 @@ def execute(self, context):
print(self.filepath)
if not (self.filepath == ""):
if os.name == 'nt':
os.popen("copy '" + os.path.join(GetBPWorkFolder(), 'blendersurf.jmsh') + "' '" + self.filepath + "'")
os.popen("copy '" + os.path.join(get_bp_work_folder(), 'blendersurf.jmsh') + "' '" + self.filepath + "'")
else:
os.popen("cp '" + os.path.join(GetBPWorkFolder(), 'blendersurf.jmsh') + "' '" + self.filepath + "'")
os.popen("cp '" + os.path.join(get_bp_work_folder(), 'blendersurf.jmsh') + "' '" + self.filepath + "'")
return {'FINISHED'}

def invoke(self, context, event):
Expand Down Expand Up @@ -256,7 +256,7 @@ def execute(self, context):

oc.addpath(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'script'))
surfdata = oc.feval('surf2jmesh', self.filepath)
AddMeshFromNodeFace(surfdata['MeshVertex3'], (np.array(surfdata['MeshTri3']) - 1).tolist(), 'importedsurf')
add_mesh_from_node_face(surfdata['MeshVertex3'], (np.array(surfdata['MeshTri3']) - 1).tolist(), 'importedsurf')

return {'FINISHED'}

Expand Down
6 changes: 3 additions & 3 deletions runmmc.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ def preparemmc(self):
'method': self.method, 'outputtype': self.outputtype, 'basisorder': self.basisorder,
'debuglevel': self.debuglevel, 'gpuid': self.gpuid}
print(obj['srctype'])
outputdir = GetBPWorkFolder()
outputdir = get_bp_work_folder()
if not os.path.isdir(outputdir):
os.makedirs(outputdir)

Expand Down Expand Up @@ -127,11 +127,11 @@ def preparemmc(self):
bpy.ops.object.delete()

outputmesh = jd.load(os.path.join(outputdir, 'volumemesh.jmsh'))
outputmesh = JMeshFallback(outputmesh)
outputmesh = jmesh_fallback(outputmesh)
if not isinstance(outputmesh['MeshTri3'], np.ndarray):
outputmesh['MeshTri3'] = np.asarray(outputmesh['MeshTri3'], dtype=np.uint32)
outputmesh['MeshTri3'] -= 1
AddMeshFromNodeFace(outputmesh['MeshVertex3'], outputmesh['MeshTri3'].tolist(), "Iso2Mesh")
add_mesh_from_node_face(outputmesh['MeshVertex3'], outputmesh['MeshTri3'].tolist(), "Iso2Mesh")

# add color to blender model
obj = bpy.data.objects['Iso2Mesh']
Expand Down
2 changes: 1 addition & 1 deletion script/blender2mesh.m
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,4 @@ function blender2mesh(filename)
save('-v7',bpmwpath('meshdata.mat'),'node','elem');
disp(['begin to save region mesh'])

blendersavemesh(node,elem);
blendersavemesh(node,elem,regionmesh_fname, volumemesh_fname);
8 changes: 5 additions & 3 deletions script/blendersavemesh.m
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
function blendersavemesh(node,elem)
function blendersavemesh(node,elem,regionmesh_fname,volumemesh_fname)
%
% blendersavemesh(node,elem)
%
Expand All @@ -9,6 +9,8 @@ function blendersavemesh(node,elem)
% input:
% node: the node coordinate list of a tetrahedral mesh (nn x 3)
% elem: the tetrahedral element list of the mesh (ne x 4)
% regionmesh_fname: file name to save the region mesh
% volumemesh_fname: file name to save the volume mesh
%
% output:
% two JMesh files are saved under the temporary folder bpmwpath('')
Expand Down Expand Up @@ -59,9 +61,9 @@ function blendersavemesh(node,elem)
outputmesh=rmfield(outputmesh,encodevarname('MeshTri3(1)'));
end
disp(['begin to save whole volumic mesh.'])
savejson('',outputmesh,'FileName',bpmwpath('regionmesh.jmsh'),'ArrayIndent',0);
savejson('',outputmesh,'FileName','regionmesh.jmsh','ArrayIndent',0);
faces = meshface(elem(:,1:4));

meshdata.MeshTri3=faces;
savejson('',meshdata,'FileName',bpmwpath('volumemesh.jmsh'),'ArrayIndent',0);
savejson('',meshdata,'FileName','volumemesh.jmsh','ArrayIndent',0);
disp(['saving complete.'])
Loading

0 comments on commit 2671b11

Please sign in to comment.