• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

DomCR / ACadSharp / 16173659446

09 Jul 2025 03:31PM UTC coverage: 75.035% (-0.02%) from 75.05%
16173659446

Pull #699

github

web-flow
Merge 8b991a37e into 34177f0e8
Pull Request #699: anonymous blocks

5857 of 8583 branches covered (68.24%)

Branch coverage included in aggregate %.

39 of 49 new or added lines in 4 files covered. (79.59%)

6 existing lines in 1 file now uncovered.

23280 of 30248 relevant lines covered (76.96%)

81520.15 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

79.7
/src/ACadSharp/Tables/BlockRecord.cs
1
using ACadSharp.Attributes;
2
using ACadSharp.Types.Units;
3
using ACadSharp.Objects;
4
using ACadSharp.Blocks;
5
using ACadSharp.Entities;
6
using System.Linq;
7
using System.Collections.Generic;
8
using ACadSharp.Objects.Evaluations;
9
using CSMath;
10

11
namespace ACadSharp.Tables
12
{
13
        /// <summary>
14
        /// Represents a <see cref="BlockRecord"/> entry
15
        /// </summary>
16
        /// <remarks>
17
        /// Object name <see cref="DxfFileToken.TableBlockRecord"/> <br/>
18
        /// Dxf class name <see cref="DxfSubclassMarker.BlockRecord"/>
19
        /// </remarks>
20
        [DxfName(DxfFileToken.TableBlockRecord)]
21
        [DxfSubClass(DxfSubclassMarker.BlockRecord)]
22
        public class BlockRecord : TableEntry, IGeometricEntity
23
        {
24
                /// <summary>
25
                /// Create an instance of the *Model_Space block.
26
                /// </summary>
27
                /// <remarks>
28
                /// It only can be one Model in each document.
29
                /// </remarks>
30
                public static BlockRecord ModelSpace
31
                {
32
                        get
33
                        {
197✔
34
                                BlockRecord record = new BlockRecord(ModelSpaceName);
197✔
35

36
                                Layout layout = new Layout();
197✔
37
                                layout.Name = Layout.ModelLayoutName;
197✔
38
                                layout.AssociatedBlock = record;
197✔
39

40
                                return record;
197✔
41
                        }
197✔
42
                }
43

44
                /// <summary>
45
                /// Create an instance of the *Paper_Space block.
46
                /// </summary>
47
                /// <remarks>
48
                /// This is the default paper space in the document.
49
                /// </remarks>
50
                public static BlockRecord PaperSpace
51
                {
52
                        get
53
                        {
197✔
54
                                BlockRecord record = new BlockRecord(PaperSpaceName);
197✔
55

56
                                Layout layout = new Layout();
197✔
57
                                layout.Name = Layout.PaperLayoutName;
197✔
58
                                layout.AssociatedBlock = record;
197✔
59

60
                                return record;
197✔
61
                        }
197✔
62
                }
63

64
                /// <summary>
65
                /// Attribute definitions in this block
66
                /// </summary>
67
                public IEnumerable<AttributeDefinition> AttributeDefinitions
68
                {
69
                        get
70
                        {
22✔
71
                                return this.Entities.OfType<AttributeDefinition>();
22✔
72
                        }
22✔
73
                }
74

75
                /// <summary>
76
                /// End block entity for this Block record.
77
                /// </summary>
78
                public BlockEnd BlockEnd
79
                {
80
                        get { return this._blockEnd; }
81,150✔
81
                        internal set
82
                        {
26,862✔
83
                                this._blockEnd = value;
26,862✔
84
                                this._blockEnd.Owner = this;
26,862✔
85
                        }
26,862✔
86
                }
87

88
                /// <summary>
89
                /// Block entity for this record
90
                /// </summary>
91
                public Block BlockEntity
92
                {
93
                        get { return this._blockEntity; }
159,768✔
94
                        internal set
95
                        {
35,964✔
96
                                this._blockEntity = value;
35,964✔
97
                                this._blockEntity.Owner = this;
35,964✔
98
                        }
35,964✔
99
                }
100

101
                /// <summary>
102
                /// Specifies the scaling allowed for the block.
103
                /// </summary>
104
                [DxfCodeValue(DxfReferenceType.Optional, 281)]
105
                public bool CanScale { get; set; } = true;
29,435✔
106

107
                /// <summary>
108
                /// Entities owned by this block.
109
                /// </summary>
110
                /// <remarks>
111
                /// Entities with an owner cannot be added to another block.
112
                /// </remarks>
113
                public CadObjectCollection<Entity> Entities { get; private set; }
304,898✔
114

115
                /// <summary>
116
                /// Gets the evaluation graph for this block if it has dynamic properties attached to it.
117
                /// </summary>
118
                public EvaluationGraph EvaluationGraph
119
                {
120
                        get
121
                        {
13✔
122
                                if (this.XDictionary == null)
13!
123
                                {
×
124
                                        return null;
×
125
                                }
126
                                else if (this.XDictionary.TryGetEntry(EvaluationGraph.DictionaryEntryName, out EvaluationGraph table))
13!
127
                                {
13✔
128
                                        return table;
13✔
129
                                }
130
                                else
131
                                {
×
132
                                        return null;
×
133
                                }
134
                        }
13✔
135
                }
136

137
                //This seems to be the right way to set the flags for the block records
138
                public new BlockTypeFlags Flags { get { return this.BlockEntity.Flags; } set { this.BlockEntity.Flags = value; } }
44,253✔
139

140
                /// <summary>
141
                /// Flag indicating if the Block has Attributes attached
142
                /// </summary>
143
                public bool HasAttributes
144
                {
145
                        get
146
                        {
84✔
147
                                return this.Entities.OfType<AttributeDefinition>().Any();
84✔
148
                        }
84✔
149
                }
150

151
                /// <summary>
152
                /// Blocks with the anonymous flag set are managed by this library or the editing software, 
153
                /// this may affect the entities or the block properties.
154
                /// </summary>
155
                public bool IsAnonymous
156
                {
157
                        get
158
                        {
14,125✔
159
                                return (this.Flags & BlockTypeFlags.Anonymous) != 0;
14,125✔
160
                        }
14,125✔
161
                        set
162
                        {
27✔
163
                                if (value)
27!
NEW
164
                                {
×
NEW
165
                                        this.Flags |= BlockTypeFlags.Anonymous;
×
NEW
166
                                }
×
167
                                else
168
                                {
27✔
169
                                        this.Flags &= ~BlockTypeFlags.Anonymous;
27✔
170
                                }
27✔
171
                        }
27✔
172
                }
173

174
                /// <summary>
175
                /// Active flag if it has an <see cref="Objects.Evaluations.EvaluationGraph"/> attached to it with dynamic expressions.
176
                /// </summary>
177
                public bool IsDynamic
178
                {
179
                        get
180
                        {
13✔
181
                                return this.EvaluationGraph != null;
13✔
182
                        }
13✔
183
                }
184

185
                /// <summary>
186
                /// Specifies whether the block can be exploded.
187
                /// </summary>
188
                [DxfCodeValue(DxfReferenceType.Optional, 280)]
189
                public bool IsExplodable { get; set; }
6,997✔
190

191
                /// <summary>
192
                /// Associated Layout.
193
                /// </summary>
194
                [DxfCodeValue(DxfReferenceType.Handle, 340)]
195
                public Layout Layout
196
                {
197
                        get { return this._layout; }
3,480✔
198
                        internal set
199
                        {
4,046✔
200
                                this._layout = value;
4,046✔
201
                        }
4,046✔
202
                }
203

204
                /// <inheritdoc/>
205
                public override string ObjectName => DxfFileToken.TableBlockRecord;
24,102✔
206

207
                /// <inheritdoc/>
208
                public override ObjectType ObjectType => ObjectType.BLOCK_HEADER;
168✔
209

210
                /// <summary>
211
                /// DXF: Binary data for bitmap preview.
212
                /// </summary>
213
                /// <remarks>
214
                /// Optional
215
                /// </remarks>
216
                [DxfCodeValue(DxfReferenceType.Optional, 310)]
217
                public byte[] Preview { get; set; }
18,187✔
218

219
                /// <summary>
220
                /// Sort entities table for this block record.
221
                /// </summary>
222
                public SortEntitiesTable SortEntitiesTable
223
                {
224
                        get
225
                        {
10,631✔
226
                                if (this.XDictionary == null)
10,631✔
227
                                {
10,085✔
228
                                        return null;
10,085✔
229
                                }
230
                                else if (this.XDictionary.TryGetEntry(SortEntitiesTable.DictionaryEntryName, out SortEntitiesTable table))
546✔
231
                                {
388✔
232
                                        return table;
388✔
233
                                }
234
                                else
235
                                {
158✔
236
                                        return null;
158✔
237
                                }
238
                        }
10,631✔
239
                }
240

241
                /// <inheritdoc/>
242
                public override string SubclassMarker => DxfSubclassMarker.BlockRecord;
70,927✔
243

244
                /// <summary>
245
                /// Block insertion units
246
                /// </summary>
247
                // [DxfCodeValue(70)]        //Table entry uses flags and has the same code but dwg saves also the block record flags
248
                public UnitsType Units { get; set; }
2,836✔
249

250
                /// <summary>
251
                /// ViewPorts attached to this block
252
                /// </summary>
253
                public IEnumerable<Viewport> Viewports
254
                {
255
                        get
256
                        {
315✔
257
                                return this.Entities.OfType<Viewport>();
315✔
258
                        }
315✔
259
                }
260

261
                /// <summary>
262
                /// Default block record name for the model space
263
                /// </summary>
264
                public const string ModelSpaceName = "*Model_Space";
265

266
                /// <summary>
267
                /// Default block record name for the paper space
268
                /// </summary>
269
                public const string PaperSpaceName = "*Paper_Space";
270

271
                private BlockEnd _blockEnd;
272

273
                private Block _blockEntity;
274

275
                private Layout _layout;
276

277
                /// <summary>
278
                /// Default constructor.
279
                /// </summary>
280
                /// <param name="name">Unique name for this block record.</param>
281
                public BlockRecord(string name) : base(name)
5,254✔
282
                {
5,254✔
283
                        this.BlockEntity = new Block(this);
5,254✔
284
                        this.BlockEnd = new BlockEnd(this);
5,254✔
285
                        this.Entities = new CadObjectCollection<Entity>(this);
5,254✔
286
                }
5,254✔
287

288
                internal BlockRecord() : base()
17,184✔
289
                {
17,184✔
290
                        this.BlockEntity = new Block(this);
17,184✔
291
                        this.BlockEnd = new BlockEnd(this);
17,184✔
292
                        this.Entities = new CadObjectCollection<Entity>(this);
17,184✔
293
                }
17,184✔
294

295
                /// <inheritdoc/>
296
                public void ApplyTransform(Transform transform)
297
                {
×
298
                        foreach (Entity item in this.Entities)
×
299
                        {
×
300
                                item.ApplyTransform(transform);
×
301
                        }
×
302
                }
×
303

304
                /// <inheritdoc/>
305
                public override CadObject Clone()
306
                {
782✔
307
                        BlockRecord clone = (BlockRecord)base.Clone();
782✔
308

309
                        clone.Layout = null;
782✔
310

311
                        if (this.SortEntitiesTable != null)
782✔
312
                        {
47✔
313
                                clone.CreateSortEntitiesTable();
47✔
314
                        }
47✔
315

316
                        clone.Entities = new CadObjectCollection<Entity>(clone);
782✔
317
                        foreach (var item in this.Entities)
21,688✔
318
                        {
9,671✔
319
                                var e = (Entity)item.Clone();
9,671✔
320
                                clone.Entities.Add(e);
9,671✔
321

322
                                if (this.SortEntitiesTable != null
9,671✔
323
                                        && this.SortEntitiesTable.Select(s => s.Entity).Contains(item))
9,683✔
324
                                {
3✔
325
                                        clone.SortEntitiesTable.Add(e, this.SortEntitiesTable.GetSorterHandle(item));
3✔
326
                                }
3✔
327
                        }
9,671✔
328

329
                        clone.BlockEntity = (Block)this.BlockEntity.Clone();
782✔
330
                        clone.BlockEntity.Owner = clone;
782✔
331
                        clone.BlockEnd = (BlockEnd)this.BlockEnd.Clone();
782✔
332
                        clone.BlockEnd.Owner = clone;
782✔
333

334
                        return clone;
782✔
335
                }
782✔
336

337
                /// <summary>
338
                /// Create an entity sorter table for this block.
339
                /// </summary>
340
                /// <returns></returns>
341
                public SortEntitiesTable CreateSortEntitiesTable()
342
                {
50✔
343
                        CadDictionary dictionary = this.CreateExtendedDictionary();
50✔
344

345
                        if (dictionary.TryGetEntry(SortEntitiesTable.DictionaryEntryName, out SortEntitiesTable table))
50!
346
                        {
×
347
                                return table;
×
348
                        }
349

350
                        table = new SortEntitiesTable(this);
50✔
351

352
                        dictionary.Add(table);
50✔
353

354
                        return table;
50✔
355
                }
50✔
356

357
                /// <summary>
358
                /// Get the bounding box for all the entities in the block.
359
                /// </summary>
360
                /// <returns></returns>
361
                public BoundingBox GetBoundingBox()
362
                {
4✔
363
                        return this.GetBoundingBox(true);
4✔
364
                }
4✔
365

366
                /// <summary>
367
                /// Get the bounding box for all the entities in the block.
368
                /// </summary>
369
                /// <param name="ignoreInfinite">Ignore infinite entities, default: true</param>
370
                /// <returns></returns>
371
                public BoundingBox GetBoundingBox(bool ignoreInfinite)
372
                {
4✔
373
                        BoundingBox box = BoundingBox.Null;
4✔
374
                        foreach (var item in this.Entities)
60✔
375
                        {
24✔
376
                                if (item.GetBoundingBox().Extent == BoundingBoxExtent.Infinite
24!
377
                                        && ignoreInfinite)
24✔
378
                                {
×
379
                                        continue;
×
380
                                }
381

382
                                box = box.Merge(item.GetBoundingBox());
24✔
383
                        }
24✔
384

385
                        return box;
4✔
386
                }
4✔
387

388
                /// <summary>
389
                /// Get the entities in this block record sorted by it's handle and the sorter assigned if is present.
390
                /// </summary>
391
                /// <remarks>
392
                /// If the record is not in a document the entities will not be sorted unless there is a
393
                /// <see cref="SortEntitiesTable"/> assigned to the block.
394
                /// </remarks>
395
                /// <returns></returns>
396
                public IEnumerable<Entity> GetSortedEntities()
397
                {
×
398
                        if (this.SortEntitiesTable != null)
×
399
                        {
×
400
                                return this.Entities.OrderBy(e => e.Handle);
×
401
                        }
402

403
                        List<(ulong, Entity)> entities = new();
×
404

405
                        foreach (var entity in this.Entities)
×
406
                        {
×
407
                                ulong sorter = this.SortEntitiesTable.GetSorterHandle(entity);
×
408
                                entities.Add((sorter, entity));
×
409
                        }
×
410

411
                        return entities.OrderBy(e => e.Item1).Select(e => e.Item2);
×
412
                }
×
413

414
                internal override void AssignDocument(CadDocument doc)
415
                {
14,125✔
416
                        base.AssignDocument(doc);
14,125✔
417

418
                        doc.RegisterCollection(this.Entities);
14,125✔
419
                }
14,125✔
420

421
                internal override void UnassignDocument()
422
                {
5✔
423
                        this.Document.UnregisterCollection(this.Entities);
5✔
424

425
                        base.UnassignDocument();
5✔
426
                }
5✔
427
        }
428
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc