Creating Block of Entities and blocks are not getting added into the layout

Creating Block of Entities and blocks are not getting added into the layout

Anonymous
Not applicable
990 Views
8 Replies
Message 1 of 9

Creating Block of Entities and blocks are not getting added into the layout

Anonymous
Not applicable

Hello,

 

 

1. I am creating a block of entities and place it at some point in drawing , but it gets placed at some distance from the given point.

2. The blocks created are not getting added in the layout. i want to at least add 3 blocks in a layout by scaling it down.

 

I have scaled the block accordingly but when i try to add the block in layout the block is not getting inserted in the particular layout as I am not able to get the points on the layout to insert the blocks. Is there any other way so that the the blocks can be inserted in layout automatically.?

 

0 Likes
991 Views
8 Replies
Replies (8)
Message 2 of 9

_gile
Consultant
Consultant

Hi,

 

It's quite impossible to help you with so few informations.

You should show some code and, perhaps, the block you try to insert.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 3 of 9

Anonymous
Not applicable

Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
Database db = doc.Database;
try
{
using (DocumentLock locDoc = ed.Document.LockDocument())
{
Transaction tr = db.TransactionManager.StartTransaction();
using (tr)
{
BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForWrite, false);
BlockTableRecord btr = new BlockTableRecord();
btr.Name = "BLOCK1";
bt.UpgradeOpen();
bt.Add(btr);
tr.AddNewlyCreatedDBObject(btr, true);
btr.Explodable = false;
Entity entity = (Entity)tr.GetObject(objectId, OpenMode.ForRead);
Entity entClone = entity.Clone() as Entity;

btr.AppendEntity(entClone);
tr.AddNewlyCreatedDBObject(entClone, true);
PromptPointResult pr = ed.GetPoint("\nEnter the insertion point: ");
if (pr.Status == PromptStatus.OK)
{
BlockTableRecord ms = bt[BlockTableRecord.ModelSpace].GetObject(OpenMode.ForWrite) as BlockTableRecord; BlockReference br = new BlockReference(pr.Value, btr.ObjectId);
ms.AppendEntity(br);
tr.AddNewlyCreatedDBObject(br, true); Autodesk.AutoCAD.ApplicationServices.Application.UpdateScreen();
}
tr.Commit();
}
}
}
catch (Autodesk.AutoCAD.Runtime.Exception e)
{}

 

 

 

 

/// I am creating a block of entities and place it at some point in drawing , but it gets placed at some distance from the given point.

0 Likes
Message 4 of 9

_gile
Consultant
Consultant

Hi

 

I see two possible reasons:


1. The current UCS is different from the GIS at the time of insertion (keep in mind that only Editor methods work about current UCS). This can be easily corrected by transforming the specified point:

BlockReference br = new BlockReference(pr.Value.TransformBy(ed.CurrentUserCoordinateSystem), btr.ObjectId);

 

2. The base point of the block is not correctly defined. The way you create the block definition (BlockTableRecord), the block base point is WCS origin.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 5 of 9

kerry_w_brown
Advisor
Advisor

 

just a casual observation :

 

What is this line accomplishing your end ?

 

 

Entity entity = (Entity)tr.GetObject(objectId, OpenMode.ForRead);

 

objectId variable doesn't seem to have a value in the code posted.

 

//-----------------

 

I can't follow the code logic ... but it's my holiday and probably my fault.

 

//-----------------

 

Personally I'd split the code  ; 

one method to assert that the BlockReference exists ( or build it )

one method to insert the block ...

 

easier to read 

and easier to test

therefore less heartache for you.

 

//-----------------

 

 

 

 


// Called Kerry or kdub in my other life.

Everything will work just as you expect it to, unless your expectations are incorrect. ~ kdub
Sometimes the question is more important than the answer. ~ kdub

NZST UTC+12 : class keyThumper<T> : Lazy<T>;      another  Swamper
0 Likes
Message 6 of 9

Anonymous
Not applicable

Thank You 🙂

0 Likes
Message 7 of 9

Anonymous
Not applicable

Hello,

 

I also having Problems adding blocks in layout. i have scaled the block and want add it in paper space.

the code below gives you the block reference of selected entities.

 

/////////////////////////////////////////////////////////////
public static BlockReference JoinEntitiesandScale(Point3d Point,double scale)
{
Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
PromptSelectionOptions opts = new PromptSelectionOptions();
opts.MessageForAdding = "Select entities: ";

PromptSelectionResult res = ed.GetSelection(opts);
SelectionSet selSet = res.Value;
ObjectId[] idArray = selSet.GetObjectIds();
BlockReference insert;
//ObjectId blockId = ObjectId.Null;
Transaction tr = db.TransactionManager.StartTransaction();
try
{
using (DocumentLock locDoc = ed.Document.LockDocument())
{
using (tr)
{
BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
//bt.UpgradeOpen();
BlockTableRecord record = new BlockTableRecord();
record.Name = "123";
bt.UpgradeOpen();
if (!bt.Has(record.Name))
{
ObjectId btrId = bt.Add(record);
tr.AddNewlyCreatedDBObject(record, true);
}
else
{
record = (BlockTableRecord)tr.GetObject(bt[record.Name], OpenMode.ForWrite);
}

ObjectIdCollection collection = new ObjectIdCollection(idArray);
IdMapping mapping = new IdMapping();
db.DeepCloneObjects(collection, record.ObjectId, mapping, false);

Matrix3d newscaleMatrix = Matrix3d.Scaling(scale, Point);
//BlockTableRecord btr = (BlockTableRecord)tr.GetObject(blockId, OpenMode.ForRead);
foreach (ObjectId entId in record)
{
DBObject obj = tr.GetObject(entId, OpenMode.ForRead);
Entity ent = obj as Entity;
if (ent != null)
{
ent.UpgradeOpen();
ent.TransformBy(newscaleMatrix);
ent.DowngradeOpen();
}
}
BlockTableRecord curSpace = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
insert = new BlockReference(Point, record.ObjectId);
curSpace.AppendEntity(insert);
tr.AddNewlyCreatedDBObject(insert, true);
tr.Commit();
}
}
if (insert != null)
{
return insert;
}
}
catch (System.Exception)
{
}
return null;
}

/////////////////////////////////////////////////////////////////////

after creating a block reference i want to add it in layout. my Code is.

////////////////////////////////////////////////////////////////

public static void Layout()
{
var doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
if (doc == null)
return;
var db = doc.Database;
var ed = doc.Editor;
try
{
Transaction tr = db.TransactionManager.StartTransaction();
using (tr)
{
PromptPointResult pr = ed.GetPoint("\nEnter table insertion point: ");
if (pr.Status == PromptStatus.OK)
{
DCS.RxServices.CADUtility.JoinEntitiesandScale(new Point3d(pr.Value.X, pr.Value.Y, 0), 0.25);

ObjectId id = LayoutManager.Current.CreateAndMakeLayoutCurrent("Plot", true);
Layout lay = (Layout)tr.GetObject(id, OpenMode.ForWrite);
lay.SetPlotSettings(
//"ISO_full_bleed_2A0_(1189.00_x_1682.00_MM)", // Try this big boy!
//"ANSI_B_(11.00_x_17.00_Inches)",
"ISO A4 (210.00 x 297.00 MM)",
"monochrome.ctb",
"DWGF6 ePlot.pc3"
);
}
tr.commit();
}


PromptSelectionOptions opts = new PromptSelectionOptions();
opts.MessageForAdding = "Select entities: ";
PromptSelectionResult res = ed.GetSelection(opts);
//1 block selected
if (res.Status == PromptStatus.OK)
{
SelectionSet selSet = res.Value;
ObjectId[] idArray = selSet.GetObjectIds();
Transaction tr1 = db.TransactionManager.StartTransaction();
using (tr1)
{

BlockTableRecord space = tr1.GetObject(SymbolUtilityServices.GetBlockPaperSpaceId(db), OpenMode.ForWrite) as BlockTableRecord;

foreach (ObjectId entId in idArray)
{
Entity entity = tr1.GetObject(entId, OpenMode.ForWrite) as Entity;
Entity entClone = entity.Clone() as Entity;
space.AppendEntity(entity);
tr1.AddNewlyCreatedDBObject(entity, true);
ObjectIdCollection collection = new ObjectIdCollection(idArray);
IdMapping mapping = new IdMapping();
db.DeepCloneObjects(collection, space.ObjectId, mapping, false);

entity.Erase();
}
tr1.Commit();

}
ed.Regen();
}
}
catch (Autodesk.AutoCAD.Runtime.Exception e)
{
}
}

///////////////////////////////////////////////////////

i want to add atleast 4 block in a layout by scaling it down. i have tried this using view ports and have created 4 viewports in a layout but is there any other way i can add blocks without using viewports.

 

 

Regards.

0 Likes
Message 8 of 9

_gile
Consultant
Consultant

Hi @Anonymous,

 

The following sample certainly doesn't exactly match your request (that I'm not sure to completely understand), but you should probably get some inspiration from it.

 

using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using AcAp = Autodesk.AutoCAD.ApplicationServices.Core.Application;

[assembly: CommandClass(typeof(MultiInsertInLayout.Commands))]

namespace MultiInsertInLayout
{
    public class Commands
    {
        [CommandMethod("Test")]
        public static void Test()
        {
            var doc = AcAp.DocumentManager.MdiActiveDocument;
            var db = doc.Database;
            Editor ed = doc.Editor;

            var selRes = ed.GetSelection();
            if (selRes.Status != PromptStatus.OK)
                return;

            var ptRes = ed.GetPoint("\nSpecify the base point: ");
            if (ptRes.Status != PromptStatus.OK)
                return;

            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                var btrId = CreateBlock("123", ptRes.Value.TransformBy(ed.CurrentUserCoordinateSystem), selRes.Value, true);
                var layout = ClearOrCreateLayout(db, "Plot");
                int nbInserts = MultiInsertInLayout(btrId, layout);
                ed.WriteMessage($"\nThe block has been inserted {nbInserts} times.");
                tr.Commit();
            }
        }

        private static ObjectId CreateBlock(string blockName, Point3d basePoint, SelectionSet selSet, bool convertToBlock)
        {
            var db = selSet[0].ObjectId.Database;
            var tr = db.TransactionManager.TopTransaction;
            var bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
            BlockTableRecord btr;
            ObjectId btrId;
            if (bt.Has("123"))
            {
                btrId = bt["123"];
                btr = (BlockTableRecord)tr.GetObject(btrId, OpenMode.ForWrite);
                foreach (ObjectId id in btr)
                {
                    var ent = (Entity)tr.GetObject(id, OpenMode.ForWrite);
                    ent.Erase();
                }
            }
            else
            {
                btr = new BlockTableRecord();
                btr.Name = "123";
                bt.UpgradeOpen();
                btrId = bt.Add(btr);
                tr.AddNewlyCreatedDBObject(btr, true);
            }
            var ids = new ObjectIdCollection(selSet.GetObjectIds());
            var mapping = new IdMapping();
            db.DeepCloneObjects(ids, btrId, mapping, false);
            var xform = Matrix3d.Displacement(basePoint.GetAsVector().Negate());
            foreach (IdPair pair in mapping)
            {
                if (pair.IsPrimary && pair.IsCloned)
                {
                    var ent = (Entity)tr.GetObject(pair.Value, OpenMode.ForWrite);
                    ent.TransformBy(xform);
                    if (convertToBlock)
                    {
                        var source = (Entity)tr.GetObject(pair.Key, OpenMode.ForWrite);
                        source.Erase();
                    }
                }
            }
            if (convertToBlock)
            {
                var curSpace = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
                var br = new BlockReference(basePoint, btrId);
                curSpace.AppendEntity(br);
                tr.AddNewlyCreatedDBObject(br, true);
            }

            return btrId;
        }

        private static Layout ClearOrCreateLayout(Database db, string layoutName)
        {
            var tr = db.TransactionManager.TopTransaction;
            var layoutDict = (DBDictionary)tr.GetObject(db.LayoutDictionaryId, OpenMode.ForRead);
            Layout layout;
            if (layoutDict.Contains(layoutName))
            {
                layout = (Layout)tr.GetObject(layoutDict.GetAt(layoutName), OpenMode.ForWrite);
            }
            else
            {
                var layoutId = LayoutManager.Current.CreateLayout(layoutName);
                layout = (Layout)tr.GetObject(layoutId, OpenMode.ForWrite);
            }
            LayoutManager.Current.CurrentLayout = layoutName;
            var btr = (BlockTableRecord)tr.GetObject(layout.BlockTableRecordId, OpenMode.ForRead);
            foreach (ObjectId id in btr)
            {
                var ent = (Entity)tr.GetObject(id, OpenMode.ForWrite);
                ent.Erase();
            }
            return layout;
        }

        private static int MultiInsertInLayout(ObjectId btrId, Layout layout)
        {
            var db = btrId.Database;
            var tr = db.TransactionManager.TopTransaction;

            // get the block definition extents and center
            var extents = new Extents3d();
            var btr = (BlockTableRecord)tr.GetObject(btrId, OpenMode.ForRead);
            foreach (ObjectId id in btr)
            {
                var ent = (Entity)tr.GetObject(id, OpenMode.ForRead);
                var bounds = ent.Bounds;
                if (bounds.HasValue)
                    extents.AddExtents(bounds.Value);
            }
            var blkWidth = extents.MaxPoint.X - extents.MinPoint.X;
            var blkHeight = extents.MaxPoint.Y - extents.MinPoint.Y;
            var blkCenter = new Point3d(
                (extents.MaxPoint.X + extents.MinPoint.X) / 2.0,
                (extents.MaxPoint.Y + extents.MinPoint.Y) / 2.0,
                0.0);

            // get the plot area extents
            var plotMargins = layout.PlotPaperMargins;
            double plotWidth = 0.0, plotHeight = 0.0;
            switch (layout.PlotRotation)
            {
                case PlotRotation.Degrees000:
                case PlotRotation.Degrees180:
                    plotWidth = layout.PlotPaperSize.X - plotMargins.MinPoint.X - plotMargins.MaxPoint.X;
                    plotHeight = layout.PlotPaperSize.Y - plotMargins.MinPoint.Y - plotMargins.MaxPoint.Y;
                    break;
                case PlotRotation.Degrees090:
                case PlotRotation.Degrees270:
                    plotWidth = layout.PlotPaperSize.Y - plotMargins.MinPoint.Y - plotMargins.MaxPoint.Y;
                    plotHeight = layout.PlotPaperSize.X - plotMargins.MinPoint.X - plotMargins.MaxPoint.X;
                    break;
            }

            // compute the scale so that the block can be inserted at least 4 times
            double scale = 1.0;
            while (plotWidth < 2.0 * scale * blkWidth || plotHeight < 2.0 * scale * blkHeight)
                scale /= 2.0;
            blkWidth *= scale;
            blkHeight *= scale;
            int columns = (int)(plotWidth / blkWidth);
            int rows = (int)(plotHeight / blkHeight);
            double colWidth = plotWidth / columns;
            double rowHeight = plotHeight / rows;

            // compute the displacement vector from block center to 'cell' center 
            var disp =
                new Vector3d(colWidth, rowHeight, 0.0) / 2.0 - blkCenter.GetAsVector() * scale;
                //new Vector3d(extents.MinPoint.X + extents.MaxPoint.X, extents.MinPoint.Y + extents.MaxPoint.Y, 0.0) * scale / 2.0;

            // insert the blocks
            var ps = (BlockTableRecord)tr.GetObject(layout.BlockTableRecordId, OpenMode.ForWrite);
            for (int i = 0; i < rows; i++)
            {
                for (int j = 0; j < columns; j++)
                {
                    Point3d insPt = new Point3d(layout.PlotOrigin.X + j * colWidth, layout.PlotOrigin.Y + i * rowHeight, 0.0);
                    var br = new BlockReference(insPt + disp, btr.ObjectId) { ScaleFactors = new Scale3d(scale) };
                    ps.AppendEntity(br);
                    tr.AddNewlyCreatedDBObject(br, true);
                }
            }
            return rows * columns;
        }
    }
}

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 9 of 9

Anonymous
Not applicable

thank u so much..... @_gile

0 Likes