/// <summary> /// Initializes a new instance of the <c>Hatch</c> class. /// </summary> /// <remarks> /// The hatch boundary paths must be on the same plane as the hatch. /// The normal and the elevation of the boundary paths will be omitted (the hatch elevation and normal will be used instead). /// Only the x and y coordinates for the center of the line, ellipse, circle and arc will be used. /// </remarks> /// <param name="pattern"><see cref="HatchPattern">Hatch pattern</see>.</param> /// <param name="paths">A list of <see cref="HatchBoundaryPath">boundary paths</see>.</param> /// <param name="associative">Defines if the hatch is associative or not.</param> public Hatch(HatchPattern pattern, IList <HatchBoundaryPath> paths, bool associative) : base(EntityType.Hatch, DxfObjectCode.Hatch) { if (pattern == null) { throw new ArgumentNullException(nameof(pattern)); } if (paths == null) { throw new ArgumentNullException(nameof(paths)); } this.pattern = pattern; this.boundaryPaths = new ObservableCollection <HatchBoundaryPath>(paths.Count); this.boundaryPaths.BeforeAddItem += this.BoundaryPaths_BeforeAddItem; this.boundaryPaths.AddItem += this.BoundaryPaths_AddItem; this.boundaryPaths.BeforeRemoveItem += this.BoundaryPaths_BeforeRemoveItem; this.boundaryPaths.RemoveItem += this.BoundaryPaths_RemoveItem; this.associative = associative; foreach (HatchBoundaryPath path in paths) { if (!this.associative) { path.ClearContour(); } this.boundaryPaths.Add(path); } }
/// <summary> /// Initializes a new instance of the <c>Hatch</c> class. /// </summary> /// <remarks> /// The hatch boundary paths must be on the same plane as the hatch. /// The normal and the elevation of the boundary paths will be omited (the hatch elevation and normal will be used instead). /// Only the x and y coordinates for the center of the line, ellipse, circle and arc will be used. /// </remarks> /// <param name="pattern"><see cref="HatchPattern">Hatch pattern</see>.</param> /// <param name="boundaryPaths">A list of <see cref="HatchBoundaryPath">boundary paths</see>.</param> public Hatch(HatchPattern pattern, List <HatchBoundaryPath> boundaryPaths) : base(DxfObjectCode.Hatch) { this.pattern = pattern; this.boundaryPaths = boundaryPaths; this.layer = Layer.Default; this.color = AciColor.ByLayer; this.lineType = LineType.ByLayer; this.normal = Vector3.UnitZ; }
/// <summary> /// Initializes a new instance of the <c>Hatch</c> class. /// </summary> /// <remarks> /// The hatch boundary paths must be on the same plane as the hatch. /// The normal and the elevation of the boundary paths will be omited (the hatch elevation and normal will be used instead). /// Only the x and y coordinates for the center of the line, ellipse, circle and arc will be used. /// </remarks> /// <param name="pattern"><see cref="HatchPattern">Hatch pattern</see>.</param> /// <param name="boundaryPaths">A list of <see cref="HatchBoundaryPath">boundary paths</see>.</param> public Hatch(HatchPattern pattern, List <HatchBoundaryPath> boundaryPaths) : base(EntityType.Hatch, DxfObjectCode.Hatch) { this.pattern = pattern; this.boundaryPaths = boundaryPaths; if (pattern.GetType() == typeof(HatchGradientPattern)) { ((HatchGradientPattern)pattern).GradientColorAciXData(this.XData); } }
/// <summary> /// Initializes a new instance of the <c>Hatch</c> class. /// </summary> /// <remarks> /// This constructor is initialized with an empty list of boundary paths, remember a hatch without boundaries will be discarded when saving the file.<br/> /// When creating an associative hatch do not add the entities that make the boundary to the document, it will be done automatically. Doing so will throw an exception.<br/> /// The hatch boundary paths must be on the same plane as the hatch. /// The normal and the elevation of the boundary paths will be omitted (the hatch elevation and normal will be used instead). /// Only the x and y coordinates for the center of the line, ellipse, circle and arc will be used. /// </remarks> /// <param name="pattern"><see cref="HatchPattern">Hatch pattern</see>.</param> /// <param name="associative">Defines if the hatch is associative or not.</param> public Hatch(HatchPattern pattern, bool associative) : base(EntityType.Hatch, DxfObjectCode.Hatch) { this.pattern = pattern ?? throw new ArgumentNullException(nameof(pattern)); this.boundaryPaths = new ObservableCollection <HatchBoundaryPath>(); this.boundaryPaths.BeforeAddItem += this.BoundaryPaths_BeforeAddItem; this.boundaryPaths.AddItem += this.BoundaryPaths_AddItem; this.boundaryPaths.BeforeRemoveItem += this.BoundaryPaths_BeforeRemoveItem; this.boundaryPaths.RemoveItem += this.BoundaryPaths_RemoveItem; this.associative = associative; }
/// <summary> /// Initializes a new instance of the <c>Hatch</c> class. /// </summary> /// <remarks> /// The hatch boundary paths must be on the same plane as the hatch. /// The normal and the elevation of the boundary paths will be omitted (the hatch elevation and normal will be used instead). /// Only the x and y coordinates for the center of the line, ellipse, circle and arc will be used. /// </remarks> /// <param name="pattern"><see cref="HatchPattern">Hatch pattern</see>.</param> /// <param name="paths">A list of <see cref="HatchBoundaryPath">boundary paths</see>.</param> public Hatch(HatchPattern pattern, List<HatchBoundaryPath> paths) : base(EntityType.Hatch, DxfObjectCode.Hatch) { if (pattern == null) throw new ArgumentNullException("pattern"); if (paths == null) throw new ArgumentNullException("paths"); if(paths.Count == 0) throw new ArgumentException("The hatch boundary must contain at least one valid path.", "paths"); this.boundaryPaths = paths; this.pattern = pattern; }
/// <summary> /// Initializes a new instance of the <c>Hatch</c> class. /// </summary> /// <remarks> /// This constructor is initialized with an empty list of boundary paths, remember a hatch without boundaries will be discarded when saving the file.<br/> /// The hatch boundary paths must be on the same plane as the hatch. /// The normal and the elevation of the boundary paths will be omitted (the hatch elevation and normal will be used instead). /// Only the x and y coordinates for the center of the line, ellipse, circle and arc will be used. /// </remarks> /// <param name="pattern"><see cref="HatchPattern">Hatch pattern</see>.</param> /// <param name="associative">Defines if the hatch is associative or not.</param> public Hatch(HatchPattern pattern, bool associative) : base(EntityType.Hatch, DxfObjectCode.Hatch) { if (pattern == null) throw new ArgumentNullException("pattern"); this.pattern = pattern; this.boundaryPaths = new ObservableCollection<HatchBoundaryPath>(); this.boundaryPaths.BeforeAddItem += this.BoundaryPaths_BeforeAddItem; this.boundaryPaths.AddItem += this.BoundaryPaths_AddItem; this.boundaryPaths.BeforeRemoveItem += this.BoundaryPaths_BeforeRemoveItem; this.boundaryPaths.RemoveItem += this.BoundaryPaths_RemoveItem; this.associative = associative; }
public virtual object Clone() { HatchPattern copy = new HatchPattern(this.name, this.description) { Style = this.style, Fill = this.fill, Type = this.type, Origin = this.origin, Angle = this.angle, Scale = this.scale, }; foreach (HatchPatternLineDefinition def in this.lineDefinitions) copy.LineDefinitions.Add((HatchPatternLineDefinition) def.Clone()); return copy; }
/// <summary> /// Initializes a new instance of the <c>Hatch</c> class. /// </summary> /// <remarks> /// The hatch boundary paths must be on the same plane as the hatch. /// The normal and the elevation of the boundary paths will be omited (the hatch elevation and normal will be used instead). /// Only the x and y coordinates for the center of the line, ellipse, circle and arc will be used. /// </remarks> /// <param name="pattern"><see cref="HatchPattern">Hatch pattern</see>.</param> /// <param name="paths">A list of <see cref="HatchBoundaryPath">boundary paths</see>.</param> public Hatch(HatchPattern pattern, List <HatchBoundaryPath> paths) : base(EntityType.Hatch, DxfObjectCode.Hatch) { if (pattern == null) { throw new ArgumentNullException("pattern"); } if (paths == null) { throw new ArgumentNullException("paths"); } if (paths.Count == 0) { throw new ArgumentException("The hatch boundary must contain at least one valid path.", "paths"); } this.boundaryPaths = paths; this.pattern = pattern; }
public virtual object Clone() { HatchPattern copy = new HatchPattern(name, description) { Style = style, Fill = fill, Type = type, Origin = origin, Angle = angle, Scale = scale, }; foreach (HatchPatternLineDefinition def in lineDefinitions) { copy.LineDefinitions.Add((HatchPatternLineDefinition)def.Clone()); } return(copy); }
/// <summary> /// Initializes a new instance of the <c>Hatch</c> class. /// </summary> /// <remarks> /// The hatch boundary paths must be on the same plane as the hatch. /// The normal and the elevation of the boundary paths will be omitted (the hatch elevation and normal will be used instead). /// Only the x and y coordinates for the center of the line, ellipse, circle and arc will be used. /// </remarks> /// <param name="pattern"><see cref="HatchPattern">Hatch pattern</see>.</param> /// <param name="paths">A list of <see cref="HatchBoundaryPath">boundary paths</see>.</param> /// <param name="associative">Defines if the hatch is associative or not.</param> public Hatch(HatchPattern pattern, ICollection<HatchBoundaryPath> paths, bool associative) : base(EntityType.Hatch, DxfObjectCode.Hatch) { if (pattern == null) throw new ArgumentNullException("pattern"); if (paths == null) throw new ArgumentNullException("paths"); this.pattern = pattern; this.boundaryPaths = new ObservableCollection<HatchBoundaryPath>(paths.Count); this.boundaryPaths.BeforeAddItem += this.BoundaryPaths_BeforeAddItem; this.boundaryPaths.AddItem += this.BoundaryPaths_AddItem; this.boundaryPaths.BeforeRemoveItem += this.BoundaryPaths_BeforeRemoveItem; this.boundaryPaths.RemoveItem += this.BoundaryPaths_RemoveItem; this.associative = associative; foreach (HatchBoundaryPath path in paths) { if (!this.associative) path.ClearContour(); this.boundaryPaths.Add(path); } }
/// <summary> /// Creates a new hatch pattern from the definition in a pat file. /// </summary> /// <param name="file">Pat file where the definition is located.</param> /// <param name="patternName">Name of the pattern definition that wants to be read (ignore case).</param> /// <returns>A Hatch pattern defined by the pat file.</returns> public static HatchPattern FromFile(string file, string patternName) { HatchPattern pattern = null; using (StreamReader reader = new StreamReader(File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite), true)) { while (!reader.EndOfStream) { string line = reader.ReadLine(); if (line == null) { throw new FileLoadException("Unknown error reading pat file.", file); } // lines starting with semicolons are comments if (line.StartsWith(";")) { continue; } // every pattern definition starts with '*' if (!line.StartsWith("*")) { continue; } // reading pattern name and description int endName = line.IndexOf(','); // the first semicolon divides the name from the description that might contain more semicolons string name = line.Substring(1, endName - 1); string description = line.Substring(endName + 1, line.Length - endName - 1); // remove start and end spaces description = description.Trim(); if (!name.Equals(patternName, StringComparison.OrdinalIgnoreCase)) { continue; } // we have found the pattern name, the next lines of the file contains the pattern definition line = reader.ReadLine(); if (line == null) { throw new FileLoadException("Unknown error reading pat file.", file); } pattern = new HatchPattern(name, description); while (!reader.EndOfStream && !line.StartsWith("*") && !string.IsNullOrEmpty(line)) { List <double> dashPattern = new List <double>(); string[] tokens = line.Split(','); double angle = double.Parse(tokens[0]); Vector2 origin = new Vector2(double.Parse(tokens[1]), double.Parse(tokens[2])); Vector2 delta = new Vector2(double.Parse(tokens[3]), double.Parse(tokens[4])); // the rest of the info is optional if it exists define the dash pattern definition for (int i = 5; i < tokens.Length; i++) { dashPattern.Add(double.Parse(tokens[i])); } HatchPatternLineDefinition lineDefinition = new HatchPatternLineDefinition { Angle = angle, Origin = origin, Delta = delta, DashPattern = dashPattern }; pattern.lineDefinitions.Add(lineDefinition); pattern.type = HatchType.UserDefined; line = reader.ReadLine(); if (line == null) { throw new FileLoadException("Unknown error reading pat file.", file); } line = line.Trim(); } // there is no need to continue parsing the file, the info has been read break; } } return(pattern); }
private static void CustomHatchPattern() { DxfDocument dxf = new DxfDocument(); LwPolyline poly = new LwPolyline(); poly.Vertexes.Add(new LwPolylineVertex(-10, -10)); poly.Vertexes.Add(new LwPolylineVertex(10, -10)); poly.Vertexes.Add(new LwPolylineVertex(10, 10)); poly.Vertexes.Add(new LwPolylineVertex(-10, 10)); poly.Vertexes[2].Bulge = 1; poly.IsClosed = true; LwPolyline poly2 = new LwPolyline(); poly2.Vertexes.Add(new LwPolylineVertex(-5, -5)); poly2.Vertexes.Add(new LwPolylineVertex(5, -5)); poly2.Vertexes.Add(new LwPolylineVertex(5, 5)); poly2.Vertexes.Add(new LwPolylineVertex(-5, 5)); poly2.Vertexes[1].Bulge = -0.25; poly2.IsClosed = true; LwPolyline poly3 = new LwPolyline(); poly3.Vertexes.Add(new LwPolylineVertex(-8, -8)); poly3.Vertexes.Add(new LwPolylineVertex(-6, -8)); poly3.Vertexes.Add(new LwPolylineVertex(-6, -6)); poly3.Vertexes.Add(new LwPolylineVertex(-8, -6)); poly3.IsClosed = true; List<HatchBoundaryPath> boundary = new List<HatchBoundaryPath>{ new HatchBoundaryPath(new List<EntityObject>{poly}), new HatchBoundaryPath(new List<EntityObject>{poly2}), new HatchBoundaryPath(new List<EntityObject>{poly3}), }; HatchPattern pattern = new HatchPattern("MyPattern", "A custom hatch pattern"); HatchPatternLineDefinition line1 = new HatchPatternLineDefinition(); line1.Angle = 45; line1.Origin = Vector2.Zero; line1.Delta=new Vector2(4,4); line1.DashPattern.Add(12); line1.DashPattern.Add(-4); pattern.LineDefinitions.Add(line1); HatchPatternLineDefinition line2 = new HatchPatternLineDefinition(); line2.Angle = 135; line2.Origin = new Vector2(2.828427125, 2.828427125); line2.Delta = new Vector2(4,-4); line2.DashPattern.Add(12); line2.DashPattern.Add(-4); pattern.LineDefinitions.Add(line2); Hatch hatch = new Hatch(pattern, boundary, true); hatch.Layer = new Layer("hatch") { Color = AciColor.Red, LineType = LineType.Continuous }; hatch.Pattern.Angle = 0; hatch.Pattern.Scale = 1; dxf.AddEntity(poly); dxf.AddEntity(poly2); dxf.AddEntity(poly3); dxf.AddEntity(hatch); dxf.Save("hatchTest.dxf"); }
private void WriteHatchPatternDefinitonLines(HatchPattern pattern) { foreach (HatchPatternLineDefinition line in pattern.LineDefinitions) { double scale = pattern.Scale; double angle = line.Angle + pattern.Angle; // Pattern fill data. // In theory this should hold the same information as the pat file but for unknown reason the dxf requires global data instead of local, // it's a guess the documentation is kinda obscure. // This means we have to apply the pattern rotation and scale to the line definitions this.chunk.Write(53, angle); double sinOrigin = Math.Sin(pattern.Angle*MathHelper.DegToRad); double cosOrigin = Math.Cos(pattern.Angle*MathHelper.DegToRad); Vector2 origin = new Vector2(cosOrigin*line.Origin.X*scale - sinOrigin*line.Origin.Y*scale, sinOrigin*line.Origin.X*scale + cosOrigin*line.Origin.Y*scale); this.chunk.Write(43, origin.X); this.chunk.Write(44, origin.Y); double sinDelta = Math.Sin(angle*MathHelper.DegToRad); double cosDelta = Math.Cos(angle*MathHelper.DegToRad); Vector2 delta = new Vector2(cosDelta*line.Delta.X*scale - sinDelta*line.Delta.Y*scale, sinDelta*line.Delta.X*scale + cosDelta*line.Delta.Y*scale); this.chunk.Write(45, delta.X); this.chunk.Write(46, delta.Y); this.chunk.Write(79, (short) line.DashPattern.Count); foreach (double dash in line.DashPattern) { this.chunk.Write(49, dash*scale); } } }
private void WriteHatchPattern(HatchPattern pattern) { this.chunk.Write(75, (short) pattern.Style); this.chunk.Write(76, (short) pattern.Type); if (pattern.Fill == HatchFillType.PatternFill) { this.chunk.Write(52, pattern.Angle); this.chunk.Write(41, pattern.Scale); this.chunk.Write(77, (short) 0); // Hatch pattern double flag this.chunk.Write(78, (short) pattern.LineDefinitions.Count); // Number of pattern definition lines this.WriteHatchPatternDefinitonLines(pattern); } // I don't know what is the purpose of these codes, it seems that it doesn't change anything but they are needed this.chunk.Write(47, 0.0); this.chunk.Write(98, 1); this.chunk.Write(10, 0.0); this.chunk.Write(20, 0.0); // dxf AutoCad2000 does not support hatch gradient patterns if (pattern is HatchGradientPattern && this.doc.DrawingVariables.AcadVer > DxfVersion.AutoCad2000) this.WriteGradientHatchPattern((HatchGradientPattern) pattern); }
/// <summary> /// Creates a new hatch pattern from the definition in a pat file. /// </summary> /// <param name="file">Pat file where the definition is located.</param> /// <param name="patternName">Name of the pattern definition that wants to be read (ignore case).</param> /// <returns>A Hatch pattern defined by the pat file.</returns> public static HatchPattern FromFile(string file, string patternName) { HatchPattern pattern = null; using (StreamReader reader = new StreamReader(File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite), true)) { while (!reader.EndOfStream) { string line = reader.ReadLine(); if (line == null) throw new FileLoadException("Unknown error reading pat file.", file); // lines starting with semicolons are comments if (line.StartsWith(";")) continue; // every pattern definition starts with '*' if (!line.StartsWith("*")) continue; // reading pattern name and description int endName = line.IndexOf(','); // the first semicolon divides the name from the description that might contain more semicolons string name = line.Substring(1, endName - 1); string description = line.Substring(endName + 1, line.Length - endName - 1); // remove start and end spaces description = description.Trim(); if (!name.Equals(patternName, StringComparison.OrdinalIgnoreCase)) continue; // we have found the pattern name, the next lines of the file contains the pattern definition line = reader.ReadLine(); if (line == null) throw new FileLoadException("Unknown error reading pat file.", file); pattern = new HatchPattern(name, description); while (!reader.EndOfStream && !line.StartsWith("*") && !string.IsNullOrEmpty(line)) { string[] tokens = line.Split(','); double angle = double.Parse(tokens[0]); Vector2 origin = new Vector2(double.Parse(tokens[1]), double.Parse(tokens[2])); Vector2 delta = new Vector2(double.Parse(tokens[3]), double.Parse(tokens[4])); HatchPatternLineDefinition lineDefinition = new HatchPatternLineDefinition { Angle = angle, Origin = origin, Delta = delta, }; // the rest of the info is optional if it exists define the dash pattern definition for (int i = 5; i < tokens.Length; i++) lineDefinition.DashPattern.Add(double.Parse(tokens[i])); pattern.LineDefinitions.Add(lineDefinition); pattern.Type = HatchType.UserDefined; line = reader.ReadLine(); if (line == null) throw new FileLoadException("Unknown error reading pat file.", file); line = line.Trim(); } // there is no need to continue parsing the file, the info has been read break; } } return pattern; }
private HatchPattern ReadHatchPattern(string name) { HatchPattern hatch = null; double angle = 0.0; double scale = 1.0; bool isGradient = false; List<HatchPatternLineDefinition> lineDefinitions = new List<HatchPatternLineDefinition>(); HatchType type = HatchType.UserDefined; HatchStyle style = HatchStyle.Normal; while (this.chunk.Code != 0 && this.chunk.Code != 1001) { switch (this.chunk.Code) { case 52: angle = this.chunk.ReadDouble(); this.chunk.Next(); break; case 41: scale = this.chunk.ReadDouble(); if (scale <= 0) scale = 1.0; this.chunk.Next(); break; case 47: this.chunk.Next(); break; case 98: this.chunk.Next(); break; case 10: this.chunk.Next(); break; case 20: this.chunk.Next(); break; case 75: style = (HatchStyle) this.chunk.ReadShort(); this.chunk.Next(); break; case 76: type = (HatchType) this.chunk.ReadShort(); this.chunk.Next(); break; case 77: // hatch pattern double flag (not used) this.chunk.Next(); break; case 78: // number of pattern definition lines short numLines = this.chunk.ReadShort(); lineDefinitions = this.ReadHatchPatternDefinitionLine(scale, angle, numLines); break; case 450: if (this.chunk.ReadInt() == 1) { isGradient = true; // gradient pattern hatch = this.ReadHatchGradientPattern(); } else this.chunk.Next(); // solid hatch, we do not need to read anything else break; default: this.chunk.Next(); break; } } if (!isGradient) hatch = new HatchPattern(name); hatch.Angle = angle; hatch.Style = style; hatch.Scale = scale; hatch.Type = type; hatch.LineDefinitions.AddRange(lineDefinitions); return hatch; }
/// <summary> /// Creates a new hatch pattern from the definition in a PAT file. /// </summary> /// <param name="file">PAT file where the definition is located.</param> /// <param name="patternName">Name of the pattern definition that wants to be read (ignore case).</param> /// <returns>A Hatch pattern as defined in the PAT file.</returns> public static HatchPattern Load(string file, string patternName) { HatchPattern pattern = null; using (StreamReader reader = new StreamReader(File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite), true)) { while (!reader.EndOfStream) { string line = reader.ReadLine(); if (line == null) throw new FileLoadException("Unknown error reading pat file.", file); line = line.Trim(); // every pattern definition starts with '*' if (!line.StartsWith("*")) continue; // reading pattern name and description int endName = line.IndexOf(','); // the first semicolon divides the name from the description that might contain more semicolons string name = line.Substring(1, endName - 1); string description = line.Substring(endName + 1, line.Length - endName - 1); // remove start and end spaces description = description.Trim(); if (!name.Equals(patternName, StringComparison.OrdinalIgnoreCase)) continue; // we have found the pattern name, the next lines of the file contains the pattern definition line = reader.ReadLine(); if (line == null) throw new FileLoadException("Unknown error reading PAT file.", file); line = line.Trim(); pattern = new HatchPattern(name, description); while (!string.IsNullOrEmpty(line) && !line.StartsWith("*") && !line.StartsWith(";")) { string[] tokens = line.Split(','); if(tokens.Length < 5) throw new FileLoadException("The hatch pattern definition lines must contain at least 5 values.", file); double angle = double.Parse(tokens[0], NumberStyles.Float, CultureInfo.InvariantCulture); Vector2 origin = new Vector2( double.Parse(tokens[1], NumberStyles.Float, CultureInfo.InvariantCulture), double.Parse(tokens[2], NumberStyles.Float, CultureInfo.InvariantCulture)); Vector2 delta = new Vector2( double.Parse(tokens[3], NumberStyles.Float, CultureInfo.InvariantCulture), double.Parse(tokens[4], NumberStyles.Float, CultureInfo.InvariantCulture)); HatchPatternLineDefinition lineDefinition = new HatchPatternLineDefinition { Angle = angle, Origin = origin, Delta = delta, }; // the rest of the info is optional if it exists define the dash pattern definition for (int i = 5; i < tokens.Length; i++) lineDefinition.DashPattern.Add(double.Parse(tokens[i], NumberStyles.Float, CultureInfo.InvariantCulture)); pattern.LineDefinitions.Add(lineDefinition); pattern.Type = HatchType.UserDefined; if(reader.EndOfStream) break; line = reader.ReadLine(); if (line == null) throw new FileLoadException("Unknown error reading PAT file.", file); line = line.Trim(); } // there is no need to continue parsing the file, the info has been read break; } } return pattern; }