using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.EditorInput;
// This line is not mandatory, but improves loading performances
[assembly: CommandClass(typeof(CloneToLayout.Utils))]
namespace CloneToLayout
{
public class Utils
{
[CommandMethod("CloneToLayout")]
public void CloneToLayout()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
if (doc == null) return;
Editor ed = doc.Editor;
Database db = doc.Database;
PromptSelectionResult rs = ed.GetSelection();
if (rs.Status != PromptStatus.OK) return;
ObjectIdCollection ids = new ObjectIdCollection(rs.Value.GetObjectIds());
testClone(ref ids);
}
public static void testClone(ref ObjectIdCollection ids)
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
Database db = doc.Database;
Extents3d ext = new Extents3d();
using (Transaction tr = doc.TransactionManager.StartTransaction())
{
foreach (ObjectId id in ids)
{
Entity ent = tr.GetObject(id, OpenMode.ForRead) as Entity;
if (ent != null) {
ext.AddExtents(ent.GeometricExtents);
}
}
// Центральная точка габаритов выбранных примитивов.
Point3d modelCenter = ext.MinPoint + (ext.MaxPoint - ext.MinPoint) * 0.5;
double modelHeight = ext.MaxPoint.Y - ext.MinPoint.Y;
double modelWidth = ext.MaxPoint.X - ext.MinPoint.X;
LayoutManager layman = LayoutManager.Current;
DBDictionary layoutDic = tr.GetObject(db.LayoutDictionaryId, OpenMode.ForRead) as DBDictionary;
double mScale = 1;
// Проходимся по всем листам (модель пропускаем)
foreach (DBDictionaryEntry entry in layoutDic)
{
Layout layout = tr.GetObject(entry.Value, OpenMode.ForRead) as Layout;
if (!layout.ModelType) // Это не модель
{
Extents3d extLayout = new Extents3d();
BlockTableRecord btrLayout = tr.GetObject(layout.BlockTableRecordId, OpenMode.ForRead) as BlockTableRecord;
// Находим габариты примитивов в листе - будем считать их рамкой листа.
foreach (ObjectId id in btrLayout)
{
Entity ent = tr.GetObject(id, OpenMode.ForRead) as Entity;
if (ent != null && !(ent is Viewport))
{
extLayout.AddExtents(ent.GeometricExtents);
}
}
// Центральная точка габаритов выбранных примитивов в листе
Point3d layoutCenter = extLayout.MinPoint + (extLayout.MaxPoint - extLayout.MinPoint) * 0.5;
double layoutHeight = extLayout.MaxPoint.Y - extLayout.MinPoint.Y;
double layoutWidth = extLayout.MaxPoint.X - extLayout.MinPoint.X;
// Находим масштабный коэффициент.
mScale = layoutWidth / modelWidth;
// Если масштабированная высота модели превышает высоту листа,
// то в качестве масштаба используем коэффициент на основе высоты
if (mScale * modelHeight > layoutHeight)
mScale = layoutHeight / modelHeight;
// Матрица масштабирования относительно центра в модели
Matrix3d matScale = Matrix3d.Scaling(mScale, modelCenter);
// Масштабируем старый центр в модели по этой матрице
Point3d modelCenterScaling = modelCenter.TransformBy(matScale);
// Находим матрицу переноса точки масштабированного центра в модели в точку
// центра листа
Matrix3d matDisp = Matrix3d.Displacement(layoutCenter - modelCenterScaling);
// Комбинированная матрица
Matrix3d matCompose = matScale.PreMultiplyBy(matDisp);
IdMapping idmap = new IdMapping();
btrLayout.UpgradeOpen();
db.DeepCloneObjects(ids, layout.BlockTableRecordId, idmap, false);
btrLayout.DowngradeOpen();
foreach (IdPair idpair in idmap)
{
if (idpair.IsPrimary)
{
Entity ent = tr.GetObject(idpair.Value, OpenMode.ForWrite) as Entity;
if (ent != null)
{
// Трансформируем по комбинированной матрице
ent.TransformBy(matCompose);
}
}
}
}
}
tr.Commit();
}
}
}
}