Best pratices to create and edit layer

Best pratices to create and edit layer

seabrahenrique
Advocate Advocate
911 Views
11 Replies
Message 1 of 12

Best pratices to create and edit layer

seabrahenrique
Advocate
Advocate

Hello everyone!

 

I face two options here to create/edit layers in AutoCAD using C#. Which one is the better thinking about the good practices:

 

Access my LayerTable direct for write, like this:

 

 

LayerTable lytab = trans.GetObject(db.LayerTableId, OpenMode.ForWrite) as LayerTable;

....Create or update my layer

 

 

 

Or access my LaterTable for read, and use the instruction lytab.UpgradeOpen(), like this:

 

 

LayerTable lytab = trans.GetObject(db.LayerTableId, OpenMode.ForRead) as LayerTable;

lytab.UpgradeOpen();

....Create or update my layer

 

 

 

I know that result of both is equals, but one is better of other? (thinking about erros, performance and etc...)

 

Thanks in advance.

0 Likes
Accepted solutions (1)
912 Views
11 Replies
Replies (11)
Message 2 of 12

seabrahenrique
Advocate
Advocate

And a complementar question:

 

I really need this foreach simply to find a layer in my LayerTable?

 

                    LayerTable lytb = trans.GetObject(db.LayerTableId, OpenMode.ForRead) as LayerTable;

                    foreach (ObjectId LyId in lytb)
                    {
                        LayerTableRecord ltbr = trans.GetObject(LyId, OpenMode.ForRead) as LayerTableRecord;

                        if (ltbr.Name == "Teste")
                        {
                            ltbr.UpgradeOpen(); 

                            ltbr.Color = Color.FromColorIndex(ColorMethod.ByLayer, 3);

                            LinetypeTable lttb = trans.GetObject(db.LinetypeTableId, OpenMode.ForRead) as LinetypeTable;
                            if (lttb.Has("Hidden"))
                            {
                                ltbr.LinetypeObjectId = lttb["Hidden"];
                            }

                            trans.Commit();
                            doc.Editor.WriteMessage("\nLayer alterado");
                            break;

                        }

 

Or is there another simple way to set a layer in my LayerTableRecord if i know that name?

 

For example, in VBA i can do:

Dim MyLayer as AcadLayer
MyLayer = ThisDrawing.Layer("NameOfLayer")

 

Can i do something similar in C# .NET to set a layer in a LayerTableRecord ltr, if i already know the name of layer is "NameOfLayer", for example?

 

Thanks again.

0 Likes
Message 3 of 12

hippe013
Advisor
Advisor

The get the layer objectId by name use the following:

(Sorry its in vb.net)

 

Dim lyrTbl As LayerTable = tr.GetObject(curDb.LayerTableId, OpenMode.ForRead)
Dim lyrId As ObjectId = lyrTbl.Item("MyLayer")

 

Message 4 of 12

norman.yuan
Mentor
Mentor

I am not sure what your were thinking of "best practice" with this code, where you have already known LayerTable.Has() method:

 

LayerTable lytb = trans.GetObject(db.LayerTableId, OpenMode.ForRead) as LayerTable;

                    foreach (ObjectId LyId in lytb)
                    {
                        LayerTableRecord ltbr = trans.GetObject(LyId, OpenMode.ForRead) as LayerTableRecord;

                        if (ltbr.Name == "Teste")
                        {
                            ltbr.UpgradeOpen(); 

                            ltbr.Color = Color.FromColorIndex(ColorMethod.ByLayer, 3);

                            LinetypeTable lttb = trans.GetObject(db.LinetypeTableId, OpenMode.ForRead) as LinetypeTable;
                            if (lttb.Has("Hidden"))
                            {
                                ltbr.LinetypeObjectId = lttb["Hidden"];
                            }

                            trans.Commit();
                            doc.Editor.WriteMessage("\nLayer alterado");
                            break;

                        }

 

 

if you already know a block name ("Teste"), you simply do:

var layerTable=(LayerTable)tran.GetObject(db.LayerTableId, OpenMode.ForRead);

LayerTableRecord layer;

if (!layerTable.Has("Teste")

{

    layerTable.UpgradeOpen();

    layer=new LayerTableRecord();

    layer.Name="Teste";

    layerTable.Add(layer);

    tran.AddNewlyCreatedDBObject(....);

}

else

{

    layer=(LayerTableRecord)tran.GetObject(layerTable["Teste", OpenMode.ForWrite);

}

 

// Change/Set layer's properties here

layer.Color=...;

layer.LineType=....;

 

Because of the method Has(), there is no need to loop through LayerTable for each LayerTableRecord and test its name in order to find the layer in interest.

 

 

 

 

Norman Yuan

Drive CAD With Code

EESignature

Message 5 of 12

seabrahenrique
Advocate
Advocate

Thanks for the collaboration, guys!

 

I already found watt i need here.

0 Likes
Message 6 of 12

hippe013
Advisor
Advisor

If you found what you needed please mark the appropriate reply as the accepted solution. It helps others know that a solution has been found. 

0 Likes
Message 7 of 12

MarkJamesRogolino
Advocate
Advocate

Pls try this.

var documentManager = Application.DocumentManager;
            var currentDocument = documentManager.MdiActiveDocument;
            var database = currentDocument.Database;
            ObjectId layerId = ObjectId.Null;
            using (DocumentLock docLock = currentDocument.LockDocument())
            {
                using (Transaction acTrans = database.TransactionManager.StartTransaction())
                {
                    // Open the Layer table for read
                    LayerTable acLyrTbl;
                    acLyrTbl = acTrans.GetObject(database.LayerTableId,
                                                 OpenMode.ForRead) as LayerTable;
                            LayerTableRecord acLyrTblRec = new LayerTableRecord();
                            acLyrTblRec.Name = "somename";
                            LinetypeTable acLinTbl;
                            acLinTbl = acTrans.GetObject(database.LinetypeTableId,
                                                               OpenMode.ForRead) as LinetypeTable;
                            acLyrTbl.UpgradeOpen();
                            acLyrTbl.Add(acLyrTblRec);
                            acTrans.AddNewlyCreatedDBObject(acLyrTblRec, true);
                    acTrans.Commit();
                }
            }
0 Likes
Message 8 of 12

kerry_w_brown
Advisor
Advisor

 

@MarkJamesRogolino 

Have you tested this code ?

what will happen if it's run twice ??

 

 


// 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
Message 9 of 12

seabrahenrique
Advocate
Advocate

Sorry, but i can't use your suggestion, see:

 

seabrahenrique_0-1667068282872.png

The LayerTable object here does not have the .Item method... Again, someone know how can i get a layer by a name in C#?

 

In VBA i used to do this:

 

Dim MyLayer as AcadLayer
MyLayer = ThisDrawing.Layer("NameOfLayer")

 

Is there a way to do something similar in .NET? I mean, if i already have the name of layer or block, can i access that using this name?

0 Likes
Message 10 of 12

kerry_w_brown
Advisor
Advisor

 

Perhaps something like this :

public void GetLayerByName( )
{            
    var db = Application.DocumentManager.MdiActiveDocument.Database;
    var layerName = "MyLayer";

    using (var tr = db.TransactionManager.StartTransaction())
    {
        var layerTable = (LayerTable)tr.GetObject(
                        db.LayerTableId, OpenMode.ForRead);

        var layerRecord = (LayerTableRecord)tr.GetObject( 
                            layerTable[layerName], OpenMode.ForRead);

        // if you really want the ObjectID  ??

        var layerRecordOid = layerRecord.ObjectId;
                
        // . . . . 

    } 
}

_kdub_0-1667072296230.png

 

Regards,

 


// 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 11 of 12

kerry_w_brown
Advisor
Advisor
Accepted solution

Of course, we should check that the LayerTable actually does have a Layer of that name  🙂

. . . or this will happen :

_kdub_0-1667074398102.png

 

public void GetLayerByName( )
{
    var db = Application.DocumentManager.MdiActiveDocument.Database;
    var layerName = "MyLayer_DoesNotExist";

    using ( var tr = db.TransactionManager.StartTransaction( ) )
    {
        var layerTable = (LayerTable)tr.GetObject(
                db.LayerTableId, OpenMode.ForRead);

        // ensure the layer exists !!
        if ( !layerTable.Has( layerName ) )
        {
            // show a message to the user.
            // then :
            return;
        }
        var layerRecord = (LayerTableRecord)tr.GetObject(
                    layerTable[layerName], OpenMode.ForRead);

        // if you really want the ObjectID  ??

        var layerRecordOid = layerRecord.ObjectId;

        // . . . .                 

    }
}

 

 

 


// 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 12 of 12

kerry_w_brown
Advisor
Advisor

For what it's worth ;

This is about 17 years old and posted more as proof of concept than professional code.

   

Making Layers with Particular Linetypes 

 

Regards,


// 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