# freecad 二次开发文档 ## freecad 源代码目录结构 **src/:**此目录包含 FreeCAD 的核心源代码。 **src/App:**包含 FreeCAD 的应用程序对象的实现,如文档、事务管理和撤销/重做系统。 **src/Base:**包含一些基本类和函数,如向量、矩阵和几何实体。 **src/Main:**包含 FreeCAD 的主程序入口点。 **src/Mod:**包含 FreeCAD 的各个模块和工作台的实现,如 Part、Sketcher、FEM 等。 **src/Gui:**包含 FreeCAD 的图形用户界面(GUI)的实现,使用 Qt 框架构建。 **src/Tools:**包含一些实用工具,如编译和构建脚本。 **data/**:此目录包含 FreeCAD 的一些资源文件,如图标、模板、样式表等。 **doc/:**此目录包含 FreeCAD 的开发文档,包括编码规范、开发指南等。 **ext/:**此目录包含 FreeCAD 依赖的外部库,如 Open CASCADE、Eigen 等 ## fem步骤 1. 创建或导入一个几何模型。 2. 转到 FEM 工作台。 3. 创建一个分析对象(Analysis Container)。 4. 定义材料属性。 5. 为模型添加约束,例如固定、力和压力。 6. 创建一个网格,将几何体划分为有限元。 7. 选择求解器,如 CalculiX、Elmer 或 Z88。 8. 运行分析。 9. 查看和分析结果。 ## python 自动创建fem分析脚本 ```python #! /usr/bin/env python3 # -*- coding: utf-8 -*- # vim:fenc=utf-8 # # Copyright © 2023 veypi # # Distributed under terms of the Apache license. """ """ doc = App.newDocument("Scripted_CalculiX_Cantilever3D") import Part box_obj = doc.addObject('Part::Box', 'Box') box_obj.Height = box_obj.Width = 1000 box_obj.Length = 8000 # see how our part looks like import FreeCADGui FreeCADGui.ActiveDocument.activeView().viewAxonometric() FreeCADGui.SendMsgToActiveView("ViewFit") import ObjectsFem # analysis analysis_object = ObjectsFem.makeAnalysis(doc, "Analysis") # solver (we gone use the well tested CcxTools solver object) solver_object = ObjectsFem.makeSolverCalculixCcxTools(doc, "CalculiX") solver_object.GeometricalNonlinearity = 'linear' solver_object.ThermoMechSteadyState = True solver_object.MatrixSolverType = 'default' solver_object.IterationsControlParameterTimeUse = False analysis_object.addObject(solver_object) # material material_object = ObjectsFem.makeMaterialSolid(doc, "SolidMaterial") mat = material_object.Material mat['Name'] = "Steel-Generic" mat['YoungsModulus'] = "210000 MPa" mat['PoissonRatio'] = "0.30" mat['Density'] = "7900 kg/m^3" material_object.Material = mat analysis_object.addObject(material_object) # fixed_constraint fixed_constraint = ObjectsFem.makeConstraintFixed(doc, "FemConstraintFixed") fixed_constraint.References = [(doc.Box, "Face1")] analysis_object.addObject(fixed_constraint) # force_constraint force_constraint = ObjectsFem.makeConstraintForce(doc, "FemConstraintForce") force_constraint.References = [(doc.Box, "Face2")] force_constraint.Force = 9000000.0 force_constraint.Direction = (doc.Box, ["Edge5"]) force_constraint.Reversed = True analysis_object.addObject(force_constraint) ## fem mesh femmesh_obj = ObjectsFem.makeMeshGmsh(doc, box_obj.Name + "_Mesh") femmesh_obj.Part = doc.Box doc.recompute() from femmesh.gmshtools import GmshTools as gt gmsh_mesh = gt(femmesh_obj) error = gmsh_mesh.create_mesh() print(error) analysis_object.addObject(femmesh_obj) doc.recompute() # activating analysis import FemGui FemGui.setActiveAnalysis(doc.Analysis) #from femtools import ccxtools #fea = ccxtools.FemToolsCcx() #fea.purge_results() #fea.run() from femtools import ccxtools fea = ccxtools.FemToolsCcx() fea.update_objects() fea.setup_working_dir() fea.setup_ccx() message = fea.check_prerequisites() if not message: fea.purge_results() fea.write_inp_file() # on error at inp file writing, the inp file path "" was returned (even if the file was written) # if we would write the inp file anyway, we need to again set it manually # fea.inp_file_name = '/tmp/FEMWB/FEMMeshGmsh.inp' fea.ccx_run() fea.load_results() else: FreeCAD.Console.PrintError( "Houston, we have a problem! {}\n".format(message)) # in report view print("Houston, we have a problem! {}\n".format( message)) # in Python console ### # show resutlt for m in analysis_object.Group: if m.isDerivedFrom('Fem::FemResultObject'): result_object = m break femmesh_obj.ViewObject.setNodeDisplacementByVectors( result_object.NodeNumbers, result_object.DisplacementVectors) print(result_object.DisplacementVectors[-1]) import time femmesh_obj.ViewObject.applyDisplacement(20) import requests d = requests.get(url="http://192.168.5.172:8015/file/123") print("|%s|" % (d.text.strip())) # 每秒请求服务器渲染变形程度 n = 0 data = 0 while 1: time.sleep(0.01) d = requests.get(url="http://192.168.5.172:8015/file/123") data = int(d.text.strip()) # 更新ui FreeCAD.Gui.updateGui() #print("%s/%s"%(n, data)) femmesh_obj.ViewObject.applyDisplacement(n) if data > n: n = n + 1 if data < n: n = n - 1 ``` ## 添加有限元fem 求解器 [参考源码](https://github.com/FreeCAD/FreeCAD/compare/a03eb6b9625ba...dfc01ec949525) 步骤: [添加mesh导出程序](https://github.com/FreeCAD/FreeCAD/commit/e100971fa0a0c17b5e4906ac540fa31ac0d11766) [添加求解器,写入程序,任务程序,约束程序](https://github.com/FreeCAD/FreeCAD/commit/cdcd271b4c97a27431dc28d852f6ed7e171dba67) [添加求解器单元测试](https://github.com/FreeCAD/FreeCAD/commit/005c66f4ecc7fb1690a54592a00ec490146b985d) [添加文档](https://github.com/FreeCAD/FreeCAD/commit/cfc08b811ff09628b1468e21e9e823587efc799a) [添加界面参数](https://github.com/FreeCAD/FreeCAD/commit/dfc01ec949525162c70648ea6d6d93c818907f1f)