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

DomCR / ACadSharp / 14214082189

02 Apr 2025 07:34AM UTC coverage: 75.523% (-0.8%) from 76.343%
14214082189

Pull #457

github

web-flow
Merge b2c68aa3f into 04434c5d6
Pull Request #457: Geometric transform

5606 of 8150 branches covered (68.79%)

Branch coverage included in aggregate %.

282 of 716 new or added lines in 47 files covered. (39.39%)

318 existing lines in 23 files now uncovered.

22348 of 28864 relevant lines covered (77.43%)

72757.24 hits per line

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

31.4
/src/ACadSharp/Entities/TextEntity.cs
1
using ACadSharp.Attributes;
2
using ACadSharp.Tables;
3
using CSMath;
4
using CSUtilities.Extensions;
5
using System;
6
using System.Collections.Generic;
7

8
namespace ACadSharp.Entities
9
{
10
        /// <summary>
11
        /// Represents a <see cref="TextEntity"/>
12
        /// </summary>
13
        /// <remarks>
14
        /// Object name <see cref="DxfFileToken.EntityText"/> <br/>
15
        /// Dxf class name <see cref="DxfSubclassMarker.Text"/>
16
        /// </remarks>
17
        [DxfName(DxfFileToken.EntityText)]
18
        [DxfSubClass(DxfSubclassMarker.Text)]
19
        public class TextEntity : Entity, IText
20
        {
21
                /// <summary>
22
                /// Second alignment point (in OCS)
23
                /// </summary>
24
                /// <remarks>
25
                /// This value is meaningful only if the value of a 72 or 73 group is nonzero (if the justification is anything other than baseline/left)
26
                /// </remarks>
27
                [DxfCodeValue(DxfReferenceType.Optional, 11, 21, 31)]
28
                public XYZ AlignmentPoint { get; set; }
6,778✔
29

30
                /// <inheritdoc/>
31
                [DxfCodeValue(40)]
32
                public double Height
33
                {
34
                        get => _height;
965✔
35
                        set
36
                        {
20,541✔
37
                                if (value < 0)
20,541!
38
                                        throw new ArgumentOutOfRangeException("Height value cannot be negative.");
×
39
                                else
40
                                        this._height = value;
20,541✔
41
                        }
20,541✔
42
                }
43

44
                /// <summary>
45
                /// Horizontal text justification type.
46
                /// </summary>
47
                [DxfCodeValue(72)]
48
                public TextHorizontalAlignment HorizontalAlignment { get; set; } = TextHorizontalAlignment.Left;
22,375✔
49

50
                /// <summary>
51
                /// First alignment point(in OCS)
52
                /// </summary>
53
                [DxfCodeValue(10, 20, 30)]
54
                public XYZ InsertPoint { get; set; } = XYZ.Zero;
121,347✔
55

56
                /// <summary>
57
                /// Mirror flags.
58
                /// </summary>
59
                [DxfCodeValue(71)]
60
                public TextMirrorFlag Mirror { get; set; } = TextMirrorFlag.None;
22,296✔
61

62
                /// <summary>
63
                /// Specifies the three-dimensional normal unit vector for the object.
64
                /// </summary>
65
                [DxfCodeValue(210, 220, 230)]
66
                public XYZ Normal { get; set; } = XYZ.AxisZ;
26,370✔
67

68
                /// <inheritdoc/>
69
                public override string ObjectName => DxfFileToken.EntityText;
1,027✔
70

71
                /// <inheritdoc/>
72
                public override ObjectType ObjectType => ObjectType.TEXT;
17✔
73

74
                /// <summary>
75
                /// Specifies the oblique angle of the object.
76
                /// </summary>
77
                /// <value>
78
                /// The angle in radians within the range of -85 to +85 degrees. A positive angle denotes a lean to the right; a negative value will have 2*PI added to it to convert it to its positive equivalent.
79
                /// </value>
80
                [DxfCodeValue(DxfReferenceType.IsAngle, 51)]
81
                public double ObliqueAngle { get; set; } = 0.0;
22,236✔
82

83
                /// <summary>
84
                /// Specifies the rotation angle for the object.
85
                /// </summary>
86
                /// <value>
87
                /// The rotation angle in radians.
88
                /// </value>
89
                [DxfCodeValue(DxfReferenceType.IsAngle, 50)]
90
                public double Rotation { get; set; }
2,168✔
91

92
                /// <inheritdoc/>
93
                [DxfCodeValue(DxfReferenceType.Name | DxfReferenceType.Optional, 7)]
94
                public TextStyle Style
95
                {
96
                        get { return this._style; }
41,265✔
97
                        set
98
                        {
7,622✔
99
                                if (value == null)
7,622!
100
                                {
×
101
                                        throw new ArgumentNullException(nameof(value));
×
102
                                }
103

104
                                if (this.Document != null)
7,622✔
105
                                {
6,729✔
106
                                        this._style = this.updateTable(value, this.Document.TextStyles);
6,729✔
107
                                }
6,729✔
108
                                else
109
                                {
893✔
110
                                        this._style = value;
893✔
111
                                }
893✔
112
                        }
7,622✔
113
                }
114

115
                /// <inheritdoc/>
116
                public override string SubclassMarker => DxfSubclassMarker.Text;
126,610✔
117

118
                /// <summary>
119
                /// Specifies the distance a 2D object is extruded above or below its elevation.
120
                /// </summary>
121
                [DxfCodeValue(39)]
122
                public double Thickness { get; set; } = 0.0;
25,418✔
123

124
                /// <inheritdoc/>
125
                /// <value>
126
                /// The maximum length is 256 characters.
127
                /// </value>
128
                [DxfCodeValue(1)]
129
                public string Value
130
                {
131
                        get
132
                        {
965✔
133
                                return _value;
965✔
134
                        }
965✔
135
                        set
136
                        {
20,518✔
137
                                if (value.Length > 256)
20,518!
NEW
138
                                        throw new ArgumentException($"Text length cannot be supiror than 256, current: {value.Length}");
×
139
                                else
140
                                        this._value = value;
20,518✔
141
                        }
20,518✔
142
                }
143

144
                /// <summary>
145
                /// Vertical text justification type.
146
                /// </summary>
147
                [DxfCodeValue(DxfReferenceType.Optional, 73)]
148
                public virtual TextVerticalAlignmentType VerticalAlignment { get; set; } = TextVerticalAlignmentType.Baseline;
21,798✔
149

150
                /// <summary>
151
                /// Relative X scale factor—widt
152
                /// </summary>
153
                /// <remarks>
154
                /// This value is also adjusted when fit-type text is used
155
                /// </remarks>
156
                [DxfCodeValue(DxfReferenceType.Optional, 41)]
157
                public double WidthFactor { get; set; } = 1.0;
22,237✔
158

159
                private double _height = 0.0;
20,548✔
160
                private TextStyle _style = TextStyle.Default;
20,548✔
161
                private string _value = string.Empty;
20,548✔
162

163
                public TextEntity() : base()
20,548✔
164
                {
20,548✔
165
                }
20,548✔
166

167
                /// <inheritdoc/>
168
                public override void ApplyTransform(Transform transform)
UNCOV
169
                {
×
NEW
170
                        bool mirrText = this.Mirror.HasFlag(TextMirrorFlag.Backward);
×
171

NEW
172
                        XYZ newInsert = transform.ApplyTransform(this.InsertPoint);
×
NEW
173
                        XYZ newNormal = this.transformNormal(transform, this.Normal);
×
174

NEW
175
                        var transformation = this.getWorldMatrix(transform, Normal, newNormal, out Matrix3 transOW, out Matrix3 transWO);
×
176

NEW
177
                        List<XY> uv = applyRotation(
×
NEW
178
                                new[]
×
NEW
179
                                {
×
NEW
180
                                        this.WidthFactor * this.Height * XY.AxisX,
×
NEW
181
                                        new XY(this.Height * Math.Tan(this.ObliqueAngle), this.Height)
×
NEW
182
                                },
×
NEW
183
                                this.Rotation);
×
184

185
                        XYZ v;
NEW
186
                        v = transOW * new XYZ(uv[0].X, uv[0].Y, 0.0);
×
NEW
187
                        v = transformation * v;
×
NEW
188
                        v = transWO * v;
×
NEW
189
                        XY newUvector = new XY(v.X, v.Y);
×
190

NEW
191
                        v = transOW * new XYZ(uv[1].X, uv[1].Y, 0.0);
×
NEW
192
                        v = transformation * v;
×
NEW
193
                        v = transWO * v;
×
NEW
194
                        XY newVvector = new XY(v.X, v.Y);
×
195

NEW
196
                        double newRotation = newUvector.GetAngle();
×
NEW
197
                        double newObliqueAngle = newVvector.GetAngle();
×
198

NEW
199
                        if (mirrText)
×
NEW
200
                        {
×
NEW
201
                                if (XY.Cross(newUvector, newVvector) < 0)
×
NEW
202
                                {
×
NEW
203
                                        newObliqueAngle = 90 - (newRotation - newObliqueAngle);
×
NEW
204
                                        if (!(this.HorizontalAlignment.HasFlag(TextHorizontalAlignment.Fit)
×
NEW
205
                                                || this.HorizontalAlignment.HasFlag(TextHorizontalAlignment.Aligned)))
×
NEW
206
                                        {
×
NEW
207
                                                newRotation += 180;
×
NEW
208
                                        }
×
209

NEW
210
                                        this.Mirror = this.Mirror.RemoveFlag(TextMirrorFlag.Backward);
×
NEW
211
                                }
×
212
                                else
NEW
213
                                {
×
NEW
214
                                        newObliqueAngle = 90 + (newRotation - newObliqueAngle);
×
NEW
215
                                }
×
NEW
216
                        }
×
217
                        else
NEW
218
                        {
×
NEW
219
                                if (XY.Cross(newUvector, newVvector) < 0.0)
×
NEW
220
                                {
×
NEW
221
                                        newObliqueAngle = 90 - (newRotation - newObliqueAngle);
×
222

NEW
223
                                        if (newUvector.Dot(uv[0]) < 0.0)
×
NEW
224
                                        {
×
NEW
225
                                                newRotation += 180;
×
226

NEW
227
                                                switch (this.HorizontalAlignment)
×
228
                                                {
229
                                                        case TextHorizontalAlignment.Left:
NEW
230
                                                                this.HorizontalAlignment = TextHorizontalAlignment.Right;
×
NEW
231
                                                                break;
×
232
                                                        case TextHorizontalAlignment.Right:
NEW
233
                                                                this.HorizontalAlignment = TextHorizontalAlignment.Left;
×
NEW
234
                                                                break;
×
235
                                                }
NEW
236
                                        }
×
237
                                        else
NEW
238
                                        {
×
NEW
239
                                                switch (this.VerticalAlignment)
×
240
                                                {
241
                                                        case TextVerticalAlignmentType.Top:
NEW
242
                                                                this.VerticalAlignment = TextVerticalAlignmentType.Bottom;
×
NEW
243
                                                                break;
×
244
                                                        case TextVerticalAlignmentType.Bottom:
NEW
245
                                                                this.VerticalAlignment = TextVerticalAlignmentType.Top;
×
NEW
246
                                                                break;
×
247
                                                }
NEW
248
                                        }
×
NEW
249
                                }
×
250
                                else
NEW
251
                                {
×
NEW
252
                                        newObliqueAngle = 90 + (newRotation - newObliqueAngle);
×
NEW
253
                                }
×
NEW
254
                        }
×
255

256
                        // the oblique angle is defined between -85 and 85 degrees
NEW
257
                        newObliqueAngle = MathHelper.NormalizeAngle(newObliqueAngle);
×
NEW
258
                        if (newObliqueAngle > 180)
×
NEW
259
                        {
×
NEW
260
                                newObliqueAngle = 180 - newObliqueAngle;
×
NEW
261
                        }
×
262

NEW
263
                        if (newObliqueAngle < -85)
×
NEW
264
                        {
×
NEW
265
                                newObliqueAngle = -85;
×
NEW
266
                        }
×
NEW
267
                        else if (newObliqueAngle > 85)
×
NEW
268
                        {
×
NEW
269
                                newObliqueAngle = 85;
×
NEW
270
                        }
×
271

272
                        // the height must be greater than zero, the cos is always positive between -85 and 85
NEW
273
                        double newHeight = newVvector.GetLength() * Math.Cos(newObliqueAngle);
×
NEW
274
                        newHeight = MathHelper.IsZero(newHeight) ? MathHelper.Epsilon : newHeight;
×
275

276
                        // the width factor is defined between 0.01 and 100
NEW
277
                        double newWidthFactor = newUvector.GetLength() / newHeight;
×
NEW
278
                        if (newWidthFactor < 0.01)
×
NEW
279
                        {
×
NEW
280
                                newWidthFactor = 0.01;
×
NEW
281
                        }
×
NEW
282
                        else if (newWidthFactor > 100)
×
NEW
283
                        {
×
NEW
284
                                newWidthFactor = 100;
×
NEW
285
                        }
×
286

NEW
287
                        this.InsertPoint = newInsert;
×
NEW
288
                        this.Normal = newNormal;
×
NEW
289
                        this.Rotation = newRotation;
×
NEW
290
                        this.Height = newHeight;
×
NEW
291
                        this.WidthFactor = newWidthFactor;
×
NEW
292
                        this.ObliqueAngle = newObliqueAngle;
×
UNCOV
293
                }
×
294

295
                /// <inheritdoc/>
296
                public override CadObject Clone()
297
                {
136✔
298
                        TextEntity clone = (TextEntity)base.Clone();
136✔
299
                        clone.Style = (TextStyle)this.Style.Clone();
136✔
300
                        return clone;
136✔
301
                }
136✔
302

303
                /// <inheritdoc/>
304
                public override BoundingBox GetBoundingBox()
305
                {
7✔
306
                        return new BoundingBox(this.InsertPoint);
7✔
307
                }
7✔
308

309
                internal override void AssignDocument(CadDocument doc)
310
                {
12,236✔
311
                        base.AssignDocument(doc);
12,236✔
312

313
                        this._style = this.updateTable(this.Style, doc.TextStyles);
12,236✔
314

315
                        doc.DimensionStyles.OnRemove += this.tableOnRemove;
12,236✔
316
                }
12,236✔
317

318
                internal override void UnassignDocument()
319
                {
434✔
320
                        this.Document.DimensionStyles.OnRemove -= this.tableOnRemove;
434✔
321

322
                        base.UnassignDocument();
434✔
323

324
                        this.Style = (TextStyle)this.Style.Clone();
434✔
325
                }
434✔
326

327
                protected override void tableOnRemove(object sender, CollectionChangedEventArgs e)
328
                {
×
329
                        base.tableOnRemove(sender, e);
×
330

331
                        if (e.Item.Equals(this.Style))
×
332
                        {
×
333
                                this.Style = this.Document.TextStyles[TextStyle.DefaultName];
×
334
                        }
×
335
                }
×
336
        }
337
}
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

© 2025 Coveralls, Inc