Because doing more Revit secondary development, was a bit confused when getting Teigha. After reading examples still felt half-understood. Reason is not very clear about underlying logic of AutoCad, including hierarchical relationship between view and layout, relationship between block and view etc. Reading code is somewhat tiring.

Below use a case to talk about knowledge points organized yesterday.

  • teigha itself is Cad sub-item under ODA. Those in need can download from ODA official website or from CSDN link. There will be a trial period after application, can communicate with ODA email during this time.
  • Teigha itself follows AutoCad logic. if like me having Revit or other Autodesk development experience some are easier to understand, e.g. transaction
  • In CAD, Model Space, Layout 1 (Paper_Space), Layout 2 (Paper_Space), various Blocks <actually various blocks are regarded as a view in CAD. When we traverse components in model view, class of block is defined as ‘BlockReference’ from name can see this is a reference>, Yesterday I was trying to get internal component info of block in BlockReference, but had no clue. Later opened CAD clicked - Edit Block function, found it is parallel hierarchy with view. Background printing BlockTable found it inside
    Image Description
    Image Description
  • Still recommend understanding AutoCad API before using Teigha development, so can get started faster

Code below is a case of my querying Geometry info in a cad file, including extracting data from model view and extracting info from block.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Teigha.DatabaseServices;
using Teigha.Runtime;

namespace RdFileLayer
{
class Program
{
static void Main(string[] args)
{
using (Services serv = new Services())
{
var path = @"C:\Users\Desktop\Secondary Development\Teigha_cad_test.dwg";
using (Database db = new Database(false,false))
{
db.ReadDwgFile(path,FileShare.Read,false,null);
using (LayerTable pTable = (LayerTable)db.LayerTableId.GetObject(OpenMode.ForRead))
{
foreach (ObjectId id in pTable)
{
using (var tr = db.TransactionManager.StartTransaction())
{
LayerTableRecord record = (LayerTableRecord) tr.GetObject(id, OpenMode.ForRead);
Console.WriteLine("-------");
Console.WriteLine("<" + record.GetRXClass().Name + ">");
Console.WriteLine(record.Name);
Console.WriteLine("In Use" + record.IsUsed);
Console.WriteLine("Color" + record.Color);
Console.WriteLine("LineWeight" + record.LineWeight);
}
}
}

using (var tr = db.TransactionManager.StartTransaction())
{
using (var bTable = (BlockTable)db.BlockTableId.GetObject(OpenMode.ForRead))
{

foreach (ObjectId id in bTable)
{
var record = tr.GetObject(id, OpenMode.ForRead) as BlockTableRecord;
int count = 0;
// var objectId = bTable[BlockTableRecord.ModelSpace];
// BlockTableRecord record =
// (BlockTableRecord)tr.GetObject(objectId, OpenMode.ForRead);
Console.WriteLine("DB_BlockTableRecord Type is : "+record.Name);
if (record.Name == BlockTableRecord.ModelSpace|| record.Name == "Block")
{
Console.WriteLine("----------------" + record.Name + "----------------");
foreach (ObjectId id1 in record)
{
var entity = (Entity)tr.GetObject(id1, OpenMode.ForRead, false, true);
Console.WriteLine("Entity Type MutiType is : ");
Console.WriteLine("DB_Type : " + entity.GetType());
if (entity is Line)
{
var item = entity as Line;
Console.WriteLine("Line - " + count);
Console.WriteLine("Line 0" + item.StartPoint);
Console.WriteLine("Line 1" + item.EndPoint);
Console.WriteLine("Line Type Name" + item.Layer);
}
else if (entity is Polyline)
{
var item = entity as Polyline;
var allNums = item.NumberOfVertices;
Console.WriteLine("DB_PolyLine : ");
for (int i = 0; i < allNums; i++)
{
var subLine = item.GetLineSegmentAt(i);
Console.WriteLine("SubLine - " + i);
Console.WriteLine("SubLine 0" + subLine.StartPoint);
Console.WriteLine("SubLine 1" + subLine.EndPoint);
Console.WriteLine("SubLine Type Name" + item.Layer);
}
Console.WriteLine("DB_PolyLine Coordinates : " + "DB_PolyLine count is : " + item.NumberOfVertices);
for (int i = 0; i < item.NumberOfVertices; i++)
{
var vertex = item.GetPoint3dAt(i);
Console.WriteLine("SubVertex Coordinate index : " + i + " Location : " + vertex);
}
}
else if (entity is Circle cItem)
{
Console.WriteLine("DB_Circle original : " + cItem.Center);
Console.WriteLine("DB_Circle Radius is : " + cItem.Radius);
}
else if (entity is DBText item)
{
Console.WriteLine("DB_Text is :" + item.TextString);
Console.WriteLine("DB_Text Position : "+ item.Position);
}
else if (entity is MText mItem)
{
Console.WriteLine("DB_MText value is : " + mItem.Text);
Console.WriteLine("DB_MText position is : " + mItem.Location);
}



count++;
}
}

}
}
}



}
}

Console.Read();
}
}
}

08.25 Nested block extraction. Sometimes entire garage layer will be made into a block and parking space a separate block in a garage. When we want to extract info in parking space block, need to extract nested block. But when extracting nested block coordinates will change to internal coordinates of block, so need to perform coordinate transformation to get real coordinates. So best to start traversing from Model-Space to extract all data info, get block reference enter then correct coordinates. There might be several layers of nesting might need to add several layers. I haven’t tested this point.

code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
else if (entity is BlockReference bItem)
{
var angle = (bItem.Rotation * 180) / Math.PI;
Console.WriteLine("DB_BlockReference : " + bItem.Name);
Console.WriteLine("DB_BlockReference Location ; " + bItem.Position);
Console.WriteLine("DB_BlockReference Rotation : " + angle);
if (angle - 0.00 < 0.001)
{
var subTable =
bItem.Database.BlockTableId.GetObject(OpenMode.ForRead) as
BlockTable;
var fakeTable = (BlockTableRecord) tr.GetObject(bItem.BlockTableRecord,
OpenMode.ForRead);
Console.WriteLine("Fake_Table type name is : " + fakeTable.Name);
Console.WriteLine("Fake_Table type Location is : " + fakeTable.Origin);
foreach (ObjectId objectId in fakeTable)
{
var subTableRecord =
tr.GetObject(objectId, OpenMode.ForRead) as Entity;
Console.WriteLine("DB_Entity Type is : "+subTableRecord.GetType());
Console.WriteLine("SubRecord PolyLines Vertex is : ");
if (subTableRecord is Polyline pl)
{
for (int i = 0; i < pl.NumberOfVertices; i++)
{
var nPoint = new Point2d(pl.GetPoint2dAt(i).X+bItem.Position.X,pl.GetPoint2dAt(i).Y+bItem.Position.Y);
Console.WriteLine("polyLines vertex index is : " + nPoint);
}
}
// if (subTableRecord.Name.ToLower() == BlockTabl
// foreach (var id2 in subTableRecord)
// {eRecord.ModelSpace.ToLower())
// {
// var subEntity = tr.GetObject(id2, OpenMode.ForRead, false,
// false) as Entity;
// Console.WriteLine("DB_Entity Type is : "+entity.GetType());
// }
// }


}

}
}
  • All operations need to be in Services, Database, Transaction…. type of commands. Tried to create a separate dll for query command today found teigha error. Best to complete query in one class when using. Record first, wait until can write into interface then update interface code

08.26

  • When calculating data, to reduce coupling, extracted data to create another class, but still error. Backstage shows null pointer problem. Estimate still cannot extract data inside struct to other modules for processing. Now created a Point, Vector, Line class myself for data processing. If need others need to create more types.
  • First stage declared failure. My ultimate goal is to realize parking space modeling in Revit building drawings. Finally found the last obstacle is current designer’s block standard. Because parking space has direction, so even if we calculate offset point inside block, cannot quickly confirm base point and direction of parking space. Because I have already realized directly parsing parking space modeling of CADLinkType Geometry in Revit, thought of using CAD replacement found time loss and computer loss are both relatively large. Better follow original plan for modeling. QAQ. Next stage want to realize modeling function, possibly algorithm weight for parallel line segments and geometric position is relatively large inside. Share again when have time.