namespace MoveDetailSwamp
{
public class Class1
{
/// <summary>
/// Moves non-standard details into correct position(?)
/// </summary>
[CommandMethod("UPDATE_DETAILS")]
public static void UpdateDetails()
{
// - store the path of the drawing for save later:
string dwgPath = @"path\to\drawing.dwg";
// - Get the dwg db, fail early if not available with try/catch:
try {
using (var db
= new Database
(false,
true)) {
db.ReadDwgFile(dwgPath, System.IO.FileShare.ReadWrite, true, "");
// - turn off the 'metric' layer: (method returns a bool that you may want to use as a check?)
TurnLayerOff("METRIC", db);
// - Get a collection of any incorrect details and their bottom left corner locations
Dictionary<ObjectId, Point3d> dodgeyDetails = GetIncorrectDetailDict(db);
// - For each of the incorect details, transform them to 0,0,0
foreach(KeyValuePair<ObjectId, Point3d> entry in dodgeyDetails) {
MoveToOrigin(entry.Key, entry.Value, db);
}
// - save the modified drawing
db.SaveAs(dwgPath, DwgVersion.AC1024);
}
}
// change the exception type to be more specific if needed
catch(System.Exception e) {
// do something with the exception message
}
}
/// <summary>
/// Moves an entity from its given location to the origin (0,0,0)
/// </summary>
/// <param name="entId"></param>
/// <param name="location">Current location (or entity origin if you like) of entity</param>
/// <param name="db"></param>
private static void MoveToOrigin(ObjectId entId, Point3d location, Database db)
{
using (var tr = db.TransactionManager.StartTransaction()) {
var ent = tr.GetObject(entId, OpenMode.ForWrite) as Entity;
if (ent != null) {
// get the vector from the incorrect point to the origin (the direction we are going)
Vector3d moveVec = location.GetVectorTo(Point3d.Origin);
// move it:
ent.TransformBy(Matrix3d.Displacement(moveVec));
}
tr.commit();
}
}
/// <summary>
/// Loops through db ModelSpace to find details that are not in the correct location
/// (i.e. their bottom left corner is not at 0,0,0)
/// </summary>
/// <param name="db"></param>
/// <returns>A dictionary of ObjectIds as keys with the location of the incorrect detail as the value</returns>
private static Dictionary<ObjectId, Point3d> GetIncorrectDetailDict(Database db)
{
Dictionary
<ObjectId, Point3d
> details
= new Dictionary
<ObjectId, Point3d
>();
using (var tr = db.TransactionManager.StartTransaction()) {
var blockTable = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
if(blockTable != null) {
var blockTableRecord = tr.GetObject(blockTable[BlockTableRecord.ModelSpace], OpenMode.ForRead) as BlockTableRecord;
if(blockTableRecord != null) {
foreach(ObjectId entId in blockTableRecord) {
var ent = tr.GetObject(entId, OpenMode.ForRead) as Entity;
Polyline poly = ent as Polyline;
if(poly != null) {
// ----- CHECKING CODE ----- //
// change to suit if detail is not rectangular
Point3d btmLeft = poly.GeometricExtents.MinPoint;
if(btmLeft != Point3d.Origin) {
details.Add(entId, btmLeft);
}
}
}
}
}
}
tr.commit();
}
return details;
}
/// <summary>
/// Turns off a layer given the layer name passed in.
/// The layername must match that of the one in the symbol table to work(?).
/// </summary>
/// <param name="layerName">Name of the layer to turn off</param>
/// <param name="db">The database containing the layer</param>
/// <returns>A bool for checking success or not (if it's important)</returns>
private static bool TurnLayerOff(string layerName, Database db)
{
using (var tr = db.TransactionManager.StartTransaction()) {
var layerTable = tr.GetObject(db.LayerTableId, OpenMode.ForRead) as LayerTable;
if(layerTable != null) {
if (layerTable.Has(layerName)) {
var layerTableRecord = tr.GetObject(layerTable[layerName], OpenMode.ForWrite) as LayerTableRecord;
if (layerTableRecord != null) {
layerTableRecord.IsOff = true;
return layerTableRecord.IsOff;
}
}
}
tr.commit();
}
// if we get here, something went wrong, send notice of failure
return false;
}
}
}