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

DomCR / ACadSharp / 18340262304

08 Oct 2025 09:31AM UTC coverage: 78.218% (+0.3%) from 77.952%
18340262304

Pull #774

github

web-flow
Merge f64ad8664 into 2472105ef
Pull Request #774: patterns def

6849 of 9511 branches covered (72.01%)

Branch coverage included in aggregate %.

157 of 215 new or added lines in 9 files covered. (73.02%)

15 existing lines in 2 files now uncovered.

26368 of 32956 relevant lines covered (80.01%)

108752.8 hits per line

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

84.31
/src/ACadSharp/Entities/HatchPattern.cs
1
using ACadSharp.Attributes;
2
using CSMath;
3
using CSUtilities.Extensions;
4
using System;
5
using System.Collections.Generic;
6
using System.Globalization;
7
using System.IO;
8
using System.Linq;
9
using System.Text;
10

11
namespace ACadSharp.Entities
12
{
13
        public partial class HatchPattern
14
        {
15
                public static HatchPattern Solid { get { return new HatchPattern("SOLID"); } }
8,877✔
16

17
                [DxfCodeValue(2)]
18
                public string Name { get; set; }
8,182✔
19

20
                /// <summary>
21
                /// Description for this pattern.
22
                /// </summary>
23
                /// <remarks>
24
                /// The description is not saved in dxf or dwg files, its only used in the .pat files.
25
                /// </remarks>
26
                public string Description { get; set; }
87✔
27

28
                [DxfCodeValue(DxfReferenceType.Count, 79)]
29
                public List<Line> Lines { get; set; } = new List<Line>();
205,015✔
30

31
                /// <summary>
32
                /// Default constructor of a hatch pattern.
33
                /// </summary>
34
                /// <param name="name"></param>
35
                public HatchPattern(string name)
4,123✔
36
                {
4,123✔
37
                        this.Name = name;
4,123✔
38
                }
4,123✔
39

40
                /// <summary>
41
                /// Update the pattern geometry with a translation, rotation and scale.
42
                /// </summary>
43
                /// <param name="translation"></param>
44
                /// <param name="rotation"></param>
45
                /// <param name="scale"></param>
46
                public void Update(XY translation, double rotation, double scale)
47
                {
4,370✔
48
                        var tr = Transform.CreateTranslation(translation.Convert<XYZ>());
4,370✔
49
                        var sc = Transform.CreateScaling(new XYZ(scale));
4,370✔
50
                        var rot = Transform.CreateRotation(XYZ.AxisZ, rotation);
4,370✔
51

52
                        var transform = new Transform(tr.Matrix * sc.Matrix * rot.Matrix);
4,370✔
53

54
                        foreach (var line in Lines)
13,114✔
55
                        {
2✔
56
                                line.Angle += rotation;
2✔
57
                                line.BasePoint = transform.ApplyTransform(line.BasePoint.Convert<XYZ>()).Convert<XY>();
2✔
58
                                line.Offset = transform.ApplyTransform(line.Offset.Convert<XYZ>()).Convert<XY>();
2✔
59
                                line.DashLengths = line.DashLengths.Select(d => d * scale).ToList();
6✔
60
                        }
2✔
61
                }
4,370✔
62

63
                [Obsolete("No real use for it")]
64
                public BoundingBox GetBoundingBox()
NEW
65
                {
×
NEW
66
                        BoundingBox box = BoundingBox.Null;
×
67

NEW
68
                        foreach (var item in this.Lines)
×
NEW
69
                        {
×
NEW
70
                                var length = item.Offset.GetLength();
×
71

72
                                //Direction of the line
NEW
73
                                double x = MathHelper.Cos(item.Angle) * length;
×
NEW
74
                                double y = MathHelper.Sin(item.Angle) * length;
×
75

NEW
76
                                box = box.Merge(new BoundingBox(
×
NEW
77
                                        XYZ.Zero,
×
NEW
78
                                        new XYZ(x, y, 0)));
×
NEW
79
                        }
×
80

NEW
81
                        return box;
×
NEW
82
                }
×
83

84
                /// <summary>
85
                /// Clones the current pattern.
86
                /// </summary>
87
                /// <returns></returns>
88
                public HatchPattern Clone()
89
                {
3✔
90
                        HatchPattern clone = (HatchPattern)this.MemberwiseClone();
3✔
91

92
                        clone.Lines = new List<Line>();
3✔
93
                        foreach (var item in this.Lines)
9!
94
                        {
×
95
                                clone.Lines.Add(item.Clone());
×
96
                        }
×
97

98
                        return clone;
3✔
99
                }
3✔
100

101
                /// <inheritdoc/>
102
                public override string ToString()
103
                {
×
104
                        return $"{this.Name}";
×
105
                }
×
106

107
                /// <summary>
108
                /// Load a collection of patterns from a .pat file.
109
                /// </summary>
110
                /// <param name="path"></param>
111
                /// <returns></returns>
112
                public static IEnumerable<HatchPattern> LoadFrom(string path)
113
                {
24✔
114
                        List<HatchPattern> patterns = new List<HatchPattern>();
24✔
115
                        HatchPattern current = null;
24✔
116

117
                        var lines = File.ReadLines(path)
24✔
118
                                .Select(line => line.Trim())
9,202✔
119
                                .Where(line => !string.IsNullOrWhiteSpace(line) && !line.StartsWith(";"))
9,202✔
120
                                .ToQueue();
24✔
121

122
                        List<int> leadingIndices = lines.Select((line, i) => (line, i))
9,222✔
123
                                .Where(t => t.line.StartsWith("*"))
9,198✔
124
                                .Select(t => t.i)
84✔
125
                                .OrderBy(i => i).ToList();
104✔
126

127
                        leadingIndices.Add(lines.Count);
24✔
128

129
                        while (lines.TryDequeue(out string line))
9,222✔
130
                        {
9,198✔
131
                                if (line.StartsWith("*"))
9,198✔
132
                                {
84✔
133
                                        int index = line.IndexOf(',');
84✔
134
                                        string noPrefix = line.Remove(0, 1);
84✔
135
                                        current = new HatchPattern(noPrefix.Substring(0, index - 1));
84✔
136
                                        current.Description = new string(noPrefix.Skip(index).ToArray()).Trim();
84✔
137

138
                                        patterns.Add(current);
84✔
139
                                }
84✔
140
                                else
141
                                {
9,114✔
142
                                        //;angle, x, y, shift, offset, [dash, space, ...]
143
                                        string[] data = line.Split(',');
9,114✔
144
                                        Line l = new Line();
9,114✔
145
                                        //angle
146
                                        l.Angle = MathHelper.DegToRad(double.Parse(data[0], CultureInfo.InvariantCulture));
9,114✔
147
                                        //x, y
148
                                        l.BasePoint = new XY(double.Parse(data[1], CultureInfo.InvariantCulture), double.Parse(data[2], CultureInfo.InvariantCulture));
9,114✔
149

150
                                        double shift = double.Parse(data[3], CultureInfo.InvariantCulture);
9,114✔
151
                                        double offset = double.Parse(data[4], CultureInfo.InvariantCulture);
9,114✔
152
                                        XY dir = new XY(shift, offset);
9,114✔
153
                                        double cos = Math.Cos(l.Angle);
9,114✔
154
                                        double sin = Math.Sin(l.Angle);
9,114✔
155
                                        l.Offset = new XY(dir.X * cos - dir.Y * sin, dir.X * sin + dir.Y * cos);
9,114✔
156

157
                                        IEnumerable<string> dashes = data.Skip(5);
9,114✔
158
                                        if (dashes.Any())
9,114✔
159
                                        {
9,114✔
160
                                                l.DashLengths.AddRange(dashes.Select(d => double.Parse(d, CultureInfo.InvariantCulture)));
27,342✔
161
                                        }
9,114✔
162

163
                                        current.Lines.Add(l);
9,114✔
164
                                }
9,114✔
165
                        }
9,198✔
166

167
                        return patterns;
24✔
168
                }
24✔
169

170
                /// <summary>
171
                /// Write a pattern or a collection of patterns into a .pat file.
172
                /// </summary>
173
                /// <param name="filename"></param>
174
                /// <param name="patterns"></param>
175
                public static void SavePatterns(string filename, params HatchPattern[] patterns)
176
                {
1✔
177
                        using StreamWriter writer = File.CreateText(filename);
1✔
178

179
                        foreach (HatchPattern p in patterns)
5✔
180
                        {
1✔
181
                                writer.Write($"*{p.Name}");
1✔
182

183
                                if (!p.Description.IsNullOrEmpty())
1✔
184
                                {
1✔
185
                                        writer.Write($",{p.Description}");
1✔
186
                                }
1✔
187

188
                                writer.WriteLine();
1✔
189

190
                                foreach (Line line in p.Lines)
7✔
191
                                {
2✔
192
                                        StringBuilder sb = new StringBuilder();
2✔
193

194
                                        double angle = MathHelper.DegToRad(line.Angle);
2✔
195
                                        double cos = Math.Cos(0.0 - line.Angle);
2✔
196
                                        double sin = Math.Sin(0.0 - line.Angle);
2✔
197

198
                                        var v = new XY(line.Offset.X * cos - line.Offset.Y * sin, line.Offset.X * sin + line.Offset.Y * cos);
2✔
199

200
                                        sb.Append(angle.ToString(CultureInfo.InvariantCulture));
2✔
201
                                        sb.Append(",");
2✔
202
                                        sb.Append(line.BasePoint.ToString(CultureInfo.InvariantCulture));
2✔
203
                                        sb.Append(",");
2✔
204
                                        sb.Append(v.ToString(CultureInfo.InvariantCulture));
2✔
205

206
                                        if (line.DashLengths.Count > 0)
2✔
207
                                        {
1✔
208
                                                sb.Append(",");
1✔
209
                                                sb.Append(line.DashLengths[0].ToString(CultureInfo.InvariantCulture));
1✔
210
                                                for (int i = 1; i < line.DashLengths.Count; i++)
6✔
211
                                                {
2✔
212
                                                        sb.Append(",");
2✔
213
                                                        sb.Append(line.DashLengths[i].ToString(CultureInfo.InvariantCulture));
2✔
214
                                                }
2✔
215
                                        }
1✔
216

217
                                        writer.WriteLine(sb.ToString());
2✔
218
                                }
2✔
219

220
                        }
1✔
221
                }
2✔
222
        }
223
}
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