@@ -136,6 +136,7 @@ PyMODINIT_FUNC initFem()
|
||||
Fem::FeaturePython ::init();
|
||||
Fem::FemMesh ::init();
|
||||
Fem::FemMeshObject ::init();
|
||||
Fem::FemMeshObjectPython ::init();
|
||||
Fem::FemMeshShapeObject ::init();
|
||||
Fem::FemMeshShapeNetgenObject ::init();
|
||||
Fem::PropertyFemMesh ::init();
|
||||
|
||||
@@ -68,23 +68,26 @@ SET(FemScripts_SRCS
|
||||
_CommandBeamSection.py
|
||||
_CommandControlSolver.py
|
||||
_CommandConstraintSelfWeight.py
|
||||
_CommandMechanicalMaterial.py
|
||||
_CommandShowResult.py
|
||||
_CommandMaterialMechanicalNonlinear.py
|
||||
_CommandMeshFromShape.py
|
||||
_CommandMechanicalMaterial.py
|
||||
_CommandMeshGmshFromShape.py
|
||||
_CommandMeshNetgenFromShape.py
|
||||
_CommandPurgeResults.py
|
||||
_CommandRunSolver.py
|
||||
_CommandShellThickness.py
|
||||
_CommandShowResult.py
|
||||
_CommandSolverCalculix.py
|
||||
_CommandSolverZ88.py
|
||||
_FemBeamSection.py
|
||||
_FemConstraintSelfWeight.py
|
||||
_FemMaterialMechanicalNonlinear.py
|
||||
_FemMeshGmsh.py
|
||||
_FemShellThickness.py
|
||||
_FemSolverCalculix.py
|
||||
_FemSolverZ88.py
|
||||
_MechanicalMaterial.py
|
||||
_TaskPanelFemBeamSection.py
|
||||
_TaskPanelFemMeshGmsh.py
|
||||
_TaskPanelFemShellThickness.py
|
||||
_TaskPanelFemSolverCalculix.py
|
||||
_TaskPanelMechanicalMaterial.py
|
||||
@@ -92,6 +95,7 @@ SET(FemScripts_SRCS
|
||||
_ViewProviderFemBeamSection.py
|
||||
_ViewProviderFemConstraintSelfWeight.py
|
||||
_ViewProviderFemMaterialMechanicalNonlinear.py
|
||||
_ViewProviderFemMeshGmsh.py
|
||||
_ViewProviderFemShellThickness.py
|
||||
_ViewProviderFemSolverCalculix.py
|
||||
_ViewProviderFemSolverZ88.py
|
||||
@@ -107,10 +111,12 @@ SET(FemScripts_SRCS
|
||||
FemBeamSection.py
|
||||
FemCommands.py
|
||||
FemConstraintSelfWeight.py
|
||||
FemGmshTools.py
|
||||
FemInputWriter.py
|
||||
FemInputWriterCcx.py
|
||||
FemInputWriterZ88.py
|
||||
FemMaterialMechanicalNonlinear.py
|
||||
FemMeshGmsh.py
|
||||
FemMeshTools.py
|
||||
FemShellThickness.py
|
||||
FemSolverCalculix.py
|
||||
@@ -123,6 +129,7 @@ SET(FemScripts_SRCS
|
||||
TestFem.py
|
||||
z88DispReader.py
|
||||
TaskPanelFemBeamSection.ui
|
||||
TaskPanelFemMeshGmsh.ui
|
||||
TaskPanelFemShellThickness.ui
|
||||
TaskPanelFemSolverCalculix.ui
|
||||
TaskPanelMechanicalMaterial.ui
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "FemMeshObject.h"
|
||||
#include "FemMesh.h"
|
||||
#include <App/DocumentObjectPy.h>
|
||||
#include <App/FeaturePythonPyImp.h>
|
||||
#include <Base/Placement.h>
|
||||
|
||||
using namespace Fem;
|
||||
@@ -70,3 +71,25 @@ void FemMeshObject::onChanged(const Property* prop)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Python feature ---------------------------------------------------------
|
||||
|
||||
namespace App {
|
||||
/// @cond DOXERR
|
||||
PROPERTY_SOURCE_TEMPLATE(Fem::FemMeshObjectPython, Fem::FemMeshObject)
|
||||
template<> const char* Fem::FemMeshObjectPython::getViewProviderName(void) const {
|
||||
return "FemGui::ViewProviderFemMeshPython";
|
||||
}
|
||||
|
||||
template<> PyObject* Fem::FemMeshObjectPython::getPyObject(void) {
|
||||
if (PythonObject.is(Py::_None())) {
|
||||
// ref counter is set to 1
|
||||
PythonObject = Py::Object(new App::FeaturePythonPyT<App::DocumentObjectPy>(this),true);
|
||||
}
|
||||
return Py::new_reference_to(PythonObject);
|
||||
}
|
||||
|
||||
// explicit template instantiation
|
||||
template class AppFemExport FeaturePythonT<Fem::FemMeshObject>;
|
||||
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#ifndef Fem_FemMeshObject_H
|
||||
#define Fem_FemMeshObject_H
|
||||
|
||||
#include <App/FeaturePython.h>
|
||||
#include <App/GeoFeature.h>
|
||||
#include <App/PropertyFile.h>
|
||||
#include <App/PropertyGeo.h>
|
||||
@@ -60,6 +61,9 @@ protected:
|
||||
virtual void onChanged (const App::Property* prop);
|
||||
};
|
||||
|
||||
typedef App::FeaturePythonT<FemMeshObject> FemMeshObjectPython;
|
||||
|
||||
|
||||
} //namespace Fem
|
||||
|
||||
|
||||
|
||||
@@ -28,8 +28,6 @@
|
||||
#endif
|
||||
|
||||
#include "FemSolverObject.h"
|
||||
|
||||
#include <Base/FileInfo.h>
|
||||
#include <App/FeaturePythonPyImp.h>
|
||||
#include <App/DocumentObjectPy.h>
|
||||
|
||||
@@ -42,20 +40,7 @@ PROPERTY_SOURCE(Fem::FemSolverObject, App::DocumentObject)
|
||||
|
||||
FemSolverObject::FemSolverObject()
|
||||
{
|
||||
|
||||
/*
|
||||
ADD_PROPERTY_TYPE(SolverName,("Calculix"), "Data",Prop_None,"Solver program name");
|
||||
ADD_PROPERTY_TYPE(Category,("FEM"), "Data",Prop_None,"FEM, CFD ...");
|
||||
ADD_PROPERTY_TYPE(Module,(""), "Data",Prop_None,"Python module name");
|
||||
ADD_PROPERTY_TYPE(ExternalCaseEditor,(""), "Data",Prop_None,"External case editor programe");
|
||||
ADD_PROPERTY_TYPE(ExternalResultViewer,(""), "Data",Prop_None,"External result viewer name");
|
||||
|
||||
ADD_PROPERTY_TYPE(AnalysisType,("Static"), "Solver",Prop_None,"Specific analysis type");
|
||||
ADD_PROPERTY_TYPE(WorkingDir,(Base::FileInfo::getTempPath()), "Solver",Prop_None,"Solver working directory");
|
||||
ADD_PROPERTY_TYPE(InputCaseName,("TestCase"), "Solver",Prop_None,"Solver input file without suffix");
|
||||
ADD_PROPERTY_TYPE(Parallel,(false), "Solver",Prop_None,"Run solver in parallel like MPI");
|
||||
ADD_PROPERTY_TYPE(ResultObtained,(false), "Solver",Prop_None,"if true, result has been obtained");
|
||||
*/
|
||||
// Attributes are implemented in the FemSolverObjectPython
|
||||
}
|
||||
|
||||
FemSolverObject::~FemSolverObject()
|
||||
|
||||
@@ -25,11 +25,7 @@
|
||||
#ifndef Fem_FemSolverObject_H
|
||||
#define Fem_FemSolverObject_H
|
||||
|
||||
#include <App/DocumentObject.h>
|
||||
#include <App/PropertyUnits.h>
|
||||
#include <App/PropertyStandard.h>
|
||||
#include <App/FeaturePython.h>
|
||||
#include "FemSolverObject.h"
|
||||
|
||||
namespace Fem
|
||||
{
|
||||
@@ -43,29 +39,7 @@ public:
|
||||
FemSolverObject(void);
|
||||
virtual ~FemSolverObject();
|
||||
|
||||
/*
|
||||
/// Solver name, unique to identify solver in registered_solver dict
|
||||
App::PropertyString SolverName;
|
||||
/// CAE category like FEM, all capitalised letters
|
||||
App::PropertyString Category;
|
||||
/// python module name
|
||||
App::PropertyString Module;
|
||||
/// Path or program name for external case editor, empty string means using FreeCAD to view
|
||||
App::PropertyString ExternalCaseEditor;
|
||||
/// Path to External Result Viewer like Paraview, empty string means using FreeCAD
|
||||
App::PropertyString ExternalResultViewer;
|
||||
|
||||
/// for FEM: Static, Frequency, etc
|
||||
App::PropertyString AnalysisType;
|
||||
/// Path of working dir for the solver
|
||||
App::PropertyString WorkingDir;
|
||||
/// name for the case file without suffix
|
||||
App::PropertyString InputCaseName;
|
||||
/// run parallel in MPI (message passing interface)/multiple cores or serial(single CPU)
|
||||
App::PropertyBool Parallel;
|
||||
/// result has been obtained, purge result may be needed for rerun
|
||||
App::PropertyBool ResultObtained;
|
||||
*/
|
||||
// Attributes are implemented in the FemSolverObjectPython
|
||||
|
||||
/// returns the type name of the ViewProvider
|
||||
virtual const char* getViewProviderName(void) const {
|
||||
|
||||
@@ -24,7 +24,7 @@ INSTALL(
|
||||
TestFem.py
|
||||
|
||||
FemCommands.py
|
||||
_CommandMeshFromShape.py
|
||||
_CommandMeshNetgenFromShape.py
|
||||
_CommandPurgeResults.py
|
||||
_CommandRunSolver.py
|
||||
_CommandControlSolver.py
|
||||
@@ -36,6 +36,15 @@ INSTALL(
|
||||
FemAnalysis.py
|
||||
_CommandAnalysis.py
|
||||
|
||||
FemMeshGmsh.py
|
||||
_FemMeshGmsh.py
|
||||
_ViewProviderFemMeshGmsh.py
|
||||
_CommandMeshGmshFromShape.py
|
||||
_TaskPanelFemMeshGmsh.py
|
||||
TaskPanelFemMeshGmsh.ui
|
||||
|
||||
FemGmshTools.py
|
||||
|
||||
FemBeamSection.py
|
||||
_FemBeamSection.py
|
||||
_ViewProviderFemBeamSection.py
|
||||
@@ -50,6 +59,11 @@ INSTALL(
|
||||
_TaskPanelFemShellThickness.py
|
||||
TaskPanelFemShellThickness.ui
|
||||
|
||||
FemConstraintSelfWeight.py
|
||||
_FemConstraintSelfWeight.py
|
||||
_ViewProviderFemConstraintSelfWeight.py
|
||||
_CommandConstraintSelfWeight.py
|
||||
|
||||
MechanicalMaterial.py
|
||||
_MechanicalMaterial.py
|
||||
_ViewProviderMechanicalMaterial.py
|
||||
@@ -85,11 +99,6 @@ INSTALL(
|
||||
_ViewProviderFemSolverZ88.py
|
||||
_CommandSolverZ88.py
|
||||
|
||||
FemConstraintSelfWeight.py
|
||||
_FemConstraintSelfWeight.py
|
||||
_ViewProviderFemConstraintSelfWeight.py
|
||||
_CommandConstraintSelfWeight.py
|
||||
|
||||
DESTINATION
|
||||
Mod/Fem
|
||||
)
|
||||
|
||||
@@ -20,8 +20,6 @@
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
|
||||
import FreeCAD
|
||||
|
||||
__title__ = "FEM Analysis managment"
|
||||
__author__ = "Juergen Riegel"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
@@ -29,6 +27,9 @@ __url__ = "http://www.freecadweb.org"
|
||||
## \addtogroup FEM
|
||||
# @{
|
||||
|
||||
import FreeCAD
|
||||
|
||||
|
||||
def makeFemAnalysis(name):
|
||||
'''makeFemAnalysis(name): makes a Fem Analysis object'''
|
||||
obj = FreeCAD.ActiveDocument.addObject("Fem::FemAnalysisPython", name)
|
||||
|
||||
@@ -24,12 +24,12 @@ __title__ = "FemBeamSection"
|
||||
__author__ = "Bernd Hahnebach"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
## \addtogroup FEM
|
||||
# @{
|
||||
|
||||
import FreeCAD
|
||||
import _FemBeamSection
|
||||
|
||||
## \addtogroup FEM
|
||||
# @{
|
||||
|
||||
def makeFemBeamSection(width=20.0, height=20.0, name="BeamSection"):
|
||||
'''makeFemBeamSection([width], [height], [name]): creates an beamsection object to define a cross section'''
|
||||
|
||||
@@ -25,15 +25,15 @@ __title__ = "Fem Commands"
|
||||
__author__ = "Przemo Firszt"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
import FreeCAD
|
||||
## \addtogroup FEM
|
||||
# @{
|
||||
|
||||
import FreeCAD
|
||||
if FreeCAD.GuiUp:
|
||||
import FreeCADGui
|
||||
import FemGui
|
||||
from PySide import QtCore
|
||||
|
||||
## \addtogroup FEM
|
||||
# @{
|
||||
|
||||
class FemCommands(object):
|
||||
def __init__(self):
|
||||
|
||||
@@ -24,12 +24,12 @@ __title__ = "FemConstraintSelfWeight"
|
||||
__author__ = "Bernd Hahnebach"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
## \addtogroup FEM
|
||||
# @{
|
||||
|
||||
import FreeCAD
|
||||
import _FemConstraintSelfWeight
|
||||
|
||||
## \addtogroup FEM
|
||||
# @{
|
||||
|
||||
def makeFemConstraintSelfWeight(name="FemConstraintSelfWeight"):
|
||||
'''makeFemFemConstraintSelfWeight([name]): creates an self weight object to define a gravity load'''
|
||||
|
||||
271
src/Mod/Fem/FemGmshTools.py
Normal file
271
src/Mod/Fem/FemGmshTools.py
Normal file
@@ -0,0 +1,271 @@
|
||||
# ***************************************************************************
|
||||
# * *
|
||||
# * Copyright (c) 2016 - Bernd Hahnebach <bernd@bimstatik.org> *
|
||||
# * *
|
||||
# * This program is free software; you can redistribute it and/or modify *
|
||||
# * it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
# * as published by the Free Software Foundation; either version 2 of *
|
||||
# * the License, or (at your option) any later version. *
|
||||
# * for detail see the LICENCE text file. *
|
||||
# * *
|
||||
# * 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 Library General Public License for more details. *
|
||||
# * *
|
||||
# * You should have received a copy of the GNU Library 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 *
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
|
||||
__title__ = "Tools for the work with GMSH mesher"
|
||||
__author__ = "Bernd Hahnebach"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
## \addtogroup FEM
|
||||
# @{
|
||||
|
||||
import FreeCAD
|
||||
import Fem
|
||||
import subprocess
|
||||
import tempfile
|
||||
from platform import system
|
||||
|
||||
|
||||
class FemGmshTools():
|
||||
def __init__(self, gmsh_mesh_obj, analysis=None):
|
||||
self.mesh_obj = gmsh_mesh_obj
|
||||
if analysis:
|
||||
self.analysis = analysis
|
||||
# group meshing turned on
|
||||
else:
|
||||
self.analysis = None
|
||||
# group meshing turned off
|
||||
|
||||
# part to mesh
|
||||
self.part_obj = self.mesh_obj.Part
|
||||
|
||||
# clmax, ElementSizeMax: float, 0.0 = 1e+22
|
||||
self.clmax = self.mesh_obj.ElementSizeMax
|
||||
if self.clmax == 0.0:
|
||||
self.clmax = 1e+22
|
||||
|
||||
# clmin, ElementSizeMin: float
|
||||
self.clmin = self.mesh_obj.ElementSizeMin
|
||||
|
||||
# order, ElementOrder: ['Auto', '1st', '2nd']
|
||||
self.order = self.mesh_obj.ElementOrder
|
||||
if self.order == '1st':
|
||||
self.order = '1'
|
||||
elif self.order == 'Auto' or self.order == '2nd':
|
||||
self.order = '2'
|
||||
else:
|
||||
print('Error in order')
|
||||
|
||||
# dimension, ElementDimension: ['Auto', '1D', '2D', '3D']
|
||||
self.dimension = self.mesh_obj.ElementDimension
|
||||
|
||||
def create_mesh(self):
|
||||
print("\nWe gone start GMSH FEM mesh run!")
|
||||
print(' Part to mesh: Name --> ' + self.part_obj.Name + ', Label --> ' + self.part_obj.Label + ', ShapeType --> ' + self.part_obj.Shape.ShapeType)
|
||||
print(' ElementSizeMax: ' + str(self.clmax))
|
||||
print(' ElementSizeMin: ' + str(self.clmin))
|
||||
print(' ElementOrder: ' + self.order)
|
||||
self.get_dimension()
|
||||
self.get_tmp_file_paths()
|
||||
self.get_gmsh_command()
|
||||
self.get_group_data()
|
||||
self.write_part_file()
|
||||
self.write_geo()
|
||||
error = self.run_gmsh_with_geo()
|
||||
self.read_and_set_new_mesh()
|
||||
return error
|
||||
|
||||
def get_dimension(self):
|
||||
# Dimension
|
||||
# GMSH uses the hightest availabe.
|
||||
# A use case for not auto would be a surface (2D) mesh of a solid or other 3d shape
|
||||
if self.dimension == 'Auto':
|
||||
shty = self.part_obj.Shape.ShapeType
|
||||
if shty == 'Solid' or shty == 'CompSolid':
|
||||
# print('Found: ' + shty)
|
||||
self.dimension = '3'
|
||||
elif shty == 'Face' or shty == 'Shell':
|
||||
# print('Found: ' + shty)
|
||||
self.dimension = '2'
|
||||
elif shty == 'Edge' or shty == 'Wire':
|
||||
# print('Found: ' + shty)
|
||||
self.dimension = '1'
|
||||
elif shty == 'Vertex':
|
||||
# print('Found: ' + shty)
|
||||
FreeCAD.Console.PrintError("You can not mesh a Vertex.\n")
|
||||
self.dimension = '0'
|
||||
elif shty == 'Compound':
|
||||
print('Found: ' + shty)
|
||||
print('I do not know what is inside your Compound. Dimension was set to 3 anyway.')
|
||||
# TODO check contents of Compound
|
||||
# use dimension 3 on any shape works for 2D and 1d meshes as well !
|
||||
# but not in combination with sewfaces or connectfaces
|
||||
self.dimension = '3'
|
||||
else:
|
||||
self.dimension = '0'
|
||||
FreeCAD.Console.PrintError('Could not retrive Dimension from shape type. Please choose dimension.')
|
||||
elif self.dimension == '3D':
|
||||
self.dimension = '3'
|
||||
elif self.dimension == '2D':
|
||||
self.dimension = '2'
|
||||
elif self.dimension == '1D':
|
||||
self.dimension = '1'
|
||||
else:
|
||||
print('Error in dimension')
|
||||
print(' ElementDimension: ' + self.dimension)
|
||||
|
||||
def get_tmp_file_paths(self):
|
||||
if system() == "Linux":
|
||||
path_sep = "/"
|
||||
elif system() == "Windows":
|
||||
path_sep = "\\"
|
||||
else:
|
||||
path_sep = "/"
|
||||
tmpdir = tempfile.gettempdir()
|
||||
# geometry file
|
||||
self.temp_file_geometry = tmpdir + path_sep + self.part_obj.Name + '_Geometry.brep'
|
||||
print(' ' + self.temp_file_geometry)
|
||||
# mesh file
|
||||
self.mesh_name = self.part_obj.Name + '_Mesh_TmpGmsh'
|
||||
self.temp_file_mesh = tmpdir + path_sep + self.mesh_name + '.unv'
|
||||
print(' ' + self.temp_file_mesh)
|
||||
# GMSH input file
|
||||
self.temp_file_geo = tmpdir + path_sep + 'shape2mesh.geo'
|
||||
print(' ' + self.temp_file_geo)
|
||||
|
||||
def get_gmsh_command(self):
|
||||
self.gmsh_bin = None
|
||||
gmsh_std_location = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem/Gmsh").GetBool("UseStandardGmshLocation")
|
||||
if gmsh_std_location:
|
||||
if system() == "Windows":
|
||||
gmsh_path = FreeCAD.getHomePath() + "bin/gmsh.exe"
|
||||
FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem/Gmsh").SetString("gmshBinaryPath", gmsh_path)
|
||||
self.gmsh_bin = gmsh_path
|
||||
elif system() == "Linux":
|
||||
p1 = subprocess.Popen(['which', 'gmsh'], stdout=subprocess.PIPE)
|
||||
if p1.wait() == 0:
|
||||
gmsh_path = p1.stdout.read().split('\n')[0]
|
||||
elif p1.wait() == 1:
|
||||
error_message = "GMSH binary gmsh not found in standard system binary path. Please install gmsh or set path to binary in FEM preferences tab GMSH.\n"
|
||||
# if FreeCAD.GuiUp:
|
||||
# QtGui.QMessageBox.critical(None, "No GMSH binary ccx", error_message)
|
||||
raise Exception(error_message)
|
||||
self.gmsh_bin = gmsh_path
|
||||
else:
|
||||
if not self.gmsh_bin:
|
||||
self.gmsh_bin = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem/Gmsh").GetString("gmshBinaryPath", "")
|
||||
if not self.gmsh_bin: # in prefs not set, we will try to use something reasonable
|
||||
if system() == "Linux":
|
||||
self.gmsh_bin = "gmsh"
|
||||
elif system() == "Windows":
|
||||
self.gmsh_bin = FreeCAD.getHomePath() + "bin/gmsh.exe"
|
||||
else:
|
||||
self.gmsh_bin = "gmsh"
|
||||
self.gmsh_bin = self.gmsh_bin
|
||||
print(' ' + self.gmsh_bin)
|
||||
|
||||
def get_group_data(self):
|
||||
if self.analysis:
|
||||
print(' Group meshing.')
|
||||
import FemMeshTools
|
||||
self.group_elements = FemMeshTools.get_analysis_group_elements(self.analysis, self.part_obj)
|
||||
print(self.group_elements)
|
||||
else:
|
||||
print(' NO group meshing.')
|
||||
|
||||
def write_part_file(self):
|
||||
self.part_obj.Shape.exportBrep(self.temp_file_geometry)
|
||||
|
||||
def write_geo(self):
|
||||
geo = open(self.temp_file_geo, "w")
|
||||
geo.write('Merge "' + self.temp_file_geometry + '";\n')
|
||||
geo.write("\n")
|
||||
if self.analysis and self.group_elements:
|
||||
print(' We gone have found elements to make mesh groups for!')
|
||||
geo.write("// group data\n")
|
||||
# we use the element name of FreeCAD which starts with 1 (example: 'Face1'), same as GMSH
|
||||
for group in self.group_elements:
|
||||
gdata = self.group_elements[group]
|
||||
# print(gdata)
|
||||
# geo.write("// " + group + "\n")
|
||||
ele_nr = ''
|
||||
if gdata[0].startswith('Solid'):
|
||||
physical_type = 'Volume'
|
||||
for ele in gdata:
|
||||
ele_nr += (ele.lstrip('Solid') + ', ')
|
||||
elif gdata[0].startswith('Face'):
|
||||
physical_type = 'Surface'
|
||||
for ele in gdata:
|
||||
ele_nr += (ele.lstrip('Face') + ', ')
|
||||
elif gdata[0].startswith('Edge') or gdata[0].startswith('Vertex'):
|
||||
geo.write("// " + group + " group data not written. Edges or Vertexes group data not supported.\n")
|
||||
print(' Groups for Edges or Vertexes reference shapes not handeled yet.')
|
||||
if ele_nr:
|
||||
ele_nr = ele_nr.rstrip(', ')
|
||||
# print(ele_nr)
|
||||
geo.write('Physical ' + physical_type + '("' + group + '") = {' + ele_nr + '};\n')
|
||||
geo.write("\n")
|
||||
geo.write("Mesh.CharacteristicLengthMax = " + str(self.clmax) + ";\n")
|
||||
geo.write("Mesh.CharacteristicLengthMin = " + str(self.clmin) + ";\n")
|
||||
geo.write("Mesh.ElementOrder = " + self.order + ";\n")
|
||||
geo.write("//Mesh.HighOrderOptimize = 1;\n") # but does not really work, in GUI it does
|
||||
geo.write("Mesh.Algorithm3D = 1;\n")
|
||||
geo.write("Mesh.Algorithm = 2;\n")
|
||||
geo.write("Mesh " + self.dimension + ";\n")
|
||||
geo.write("Mesh.Format = 2;\n") # unv
|
||||
if self.analysis and self.group_elements:
|
||||
geo.write("// For each group save not only the elements but the nodes too.;\n")
|
||||
geo.write("Mesh.SaveGroupsOfNodes = 1;\n")
|
||||
geo.write("// Needed for Group meshing too, because for one material there is no group defined;\n") # belongs to Mesh.SaveAll but anly needed if there are groups
|
||||
geo.write("// Ignore Physical definitions and save all elements;\n")
|
||||
geo.write("Mesh.SaveAll = 1;\n")
|
||||
geo.write("\n")
|
||||
geo.write('Save "' + self.temp_file_mesh + '";\n')
|
||||
geo.write("\n\n")
|
||||
geo.write("//////////////////////////////////////////////////////////////////////\n")
|
||||
geo.write("// GMSH documentation:\n")
|
||||
geo.write("// http://gmsh.info/doc/texinfo/gmsh.html#Mesh\n")
|
||||
geo.write("//\n")
|
||||
geo.write("// We do not check if something went wrong, like negative jacobians etc. You can run GMSH manually yourself: \n")
|
||||
geo.write("//\n")
|
||||
geo.write("// to see full GMSH log, run in bash:\n")
|
||||
geo.write("// " + self.gmsh_bin + " - " + self.temp_file_geo + "\n")
|
||||
geo.write("//\n")
|
||||
geo.write("// to run GMSH and keep file in GMSH GUI (with log), run in bash:\n")
|
||||
geo.write("// " + self.gmsh_bin + " " + self.temp_file_geo + "\n")
|
||||
geo.close
|
||||
|
||||
def run_gmsh_with_geo(self):
|
||||
self.error = False
|
||||
comandlist = [self.gmsh_bin, '-', self.temp_file_geo]
|
||||
# print(comandlist)
|
||||
try:
|
||||
p = subprocess.Popen(comandlist, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
output, error = p.communicate()
|
||||
# print(output) # stdout is still cut at some point but the warnings are in stderr and thus printed :-)
|
||||
# print(error)
|
||||
except:
|
||||
error = 'Error executing: {}\n'.format(self.gmsh_command)
|
||||
FreeCAD.Console.PrintError(error)
|
||||
self.error = True
|
||||
return error
|
||||
|
||||
def read_and_set_new_mesh(self):
|
||||
if not self.error:
|
||||
fem_mesh = Fem.read(self.temp_file_mesh)
|
||||
self.mesh_obj.FemMesh = fem_mesh
|
||||
print(' The Part should have a pretty new FEM mesh!')
|
||||
else:
|
||||
print('No mesh was created.')
|
||||
del self.temp_file_geometry
|
||||
del self.temp_file_mesh
|
||||
|
||||
# @}
|
||||
@@ -20,27 +20,17 @@
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
|
||||
|
||||
'''
|
||||
- next step would be save the constraints node and element data in the in the FreeCAD FEM Mesh Object
|
||||
and link them to the appropriate constraint object
|
||||
- if the informations are used by the FEM Mesh file exporter FreeCAD would support writing FEM Mesh Groups
|
||||
- which is a most needed feature of FEM module
|
||||
- smesh supports mesh groups, how about pythonbinding in FreeCAD. Is there somethin implemented allready?
|
||||
'''
|
||||
|
||||
|
||||
__title__ = "FemInputWriter"
|
||||
__author__ = "Bernd Hahnebach"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
## \addtogroup FEM
|
||||
# @{
|
||||
|
||||
import FreeCAD
|
||||
import FemMeshTools
|
||||
import os
|
||||
|
||||
## \addtogroup FEM
|
||||
# @{
|
||||
|
||||
class FemInputWriter():
|
||||
def __init__(self,
|
||||
@@ -85,6 +75,7 @@ class FemInputWriter():
|
||||
self.femnodes_mesh = {}
|
||||
self.femelement_table = {}
|
||||
self.constraint_conflict_nodes = []
|
||||
self.femnodes_ele_table = {}
|
||||
|
||||
def get_constraints_fixed_nodes(self):
|
||||
# get nodes
|
||||
@@ -159,9 +150,25 @@ class FemInputWriter():
|
||||
def get_constraints_pressure_faces(self):
|
||||
# TODO see comments in get_constraints_force_nodeloads(), it applies here too. Mhh it applies to all constraints ...
|
||||
|
||||
'''
|
||||
# depreciated version
|
||||
# get the faces and face numbers
|
||||
for femobj in self.pressure_objects: # femobj --> dict, FreeCAD document object is femobj['Object']
|
||||
femobj['PressureFaces'] = FemMeshTools.get_pressure_obj_faces(self.femmesh, femobj)
|
||||
# print femobj['PressureFaces']
|
||||
femobj['PressureFaces'] = FemMeshTools.get_pressure_obj_faces_depreciated(self.femmesh, femobj)
|
||||
# print(femobj['PressureFaces'])
|
||||
'''
|
||||
|
||||
if not self.femnodes_mesh:
|
||||
self.femnodes_mesh = self.femmesh.Nodes
|
||||
if not self.femelement_table:
|
||||
self.femelement_table = FemMeshTools.get_femelement_table(self.femmesh)
|
||||
if not self.femnodes_ele_table:
|
||||
self.femnodes_ele_table = FemMeshTools.get_femnodes_ele_table(self.femnodes_mesh, self.femelement_table)
|
||||
|
||||
for femobj in self.pressure_objects: # femobj --> dict, FreeCAD document object is femobj['Object']
|
||||
pressure_faces = FemMeshTools.get_pressure_obj_faces(self.femmesh, self.femelement_table, self.femnodes_ele_table, femobj)
|
||||
# print(len(pressure_faces))
|
||||
femobj['PressureFaces'] = [(femobj['Object'].Name + ': face load', pressure_faces)]
|
||||
# print(femobj['PressureFaces'])
|
||||
|
||||
# @}
|
||||
|
||||
@@ -21,11 +21,12 @@
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
|
||||
|
||||
__title__ = "FemInputWriterCcx"
|
||||
__author__ = "Przemo Firszt, Bernd Hahnebach"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
## \addtogroup FEM
|
||||
# @{
|
||||
|
||||
import FreeCAD
|
||||
import os
|
||||
@@ -34,8 +35,6 @@ import time
|
||||
import FemMeshTools
|
||||
import FemInputWriter
|
||||
|
||||
## \addtogroup FEM
|
||||
# @{
|
||||
|
||||
class FemInputWriterCcx(FemInputWriter.FemInputWriter):
|
||||
def __init__(self,
|
||||
@@ -66,7 +65,7 @@ class FemInputWriterCcx(FemInputWriter.FemInputWriter):
|
||||
print('FemInputWriterCcx --> self.file_name --> ' + self.file_name)
|
||||
|
||||
def write_calculix_input_file(self):
|
||||
if self.solver_obj.SplitInputWriter == True:
|
||||
if self.solver_obj.SplitInputWriter is True:
|
||||
self.write_calculix_splitted_input_file()
|
||||
else:
|
||||
self.write_calculix_one_input_file()
|
||||
@@ -974,7 +973,12 @@ class FemInputWriterCcx(FemInputWriter.FemInputWriter):
|
||||
if all_found is False:
|
||||
if not self.femelement_table:
|
||||
self.femelement_table = FemMeshTools.get_femelement_table(self.femmesh)
|
||||
FemMeshTools.get_femelement_sets(self.femmesh, self.femelement_table, self.material_objects)
|
||||
# we gone use the binary search for get_femelements_by_femnodes(), thus we need the parameter values self.femnodes_ele_table
|
||||
if not self.femnodes_mesh:
|
||||
self.femnodes_mesh = self.femmesh.Nodes
|
||||
if not self.femnodes_ele_table:
|
||||
self.femnodes_ele_table = FemMeshTools.get_femnodes_ele_table(self.femnodes_mesh, self.femelement_table)
|
||||
FemMeshTools.get_femelement_sets(self.femmesh, self.femelement_table, self.material_objects, self.femnodes_ele_table)
|
||||
for mat_data in self.material_objects:
|
||||
mat_obj = mat_data['Object']
|
||||
ccx_elset = {}
|
||||
|
||||
@@ -20,19 +20,18 @@
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
|
||||
|
||||
__title__ = "FemInputWriterZ88"
|
||||
__author__ = "Bernd Hahnebach"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
## \addtogroup FEM
|
||||
# @{
|
||||
|
||||
import FreeCAD
|
||||
import FemMeshTools
|
||||
import importZ88Mesh
|
||||
import FemInputWriter
|
||||
|
||||
## \addtogroup FEM
|
||||
# @{
|
||||
|
||||
class FemInputWriterZ88(FemInputWriter.FemInputWriter):
|
||||
def __init__(self,
|
||||
|
||||
@@ -24,13 +24,13 @@ __title__ = "FemMaterialMechanicalNonlinear"
|
||||
__author__ = "Bernd Hahnebach"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
## \addtogroup FEM
|
||||
# @{
|
||||
|
||||
import FreeCAD
|
||||
import FemGui
|
||||
import _FemMaterialMechanicalNonlinear
|
||||
|
||||
## \addtogroup FEM
|
||||
# @{
|
||||
|
||||
def makeFemMaterialMechanicalNonlinear(base_material, name="MechanicalMaterialNonlinear"):
|
||||
'''makeFemMaterialMechanicalNonlinear(base_material, [name]): creates an nonlinear material object'''
|
||||
|
||||
43
src/Mod/Fem/FemMeshGmsh.py
Normal file
43
src/Mod/Fem/FemMeshGmsh.py
Normal file
@@ -0,0 +1,43 @@
|
||||
# ***************************************************************************
|
||||
# * *
|
||||
# * Copyright (c) 2016 - Bernd Hahnebach <bernd@bimstatik.org> *
|
||||
# * *
|
||||
# * This program is free software; you can redistribute it and/or modify *
|
||||
# * it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
# * as published by the Free Software Foundation; either version 2 of *
|
||||
# * the License, or (at your option) any later version. *
|
||||
# * for detail see the LICENCE text file. *
|
||||
# * *
|
||||
# * 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 Library General Public License for more details. *
|
||||
# * *
|
||||
# * You should have received a copy of the GNU Library 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 *
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
|
||||
__title__ = "FemMeshGmsh"
|
||||
__author__ = "Bernd Hahnebach"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
## \addtogroup FEM
|
||||
# @{
|
||||
|
||||
import FreeCAD
|
||||
import _FemMeshGmsh
|
||||
|
||||
|
||||
def makeFemMeshGmsh(name="FEMMeshGMSH"):
|
||||
'''makeFemMeshGmsh(name): makes a GMSH FEM mesh object'''
|
||||
obj = FreeCAD.ActiveDocument.addObject("Fem::FemMeshObjectPython", name)
|
||||
_FemMeshGmsh._FemMeshGmsh(obj)
|
||||
if FreeCAD.GuiUp:
|
||||
import _ViewProviderFemMeshGmsh
|
||||
_ViewProviderFemMeshGmsh._ViewProviderFemMeshGmsh(obj.ViewObject)
|
||||
return obj
|
||||
|
||||
# @}
|
||||
@@ -20,35 +20,39 @@
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
|
||||
|
||||
__title__ = "Tools for the work with FEM meshes"
|
||||
__author__ = "Bernd Hahnebach"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
## \addtogroup FEM
|
||||
# @{
|
||||
|
||||
import FreeCAD
|
||||
|
||||
## \addtogroup FEM
|
||||
# @{
|
||||
|
||||
def get_femnodes_by_femobj_with_references(femmesh, femobj):
|
||||
node_set = []
|
||||
if femmesh.GroupCount:
|
||||
node_set = get_femnode_set_from_group_data(femmesh, femobj)
|
||||
# print 'node_set_group: ', node_set
|
||||
# print('node_set_group: ', node_set)
|
||||
if not node_set:
|
||||
node_set = get_femnodes_by_references(femmesh, femobj['Object'].References)
|
||||
# print 'node_set_nogroup: ', node_set
|
||||
# print('node_set_nogroup: ', node_set)
|
||||
return node_set
|
||||
|
||||
|
||||
def get_femelements_by_references(femmesh, femelement_table, references):
|
||||
def get_femelements_by_references(femmesh, femelement_table, references, femnodes_ele_table=None):
|
||||
'''get the femelements for a list of references
|
||||
'''
|
||||
references_femelements = []
|
||||
for ref in references:
|
||||
ref_femnodes = get_femnodes_by_refshape(femmesh, ref) # femnodes for the current ref
|
||||
references_femelements += get_femelements_by_femnodes(femelement_table, ref_femnodes) # femelements for all references
|
||||
if femnodes_ele_table:
|
||||
# blind fast binary search, works for volumes only
|
||||
references_femelements += get_femelements_by_femnodes_bin(femelement_table, femnodes_ele_table, ref_femnodes) # femelements for all references
|
||||
else:
|
||||
# standars search
|
||||
references_femelements += get_femelements_by_femnodes_std(femelement_table, ref_femnodes) # femelements for all references
|
||||
return references_femelements
|
||||
|
||||
|
||||
@@ -103,12 +107,160 @@ def get_femelement_table(femmesh):
|
||||
return femelement_table
|
||||
|
||||
|
||||
def get_femelements_by_femnodes(femelement_table, node_list):
|
||||
def get_femnodes_ele_table(femnodes_mesh, femelement_table):
|
||||
'''the femnodes_ele_table contains for each node its membership in elements
|
||||
{nodeID : [[eleID, NodePosition], [], ...], nodeID : [[], [], ...], ...}
|
||||
stored informatation are:
|
||||
element number, the number of nodes per element, the position of the node in the element.
|
||||
The position of the node in the element is coded as a set bit at that position in a bit array (integer)
|
||||
Fixme: the number of nodes per element should be replaced by the type of the element
|
||||
but I did not know, how to get this from the mesh.
|
||||
Since the femelement_table contains either volume or face or edgemesh the femnodes_ele_table only
|
||||
has either volume or face or edge elements, see get_femelement_table()
|
||||
'''
|
||||
femnodes_ele_table = {} # node_dict in ulrichs class
|
||||
for n in femnodes_mesh: # initialize it with sorted node keys and empty lists
|
||||
femnodes_ele_table[n] = []
|
||||
for ele in femelement_table:
|
||||
ele_list = femelement_table[ele]
|
||||
# print(ele_list)
|
||||
pos = int(1)
|
||||
for ele_node in ele_list:
|
||||
femnodes_ele_table[ele_node].append([ele, pos])
|
||||
pos = pos << 1
|
||||
print('len femnodes_ele_table:' + str(len(femnodes_ele_table)))
|
||||
# print('femnodes_ele_table: ', femnodes_ele_table)
|
||||
return femnodes_ele_table
|
||||
|
||||
|
||||
def get_copy_of_empty_femelement_table(femelement_table):
|
||||
'''{eleID : 0, eleID : 0, ...}
|
||||
'''
|
||||
empty_femelement_table = {}
|
||||
for ele in femelement_table: # initialize it with sorted element keys and empty int
|
||||
empty_femelement_table[ele] = 0
|
||||
return empty_femelement_table.copy()
|
||||
|
||||
|
||||
def get_bit_pattern_dict(femelement_table, femnodes_ele_table, node_set):
|
||||
'''Now we are looking for nodes inside of the Faces = filling the bit_pattern_dict
|
||||
{eleID : [lenEleNodes, binary_position]}
|
||||
see forumpost for a ver good explanation whats really happening
|
||||
http://forum.freecadweb.org/viewtopic.php?f=18&p=141133&sid=013c93f496a63872951d2ce521702ffa#p141108
|
||||
The bit_pattern_dict holds later an integer (bit array) for each element, which gives us
|
||||
the information we are searching for:
|
||||
Is this element part of the node list (searching for elements) or has this element a face we are searching for?
|
||||
The number in the ele_dict is organized as a bit array.
|
||||
The corresponding bit is set, if the node of the node_set is contained in the element.
|
||||
'''
|
||||
print('len femnodes_ele_table:' + str(len(femnodes_ele_table)))
|
||||
print('len node_set: ' + str(len(node_set)))
|
||||
# print('node_set: ', node_set)
|
||||
bit_pattern_dict = get_copy_of_empty_femelement_table(femelement_table)
|
||||
# # initializing the bit_pattern_dict
|
||||
for ele in femelement_table:
|
||||
len_ele = len(femelement_table[ele])
|
||||
bit_pattern_dict[ele] = [len_ele, 0]
|
||||
for node in node_set:
|
||||
for nList in femnodes_ele_table[node]:
|
||||
bit_pattern_dict[nList[0]][1] += nList[1]
|
||||
print('len bit_pattern_dict:' + str(len(bit_pattern_dict)))
|
||||
# print('bit_pattern_dict: ', bit_pattern_dict)
|
||||
return bit_pattern_dict
|
||||
|
||||
|
||||
def get_ccxelement_faces_from_binary_search(bit_pattern_dict):
|
||||
'''get the CalculiX element face numbers
|
||||
'''
|
||||
tet10_mask = {
|
||||
119: 1,
|
||||
411: 2,
|
||||
717: 3,
|
||||
814: 4}
|
||||
tet4_mask = {
|
||||
7: 1,
|
||||
11: 2,
|
||||
13: 3,
|
||||
14: 4}
|
||||
hex8_mask = {
|
||||
240: 1,
|
||||
15: 2,
|
||||
102: 3,
|
||||
204: 4,
|
||||
153: 5,
|
||||
51: 6}
|
||||
hex20_mask = {
|
||||
61680: 1,
|
||||
3855: 2,
|
||||
402022: 3,
|
||||
804044: 4,
|
||||
624793: 5,
|
||||
201011: 6}
|
||||
pent6_mask = {
|
||||
56: 1,
|
||||
7: 2,
|
||||
54: 3,
|
||||
45: 4,
|
||||
27: 5}
|
||||
pent15_mask = {
|
||||
3640: 1,
|
||||
455: 2,
|
||||
25782: 3,
|
||||
22829: 4,
|
||||
12891: 5}
|
||||
vol_dict = {
|
||||
4: tet4_mask,
|
||||
6: pent6_mask,
|
||||
8: hex8_mask,
|
||||
10: tet10_mask,
|
||||
15: pent15_mask,
|
||||
20: hex20_mask}
|
||||
faces = []
|
||||
for ele in bit_pattern_dict:
|
||||
mask_dict = vol_dict[bit_pattern_dict[ele][0]]
|
||||
for key in mask_dict:
|
||||
if (key & bit_pattern_dict[ele][1]) == key:
|
||||
faces.append([ele, mask_dict[key]])
|
||||
print('found Faces: ', len(faces))
|
||||
print('faces: ', faces)
|
||||
return faces
|
||||
|
||||
|
||||
def get_femelements_by_femnodes_bin(femelement_table, femnodes_ele_table, node_list):
|
||||
'''for every femelement of femelement_table
|
||||
if all nodes of the femelement are in node_list,
|
||||
the femelement is added to the list which is returned
|
||||
blind fast binary search, but workd for volumes only
|
||||
'''
|
||||
print('binary search: get_femelements_by_femnodes_bin')
|
||||
vol_masks = {
|
||||
4: 15,
|
||||
6: 63,
|
||||
8: 255,
|
||||
10: 1023,
|
||||
15: 32767,
|
||||
20: 1048575}
|
||||
# Now we are looking for nodes inside of the Volumes = filling the bit_pattern_dict
|
||||
print('len femnodes_ele_table:' + str(len(femnodes_ele_table)))
|
||||
bit_pattern_dict = get_bit_pattern_dict(femelement_table, femnodes_ele_table, node_list)
|
||||
# search
|
||||
ele_list = [] # The ele_list contains the result of the search.
|
||||
for ele in bit_pattern_dict:
|
||||
# print('bit_pattern_dict[ele][0]: ', bit_pattern_dict[ele][0])
|
||||
if bit_pattern_dict[ele][1] == vol_masks[bit_pattern_dict[ele][0]]:
|
||||
ele_list.append(ele)
|
||||
print('found Volumes: ', len(ele_list))
|
||||
print(' volumes: ', len(ele_list))
|
||||
return ele_list
|
||||
|
||||
|
||||
def get_femelements_by_femnodes_std(femelement_table, node_list):
|
||||
'''for every femelement of femelement_table
|
||||
if all nodes of the femelement are in node_list,
|
||||
the femelement is added to the list which is returned
|
||||
e: elementlist
|
||||
nodes: nodelist '''
|
||||
print('std search: get_femelements_by_femnodes_std')
|
||||
e = [] # elementlist
|
||||
for elementID in sorted(femelement_table):
|
||||
nodecount = 0
|
||||
@@ -172,11 +324,11 @@ def get_femvolumeelements_by_femfacenodes(femelement_table, node_list):
|
||||
e.append(elementID)
|
||||
else:
|
||||
FreeCAD.Console.PrintError('Error in get_femvolumeelements_by_femfacenodes(): not known volume element: ' + el_nd_ct + '\n')
|
||||
# print sorted(e)
|
||||
# print(sorted(e))
|
||||
return e
|
||||
|
||||
|
||||
def get_femelement_sets(femmesh, femelement_table, fem_objects): # fem_objects = FreeCAD FEM document objects
|
||||
def get_femelement_sets(femmesh, femelement_table, fem_objects, femnodes_ele_table=None): # fem_objects = FreeCAD FEM document objects
|
||||
# get femelements for reference shapes of each obj.References
|
||||
count_femelements = 0
|
||||
referenced_femelements = []
|
||||
@@ -186,7 +338,7 @@ def get_femelement_sets(femmesh, femelement_table, fem_objects): # fem_objects
|
||||
fem_object['ShortName'] = get_elset_short_name(obj, fem_object_i) # unique short identifier
|
||||
if obj.References:
|
||||
ref_shape_femelements = []
|
||||
ref_shape_femelements = get_femelements_by_references(femmesh, femelement_table, obj.References)
|
||||
ref_shape_femelements = get_femelements_by_references(femmesh, femelement_table, obj.References, femnodes_ele_table)
|
||||
referenced_femelements += ref_shape_femelements
|
||||
count_femelements += len(ref_shape_femelements)
|
||||
fem_object['FEMElements'] = ref_shape_femelements
|
||||
@@ -213,10 +365,11 @@ def get_femnode_set_from_group_data(femmesh, fem_object):
|
||||
# we assume the mesh group data fits with the reference shapes, no check is done in this regard !!!
|
||||
# what happens if a reference shape was changed, but the mesh and the mesh groups were not created new !?!
|
||||
obj = fem_object['Object']
|
||||
group_nodes = None
|
||||
if femmesh.GroupCount:
|
||||
for g in femmesh.Groups:
|
||||
grp_name = femmesh.getGroupName(g)
|
||||
if grp_name.startswith(obj.Name + '_'):
|
||||
if grp_name.startswith(obj.Name):
|
||||
if femmesh.getGroupElementType(g) == "Node":
|
||||
print("Constraint: " + obj.Name + " --> " + "mesh group: " + grp_name)
|
||||
group_nodes = femmesh.getGroupElements(g) # == ref_shape_femelements
|
||||
@@ -235,7 +388,7 @@ def get_femelement_sets_from_group_data(femmesh, fem_objects):
|
||||
if femmesh.GroupCount:
|
||||
for g in femmesh.Groups:
|
||||
grp_name = femmesh.getGroupName(g)
|
||||
if grp_name.startswith(obj.Name + '_'):
|
||||
if grp_name.startswith(obj.Name):
|
||||
if femmesh.getGroupElementType(g) == "Volume":
|
||||
print("Constraint: " + obj.Name + " --> " + "mesh group: " + grp_name)
|
||||
group_elements = femmesh.getGroupElements(g) # == ref_shape_femelements
|
||||
@@ -372,7 +525,7 @@ def get_force_obj_edge_nodeload_table(femmesh, femelement_table, femnodes_mesh,
|
||||
return force_obj_node_load_table
|
||||
|
||||
|
||||
def get_pressure_obj_faces(femmesh, femobj):
|
||||
def get_pressure_obj_faces_depreciated(femmesh, femobj):
|
||||
pressure_faces = []
|
||||
for o, elem_tup in femobj['Object'].References:
|
||||
for elem in elem_tup:
|
||||
@@ -384,6 +537,16 @@ def get_pressure_obj_faces(femmesh, femobj):
|
||||
return pressure_faces
|
||||
|
||||
|
||||
def get_pressure_obj_faces(femmesh, femelement_table, femnodes_ele_table, femobj):
|
||||
# get the nodes
|
||||
prs_face_node_set = get_femnodes_by_femobj_with_references(femmesh, femobj) # sorted and duplicates removed
|
||||
# print('prs_face_node_set: ', prs_face_node_set)
|
||||
# fill the bit_pattern_dict and search for the faces
|
||||
bit_pattern_dict = get_bit_pattern_dict(femelement_table, femnodes_ele_table, prs_face_node_set)
|
||||
pressure_faces = get_ccxelement_faces_from_binary_search(bit_pattern_dict)
|
||||
return pressure_faces
|
||||
|
||||
|
||||
def get_force_obj_face_nodeload_table(femmesh, femelement_table, femnodes_mesh, frc_obj):
|
||||
# force_obj_node_load_table = [('refshape_name.elemname',node_load_table), ..., ('refshape_name.elemname',node_load_table)]
|
||||
force_obj_node_load_table = []
|
||||
@@ -483,7 +646,7 @@ def get_ref_edgenodes_table(femmesh, femelement_table, refedge):
|
||||
# FIXME duplicate_mesh_elements: as soon as contact ans springs are supported the user should decide on which edge the load is applied
|
||||
edge_table = delete_duplicate_mesh_elements(edge_table)
|
||||
elif is_edge_femmesh(femmesh):
|
||||
refedge_fem_edgeelements = get_femelements_by_femnodes(femelement_table, refedge_nodes)
|
||||
refedge_fem_edgeelements = get_femelements_by_femnodes_std(femelement_table, refedge_nodes)
|
||||
for elem in refedge_fem_edgeelements:
|
||||
edge_table[elem] = femelement_table[elem] # { edgeID : ( nodeID, ... , nodeID )} # all nodes off this femedgeelement
|
||||
return edge_table
|
||||
@@ -571,10 +734,10 @@ def get_ref_facenodes_table(femmesh, femelement_table, ref_face):
|
||||
face_table[mf] = femmesh.getElementNodes(mf)
|
||||
elif is_face_femmesh(femmesh):
|
||||
ref_face_nodes = femmesh.getNodesByFace(ref_face)
|
||||
ref_face_elements = get_femelements_by_femnodes(femelement_table, ref_face_nodes)
|
||||
ref_face_elements = get_femelements_by_femnodes_std(femelement_table, ref_face_nodes)
|
||||
for mf in ref_face_elements:
|
||||
face_table[mf] = femelement_table[mf]
|
||||
# print face_table
|
||||
# print(face_table)
|
||||
return face_table
|
||||
|
||||
|
||||
@@ -588,10 +751,10 @@ def build_mesh_faces_of_volume_elements(face_table, femelement_table):
|
||||
index = femelement_table[veID].index(n)
|
||||
# print(index)
|
||||
face_nodenumber_table[veID].append(index + 1) # lokale node number = index + 1
|
||||
# print 'VolElement:', veID
|
||||
# print ' --> ', femelement_table[veID]
|
||||
# print ' --> ', face_table[veID]
|
||||
# print ' --> ', face_nodenumber_table[veID]
|
||||
# print('VolElement:', veID)
|
||||
# print(' --> ', femelement_table[veID])
|
||||
# print(' --> ', face_table[veID])
|
||||
# print(' --> ', face_nodenumber_table[veID])
|
||||
for veID in face_nodenumber_table:
|
||||
vol_node_ct = len(femelement_table[veID])
|
||||
face_node_indexs = sorted(face_nodenumber_table[veID])
|
||||
@@ -681,7 +844,7 @@ def build_mesh_faces_of_volume_elements(face_table, femelement_table):
|
||||
i -= 1 # node_number starts with 1, index starts with 0 --> index = node number - 1
|
||||
face_nodes.append(femelement_table[veID][i])
|
||||
face_table[veID] = face_nodes # reset the entry in face_table
|
||||
# print ' --> ', face_table[veID]
|
||||
# print(' --> ', face_table[veID])
|
||||
return face_table
|
||||
|
||||
|
||||
@@ -840,13 +1003,13 @@ def get_analysis_group_elements(aAnalysis, aPart):
|
||||
{ConstraintName : ['ShapeType of the Elements'], [ElementID, ElementID, ...], ...}
|
||||
'''
|
||||
aShape = aPart.Shape
|
||||
group_elements = {}
|
||||
group_elements = {} # { name : [element, element, ... , element]}
|
||||
empty_references = []
|
||||
for m in aAnalysis.Member:
|
||||
if hasattr(m, "References"):
|
||||
# print(m.Name)
|
||||
key = m.Name
|
||||
indexes = []
|
||||
elements = []
|
||||
stype = None
|
||||
if m.References:
|
||||
for r in m.References:
|
||||
@@ -868,117 +1031,134 @@ def get_analysis_group_elements(aAnalysis, aPart):
|
||||
# print(ref_shape)
|
||||
found_element = find_element_in_shape(aShape, ref_shape)
|
||||
if found_element is not None:
|
||||
indexes.append(found_element)
|
||||
elements.append(found_element)
|
||||
else:
|
||||
FreeCAD.Console.PrintError('Problem: No element found for: ' + str(ref_shape) + '\n')
|
||||
print(' ' + m.Name)
|
||||
print(' ' + str(m.References))
|
||||
print(' ' + r[0].Name)
|
||||
group_elements[key] = [stype, sorted(indexes)]
|
||||
group_elements[key] = sorted(elements)
|
||||
else:
|
||||
print('Empty reference: ' + m.Name)
|
||||
print(' Empty reference: ' + m.Name)
|
||||
empty_references.append(m)
|
||||
if empty_references:
|
||||
if len(empty_references) == 1:
|
||||
group_elements = get_anlysis_empty_references_group_elements(group_elements, aAnalysis, aShape)
|
||||
else:
|
||||
FreeCAD.Console.PrintError('Error: more than one object with empty references!\n')
|
||||
print(empty_references)
|
||||
FreeCAD.Console.PrintError('Problem: more than one object with empty references.\n')
|
||||
print('We gone try to get the empty material references anyway.\n')
|
||||
# ShellThickness and BeamSection could have empty references, but on solid meshes only materials should have empty references
|
||||
for er in empty_references:
|
||||
print(er.Name)
|
||||
group_elements = get_anlysis_empty_references_group_elements(group_elements, aAnalysis, aShape)
|
||||
# check if all groups have elements:
|
||||
for g in group_elements:
|
||||
# print group_elements[g][1]
|
||||
if len(group_elements[g][1]) == 0:
|
||||
# print(group_elements[g])
|
||||
if len(group_elements[g]) == 0:
|
||||
FreeCAD.Console.PrintError('Error: shapes for: ' + g + 'not found!\n')
|
||||
return group_elements
|
||||
|
||||
|
||||
def get_anlysis_empty_references_group_elements(group_elements, aAnalysis, aShape):
|
||||
'''get the elementIDs if the Reference shape is empty
|
||||
see get_analysis_group_elements()
|
||||
see get_analysis_group_elements() for more informatations
|
||||
on solid meshes only material objects could have an empty reference without beeing something wrong!
|
||||
face meshes could have empty ShellThickness and edge meshes could have empty BeamSection
|
||||
'''
|
||||
# print(group_elements)
|
||||
material_ref_shapes = []
|
||||
material_shape_type = ''
|
||||
missed_material_refshapes = []
|
||||
empty_reference_material = None
|
||||
for m in aAnalysis.Member:
|
||||
# only materials could have an empty reference without beeing something wrong!
|
||||
if m.isDerivedFrom("App::MaterialObjectPython"):
|
||||
if hasattr(m, "References") and m.References:
|
||||
if not material_shape_type:
|
||||
material_shape_type = group_elements[m.Name][0]
|
||||
elif material_shape_type != group_elements[m.Name][0]:
|
||||
print('Problem, material shape type does not match get_anlysis_empty_references_group_elements')
|
||||
for i in group_elements[m.Name][1]:
|
||||
material_ref_shapes.append(i)
|
||||
elif hasattr(m, "References") and not m.References:
|
||||
if hasattr(m, "References") and not m.References:
|
||||
if not empty_reference_material:
|
||||
empty_reference_material = m.Name
|
||||
else:
|
||||
print('Problem in get_anlysis_empty_references_group_elements, we seams to have two materials with empty referneces')
|
||||
FreeCAD.Console.PrintError('Problem in get_anlysis_empty_references_group_elements, we seams to have two or more materials with empty referneces')
|
||||
return {}
|
||||
elif hasattr(m, "References") and m.References:
|
||||
# ShapeType ot the group elements, strip the number of the first group element
|
||||
# http://stackoverflow.com/questions/12851791/removing-numbers-from-string
|
||||
group_shape_type = ''.join(i for i in group_elements[m.Name][0] if not i.isdigit())
|
||||
if not material_shape_type:
|
||||
material_shape_type = group_shape_type
|
||||
elif material_shape_type != group_shape_type:
|
||||
FreeCAD.Console.PrintError('Problem, material shape type does not match get_anlysis_empty_references_group_elements')
|
||||
for ele in group_elements[m.Name]:
|
||||
material_ref_shapes.append(ele)
|
||||
if material_shape_type == 'Solid':
|
||||
# print(len(aShape.Solids))
|
||||
for i in range(len(aShape.Solids)):
|
||||
if i not in material_ref_shapes:
|
||||
missed_material_refshapes.append(i)
|
||||
ele = 'Solid' + str(i + 1)
|
||||
if ele not in material_ref_shapes:
|
||||
missed_material_refshapes.append(ele)
|
||||
elif material_shape_type == 'Face':
|
||||
# print(len(aShape.Faces))
|
||||
for i in range(len(aShape.Faces)):
|
||||
if i not in material_ref_shapes:
|
||||
missed_material_refshapes.append(i)
|
||||
ele = 'Face' + str(i + 1)
|
||||
if ele not in material_ref_shapes:
|
||||
missed_material_refshapes.append(ele)
|
||||
elif material_shape_type == 'Edge':
|
||||
# print(len(aShape.Edges))
|
||||
for i in range(len(aShape.Edges)):
|
||||
if i not in material_ref_shapes:
|
||||
missed_material_refshapes.append(i)
|
||||
ele = 'Edge' + str(i + 1)
|
||||
if ele not in material_ref_shapes:
|
||||
missed_material_refshapes.append(ele)
|
||||
else:
|
||||
print('It seams we only have one material with no reference shapes. Means the whole solid is one material. Since we only support material groups for Solids at the moment this should be Solid')
|
||||
material_shape_type = 'Solid'
|
||||
missed_material_refshapes.append(0)
|
||||
print(' One material with no reference shapes. No need to make a group for materials.')
|
||||
# make no changes group_elements
|
||||
return group_elements
|
||||
# print(sorted(material_ref_shapes))
|
||||
# print(sorted(missed_material_refshapes))
|
||||
# print(group_elements)
|
||||
group_elements[empty_reference_material] = [material_shape_type, sorted(missed_material_refshapes)]
|
||||
group_elements[empty_reference_material] = sorted(missed_material_refshapes)
|
||||
# print(group_elements)
|
||||
return group_elements
|
||||
|
||||
|
||||
def find_element_in_shape(aShape, anElement):
|
||||
# import Part
|
||||
if anElement.ShapeType == 'Solid' or anElement.ShapeType == 'CompSolid':
|
||||
ele_st = anElement.ShapeType
|
||||
if ele_st == 'Solid' or ele_st == 'CompSolid':
|
||||
for index, solid in enumerate(aShape.Solids):
|
||||
# print(is_same_geometry(solid, anElement))
|
||||
if is_same_geometry(solid, anElement):
|
||||
# print(index)
|
||||
# Part.show(aShape.Solids[index])
|
||||
return index
|
||||
ele = ele_st + str(index + 1)
|
||||
return ele
|
||||
FreeCAD.Console.PrintError('Solid ' + str(anElement) + ' not found in: ' + str(aShape) + '\n')
|
||||
if anElement.ShapeType == 'Solid' and aShape.ShapeType == 'Solid':
|
||||
if ele_st == 'Solid' and aShape.ShapeType == 'Solid':
|
||||
print('We have been searching for a Solid in a Solid and we have not found it. In most cases this should be searching for a Solid inside a CompSolid. Check the ShapeType of your Part to mesh.')
|
||||
# Part.show(anElement)
|
||||
# Part.show(aShape)
|
||||
elif anElement.ShapeType == 'Face' or anElement.ShapeType == 'Shell':
|
||||
elif ele_st == 'Face' or ele_st == 'Shell':
|
||||
for index, face in enumerate(aShape.Faces):
|
||||
# print(is_same_geometry(face, anElement))
|
||||
if is_same_geometry(face, anElement):
|
||||
# print(index)
|
||||
# Part.show(aShape.Faces[index])
|
||||
return index
|
||||
elif anElement.ShapeType == 'Edge' or anElement.ShapeType == 'Wire':
|
||||
for index, face in enumerate(aShape.Edges):
|
||||
# print(is_same_geometry(face, anElement))
|
||||
if is_same_geometry(face, anElement):
|
||||
ele = ele_st + str(index + 1)
|
||||
return ele
|
||||
elif ele_st == 'Edge' or ele_st == 'Wire':
|
||||
for index, edge in enumerate(aShape.Edges):
|
||||
# print(is_same_geometry(edge, anElement))
|
||||
if is_same_geometry(edge, anElement):
|
||||
# print(index)
|
||||
# Part.show(aShape.Edges[index])
|
||||
return index
|
||||
elif anElement.ShapeType == 'Vertex':
|
||||
for index, face in enumerate(aShape.Vertexes):
|
||||
# print(is_same_geometry(face, anElement))
|
||||
if is_same_geometry(face, anElement):
|
||||
ele = ele_st + str(index + 1)
|
||||
return ele
|
||||
elif ele_st == 'Vertex':
|
||||
for index, vertex in enumerate(aShape.Vertexes):
|
||||
# print(is_same_geometry(vertex, anElement))
|
||||
if is_same_geometry(vertex, anElement):
|
||||
# print(index)
|
||||
# Part.show(aShape.Vertexes[index])
|
||||
return index
|
||||
elif anElement.ShapeType == 'Compound':
|
||||
ele = ele_st + str(index + 1)
|
||||
return ele
|
||||
elif ele_st == 'Compound':
|
||||
FreeCAD.Console.PrintError('Compound is not supported.\n')
|
||||
|
||||
|
||||
|
||||
@@ -24,12 +24,12 @@ __title__ = "Selection Observer"
|
||||
__author__ = "Bernd Hahnebach"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
## \addtogroup FEM
|
||||
# @{
|
||||
|
||||
import FreeCAD
|
||||
import FreeCADGui
|
||||
|
||||
## \addtogroup FEM
|
||||
# @{
|
||||
|
||||
class FemSelectionObserver:
|
||||
'''FemSelectionObserver'''
|
||||
|
||||
@@ -24,12 +24,12 @@ __title__ = "FemShellThickness"
|
||||
__author__ = "Bernd Hahnebach"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
## \addtogroup FEM
|
||||
# @{
|
||||
|
||||
import FreeCAD
|
||||
import _FemShellThickness
|
||||
|
||||
## \addtogroup FEM
|
||||
# @{
|
||||
|
||||
def makeFemShellThickness(thickness=20.0, name="ShellThickness"):
|
||||
'''makeFemShellThickness([thickness], [name]): creates an shellthickness object to define a plate thickness'''
|
||||
|
||||
@@ -24,12 +24,12 @@ __title__ = "FemSolverCalculix"
|
||||
__author__ = "Bernd Hahnebach"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
## \addtogroup FEM
|
||||
# @{
|
||||
|
||||
import FreeCAD
|
||||
import _FemSolverCalculix
|
||||
|
||||
## \addtogroup FEM
|
||||
# @{
|
||||
|
||||
def makeFemSolverCalculix(name="CalculiX"):
|
||||
'''makeSolverCalculix(name): makes a Calculix solver object'''
|
||||
|
||||
@@ -24,12 +24,12 @@ __title__ = "FemSolverZ88"
|
||||
__author__ = "Bernd Hahnebach"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
## \addtogroup FEM
|
||||
# @{
|
||||
|
||||
import FreeCAD
|
||||
import _FemSolverZ88
|
||||
|
||||
## \addtogroup FEM
|
||||
# @{
|
||||
|
||||
def makeFemSolverZ88(name="Z88"):
|
||||
'''makeSolverZ88(name): makes a Z88 solver object'''
|
||||
|
||||
@@ -21,17 +21,16 @@
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
|
||||
|
||||
__title__ = "Fem Tools super class"
|
||||
__author__ = "Przemo Firszt, Bernd Hahnebach"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
## \addtogroup FEM
|
||||
# @{
|
||||
|
||||
import FreeCAD
|
||||
from PySide import QtCore
|
||||
|
||||
## \addtogroup FEM
|
||||
# @{
|
||||
|
||||
class FemTools(QtCore.QRunnable, QtCore.QObject):
|
||||
## The constructor
|
||||
|
||||
@@ -21,11 +21,12 @@
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
|
||||
|
||||
__title__ = "FemToolsCcx"
|
||||
__author__ = "Przemo Firszt, Bernd Hahnebach"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
## \addtogroup FEM
|
||||
# @{
|
||||
|
||||
import FreeCAD
|
||||
import FemTools
|
||||
@@ -33,8 +34,6 @@ from PySide import QtCore
|
||||
if FreeCAD.GuiUp:
|
||||
from PySide import QtGui
|
||||
|
||||
## \addtogroup FEM
|
||||
# @{
|
||||
|
||||
class FemToolsCcx(FemTools.FemTools):
|
||||
|
||||
@@ -242,6 +241,9 @@ class FemToolsCcx(FemTools.FemTools):
|
||||
for m in self.analysis.Member:
|
||||
if m.isDerivedFrom("Fem::FemResultObject"):
|
||||
self.results_present = True
|
||||
break
|
||||
else:
|
||||
FreeCAD.Console.PrintError('FEM: No result object in active Analysis.\n')
|
||||
else:
|
||||
raise Exception('FEM: No results found at {}!'.format(frd_result_file))
|
||||
|
||||
@@ -256,7 +258,7 @@ class FemToolsCcx(FemTools.FemTools):
|
||||
else:
|
||||
raise Exception('FEM: No .dat results found at {}!'.format(dat_result_file))
|
||||
if mode_frequencies:
|
||||
print(mode_frequencies)
|
||||
# print(mode_frequencies)
|
||||
for m in self.analysis.Member:
|
||||
if m.isDerivedFrom("Fem::FemResultObject") and m.Eigenmode > 0:
|
||||
for mf in mode_frequencies:
|
||||
|
||||
@@ -20,19 +20,18 @@
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
|
||||
|
||||
__title__ = "FemToolsZ88"
|
||||
__author__ = "Bernd Hahnebach"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
## \addtogroup FEM
|
||||
# @{
|
||||
|
||||
import FreeCAD
|
||||
import FemTools
|
||||
from PySide import QtCore
|
||||
from PySide.QtGui import QApplication
|
||||
|
||||
## \addtogroup FEM
|
||||
# @{
|
||||
|
||||
class FemToolsZ88(FemTools.FemTools):
|
||||
|
||||
@@ -110,8 +109,7 @@ class FemToolsZ88(FemTools.FemTools):
|
||||
self.z88_binary = z88_path
|
||||
else:
|
||||
if not z88_binary:
|
||||
self.fem_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem/Z88")
|
||||
z88_binary = self.fem_prefs.GetString("z88BinaryPath", "")
|
||||
z88_binary = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem/Z88").GetString("z88BinaryPath", "")
|
||||
if not z88_binary:
|
||||
if system() == "Linux":
|
||||
z88_binary = "z88r"
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "PropertyFemMeshItem.h"
|
||||
#include "DlgSettingsFemGeneralImp.h"
|
||||
#include "DlgSettingsFemCcxImp.h"
|
||||
#include "DlgSettingsFemGmshImp.h"
|
||||
#include "DlgSettingsFemZ88Imp.h"
|
||||
#include "ViewProviderFemMesh.h"
|
||||
#include "ViewProviderFemMeshShape.h"
|
||||
@@ -109,6 +110,7 @@ PyMODINIT_FUNC initFemGui()
|
||||
FemGui::ViewProviderFemAnalysis ::init();
|
||||
FemGui::ViewProviderFemAnalysisPython ::init();
|
||||
FemGui::ViewProviderFemMesh ::init();
|
||||
FemGui::ViewProviderFemMeshPython ::init();
|
||||
FemGui::ViewProviderFemMeshShape ::init();
|
||||
FemGui::ViewProviderFemMeshShapeNetgen ::init();
|
||||
FemGui::ViewProviderSolver ::init();
|
||||
@@ -153,6 +155,7 @@ PyMODINIT_FUNC initFemGui()
|
||||
// register preferences pages
|
||||
new Gui::PrefPageProducer<FemGui::DlgSettingsFemGeneralImp> (QT_TRANSLATE_NOOP("QObject","FEM"));
|
||||
new Gui::PrefPageProducer<FemGui::DlgSettingsFemCcxImp> (QT_TRANSLATE_NOOP("QObject","FEM"));
|
||||
new Gui::PrefPageProducer<FemGui::DlgSettingsFemGmshImp> (QT_TRANSLATE_NOOP("QObject","FEM"));
|
||||
new Gui::PrefPageProducer<FemGui::DlgSettingsFemZ88Imp> (QT_TRANSLATE_NOOP("QObject","FEM"));
|
||||
|
||||
// add resources and reloads the translators
|
||||
|
||||
@@ -44,6 +44,7 @@ SOURCE_GROUP("Python" FILES ${Python_SRCS})
|
||||
set(FemGui_MOC_HDRS
|
||||
DlgSettingsFemCcxImp.h
|
||||
DlgSettingsFemGeneralImp.h
|
||||
DlgSettingsFemGmshImp.h
|
||||
DlgSettingsFemZ88Imp.h
|
||||
PropertyFemMeshItem.h
|
||||
TaskObjectName.h
|
||||
@@ -83,6 +84,7 @@ SOURCE_GROUP("Moc" FILES ${FemGui_MOC_SRCS})
|
||||
set(FemGui_UIC_SRCS
|
||||
DlgSettingsFemCcx.ui
|
||||
DlgSettingsFemGeneral.ui
|
||||
DlgSettingsFemGmsh.ui
|
||||
DlgSettingsFemZ88.ui
|
||||
TaskCreateNodeSet.ui
|
||||
TaskObjectName.ui
|
||||
@@ -125,6 +127,9 @@ SET(FemGui_DLG_SRCS
|
||||
DlgSettingsFemGeneral.ui
|
||||
DlgSettingsFemGeneralImp.cpp
|
||||
DlgSettingsFemGeneralImp.h
|
||||
DlgSettingsFemGmsh.ui
|
||||
DlgSettingsFemGmshImp.cpp
|
||||
DlgSettingsFemGmshImp.h
|
||||
DlgSettingsFemZ88.ui
|
||||
DlgSettingsFemZ88Imp.cpp
|
||||
DlgSettingsFemZ88Imp.h
|
||||
|
||||
230
src/Mod/Fem/Gui/DlgSettingsFemGmsh.ui
Normal file
230
src/Mod/Fem/Gui/DlgSettingsFemGmsh.ui
Normal file
@@ -0,0 +1,230 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>FemGui::DlgSettingsFemGmshImp</class>
|
||||
<widget class="QWidget" name="FemGui::DlgSettingsFemGmshImp">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>372</width>
|
||||
<height>144</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>GMSH</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="gb_gmsh_param">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::LeftToRight</enum>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>GMSH</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetNoConstraint</enum>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gl_01">
|
||||
<item row="0" column="2">
|
||||
<widget class="Gui::PrefCheckBox" name="cb_gmsh_binary_std">
|
||||
<property name="text">
|
||||
<string>Use standard gmsh binary path</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>UseStandardGmshLocation</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Mod/Fem/Gmsh</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="l_gmsh_binary_std">
|
||||
<property name="text">
|
||||
<string>GMSH binary</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="l_gmsh_binary_path">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>gmsh binary path</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="Gui::PrefFileChooser" name="fc_gmsh_binary_path" native="true">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="sizeIncrement">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="baseSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Leave blank to use default gmsh binary file</string>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>gmshBinaryPath</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Mod/Fem/Gmsh</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>Gui::PrefCheckBox</class>
|
||||
<extends>QCheckBox</extends>
|
||||
<header>Gui/PrefWidgets.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>Gui::FileChooser</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>Gui/FileDialog.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>Gui::PrefFileChooser</class>
|
||||
<extends>Gui::FileChooser</extends>
|
||||
<header>Gui/PrefWidgets.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="Resources/Fem.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>cb_gmsh_binary_std</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>l_gmsh_binary_path</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>406</x>
|
||||
<y>45</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>148</x>
|
||||
<y>68</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>cb_gmsh_binary_std</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>fc_gmsh_binary_path</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>406</x>
|
||||
<y>45</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>406</x>
|
||||
<y>68</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>cb_gmsh_binary_std</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>l_gmsh_binary_path</receiver>
|
||||
<slot>setDisabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>406</x>
|
||||
<y>45</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>148</x>
|
||||
<y>68</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>cb_gmsh_binary_std</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>fc_gmsh_binary_path</receiver>
|
||||
<slot>setDisabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>406</x>
|
||||
<y>45</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>406</x>
|
||||
<y>68</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
69
src/Mod/Fem/Gui/DlgSettingsFemGmshImp.cpp
Normal file
69
src/Mod/Fem/Gui/DlgSettingsFemGmshImp.cpp
Normal file
@@ -0,0 +1,69 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2016 FreeCAD Developers *
|
||||
* Author: Bernd Hahnebach <bernd@bimstatik.ch> *
|
||||
* Based on src/Mod/Fem/Gui/DlgSettingsFemCcxImp.cpp *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library 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 Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#include "Gui/Application.h"
|
||||
#include "DlgSettingsFemGmshImp.h"
|
||||
#include <Gui/PrefWidgets.h>
|
||||
|
||||
using namespace FemGui;
|
||||
|
||||
DlgSettingsFemGmshImp::DlgSettingsFemGmshImp( QWidget* parent )
|
||||
: PreferencePage( parent )
|
||||
{
|
||||
this->setupUi(this);
|
||||
}
|
||||
|
||||
DlgSettingsFemGmshImp::~DlgSettingsFemGmshImp()
|
||||
{
|
||||
// no need to delete child widgets, Qt does it all for us
|
||||
}
|
||||
|
||||
void DlgSettingsFemGmshImp::saveSettings()
|
||||
{
|
||||
cb_gmsh_binary_std->onSave();
|
||||
fc_gmsh_binary_path->onSave();
|
||||
}
|
||||
|
||||
void DlgSettingsFemGmshImp::loadSettings()
|
||||
{
|
||||
cb_gmsh_binary_std->onRestore();
|
||||
fc_gmsh_binary_path->onRestore();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the strings of the subwidgets using the current language.
|
||||
*/
|
||||
void DlgSettingsFemGmshImp::changeEvent(QEvent *e)
|
||||
{
|
||||
if (e->type() == QEvent::LanguageChange) {
|
||||
}
|
||||
else {
|
||||
QWidget::changeEvent(e);
|
||||
}
|
||||
}
|
||||
|
||||
#include "moc_DlgSettingsFemGmshImp.cpp"
|
||||
50
src/Mod/Fem/Gui/DlgSettingsFemGmshImp.h
Normal file
50
src/Mod/Fem/Gui/DlgSettingsFemGmshImp.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/**************************************************************************
|
||||
* Copyright (c) 2016 FreeCAD Developers *
|
||||
* Author: Bernd Hahnebach <bernd@bimstatik.ch> *
|
||||
* Based on src/Mod/Fem/Gui/DlgSettingsFemCcx.h *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library 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 Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef FEMGUI_DLGSETTINGSFEMGMSHIMP_H
|
||||
#define FEMGUI_DLGSETTINGSFEMGMSHIMP_H
|
||||
|
||||
#include "ui_DlgSettingsFemGmsh.h"
|
||||
#include <Gui/PropertyPage.h>
|
||||
|
||||
namespace FemGui {
|
||||
|
||||
class DlgSettingsFemGmshImp : public Gui::Dialog::PreferencePage, public Ui_DlgSettingsFemGmshImp
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
DlgSettingsFemGmshImp( QWidget* parent = 0 );
|
||||
~DlgSettingsFemGmshImp();
|
||||
|
||||
protected:
|
||||
void saveSettings();
|
||||
void loadSettings();
|
||||
void changeEvent(QEvent *e);
|
||||
};
|
||||
|
||||
} // namespace FemGui
|
||||
|
||||
#endif // FEMGUI_DLGSETTINGSFEMGMSHIMP_H
|
||||
@@ -1,6 +1,8 @@
|
||||
<RCC>
|
||||
<qresource>
|
||||
<file>icons/fem-fem-mesh-from-shape.svg</file>
|
||||
<file>icons/fem-fem-mesh-gmsh-from-shape.svg</file>
|
||||
<file>icons/fem-fem-mesh-netgen-from-shape.svg</file>
|
||||
<file>icons/fem-fem-mesh-create-node-by-poly.svg</file>
|
||||
<file>icons/fem-analysis.svg</file>
|
||||
<file>icons/fem-cfd-analysis.svg</file>
|
||||
|
||||
246
src/Mod/Fem/Gui/Resources/icons/fem-fem-mesh-gmsh-from-shape.svg
Normal file
246
src/Mod/Fem/Gui/Resources/icons/fem-fem-mesh-gmsh-from-shape.svg
Normal file
@@ -0,0 +1,246 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="64px"
|
||||
height="64px"
|
||||
id="svg2860"
|
||||
sodipodi:version="0.32"
|
||||
inkscape:version="0.48.5 r10040"
|
||||
sodipodi:docname="fem-fem-mesh-gmsh-from-shape.svg"
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape"
|
||||
version="1.1">
|
||||
<defs
|
||||
id="defs2862">
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3377"
|
||||
id="radialGradient3692"
|
||||
cx="45.883327"
|
||||
cy="28.869568"
|
||||
fx="45.883327"
|
||||
fy="28.869568"
|
||||
r="19.467436"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3377"
|
||||
id="radialGradient3703"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
cx="135.38333"
|
||||
cy="97.369568"
|
||||
fx="135.38333"
|
||||
fy="97.369568"
|
||||
r="19.467436"
|
||||
gradientTransform="matrix(0.97435,0.2250379,-0.4623105,2.0016728,48.487554,-127.99883)" />
|
||||
<linearGradient
|
||||
id="linearGradient3377">
|
||||
<stop
|
||||
id="stop3379"
|
||||
offset="0"
|
||||
style="stop-color:#faff2b;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop3381"
|
||||
offset="1"
|
||||
style="stop-color:#ffaa00;stop-opacity:1;" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3377"
|
||||
id="radialGradient3705"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
cx="148.88333"
|
||||
cy="81.869568"
|
||||
fx="148.88333"
|
||||
fy="81.869568"
|
||||
r="19.467436"
|
||||
gradientTransform="matrix(1.3852588,-5.1367833e-2,3.7056289e-2,0.9993132,-60.392403,7.7040438)" />
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 32 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="64 : 32 : 1"
|
||||
inkscape:persp3d-origin="32 : 21.333333 : 1"
|
||||
id="perspective2868" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="15.556349"
|
||||
inkscape:cx="46.201605"
|
||||
inkscape:cy="36.413493"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1392"
|
||||
inkscape:window-x="-2"
|
||||
inkscape:window-y="25"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata2865">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer">
|
||||
<g
|
||||
id="g3618"
|
||||
transform="translate(-129.7515,-68.681262)">
|
||||
<path
|
||||
style="opacity:0.66523605;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.07586193;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="M 164.25407,125.89934 L 185.75844,120.53301 L 191.3165,115.1667 L 181.45756,113.73568 L 164.25407,125.89934 z"
|
||||
id="path3546" />
|
||||
<path
|
||||
style="opacity:1;fill:url(#radialGradient3705);fill-opacity:1;fill-rule:evenodd;stroke:#7b5600;stroke-width:2.20000005;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="M 152.88222,77.612314 L 133.06781,84.791524 L 163.56337,88.940395 L 163.98885,124.71349 L 180.09861,114.12316 L 180.67448,79.738312 L 152.88222,77.612314 z"
|
||||
id="rect3522"
|
||||
sodipodi:nodetypes="ccccccc" />
|
||||
<path
|
||||
style="opacity:1;fill:url(#radialGradient3703);fill-opacity:1;fill-rule:evenodd;stroke:#7b5600;stroke-width:2.20000005;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="M 133.33785,84.998317 L 164.04669,88.363932 L 164.04669,124.84112 L 132.92286,119.77634 L 133.33785,84.998317 z"
|
||||
id="rect3520"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
style="opacity:1;fill:url(#radialGradient3692);fill-opacity:1;fill-rule:evenodd;stroke:#7b5600;stroke-width:2.20000005;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="M 163.81279,88.408895 L 180.53877,80.000095"
|
||||
id="path3536" />
|
||||
</g>
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 10.545455,17.272727 L 9.6363636,52"
|
||||
id="path2390" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 18.545455,18 C 18.545455,18.060606 18.545455,18.121212 18.545455,18 z"
|
||||
id="path2392" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 16,53.454545 C 16.060606,53.454545 16.121212,53.454545 16,53.454545 z"
|
||||
id="path2394" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 19.090909,53.818182 L 20,18.909091"
|
||||
id="path2398"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 28.545455,19.272727 L 27.454545,55.454545"
|
||||
id="path2400" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 10.727273,17.090909 C 10.969697,17.090909 10.969697,17.090909 10.727273,17.090909 z"
|
||||
id="path2402" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 28.545455,8.7272727 C 28.545455,8.7878788 28.545455,8.8484848 28.545455,8.7272727 z"
|
||||
id="path2404" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 27.636364,9.0909091 C 27.575758,9.0909091 27.515152,9.0909091 27.636364,9.0909091 z"
|
||||
id="path2406" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 29.090909,9.6363637 C 28.839485,9.9151131 11.048018,15.903965 10.727273,16.545455"
|
||||
id="path2408"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 37,10.181818 C 36.748576,10.460567 20.048018,17.722146 20.636364,18.181818"
|
||||
id="path2410"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 45.28032,10.909091 C 45.028896,11.18784 28.328338,18.449419 28.916684,18.909091"
|
||||
id="path2412"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 52.007593,18.727273 C 51.756169,19.006022 35.055611,26.267601 35.643957,26.727273"
|
||||
id="path2414"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 52.007593,26.727273 C 51.756169,27.006022 35.055611,34.267601 35.643957,34.727273"
|
||||
id="path2416"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 51.28032,34.727273 C 51.028896,35.006022 34.328338,42.267601 34.916684,42.727273"
|
||||
id="path2418"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 50.734866,41.636364 C 50.483442,41.915113 33.782884,49.176692 34.37123,49.636364"
|
||||
id="path2420"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 3.8181818,23.636364 C 4.0606061,23.636364 4.0606061,23.636364 3.8181818,23.636364 z"
|
||||
id="path2422" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 3.6363636,23.636364 L 34.545455,26.909091"
|
||||
id="path2424" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 34,34.909091 L 3.8181818,31.454545"
|
||||
id="path2426" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 34.181818,43.454545 L 2.9090909,40.181818"
|
||||
id="path2432" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 34,49.818182 L 3.4545455,46.545455"
|
||||
id="path2434" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:39.81731415px;font-style:normal;font-variant:normal;font-weight:300;font-stretch:condensed;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Comfortaa;-inkscape-font-specification:Comfortaa Light Condensed"
|
||||
x="30.467127"
|
||||
y="34.934822"
|
||||
id="text3014-3"
|
||||
sodipodi:linespacing="125%"
|
||||
inkscape:transform-center-x="22.121859"
|
||||
inkscape:transform-center-y="-23.950112"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3016-6"
|
||||
x="30.467127"
|
||||
y="34.934822"
|
||||
style="font-size:56px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;font-family:Courier 10 Pitch;-inkscape-font-specification:Courier 10 Pitch">G</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:39.81731415px;font-style:normal;font-variant:normal;font-weight:300;font-stretch:condensed;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Comfortaa;-inkscape-font-specification:Comfortaa Light Condensed"
|
||||
x="31.865446"
|
||||
y="33.462196"
|
||||
id="text3014"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3016"
|
||||
x="31.865446"
|
||||
y="33.462196"
|
||||
style="font-size:56px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#ff0000;font-family:Courier 10 Pitch;-inkscape-font-specification:Courier 10 Pitch">G</tspan></text>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 12 KiB |
@@ -0,0 +1,246 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="64px"
|
||||
height="64px"
|
||||
id="svg2860"
|
||||
sodipodi:version="0.32"
|
||||
inkscape:version="0.48.5 r10040"
|
||||
sodipodi:docname="fem-fem-mesh-netgen-from-shape.svg"
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape"
|
||||
version="1.1">
|
||||
<defs
|
||||
id="defs2862">
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3377"
|
||||
id="radialGradient3692"
|
||||
cx="45.883327"
|
||||
cy="28.869568"
|
||||
fx="45.883327"
|
||||
fy="28.869568"
|
||||
r="19.467436"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3377"
|
||||
id="radialGradient3703"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
cx="135.38333"
|
||||
cy="97.369568"
|
||||
fx="135.38333"
|
||||
fy="97.369568"
|
||||
r="19.467436"
|
||||
gradientTransform="matrix(0.97435,0.2250379,-0.4623105,2.0016728,48.487554,-127.99883)" />
|
||||
<linearGradient
|
||||
id="linearGradient3377">
|
||||
<stop
|
||||
id="stop3379"
|
||||
offset="0"
|
||||
style="stop-color:#faff2b;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop3381"
|
||||
offset="1"
|
||||
style="stop-color:#ffaa00;stop-opacity:1;" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3377"
|
||||
id="radialGradient3705"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
cx="148.88333"
|
||||
cy="81.869568"
|
||||
fx="148.88333"
|
||||
fy="81.869568"
|
||||
r="19.467436"
|
||||
gradientTransform="matrix(1.3852588,-5.1367833e-2,3.7056289e-2,0.9993132,-60.392403,7.7040438)" />
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 32 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="64 : 32 : 1"
|
||||
inkscape:persp3d-origin="32 : 21.333333 : 1"
|
||||
id="perspective2868" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="5.5"
|
||||
inkscape:cx="9.7619234"
|
||||
inkscape:cy="40.839396"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:window-width="1280"
|
||||
inkscape:window-height="1115"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="28"
|
||||
inkscape:window-maximized="0" />
|
||||
<metadata
|
||||
id="metadata2865">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer">
|
||||
<g
|
||||
id="g3618"
|
||||
transform="translate(-129.7515,-68.681262)">
|
||||
<path
|
||||
style="opacity:0.66523605;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.07586193;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="M 164.25407,125.89934 L 185.75844,120.53301 L 191.3165,115.1667 L 181.45756,113.73568 L 164.25407,125.89934 z"
|
||||
id="path3546" />
|
||||
<path
|
||||
style="opacity:1;fill:url(#radialGradient3705);fill-opacity:1;fill-rule:evenodd;stroke:#7b5600;stroke-width:2.20000005;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="M 152.88222,77.612314 L 133.06781,84.791524 L 163.56337,88.940395 L 163.98885,124.71349 L 180.09861,114.12316 L 180.67448,79.738312 L 152.88222,77.612314 z"
|
||||
id="rect3522"
|
||||
sodipodi:nodetypes="ccccccc" />
|
||||
<path
|
||||
style="opacity:1;fill:url(#radialGradient3703);fill-opacity:1;fill-rule:evenodd;stroke:#7b5600;stroke-width:2.20000005;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="M 133.33785,84.998317 L 164.04669,88.363932 L 164.04669,124.84112 L 132.92286,119.77634 L 133.33785,84.998317 z"
|
||||
id="rect3520"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
style="opacity:1;fill:url(#radialGradient3692);fill-opacity:1;fill-rule:evenodd;stroke:#7b5600;stroke-width:2.20000005;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="M 163.81279,88.408895 L 180.53877,80.000095"
|
||||
id="path3536" />
|
||||
</g>
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 10.545455,17.272727 L 9.6363636,52"
|
||||
id="path2390" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 18.545455,18 C 18.545455,18.060606 18.545455,18.121212 18.545455,18 z"
|
||||
id="path2392" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 16,53.454545 C 16.060606,53.454545 16.121212,53.454545 16,53.454545 z"
|
||||
id="path2394" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 19.090909,53.818182 L 20,18.909091"
|
||||
id="path2398"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 28.545455,19.272727 L 27.454545,55.454545"
|
||||
id="path2400" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 10.727273,17.090909 C 10.969697,17.090909 10.969697,17.090909 10.727273,17.090909 z"
|
||||
id="path2402" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 28.545455,8.7272727 C 28.545455,8.7878788 28.545455,8.8484848 28.545455,8.7272727 z"
|
||||
id="path2404" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 27.636364,9.0909091 C 27.575758,9.0909091 27.515152,9.0909091 27.636364,9.0909091 z"
|
||||
id="path2406" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 29.090909,9.6363637 C 28.839485,9.9151131 11.048018,15.903965 10.727273,16.545455"
|
||||
id="path2408"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 37,10.181818 C 36.748576,10.460567 20.048018,17.722146 20.636364,18.181818"
|
||||
id="path2410"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 45.28032,10.909091 C 45.028896,11.18784 28.328338,18.449419 28.916684,18.909091"
|
||||
id="path2412"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 52.007593,18.727273 C 51.756169,19.006022 35.055611,26.267601 35.643957,26.727273"
|
||||
id="path2414"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 52.007593,26.727273 C 51.756169,27.006022 35.055611,34.267601 35.643957,34.727273"
|
||||
id="path2416"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 51.28032,34.727273 C 51.028896,35.006022 34.328338,42.267601 34.916684,42.727273"
|
||||
id="path2418"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 50.734866,41.636364 C 50.483442,41.915113 33.782884,49.176692 34.37123,49.636364"
|
||||
id="path2420"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 3.8181818,23.636364 C 4.0606061,23.636364 4.0606061,23.636364 3.8181818,23.636364 z"
|
||||
id="path2422" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 3.6363636,23.636364 L 34.545455,26.909091"
|
||||
id="path2424" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 34,34.909091 L 3.8181818,31.454545"
|
||||
id="path2426" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 34.181818,43.454545 L 2.9090909,40.181818"
|
||||
id="path2432" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 34,49.818182 L 3.4545455,46.545455"
|
||||
id="path2434" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:21.4082737px;font-style:normal;font-variant:normal;font-weight:300;font-stretch:condensed;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Comfortaa;-inkscape-font-specification:Comfortaa Light Condensed"
|
||||
x="30.022514"
|
||||
y="34.590149"
|
||||
id="text3014-3"
|
||||
sodipodi:linespacing="125%"
|
||||
inkscape:transform-center-x="11.894093"
|
||||
inkscape:transform-center-y="-12.877075"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3016-6"
|
||||
x="30.022514"
|
||||
y="34.590149"
|
||||
style="font-size:56px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;font-family:Courier 10 Pitch;-inkscape-font-specification:Courier 10 Pitch">N</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:21.4082737px;font-style:normal;font-variant:normal;font-weight:300;font-stretch:condensed;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Comfortaa;-inkscape-font-specification:Comfortaa Light Condensed"
|
||||
x="32.172535"
|
||||
y="32.538422"
|
||||
id="text3014"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3016"
|
||||
x="32.172535"
|
||||
y="32.538422"
|
||||
style="font-size:56px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#ff0000;font-family:Courier 10 Pitch;-inkscape-font-specification:Courier 10 Pitch">N</tspan></text>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 12 KiB |
@@ -2464,3 +2464,15 @@ void ViewProviderFEMMeshBuilder::createMesh(const App::Property* prop,
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Python feature -----------------------------------------------------------------------
|
||||
|
||||
namespace Gui {
|
||||
/// @cond DOXERR
|
||||
PROPERTY_SOURCE_TEMPLATE(FemGui::ViewProviderFemMeshPython, FemGui::ViewProviderFemMesh)
|
||||
/// @endcond
|
||||
|
||||
// explicit template instantiation
|
||||
template class FemGuiExport ViewProviderPythonFeatureT<ViewProviderFemMesh>;
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
#include <Gui/ViewProviderGeometryObject.h>
|
||||
#include <Gui/ViewProviderBuilder.h>
|
||||
#include <Gui/ViewProviderPythonFeature.h>
|
||||
|
||||
#include <CXX/Objects.hxx>
|
||||
|
||||
@@ -163,6 +164,9 @@ private:
|
||||
class Private;
|
||||
};
|
||||
|
||||
typedef Gui::ViewProviderPythonFeatureT<ViewProviderFemMesh> ViewProviderFemMeshPython;
|
||||
|
||||
|
||||
} //namespace FemGui
|
||||
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<GenerateModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="generateMetaModel_Module.xsd">
|
||||
<PythonExport
|
||||
Father="ViewProviderPy"
|
||||
Father="ViewProviderDocumentObjectPy"
|
||||
Name="ViewProviderFemMeshPy"
|
||||
Twin="ViewProviderFemMesh"
|
||||
TwinPointer="ViewProviderFemMesh"
|
||||
Include="Mod/Fem/Gui/ViewProviderFemMesh.h"
|
||||
Namespace="FemGui"
|
||||
FatherInclude="Gui/ViewProviderPy.h"
|
||||
FatherInclude="Gui/ViewProviderDocumentObjectPy.h"
|
||||
FatherNamespace="Gui"
|
||||
Constructor="false"
|
||||
Delete="false">
|
||||
|
||||
@@ -58,13 +58,14 @@ Gui::ToolBarItem* Workbench::setupToolBars() const
|
||||
*fem << "Fem_Analysis"
|
||||
<< "Fem_SolverCalculix"
|
||||
// << "Fem_SolverZ88"
|
||||
<< "Fem_MeshFromShape"
|
||||
<< "Fem_MeshNetgenFromShape"
|
||||
<< "Fem_MeshGmshFromShape"
|
||||
<< "Fem_MechanicalMaterial"
|
||||
<< "Fem_MaterialMechanicalNonlinear"
|
||||
<< "Fem_BeamSection"
|
||||
<< "Fem_ShellThickness"
|
||||
<< "Separator"
|
||||
<< "Fem_CreateNodesSet"
|
||||
//<< "Fem_CreateNodesSet"
|
||||
<< "Separator"
|
||||
<< "Fem_ConstraintFixed"
|
||||
<< "Fem_ConstraintDisplacement"
|
||||
@@ -75,12 +76,11 @@ Gui::ToolBarItem* Workbench::setupToolBars() const
|
||||
<< "Fem_ConstraintSelfWeight"
|
||||
<< "Fem_ConstraintForce"
|
||||
<< "Fem_ConstraintPressure"
|
||||
<< "Separator"
|
||||
<< "Fem_ConstraintBearing"
|
||||
<< "Fem_ConstraintGear"
|
||||
<< "Fem_ConstraintPulley"
|
||||
<< "Separator"
|
||||
<< "Fem_ConstraintFluidBoundary"
|
||||
//<< "Separator"
|
||||
//<< "Fem_ConstraintBearing"
|
||||
//<< "Fem_ConstraintGear"
|
||||
//<< "Fem_ConstraintPulley"
|
||||
//<< "Fem_ConstraintFluidBoundary"
|
||||
<< "Separator"
|
||||
<< "Fem_ConstraintTemperature"
|
||||
<< "Fem_ConstraintHeatflux"
|
||||
@@ -119,7 +119,8 @@ Gui::MenuItem* Workbench::setupMenuBar() const
|
||||
*fem << "Fem_Analysis"
|
||||
<< "Fem_SolverCalculix"
|
||||
<< "Fem_SolverZ88"
|
||||
<< "Fem_MeshFromShape"
|
||||
<< "Fem_MeshNetgenFromShape"
|
||||
<< "Fem_MeshGmshFromShape"
|
||||
<< "Fem_MechanicalMaterial"
|
||||
<< "Fem_MaterialMechanicalNonlinear"
|
||||
<< "Fem_BeamSection"
|
||||
|
||||
@@ -25,10 +25,8 @@
|
||||
# * Juergen Riegel 2002 *
|
||||
# ***************************************************************************/
|
||||
|
||||
|
||||
import FreeCAD
|
||||
|
||||
|
||||
FreeCAD.addExportType("TetGen file (*.poly)", "convert2TetGen")
|
||||
FreeCAD.addImportType("FEM formats (*.unv *.med *.dat *.bdf)", "Fem")
|
||||
if("BUILD_FEM_VTK" in FreeCAD.__cmake__):
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
#* Juergen Riegel 2002 *
|
||||
#***************************************************************************/
|
||||
|
||||
|
||||
import FreeCAD
|
||||
import FreeCADGui
|
||||
|
||||
@@ -50,8 +49,8 @@ class FemWorkbench (Workbench):
|
||||
import _CommandRunSolver
|
||||
import _CommandPurgeResults
|
||||
import _CommandControlSolver
|
||||
|
||||
import _CommandMeshFromShape
|
||||
import _CommandMeshGmshFromShape
|
||||
import _CommandMeshNetgenFromShape
|
||||
import _CommandAnalysis
|
||||
import _CommandShellThickness
|
||||
import _CommandBeamSection
|
||||
|
||||
@@ -24,12 +24,12 @@ __title__ = "MechanicalMaterial"
|
||||
__author__ = "Juergen Riegel, Bernd Hahnebach"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
## \addtogroup FEM
|
||||
# @{
|
||||
|
||||
import FreeCAD
|
||||
import _MechanicalMaterial
|
||||
|
||||
## \addtogroup FEM
|
||||
# @{
|
||||
|
||||
def makeMechanicalMaterial(name):
|
||||
'''makeMaterial(name): makes an Material
|
||||
|
||||
203
src/Mod/Fem/TaskPanelFemMeshGmsh.ui
Normal file
203
src/Mod/Fem/TaskPanelFemMeshGmsh.ui
Normal file
@@ -0,0 +1,203 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>GmshMesh</class>
|
||||
<widget class="QWidget" name="GmshMesh">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>413</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>FEM Mesh by GMSH </string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="gb01_mesh_params">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>1677215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>FEM Mesh Parameter</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_9">
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout_1">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
||||
</property>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="l_dimension">
|
||||
<property name="text">
|
||||
<string>Mesh element dimension:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="cb_dimension"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="l_order">
|
||||
<property name="text">
|
||||
<string>Mesh element order:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="cb_order"/>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="l_max">
|
||||
<property name="text">
|
||||
<string>Max element size (0.0 = Auto):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="Gui::InputField" name="if_max">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0.0</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="singleStep" stdset="0">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum" stdset="0">
|
||||
<double>1000000000.000000000000000</double>
|
||||
</property>
|
||||
<property name="unit" stdset="0">
|
||||
<string notr="true">mm</string>
|
||||
</property>
|
||||
<property name="decimals" stdset="0">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="value" stdset="0">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="l_min">
|
||||
<property name="text">
|
||||
<string>Min element size (0.0 = Auto):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="Gui::InputField" name="if_min">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0.0</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="singleStep" stdset="0">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum" stdset="0">
|
||||
<double>1000000000.000000000000000</double>
|
||||
</property>
|
||||
<property name="unit" stdset="0">
|
||||
<string notr="true">mm</string>
|
||||
</property>
|
||||
<property name="decimals" stdset="0">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="value" stdset="0">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="gb03_run_gmsh">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>1677215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>GMSH</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_8">
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
||||
</property>
|
||||
<item row="0" column="1">
|
||||
<layout class="QGridLayout" name="gl_actions">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="l_time">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Time:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QTextEdit" name="te_output">
|
||||
<property name="lineWrapMode">
|
||||
<enum>QTextEdit::NoWrap</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>Gui::InputField</class>
|
||||
<extends>QLineEdit</extends>
|
||||
<header>Gui/InputField.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -29,10 +29,8 @@ __url__ = "http://www.freecadweb.org"
|
||||
|
||||
import FreeCAD
|
||||
from FemCommands import FemCommands
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
import FreeCADGui
|
||||
from PySide import QtCore
|
||||
import FreeCADGui
|
||||
from PySide import QtCore
|
||||
|
||||
|
||||
class _CommandAnalysis(FemCommands):
|
||||
@@ -58,11 +56,6 @@ class _CommandAnalysis(FemCommands):
|
||||
if (len(sel) == 1):
|
||||
if(sel[0].isDerivedFrom("Fem::FemMeshObject")):
|
||||
FreeCADGui.doCommand("FemGui.getActiveAnalysis().Member = FemGui.getActiveAnalysis().Member + [App.activeDocument()." + sel[0].Name + "]")
|
||||
if(sel[0].isDerivedFrom("Part::Feature")):
|
||||
FreeCADGui.doCommand("App.activeDocument().addObject('Fem::FemMeshShapeNetgenObject', '" + sel[0].Name + "_Mesh')")
|
||||
FreeCADGui.doCommand("App.activeDocument().ActiveObject.Shape = App.activeDocument()." + sel[0].Name)
|
||||
FreeCADGui.doCommand("FemGui.getActiveAnalysis().Member = FemGui.getActiveAnalysis().Member + [App.activeDocument().ActiveObject]")
|
||||
FreeCADGui.doCommand("Gui.activeDocument().setEdit(App.ActiveDocument.ActiveObject.Name)")
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
|
||||
@@ -29,10 +29,8 @@ __url__ = "http://www.freecadweb.org"
|
||||
|
||||
import FreeCAD
|
||||
from FemCommands import FemCommands
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
import FreeCADGui
|
||||
from PySide import QtCore
|
||||
import FreeCADGui
|
||||
from PySide import QtCore
|
||||
|
||||
|
||||
class _CommandBeamSection(FemCommands):
|
||||
|
||||
@@ -29,10 +29,8 @@ __url__ = "http://www.freecadweb.org"
|
||||
|
||||
import FreeCAD
|
||||
from FemCommands import FemCommands
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
import FreeCADGui
|
||||
from PySide import QtCore
|
||||
import FreeCADGui
|
||||
from PySide import QtCore
|
||||
|
||||
|
||||
class _CommandConstraintSelfWeight(FemCommands):
|
||||
|
||||
@@ -29,10 +29,8 @@ __url__ = "http://www.freecadweb.org"
|
||||
|
||||
import FreeCAD
|
||||
from FemCommands import FemCommands
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
import FreeCADGui
|
||||
from PySide import QtCore
|
||||
import FreeCADGui
|
||||
from PySide import QtCore
|
||||
|
||||
|
||||
class _CommandControlSolver(FemCommands):
|
||||
|
||||
@@ -29,11 +29,9 @@ __url__ = "http://www.freecadweb.org"
|
||||
|
||||
import FreeCAD
|
||||
from FemCommands import FemCommands
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
import FreeCADGui
|
||||
import FemGui
|
||||
from PySide import QtCore
|
||||
import FreeCADGui
|
||||
import FemGui
|
||||
from PySide import QtCore
|
||||
|
||||
|
||||
class _CommandMaterialMechanicalNonlinear(FemCommands):
|
||||
|
||||
@@ -29,11 +29,9 @@ __url__ = "http://www.freecadweb.org"
|
||||
|
||||
import FreeCAD
|
||||
from FemCommands import FemCommands
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
import FreeCADGui
|
||||
import FemGui
|
||||
from PySide import QtCore
|
||||
import FreeCADGui
|
||||
import FemGui
|
||||
from PySide import QtCore
|
||||
|
||||
|
||||
class _CommandMechanicalMaterial(FemCommands):
|
||||
|
||||
65
src/Mod/Fem/_CommandMeshGmshFromShape.py
Normal file
65
src/Mod/Fem/_CommandMeshGmshFromShape.py
Normal file
@@ -0,0 +1,65 @@
|
||||
# ***************************************************************************
|
||||
# * *
|
||||
# * Copyright (c) 2016 - Bernd Hahnebach <bernd@bimstatik.org> *
|
||||
# * *
|
||||
# * This program is free software; you can redistribute it and/or modify *
|
||||
# * it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
# * as published by the Free Software Foundation; either version 2 of *
|
||||
# * the License, or (at your option) any later version. *
|
||||
# * for detail see the LICENCE text file. *
|
||||
# * *
|
||||
# * 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 Library General Public License for more details. *
|
||||
# * *
|
||||
# * You should have received a copy of the GNU Library 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 *
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
|
||||
__title__ = "Command GMSH Mesh From Shape"
|
||||
__author__ = "Bernd Hahnebach"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
## @package CommandMeshGmshFromShape
|
||||
# \ingroup FEM
|
||||
|
||||
import FreeCAD
|
||||
from FemCommands import FemCommands
|
||||
import FreeCADGui
|
||||
import FemGui
|
||||
from PySide import QtCore
|
||||
|
||||
|
||||
class _CommandMeshGmshFromShape(FemCommands):
|
||||
# the Fem_MeshGmshFromShape command definition
|
||||
def __init__(self):
|
||||
super(_CommandMeshGmshFromShape, self).__init__()
|
||||
self.resources = {'Pixmap': 'fem-fem-mesh-gmsh-from-shape',
|
||||
'MenuText': QtCore.QT_TRANSLATE_NOOP("Fem_MeshGmshFromShape", "FEM mesh from shape by GMSH"),
|
||||
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Fem_MeshGmshFromShape", "Create a FEM mesh from a shape by GMSH mesher")}
|
||||
self.is_active = 'with_part_feature'
|
||||
|
||||
def Activated(self):
|
||||
FreeCAD.ActiveDocument.openTransaction("Create FEM mesh by GMSH")
|
||||
FreeCADGui.addModule("FemGui")
|
||||
sel = FreeCADGui.Selection.getSelection()
|
||||
if (len(sel) == 1):
|
||||
if(sel[0].isDerivedFrom("Part::Feature")):
|
||||
mesh_obj_name = sel[0].Name + "_Mesh"
|
||||
FreeCADGui.addModule("FemMeshGmsh")
|
||||
FreeCADGui.doCommand("FemMeshGmsh.makeFemMeshGmsh('" + mesh_obj_name + "')")
|
||||
FreeCADGui.doCommand("App.ActiveDocument.ActiveObject.Part = App.ActiveDocument." + sel[0].Name)
|
||||
if FemGui.getActiveAnalysis():
|
||||
FreeCADGui.addModule("FemGui")
|
||||
FreeCADGui.doCommand("FemGui.getActiveAnalysis().Member = FemGui.getActiveAnalysis().Member + [App.ActiveDocument.ActiveObject]")
|
||||
FreeCADGui.doCommand("Gui.ActiveDocument.setEdit(App.ActiveDocument.ActiveObject.Name)")
|
||||
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
FreeCADGui.addCommand('Fem_MeshGmshFromShape', _CommandMeshGmshFromShape())
|
||||
@@ -20,32 +20,30 @@
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
|
||||
__title__ = "Command Mesh From Shape"
|
||||
__title__ = "Command Mesh Netgen From Shape"
|
||||
__author__ = "Juergen Riegel"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
## @package CommandMeshFromShape
|
||||
## @package CommandMeshNetgenFromShape
|
||||
# \ingroup FEM
|
||||
|
||||
import FreeCAD
|
||||
from FemCommands import FemCommands
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
import FreeCADGui
|
||||
from PySide import QtCore
|
||||
import FreeCADGui
|
||||
from PySide import QtCore
|
||||
|
||||
|
||||
class _CommandMeshFromShape(FemCommands):
|
||||
# the Fem_MeshFromShape command definition
|
||||
class _CommandMeshNetgenFromShape(FemCommands):
|
||||
# the Fem_MeshNetgenFromShape command definition
|
||||
def __init__(self):
|
||||
super(_CommandMeshFromShape, self).__init__()
|
||||
self.resources = {'Pixmap': 'fem-fem-mesh-from-shape',
|
||||
'MenuText': QtCore.QT_TRANSLATE_NOOP("Fem_MeshFromShape", "FEM mesh from shape"),
|
||||
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Fem_MeshFromShape", "Create a FEM volume mesh from a solid shape")}
|
||||
super(_CommandMeshNetgenFromShape, self).__init__()
|
||||
self.resources = {'Pixmap': 'fem-fem-mesh-netgen-from-shape',
|
||||
'MenuText': QtCore.QT_TRANSLATE_NOOP("Fem_MeshFromShape", "FEM mesh from shape by Netgen"),
|
||||
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Fem_MeshFromShape", "Create a FEM volume mesh from a solid or face shape by Netgen internal mesher")}
|
||||
self.is_active = 'with_part_feature'
|
||||
|
||||
def Activated(self):
|
||||
FreeCAD.ActiveDocument.openTransaction("Create FEM mesh")
|
||||
FreeCAD.ActiveDocument.openTransaction("Create FEM mesh Netgen")
|
||||
FreeCADGui.addModule("FemGui")
|
||||
sel = FreeCADGui.Selection.getSelection()
|
||||
if (len(sel) == 1):
|
||||
@@ -58,4 +56,4 @@ class _CommandMeshFromShape(FemCommands):
|
||||
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
FreeCADGui.addCommand('Fem_MeshFromShape', _CommandMeshFromShape())
|
||||
FreeCADGui.addCommand('Fem_MeshNetgenFromShape', _CommandMeshNetgenFromShape())
|
||||
@@ -30,10 +30,8 @@ __url__ = "http://www.freecadweb.org"
|
||||
import FreeCAD
|
||||
from FemCommands import FemCommands
|
||||
import FemTools
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
import FreeCADGui
|
||||
from PySide import QtCore
|
||||
import FreeCADGui
|
||||
from PySide import QtCore
|
||||
|
||||
|
||||
class _CommandPurgeResults(FemCommands):
|
||||
|
||||
@@ -29,10 +29,8 @@ __url__ = "http://www.freecadweb.org"
|
||||
|
||||
import FreeCAD
|
||||
from FemCommands import FemCommands
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
import FreeCADGui
|
||||
from PySide import QtCore, QtGui
|
||||
import FreeCADGui
|
||||
from PySide import QtCore, QtGui
|
||||
|
||||
|
||||
class _CommandRunSolver(FemCommands):
|
||||
|
||||
@@ -29,10 +29,8 @@ __url__ = "http://www.freecadweb.org"
|
||||
|
||||
import FreeCAD
|
||||
from FemCommands import FemCommands
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
import FreeCADGui
|
||||
from PySide import QtCore
|
||||
import FreeCADGui
|
||||
from PySide import QtCore
|
||||
|
||||
|
||||
class _CommandShellThickness(FemCommands):
|
||||
|
||||
@@ -29,10 +29,8 @@ __url__ = "http://www.freecadweb.org"
|
||||
|
||||
import FreeCAD
|
||||
from FemCommands import FemCommands
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
import FreeCADGui
|
||||
from PySide import QtCore, QtGui
|
||||
import FreeCADGui
|
||||
from PySide import QtCore, QtGui
|
||||
|
||||
|
||||
class _CommandShowResult(FemCommands):
|
||||
|
||||
@@ -29,11 +29,9 @@ __url__ = "http://www.freecadweb.org"
|
||||
|
||||
import FreeCAD
|
||||
from FemCommands import FemCommands
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
import FreeCADGui
|
||||
import FemGui
|
||||
from PySide import QtCore
|
||||
import FreeCADGui
|
||||
import FemGui
|
||||
from PySide import QtCore
|
||||
|
||||
|
||||
class _CommandSolverCalculix(FemCommands):
|
||||
|
||||
@@ -29,10 +29,8 @@ __url__ = "http://www.freecadweb.org"
|
||||
|
||||
import FreeCAD
|
||||
from FemCommands import FemCommands
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
import FreeCADGui
|
||||
from PySide import QtCore
|
||||
import FreeCADGui
|
||||
from PySide import QtCore
|
||||
|
||||
|
||||
class _CommandSolverZ88(FemCommands):
|
||||
|
||||
@@ -27,6 +27,7 @@ __url__ = "http://www.freecadweb.org"
|
||||
## @package FemBeamSection
|
||||
# \ingroup FEM
|
||||
|
||||
|
||||
class _FemBeamSection:
|
||||
"The FemBeamSection object"
|
||||
def __init__(self, obj):
|
||||
|
||||
@@ -27,6 +27,7 @@ __url__ = "http://www.freecadweb.org"
|
||||
## @package FemConstraintSelfWeight
|
||||
# \ingroup FEM
|
||||
|
||||
|
||||
class _FemConstraintSelfWeight:
|
||||
"The FemConstraintSelfWeight object"
|
||||
def __init__(self, obj):
|
||||
|
||||
@@ -27,6 +27,7 @@ __url__ = "http://www.freecadweb.org"
|
||||
## @package FemMaterialMechanicalNonLinear
|
||||
# \ingroup FEM
|
||||
|
||||
|
||||
class _FemMaterialMechanicalNonlinear:
|
||||
"The FemMaterialMechanicalNonlinear object"
|
||||
def __init__(self, obj):
|
||||
|
||||
69
src/Mod/Fem/_FemMeshGmsh.py
Normal file
69
src/Mod/Fem/_FemMeshGmsh.py
Normal file
@@ -0,0 +1,69 @@
|
||||
# ***************************************************************************
|
||||
# * *
|
||||
# * Copyright (c) 2016 - Bernd Hahnebach <bernd@bimstatik.org> *
|
||||
# * *
|
||||
# * This program is free software; you can redistribute it and/or modify *
|
||||
# * it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
# * as published by the Free Software Foundation; either version 2 of *
|
||||
# * the License, or (at your option) any later version. *
|
||||
# * for detail see the LICENCE text file. *
|
||||
# * *
|
||||
# * 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 Library General Public License for more details. *
|
||||
# * *
|
||||
# * You should have received a copy of the GNU Library 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 *
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
|
||||
__title__ = "_FemMeshGmsh"
|
||||
__author__ = "Bernd Hahnebach"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
## @package FemMeshGmsh
|
||||
# \ingroup FEM
|
||||
|
||||
|
||||
class _FemMeshGmsh():
|
||||
"""The Fem::FemMeshObject's Proxy python type, add GMSH specific properties
|
||||
"""
|
||||
|
||||
# they will be used from the task panel too, thus they need to be outside of the __init__
|
||||
known_element_dimensions = ['Auto', '1D', '2D', '3D']
|
||||
known_element_orders = ['Auto', '1st', '2nd']
|
||||
|
||||
def __init__(self, obj):
|
||||
self.Type = "FemMeshGmsh"
|
||||
self.Object = obj # keep a ref to the DocObj for nonGui usage
|
||||
obj.Proxy = self # link between App::DocumentObject to this object
|
||||
|
||||
obj.addProperty("App::PropertyLink", "Part", "FEM Mesh", "Part object to mesh")
|
||||
obj.Part = None
|
||||
|
||||
obj.addProperty("App::PropertyFloat", "ElementSizeMax", "FEM Mesh Params", "Max mesh element size (0.0 = infinity)")
|
||||
obj.ElementSizeMax = 0.0 # will be 1e+22
|
||||
|
||||
obj.addProperty("App::PropertyFloat", "ElementSizeMin", "FEM Mesh Params", "Min mesh element size")
|
||||
obj.ElementSizeMin = 0.0
|
||||
|
||||
obj.addProperty("App::PropertyEnumeration", "ElementDimension", "FEM Mesh Params", "Dimension of mesh elements (Auto = according ShapeType of part to mesh)")
|
||||
obj.ElementDimension = _FemMeshGmsh.known_element_dimensions
|
||||
obj.ElementDimension = 'Auto' # according ShapeType of Part to mesh
|
||||
|
||||
obj.addProperty("App::PropertyEnumeration", "ElementOrder", "FEM Mesh Params", "Order of mesh elements (Auto will be 2nd)")
|
||||
obj.ElementOrder = _FemMeshGmsh.known_element_orders
|
||||
obj.ElementOrder = 'Auto' # = 2nd
|
||||
|
||||
def execute(self, obj):
|
||||
return
|
||||
|
||||
def __getstate__(self):
|
||||
return self.Type
|
||||
|
||||
def __setstate__(self, state):
|
||||
if state:
|
||||
self.Type = state
|
||||
@@ -27,6 +27,7 @@ __url__ = "http://www.freecadweb.org"
|
||||
## @package FemShellThickness
|
||||
# \ingroup FEM
|
||||
|
||||
|
||||
class _FemShellThickness:
|
||||
"The FemShellThickness object"
|
||||
def __init__(self, obj):
|
||||
|
||||
@@ -42,7 +42,7 @@ class _FemSolverCalculix():
|
||||
obj.addProperty("App::PropertyString", "SolverType", "Base", "Type of the solver", 1) # the 1 set the property to ReadOnly
|
||||
obj.SolverType = str(self.Type)
|
||||
|
||||
fem_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem/General")
|
||||
# fem_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem/General") # not needed ATM
|
||||
ccx_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem/Ccx")
|
||||
|
||||
obj.addProperty("App::PropertyPath", "WorkingDir", "Fem", "Working directory for calculations, will only be used it is left blank in preferences")
|
||||
|
||||
@@ -27,6 +27,7 @@ __url__ = "http://www.freecadweb.org"
|
||||
## @package MechanicalMaterial
|
||||
# \ingroup FEM
|
||||
|
||||
|
||||
class _MechanicalMaterial:
|
||||
"The Material object"
|
||||
def __init__(self, obj):
|
||||
|
||||
170
src/Mod/Fem/_TaskPanelFemMeshGmsh.py
Normal file
170
src/Mod/Fem/_TaskPanelFemMeshGmsh.py
Normal file
@@ -0,0 +1,170 @@
|
||||
# ***************************************************************************
|
||||
# * *
|
||||
# * Copyright (c) 2016 - Bernd Hahnebach <bernd@bimstatik.org> *
|
||||
# * *
|
||||
# * This program is free software; you can redistribute it and/or modify *
|
||||
# * it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
# * as published by the Free Software Foundation; either version 2 of *
|
||||
# * the License, or (at your option) any later version. *
|
||||
# * for detail see the LICENCE text file. *
|
||||
# * *
|
||||
# * 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 Library General Public License for more details. *
|
||||
# * *
|
||||
# * You should have received a copy of the GNU Library 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 *
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
|
||||
__title__ = "_TaskPanelFemMeshGmsh"
|
||||
__author__ = "Bernd Hahnebach"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
## @package TaskPanelFemMeshGmsh
|
||||
# \ingroup FEM
|
||||
|
||||
import FreeCAD
|
||||
import time
|
||||
import _FemMeshGmsh
|
||||
import FreeCADGui
|
||||
from PySide import QtGui
|
||||
from PySide import QtCore
|
||||
from PySide.QtCore import Qt
|
||||
from PySide.QtGui import QApplication
|
||||
|
||||
|
||||
class _TaskPanelFemMeshGmsh:
|
||||
'''The TaskPanel for editing References property of FemMeshGmsh objects and creation of new FEM mesh'''
|
||||
def __init__(self, obj):
|
||||
self.mesh_obj = obj
|
||||
self.form = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Fem/TaskPanelFemMeshGmsh.ui")
|
||||
|
||||
self.Timer = QtCore.QTimer()
|
||||
self.Timer.start(100) # 100 milli seconds
|
||||
self.gmsh_runs = False
|
||||
self.console_message_gmsh = ''
|
||||
|
||||
QtCore.QObject.connect(self.form.if_max, QtCore.SIGNAL("valueChanged(double)"), self.max_changed)
|
||||
QtCore.QObject.connect(self.form.if_min, QtCore.SIGNAL("valueChanged(double)"), self.min_changed)
|
||||
QtCore.QObject.connect(self.form.cb_dimension, QtCore.SIGNAL("activated(int)"), self.choose_dimension)
|
||||
QtCore.QObject.connect(self.form.cb_order, QtCore.SIGNAL("activated(int)"), self.choose_order)
|
||||
QtCore.QObject.connect(self.Timer, QtCore.SIGNAL("timeout()"), self.update_timer_text)
|
||||
|
||||
self.form.cb_dimension.addItems(_FemMeshGmsh._FemMeshGmsh.known_element_dimensions)
|
||||
self.form.cb_order.addItems(_FemMeshGmsh._FemMeshGmsh.known_element_orders)
|
||||
|
||||
self.get_mesh_params()
|
||||
self.get_active_analysis()
|
||||
self.update()
|
||||
|
||||
def getStandardButtons(self):
|
||||
return int(QtGui.QDialogButtonBox.Apply | QtGui.QDialogButtonBox.Close)
|
||||
# show a apply and a close button
|
||||
# def reject() is called on close button
|
||||
# def clicked(self, button) is needed, to access the apply button
|
||||
# def accept() in no longer needed, since there is no OK button
|
||||
|
||||
def reject(self):
|
||||
FreeCADGui.ActiveDocument.resetEdit()
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
return True
|
||||
|
||||
def clicked(self, button):
|
||||
if button == QtGui.QDialogButtonBox.Apply:
|
||||
self.run_gmsh()
|
||||
|
||||
def get_mesh_params(self):
|
||||
self.clmax = self.mesh_obj.ElementSizeMax
|
||||
self.clmin = self.mesh_obj.ElementSizeMin
|
||||
self.order = self.mesh_obj.ElementOrder
|
||||
self.dimension = self.mesh_obj.ElementDimension
|
||||
|
||||
def set_mesh_params(self):
|
||||
self.mesh_obj.ElementSizeMax = self.clmax
|
||||
self.mesh_obj.ElementSizeMin = self.clmin
|
||||
self.mesh_obj.ElementOrder = self.order
|
||||
self.mesh_obj.ElementDimension = self.dimension
|
||||
|
||||
def update(self):
|
||||
'fills the widgets'
|
||||
self.form.if_max.setText("{} mm".format(self.clmax))
|
||||
self.form.if_min.setText("{} mm".format(self.clmin))
|
||||
index_dimension = self.form.cb_dimension.findText(self.dimension)
|
||||
self.form.cb_dimension.setCurrentIndex(index_dimension)
|
||||
index_order = self.form.cb_order.findText(self.order)
|
||||
self.form.cb_order.setCurrentIndex(index_order)
|
||||
|
||||
def console_log(self, message="", color="#000000"):
|
||||
self.console_message_gmsh = self.console_message_gmsh + '<font color="#0000FF">{0:4.1f}:</font> <font color="{1}">{2}</font><br>'.\
|
||||
format(time.time() - self.Start, color, message.encode('utf-8', 'replace'))
|
||||
self.form.te_output.setText(self.console_message_gmsh)
|
||||
self.form.te_output.moveCursor(QtGui.QTextCursor.End)
|
||||
|
||||
def update_timer_text(self):
|
||||
# print('timer1')
|
||||
if self.gmsh_runs:
|
||||
print('timer2')
|
||||
# print('Time: {0:4.1f}: '.format(time.time() - self.Start))
|
||||
self.form.l_time.setText('Time: {0:4.1f}: '.format(time.time() - self.Start))
|
||||
|
||||
def max_changed(self, value):
|
||||
self.clmax = float(value)
|
||||
|
||||
def min_changed(self, value):
|
||||
self.clmin = float(value)
|
||||
|
||||
def choose_dimension(self, index):
|
||||
if index < 0:
|
||||
return
|
||||
self.form.cb_dimension.setCurrentIndex(index)
|
||||
self.dimension = str(self.form.cb_dimension.itemText(index)) # form returns unicode
|
||||
|
||||
def choose_order(self, index):
|
||||
if index < 0:
|
||||
return
|
||||
self.form.cb_order.setCurrentIndex(index)
|
||||
self.order = str(self.form.cb_order.itemText(index)) # form returns unicode
|
||||
|
||||
def run_gmsh(self):
|
||||
QApplication.setOverrideCursor(Qt.WaitCursor)
|
||||
self.Start = time.time()
|
||||
self.form.l_time.setText('Time: {0:4.1f}: '.format(time.time() - self.Start))
|
||||
self.console_message_gmsh = ''
|
||||
self.gmsh_runs = True
|
||||
self.console_log("We gone start ...")
|
||||
self.get_active_analysis()
|
||||
self.set_mesh_params()
|
||||
import FemGmshTools
|
||||
gmsh_mesh = FemGmshTools.FemGmshTools(self.obj, self.analysis)
|
||||
self.console_log("Start GMSH ...")
|
||||
error = gmsh_mesh.create_mesh()
|
||||
if error:
|
||||
print(error)
|
||||
self.console_log('GMSH had warnings ...')
|
||||
self.console_log(error, '#FF0000')
|
||||
else:
|
||||
self.console_log('Clean run of GMSH')
|
||||
self.console_log("GMSH done!")
|
||||
self.form.l_time.setText('Time: {0:4.1f}: '.format(time.time() - self.Start))
|
||||
self.Timer.stop()
|
||||
self.update()
|
||||
QApplication.restoreOverrideCursor()
|
||||
|
||||
def get_active_analysis(self):
|
||||
import FemGui
|
||||
self.analysis = FemGui.getActiveAnalysis()
|
||||
if self.analysis:
|
||||
for m in FemGui.getActiveAnalysis().Member:
|
||||
if m.Name == self.mesh_obj.Name:
|
||||
print(self.analysis.Name)
|
||||
return
|
||||
else:
|
||||
# print('Mesh is not member of active analysis, means no group meshing')
|
||||
self.analysis = None # no group meshing
|
||||
else:
|
||||
# print('No active analyis, means no group meshing')
|
||||
self.analysis = None # no group meshing
|
||||
@@ -31,13 +31,11 @@ import FemToolsCcx
|
||||
import FreeCAD
|
||||
import os
|
||||
import time
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
import FreeCADGui
|
||||
import FemGui
|
||||
from PySide import QtCore, QtGui
|
||||
from PySide.QtCore import Qt
|
||||
from PySide.QtGui import QApplication
|
||||
import FreeCADGui
|
||||
import FemGui
|
||||
from PySide import QtCore, QtGui
|
||||
from PySide.QtCore import Qt
|
||||
from PySide.QtGui import QApplication
|
||||
|
||||
|
||||
class _TaskPanelFemSolverCalculix:
|
||||
@@ -83,6 +81,25 @@ class _TaskPanelFemSolverCalculix:
|
||||
|
||||
self.update()
|
||||
|
||||
def getStandardButtons(self):
|
||||
# only show a close button
|
||||
# def accept() in no longer needed, since there is no OK button
|
||||
return int(QtGui.QDialogButtonBox.Close)
|
||||
|
||||
def reject(self):
|
||||
FreeCADGui.ActiveDocument.resetEdit()
|
||||
|
||||
def update(self):
|
||||
'fills the widgets'
|
||||
self.form.le_working_dir.setText(self.solver_object.WorkingDir)
|
||||
if self.solver_object.AnalysisType == 'static':
|
||||
self.form.rb_static_analysis.setChecked(True)
|
||||
elif self.solver_object.AnalysisType == 'frequency':
|
||||
self.form.rb_frequency_analysis.setChecked(True)
|
||||
elif self.solver_object.AnalysisType == 'thermomech':
|
||||
self.form.rb_thermomech_analysis.setChecked(True)
|
||||
return
|
||||
|
||||
def femConsoleMessage(self, message="", color="#000000"):
|
||||
self.fem_console_message = self.fem_console_message + '<font color="#0000FF">{0:4.1f}:</font> <font color="{1}">{2}</font><br>'.\
|
||||
format(time.time() - self.Start, color, message.encode('utf-8', 'replace'))
|
||||
@@ -152,26 +169,6 @@ class _TaskPanelFemSolverCalculix:
|
||||
QApplication.restoreOverrideCursor()
|
||||
self.form.l_time.setText('Time: {0:4.1f}: '.format(time.time() - self.Start))
|
||||
|
||||
def getStandardButtons(self):
|
||||
return int(QtGui.QDialogButtonBox.Close)
|
||||
|
||||
def update(self):
|
||||
'fills the widgets'
|
||||
self.form.le_working_dir.setText(self.solver_object.WorkingDir)
|
||||
if self.solver_object.AnalysisType == 'static':
|
||||
self.form.rb_static_analysis.setChecked(True)
|
||||
elif self.solver_object.AnalysisType == 'frequency':
|
||||
self.form.rb_frequency_analysis.setChecked(True)
|
||||
elif self.solver_object.AnalysisType == 'thermomech':
|
||||
self.form.rb_thermomech_analysis.setChecked(True)
|
||||
return
|
||||
|
||||
def accept(self):
|
||||
FreeCADGui.ActiveDocument.resetEdit()
|
||||
|
||||
def reject(self):
|
||||
FreeCADGui.ActiveDocument.resetEdit()
|
||||
|
||||
def choose_working_dir(self):
|
||||
current_wd = self.setup_working_dir()
|
||||
wd = QtGui.QFileDialog.getExistingDirectory(None, 'Choose CalculiX working directory',
|
||||
|
||||
@@ -31,12 +31,11 @@ import FreeCAD
|
||||
import FemTools
|
||||
import numpy as np
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
import FreeCADGui
|
||||
import FemGui
|
||||
from PySide import QtCore, QtGui
|
||||
from PySide.QtCore import Qt
|
||||
from PySide.QtGui import QApplication
|
||||
import FreeCADGui
|
||||
import FemGui
|
||||
from PySide import QtCore, QtGui
|
||||
from PySide.QtCore import Qt
|
||||
from PySide.QtGui import QApplication
|
||||
|
||||
|
||||
class _TaskPanelShowResult:
|
||||
@@ -304,10 +303,6 @@ class _TaskPanelShowResult:
|
||||
def update(self):
|
||||
self.MeshObject = None
|
||||
self.result_object = get_results_object(FreeCADGui.Selection.getSelection())
|
||||
# Disable temperature radio button if it does ot exist in results
|
||||
if len(self.result_object.Temperature) == 1:
|
||||
self.form.rb_temperature.setEnabled(0)
|
||||
|
||||
for i in FemGui.getActiveAnalysis().Member:
|
||||
if i.isDerivedFrom("Fem::FemMeshObject"):
|
||||
self.MeshObject = i
|
||||
@@ -315,13 +310,21 @@ class _TaskPanelShowResult:
|
||||
|
||||
self.suitable_results = False
|
||||
if self.result_object:
|
||||
# Disable temperature radio button if it does ot exist in results
|
||||
if len(self.result_object.Temperature) == 1:
|
||||
self.form.rb_temperature.setEnabled(0)
|
||||
|
||||
if (self.MeshObject.FemMesh.NodeCount == len(self.result_object.NodeNumbers)):
|
||||
self.suitable_results = True
|
||||
else:
|
||||
if not self.MeshObject.FemMesh.VolumeCount:
|
||||
FreeCAD.Console.PrintError('Graphical bending stress output for beam or shell FEM Meshes not yet supported!\n')
|
||||
FreeCAD.Console.PrintError('FEM: Graphical bending stress output for beam or shell FEM Meshes not yet supported.\n')
|
||||
else:
|
||||
FreeCAD.Console.PrintError('Result node numbers are not equal to FEM Mesh NodeCount!\n')
|
||||
FreeCAD.Console.PrintError('FEM: Result node numbers are not equal to FEM Mesh NodeCount.\n')
|
||||
else:
|
||||
error_message = 'FEM: Result task panel, no result object to display results for.\n'
|
||||
FreeCAD.Console.PrintError(error_message)
|
||||
QtGui.QMessageBox.critical(None, 'No result object', error_message)
|
||||
|
||||
def accept(self):
|
||||
FreeCADGui.Control.closeDialog()
|
||||
|
||||
111
src/Mod/Fem/_ViewProviderFemMeshGmsh.py
Normal file
111
src/Mod/Fem/_ViewProviderFemMeshGmsh.py
Normal file
@@ -0,0 +1,111 @@
|
||||
# ***************************************************************************
|
||||
# * *
|
||||
# * Copyright (c) 2016 - Bernd Hahnebach <bernd@bimstatik.org> *
|
||||
# * *
|
||||
# * This program is free software; you can redistribute it and/or modify *
|
||||
# * it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
# * as published by the Free Software Foundation; either version 2 of *
|
||||
# * the License, or (at your option) any later version. *
|
||||
# * for detail see the LICENCE text file. *
|
||||
# * *
|
||||
# * 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 Library General Public License for more details. *
|
||||
# * *
|
||||
# * You should have received a copy of the GNU Library 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 *
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
|
||||
__title__ = "_ViewProviderFemMeshGmsh"
|
||||
__author__ = "Bernd Hahnebach"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
## @package ViewProviderFemMeshGmsh
|
||||
# \ingroup FEM
|
||||
|
||||
import FreeCAD
|
||||
import FreeCADGui
|
||||
import FemGui
|
||||
|
||||
|
||||
class _ViewProviderFemMeshGmsh:
|
||||
"A View Provider for the FemMeshGmsh object"
|
||||
def __init__(self, vobj):
|
||||
vobj.Proxy = self
|
||||
|
||||
def getIcon(self):
|
||||
return ":/icons/fem-fem-mesh-from-shape.svg"
|
||||
|
||||
def attach(self, vobj):
|
||||
self.ViewObject = vobj
|
||||
self.Object = vobj.Object
|
||||
|
||||
def updateData(self, obj, prop):
|
||||
return
|
||||
|
||||
def onChanged(self, vobj, prop):
|
||||
return
|
||||
|
||||
def setEdit(self, vobj, mode):
|
||||
self.ViewObject.show() # show the mesh on edit if it is hided
|
||||
import _TaskPanelFemMeshGmsh
|
||||
taskd = _TaskPanelFemMeshGmsh._TaskPanelFemMeshGmsh(self.Object)
|
||||
taskd.obj = vobj.Object
|
||||
FreeCADGui.Control.showDialog(taskd)
|
||||
return True
|
||||
|
||||
def unsetEdit(self, vobj, mode):
|
||||
FreeCADGui.Control.closeDialog()
|
||||
return
|
||||
|
||||
def doubleClicked(self, vobj):
|
||||
# Group meshing is only active on active analysis, we should make sure the analysis the mesh belongs too is active
|
||||
gui_doc = FreeCADGui.getDocument(vobj.Object.Document)
|
||||
if not gui_doc.getInEdit():
|
||||
# may be go the other way around and just activate the analysis the user has doubleClicked on ?!
|
||||
# not a fast one, we need to iterate over all member of all analysis to know to which analyis the object belongs too!!!
|
||||
if FemGui.getActiveAnalysis() is not None:
|
||||
if FemGui.getActiveAnalysis().Document is FreeCAD.ActiveDocument:
|
||||
if self.Object in FemGui.getActiveAnalysis().Member:
|
||||
if not gui_doc.getInEdit():
|
||||
gui_doc.setEdit(vobj.Object.Name)
|
||||
else:
|
||||
FreeCAD.Console.PrintError('Activate the analysis this mesh belongs to!\n')
|
||||
else:
|
||||
print('Mesh does not belong to the active analysis.')
|
||||
for o in gui_doc.Document.Objects:
|
||||
if o.isDerivedFrom('Fem::FemAnalysisPython'):
|
||||
for m in o.Member:
|
||||
if m == self.Object:
|
||||
FemGui.setActiveAnalysis(o)
|
||||
print('Analysis the Mesh belongs too was activated.')
|
||||
gui_doc.setEdit(vobj.Object.Name)
|
||||
break
|
||||
else:
|
||||
FreeCAD.Console.PrintError('Active Analysis is not in active Document!\n')
|
||||
else:
|
||||
# no active analysis, we gone have a look if the obj belongs to a non active analysis,
|
||||
for o in gui_doc.Document.Objects:
|
||||
if o.isDerivedFrom('Fem::FemAnalysisPython'):
|
||||
for m in o.Member:
|
||||
if m == self.Object:
|
||||
FemGui.setActiveAnalysis(o)
|
||||
print('Analysis the Mesh belongs too was activated.')
|
||||
gui_doc.setEdit(vobj.Object.Name)
|
||||
break
|
||||
else:
|
||||
print('Mesh GMSH object does not belong to an analysis. Group meshing will is deactivated.')
|
||||
gui_doc.setEdit(vobj.Object.Name)
|
||||
else:
|
||||
FreeCAD.Console.PrintError('Active Task Dialog found! Please close this one first!\n')
|
||||
return True
|
||||
|
||||
def __getstate__(self):
|
||||
return None
|
||||
|
||||
def __setstate__(self, state):
|
||||
return None
|
||||
@@ -20,7 +20,7 @@
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
|
||||
__title__ = "_FemViewProviderSolverCalculix"
|
||||
__title__ = "_ViewProviderFemSolverCalculix"
|
||||
__author__ = "Bernd Hahnebach"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
|
||||
__title__ = "_FemViewProviderSolverZ88"
|
||||
__title__ = "_ViewProviderFemSolverZ88"
|
||||
__author__ = "Bernd Hahnebach"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
|
||||
@@ -20,10 +20,6 @@
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
|
||||
|
||||
import FreeCAD
|
||||
import os
|
||||
|
||||
__title__ = "ccxDatReader"
|
||||
__author__ = "Przemo Firszt"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
@@ -31,6 +27,10 @@ __url__ = "http://www.freecadweb.org"
|
||||
## @package ccxDatReader
|
||||
# \ingroup FEM
|
||||
|
||||
import FreeCAD
|
||||
import os
|
||||
|
||||
|
||||
if open.__module__ == '__builtin__':
|
||||
# because we'll redefine open below
|
||||
pyopen = open
|
||||
|
||||
@@ -22,12 +22,6 @@
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
|
||||
|
||||
import FreeCAD
|
||||
import os
|
||||
from math import pow, sqrt
|
||||
import numpy as np
|
||||
|
||||
__title__ = "FreeCAD Calculix library"
|
||||
__author__ = "Juergen Riegel , Michael Hindley, Bernd Hahnebach"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
@@ -35,6 +29,12 @@ __url__ = "http://www.freecadweb.org"
|
||||
## @package ccxFrdReader
|
||||
# \ingroup FEM
|
||||
|
||||
import FreeCAD
|
||||
import os
|
||||
from math import pow, sqrt
|
||||
import numpy as np
|
||||
|
||||
|
||||
if open.__module__ == '__builtin__':
|
||||
pyopen = open # because we'll redefine open below
|
||||
|
||||
@@ -331,6 +331,8 @@ def readResult(frd_input):
|
||||
elements_found = False
|
||||
|
||||
frd_file.close()
|
||||
if not nodes:
|
||||
FreeCAD.Console.PrintError('FEM: No nodes found in Frd file.\n')
|
||||
return {'Nodes': nodes,
|
||||
'Hexa8Elem': elements_hexa8, 'Penta6Elem': elements_penta6, 'Tetra4Elem': elements_tetra4, 'Tetra10Elem': elements_tetra10,
|
||||
'Penta15Elem': elements_penta15, 'Hexa20Elem': elements_hexa20, 'Tria3Elem': elements_tria3, 'Tria6Elem': elements_tria6,
|
||||
|
||||
@@ -20,11 +20,6 @@
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
|
||||
import FemMeshTools
|
||||
import FreeCAD
|
||||
import os
|
||||
import string
|
||||
|
||||
__title__ = "FreeCAD .inp file reader"
|
||||
__author__ = "Frantisek Loeffelmann "
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
@@ -33,6 +28,12 @@ __date__ = "04/08/2016"
|
||||
## @package importInpMesh
|
||||
# \ingroup FEM
|
||||
|
||||
import FemMeshTools
|
||||
import FreeCAD
|
||||
import os
|
||||
import string
|
||||
|
||||
|
||||
if open.__module__ == '__builtin__':
|
||||
pyopen = open # because we'll redefine open below
|
||||
|
||||
|
||||
@@ -20,12 +20,6 @@
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
|
||||
|
||||
import FreeCAD
|
||||
import os
|
||||
import FemMeshTools
|
||||
|
||||
|
||||
__title__ = "FreeCAD Z88 Mesh reader and writer"
|
||||
__author__ = "Bernd Hahnebach "
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
@@ -33,6 +27,11 @@ __url__ = "http://www.freecadweb.org"
|
||||
## @package importZ88Mesh
|
||||
# \ingroup FEM
|
||||
|
||||
import FreeCAD
|
||||
import os
|
||||
import FemMeshTools
|
||||
|
||||
|
||||
Debug = False
|
||||
|
||||
if open.__module__ == '__builtin__':
|
||||
|
||||
@@ -547,7 +547,7 @@ FemConstraintFixed,3
|
||||
** Element + CalculiX face + load in [MPa]
|
||||
** written by write_constraints_pressure function
|
||||
*DLOAD
|
||||
** face load on shape: Box:Face2
|
||||
** FemConstraintPressure: face load
|
||||
635,P1,1000.0
|
||||
638,P3,1000.0
|
||||
641,P2,1000.0
|
||||
|
||||
@@ -20,12 +20,6 @@
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
|
||||
|
||||
import FreeCAD
|
||||
import os
|
||||
from math import pow, sqrt
|
||||
|
||||
|
||||
__title__ = "FreeCAD Z88 Disp Reader"
|
||||
__author__ = "Bernd Hahnebach "
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
@@ -33,6 +27,11 @@ __url__ = "http://www.freecadweb.org"
|
||||
## @package z88DispReader
|
||||
# \ingroup FEM
|
||||
|
||||
import FreeCAD
|
||||
import os
|
||||
from math import pow, sqrt
|
||||
|
||||
|
||||
Debug = False
|
||||
|
||||
if open.__module__ == '__builtin__':
|
||||
|
||||
Reference in New Issue
Block a user