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

DomCR / ACadSharp / 18346055955

08 Oct 2025 01:19PM UTC coverage: 78.364% (+0.4%) from 77.952%
18346055955

push

github

web-flow
Merge pull request #774 from DomCR/svg-hatch

patterns def

6854 of 9493 branches covered (72.2%)

Branch coverage included in aggregate %.

191 of 211 new or added lines in 9 files covered. (90.52%)

9 existing lines in 2 files now uncovered.

26384 of 32922 relevant lines covered (80.14%)

108865.14 hits per line

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

93.48
/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
                /// <summary>
18
                /// Description for this pattern.
19
                /// </summary>
20
                /// <remarks>
21
                /// The description is not saved in dxf or dwg files, its only used in the .pat files.
22
                /// </remarks>
23
                public string Description { get; set; }
87✔
24

25
                /// <summary>
26
                /// Gets or sets the collection of <see cref="Line"/> objects.
27
                /// </summary>
28
                /// <remarks>This property allows adding, removing, or modifying the lines in the collection. Changes to this
29
                /// collection directly affect the associated context.</remarks>
30
                [DxfCodeValue(DxfReferenceType.Count, 79)]
31
                public List<Line> Lines { get; set; } = new List<Line>();
205,015✔
32

33
                /// <summary>
34
                /// Name for this pattern.
35
                /// </summary>
36
                [DxfCodeValue(2)]
37
                public string Name { get; set; }
8,182✔
38

39
                /// <summary>
40
                /// Default constructor of a hatch pattern.
41
                /// </summary>
42
                /// <param name="name"></param>
43
                public HatchPattern(string name)
4,123✔
44
                {
4,123✔
45
                        this.Name = name;
4,123✔
46
                }
4,123✔
47

48
                /// <summary>
49
                /// Load a collection of patterns from a .pat file.
50
                /// </summary>
51
                /// <param name="path"></param>
52
                /// <returns></returns>
53
                public static IEnumerable<HatchPattern> LoadFrom(string path)
54
                {
24✔
55
                        List<HatchPattern> patterns = new List<HatchPattern>();
24✔
56
                        HatchPattern current = null;
24✔
57

58
                        var lines = File.ReadLines(path)
24✔
59
                                .Select(line => line.Trim())
9,202✔
60
                                .Where(line => !string.IsNullOrWhiteSpace(line) && !line.StartsWith(";"))
9,202✔
61
                                .ToQueue();
24✔
62

63
                        List<int> leadingIndices = lines.Select((line, i) => (line, i))
9,222✔
64
                                .Where(t => t.line.StartsWith("*"))
9,198✔
65
                                .Select(t => t.i)
84✔
66
                                .OrderBy(i => i).ToList();
104✔
67

68
                        leadingIndices.Add(lines.Count);
24✔
69

70
                        while (lines.TryDequeue(out string line))
9,222✔
71
                        {
9,198✔
72
                                if (line.StartsWith("*"))
9,198✔
73
                                {
84✔
74
                                        int index = line.IndexOf(',');
84✔
75
                                        string noPrefix = line.Remove(0, 1);
84✔
76
                                        current = new HatchPattern(noPrefix.Substring(0, index - 1));
84✔
77
                                        current.Description = new string(noPrefix.Skip(index).ToArray()).Trim();
84✔
78

79
                                        patterns.Add(current);
84✔
80
                                }
84✔
81
                                else
82
                                {
9,114✔
83
                                        //;angle, x, y, shift, offset, [dash, space, ...]
84
                                        string[] data = line.Split(',');
9,114✔
85
                                        Line l = new Line();
9,114✔
86
                                        //angle
87
                                        l.Angle = MathHelper.DegToRad(double.Parse(data[0], CultureInfo.InvariantCulture));
9,114✔
88
                                        //x, y
89
                                        l.BasePoint = new XY(double.Parse(data[1], CultureInfo.InvariantCulture), double.Parse(data[2], CultureInfo.InvariantCulture));
9,114✔
90

91
                                        double shift = double.Parse(data[3], CultureInfo.InvariantCulture);
9,114✔
92
                                        double offset = double.Parse(data[4], CultureInfo.InvariantCulture);
9,114✔
93
                                        XY dir = new XY(shift, offset);
9,114✔
94
                                        double cos = Math.Cos(l.Angle);
9,114✔
95
                                        double sin = Math.Sin(l.Angle);
9,114✔
96
                                        l.Offset = new XY(dir.X * cos - dir.Y * sin, dir.X * sin + dir.Y * cos);
9,114✔
97

98
                                        IEnumerable<string> dashes = data.Skip(5);
9,114✔
99
                                        if (dashes.Any())
9,114✔
100
                                        {
9,114✔
101
                                                l.DashLengths.AddRange(dashes.Select(d => double.Parse(d, CultureInfo.InvariantCulture)));
27,342✔
102
                                        }
9,114✔
103

104
                                        current.Lines.Add(l);
9,114✔
105
                                }
9,114✔
106
                        }
9,198✔
107

108
                        return patterns;
24✔
109
                }
24✔
110

111
                /// <summary>
112
                /// Write a pattern or a collection of patterns into a .pat file.
113
                /// </summary>
114
                /// <param name="filename"></param>
115
                /// <param name="patterns"></param>
116
                public static void SavePatterns(string filename, params HatchPattern[] patterns)
117
                {
1✔
118
                        using StreamWriter writer = File.CreateText(filename);
1✔
119

120
                        foreach (HatchPattern p in patterns)
5✔
121
                        {
1✔
122
                                writer.Write($"*{p.Name}");
1✔
123

124
                                if (!p.Description.IsNullOrEmpty())
1✔
125
                                {
1✔
126
                                        writer.Write($",{p.Description}");
1✔
127
                                }
1✔
128

129
                                writer.WriteLine();
1✔
130

131
                                foreach (Line line in p.Lines)
7✔
132
                                {
2✔
133
                                        StringBuilder sb = new StringBuilder();
2✔
134

135
                                        double angle = MathHelper.DegToRad(line.Angle);
2✔
136
                                        double cos = Math.Cos(0.0 - line.Angle);
2✔
137
                                        double sin = Math.Sin(0.0 - line.Angle);
2✔
138

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

141
                                        sb.Append(angle.ToString(CultureInfo.InvariantCulture));
2✔
142
                                        sb.Append(",");
2✔
143
                                        sb.Append(line.BasePoint.ToString(CultureInfo.InvariantCulture));
2✔
144
                                        sb.Append(",");
2✔
145
                                        sb.Append(v.ToString(CultureInfo.InvariantCulture));
2✔
146

147
                                        if (line.DashLengths.Count > 0)
2✔
148
                                        {
1✔
149
                                                sb.Append(",");
1✔
150
                                                sb.Append(line.DashLengths[0].ToString(CultureInfo.InvariantCulture));
1✔
151
                                                for (int i = 1; i < line.DashLengths.Count; i++)
6✔
152
                                                {
2✔
153
                                                        sb.Append(",");
2✔
154
                                                        sb.Append(line.DashLengths[i].ToString(CultureInfo.InvariantCulture));
2✔
155
                                                }
2✔
156
                                        }
1✔
157

158
                                        writer.WriteLine(sb.ToString());
2✔
159
                                }
2✔
160
                        }
1✔
161
                }
2✔
162

163
                /// <summary>
164
                /// Clones the current pattern.
165
                /// </summary>
166
                /// <returns></returns>
167
                public HatchPattern Clone()
168
                {
3✔
169
                        HatchPattern clone = (HatchPattern)this.MemberwiseClone();
3✔
170

171
                        clone.Lines = new List<Line>();
3✔
172
                        foreach (var item in this.Lines)
9!
NEW
173
                        {
×
NEW
174
                                clone.Lines.Add(item.Clone());
×
NEW
175
                        }
×
176

177
                        return clone;
3✔
178
                }
3✔
179

180
                /// <inheritdoc/>
181
                public override string ToString()
NEW
182
                {
×
NEW
183
                        return $"{this.Name}";
×
NEW
184
                }
×
185

186
                /// <summary>
187
                /// Update the pattern geometry with a translation, rotation and scale.
188
                /// </summary>
189
                /// <param name="translation"></param>
190
                /// <param name="rotation"></param>
191
                /// <param name="scale"></param>
192
                public void Update(XY translation, double rotation, double scale)
193
                {
4,370✔
194
                        var tr = Transform.CreateTranslation(translation.Convert<XYZ>());
4,370✔
195
                        var sc = Transform.CreateScaling(new XYZ(scale));
4,370✔
196
                        var rot = Transform.CreateRotation(XYZ.AxisZ, rotation);
4,370✔
197

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

200
                        foreach (var line in Lines)
13,114✔
201
                        {
2✔
202
                                line.Angle += rotation;
2✔
203
                                line.BasePoint = transform.ApplyTransform(line.BasePoint.Convert<XYZ>()).Convert<XY>();
2✔
204
                                line.Offset = transform.ApplyTransform(line.Offset.Convert<XYZ>()).Convert<XY>();
2✔
205
                                line.DashLengths = line.DashLengths.Select(d => d * scale).ToList();
6✔
206
                        }
2✔
207
                }
4,370✔
208
        }
209
}
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