利用向量知识,编写几行宏,根据给定的坐标文本文件,在FC中绘制出轴线,拐点处根据给定的转弯半径进行倒角(平曲线、竖曲线)。
得到轴线后就用断面进行扫掠即可,如下图:

实践操作——用截面扫掠

用上述代码读取坐标数据绘制好扫掠路径后,选中所有线,再点“创建减料体”(翻译错误,应该是创建子形状绑定),

将这些线变成一个整体。名称为binder
选中起始端点——建立基准点,再用这个端点建立基准面,这个基准面垂直起始线段。
在这个基准面上作草图:扫掠的断面。close
选中草图,点“增料管状体”,任务标签里,sweep path闪动,此时,导航面板切换到“模型”,选中binder作为扫掠路径。
大功告成。——如上图所示。
问题:如何将平面xy坐标和纵面yz坐标进行叠加,生成xyz?
用我开发的工具,选中平面线路,纵面线路和地形线,会相互插值得到一组xyz数据。
https://zsj.itdos.net/docs/hydrows/hydrows-001-001

FreeCAD地下管道建模实战:Python脚本自动化生成3D模型(附完整代码)

原创于 2026-02-26 02:44:29 发布
文章标签:

#FreeCAD

#Python脚本

#三维建模

#管道设计

FreeCAD地下管道建模实战:Python 脚本自动化生成3D模型(附完整代码)
如果你是一位土木或市政工程师,每天面对海量的管道中心线数据和横截面尺寸,还在用传统CAD软件一根一根地手动绘制三维管道模型,那感觉一定像是在用勺子舀干一个游泳池。我经历过那个阶段,直到我发现,将FreeCAD与Python脚本结合,能把几天甚至几周的工作压缩到几分钟内完成。这不仅仅是效率的提升,更是一种工作范式的转变——从重复劳动转向创造性设计。

FreeCAD,这款开源参数化三维建模器,对于专业工程师而言,其价值远不止于“免费”。它的核心魅力在于一个完全开放的Python API,这意味着你可以用代码精确控制建模的每一个环节。想象一下,当你手头有成千上万条管道的GIS数据或测量数据时,一个脚本就能自动读取、解析、生成完整的三维管网模型,并导出为通用的STEP、IFC或OBJ格式,直接用于设计审查、施工模拟或碰撞检测。这不再是幻想,而是可以立即上手的工程实践。

本文将从一个实战角度出发,抛开那些泛泛而谈的界面介绍,直击地下管道自动化建模的核心痛点。我会分享一套经过实际项目验证的Python脚本框架,从数据准备、模型生成、到后处理导出的完整流程。你会发现,无需深厚的计算机图形学背景,利用FreeCAD清晰的几何构建逻辑,就能构建出强大、可靠的自动化工具链。

  1. 工程痛点分析与FreeCAD的破局之道
    在市政、给排水、石油化工等领域,地下管网系统极其复杂。传统的三维建模流程存在几个显著的效率瓶颈:

数据与模型脱节:设计数据(如管径、标高、坐标)通常存储在Excel、数据库或GIS系统中,而建模却在另一套CAD软件里手动进行,极易出错且难以同步更新。
批量处理能力弱:对于规则排列的管道,如厂区管网,手动复制、修改每一段的参数枯燥且低效。
变更管理困难:设计方案调整时,牵一发而动全身,手动修改关联模型的工作量巨大。
模型信息割裂:生成的三维模型往往只是一个“壳”,缺乏管道材质、流速、承压等级等工程属性,无法支撑更深层次的数字化应用。
FreeCAD的参数化与脚本化特性,正是为解决这些问题而生。参数化意味着模型的尺寸、位置由可修改的参数驱动;脚本化则意味着你可以用程序批量定义和修改这些参数。

注意:FreeCAD 1.0版本在稳定性和核心功能上已趋于成熟,特别是其Python API接口非常稳定,这为开发生产级自动化工具提供了可靠基础。

与一些昂贵的专业BIM软件相比,FreeCAD的自动化方案门槛更低,灵活性更高。你不需要购买额外的“二次开发模块”或学习专用的脚本语言,标准的Python知识加上对FreeCAD几何内核(OpenCASCADE)的基本理解,就足以开启自动化之旅。

下面的表格对比了传统手动建模与FreeCAD脚本自动化在典型管道建模任务中的差异:

任务环节 传统手动建模方式 FreeCAD Python脚本自动化方式
数据输入 人工对照表格,在GUI中逐个输入坐标、管径。 脚本自动读取CSV、JSON或数据库,将数据转化为Python数据结构。
模型生成 使用拉伸、扫描等命令逐个创建管道实体。 循环遍历数据,调用Part.makeCylinder或Part.makePipe等函数批量生成。
连接处理 手动添加法兰、三通、弯头等部件,并做布尔运算。 根据拓扑关系(连接点编号)自动判断节点类型,调用相应部件库函数生成。
属性附加 在图层或单独的属性表中手动填写。 在创建对象时,直接将工程属性(如Material, FlowRate)写入对象的动态属性中。
设计变更 找到所有相关模型,逐一修改尺寸和位置。 修改源头数据文件,重新运行脚本,模型自动更新。
格式导出 通过菜单手动导出为所需格式。 脚本末尾调用export方法,一键导出多种格式(STEP, IFC, OBJ)。
这种对比清晰地揭示了自动化带来的范式变革:工程师的工作重心从“操作软件”转移到了“设计流程和规则”。

  1. 环境搭建与核心Python API初探
    开始之前,你需要安装FreeCAD。建议直接从其官网下载最新的稳定版(1.0或更高版本)。安装完成后,我们最关心的不是它的图形界面 ,而是其内置的Python解释器和模块。

FreeCAD启动后,其实同时启动了一个功能完整的Python环境。你可以通过其宏编辑器(Macro -> Macros… -> Create)来编写和测试代码,但对于复杂的项目,我更推荐使用外部IDE(如VS Code、PyCharm)连接到FreeCAD的Python库进行开发。不过,对于快速学习和原型验证,宏编辑器足够了。

FreeCAD的Python API主要围绕几个核心模块展开:

FreeCAD: 提供基础功能,如文档管理、向量(Vector)运算。
Part: 这是几何建模的核心,所有创建和修改几何体(点、线、面、体)的功能都在这里。
App: 负责应用程序级别的对象和文档管理。
Draft, Arch, FEM等:针对特定工作台(如绘图、建筑、有限元分析)的模块。
让我们从一个最简单的例子开始,理解FreeCAD如何用代码“思考”。假设我们要创建一段水平的圆形管道,已知起点坐标(0,0,0),终点坐标(5000,0,0),管道外径为300毫米。

示例1:创建单段直管道

import FreeCAD
import Part
from FreeCAD import Vector

获取或创建活动文档

doc = App.ActiveDocument
if doc is None:
doc = App.newDocument(“Pipeline”)

定义管道参数

start_point = Vector(0, 0, 0)
end_point = Vector(5000, 0, 0) # 5米长的管道
radius = 150.0 # 半径150mm,即DN300管

方法1:使用扫掠(Sweep)方式。先创建路径(直线),再创建剖面(圆),然后扫掠。

创建路径直线

line = Part.makeLine(start_point, end_point)

创建剖面圆。圆的中心在起点,法线方向为路径方向(这里沿X轴)

我们需要一个垂直于路径的平面来放置圆。这里简单处理,假设路径水平。

circle = Part.makeCircle(radius, start_point, Vector(1,0,0))
wire_circle = Part.Wire(circle)

创建扫掠体(管道实体)

pipe_solid = wire_circle.makePipeShell([line], True, False, 2) # 最后一个参数是过渡类型

将实体添加到文档中

pipe_obj = doc.addObject(“Part::Feature”, “SinglePipe”)
pipe_obj.Shape = pipe_solid

更新视图

doc.recompute()
App.Console.PrintMessage(“单段管道创建完成!\n”)
AI写代码
python
运行

运行这段代码,你会在三维视图中看到一段圆柱体。然而,对于管道建模,Part模块提供了一个更直接的方法——makePipe。但需要注意的是,makePipe通常用于沿一条空间曲线(脊线)扫掠一个或多个剖面来创建复杂管道,对于简单的直管,用makeCylinder反而更直观高效。

示例2:使用makeCylinder创建直管(更高效)

import FreeCAD
import Part
from FreeCAD import Vector

doc = App.ActiveDocument
if doc is None:
doc = App.newDocument(“Pipeline”)

start = Vector(0,0,0)
end = Vector(5000,0,0)
radius = 150.0

计算管道的长度和方向向量

direction = end.sub(start)
length = direction.Length
direction.normalize() # 单位化方向向量

Part.makeCylinder(半径, 高度, 底面中心点, 方向向量)

pipe_solid = Part.makeCylinder(radius, length, start, direction)

pipe_obj = doc.addObject(“Part::Feature”, “CylinderPipe”)
pipe_obj.Shape = pipe_solid

doc.recompute()
AI写代码
python
运行

这两种方法都可行,但makeCylinder在计算上更轻量。关键在于理解:在FreeCAD中,三维模型本质上是Part.TopoShape对象,而Python脚本就是通过组合各种基础几何形状(Part.make…系列函数)来构建复杂的TopoShape。

  1. 从数据到模型:批量生成管道网络
    实战中,我们面对的是管道网络。数据通常以表格形式存在,每一行代表一段管道,包含起始点(X1,Y1,Z1)、终点(X2,Y2,Z2)、管径(D)等字段。我们的目标是将这个表格自动转化为三维模型。

假设我们有一个pipes.csv文件,内容如下:

ID,StartX,StartY,StartZ,EndX,EndY,EndZ,Diameter, Material
P001,0,0,-2,10,0,-2,300, HDPE
P002,10,0,-2,10,8,-2,250, PVC
P003,10,8,-2,2,8,-2.5,300, HDPE
AI写代码
csv
下面是一个完整的脚本,演示如何读取CSV文件并批量生成管道模型,同时为每根管道附加自定义属性。

示例3:批量从CSV生成管道网络

import FreeCAD
import Part
import csv
from FreeCAD import Vector

def create_pipe_from_row(row):
“””根据一行数据字典创建管道实体”””
try:
start = Vector(float(row[‘StartX’]), float(row[‘StartY’]), float(row[‘StartZ’]))
end = Vector(float(row[‘EndX’]), float(row[‘EndY’]), float(row[‘EndZ’]))
radius = float(row[‘Diameter’]) / 2.0 / 1000.0 # 假设CSV中单位为mm,转换为米(FreeCAD默认单位)
except KeyError as e:
App.Console.PrintError(f”CSV行中缺少必要列: {e}\n”)
return None

direction = end.sub(start)
length = direction.Length
if length < 1e-7:  # 忽略长度极短的段
    return None
direction.normalize()

# 创建圆柱体作为管道
pipe_solid = Part.makeCylinder(radius, length, start, direction)
return pipe_solid

主程序

doc = App.ActiveDocument
if doc is None:
doc = App.newDocument(“PipelineNetwork”)

csv_file_path = “/path/to/your/pipes.csv” # 请替换为实际路径

with open(csv_file_path, mode=’r’, encoding=’utf-8-sig’) as file:
reader = csv.DictReader(file)
for i, row in enumerate(reader):
pipe_shape = create_pipe_from_row(row)
if pipe_shape:

        # 创建文档对象
        obj_name = f"Pipe_{row.get('ID', f'{i:03d}')}"
        pipe_obj = doc.addObject("Part::Feature", obj_name)
        pipe_obj.Shape = pipe_shape

        # 为对象添加自定义工程属性(扩展数据)
        pipe_obj.addProperty("App::PropertyString", "Material", "Engineering")
        pipe_obj.addProperty("App::PropertyLength", "Diameter", "Engineering")
        pipe_obj.addProperty("App::PropertyString", "SourceID", "Engineering")

        # 赋值
        pipe_obj.Material = row.get('Material', 'Unknown')
        # 注意:FreeCAD属性赋值时,长度单位会自动处理。这里我们输入毫米值。
        pipe_obj.Diameter = f"{float(row['Diameter'])} mm"
        pipe_obj.SourceID = row.get('ID', '')

        App.Console.PrintMessage(f"已创建管道: {obj_name}\n")

一次性重算文档,比每创建一个就recompute一次效率高得多。

doc.recompute()
App.Console.PrintMessage(“管道网络批量生成完毕!\n”)
AI写代码
python
运行

这个脚本实现了自动化建模的核心循环。但它生成的管道是彼此独立的圆柱体,在交叉点会互相穿透。在实际工程中,我们需要处理管道之间的连接,比如添加三通、弯头,或者进行布尔运算实现切割。

  1. 高级技巧:处理连接与生成复杂节点
    一个真实的管网中,管道在检查井、阀门井或直接相交处需要连接。完全自动化的连接处理涉及复杂的几何推理,但我们可以针对常见情况实现半自动化或规则驱动的生成。

思路:首先识别网络中的节点(管道的起点和终点),统计连接到每个节点的管道数量(度数)。根据度数决定节点类型:

度数为1:末端,可能需要添加端帽。
度数为2:直通或弯头。通过计算两根管道的方向向量夹角,判断是直通(夹角接近180度)还是需要弯头(如90度)。
度数为3或以上:三通、四通等。
我们可以预先用FreeCAD建好标准管件(法兰、弯头、三通)的模型,并保存为.FCStd文件。在脚本中,根据节点类型,读取相应的标准件文件,然后通过坐标变换(平移和旋转)将其精准放置到节点位置。

下面演示如何为两个相交的管道在交点处插入一个标准三通:

示例4:在管道交点插入标准三通(概念性代码)

import FreeCAD
import Part
import Mesh
from FreeCAD import Vector, Rotation, Placement

def insert_tee_at_junction(pipe_a, pipe_b, pipe_c, junction_point):
“””
假设在 junction_point 处,pipe_a, pipe_b, pipe_c 三根管道相连。
此函数加载一个标准三通模型,并对其进行平移旋转,使其与现有管道对齐。
这是一个简化示例,实际对齐计算需要根据三通分支的方向和管径进行。
“””
doc = App.ActiveDocument

# 1. 加载预先做好的三通标准件
# 假设文件路径,且文件中有一个名为“Tee”的Part对象
std_tee_path = "/path/to/standard_parts/tee_DN300.FCStd"
try:
    # 导入文档会将其作为子文档打开,我们需要合并对象
    imported_doc = App.openDocument(std_tee_path)
    # 这里需要遍历导入文档中的对象,找到我们需要的,复制到当前文档。
    # 为简化,我们假设直接在当前文档创建了一个简单三通形状。
    App.Console.PrintWarning("标准件加载逻辑需根据实际文件结构实现。此处使用替代几何体。\n")
    # 创建一个简单的替代三通(三个垂直相交的圆柱)
    main_cylinder = Part.makeCylinder(150, 500, Vector(-250,0,0), Vector(1,0,0))
    branch_cylinder = Part.makeCylinder(150, 300, Vector(0,-150,0), Vector(0,1,0))
    tee_shape = main_cylinder.fuse(branch_cylinder)
except:
    App.Console.PrintError(f"无法加载标准件文件: {std_tee_path}\n")
    return

# 2. 计算三通需要放置的位置和方向(这是核心难点)
# 简化:假设三通的主轴与pipe_a方向对齐,支管与pipe_b方向对齐。
dir_a = (pipe_a.EndPoint - pipe_a.StartPoint).normalize()
dir_b = (pipe_b.EndPoint - pipe_b.StartPoint).normalize()

# 计算旋转:将世界坐标系的三通(假设其主轴沿X轴,支管沿Y轴)旋转到目标方向。
# 这需要构造一个旋转矩阵(Rotation)
# 此处省略复杂的旋转矩阵计算...
rotation = Rotation(Vector(1,0,0), dir_a) # 一个简化的旋转

# 3. 创建放置(Placement):组合平移和旋转
placement = Placement(junction_point, rotation)

# 4. 对三通形状应用变换
tee_shape.Placement = placement
# 或者使用变换方法:tee_shape.transformGeometry(placement.toMatrix())

# 5. 将变换后的三通添加到文档
tee_obj = doc.addObject("Part::Feature", "Tee_Fitting")
tee_obj.Shape = tee_shape

# 6. (可选)对原始管道进行布尔切割,使其与三通内壁匹配,实现无缝连接。
# pipe_a_cut = pipe_a.Shape.cut(tee_shape)
# ... 操作后替换原管道形状

doc.recompute()
App.Console.PrintMessage("三通插入完成(示意)。\n")

使用示例(需要先有pipe_a, pipe_b, pipe_c对象):

insert_tee_at_junction(pipe_a_obj, pipe_b_obj, pipe_c_obj, Vector(10,0,-2))

AI写代码
python
运行

提示:实际的管件对齐算法非常复杂,需要考虑管径匹配、分支角度、端部处理(平口、承插口)等。对于生产环境,建议采用分步半自动化策略:脚本先生成所有直管段,并标记出所有连接点;然后工程师在FreeCAD GUI中,利用其强大的捕捉和对齐工具,快速从标准件库中拖放装配管件。这样平衡了自动化效率和建模精度。

  1. 模型导出、优化与工作流 集成
    模型生成后,下一步是导出用于其他用途。FreeCAD支持导出数十种格式,对于工程协作,STEP (AP214) 和 IFC 是最通用的。

示例5:将整个文档或选定对象导出为STEP和OBJ格式

import FreeCAD
import ImportGui

doc = App.ActiveDocument
if not doc:
App.Console.PrintError(“没有活动文档!\n”)
else:

# 导出整个文档
step_file = "/path/to/export/pipeline_network.step"
obj_file = "/path/to/export/pipeline_network.obj"

try:
    # 导出为STEP
    ImportGui.export(doc.Objects, step_file) # 新版本API
    # 旧版本可能是:doc.exportObjects(doc.Objects, step_file)
    App.Console.PrintMessage(f"模型已导出为STEP: {step_file}\n")

    # 导出为OBJ (用于可视化、3D打印)
    # 注意:OBJ导出通常需要先网格化(Meshing)
    import Mesh
    mesh_objects = []
    for obj in doc.Objects:
        if hasattr(obj, 'Shape'):
            mesh = Mesh.Mesh(obj.Shape.tessellate(0.1)) # 0.1是细化参数
            mesh_objects.append(mesh)
    combined_mesh = Mesh.Mesh()
    for mesh in mesh_objects:
        combined_mesh.addMesh(mesh)
    combined_mesh.write(obj_file)
    App.Console.PrintMessage(f"模型已导出为OBJ: {obj_file}\n")

except Exception as e:
    App.Console.PrintError(f"导出过程中发生错误: {e}\n")

AI写代码
python
运行

模型优化:当管道数量极大时,生成的FreeCAD文档可能会变得笨重。为了提高性能,可以考虑:

使用复合形状(Compound):将数百根相同规格的管道合并为一个Part.Compound对象,能显著减少文档树中的对象数量,提升视图操作速度。
import Part
shapes = []
for pipe_obj in pipe_object_list:
shapes.append(pipe_obj.Shape)
compound = Part.Compound(shapes)
comp_obj = doc.addObject(“Part::Feature”, “Pipes_Compound”)
comp_obj.Shape = compound
AI写代码
python
运行
分图层(Group)管理:将不同类型的管道(如给水、排水、燃气)放入不同的App.DocumentObjectGroup中,便于显示/隐藏和选择。
细节层次(LOD):在脚本中,可以根据视图缩放级别生成不同精度的模型(例如,远距离显示时用简单圆柱,近距离显示时添加法兰盘细节)。
工作流集成:最理想的状态是将此Python脚本集成到你的现有工程数据平台中。例如,可以创建一个简单的Web界面或桌面工具,工程师上传包含管道数据的Excel文件,后台调用FreeCAD的命令行 模式执行脚本,生成模型并返回下载链接。

FreeCAD支持无头模式(headless mode),即不启动图形界面,直接在命令行运行Python脚本。这在服务器端自动化处理中非常有用。

示例:在Linux/macOS命令行无头运行FreeCAD脚本

/path/to/FreeCAD –console –run-python-script /path/to/your/pipeline_script.py

在Windows上类似

FreeCADCmd.exe -c “exec(open(r’C:\path\to\your\pipeline_script.py’).read())”
AI写代码
bash
通过这种方式,你可以将FreeCAD的自动化建模能力嵌入到CI/CD流水线或数据发布流程中,实现从原始勘测数据到发布就绪的三维模型的全自动转换。
————————————————
版权声明:本文为CSDN博主「pluto」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/pluto/article/details/153804751

作者:秦晓川  创建时间:2023-08-12 21:30
最后编辑:秦晓川  更新时间:2026-03-03 15:41