#region netDxf, Copyright(C) 2013 Daniel Carvajal, Licensed under LGPL. // netDxf library // Copyright (C) 2013 Daniel Carvajal (haplokuon@gmail.com) // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #endregion using System; using System.Collections.Generic; namespace netDxf.Entities { /// /// Represents a hatch entity. /// public class Hatch : EntityObject { #region private fields private List boundaryPaths; private HatchPattern pattern; private double elevation; #endregion #region constructors /// /// Initializes a new instance of the Hatch class. /// /// /// 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. /// /// Hatch pattern. /// A list of boundary paths. public Hatch(HatchPattern pattern, IEnumerable boundaryPaths) : base(EntityType.Hatch, DxfObjectCode.Hatch) { this.boundaryPaths = new List(); this.boundaryPaths.AddRange(boundaryPaths); this.pattern = pattern; if (pattern.GetType() == typeof (HatchGradientPattern)) ((HatchGradientPattern) pattern).GradientColorAciXData(this.XData); } #endregion #region public properties /// /// Gets or sets the hatch pattern name. /// public HatchPattern Pattern { get { return this.pattern; } set { if (value.GetType() == typeof(HatchGradientPattern)) ((HatchGradientPattern)value).GradientColorAciXData(this.XData); this.pattern = value; } } /// /// Gets or sets the hatch boundary paths. /// /// /// If the hatch is associative the boundary paths will be also added to the document. /// public List BoundaryPaths { get { return this.boundaryPaths; } set { if (value == null) throw new ArgumentNullException("value"); this.boundaryPaths = value; } } /// /// Gets or sets the hatch elevation, its position along its normal. /// public double Elevation { get { return this.elevation; } set { this.elevation = value; } } #endregion #region public methods /// /// Creates a list of entities that represents the boundary of the hatch in world coordinates. /// /// A list of entities that makes the boundary of the hatch in world coordinates. /// /// The generated list can be used to directly draw the hatch boundary given the normal and elevation of the hatch. /// All entities are in world coordinates except the LwPolyline boundary path since by definition its vertexes are expressed in object coordinates. /// This list differs in that the hatch entities list are in local coordinates of the hatch /// while with this method the entities are transformed by the normal and elevetation of it. /// public List CreateWCSBoundary() { List data = new List(); Matrix3 trans = MathHelper.ArbitraryAxis(this.normal); Vector3 pos = trans * new Vector3(0.0, 0.0, this.elevation); foreach (HatchBoundaryPath path in this.boundaryPaths) { foreach (EntityObject entity in path.Data) { switch (entity.Type) { case (EntityType.Arc): data.Add(ProcessArc((Arc)entity, trans, pos)); break; case (EntityType.Circle): data.Add(ProcessCircle((Circle)entity, trans, pos)); break; case (EntityType.Ellipse): data.Add(ProcessEllipse((Ellipse)entity, trans, pos)); break; case (EntityType.Line): data.Add(ProcessLine((Line)entity, trans, pos)); break; case (EntityType.LightWeightPolyline): // LwPolylines need an special threatement since their vertexes are expressed in object coordinates. data.Add(ProcessLwPolyline((LwPolyline)entity, this.normal, this.elevation)); break; case (EntityType.Spline): data.Add(ProcessSpline((Spline)entity, trans, pos)); break; } } } return data; } #endregion #region private methods private static EntityObject ProcessArc(Arc arc, Matrix3 trans, Vector3 pos) { Arc copy = (Arc) arc.Clone(); copy.Center = trans * arc.Center + pos; copy.Normal = trans * arc.Normal; return copy; } private static EntityObject ProcessCircle(Circle circle, Matrix3 trans, Vector3 pos) { Circle copy = (Circle)circle.Clone(); copy.Center = trans * circle.Center + pos; copy.Normal = trans * circle.Normal; return copy; } private static Ellipse ProcessEllipse(Ellipse ellipse, Matrix3 trans, Vector3 pos) { Ellipse copy = (Ellipse)ellipse.Clone(); copy.Center = trans * ellipse.Center + pos; copy.Normal = trans * ellipse.Normal; return copy; } private static Line ProcessLine(Line line, Matrix3 trans, Vector3 pos) { Line copy = (Line)line.Clone(); copy.StartPoint = trans * line.StartPoint + pos; copy.EndPoint = trans * line.EndPoint + pos; copy.Normal = trans * copy.Normal; return copy; } private static LwPolyline ProcessLwPolyline(LwPolyline polyline, Vector3 normal, double elevation) { LwPolyline copy = (LwPolyline) polyline.Clone(); copy.Elevation = elevation; copy.Normal = normal; return copy; } private static Spline ProcessSpline(Spline spline, Matrix3 trans, Vector3 pos) { Spline copy = (Spline) spline.Clone(); foreach (SplineVertex vertex in copy.ControlPoints) { vertex.Location = trans*vertex.Location + pos; } copy.Normal = trans*spline.Normal; return copy; } #endregion #region overrides /// /// Creates a new Hatch that is a copy of the current instance. /// /// A new Hatch that is a copy of this instance. public override object Clone() { return new Hatch(this.pattern, this.boundaryPaths) { //EntityObject properties Color = this.color, Layer = this.layer, LineType = this.lineType, Lineweight = this.lineweight, LineTypeScale = this.lineTypeScale, Normal = this.normal, XData = this.xData, //Hatch properties Elevation = this.elevation }; } #endregion } }