Author Topic: LayerTableRecords on showing Used Layers  (Read 2972 times)

0 Members and 1 Guest are viewing this topic.

GumbyCAD

  • Newt
  • Posts: 84
LayerTableRecords on showing Used Layers
« on: May 05, 2014, 10:29:40 PM »
Hi,

I have found that when reading the layer table from an Open Drawing and from a side database you get different results.

When you read the Layer Table of an open Drawing you get all layers even unused ones.

However when you read the Layer Table from a side database you only get the used Layers.

Can anyone confim this?
(Or am i doing something wrong)

Stephan

Code - Visual Basic: [Select]
  1.         Using DocKock As DocumentLock = Doc.LockDocument
  2.  
  3.             Using db As Database = Doc.Database
  4.  
  5.                 Using tr As Transaction = db.TransactionManager.StartTransaction()
  6.  
  7.                     Dim lt As LayerTable = TryCast(tr.GetObject(db.LayerTableId, OpenMode.ForRead), LayerTable)
  8.  
  9.                     For Each layerId As ObjectId In lt
  10.  
  11.                         layer = TryCast(tr.GetObject(layerId, OpenMode.ForWrite), LayerTableRecord)
  12.                         Edd.WriteMessage(layer.Name & " Found In Current Drawing" & vbCrLf)
  13.  
  14.                     Next
  15.  
  16.                     tr.Commit()
  17.  
  18.                 End Using
  19.  
  20.             End Using
  21.  
  22.        End Using
  23.  

Code - Visual Basic: [Select]
  1.             Using DocKock As DocumentLock = CurrentDoc.LockDocument
  2.  
  3.                 SideDB = New Database(False, True)
  4.                 SideDB.ReadDwgFile(ExistingFileName, FileOpenMode.OpenForReadAndWriteNoShare, False, "")
  5.  
  6.                 Using SideDB
  7.  
  8.                     Dim layer As LayerTableRecord
  9.                     Using tr As Transaction = SideDB.TransactionManager.StartTransaction()
  10.  
  11.                         Dim lt As LayerTable = TryCast(tr.GetObject(SideDB.LayerTableId, OpenMode.ForWrite), LayerTable)
  12.  
  13.                         For Each layerId As ObjectId In lt
  14.  
  15.                             layer = TryCast(tr.GetObject(layerId, OpenMode.ForWrite), LayerTableRecord)
  16.                             Edd.WriteMessage("Analsysing Layer: " & layer.Name & vbCrLf)
  17.                  
  18.                         Next
  19.  
  20.                         tr.Commit()
  21.  
  22.                     End Using
  23.  
  24.                 End Using
  25.  
  26.             End Using
  27.  

Andrey Bushman

  • Swamp Rat
  • Posts: 864
Re: LayerTableRecords on showing Used Layers
« Reply #1 on: May 06, 2014, 02:44:29 AM »
Can anyone confim this?
I can't. Look the screen [the result of testing] below.
Code - C#: [Select]
  1. // © Andrey Bushman, 2014
  2. // LayerTableRecordTesting.cs
  3. // Testing of case: http://www.theswamp.org/index.php?topic=46980.0
  4. using System;
  5. using System.IO;
  6. using System.Collections.Generic;
  7. using System.Linq;
  8. using Mb = MbUnit.Framework;
  9. using cad = Autodesk.AutoCAD.ApplicationServices.Application;
  10. using Ap = Autodesk.AutoCAD.ApplicationServices;
  11. using Db = Autodesk.AutoCAD.DatabaseServices;
  12. using Ed = Autodesk.AutoCAD.EditorInput;
  13. using Rt = Autodesk.AutoCAD.Runtime;
  14. using Hs = Autodesk.AutoCAD.DatabaseServices.HostApplicationServices;
  15. using Us = Autodesk.AutoCAD.DatabaseServices.SymbolUtilityServices;
  16.  
  17. namespace Bushman.CAD.Testing {
  18.  
  19.   [Mb.TestFixture]
  20.   [Mb.Description("The LayerTableRecord count testing.")]
  21.   sealed class LayerTableRecordTesting {
  22.     const String fileName = @"C:\public\acad_test\test.dwg";
  23.     Int32 count = 0;
  24.     [Mb.FixtureSetUp]
  25.     [Mb.Description("Create DWG file if it not exist still.")]
  26.     private void SetUp() {
  27.       if (!File.Exists(fileName)) {
  28.         Db.Database prewDb = Hs.WorkingDatabase;
  29.         using (Db.Database db = new Db.Database(true, true)) {
  30.           Hs.WorkingDatabase = db;
  31.           using (Db.Transaction tr = db.TransactionManager.StartTransaction()) {
  32.             Db.LayerTable lt = tr.GetObject(db.LayerTableId,
  33.               Db.OpenMode.ForWrite) as Db.LayerTable;
  34.             Db.LayerTableRecord record = new Db.LayerTableRecord();
  35.             record.Name = "Test-Layer";
  36.             record.Description = "This layer was created for testing";
  37.             lt.Add(record);
  38.             tr.AddNewlyCreatedDBObject(record, true);
  39.  
  40.             Db.LayerTableRecord record2 = new Db.LayerTableRecord();
  41.             record2.Name = "Test-Layer-2";
  42.             record2.Description = "This layer was created for testing too";
  43.             lt.Add(record2);
  44.             tr.AddNewlyCreatedDBObject(record2, true);
  45.  
  46.             Db.Circle circle = new Db.Circle();
  47.             circle.SetDatabaseDefaults();
  48.             circle.Radius = 100;
  49.             circle.Center = new Autodesk.AutoCAD.Geometry.Point3d(0, 0, 0);
  50.             circle.LayerId = record.ObjectId;
  51.             cad.SetSystemVariable("CLAYER", record.Name);
  52.  
  53.             Db.BlockTableRecord model = tr.GetObject(Us.GetBlockModelSpaceId(db),
  54.               Db.OpenMode.ForWrite) as Db.BlockTableRecord;
  55.             model.AppendEntity(circle);
  56.             tr.AddNewlyCreatedDBObject(circle, true);
  57.  
  58.             IEnumerable<Db.ObjectId> layerIds = lt.Cast<Db.ObjectId>().Where(n =>
  59.             n.IsValid && !n.IsErased && !n.IsEffectivelyErased);
  60.             count = layerIds.Count();
  61.             tr.Commit();
  62.           }
  63.           db.SaveAs(fileName, Db.DwgVersion.Newest);
  64.           db.CloseInput(true);
  65.           Hs.WorkingDatabase = prewDb;
  66.         }
  67.       }
  68.     }
  69.  
  70.     [Mb.Test]
  71.     [Mb.Description("LayerTableRecord iteration for a Database.")]
  72.     private void DatabaseTesting() {
  73.       Db.Database prewDb = Hs.WorkingDatabase;
  74.       Int32 countDb = 0;
  75.       using (Db.Database db = new Db.Database(true, true)) {
  76.         db.ReadDwgFile(fileName, Db.FileOpenMode.OpenForReadAndReadShare, false,
  77.           String.Empty);
  78.         Hs.WorkingDatabase = db;
  79.         CheckLayerItems(db, ref countDb);
  80.         db.CloseInput(true);
  81.         Hs.WorkingDatabase = prewDb;
  82.       }
  83.       Mb.Assert.AreEqual<Int32>(count, countDb, "count != countDb.");
  84.     }
  85.  
  86.     [Mb.Test]
  87.     [Mb.Description("LayerTableRecord iteration for a Document.")]
  88.     private void DocumentTesting() {
  89.       Db.Database prewDb = Hs.WorkingDatabase;
  90.       Ap.Document doc = Ap.DocumentCollectionExtension.Add(cad.DocumentManager,
  91.         fileName);
  92.       Hs.WorkingDatabase = doc.Database;
  93.       Int32 countDwg = 0;
  94.       using (doc.LockDocument()) {
  95.         CheckLayerItems(doc.Database, ref countDwg);
  96.       }
  97.       Ap.DocumentExtension.CloseAndDiscard(doc);
  98.       Hs.WorkingDatabase = prewDb;
  99.       Mb.Assert.AreEqual<Int32>(count, countDwg, "count != countDwg.");
  100.     }
  101.  
  102.     [Mb.FixtureTearDown]
  103.     void RemoveTestDwg() {
  104.       if (File.Exists(fileName))
  105.         File.Delete(fileName);
  106.     }
  107.  
  108.     private static void CheckLayerItems(Db.Database db, ref Int32 count) {
  109.       using (Db.Transaction tr = db.TransactionManager.StartTransaction()) {
  110.         Db.LayerTable lt = tr.GetObject(db.LayerTableId, Db.OpenMode.ForRead)
  111.           as Db.LayerTable;
  112.         Console.WriteLine("Layer names:");
  113.         IEnumerable<Db.ObjectId> layerIds = lt.Cast<Db.ObjectId>().Where(n =>
  114.           n.IsValid && !n.IsErased && !n.IsEffectivelyErased);
  115.         foreach (Db.ObjectId id in layerIds) {
  116.           Db.LayerTableRecord ltr = tr.GetObject(id, Db.OpenMode.ForRead)
  117.             as Db.LayerTableRecord;
  118.           Console.WriteLine(ltr.Name);
  119.         }
  120.         Console.WriteLine("Layers count: {0}.", count = layerIds.Count());
  121.         tr.Commit();
  122.       }
  123.     }
  124.   }
  125. }

Quote
all layers even unused ones
Maybe you confuse the "Layer" concept with the "Layout"?
Quote
DocKock
Is it misprint?
Quote
Using db As Database = Doc.Database
Dispose will be called. You must never Dispose for the Document and its Database yourself (as I know). You need Dispose call if Database was opened as "new Database(...)" only.

Are you sure the WorkingDatabase has the same Database in your both cases?
« Last Edit: May 06, 2014, 06:50:35 AM by Andrey Bushman »

Andrey Bushman

  • Swamp Rat
  • Posts: 864
Re: LayerTableRecords on showing Used Layers
« Reply #2 on: May 06, 2014, 02:54:39 AM »
I have updated my previous message. Read the floor (about the Dispose & WorkingDatabase).

GumbyCAD

  • Newt
  • Posts: 84
Re: LayerTableRecords on showing Used Layers
« Reply #3 on: May 06, 2014, 03:08:24 AM »
DocLock is on purpose..... Sorry for the confusion.

I will double check my Code again thanks.

Andrey Bushman

  • Swamp Rat
  • Posts: 864
Re: LayerTableRecords on showing Used Layers
« Reply #4 on: May 06, 2014, 06:22:44 AM »
I have fixed some errors in my #1 post: I removed the memory leak (I added the using blocks for Database initialization). Also I have added the RemoveTestDwg method.

WILL HATCH

  • Bull Frog
  • Posts: 450
Re: LayerTableRecords on showing Used Layers
« Reply #5 on: May 06, 2014, 11:45:06 PM »
not a clue why you would be experiencing that. What version are you using?

Since your code is incomplete I wrote something to illustrate which copies the current file (apples to apples) and then uses it as a side database:
Code - C#: [Select]
  1.         [CommandMethod("testGetLayers")]
  2.         public void getLayers()
  3.         {
  4.             Document doc = Application.DocumentManager.MdiActiveDocument;
  5.             Editor ed = doc.Editor;
  6.             Database db = doc.Database;
  7.             string newPath = db.Filename.Replace(".dwg", "_copy.dwg");
  8.             File.Copy(db.Filename, newPath);
  9.             showLayers(db);
  10.             using (Database ndb = new Database(false, true))
  11.             {
  12.                 ndb.ReadDwgFile(newPath, FileOpenMode.OpenForReadAndAllShare, false, "");
  13.                 showLayers(ndb);
  14.                 ndb.CloseInput(true);
  15.             }
  16.             using (Database ndb = new Database(false, true))
  17.             {
  18.                 ndb.ReadDwgFile(newPath, FileOpenMode.OpenForReadAndAllShare, false, "");
  19.                 ndb.CloseInput(true);
  20.                 showLayers(ndb);
  21.             }
  22.         }
  23.         private void showLayers(Database db)
  24.         {
  25.             using (Transaction tr = db.TransactionManager.StartTransaction())
  26.             {
  27.                 string output = "Found layers in " + db.Filename +":";
  28.                 LayerTable lt = (LayerTable)tr.GetObject(db.LayerTableId, OpenMode.ForRead);
  29.                 foreach (ObjectId id in lt)
  30.                 {
  31.                     LayerTableRecord ltr = (LayerTableRecord)tr.GetObject(id, OpenMode.ForRead);
  32.                     output += "\n\t" + ltr.Name;
  33.                 }
  34.                 Application.ShowAlertDialog(output);
  35.                 tr.Commit();
  36.             }
  37.         }

WILL HATCH

  • Bull Frog
  • Posts: 450
Re: LayerTableRecords on showing Used Layers
« Reply #6 on: May 06, 2014, 11:51:49 PM »
DocKock

Who's there