65
« on: November 24, 2010, 02:54:52 PM »
I think I got something working with the strcture way using a ResultBuffer (the AutoCAD .NET/ObjectARX object which looks the most like a LISP DXF list).
In the following example:
The ParamBlockDoubled are stored in a List<ParamBlockDoubled>, there's no need to use a Dictionary as the items Value (objectId) are never used.
DoubleToErase is defined as a List<BlockReference> because it avoid to open them twice from their ObjectId.
It still uses the BlockTable -> BlockTableRecord _> GetReferenceIds route which avoid to run through the whole database.
using System;
using System.Collections.Generic;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
namespace DuplicateTest
{
public class Commands
{
[CommandMethod("Test")]
public void DelDupBlkRef()
{
try
{
int del = DeleteDuplicatedBlockRef();
Application.ShowAlertDialog(del.ToString() + " duplicated block(s) have been erased");
}
catch (System.Exception e)
{
Application.ShowAlertDialog("\nError: " + e.Message);
}
}
private int DeleteDuplicatedBlockRef()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
int result = 0;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
List<ParamBlockDoubled> CollWithoutDouble = new List<ParamBlockDoubled>();
List<BlockReference> DoubleToErase = new List<BlockReference>();
foreach (ObjectId id in bt)
{
BlockTableRecord btr =
(BlockTableRecord)tr.GetObject(id, OpenMode.ForWrite);
ObjectIdCollection idCol = btr.GetBlockReferenceIds(true, false);
foreach (ObjectId oId in idCol)
{
BlockReference br = (BlockReference)tr.GetObject(oId, OpenMode.ForRead, false);
ParamBlockDoubled pbd = new ParamBlockDoubled(br);
if (!CollWithoutDouble.Contains(pbd))
CollWithoutDouble.Add(pbd);
else
DoubleToErase.Add(br);
}
}
foreach (BlockReference b in DoubleToErase)
{
b.UpgradeOpen();
b.Erase();
result ++;
}
tr.Commit();
}
return result;
}
public struct ParamBlockDoubled
{
// fields
public ResultBuffer resBuf;
// constructor
public ParamBlockDoubled(BlockReference bRef)
{
Point3d pos = new Point3d(
Math.Round(bRef.Position.X, 6),
Math.Round(bRef.Position.Y, 6),
Math.Round(bRef.Position.Z, 6));
resBuf =
new ResultBuffer(
new TypedValue[8] {
new TypedValue(330, bRef.OwnerId),
new TypedValue(2, bRef.Name),
new TypedValue(10, pos),
new TypedValue(8, bRef.Layer),
new TypedValue(50, Math.Round(bRef.Rotation, 6)),
new TypedValue(40, Math.Round(bRef.ScaleFactors.X, 6)),
new TypedValue(41, Math.Round(bRef.ScaleFactors.Y, 6)),
new TypedValue(42, Math.Round(bRef.ScaleFactors.Z, 6))});
}
// override method
public override bool Equals(object obj)
{
if (obj.GetType() != typeof(ParamBlockDoubled))
return false;
ParamBlockDoubled pbd = (ParamBlockDoubled)obj;
return this.resBuf.Equals(pbd.resBuf);
}
public override int GetHashCode()
{
return base.GetHashCode();
}
}
}
}