// © Andrey Bushman, 2014
// ExtensionMethods.cs
// This code partially based on Alexander Rivilis's code (ARX version):
// http://adn-cis.org/forum/index.php?topic=1060.msg4983#msg4983
using System;
using System.Collections.Generic;
using System.Linq;
#if AUTOCAD
using cad = Autodesk.AutoCAD.ApplicationServices.Application;
using Ap = Autodesk.AutoCAD.ApplicationServices;
using Db = Autodesk.AutoCAD.DatabaseServices;
using Ed = Autodesk.AutoCAD.EditorInput;
using Rt = Autodesk.AutoCAD.Runtime;
using Gm = Autodesk.AutoCAD.Geometry;
#endif
namespace Bushman.CAD {
public static class ExtensionMethods {
static Rt.RXClass proxyObjectRXType = Rt.RXClass.GetClass(typeof(
Db.ProxyObject));
static Rt.RXClass proxyEntityRXType = Rt.RXClass.GetClass(typeof(
Db.ProxyEntity));
public static Db.ObjectId[] GetDBObjectIds(this Db.Database db) {
Db.ObjectId[] ids = GetDBObjectIds(db, (n => true));
return ids;
}
public static Db.ObjectId[] GetDBObjectIds(this Db.Database db,
Func<Db.ObjectId, Boolean> filter) {
// Check arguments
if (null == db)
throw new ArgumentNullException("null == db");
if (null == filter)
throw new ArgumentNullException("null == filter");
if (db.IsDisposed)
throw new ArgumentException("true == db.IsDisposed");
// -------------------
Int32 approxNum = db.ApproxNumObjects;
List<Db.ObjectId> ids = new List<Db.ObjectId>();
for (Int64 i = db.BlockTableId.Handle.Value; i < db.Handseed.Value
&& approxNum > 0; ++i) {
Db.Handle h = new Db.Handle(i);
Db.ObjectId id = Db.ObjectId.Null;
Boolean parseResult = db.TryGetObjectId(h, out id);
if (parseResult) {
--approxNum;
if (filter(id)) {
ids.Add(id);
}
}
}
return ids.ToArray();
}
public static Db.ObjectId[] GetEntityIds(this Db.Database db) {
Db.ObjectId[] ids = GetEntityIds(db, (n => true));
return ids;
}
public static Db.ObjectId[] GetEntityIds(this Db.Database db,
Func<Db.ObjectId, Boolean> filter) {
// Check arguments
if (null == db)
throw new ArgumentNullException("null == db");
if (null == filter)
throw new ArgumentNullException("null == filter");
if (db.IsDisposed)
throw new ArgumentException("true == db.IsDisposed");
// -------------------
List<Db.ObjectId> ids = new List<Db.ObjectId>();
// Entity items can be located in the BlockTableRecord instances
// only.
using (Db.Transaction tr = db.TransactionManager.StartTransaction()
) {
Db.BlockTable bt = tr.GetObject(db.BlockTableId,
Db.OpenMode.ForRead) as Db.BlockTable;
// Skip erased BlockTableRecord instances.
IEnumerable<Db.ObjectId> btrIds = bt.Cast<Db.ObjectId>()
.Where(n => !n.IsErased);
foreach (Db.ObjectId btrId in btrIds) {
Db.BlockTableRecord btr = tr.GetObject(btrId,
Db.OpenMode.ForRead) as Db.BlockTableRecord;
foreach (Db.ObjectId id in btr) {
if (filter(id)) {
ids.Add(id);
}
}
}
tr.Commit();
}
return ids.ToArray();
}
public static Db.ObjectId[] ExplodeProxyEntity(
Db.ObjectId proxyEntityId, out Boolean handOverTo_called) {
// Check arguments
if (null == proxyEntityId)
throw new ArgumentException("null == proxyEntityId");
if (proxyEntityId.IsErased)
throw new ArgumentException("true == proxyEntityId.IsErased");
if (null == proxyEntityId.Database)
throw new ArgumentException("null == proxyEntityId.Database");
if (proxyEntityId.Database.IsDisposed)
throw new ArgumentException(
"true == proxyEntityId.Database.IsDisposed");
if (!proxyEntityId.ObjectClass.IsDerivedFrom(proxyEntityRXType))
throw new ArgumentException("false == proxyEntityId." +
"ObjectClass.IsDerivedFrom(proxyEntityRXType)");
// -------------------
using (Db.DBObjectCollection newDBObjects =
new Db.DBObjectCollection()) {
Db.Database db = proxyEntityId.Database;
using (Db.Transaction tr = db.TransactionManager
.StartOpenCloseTransaction()) {
Db.ProxyEntity proxyEntity = tr.GetObject(
proxyEntityId, Db.OpenMode.ForWrite)
as Db.ProxyEntity;
if (proxyEntity.GraphicsMetafileType ==
Db.GraphicsMetafileType.FullGraphics) {
proxyEntity.Explode(newDBObjects);
}
else if (proxyEntity.GraphicsMetafileType ==
Db.GraphicsMetafileType.BoundingBox) {
Db.Extents3d ext = proxyEntity.GeometricExtents;
Gm.Point3dCollection arr =
new Gm.Point3dCollection();
arr.Add(ext.MinPoint);
arr.Add(new Gm.Point3d(ext.MinPoint.X,
ext.MaxPoint.Y, ext.MinPoint.Z));
arr.Add(new Gm.Point3d(ext.MaxPoint.X,
ext.MaxPoint.Y, ext.MinPoint.Z));
arr.Add(new Gm.Point3d(ext.MaxPoint.X,
ext.MinPoint.Y, ext.MinPoint.Z));
Db.Polyline3d pline = new Db.Polyline3d(
Db.Poly3dType.SimplePoly, arr, true);
pline.LayerId = proxyEntity.LayerId;
pline.LinetypeId = proxyEntity.LinetypeId;
pline.Color = proxyEntity.Color;
newDBObjects.Add(pline);
}
// ----------------
Boolean canBeErased = (proxyEntity.ProxyFlags & 0x1) != 0;
if (canBeErased) {
proxyEntity.Erase();
handOverTo_called = false;
}
else {
using (Db.Line tmp = new Db.Line()) {
proxyEntity.HandOverTo(tmp, false, false);
tmp.Erase();
proxyEntity.Dispose();
handOverTo_called = true;
}
}
Db.BlockTableRecord btr = tr.GetObject(
proxyEntity.BlockId, Db.OpenMode.ForWrite, false)
as Db.BlockTableRecord;
if (newDBObjects.Count > 0) {
foreach (Db.DBObject item in newDBObjects) {
if (item is Db.Entity) {
Db.Entity _ent = item as Db.Entity;
btr.AppendEntity(_ent);
tr.AddNewlyCreatedDBObject(item, true);
}
}
}
Db.ObjectIdCollection idsRef =
btr.GetBlockReferenceIds(true, true);
foreach (Db.ObjectId id in idsRef) {
Db.BlockReference br = tr.GetObject(id,
Db.OpenMode.ForWrite, false)
as Db.BlockReference;
br.RecordGraphicsModified(true);
}
tr.Commit();
}
return newDBObjects.Cast<Db.DBObject>().Select(n => n.ObjectId)
.ToArray();
}
}
public static void RemoveDBObject(Db.ObjectId id,
out Boolean handOverTo_called) {
// Check arguments
if (null == id)
throw new ArgumentException("null == id");
if (id.IsErased)
throw new ArgumentException("true == id.IsErased");
if (null == id.Database)
throw new ArgumentException("null == id.Database");
if (id.Database.IsDisposed)
throw new ArgumentException("true == id.Database.IsDisposed");
// -------------------
Db.Database db = id.Database;
using (Db.Transaction tr = db.TransactionManager
.StartOpenCloseTransaction()) {
Db.DBObject obj = tr.GetObject(id, Db.OpenMode.ForWrite);
EraseDBObject(obj, out handOverTo_called);
tr.Commit();
}
}
private static void EraseDBObject(Db.DBObject obj,
out Boolean handOverTo_called) {
// Check argument
if (null == obj)
throw new ArgumentNullException("null == obj");
if (obj.IsErased)
throw new ArgumentException("true == obj.IsErased");
if (obj.IsDisposed)
throw new ArgumentException("true == obj.IsDisposed");
if (null == obj.Database)
throw new ArgumentException("null == obj.Database");
if (obj.Database.IsDisposed)
throw new ArgumentException("true == obj.Database.IsDisposed");
// ----------------
Boolean canBeErased = true;
// AcDbProxyEntity::kEraseAllowed = 0x1
if (obj is Db.ProxyObject) {
Db.ProxyObject proxy = obj as Db.ProxyObject;
canBeErased = (proxy.ProxyFlags & 0x1) != 0;
}
else if (obj is Db.ProxyEntity) {
Db.ProxyEntity proxy = obj as Db.ProxyEntity;
canBeErased = (proxy.ProxyFlags & 0x1) != 0;
}
if (canBeErased) {
obj.Erase(true);
handOverTo_called = false;
}
else {
using (Db.DBObject tmp = obj is Db.Entity ?
(Db.DBObject)new Db.Line() : new Db.DBDictionary()) {
obj.HandOverTo(tmp, false, false);
tmp.Erase(true);
obj.Dispose();
handOverTo_called = true;
}
}
}
public static Db.ObjectId[] GetFreeAnnotativeScaleIds(
this Db.Database db) {
// Check argument
if (null == db)
throw new ArgumentNullException("null == db");
if (db.IsDisposed)
throw new ArgumentException("true == db.IsDisposed");
// ----------------
using (Db.ObjectIdCollection ids = new Db.ObjectIdCollection()) {
Db.ObjectContextManager ocMng = db.ObjectContextManager;
if (null != ocMng) {
Db.ObjectContextCollection ocItems =
ocMng.GetContextCollection("ACDB_ANNOTATIONSCALES");
if (null != ocItems) {
foreach (Db.ObjectContext item in ocItems) {
if (item is Db.AnnotationScale)
ids.Add(new Db.ObjectId(item.UniqueIdentifier)
);
}
db.Purge(ids);
}
}
return ids.Cast<Db.ObjectId>().ToArray();
}
}
public static void RemoveFreeAnnotativeScales(this Db.Database db) {
// Check argument
if (null == db)
throw new ArgumentNullException("null == db");
if (db.IsDisposed)
throw new ArgumentException("true == db.IsDisposed");
// -----------------
Db.ObjectId[] ids = db.GetFreeAnnotativeScaleIds();
using (Db.Transaction tr = db.TransactionManager.StartTransaction()
) {
foreach (Db.ObjectId id in ids) {
try {
Db.DBObject obj = tr.GetObject(id, Db.OpenMode
.ForWrite, false);
obj.Erase();
}
catch { }
}
tr.Commit();
}
}
public static Db.ObjectId[] GetLockedLayerIds(Db.ObjectId[] entityIds
) {
if (null == entityIds)
throw new ArgumentNullException("null == entityIds");
if (0 == entityIds.Length)
return new Db.ObjectId[] { };
if (entityIds.Select(n => n.Database).Distinct().Count() > 1)
throw new ArgumentException(
"All items of 'entityIds' must to have the same " +
"'Database' property value.");
Rt.RXClass entityRXType = Rt.RXClass.GetClass(typeof(Db.Entity));
if (entityIds.Any(n => !n.ObjectClass.IsDerivedFrom(entityRXType)))
throw new ArgumentException("All items of 'entityIds' must " +
"to be derived from Entity type.");
if (null == entityIds[0].Database || entityIds[0].Database
.IsDisposed)
throw new ArgumentNullException(
"entityIds[0].Database || entityIds[0].Database.IsDisposed"
);
HashSet<Db.ObjectId> hashSet = new HashSet<Db.ObjectId>();
using (Db.Transaction tr = entityIds[0].Database.TransactionManager
.StartTransaction()) {
foreach (Db.ObjectId id in entityIds) {
Db.Entity entity = tr.GetObject(id, Db.OpenMode
.ForRead, true) as Db.Entity;
Db.LayerTableRecord layer = tr.GetObject(entity.LayerId,
Db.OpenMode.ForRead, false) as Db.LayerTableRecord;
if (layer.IsLocked) {
hashSet.Add(entity.LayerId);
}
}
tr.Commit();
}
return hashSet.ToArray();
}
}
}