BRX.NET: erasing entities
{ _AcAp.Document document = _AcAp.Application.DocumentManager.MdiActiveDocument; _AcEd.Editor editor = document.Editor; _AcDb.Database database = document.Database; ObjectIdCollection ids; try { using (_AcDb.Transaction trans = database.TransactionManager.StartTransaction()) { ids = GetSelectionIds(filterType, filterData); foreach (ObjectId id in ids) { DBObject entity = (DBObject)trans.GetObject(id, OpenMode.ForWrite); entity.Erase(); } trans.Commit(); } database.ReclaimMemoryFromErasedObjects(ids); return true; } catch (System.Exception ex) { _AcAp.Application.ShowAlertDialog(string.Format("\nError: {0}\nStackTrace: {1}", ex.Message, ex.StackTrace)); return false; }}[/code]
Comments
-
Hi Arno,
looks like you may have found a bug! It took me a while to find where it was hiding, but I found it.
it's in the constructor public ObjectIdCollection(ObjectId[] values);
to work around it, build your ObjectIdCollection using add I.e.
[code]
static _AcDb.ObjectIdCollection ToObjectIdCollection(IEnumerable<<span style="color: #010001;">_AcDb.ObjectId> ids)
{
_AcDb.ObjectIdCollection col = new _AcDb.ObjectIdCollection();
foreach (_AcDb.ObjectId id in ids)
col.Add(id);
return col;
}
[/code]
here is the test I used
[code]
namespace BcadMgdTest
{
public static class Commands
{
[_AcRx.CommandMethod("doit")]
public static void doit()
{
List<<span style="color: #010001;">_AcDb.ObjectId> ids = new List<<span style="color: #010001;">_AcDb.ObjectId>();
_AcAp.Document doc = _AcAp.Application.DocumentManager.MdiActiveDocument;
_AcEd.Editor ed = doc.Editor;
_AcDb.Database db = doc.Database;
_AcDb.TransactionManager tm = db.TransactionManager;
using (_AcDb.Transaction tr = tm.StartTransaction())
{
_AcDb.BlockTable blockTable = tr.GetObject
(db.BlockTableId, _AcDb.OpenMode.ForRead, false)
as _AcDb.BlockTable;
foreach (_AcDb.ObjectId blockTableRecordId in blockTable)
{
_AcDb.BlockTableRecord blockTableRecord = tr.GetObject
(blockTableRecordId, _AcDb.OpenMode.ForRead, false)
as _AcDb.BlockTableRecord;
foreach (_AcDb.ObjectId id in blockTableRecord)
{
ids.Add(id);
}
}
tr.Commit();
}
testids(ids, doc);
testids(ToObjectIdCollection(ids), doc);
// bug in ObjectIdCollection ctor
testids(new _AcDb.ObjectIdCollection(ids.ToArray()), doc);
}
static _AcDb.ObjectIdCollection ToObjectIdCollection(IEnumerable<<span style="color: #010001;">_AcDb.ObjectId> ids)
{
_AcDb.ObjectIdCollection col = new _AcDb.ObjectIdCollection();
foreach (_AcDb.ObjectId id in ids)
col.Add(id);
return col;
}
public static void testids(IEnumerable<<span style="color: #010001;">_AcDb.ObjectId> ids, _AcAp.Document document)
{
document.Editor.WriteMessage("\nstart\n");
foreach (_AcDb.ObjectId id in ids)
document.Editor.WriteMessage("-{0}-", id);
document.Editor.WriteMessage("\nend\n");
}
public static void testids(_AcDb.ObjectIdCollection ids, _AcAp.Document document)
{
document.Editor.WriteMessage("\nstart\n");
foreach (_AcDb.ObjectId id in ids)
document.Editor.WriteMessage("-{0}-", id);
document.Editor.WriteMessage("\nend\n");
}
}
}
[/code]
I will file a report on this so it's fixed.
0 -
Spot on Dan!
That's exatly what I saw; the first id in the collection is found, the second one was '0' causing the problems.
I do use the ObjectCollectionIds(ObjectIds[] values) to wrap the selected entity IDs but that was in the GetSelectionIds method I didn't send. ;-)
Another mistery solved hopefully.
Cheers,
Arno
0 -
Hi Arno,
[code]
public class ObjectIdList : List<<span style="color: #2b91af;">ObjectId>
{
public ObjectIdList(){}
public ObjectIdList(ObjectId src)
{
base.Add(src);
}
public ObjectIdList(ObjectId[] src)
{
base.AddRange(src);
}
public ObjectIdList(ObjectIdList src)
{
base.AddRange(src);
}
public ObjectIdList(ObjectIdCollection src)
{
foreach (ObjectId oid in src)
base.Add(oid);
}
public static implicit operator ObjectIdList(ObjectId[] src)
{
return ((src != null) ? new ObjectIdList(src) : null);
}
public static implicit operator ObjectIdList(ObjectIdCollection src)
{
return ((src != null) ? new ObjectIdList(src) : null);
}
public static implicit operator ObjectId[](ObjectIdList src)
{
return ((src != null) ? src.ToArray() : null);
}
public static implicit operator ObjectIdCollection(ObjectIdList src)
{
ObjectIdCollection dest = new ObjectIdCollection();
src.ForEach(Item => dest.Add(Item));
return dest;
}
}
[/code]
the class can then be used as
[code]
public static class Commands
{
[_AcRx.CommandMethod("doit")]
public static void doit()
{
_AcAp.Document doc = _AcAp.Application.DocumentManager.MdiActiveDocument;
_AcEd.PromptSelectionResult res = doc.Editor.GetSelection();
if (res.Status == _AcEd.PromptStatus.OK)
{
ObjectIdList ids = res.Value.GetObjectIds();
testids(ids, doc);
}
}
public static void testids(ObjectIdList ids, _AcAp.Document document)
{
//lambda expresion
ids.ForEach( ID => document.Editor.WriteMessage("-{0}-", ID));
// implicit cast to ObjectIdCollection;
document.Database.ReclaimMemoryFromErasedObjects(ids);
}
}
[/code]
cheers : )
0 -
Also.. There is a TypedValueList class somewhere at the swamp that wraps Resulbuffer + TypedValue[] very useful for creating selection set filters : )
0 -
Thanks a lot Daniel, this will keep me going for a while...
0 -
Just to complete this subject for those interested: I had left out the GetSelectionIds() method just because it didn't seem to matter, but that's where the problem was. Here's the snippets I was playing with (see the fix at the end of the try block):[code]public static ObjectIdCollection GetSelectionIds (short[] filterType, object[] filterData)
{ _AcEd.Editor editor = _AcAp.Application.DocumentManager.MdiActiveDocument.Editor; ObjectIdCollection ids = new ObjectIdCollection(); try { List<_AcDb.</font>TypedValue> dxfCodes = new List<</font>TypedValue>(filterType.Length); for (int i = 0; i < filterType.Length; i++) dxfCodes.Add(</font>new _AcDb.TypedValue(filterType[i], filterData[i])); _AcEd.SelectionFilter selectionFilter = new SelectionFilter(dxfCodes.ToArray()); _AcEd.PromptSelectionResult res = editor.SelectAll(selectionFilter); if (res.Status == _AcEd.PromptStatus.OK) { _AcEd.SelectionSet sset = res.Value; //ids = new ObjectIdCollection(sset.GetObjectIds()); << //this was causing the problem</span> foreach (ObjectId objectId in sset.GetObjectIds()) //the fix as suggested by Daniel ids.Add(objectId); } } catch (System.Exception ex) { _AcAp.Application.ShowAlertDialog(string.Format("\nError: {0}\nStackTrace: {1}", ex.Message, ex.StackTrace)); } return ids;
}[/code]0