获取块内实体 封装

using System;

using System.Collections.Generic;

using Autodesk.AutoCAD.DatabaseServices;

using Autodesk.AutoCAD.Geometry;

namespace CadTools

{

/// <summary>

/// 嵌套实体拾取结果

/// </summary>

public class NestedPickResult

{

/// <summary>

/// 最终命中的实体ID

/// </summary>

public ObjectId EntityId;

/// <summary>

/// 最终命中的实体

/// </summary>

public Entity Entity;

/// <summary>

/// 从外到内的块路径

/// </summary>

public List<ObjectId> BlockPath = new List<ObjectId>();

/// <summary>

/// 累计变换矩阵

/// </summary>

public Matrix3d Transform = Matrix3d.Identity;

}

public static class NestedEntityHelper

{

/// <summary>

/// 按点获取最深层嵌套实体

/// </summary>

/// <param name="db">数据库</param>

/// <param name="pt">世界坐标点</param>

/// <param name="tol">命中容差</param>

/// <returns></returns>

public static NestedPickResult 按点获取最深层嵌套实体(

this Database db,

Point3d pt,

double tol = 1.0)

{

if (db == null)

return null;

NestedPickResult result = null;

using (Transaction tr = db.TransactionManager.StartTransaction())

{

BlockTable bt =

(BlockTable)tr.GetObject(

db.BlockTableId,

OpenMode.ForRead);

BlockTableRecord ms =

(BlockTableRecord)tr.GetObject(

btBlockTableRecord.ModelSpace,

OpenMode.ForRead);

FindInBlock(

tr,

ms,

pt,

Matrix3d.Identity,

new List<ObjectId>(),

tol,

ref result);

tr.Commit();

}

return result;

}

/// <summary>

/// 递归扫描块

/// </summary>

private static bool FindInBlock(

Transaction tr,

BlockTableRecord btr,

Point3d worldPt,

Matrix3d currentTransform,

List<ObjectId> path,

double tol,

ref NestedPickResult result)

{

bool found = false;

foreach (ObjectId id in btr)

{

Entity ent =

tr.GetObject(id, OpenMode.ForRead) as Entity;

if (ent == null)

continue;

// 先处理块参照

BlockReference br = ent as BlockReference;

if (br != null)

{

Matrix3d newTransform =

currentTransform * br.BlockTransform;

BlockTableRecord childBtr;

try

{

ObjectId btrId =

br.IsDynamicBlock

? br.DynamicBlockTableRecord

: br.BlockTableRecord;

childBtr =

(BlockTableRecord)tr.GetObject(

btrId,

OpenMode.ForRead);

}

catch

{

continue;

}

if (!PointInsideEntityExtents(

br,

worldPt,

currentTransform,

tol))

{

continue;

}

List<ObjectId> newPath =

new List<ObjectId>(path);

newPath.Add(br.ObjectId);

if (FindInBlock(

tr,

childBtr,

worldPt,

newTransform,

newPath,

tol,

ref result))

{

found = true;

}

}

// 当前实体命中检测

if (EntityHitTest(

ent,

worldPt,

currentTransform,

tol))

{

result = new NestedPickResult();

result.EntityId = ent.ObjectId;

result.Entity = ent;

result.BlockPath =

new List<ObjectId>(path);

result.Transform =

currentTransform;

found = true;

}

}

return found;

}

/// <summary>

/// 实体命中测试

/// </summary>

private static bool EntityHitTest(

Entity ent,

Point3d worldPt,

Matrix3d transform,

double tol)

{

try

{

if (!PointInsideEntityExtents(

ent,

worldPt,

transform,

tol))

{

return false;

}

Curve curve = ent as Curve;

if (curve != null)

{

Curve clone =

curve.GetTransformedCopy(transform)

as Curve;

Point3d closest =

clone.GetClosestPointTo(

worldPt,

false);

double dist =

closest.DistanceTo(worldPt);

clone.Dispose();

return dist <= tol;

}

return true;

}

catch

{

return false;

}

}

/// <summary>

/// 包围盒快速过滤

/// </summary>

private static bool PointInsideEntityExtents(

Entity ent,

Point3d pt,

Matrix3d transform,

double tol)

{

try

{

Extents3d ext = ent.GeometricExtents;

ext.TransformBy(transform);

return

pt.X >= ext.MinPoint.X - tol &&

pt.X <= ext.MaxPoint.X + tol &&

pt.Y >= ext.MinPoint.Y - tol &&

pt.Y <= ext.MaxPoint.Y + tol &&

pt.Z >= ext.MinPoint.Z - tol &&

pt.Z <= ext.MaxPoint.Z + tol;

}

catch

{

return false;

}

}

}

}

相关推荐
海绵宝宝的月光宝盒2 天前
14-AutoCAD-阵列命令应用与案例实战(AR)
经验分享·笔记·自动化·课程设计·制造·学习方法·cad
广州智造3 天前
Radioss弹簧的内力和弯矩计算
cad·cae·radioss·阻尼·刚度
虹科数字化与AR3 天前
安宝特方案丨汽车制造质检三步走:从导入CAD到数字化报告,一台iPad全搞定
经验分享·cad
comedate3 天前
SMLib 的 Examples 导读:PyAPI / SM_API / SMLib 三组示例怎么读
python·cad·smlib·examples·sm_api
广州智造4 天前
Radioss弹簧单元失效
cad·cae·仿真软件·hypermesh·显示求解器
海绵宝宝的月光宝盒5 天前
9-AutoCAD-移动、旋转、复制命令应用与案例实战
经验分享·笔记·职场和发展·课程设计·制造·学习方法·cad
广州智造5 天前
Radioss混凝土材料仿真案例
设计·cad·建模·cae·仿真软件·radioss
comedate5 天前
[SMLib] SMLib 的 usd.heal_file:STEP/IGES 导入模型修复实战
cad·step·smlib·heal·iges·导入修复
海绵宝宝的月光宝盒6 天前
7-AutoCAD-参考线、多行文字、填充命令应用
经验分享·笔记·学习·职场和发展·课程设计·制造·cad
comedate6 天前
SMLib vs OpenCASCADE:2026 开源 CAD 内核怎么选?
cad·opencascade·选型对比·smlib·nurbs