ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

FreeCAD Draft 工作台 Tracker 机制深度解析:基于 Coin3D 的临时预览对象体系

FreeCAD Draft 工作台 Tracker 机制深度解析:基于 Coin3D 的临时预览对象体系 FreeCAD Draft 工作台 Tracker 机制深度解析基于 Coin3D 的临时预览对象体系【免费下载链接】FreeCADOfficial source code of FreeCAD, a free and opensource multiplatform 3D parametric modeler.项目地址: https://gitcode.com/GitHub_Trending/fr/FreeCAD导读本文围绕 DraftTrackers.rst 文档所描述的 Draft Trackers 概念展开完整剖析 FreeCAD Draft/Arch 工作台在 3D 视图中绘制临时几何预览虚线框、吸附标记、弧线、幽灵对象、网格等的底层实现。读者将掌握 Tracker 的通用生命周期 APIon/off/finalize/置顶置底、17 个具体 Tracker 类的职责与构造参数以及它们如何与 DraftWorkingPlane、Coin3Dpivy场景图协作从而能理解甚至自行编写 Draft 工具的交互预览逻辑。一、什么是 Draft Tracker临时屏幕小部件的职责边界DraftTrackers.rst对 Trackers 给出了精确定义Different trackers (temporary screen widgets) used in the Draft and Arch modules——即 Draft 与 Arch 模块中使用的一族临时屏幕小部件widget。这份 RST 文件本身是 FreeCAD 文档系统Sphinx automodule的入口它会将DraftTrackers模块的全部公开成员自动展开为 API 文档页。在当前的 FreeCAD 源码仓库中这个被文档化的模块实体位于 src/Mod/Draft/draftguitools/gui_trackers.py模块头部 docstring 明确写道Provides Coin based objects used by the Draft Workbench to draw temporary geometry, that is, previews, of the real objects that will be created on the 3D view.即Tracker 是建立在 Coinpivy基础上的对象用于在 3D 视图中绘制临时几何preview这些几何是即将被真正创建的对象的预览形态。这与 Draft 工作台的交互模式一一对应鼠标移动过程中你看到的虚线矩形、虚线圈、吸附方块、幽灵拷贝都不是真实文档对象而是由 Tracker 直接注入 Open Inventor 场景图scenegraph的临时节点命令结束时它们会被移除正式对象则由 Draft 的 make 函数创建。在代码组织上该模块通过 src/Mod/Draft/DraftTools.py#L60 的import draftguitools.gui_trackers as trackers被 Draft 的图形工具draftguitools包统一引用并被 src/Mod/Draft/drafttests/test_import_gui.py#L62-L64 的导入测试覆盖确保模块在 GUI 环境中可正常加载。二、基类 Tracker所有预览对象的通用骨架所有 Tracker 均继承自模块最底层的Tracker基类gui_trackers.py#L63-L184它定义了一个可挂在 3D 场景图中的可开关节点这一通用模型。2.1 构造函数参数def __init__(self, dottedFalse, scolorNone, swidthNone, children[], ontopFalse, nameNone):各参数含义与默认行为参数默认值作用dottedFalse是否以虚线LINES 风格绘制。为真时强制lineWeight 3、linePattern 0x0F0FscolorNone线条颜色RGB 三元组。为None时回落到参数系统默认色swidthNone线宽直接写入SoDrawStyle.lineWidthchildren[]由调用方预先构建的 Coin 节点列表会依次加入SoSeparatorontopFalse为真时节点插入场景图索引 0最顶层不被遮挡nameNone设置SoSwitch的节点名便于调试与场景图检索基类内部组装了SoBaseColorSoDrawStyle 子节点列表统一放入一个SoSwitch即开关。开关通过whichChild控制可见性0显示、-1隐藏。2.2 生命周期 APIon / off / finalize这是所有 Tracker 最核心的调用契约也是命令类如gui_arcs.py、gui_base.py中反复出现的固定流程on()/off()切换SoSwitch.whichChild0 / -1并同步维护self.Visible标志gui_trackers.py#L132-L140finalize()命令结束时调用通过ToDo.delay延迟到非场景图遍历期间移除SoSwitch节点避免在事件处理器中直接修改场景图导致崩溃gui_trackers.py#L91-L96_insertSwitch/_removeSwitch真正操作场景图的方法二者都要求不得在场景图遍历期间调用这是使用ToDo.delay的原因gui_trackers.py#L106-L130lowerTracker()/raiseTracker()把开关节点移到场景图底部不遮挡其他对象或顶部遮挡其他对象gui_trackers.py#L142-L164get_scene_graph()通过gui_utils.get_3d_view()获取当前 3D 视图的场景图非 3D 视图时返回None。2.3 默认配色逻辑setColor()gui_trackers.py#L166-L180体现了 Tracker 与 Draft 参数系统的联动显式传入color时直接使用否则若当前处于 Draft 的Dimension/Label/Text命令中使用参数DefaultAnnoLineColor其余情况使用视图参数DefaultShapeLineColor默认值见 params.py#L699类型unsigned默认421075455。_get_wp()返回FreeCAD.DraftWorkingPlane这是各 Tracker 将屏幕坐标换算到工作平面局部坐标的公共入口。三、按功能族逐一解析 17 个具体 Tracker模块共定义 17 个具体 Tracker不含基类可按下述功能族理解。以下行号均指向 src/Mod/Draft/draftguitools/gui_trackers.py。3.1 点与标记snapTracker、editTrackersnapTracker#L186-L227——支持吸附的工具使用的吸附点标记使用SoMarkerSet点标记符号默认索引为FreeCADGui.getMarkerIndex(CIRCLE_FILLED, params.get_param_view(MarkerSize))即圆形实心点尺寸跟随视图参数MarkerSize默认 9见 params.py#L708setMarker(style)可切换符号样式setCoords(point)设置单个坐标addCoords(point)追加坐标供多吸附点场景用clear()清空颜色取自 Draft 参数snapcolorgui_trackers.py#L208-L213而非基类的默认形状色节点外层包了SoAnnotation保证标记始终面向相机、不被透视变形。editTracker#L973-L1046——Draft 编辑模式下的节点编辑手柄默认使用SQUARE_FILLED方块标记构造参数pos、name、idx、objcol、marker、inactive分别控制初始位置、所属对象名、节点索引、颜色、标记样式与是否可交互关键点当inactiveFalse时使用SoFCSelection节点并把subElementName设为EditNode str(idx)从而让编辑节点参与拾取/选择inactiveTrue时退化为纯展示的SoSeparator提供set/get/move、get_doc_name、get_obj_name、get_subelement_name、get_subelement_index从EditNodeN解析索引等接口实际使用见 gui_edit.py#L607 与 #L639Draft 编辑Edit命令逐节点创建editTracker并传入对象名与节点序号。3.2 直线与折线lineTracker、wireTracker、polygonTrackerlineTracker#L230-L260——两点临时直线SoLineSet固定 2 顶点p1(point)/p2(point)同时承担 getter/setter设置时会做值比较避免无谓的场景图写入getLength()返回两点欧氏距离。在 gui_arcs.py#L91-L92 中弧命令先创建trackers.lineTracker(dottedTrue)绘制临时弦线再叠加arcTracker。wireTracker#L1108-L1142——由Part.Wire驱动的多段线预览构造时接收一个线框对象通过geo_wires.isReallyClosed(wire)判断闭合性闭合时顶点数 1首点重复以闭合环update(wire, forceclosedFalse)与updateFromPointlist(points, forceclosedFalse)支持从线框或点列表两种数据源刷新。polygonTracker#L263-L322——正多边形工具Draft Polygon的实时预览构造参数sides指定边数默认 3faceTrue时额外添加 50% 透明度的SoIndexedFaceSet半透明填充面setOrigin(point, radius1.0)初始化外接圆圆心update(point)根据鼠标点计算外接圆半径通过工作平面局部坐标math.hypot求半径_drawPolygon的关键在于坐标空间换算先把原点get_local_coords到工作平面局部系按2πi/sides逐顶点计算再get_global_coords回到全局系最后重复首点闭合多边形。3.3 矩形rectangleTrackerrectangleTracker#L325-L431——Draft Rectangle 的预览SoLineSet固定 5 顶点闭合矩形同样支持faceTrue半透明填充记录工作平面基向量u、vwp.u、wp.vsetPlane(u, vNone)可重设v缺省时由法向叉乘u推导setorigin(point)设基角点update(point)通过DraftVecUtils.project把对角点分别投影到u、v轴得到矩形四顶点提供p1()/p2()/p3()/p4()基角点、u 轴端点、对角点、v 轴端点、getSize()返回长宽、getNormal()u×v归一化与isInside(point)投影法点内判断后者可用于拾取点是否落在预览矩形内的交互判定。3.4 尺寸标注dimTracker、archDimTrackerdimTracker#L434-L495——Draft Dimension 的临时尺寸线SoLineSet固定 4 顶点update(pts)接收 13 个点起点、终点、可选定位点calc()负责计算四条折线顶点关键几何运算当存在第三点时用Part.LineSegment(p1, p4).toShape()构造基准线调用geo_geometry.findDistance求第三点到基线的垂足与偏移从而让尺寸线偏移出被测对象。archDimTracker#L1653-L1759——Arch 尺寸标注的 Tracker它是SketcherSoDatumLabel节点的封装模块文档称其用于 Draft 与 Arch 两个模块这是 Arch 侧的典型实例mode支持四种显示模式setMode0无引线纯标记、1对齐默认、2水平、3垂直setString()自动计算Distance水平/垂直模式分别取 Δx、Δy 绝对值对齐模式取长度用FreeCAD.Units.Quantity(...).UserString生成带单位文本并依据相机视野比例自动把文本放在尺寸线内侧或外侧防止尺寸标注与光标附近曲线相交p1()/p2()会把输入点投影到当前工作平面plane.project_point再写入SoDatumLabel的pnts颜色与文字大小分别联动snapcolor与MarkerSize。3.5 曲线族bsplineTracker、bezcurveTracker、arcTracker这三个 Tracker 代表了先用 OCCT 建模、再转 Inventor 字符串渲染的实现路径是理解 Draft 曲线预览原理的范本。bsplineTracker#L498-L570recompute()中用Part.BSplineCurve()c.interpolate(...)对控制点做 B 样条插值当首尾点距离小于容差utils.tolerance()且点数 ≥3 时以闭合模式插值生成的Part.Shape通过c.writeInventor(2, 0.01)序列化为 Open Inventor 文本再用coin.SoInput().setBuffer(buf)coin.SoDB.readAll反序列化为 Coin 节点代码内附有 pivySoInput.setBuffer()的已知 bug 规避若反序列化抛异常则正则提取point [...]块手工重建SoCoordinate3SoLineSetgui_trackers.py#L540-L560。此模式在 bezcurveTracker 与 arcTracker 中重复出现。bezcurveTracker#L573-L652支持分段贝塞尔update(points, degree)传入次数后将控制点按degree切片为多段逐段用Part.BezierCurve()构造并写 Inventor段间以startpoint segpoles[-1]续接维护self.bezcurve段列表recompute()时先清空旧段再重建。arcTracker#L655-L782——用于 Arc 命令与角度尺寸标注几何基础是单位圆Part.makeCircle(1, Vector(0,0,0), normal, startangle, endangle)通过SoTransform的translation圆心与scaleFactor半径做仿射变换因此只存单位圆、变换随参数走性能好setCenter/setRadius/getRadius/setStartAngle/setEndAngle/setApertureAngle开口角均为常用接口setBy3Points(p1, p2, p3)用Part.ArcOfCircle三点定弧并注意把法向取反源码注释axis is always in wrong direction同时关闭autoinvertgetAngle(pt)基于偏差向量getDeviation()求角度用于把鼠标点换算为起始/终止角recompute()中处理了endangle startangle时的方向反转自动反转开关autoinvert。使用实例见 gui_arcs.py#L534 与setBy3Points的调用注释 #L626。3.6 对象级预览ghostTracker、boxTracker、radiusTrackerghostTracker#L785-L970——幽灵对象用于整体复制已有对象的显示表示是 Draft Move/Rotate/Scale 等变换命令的核心预览构造参数sel可传入单个对象、对象列表或Part.Shape对普通对象调用getNodeFull深拷贝obj.ViewObject.RootNode.copy()并写入全局放置变换对Part.Shape调用getNodeLight直接shape.writeInventor()取线框节点对Part.Vertex则画方块标记提供完整的刚体变换接口move(delta)相对平移、rotate(axis, angle)、scale(delta)、center(point)变换中心、setMatrix/getMatrix与SoGetMatrixAction联动支持法向翻转镜像flip_normals(True/False)通过SoSearchAction找到SoIndexedFaceSet并交换每个四边形索引的前两个顶点实现remove()在子元素选择模式切换时调用finalize()清理。boxTracker#L1545-L1623——基于SoCube的立方体预览如旋转命令的临时包围盒可基于一条线对象构造line参数update()自动取线的长度作为立方体长轴并把法向作为高度方向通过FreeCAD.Rotation(lvec, Vector(), normal, XZY)对齐姿态width()/length()/height()三接口均可读写对应尺寸shadedTrue时用半透明材质透明度 0.8否则纯线框。radiusTracker#L1626-L1650——透明绿色球体用于可视化半径如倒角/圆角半径材质透明度 0.9、diffuseColor [0, 1, 0]update(arg1, arg2None)兼容半径与位置两种入参两个参数可分别指定位置与半径。3.7 工作平面与网格PlaneTracker、gridTrackerPlaneTracker#L1049-L1105——Draft Select Plane / 旋转工作平面时的半透明平面盘半透明方形面透明度 0.8[0.4, 0.4, 0.6] 高亮轴线箭头 小刻度线尺寸与吸附范围相关用get_3d_view().getPoint((100,100))与(110,100)估算屏幕 10 像素对应的世界长度bl再乘snapRange / 2.0snapRange默认 8见 params.py#L538SoPickStyle.UNPICKABLE保证该预览不可被拾取set(posNone)读取DraftWorkingPlane的放置四元数 基点同步到SoTransform。在 gui_base.py#L174 中Draft 命令基类创建trackers.PlaneTracker()以显示当前工作平面。gridTracker#L1145-L1542——Draft Grid网格的实现是模块中最复杂的 Tracker绘制小方格线、主网格线、坐标轴、网格边界文字与人形示意图human figure颜色与透明度全部来自 Draft 参数gridColor、gridTransparency百分比、coloredGridAxes彩色坐标轴从BaseApp/Preferences/View读AxisXColor/AxisYColor/AxisZColor默认值分别为0xCC333300、0x33CC3300、0x3333CC00参数键列表见 params.py#L52-L59尺寸参数通过get_grid_param读取gridSpacing映射偏好GridSpacing、gridEveryGridMainlines主网格线间隔、gridSizeGridSize总行数映射关系见 params.py#L808-L810reset()中若间距解析失败则回退为 1update()会裁剪网格为偶数条主线的对称范围按mainlines区分小格/主线gridBorderTrue时额外绘制边界、角标文字SoAsciiTextSoFont字体取textfont参数与边角光标短线displayHumanFigure(wp)仅在gridBorder与gridShowHuman均为真、且工作平面法向近似竖直与 Z 轴夹角 0.001 弧度时在网格角绘制基于HumanFigure.brepBIM 工作台采样的人形剪影约 80 个顶点getClosestNode(point)把点投影到工作平面局部系后按space取整返回最近网格节点——这是吸附到网格的实现基础on()/off()重写父类额外调用grid_observer._update_grid_gui()同步工具栏网格按钮的选中态。四、Tracker 与参数系统的联动关系Tracker 的视觉表现高度参数化均通过 src/Mod/Draft/draftutils/params.py 读取偏好。下表汇总了源码中确认的关联参数默认值以当前仓库为准参数默认值消费方作用View/MarkerSize9snapTracker、editTracker、ghostTracker、archDimTracker点标记/文字尺寸Mod/Draft/snapcolor偏好色snapTracker、ghostTracker、editTracker、archDimTracker吸附相关标记颜色View/DefaultShapeLineColor421075455Tracker 基类常规预览线条颜色View/DefaultAnnoLineColor偏好色Tracker 基类标注类命令预览颜色Mod/Draft/snapRange8PlaneTracker工作平面预览盘尺寸Mod/Draft/gridSpacing偏好GridSpacinggridTracker网格间距Mod/Draft/gridEvery偏好GridMainlinesgridTracker主线间隔Mod/Draft/gridSize偏好GridSizegridTracker网格总尺寸Mod/Draft/gridColor/gridTransparency偏好gridTracker网格颜色与透明度Mod/Draft/coloredGridAxes偏好gridTracker是否按 XYZ 三色绘制坐标轴Mod/Draft/gridBorder/gridShowHuman偏好gridTracker是否绘制边界文字与人形剪影Mod/Draft/textfont偏好gridTracker网格标注字体当用户修改偏好时params.py#L78-L92 的参数观察者会触发回调如snapcolor变更回调_param_observer_callback_snapcolor保证已存在的 Tracker 在下一次重绘时采用新值。五、Tracker 的典型使用流程与命令集成综合 gui_arcs.py、gui_beziers.py、gui_dimensions.py第 L104-L105 行创建dimTracker与arcTracker等命令类一个完整 Tracker 生命周期可归纳为创建命令激活时构造具体 Tracker构造器内部通过ToDo.delay把开关节点异步插入场景图激活调用on()显示预览刷新鼠标/键盘事件中反复调用p1()/p2()/update()/setCoords()等接口更新坐标节点SoCoordinate3/SoTransform的字段写入会触发 Coin 自动重绘停用命令结束或切换状态时调用off()隐藏或直接finalize()从场景图移除节点清理finalize()通过ToDo.delay延迟移除规避场景图遍历期间改图的崩溃风险。以arcTracker为例gui_arcs.py#L534 将self.tracker trackers.arcTracker()作为弧命令的实例属性在鼠标事件中通过setCenter/setRadius/setStartPoint/setEndPoint或setBy3Points持续刷新预览。这一模式与 Draft 命令框架gui_base.py中的命令基类持有planetrack等保持一致。对于想要自行编写 Tracker 的开发者可参照下述接口组合伪代码示意接口签名与上文一致import pivy.coin as coin from draftguitools import gui_trackers as trackers # 创建一个虚线、置于顶层的三点弧预览 arc trackers.arcTracker(dottedTrue, scolor(1.0, 0.6, 0.0), swidth2, ontopTrue) arc.setCenter(FreeCAD.Vector(0, 0, 0)) arc.setRadius(10) arc.setStartPoint(p1) # 由点反推起始角 arc.setEndPoint(p3) # 由点反推终止角 arc.on() # 显示 # ... 交互过程中持续更新 ... arc.off() # 隐藏 arc.finalize() # 从场景图移除六、与其他模块的协作关系Tracker 虽定义在 Draft 工作台内但其渲染基础是全局的Coin3Dpivy场景图所有 Tracker 直接操作pivy.coin节点SoSwitch、SoCoordinate3、SoLineSet、SoMarkerSet、SoTransform、SoAnnotation、SoFCSelection等由 FreeCAD 3D 视图的 SoRenderManager 统一渲染DraftWorkingPlanePlaneTracker、gridTracker、polygonTracker、rectangleTracker、archDimTracker均通过FreeCAD.DraftWorkingPlane做全局坐标 ↔ 平面局部坐标换算保证预览贴合当前绘图平面OCCTPart 模块bspline/bezier/arc 三个 Tracker 用Part.BSplineCurve、Part.BezierCurve、Part.makeCircle、Part.ArcOfCircle构建精确曲线再经writeInventor桥接至 CoinDraft 参数系统见上文第四节偏好变更通过观察者机制实时影响 Tracker 外观Draft 网格观察者grid_observer使 gridTracker 的开关状态与工具栏按钮联动。从源码结构看Arch 工作台的尺寸标注复用archDimTracker定义于本模块内印证了DraftTrackers.rst中used in the Draft and Arch modules的描述ghostTracker的getNodeFull亦兼容 Arch 的Label等对象类型。七、相关文档与测试入口本文对应文档 src/Doc/sphinx/DraftTrackers.rstSphinxautomodule入口最终生成DraftTrackers模块 API 页模块实现 src/Mod/Draft/draftguitools/gui_trackers.py共 1762 行含 1 个基类与 17 个具体 Tracker参数定义与默认值 src/Mod/Draft/draftutils/params.py命令集成示例 src/Mod/Draft/draftguitools/gui_arcs.py、 src/Mod/Draft/draftguitools/gui_dimensions.py、 src/Mod/Draft/draftguitools/gui_base.py、 src/Mod/Draft/draftguitools/gui_edit.py导入与测试 src/Mod/Draft/DraftTools.py#L60统一导入、 src/Mod/Draft/drafttests/test_import_gui.py#L62-L64模块可导入性测试以及 src/Mod/Draft/drafttests/test_manual_input_gui.py#L341-L361 中模拟 Tracker 对象验证吸附解析逻辑的测试。八、小结Draft Trackers 是连接交互输入与正式建模的桥梁它以 Coin3D 场景图为画布以SoSwitch为开关以坐标/变换节点为参数载体在命令执行期间提供零文档负担的实时预览并在命令结束时干净地清理自身。理解这一机制不仅有助于读懂 Draft/Arch 数十个交互命令的实现也为在 FreeCAD 中开发自定义绘图工具提供了可复用的预览层设计范式——创建 Tracker → 监听事件刷新 → 结束时 finalize即是全部要点。【免费下载链接】FreeCADOfficial source code of FreeCAD, a free and opensource multiplatform 3D parametric modeler.项目地址: https://gitcode.com/GitHub_Trending/fr/FreeCAD创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表