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

DomCR / ACadSharp / 13724323339

07 Mar 2025 03:53PM UTC coverage: 75.232% (-0.9%) from 76.11%
13724323339

Pull #457

github

web-flow
Merge af0c8b917 into a1ba04cda
Pull Request #457: Geometric transform

5481 of 8007 branches covered (68.45%)

Branch coverage included in aggregate %.

221 of 620 new or added lines in 40 files covered. (35.65%)

305 existing lines in 16 files now uncovered.

21808 of 28266 relevant lines covered (77.15%)

74119.66 hits per line

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

68.75
/src/ACadSharp/Entities/Insert.cs
1
using ACadSharp.Attributes;
2
using ACadSharp.Tables;
3
using CSMath;
4
using System;
5
using System.Linq;
6

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

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

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

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

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

53
                /// <inheritdoc/>
54
                public override bool HasDynamicSubclass => true;
2✔
55

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

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

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

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

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

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

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

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

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

117
                /// <summary>
118
                /// X scale factor.
119
                /// </summary>
120
                [DxfCodeValue(41)]
121
                public double XScale { get; set; } = 1;
10,953✔
122

123
                /// <summary>
124
                /// Y scale factor.
125
                /// </summary>
126
                [DxfCodeValue(42)]
127
                public double YScale { get; set; } = 1;
10,713✔
128

129
                /// <summary>
130
                /// Z scale factor.
131
                /// </summary>
132
                [DxfCodeValue(43)]
133
                public double ZScale { get; set; } = 1;
10,707✔
134

135
                /// <summary>
136
                /// Constructor to reference an insert to a block record
137
                /// </summary>
138
                /// <param name="block">Block Record to reference</param>
139
                /// <exception cref="ArgumentNullException"></exception>
140
                public Insert(BlockRecord block) : this()
19✔
141
                {
19✔
142
                        if (block is null) throw new ArgumentNullException(nameof(block));
19!
143

144
                        if (block.Document != null)
19✔
145
                        {
2✔
146
                                this.Block = (BlockRecord)block.Clone();
2✔
147
                        }
2✔
148
                        else
149
                        {
17✔
150
                                this.Block = block;
17✔
151
                        }
17✔
152

153
                        this.UpdateAttributes();
19✔
154
                }
19✔
155

156
                internal Insert() : base()
6,899✔
157
                {
6,899✔
158
                        this.Attributes = new SeqendCollection<AttributeEntity>(this);
6,899✔
159
                }
6,899✔
160

161
                /// <inheritdoc/>
162
                public override void ApplyTransform(Transform transform)
NEW
163
                {
×
NEW
164
                        XYZ newPosition = transform.ApplyTransform(this.InsertPoint);
×
NEW
165
                        XYZ newNormal = this.transformNormal(transform, this.Normal);
×
166

NEW
167
                        Matrix3 transOW = Matrix3.ArbitraryAxis(this.Normal);
×
NEW
168
                        transOW *= Matrix3.RotationZ(this.Rotation);
×
169

NEW
170
                        Matrix3 transWO = Matrix3.ArbitraryAxis(newNormal);
×
NEW
171
                        transWO = transWO.Transpose();
×
172

NEW
173
                        var transformation = new Matrix3(transform.Matrix);
×
NEW
174
                        XYZ v = transOW * XYZ.AxisX;
×
NEW
175
                        v = transformation * v;
×
NEW
176
                        v = transWO * v;
×
NEW
177
                        double newRotation = new XY(v.X, v.Y).GetAngle();
×
178

NEW
179
                        transWO = Matrix3.RotationZ(newRotation).Transpose() * transWO;
×
180

NEW
181
                        XYZ s = transOW * new XYZ(this.XScale, this.YScale, this.ZScale);
×
NEW
182
                        s = transformation * s;
×
NEW
183
                        s = transWO * s;
×
NEW
184
                        XYZ newScale = new XYZ(
×
NEW
185
                                MathHelper.IsZero(s.X) ? MathHelper.Epsilon : s.X,
×
NEW
186
                                MathHelper.IsZero(s.Y) ? MathHelper.Epsilon : s.Y,
×
NEW
187
                                MathHelper.IsZero(s.Z) ? MathHelper.Epsilon : s.Z);
×
188

NEW
189
                        this.Normal = newNormal;
×
NEW
190
                        this.InsertPoint = newPosition;
×
NEW
191
                        this.XScale = newScale.X;
×
NEW
192
                        this.YScale = newScale.Y;
×
NEW
193
                        this.ZScale = newScale.Z;
×
NEW
194
                        this.Rotation = newRotation;
×
195

NEW
196
                        foreach (AttributeEntity att in this.Attributes)
×
NEW
197
                        {
×
NEW
198
                                att.ApplyTransform(transform);
×
NEW
199
                        }
×
NEW
200
                }
×
201

202
                /// <inheritdoc/>
203
                public override CadObject Clone()
204
                {
29✔
205
                        Insert clone = (Insert)base.Clone();
29✔
206

207
                        clone.Block = (BlockRecord)this.Block?.Clone();
29✔
208

209
                        clone.Attributes = new SeqendCollection<AttributeEntity>(clone);
29✔
210
                        foreach (var att in this.Attributes)
89✔
211
                        {
1✔
212
                                clone.Attributes.Add((AttributeEntity)att.Clone());
1✔
213
                        }
1✔
214

215
                        return clone;
29✔
216
                }
29✔
217

218
                /// <inheritdoc/>
219
                public override BoundingBox GetBoundingBox()
220
                {
1✔
221
                        BoundingBox box = this.Block.BlockEntity.GetBoundingBox();
1✔
222

223
                        var scale = new XYZ(this.XScale, this.YScale, this.ZScale);
1✔
224
                        var min = box.Min * scale + this.InsertPoint;
1✔
225
                        var max = box.Max * scale + this.InsertPoint;
1✔
226

227
                        return new BoundingBox(min, max);
1✔
228
                }
1✔
229

230
                /// <summary>
231
                /// Updates all attribute definitions contained in the block reference as <see cref="AttributeDefinition"/> entitites in the insert
232
                /// </summary>
233
                public void UpdateAttributes()
234
                {
19✔
235
                        var atts = this.Attributes.ToArray();
19✔
236

237
                        foreach (AttributeEntity att in atts)
57!
238
                        {
×
239
                                //Tags are not unique, is it needed? check how the different applications link the atts
240
                                if (!this.Block.AttributeDefinitions.Select(d => d.Tag).Contains(att.Tag))
×
241
                                {
×
242
                                        this.Attributes.Remove(att);
×
243
                                }
×
244
                        }
×
245

246
                        foreach (AttributeDefinition attdef in this.Block.AttributeDefinitions)
59✔
247
                        {
1✔
248
                                if (!this.Attributes.Select(d => d.Tag).Contains(attdef.Tag))
1✔
249
                                {
1✔
250
                                        AttributeEntity att = new AttributeEntity(attdef);
1✔
251

252
                                        this.Attributes.Add(att);
1✔
253
                                }
1✔
254
                        }
1✔
255
                }
19✔
256

257
                internal override void AssignDocument(CadDocument doc)
258
                {
4,191✔
259
                        base.AssignDocument(doc);
4,191✔
260

261
                        doc.RegisterCollection(this.Attributes);
4,191✔
262

263
                        //Should only be triggered for internal use
264
                        if (this.Block == null)
4,191✔
265
                                return;
4,074✔
266

267
                        if (doc.BlockRecords.TryGetValue(this.Block.Name, out BlockRecord blk))
117✔
268
                        {
27✔
269
                                this.Block = blk;
27✔
270
                        }
27✔
271
                        else
272
                        {
90✔
273
                                doc.BlockRecords.Add(this.Block);
90✔
274
                        }
90✔
275
                }
4,191✔
276

277
                internal override void UnassignDocument()
278
                {
82✔
279
                        this.Block = (BlockRecord)this.Block.Clone();
82✔
280
                        this.Document.UnregisterCollection(this.Attributes);
82✔
281

282
                        base.UnassignDocument();
82✔
283
                }
82✔
284
        }
285
}
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