乐筑天下

搜索
欢迎各位开发者和用户入驻本平台 尊重版权,从我做起,拒绝盗版,拒绝倒卖 签到、发布资源、邀请好友注册,可以获得银币 请注意保管好自己的密码,避免账户资金被盗
查看: 180|回复: 11

是不是?NET API有ActiveX AcadEntity类的等价物吗?

[复制链接]

21

主题

58

帖子

3

银币

初露锋芒

Rank: 3Rank: 3Rank: 3

铜币
142
发表于 2019-5-3 06:14:31 | 显示全部楼层 |阅读模式
我正在写一个从模型空间中移除圆/线/折线等的程序。这些对象是我的命令出于各种原因使用的临时对象,当我在每个命令结束时进行清理时,我需要删除它们。我希望ActiveX提供的这个相当有用的类有一个等价的类,而不是为每一个对象类都有一个单独的例程,或者遍历模型空间中的实体。
如果没有,我将简单地继续编写单独的例程。

本帖以下内容被隐藏保护;需要你回复后,才能看到!

游客,如果您要查看本帖隐藏内容请回复
回复

使用道具 举报

15

主题

687

帖子

169

银币

中流砥柱

Rank: 25

铜币
582
发表于 2019-5-3 06:41:31 | 显示全部楼层
嗨,
您可以使用继承。
Circle、Line、Polyline类派生自Curve,它由Entity驱动,Entity派生自提供Erase()方法的DBObject。
这意味着DBObject实例,作为派生类的任何实例,可以调用Erase()方法。
回复

使用道具 举报

21

主题

58

帖子

3

银币

初露锋芒

Rank: 3Rank: 3Rank: 3

铜币
142
发表于 2019-5-3 08:14:37 | 显示全部楼层
我已经尝试过了,它会导致访问冲突。代码:
要删除的圆圈由以下人员创建:
这是欧特克帮助中一个非常普通的例程的副本。
我假设删除此对象需要一个数据库事务,就像创建例程一样。
回复

使用道具 举报

21

主题

58

帖子

3

银币

初露锋芒

Rank: 3Rank: 3Rank: 3

铜币
142
发表于 2019-5-3 08:24:10 | 显示全部楼层
可以肯定的是,我找到的所有删除对象的示例要么涉及使用ObjectId在模型中查找对象,我认为这很慢。......
或者,像这样(http://docs.autodesk.com/ACD/2011/ENU/filesMDG/WS1a9193826455f5ff2566ffd511ff6f8c7ca-3eef.htm)涉及创建对象,然后在单个事务中删除它......从长远来看,这对我没有好处。
我可以创建一个涵盖整个命令的大事务,但当用户退出命令时,这将涉及一些痛苦的双重检查,这完全是糟糕的编程。
回复

使用道具 举报

21

主题

58

帖子

3

银币

初露锋芒

Rank: 3Rank: 3Rank: 3

铜币
142
发表于 2019-5-3 08:51:22 | 显示全部楼层
我想我应该使用以下命令来执行ObjectId路由:
  1.         public void Erase(ObjectId id)
  2.         {
  3.             if (id.Database.TransactionManager.TopTransaction != null)
  4.                 id.GetObject(OpenMode.ForWrite).Erase();
  5.             else
  6. #pragma warning disable CS0618
  7.                 using (var obj = id.Open(OpenMode.ForWrite))
  8.                     obj.Erase();
  9. #pragma warning restore CS0618
  10.         }

无论如何,事实证明,ObjectId和我的圈的大多数属性都产生了访问冲突。因此,我的创建例程返回对新创建的圆实体的引用时出错了
这是一种非常基本的编程实践,即在方法中创建一个对象并返回以供使用和滥用。我注意到许多Autodesk帮助示例创建thingy,然后返回void
请不要告诉我必须创建一个实体,然后再去寻找它……或者我又回到了拥有一笔大额交易的想法
回复

使用道具 举报

15

主题

687

帖子

169

银币

中流砥柱

Rank: 25

铜币
582
发表于 2019-5-3 09:39:39 | 显示全部楼层
您不能在用于打开它或已将其添加到的事务之外使用DBObject实例,因此,您可以将DBObject的ObjectId从一个事务使用到另一个事务,但通常您应该在main方法中启动一个事务并将其作为参数传递给被调用的方法(或从这些方法中获取顶部事务)。无论如何,大多数时候,您可以避免向数据库添加临时Entity。出于地理目的,您应该使用Geometry命名空间(LineSegment2d/3d, CircularArc2d/3d,...)中的非数据库常驻对象。对于仅用于创建其他实体的实体,您可以简单地使用实体,而不是添加它并擦除它。这是一个通过挤压圆来创建圆柱体的示例,它需要创建一个圆形和一个带有此圆形的区域来挤压区域。Circle和Area都没有添加到数据库中,两者都在创建区域后进行处理(使用语句)。静态ObjectId CreateCylinder(数据库db、Point3d中心、Vector3d法线、双半径、双高度)。
{。
ObjectId id;。
使用(var tr=db.TransactionManager.StartTransaction())。
{。
使用(var圆=新圆(中心,法线,半径))。
{。
var曲线=新的DBObjectCollection();。
curves.Add(圆);。
var区域=Region.CreateFromCurves(曲线);。
使用(var区域=(区域)区域[0])。
{。
var缸=new Solid3d();。
cylinder.Extrude(区域,高度,0.0);。
var space=(BlockTableRecords)tr.GetObject(db.CurrentSpaceId,OpenMode.ForWrite);。
id=space.AppendEntity(柱体);。
tr.AddNewlyCreatedDBObject(气缸,真);。
} // 。
} // 。
tr.Commit();。
}。
返回id;。
}。
回复

使用道具 举报

21

主题

58

帖子

3

银币

初露锋芒

Rank: 3Rank: 3Rank: 3

铜币
142
发表于 2019-5-3 10:28:06 | 显示全部楼层
谢谢Gile。真的吗?我不能说我很惊讶...在过去的两年里,我在使用设计工具(Tekla和AutoCAD)时看到的糟糕编程/设计比我之前整个职业生涯的总和还要多。我可能会补充说,不是你的,而是我从继承工作的程序员那里继承的(任何10K+行过程的人?)。现在我有了一个新的构建项目,我希望不必妥协,拥有一个体面的OOP设计,并且不必接近COM。这种情况会有所改变。
但我可以使用这些ObjectId对象。如果可以避免的话,我不会处理一笔大交易...最重要的是,我想要易读性(封装),并且希望避免像孩子们聚会上的糖果一样传递参数。
在这种情况下,我需要一组可见的对象,在命令期间使用,主要用于选择目的。但是,我明白你的观点,即能够使用这些类来完成工作,而不必在数据库上捣乱。
我将继续努力,直到我遇到下一堵砖墙。
回复

使用道具 举报

21

主题

58

帖子

3

银币

初露锋芒

Rank: 3Rank: 3Rank: 3

铜币
142
发表于 2019-5-3 11:07:38 | 显示全部楼层
而且情况变得更糟。这个ObjectId类是不可空的,所以我不能设置返回的默认值。因此,我现在必须在业务类中丢失错误处理程序,否则代码将无法编译
我开始怀疑,使用ActiveX API是否会更好(因为它使用了讨厌的对象类,甚至更糟糕的是数组)。我选择哪种方式似乎无关紧要,使用Autodesk产品涉及到某种捏造。
回复

使用道具 举报

85

主题

404

帖子

7

银币

中流砥柱

Rank: 25

铜币
751
发表于 2019-5-3 12:04:44 | 显示全部楼层
对于ObjectID,您可以返回ObjectID.Null我有一个Erase函数,如下所示://。
///从当前文档中擦除对象。
>/// //要擦除的对象的ObjectID。
公共静态bool擦除(ObjectId id)。
{。
if(id==ObjectId.Null)返回false;。
使用(Active.Document.LockDocument())。
{。
使用(事务acTr=Active.Document.TransactionManager.StartTransaction())。
{。
DBObject obj=acTr.GetObject(id,OpenMode.ForWrite, true);。
如果(obj!=null)。
{。
obj.Erase(真);。
acTr.Commit();。
返回true;。
}。
acTr.Commit();。
返回false;。
}。
}。
}每当您创建一个数据库元素时,您都可以从数据库元素中返回对象ID,可能类似于:public ObjectID MakeCircle(pt中心,双半径)。
{。
ObjectID结果=ObjectID.Null;。
...。
结果=curSpace.AppendEntity(br);。
...。
返回结果;。
}此外,为了减少事务,您可以将Erase函数传递给ObjectIDCollection,并使用一个事务来擦除整个集合(通过迭代)现在您得到了这样的东西:ObjectIdCollection Object=new ObjectIdCollection();。
...//做你的东西,让你的临时对象。
tempObjects.Add(MakeCircle(centerPt,4));。
...//做更多的东西。
//一次擦除它们。
擦除对象(temObject);正如Gile所说,最好不要实际添加到数据库中(也许您可以使用jig显示您的临时对象?),但这让您开始。。
回复

使用道具 举报

15

主题

687

帖子

169

银币

中流砥柱

Rank: 25

铜币
582
发表于 2019-5-3 12:10:13 | 显示全部楼层
ObjectId具有Null静态属性和IsNull实例属性
使用top事务允许您使用DBObjects而不是ObjectId,并且将事务传递给被调用的方法不是强制性的
在我这边,我喜欢使用从顶级事务中调用的扩展方法,这里有一个小示例来替换“AddCircleToDrawing”方法
静态类扩展
{
公共静态T GetObject

这个ObjectId id,
OpenMode=OpenMode.ForRead,
bool openErased=false,
bool-forceOpenOnLockedLayer=false),其中T:DBObject
{
如果(id.IsNull)抛出新的Autodesk.AutoCAD.Runtime.Exception(ErrorStatus.NullObjectId)
事务tr=id.Database.TransactionManager.TopTransaction
如果(tr==null)抛出新的Autodesk.AutoCAD.Runtime.Exception(ErrorStatus.NoActiveTransactions)
返回(T)tr。GetObject(id、模式、openErased、forceOpenOnLockedLayer)
}
公共静态圆AddCircle(此BlockTableRecord所有者,Point3d中心,双半径,字符串layerName)
{
如果(owner==null)抛出新的ArgumentNullException(“owner”)
var layerTable=owner.Database.LayerTableId.GetObject
()
如果(!layerTable.Has(layerName))抛出新的Autodesk.AutoCAD.Runtime.Exception(ErrorStatus.BadLayerName)
var tr=owner.Database.TransactionManager.TopTransaction
var circle=new circle(){Center=Center,Radius=Radius,Layer=layerName}
所有者。追加实体(圆)
tr.addNewlyCreatedBobObject(圆,真)
返回圆
}
}

在主方法中
使用(var tr=db.TransactionManager.StartTransaction())
{
var space=db.CurrentSpaceId.GetObject
(OpenMode.ForWrite)
var easiBaseOutline=space。AddCircle(插入点,600,LayerNames.Temporary实体)
//用“easiBaseOutline”完成你的工作
tr.Commit()
}

在本论坛中搜索GetObjects,您将找到有关此类扩展方法的更多讨论。
回复

使用道具 举报

发表回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

  • 微信公众平台

  • 扫描访问手机版

  • 点击图片下载手机App

QQ|关于我们|小黑屋|乐筑天下 繁体中文

GMT+8, 2025-2-4 08:53 , Processed in 0.366573 second(s), 83 queries .

© 2020-2025 乐筑天下

联系客服 关注微信 帮助中心 下载APP 返回顶部 返回列表