• 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

40.45
/src/ACadSharp/Entities/MText.cs
1
using ACadSharp.Attributes;
2
using ACadSharp.Tables;
3
using CSMath;
4
using System;
5
using System.Collections.Generic;
6

7
namespace ACadSharp.Entities
8
{
9
        /// <summary>
10
        /// Represents a <see cref="MText"/> entity.
11
        /// </summary>
12
        /// <remarks>
13
        /// Object name <see cref="DxfFileToken.EntityMText"/> <br/>
14
        /// Dxf class name <see cref="DxfSubclassMarker.MText"/>
15
        /// </remarks>
16
        [DxfName(DxfFileToken.EntityMText)]
17
        [DxfSubClass(DxfSubclassMarker.MText)]
18
        public partial class MText : Entity, IText
19
        {
20
                /// <inheritdoc/>
21
                public override ObjectType ObjectType => ObjectType.MTEXT;
1✔
22

23
                /// <inheritdoc/>
24
                public override string ObjectName => DxfFileToken.EntityMText;
1,334✔
25

26
                /// <inheritdoc/>
27
                public override string SubclassMarker => DxfSubclassMarker.MText;
126,038✔
28

29
                /// <summary>
30
                /// A 3D WCS coordinate representing the insertion or origin point.
31
                /// </summary>
32
                [DxfCodeValue(10, 20, 30)]
33
                public XYZ InsertPoint { get; set; } = XYZ.Zero;
57,291✔
34

35
                /// <summary>
36
                /// Specifies the three-dimensional normal unit vector for the object.
37
                /// </summary>
38
                [DxfCodeValue(210, 220, 230)]
39
                public XYZ Normal { get; set; } = XYZ.AxisZ;
16,544✔
40

41
                /// <inheritdoc/>
42
                [DxfCodeValue(40)]
43
                public double Height
44
                {
45
                        get => this._height;
751✔
46
                        set
47
                        {
11,360✔
48
                                if (value < 0)
11,360!
49
                                        throw new ArgumentOutOfRangeException("Height value cannot be negative.");
×
50
                                else
51
                                        this._height = value;
11,360✔
52
                        }
11,360✔
53
                }
54

55
                /// <summary>
56
                /// Reference rectangle width.
57
                /// </summary>
58
                [DxfCodeValue(41)]
59
                public double RectangleWidth { get; set; }
12,109✔
60

61
                /// <summary>
62
                /// Reference rectangle height.
63
                /// </summary>
64
                [DxfCodeValue(46)]
65
                public double RectangleHeight { get; set; }
7,722✔
66

67
                /// <summary>
68
                /// Attachment point
69
                /// </summary>
70
                [DxfCodeValue(71)]
71
                public AttachmentPointType AttachmentPoint { get; set; } = AttachmentPointType.TopLeft;
23,331✔
72

73
                /// <summary>
74
                /// Drawing direction
75
                /// </summary>
76
                [DxfCodeValue(72)]
77
                public DrawingDirectionType DrawingDirection { get; set; }
12,104✔
78

79
                /// <inheritdoc/>
80
                [DxfCodeValue(1)]
81
                public string Value { get; set; } = string.Empty;
35,153✔
82

83
                /// <inheritdoc/>
84
                [DxfCodeValue(DxfReferenceType.Name | DxfReferenceType.Optional, 7)]
85
                public TextStyle Style
86
                {
87
                        get { return this._style; }
36,570✔
88
                        set
89
                        {
4,758✔
90
                                if (value == null)
4,758!
91
                                {
×
92
                                        throw new ArgumentNullException(nameof(value));
×
93
                                }
94

95
                                if (this.Document != null)
4,758✔
96
                                {
4,527✔
97
                                        this._style = this.updateTable(value, this.Document.TextStyles);
4,527✔
98
                                }
4,527✔
99
                                else
100
                                {
231✔
101
                                        this._style = value;
231✔
102
                                }
231✔
103
                        }
4,758✔
104
                }
105

106
                /// <inheritdoc/>
107
                [DxfCodeValue(11, 21, 31)]
108
                public XYZ AlignmentPoint { get; set; }
13,047✔
109

110
                /// <summary>
111
                /// Horizontal width of the characters that make up the mtext entity.
112
                /// This value will always be equal to or less than the value of group code 41 
113
                /// </summary>
114
                /// <remarks>
115
                /// read-only, ignored if supplied
116
                /// </remarks>
117
                [DxfCodeValue(DxfReferenceType.Ignored, 42)]
118
                public double HorizontalWidth { get; set; } = 0.9;
11,366✔
119

120
                /// <summary>
121
                /// Vertical height of the mtext entity
122
                /// </summary>
123
                /// <remarks>
124
                /// read-only, ignored if supplied
125
                /// </remarks>
126
                [DxfCodeValue(DxfReferenceType.Ignored, 43)]
127
                public double VerticalHeight { get; set; } = 0.2;
11,366✔
128

129
                /// <summary>
130
                /// Specifies the rotation angle for the object.
131
                /// </summary>
132
                /// <value>
133
                /// The rotation angle in radians.
134
                /// </value>
135
                [DxfCodeValue(DxfReferenceType.IsAngle, 50)]
136
                public double Rotation { get; set; } = 0.0;
11,230✔
137

138
                /// <summary>
139
                /// Mtext line spacing style.
140
                /// </summary>
141
                [DxfCodeValue(73)]
142
                public LineSpacingStyleType LineSpacingStyle { get; set; }
11,458✔
143

144
                /// <summary>
145
                /// Mtext line spacing factor.
146
                /// </summary>
147
                /// <remarks>
148
                /// Percentage of default (3-on-5) line spacing to be applied.Valid values range from 0.25 to 4.00
149
                /// </remarks>
150
                [DxfCodeValue(44)]
151
                public double LineSpacing { get; set; } = 1.0;
22,688✔
152

153
                /// <summary>
154
                /// Background fill setting
155
                /// </summary>
156
                [DxfCodeValue(90)]
157
                public BackgroundFillFlags BackgroundFillFlags { get; set; } = BackgroundFillFlags.None;
18,601✔
158

159
                /// <summary>
160
                /// Determines how much border there is around the text.
161
                /// </summary>
162
                [DxfCodeValue(45)]
163
                public double BackgroundScale { get; set; } = 1.5;
11,621✔
164

165
                /// <summary>
166
                /// Background fill color 
167
                /// </summary>
168
                /// <remarks>
169
                /// Color to use for background fill when group code 90 is 1.
170
                /// </remarks>
171
                [DxfCodeValue(63, 420, 430)]
172
                public Color BackgroundColor { get; set; }
260✔
173

174
                /// <summary>
175
                /// Transparency of background fill color
176
                /// </summary>
177
                [DxfCodeValue(441)]
178
                public Transparency BackgroundTransparency { get; set; }
260✔
179

180
                public TextColumn Column { get; set; } = new TextColumn();
13,416✔
181

182
                public bool IsAnnotative { get; set; } = false;
12,608✔
183

184
                private double _height = 1.0;
11,225✔
185

186
                private TextStyle _style = TextStyle.Default;
11,225✔
187

188
                /// <inheritdoc/>
189
                public MText() : base() { }
33,675✔
190

191
                /// <inheritdoc/>
192
                public override void ApplyTransform(Transform transform)
NEW
193
                {
×
NEW
194
                        XYZ newInsert = transform.ApplyTransform(this.InsertPoint);
×
NEW
195
                        XYZ newNormal = this.transformNormal(transform, this.Normal);
×
196

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

NEW
199
                        transWO = transWO.Transpose();
×
200

NEW
201
                        List<XY> uv = applyRotation(
×
NEW
202
                                new[]
×
NEW
203
                                {
×
NEW
204
                                        XY.AxisX, XY.AxisY
×
NEW
205
                                },
×
NEW
206
                                this.Rotation);
×
207

208
                        XYZ v;
NEW
209
                        v = transOW * new XYZ(uv[0].X, uv[0].Y, 0.0);
×
NEW
210
                        v = transformation * v;
×
NEW
211
                        v = transWO * v;
×
NEW
212
                        XY newUvector = new XY(v.X, v.Y);
×
213

214
                        // the MText entity does not support non-uniform scaling
NEW
215
                        double scale = newUvector.GetLength();
×
216

NEW
217
                        v = transOW * new XYZ(uv[1].X, uv[1].Y, 0.0);
×
NEW
218
                        v = transformation * v;
×
NEW
219
                        v = transWO * v;
×
NEW
220
                        XY newVvector = new XY(v.X, v.Y);
×
221

NEW
222
                        double newRotation = newUvector.GetAngle();
×
223

NEW
224
                        if (XY.Cross(newUvector, newVvector) < 0.0)
×
NEW
225
                        {
×
NEW
226
                                if (newUvector.Dot(uv[0]) < 0.0)
×
NEW
227
                                {
×
NEW
228
                                        newRotation += 180;
×
229

NEW
230
                                        switch (this.AttachmentPoint)
×
231
                                        {
232
                                                case AttachmentPointType.TopLeft:
NEW
233
                                                        this.AttachmentPoint = AttachmentPointType.TopRight;
×
NEW
234
                                                        break;
×
235
                                                case AttachmentPointType.TopRight:
NEW
236
                                                        this.AttachmentPoint = AttachmentPointType.TopLeft;
×
NEW
237
                                                        break;
×
238
                                                case AttachmentPointType.MiddleLeft:
NEW
239
                                                        this.AttachmentPoint = AttachmentPointType.MiddleRight;
×
NEW
240
                                                        break;
×
241
                                                case AttachmentPointType.MiddleRight:
NEW
242
                                                        this.AttachmentPoint = AttachmentPointType.MiddleLeft;
×
NEW
243
                                                        break;
×
244
                                                case AttachmentPointType.BottomLeft:
NEW
245
                                                        this.AttachmentPoint = AttachmentPointType.BottomRight;
×
NEW
246
                                                        break;
×
247
                                                case AttachmentPointType.BottomRight:
NEW
248
                                                        this.AttachmentPoint = AttachmentPointType.BottomLeft;
×
NEW
249
                                                        break;
×
250
                                        }
NEW
251
                                }
×
252
                                else
NEW
253
                                {
×
NEW
254
                                        switch (this.AttachmentPoint)
×
255
                                        {
256
                                                case AttachmentPointType.TopLeft:
NEW
257
                                                        this.AttachmentPoint = AttachmentPointType.BottomLeft;
×
NEW
258
                                                        break;
×
259
                                                case AttachmentPointType.TopCenter:
NEW
260
                                                        this.AttachmentPoint = AttachmentPointType.BottomCenter;
×
NEW
261
                                                        break;
×
262
                                                case AttachmentPointType.TopRight:
NEW
263
                                                        this.AttachmentPoint = AttachmentPointType.BottomRight;
×
NEW
264
                                                        break;
×
265
                                                case AttachmentPointType.BottomLeft:
NEW
266
                                                        this.AttachmentPoint = AttachmentPointType.TopLeft;
×
NEW
267
                                                        break;
×
268
                                                case AttachmentPointType.BottomCenter:
NEW
269
                                                        this.AttachmentPoint = AttachmentPointType.TopCenter;
×
NEW
270
                                                        break;
×
271
                                                case AttachmentPointType.BottomRight:
NEW
272
                                                        this.AttachmentPoint = AttachmentPointType.TopRight;
×
NEW
273
                                                        break;
×
274
                                        }
NEW
275
                                }
×
NEW
276
                        }
×
277

NEW
278
                        double newHeight = this.Height * scale;
×
NEW
279
                        newHeight = MathHelper.IsZero(newHeight) ? MathHelper.Epsilon : newHeight;
×
280

NEW
281
                        this.InsertPoint = newInsert;
×
NEW
282
                        this.Normal = newNormal;
×
NEW
283
                        this.Rotation = newRotation;
×
NEW
284
                        this.Height = newHeight;
×
NEW
285
                        this.RectangleWidth *= scale;
×
NEW
286
                }
×
287

288
                /// <inheritdoc/>
289
                public override BoundingBox GetBoundingBox()
290
                {
5✔
291
                        return new BoundingBox(this.InsertPoint);
5✔
292
                }
5✔
293

294
                /// <summary>
295
                /// Get the text value separated in lines.
296
                /// </summary>
297
                /// <returns></returns>
298
                public string[] GetTextLines()
299
                {
2✔
300
                        return this.Value.Split(
2✔
301
                                new string[] { "\r\n", "\r", "\n", "\\P" },
2✔
302
                                StringSplitOptions.None
2✔
303
                        );
2✔
304
                }
2✔
305

306
                /// <inheritdoc/>
307
                public override CadObject Clone()
308
                {
123✔
309
                        MText clone = (MText)base.Clone();
123✔
310

311
                        clone.Style = (TextStyle)(this.Style?.Clone());
123!
312
                        clone.Column = this.Column?.Clone();
123!
313

314
                        return clone;
123✔
315
                }
123✔
316

317
                internal override void AssignDocument(CadDocument doc)
318
                {
11,246✔
319
                        base.AssignDocument(doc);
11,246✔
320

321
                        this._style = this.updateTable(this.Style, doc.TextStyles);
11,246✔
322

323
                        doc.DimensionStyles.OnRemove += this.tableOnRemove;
11,246✔
324
                }
11,246✔
325

326
                internal override void UnassignDocument()
327
                {
70✔
328
                        this.Document.DimensionStyles.OnRemove -= this.tableOnRemove;
70✔
329

330
                        base.UnassignDocument();
70✔
331

332
                        this.Style = (TextStyle)this.Style.Clone();
70✔
333
                }
70✔
334

335
                protected override void tableOnRemove(object sender, CollectionChangedEventArgs e)
336
                {
×
337
                        base.tableOnRemove(sender, e);
×
338

339
                        if (e.Item.Equals(this.Style))
×
340
                        {
×
341
                                this.Style = this.Document.TextStyles[TextStyle.DefaultName];
×
342
                        }
×
343
                }
×
344
        }
345
}
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