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

DomCR / ACadSharp / 14305968221

07 Apr 2025 09:41AM UTC coverage: 75.187% (-1.0%) from 76.181%
14305968221

push

github

DomCR
badge fix

5615 of 8186 branches covered (68.59%)

Branch coverage included in aggregate %.

22386 of 29056 relevant lines covered (77.04%)

72281.98 hits per line

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

67.32
/src/ACadSharp/Entities/Insert.cs
1
using ACadSharp.Attributes;
2
using ACadSharp.Tables;
3
using CSMath;
4
using CSUtilities.Extensions;
5
using System;
6
using System.Linq;
7
using System.Xml.Linq;
8

9
namespace ACadSharp.Entities
10
{
11
        /// <summary>
12
        /// Represents a <see cref="Insert"/> entity.
13
        /// </summary>
14
        /// <remarks>
15
        /// Object name <see cref="DxfFileToken.EntityInsert"/> <br/>
16
        /// Dxf class name <see cref="DxfSubclassMarker.Insert"/>
17
        /// </remarks>
18
        [DxfName(DxfFileToken.EntityInsert)]
19
        [DxfSubClass(DxfSubclassMarker.Insert)]
20
        public class Insert : Entity
21
        {
22
                /// <summary>
23
                /// Attributes from the block reference
24
                /// </summary>
25
                /// <remarks>
26
                /// If an attribute should be added in this collection a definition will be added into the block reference as well
27
                /// </remarks>
28
                public SeqendCollection<AttributeEntity> Attributes { get; private set; }
13,519✔
29

30
                /// <summary>
31
                /// Gets the insert block definition.
32
                /// </summary>
33
                [DxfCodeValue(DxfReferenceType.Name, 2)]
34
                public BlockRecord Block { get; internal set; }
11,543✔
35

36
                /// <summary>
37
                /// Column count
38
                /// </summary>
39
                [DxfCodeValue(DxfReferenceType.Optional, 70)]
40
                public ushort ColumnCount { get; set; } = 1;
7,451✔
41

42
                /// <summary>
43
                /// Column spacing
44
                /// </summary>
45
                [DxfCodeValue(DxfReferenceType.Optional, 44)]
46
                public double ColumnSpacing { get; set; } = 0;
7,193✔
47

48
                /// <summary>
49
                /// True if the insert has attribute entities in it
50
                /// </summary>
51
                [DxfCodeValue(DxfReferenceType.Ignored, 66)]
52
                public bool HasAttributes
53
                { get { return this.Attributes.Any(); } }
831✔
54

55
                /// <inheritdoc/>
56
                public override bool HasDynamicSubclass => true;
2✔
57

58
                /// <summary>
59
                /// A 3D WCS coordinate representing the insertion or origin point.
60
                /// </summary>
61
                [DxfCodeValue(10, 20, 30)]
62
                public XYZ InsertPoint { get; set; } = XYZ.Zero;
39,228✔
63

64
                /// <summary>
65
                /// Specifies the rotation angle for the object.
66
                /// </summary>
67
                public bool IsMultiple
68
                { get { return this.RowCount > 1 || this.ColumnCount > 1; } }
795✔
69

70
                /// <summary>
71
                /// Specifies the three-dimensional normal unit vector for the object.
72
                /// </summary>
73
                [DxfCodeValue(210, 220, 230)]
74
                public XYZ Normal { get; set; } = XYZ.AxisZ;
8,847✔
75

76
                /// <inheritdoc/>
77
                public override string ObjectName => DxfFileToken.EntityInsert;
393✔
78

79
                /// <inheritdoc/>
80
                public override ObjectType ObjectType
81
                {
82
                        get
83
                        {
17✔
84
                                if (this.RowCount > 1 || this.ColumnCount > 1)
17✔
85
                                {
16✔
86
                                        return ObjectType.MINSERT;
16✔
87
                                }
88
                                else
89
                                {
1✔
90
                                        return ObjectType.INSERT;
1✔
91
                                }
92
                        }
17✔
93
                }
94

95
                /// <summary>
96
                /// Specifies the rotation angle for the object.
97
                /// </summary>
98
                /// <value>
99
                /// The rotation angle in radians.
100
                /// </value>
101
                [DxfCodeValue(DxfReferenceType.IsAngle, 50)]
102
                public double Rotation { get; set; } = 0.0;
9,296✔
103

104
                /// <summary>
105
                /// Row count
106
                /// </summary>
107
                [DxfCodeValue(DxfReferenceType.Optional, 71)]
108
                public ushort RowCount { get; set; } = 1;
7,475✔
109

110
                /// <summary>
111
                /// Row spacing
112
                /// </summary>
113
                [DxfCodeValue(DxfReferenceType.Optional, 45)]
114
                public double RowSpacing { get; set; } = 0;
7,193✔
115

116
                /// <inheritdoc/>
117
                public override string SubclassMarker => this.IsMultiple ? DxfSubclassMarker.MInsert : DxfSubclassMarker.Insert;
257!
118

119
                /// <summary>
120
                /// X scale factor.
121
                /// </summary>
122
                [DxfCodeValue(41)]
123
                public double XScale
124
                {
125
                        get
126
                        {
311✔
127
                                return this._xscale;
311✔
128
                        }
311✔
129
                        set
130
                        {
3,753✔
131
                                if (value.Equals(0))
3,753✔
132
                                {
1✔
133
                                        string name = nameof(this.XScale);
1✔
134
                                        throw new ArgumentOutOfRangeException(name, value, $"{name} value must be none zero.");
1✔
135
                                }
136
                                this._xscale = value;
3,752✔
137
                        }
3,752✔
138
                }
139

140
                /// <summary>
141
                /// Y scale factor.
142
                /// </summary>
143
                [DxfCodeValue(42)]
144
                public double YScale
145
                {
146
                        get
147
                        {
275✔
148
                                return this._yscale;
275✔
149
                        }
275✔
150
                        set
151
                        {
3,549✔
152
                                if (value.Equals(0))
3,549✔
153
                                {
1✔
154
                                        string name = nameof(this.YScale);
1✔
155
                                        throw new ArgumentOutOfRangeException(name, value, $"{name} value must be none zero.");
1✔
156
                                }
157
                                this._yscale = value;
3,548✔
158
                        }
3,548✔
159
                }
160

161
                /// <summary>
162
                /// Z scale factor.
163
                /// </summary>
164
                [DxfCodeValue(43)]
165
                public double ZScale
166
                {
167
                        get
168
                        {
268✔
169
                                return this._zscale;
268✔
170
                        }
268✔
171
                        set
172
                        {
3,549✔
173
                                if (value.Equals(0))
3,549✔
174
                                {
1✔
175
                                        string name = nameof(this.ZScale);
1✔
176
                                        throw new ArgumentOutOfRangeException(name, value, $"{name} value must be none zero.");
1✔
177
                                }
178
                                this._zscale = value;
3,548✔
179
                        }
3,548✔
180
                }
181

182
                private double _xscale = 1;
6,903✔
183

184
                private double _yscale = 1;
6,903✔
185

186
                private double _zscale = 1;
6,903✔
187

188
                /// <summary>
189
                /// Constructor to reference an insert to a block record
190
                /// </summary>
191
                /// <param name="block">Block Record to reference</param>
192
                /// <exception cref="ArgumentNullException"></exception>
193
                public Insert(BlockRecord block) : this()
21✔
194
                {
21✔
195
                        if (block is null) throw new ArgumentNullException(nameof(block));
21!
196

197
                        if (block.Document != null)
21✔
198
                        {
2✔
199
                                this.Block = (BlockRecord)block.Clone();
2✔
200
                        }
2✔
201
                        else
202
                        {
19✔
203
                                this.Block = block;
19✔
204
                        }
19✔
205

206
                        foreach (var item in block.AttributeDefinitions)
69✔
207
                        {
3✔
208
                                this.Attributes.Add(new AttributeEntity(item));
3✔
209
                        }
3✔
210
                }
21✔
211

212
                internal Insert() : base()
6,903✔
213
                {
6,903✔
214
                        this.Attributes = new SeqendCollection<AttributeEntity>(this);
6,903✔
215
                }
6,903✔
216

217
                /// <inheritdoc/>
218
                public override void ApplyTransform(Transform transform)
219
                {
×
220
                        XYZ newPosition = transform.ApplyTransform(this.InsertPoint);
×
221
                        XYZ newNormal = this.transformNormal(transform, this.Normal);
×
222

223
                        Matrix3 transOW = Matrix3.ArbitraryAxis(this.Normal);
×
224
                        transOW *= Matrix3.RotationZ(this.Rotation);
×
225

226
                        Matrix3 transWO = Matrix3.ArbitraryAxis(newNormal);
×
227
                        transWO = transWO.Transpose();
×
228

229
                        var transformation = new Matrix3(transform.Matrix);
×
230
                        XYZ v = transOW * XYZ.AxisX;
×
231
                        v = transformation * v;
×
232
                        v = transWO * v;
×
233
                        double newRotation = new XY(v.X, v.Y).GetAngle();
×
234

235
                        transWO = Matrix3.RotationZ(newRotation).Transpose() * transWO;
×
236

237
                        XYZ s = transOW * new XYZ(this.XScale, this.YScale, this.ZScale);
×
238
                        s = transformation * s;
×
239
                        s = transWO * s;
×
240
                        XYZ newScale = new XYZ(
×
241
                                MathHelper.IsZero(s.X) ? MathHelper.Epsilon : s.X,
×
242
                                MathHelper.IsZero(s.Y) ? MathHelper.Epsilon : s.Y,
×
243
                                MathHelper.IsZero(s.Z) ? MathHelper.Epsilon : s.Z);
×
244

245
                        this.Normal = newNormal;
×
246
                        this.InsertPoint = newPosition;
×
247
                        this.XScale = newScale.X;
×
248
                        this.YScale = newScale.Y;
×
249
                        this.ZScale = newScale.Z;
×
250
                        this.Rotation = newRotation;
×
251

252
                        foreach (AttributeEntity att in this.Attributes)
×
253
                        {
×
254
                                att.ApplyTransform(transform);
×
255
                        }
×
256
                }
×
257

258
                /// <inheritdoc/>
259
                public override CadObject Clone()
260
                {
31✔
261
                        Insert clone = (Insert)base.Clone();
31✔
262

263
                        clone.Block = (BlockRecord)this.Block?.Clone();
31✔
264

265
                        clone.Attributes = new SeqendCollection<AttributeEntity>(clone);
31✔
266
                        foreach (var att in this.Attributes)
95✔
267
                        {
1✔
268
                                clone.Attributes.Add((AttributeEntity)att.Clone());
1✔
269
                        }
1✔
270

271
                        return clone;
31✔
272
                }
31✔
273

274
                /// <inheritdoc/>
275
                public override BoundingBox GetBoundingBox()
276
                {
3✔
277
                        BoundingBox box = this.Block.GetBoundingBox();
3✔
278

279
                        var scale = new XYZ(this.XScale, this.YScale, this.ZScale);
3✔
280
                        var min = box.Min * scale + this.InsertPoint;
3✔
281
                        var max = box.Max * scale + this.InsertPoint;
3✔
282

283
                        return new BoundingBox(min, max);
3✔
284
                }
3✔
285

286
                /// <summary>
287
                /// Get the transform that will be applied to the entities in the <see cref="BlockRecord"/> when this entity is processed.
288
                /// </summary>
289
                /// <returns></returns>
290
                public Transform GetTransform()
291
                {
1✔
292
                        XYZ scale = new XYZ(XScale, YScale, ZScale);
1✔
293

294
                        //TODO: Apply rotation
295
                        return new Transform(this.InsertPoint, scale, XYZ.Zero);
1✔
296
                }
1✔
297

298
                /// <summary>
299
                /// Updates all attribute definitions contained in the block reference as <see cref="AttributeDefinition"/> entities in the insert.
300
                /// </summary>
301
                /// <remarks>
302
                /// This will update the attributes based on their <see cref="AttributeBase.Tag"/>.
303
                /// </remarks>
304
                public void UpdateAttributes()
305
                {
×
306
                        var atts = this.Attributes.ToArray();
×
307

308
                        foreach (AttributeEntity att in atts)
×
309
                        {
×
310
                                //Tags are not unique, is it needed? check how the different applications link the atts
311
                                if (!this.Block.AttributeDefinitions.Select(d => d.Tag).Contains(att.Tag))
×
312
                                {
×
313
                                        this.Attributes.Remove(att);
×
314
                                }
×
315
                        }
×
316

317
                        foreach (AttributeDefinition attdef in this.Block.AttributeDefinitions)
×
318
                        {
×
319
                                if (!this.Attributes.Select(d => d.Tag).Contains(attdef.Tag))
×
320
                                {
×
321
                                        AttributeEntity att = new AttributeEntity(attdef);
×
322

323
                                        this.Attributes.Add(att);
×
324
                                }
×
325
                        }
×
326
                }
×
327

328
                internal override void AssignDocument(CadDocument doc)
329
                {
4,192✔
330
                        base.AssignDocument(doc);
4,192✔
331

332
                        doc.RegisterCollection(this.Attributes);
4,192✔
333

334
                        //Should only be triggered for internal use
335
                        if (this.Block == null)
4,192✔
336
                                return;
4,075✔
337

338
                        if (doc.BlockRecords.TryGetValue(this.Block.Name, out BlockRecord blk))
117✔
339
                        {
27✔
340
                                this.Block = blk;
27✔
341
                        }
27✔
342
                        else
343
                        {
90✔
344
                                doc.BlockRecords.Add(this.Block);
90✔
345
                        }
90✔
346
                }
4,192✔
347

348
                internal override void UnassignDocument()
349
                {
82✔
350
                        this.Block = (BlockRecord)this.Block.Clone();
82✔
351
                        this.Document.UnregisterCollection(this.Attributes);
82✔
352

353
                        base.UnassignDocument();
82✔
354
                }
82✔
355
        }
356
}
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