/// <summary> /// Intitializes a new instance of the <c>Attribute</c> class. /// </summary> /// <param name="definition"><see cref="AttributeDefinition">Attribute definition</see>.</param> /// <param name="value">Attribute value.</param> public Attribute(AttributeDefinition definition, object value) : base(DxfObjectCode.Attribute) { this.definition = definition; this.value = value; this.color = definition.Color; this.layer = definition.Layer; this.lineType = definition.LineType; }
private void WriteAttributeDefinition(AttributeDefinition def) { this.WriteCodePair(0, DxfObjectCode.AttributeDefinition); this.WriteCodePair(5, def.Handle); this.WriteCodePair(100, SubclassMarker.Entity); this.WriteEntityCommonCodes(def); this.WriteCodePair(100, SubclassMarker.Text); this.WriteCodePair(10, def.BasePoint.X); this.WriteCodePair(20, def.BasePoint.Y); this.WriteCodePair(30, def.BasePoint.Z); this.WriteCodePair(40, def.Height); this.WriteCodePair(1, def.Value); this.WriteCodePair(7, def.Style); this.WriteCodePair(41, def.WidthFactor); this.WriteCodePair(50, def.Rotation); this.WriteCodePair(100, SubclassMarker.AttributeDefinition); this.WriteCodePair(2, def.Id); this.WriteCodePair(3, def.Text); this.WriteCodePair(70, (int) def.Flags); switch (def.Alignment) { case TextAlignment.TopLeft: this.WriteCodePair(72, 0); this.WriteCodePair(74, 3); break; case TextAlignment.TopCenter: this.WriteCodePair(72, 1); this.WriteCodePair(74, 3); break; case TextAlignment.TopRight: this.WriteCodePair(72, 2); this.WriteCodePair(74, 3); break; case TextAlignment.MiddleLeft: this.WriteCodePair(72, 0); this.WriteCodePair(74, 2); break; case TextAlignment.MiddleCenter: this.WriteCodePair(72, 1); this.WriteCodePair(74, 2); break; case TextAlignment.MiddleRight: this.WriteCodePair(72, 2); this.WriteCodePair(74, 2); break; case TextAlignment.BottomLeft: this.WriteCodePair(72, 0); this.WriteCodePair(74, 1); break; case TextAlignment.BottomCenter: this.WriteCodePair(72, 1); this.WriteCodePair(74, 1); break; case TextAlignment.BottomRight: this.WriteCodePair(72, 2); this.WriteCodePair(74, 1); break; case TextAlignment.BaselineLeft: this.WriteCodePair(72, 0); this.WriteCodePair(74, 0); break; case TextAlignment.BaselineCenter: this.WriteCodePair(72, 1); this.WriteCodePair(74, 0); break; case TextAlignment.BaselineRight: this.WriteCodePair(72, 2); this.WriteCodePair(74, 0); break; } this.WriteCodePair(11, def.BasePoint.X); this.WriteCodePair(21, def.BasePoint.Y); this.WriteCodePair(31, def.BasePoint.Z); }
/// <summary> /// Initializes a new instance of the <c>Attribute</c> class. /// </summary> /// <param name="definition"><see cref="AttributeDefinition">Attribute definition</see>.</param> /// <remarks> /// Although the attribute entity could override values defined in its definition for simplicity the implementation has restricted this possibility. /// </remarks> public Attribute(AttributeDefinition definition) : base(DxfObjectCode.Attribute) { if (definition == null) throw new ArgumentNullException("definition"); //EntityObject properties this.color = definition.Color; this.layer = definition.Layer; this.lineType = definition.LineType; this.lineweight = definition.Lineweight; this.lineTypeScale = definition.LineTypeScale; this.transparency = definition.Transparency; this.isVisible = definition.IsVisible; this.normal = definition.Normal; //Attribute definition properties this.definition = definition; this.tag = definition.Tag; this.value = definition.Value; this.style = definition.Style; this.position = definition.Position; this.flags = definition.Flags; this.height = definition.Height; this.widthFactor = definition.WidthFactor; this.obliqueAngle = definition.ObliqueAngle; this.rotation = definition.Rotation; this.alignment = definition.Alignment; }
/// <summary> /// Creates a new AttributeDefinition that is a copy of the current instance. /// </summary> /// <returns>A new AttributeDefinition that is a copy of this instance.</returns> public override object Clone() { AttributeDefinition entity = new AttributeDefinition(this.tag) { //EntityObject properties Layer = (Layer)this.layer.Clone(), LineType = (LineType)this.lineType.Clone(), Color = (AciColor)this.color.Clone(), Lineweight = (Lineweight)this.lineweight.Clone(), Transparency = (Transparency)this.transparency.Clone(), LineTypeScale = this.lineTypeScale, Normal = this.normal, //Attribute definition properties Prompt = this.prompt, Value = this.value, Height = this.height, WidthFactor = this.widthFactor, ObliqueAngle = this.obliqueAngle, Style = this.style, Position = this.position, Flags = this.flags, Rotation = this.rotation, Alignment = this.alignment }; foreach (XData data in this.xData.Values) entity.XData.Add((XData)data.Clone()); return entity; }
private AttributeDefinition ReadAttributeDefinition() { string tag = string.Empty; string text = string.Empty; object value = null; AttributeFlags flags = AttributeFlags.Visible; Vector3 firstAlignmentPoint = Vector3.Zero; Vector3 secondAlignmentPoint = Vector3.Zero; TextStyle style = TextStyle.Default; double height = 0.0; double widthFactor = 0.0; short horizontalAlignment = 0; short verticalAlignment = 0; double rotation = 0.0; double obliqueAngle = 0.0; Vector3 normal = Vector3.UnitZ; this.chunk.Next(); while (this.chunk.Code != 0) { switch (this.chunk.Code) { case 2: tag = this.DecodeEncodedNonAsciiCharacters(this.chunk.ReadString()); this.chunk.Next(); break; case 3: text = this.DecodeEncodedNonAsciiCharacters(this.chunk.ReadString()); this.chunk.Next(); break; case 1: value = this.DecodeEncodedNonAsciiCharacters(this.chunk.ReadString()); this.chunk.Next(); break; case 70: flags = (AttributeFlags) this.chunk.ReadShort(); this.chunk.Next(); break; case 10: firstAlignmentPoint.X = this.chunk.ReadDouble(); this.chunk.Next(); break; case 20: firstAlignmentPoint.Y = this.chunk.ReadDouble(); this.chunk.Next(); break; case 30: firstAlignmentPoint.Z = this.chunk.ReadDouble(); this.chunk.Next(); break; case 11: secondAlignmentPoint.X = this.chunk.ReadDouble(); this.chunk.Next(); break; case 21: secondAlignmentPoint.Y = this.chunk.ReadDouble(); this.chunk.Next(); break; case 31: secondAlignmentPoint.Z = this.chunk.ReadDouble(); this.chunk.Next(); break; case 7: string styleName = this.DecodeEncodedNonAsciiCharacters(this.chunk.ReadString()); style = this.GetTextStyle(styleName); this.chunk.Next(); break; case 40: height = this.chunk.ReadDouble(); this.chunk.Next(); break; case 41: widthFactor = this.chunk.ReadDouble(); this.chunk.Next(); break; case 50: rotation = this.chunk.ReadDouble(); this.chunk.Next(); break; case 51: obliqueAngle = MathHelper.NormalizeAngle(this.chunk.ReadDouble()); if (obliqueAngle > 180) obliqueAngle -= 360; if (obliqueAngle < -85.0 || obliqueAngle > 85.0) obliqueAngle = 0.0; this.chunk.Next(); break; case 72: horizontalAlignment = this.chunk.ReadShort(); this.chunk.Next(); break; case 74: verticalAlignment = this.chunk.ReadShort(); this.chunk.Next(); break; case 210: normal.X = this.chunk.ReadDouble(); this.chunk.Next(); break; case 220: normal.Y = this.chunk.ReadDouble(); this.chunk.Next(); break; case 230: normal.Z = this.chunk.ReadDouble(); this.chunk.Next(); break; default: this.chunk.Next(); break; } } TextAlignment alignment = ObtainAlignment(horizontalAlignment, verticalAlignment); Vector3 ocsBasePoint = alignment == TextAlignment.BaselineLeft ? firstAlignmentPoint : secondAlignmentPoint; Vector3 wcsBasePoint = MathHelper.Transform(ocsBasePoint, normal, CoordinateSystem.Object, CoordinateSystem.World); AttributeDefinition attDef = new AttributeDefinition(tag) { Position = wcsBasePoint, Normal = normal, Alignment = alignment, Prompt = text, Value = value, Flags = flags, Style = style, Height = height, WidthFactor = MathHelper.IsZero(widthFactor) ? style.WidthFactor : widthFactor, ObliqueAngle = obliqueAngle, Rotation = rotation }; return attDef; }
/// <summary> /// Intitializes a new instance of the <c>Attribute</c> class. /// </summary> /// <param name="definition"><see cref="AttributeDefinition">Attribute definition</see>.</param> /// <remarks> /// Althought the attribute entity could override values defined in its definiton for simplicity the implementation has restricted this posibility. /// </remarks> public Attribute(AttributeDefinition definition) : this(definition, null) { }
private static void NestedBlock() { Block blockMM = new Block("BlockMM"); blockMM.Record.Units = DrawingUnits.Millimeters; AttributeDefinition attDefMM = new AttributeDefinition("MyAttributeMM"); attDefMM.Height = 1.0; attDefMM.Value = "This is block mm"; blockMM.AttributeDefinitions.Add(attDefMM); Line line1MM = new Line(Vector2.Zero, Vector2.UnitX); blockMM.Entities.Add(line1MM); Insert insMM = new Insert(blockMM); insMM.TransformAttributes(); Block blockCM = new Block("BlockCM"); blockCM.Record.Units = DrawingUnits.Centimeters; AttributeDefinition attDefCM = new AttributeDefinition("MyAttributeCM"); attDefCM.Height = 1.0; attDefCM.Value = "This is block cm"; blockCM.AttributeDefinitions.Add(attDefCM); Line line1CM = new Line(Vector2.Zero, Vector2.UnitY); blockCM.Entities.Add(line1CM); blockCM.Entities.Add(insMM); Insert insCM = new Insert(blockCM); DxfDocument doc = new DxfDocument(); doc.DrawingVariables.InsUnits = DrawingUnits.Meters; //doc.AddEntity(insMM); doc.AddEntity(insCM); doc.Save("test.dxf"); }
/// <summary> /// Initializes a new instance of <c>AttributeDefinitionDictionaryEventArgs</c>. /// </summary> /// <param name="item">Item that is being added or removed from the dictionary.</param> public AttributeDefinitionDictionaryEventArgs(AttributeDefinition item) { this.item = item; this.cancel = false; }
private static void TextAndDimensionStyleUsesAndRemove() { DxfDocument dxf = new DxfDocument(); Layer layer1 = new Layer("Layer1"); layer1.Color = AciColor.Blue; layer1.LineType = LineType.Center; Layer layer2 = new Layer("Layer2"); layer2.Color = AciColor.Red; // blocks needs an special attention Layer layer3 = new Layer("Layer3"); layer3.Color = AciColor.Yellow; Circle circle = new Circle(Vector3.Zero, 15); // it is always recommended that all block entities will be located in layer 0, but this is up to the user. circle.Layer = new Layer("circle"); circle.Layer.Color = AciColor.Green; Block block = new Block("MyBlock"); block.Entities.Add(circle); AttributeDefinition attdef = new AttributeDefinition("NewAttribute"); block.AttributeDefinitions.Add(attdef); Insert insert = new Insert(block, new Vector2(5, 5)); insert.Attributes[0].Style = new TextStyle("Arial.ttf"); dxf.AddEntity(insert); dxf.Save("style.dxf"); DxfDocument dxf2; dxf2 = DxfDocument.Load("style.dxf"); dxf.RemoveEntity(circle); Vector3 p1 = new Vector3(0, 0, 0); Vector3 p2 = new Vector3(5, 5, 0); Line line = new Line(p1, p2); dxf.AddEntity(line); DimensionStyle myStyle = new DimensionStyle("MyStyle"); myStyle.DIMTXSTY = new TextStyle("Tahoma.ttf"); myStyle.DIMPOST = "<>mm"; myStyle.DIMDEC = 2; double offset = 7; LinearDimension dimX = new LinearDimension(line, offset, 0.0, myStyle); dimX.Rotation += 30.0; LinearDimension dimY = new LinearDimension(line, offset, 90.0, myStyle); dimY.Rotation += 30.0; dxf.AddEntity(dimX); dxf.AddEntity(dimY); dxf.Save("style2.dxf"); dxf2 = DxfDocument.Load("style2.dxf"); dxf.RemoveEntity(dimX); dxf.RemoveEntity(dimY); bool ok; // we can remove myStyle it was only referenced by dimX and dimY ok = dxf.DimensionStyles.Remove(myStyle.Name); // we cannot remove myStyle.TextStyle since it is in use by the internal blocks created by the dimension entities ok = dxf.Blocks.Remove(dimX.Block.Name); ok = dxf.Blocks.Remove(dimY.Block.Name); // no we can remove the unreferenced textStyle ok = dxf.TextStyles.Remove(myStyle.DIMTXSTY.Name); dxf.Save("style3.dxf"); dxf2 = DxfDocument.Load("style3.dxf"); }
private static void WriteNestedInsert() { // nested blocks DxfDocument dxf = new DxfDocument(); Block nestedBlock = new Block("Nested block"); Circle circle = new Circle(Vector3.Zero, 5); circle.Layer = new Layer("circle"); circle.Layer.Color.Index = 2; nestedBlock.Entities.Add(circle); AttributeDefinition attdef = new AttributeDefinition("NewAttribute"); attdef.Prompt = "InfoText"; attdef.Alignment = TextAlignment.MiddleCenter; nestedBlock.AttributeDefinitions.Add(attdef); Insert nestedInsert = new Insert(nestedBlock, new Vector3(0, 0, 0)); // the position will be relative to the position of the insert that nest it nestedInsert.Attributes[0].Value = 24; Insert nestedInsert2 = new Insert(nestedBlock, new Vector3(-20, 0, 0)); // the position will be relative to the position of the insert that nest it nestedInsert2.Attributes[0].Value = -20; Block block = new Block("MyBlock"); block.Entities.Add(new Line(new Vector3(-5, -5, 0), new Vector3(5, 5, 0))); block.Entities.Add(new Line(new Vector3(5, -5, 0), new Vector3(-5, 5, 0))); block.Entities.Add(nestedInsert); block.Entities.Add(nestedInsert2); Insert insert = new Insert(block, new Vector3(5, 5, 5)); insert.Layer = new Layer("insert"); dxf.AddEntity(insert); //dxf.AddEntity(circle); // this is not allowed the circle is already part of a block dxf.Save("nested insert.dxf"); dxf = DxfDocument.Load("nested insert.dxf"); dxf.DrawingVariables.AcadVer = DxfVersion.AutoCad2010; dxf.Save("nested insert copy.dxf"); }
private static void LayerAndLineTypesUsesAndRemove() { DxfDocument dxf = new DxfDocument(); Layer layer1 = new Layer("Layer1"); layer1.Color = AciColor.Blue; layer1.LineType = LineType.Center; Layer layer2 = new Layer("Layer2"); layer2.Color = AciColor.Red; LwPolyline poly = new LwPolyline(); poly.Vertexes.Add(new LwPolylineVertex(0, 0)); poly.Vertexes.Add(new LwPolylineVertex(10, 10)); poly.Vertexes.Add(new LwPolylineVertex(20, 0)); poly.Vertexes.Add(new LwPolylineVertex(30, 10)); poly.Layer = layer1; dxf.AddEntity(poly); Ellipse ellipse = new Ellipse(new Vector3(2, 2, 0), 5, 3); ellipse.Rotation = 30; ellipse.Layer = layer1; dxf.AddEntity(ellipse); Line line = new Line(new Vector2(10, 5), new Vector2(-10, -5)); line.Layer = layer2; line.LineType = LineType.DashDot; dxf.AddEntity(line); bool ok; // this will return false since layer1 is not empty ok = dxf.Layers.Remove(layer1.Name); List<DxfObject> entities = dxf.Layers.GetReferences(layer1.Name); foreach (DxfObject o in entities) { dxf.RemoveEntity(o as EntityObject); } // now this should return true since layer1 is empty ok = dxf.Layers.Remove(layer1.Name); // blocks needs an special attention Layer layer3 = new Layer("Layer3"); layer3.Color = AciColor.Yellow; Circle circle = new Circle(Vector3.Zero, 15); // it is always recommended that all block entities will be located in layer 0, but this is up to the user. circle.Layer = new Layer("circle"); circle.Layer.Color = AciColor.Green; Block block = new Block("MyBlock"); block.Entities.Add(circle); block.Layer = new Layer("blockLayer"); AttributeDefinition attdef = new AttributeDefinition("NewAttribute"); attdef.Layer = new Layer("attDefLayer"); attdef.LineType = LineType.Center; block.AttributeDefinitions.Add(attdef); Insert insert = new Insert(block, new Vector2(5, 5)); insert.Layer = layer3; insert.Attributes[0].Layer = new Layer("attLayer"); insert.Attributes[0].LineType = LineType.Dashed; dxf.AddEntity(insert); dxf.Save("test.dxf"); DxfDocument dxf2 = DxfDocument.Load("test.dxf"); // this list will contain the circle entity List<DxfObject> dxfObjects; dxfObjects = dxf.Layers.GetReferences("circle"); // but we cannot removed since it is part of a block ok = dxf.RemoveEntity(circle); // we need to remove first the block, but to do this we need to make sure there are no references of that block in the document dxfObjects = dxf.Blocks.GetReferences(block.Name); foreach (DxfObject o in dxfObjects) { dxf.RemoveEntity(o as EntityObject); } // now it is safe to remove the block since we do not have more references in the document ok = dxf.Blocks.Remove(block.Name); // now it is safe to remove the layer "circle", the circle entity was removed with the block since it was part of it ok = dxf.Layers.Remove("circle"); // purge all document layers, only empty layers will be removed dxf.Layers.Clear(); // purge all document line types, only line types without references will be removed dxf.LineTypes.Clear(); dxf.Save("test2.dxf"); }
private static void BlockWithAttributes() { DxfDocument dxf = new DxfDocument(); Block block = new Block("BlockWithAttributes"); block.Layer = new Layer("BlockSample"); // It is possible to change the block position, even though it is recommended to keep it at Vector3.Zero, // since the block geometry is expressed in local coordinates of the block. // The block position defines the base point when inserting an Insert entity. block.Origin = new Vector3(10, 5, 0); // create an attribute definition, the attDef tag must be unique as it is the way to identify the attribute. // even thought AutoCad allows multiple attribute definition in block definitions, it is not recommended AttributeDefinition attdef = new AttributeDefinition("NewAttribute"); // this is the text prompt shown to introduce the attribute value when a new Insert entity is inserted into the drawing attdef.Prompt = "InfoText"; // optionally we can set a default value for new Insert entities attdef.Value = 0; // the attribute definition position is in local coordinates to the Insert entity to which it belongs attdef.Position = new Vector3(1, 1, 0); // modifying directly the text style might not get the desired results. Create one or get one from the text style table, modify it and assign it to the attribute text style. // one thing to note, if there is already a text style with the assigned name, the existing one in the text style table will override the new one. //attdef.Style.IsVertical = true; TextStyle txt = new TextStyle("MyStyle", "Arial.ttf"); txt.IsVertical = true; attdef.Style = txt; attdef.WidthFactor = 2; // not all alignment options are available for TTF fonts attdef.Alignment = TextAlignment.MiddleCenter; attdef.Rotation = 90; // remember, netDxf does not allow adding attribute definitions with the same tag, even thought AutoCad allows this behavior, it is not recommended in anyway. // internally attributes and their associated attribute definitions are handled through dictionaries, // and the tags work as ids to easily identify the information stored in the attribute value. // When reading a file the attributes or attribute definitions with duplicate tags will be automatically removed. // This is subject to change on public demand, it is possible to reimplement this behavior with simple collections to allow for duplicate tags. block.AttributeDefinitions.Add(attdef); // The entities list defines the actual geometry of the block, they are expressed in th block local coordinates Line line1 = new Line(new Vector3(-5, -5, 0), new Vector3(5, 5, 0)); Line line2 = new Line(new Vector3(5, -5, 0), new Vector3(-5, 5, 0)); block.Entities.Add(line1); block.Entities.Add(line2); // You can check the entity ownership with: Block line1Owner = line1.Owner; Block line2Owner = line2.Owner; // in this example line1Oner = line2Owner = block // As explained in the PaperSpace() sample, the layout associated with a common block will always be null Layout associatedLayout = line1.Owner.Record.Layout; // associatedLayout = null // create an Insert entity with the block definition, during the initialization the Insert attributes list will be created with the default attdef properties Insert insert1 = new Insert(block) { Position = new Vector3(5, 5, 5), Normal = new Vector3(1, 1, 1), Rotation = 45 }; // When the insert position, rotation, normal and/or scale are modified we need to transform the attributes. // It is not recommended to manually change the attribute position and orientation and let the Insert entity handle the transformations to maintain them in the same local position. // In this particular case we have changed the position, normal and rotation. insert1.TransformAttributes(); // Once the insert has been created we can modify the attributes properties, the list cannot be modified only the items stored in it insert1.Attributes[0].Value = 24; // Modifying directly the layer might not get the desired results. Create one or get one from the layers table, modify it and assign it to the insert // One thing to note, if there is already a layer with the same name, the existing one in the layers table will override the new one, when the entity is added to the document. Layer layer = new Layer("MyInsertLayer"); layer.Color.Index = 4; // optionally we can add the new layer to the document, if not the new layer will be added to the Layers collection when the insert entity is added to the document // in case a new layer is found in the list the add method will return the layer already stored in the list // this behavior is similar for all TableObject elements, all table object names must be unique (case insensitive) layer = dxf.Layers.Add(layer); // assign the new layer to the insert insert1.Layer = layer; // add the entity to the document dxf.AddEntity(insert1); // create a second insert entity // the constructor will automatically reposition the insert2 attributes to the insert local position Insert insert2 = new Insert(block, new Vector3(10, 5, 0)); // as before now we can change the insert2 attribute value insert2.Attributes[0].Value = 34; // additionally we can insert extended data information XData xdata1 = new XData(new ApplicationRegistry("netDxf")); xdata1.XDataRecord.Add(new XDataRecord(XDataCode.String, "extended data with netDxf")); xdata1.XDataRecord.Add(XDataRecord.OpenControlString); xdata1.XDataRecord.Add(new XDataRecord(XDataCode.WorldSpacePositionX, 0.0)); xdata1.XDataRecord.Add(new XDataRecord(XDataCode.WorldSpacePositionY, 0.0)); xdata1.XDataRecord.Add(new XDataRecord(XDataCode.WorldSpacePositionZ, 0.0)); xdata1.XDataRecord.Add(XDataRecord.CloseControlString); insert2.XData.Add(xdata1); dxf.AddEntity(insert2); // all entities support this feature XData xdata2 = new XData(new ApplicationRegistry("MyApplication1")); xdata2.XDataRecord.Add(new XDataRecord(XDataCode.String, "extended data with netDxf")); xdata2.XDataRecord.Add(XDataRecord.OpenControlString); xdata2.XDataRecord.Add(new XDataRecord(XDataCode.String, "string record")); xdata2.XDataRecord.Add(new XDataRecord(XDataCode.Real, 15.5)); xdata2.XDataRecord.Add(new XDataRecord(XDataCode.Int32, 350)); xdata2.XDataRecord.Add(XDataRecord.CloseControlString); // multiple extended data entries might be added XData xdata3 = new XData(new ApplicationRegistry("MyApplication2")); xdata3.XDataRecord.Add(new XDataRecord(XDataCode.String, "extended data with netDxf")); xdata3.XDataRecord.Add(XDataRecord.OpenControlString); xdata3.XDataRecord.Add(new XDataRecord(XDataCode.String, "string record")); xdata3.XDataRecord.Add(new XDataRecord(XDataCode.Real, 15.5)); xdata3.XDataRecord.Add(new XDataRecord(XDataCode.Int32, 350)); xdata3.XDataRecord.Add(XDataRecord.CloseControlString); Circle circle = new Circle(Vector3.Zero, 5); circle.Layer = new Layer("MyCircleLayer"); // AutoCad 2000 does not support true colors, in that case an approximated color index will be used instead circle.Layer.Color = new AciColor(Color.MediumSlateBlue); circle.XData.Add(xdata2); circle.XData.Add(xdata3); dxf.AddEntity(circle); dxf.Save("BlockWithAttributes.dxf"); DxfDocument dxfLoad = DxfDocument.Load("BlockWithAttributes.dxf"); }
public static void LoadAndSaveBlocks() { // Create a block to be used as sample Block baseBlk = new Block("BaseBlock"); baseBlk.Record.Units = DrawingUnits.Millimeters; baseBlk.Entities.Add(new Line(new Vector3(-5, -5, 0), new Vector3(5, 5, 0))); baseBlk.Entities.Add(new Line(new Vector3(5, -5, 0), new Vector3(-5, 5, 0))); AttributeDefinition attdef = new AttributeDefinition("MyAttribute") { Prompt = "Enter a value:", Value = 0, Position = Vector3.Zero, Layer = new Layer("MyLayer") { Color = AciColor.Red } }; baseBlk.AttributeDefinitions.Add(attdef); // Blocks are saved in a similar way as other dxf, just pass the dxf file name, the DxfVersion, and optionally if the dxf needs to be saved in binary format // Only AutoCad2000 and newer versions are supported. // The block entities and attribute definitions will be added to the Model layout. // The drawing header units will be the ones defined in the block record. baseBlk.Save(baseBlk.Name + ".dxf", DxfVersion.AutoCad2000); DxfDocument dxf = new DxfDocument(); // Blocks are loaded as any other dxf, just pass the dxf file name, // optionally you can also give it a name, by default the file name without extension will be used. // Only AutoCad2000 and newer versions are supported, // Only the entities contained in the Model layout will be used. // The block units will be the ones defined in the dxf header. Block block = Block.Load(baseBlk.Name + ".dxf", "MyBlock"); // in case the loading process has failed check for null // In DEBUG mode the loading process will raise exceptions while in RELEASE it will just return null, the same as loading a DxfDocument if (block == null) { Console.WriteLine("Error loading the block dxf file."); Console.WriteLine("Press a key to continue..."); Console.ReadKey(); return; } // once the block is loaded we can use it in insert entities Insert insert = new Insert(block, new Vector2(10)); // the block might also contain attribute definitions int attdefCount = block.AttributeDefinitions.Count; // this is the list of attribute definition tags // remember netDxf does not allow the use of duplicate tag names, although AutoCad allows it, it is not recommended ICollection<string> tags = block.AttributeDefinitions.Tags; // we can assign values to the insert attributes foreach (Attribute att in insert.Attributes) { att.Value = string.Format("{0} value", att.Tag); } // optionally we can manually add the block definition to the document dxf.Blocks.Add(block); // we add the insert entity to the document, if the block associated with the block has not been added this method will do it automatically dxf.AddEntity(insert); // also it is possible to manually add attribute definitions to a document AttributeDefinition def = new AttributeDefinition("AttDefOutsideBlock") { Prompt = "Enter value:", Value = 0, Color = AciColor.Blue, Position = new Vector3(0, 30, 0) }; // we will add the attribute definition to the document just like anyother entity dxf.AddEntity(def); // now we can save our new document dxf.Save("CreateBlockFromDxf.dxf"); DxfDocument load = DxfDocument.Load("CreateBlockFromDxf.dxf"); }
private void WriteAttributeDefinition(AttributeDefinition def) { this.chunk.Write(100, SubclassMarker.Text); Vector3 ocsInsertion = MathHelper.Transform(def.Position, def.Normal, CoordinateSystem.World, CoordinateSystem.Object); this.chunk.Write(10, ocsInsertion.X); this.chunk.Write(20, ocsInsertion.Y); this.chunk.Write(30, ocsInsertion.Z); this.chunk.Write(40, def.Height); object value = def.Value; if (value == null) this.chunk.Write(1, string.Empty); else if (value is string) this.chunk.Write(1, this.EncodeNonAsciiCharacters((string) value)); else this.chunk.Write(1, value.ToString()); switch (def.Alignment) { case TextAlignment.TopLeft: this.chunk.Write(72, (short) 0); break; case TextAlignment.TopCenter: this.chunk.Write(72, (short) 1); break; case TextAlignment.TopRight: this.chunk.Write(72, (short) 2); break; case TextAlignment.MiddleLeft: this.chunk.Write(72, (short) 0); break; case TextAlignment.MiddleCenter: this.chunk.Write(72, (short) 1); break; case TextAlignment.MiddleRight: this.chunk.Write(72, (short) 2); break; case TextAlignment.BottomLeft: this.chunk.Write(72, (short) 0); break; case TextAlignment.BottomCenter: this.chunk.Write(72, (short) 1); break; case TextAlignment.BottomRight: this.chunk.Write(72, (short) 2); break; case TextAlignment.BaselineLeft: this.chunk.Write(72, (short) 0); break; case TextAlignment.BaselineCenter: this.chunk.Write(72, (short) 1); break; case TextAlignment.BaselineRight: this.chunk.Write(72, (short) 2); break; case TextAlignment.Aligned: this.chunk.Write(72, (short) 3); break; case TextAlignment.Middle: this.chunk.Write(72, (short) 4); break; case TextAlignment.Fit: this.chunk.Write(72, (short) 5); break; } this.chunk.Write(50, def.Rotation); this.chunk.Write(51, def.ObliqueAngle); this.chunk.Write(41, def.WidthFactor); this.chunk.Write(7, this.EncodeNonAsciiCharacters(def.Style.Name)); this.chunk.Write(11, def.Position.X); this.chunk.Write(21, def.Position.Y); this.chunk.Write(31, def.Position.Z); this.chunk.Write(210, def.Normal.X); this.chunk.Write(220, def.Normal.Y); this.chunk.Write(230, def.Normal.Z); this.chunk.Write(100, SubclassMarker.AttributeDefinition); this.chunk.Write(3, this.EncodeNonAsciiCharacters(def.Prompt)); this.chunk.Write(2, this.EncodeNonAsciiCharacters(def.Tag)); this.chunk.Write(70, (short) def.Flags); switch (def.Alignment) { case TextAlignment.TopLeft: this.chunk.Write(74, (short) 3); break; case TextAlignment.TopCenter: this.chunk.Write(74, (short) 3); break; case TextAlignment.TopRight: this.chunk.Write(74, (short) 3); break; case TextAlignment.MiddleLeft: this.chunk.Write(74, (short) 2); break; case TextAlignment.MiddleCenter: this.chunk.Write(74, (short) 2); break; case TextAlignment.MiddleRight: this.chunk.Write(74, (short) 2); break; case TextAlignment.BottomLeft: this.chunk.Write(74, (short) 1); break; case TextAlignment.BottomCenter: this.chunk.Write(74, (short) 1); break; case TextAlignment.BottomRight: this.chunk.Write(74, (short) 1); break; case TextAlignment.BaselineLeft: this.chunk.Write(74, (short) 0); break; case TextAlignment.BaselineCenter: this.chunk.Write(74, (short) 0); break; case TextAlignment.BaselineRight: this.chunk.Write(74, (short) 0); break; case TextAlignment.Aligned: this.chunk.Write(74, (short) 0); break; case TextAlignment.Middle: this.chunk.Write(74, (short) 0); break; case TextAlignment.Fit: this.chunk.Write(74, (short) 0); break; } }
public static void ModifyingBlockProperties() { DxfDocument doc = new DxfDocument(); doc.DrawingVariables.InsUnits = DrawingUnits.Centimeters; Line existingLine = new Line(new Vector2(-10, 10), new Vector2(10, -10)); doc.AddEntity(existingLine); AttributeDefinition attDef4 = new AttributeDefinition("MyAttribute4"); attDef4.Value = "MyValue4"; attDef4.Alignment = TextAlignment.TopCenter; Block block = new Block("MyBlock", null, new List<AttributeDefinition>{attDef4}); block.Record.Units = DrawingUnits.Millimeters; // this is incorrect we cannot add an entity that belongs to a document when the block does not belong to anyone. //block.Entities.Add(existingLine); doc.Blocks.Add(block); // when the block and the entity that is being added belong to the same document, the entity will be removed from its current layout and added to the block // you cannot add an entity that belongs to a different document or block. Clone it instead. block.Entities.Add(existingLine); // now we can modify the block properties even if it has been already added to the document Line line = new Line(new Vector2(-10, -10), new Vector2(10, 10)); // when new entities that do not belong to anyone are added to an existing block, they will also be added to the document block.Entities.Add(line); DxfDocument doc2 = new DxfDocument(); Circle circle = new Circle(Vector2.Zero, 5); doc2.AddEntity(circle); // this is incorrect the circle already belongs to another document //block.Entities.Add(circle); // we need to clone it first Circle circle2 = (Circle) circle.Clone(); circle2.Radius = 2.5; block.Entities.Add(circle2); //you could also remove circle2 from doc2 and add it to the block doc2.RemoveEntity(circle); block.Entities.Add(circle); AttributeDefinition attDef = new AttributeDefinition("MyAttribute1"); attDef.Value = "MyValue1"; block.AttributeDefinitions.Add(attDef); // the same that is applicable to entities is also true to attribute definitions AttributeDefinition attDef2 = new AttributeDefinition("MyAttribute2"); attDef2.Value = "MyValue2"; attDef2.Alignment = TextAlignment.BaselineRight; block.AttributeDefinitions.Add(attDef2); Insert ins = new Insert(block); doc.AddEntity(ins); // if the insert has been added to a document, any new attribute definitions added to the block will not be reflected in the insert // this mimics the behavior in AutoCad AttributeDefinition attDef3 = new AttributeDefinition("MyAttribute3"); attDef3.Value = "MyValue3"; attDef3.Alignment = TextAlignment.TopCenter; block.AttributeDefinitions.Add(attDef3); ins.Rotation = 30; // to update the insert attributes call the method Sync, this method will also call the method TransformAttributes ins.Sync(); // the ins2 will have all three attributes Insert ins2 = new Insert(block, new Vector2(20,0)); doc.AddEntity(ins2); doc.Save("Test.dxf"); block.Name = "MyBlockRenamed"; doc.Save("BlockRename.dxf"); doc = Test("BlockRename.dxf"); }
/// <summary> /// Recalculate the attributes position, normal, rotation, text height, width factor, and oblique angle from the values applied to the insertion. /// </summary> /// <remarks> /// Changes to the insert, the block, or the document insertion units will require this method to be called manually.<br /> /// The attributes position, normal, rotation, text height, width factor, and oblique angle values includes the transformations applied to the insertion, /// if required this method will calculate the proper values according to the ones defined by the attribute definition.<br /> /// All the attribute values can be changed manually independently to its definition, /// but, usually, you will want them to be transformed with the insert based on the local values defined by the attribute definition.<br /> /// This method only applies to attributes that have a definition, some dxf files might generate attributes that have no definition in the block.<br /> /// At the moment the attribute width factor and oblique angle are not calculated, this is applied to inserts with non uniform scaling. /// </remarks> public void TransformAttributes() { // if the insert does not contain attributes there is nothing to do if (this.attributes.Count == 0) { return; } DrawingUnits insUnits; if (this.Owner == null) { insUnits = DrawingUnits.Unitless; } else { // if the insert belongs to a block the units to use are the ones defined in the BlockRecord // if the insert belongs to a layout the units to use are the ones defined in the Document insUnits = this.Owner.Record.Layout == null ? this.Owner.Record.Units : this.Owner.Record.Owner.Owner.DrawingVariables.InsUnits; } Vector3 insScale = this.scale * UnitHelper.ConversionFactor(this.block.Record.Units, insUnits); Matrix3 insTrans = this.GetTransformation(insUnits); foreach (Attribute att in this.attributes) { AttributeDefinition attdef = att.Definition; if (attdef == null) { continue; } Vector3 wcsAtt = insTrans * (attdef.Position - this.block.Origin); att.Position = this.position + wcsAtt; Vector2 txtU = new Vector2(attdef.WidthFactor, 0.0); txtU = MathHelper.Transform(txtU, attdef.Rotation * MathHelper.DegToRad, CoordinateSystem.Object, CoordinateSystem.World); Vector3 ocsTxtU = MathHelper.Transform(new Vector3(txtU.X, txtU.Y, 0.0), attdef.Normal, CoordinateSystem.Object, CoordinateSystem.World); Vector3 wcsTxtU = insTrans * ocsTxtU; Vector2 txtV = new Vector2(0.0, attdef.Height); txtV = MathHelper.Transform(txtV, attdef.Rotation * MathHelper.DegToRad, CoordinateSystem.Object, CoordinateSystem.World); Vector3 ocsTxtV = MathHelper.Transform(new Vector3(txtV.X, txtV.Y, 0.0), attdef.Normal, CoordinateSystem.Object, CoordinateSystem.World); Vector3 wcsTxtV = insTrans * ocsTxtV; Vector3 txtNormal = Vector3.CrossProduct(wcsTxtU, wcsTxtV); att.Normal = txtNormal; double txtHeight = MathHelper.PointLineDistance(wcsTxtV, Vector3.Zero, Vector3.Normalize(wcsTxtU)); att.Height = txtHeight; double txtAng = Vector2.Angle(new Vector2(txtU.X * insScale.X, txtU.Y * insScale.Y)) * MathHelper.RadToDeg; if (Vector3.Equals(attdef.Normal, Vector3.UnitZ)) { att.Rotation = this.rotation + txtAng; //double txtWidth = MathHelper.PointLineDistance(wcsTxtU, Vector3.Zero, Vector3.Normalize(wcsTxtV)); //att.WidthFactor = txtWidth; att.WidthFactor = attdef.WidthFactor; //double a1d1Ang = Vector2.Angle(new Vector2(txtV.X * insScale.X, txtV.Y * insScale.Y)) * MathHelper.RadToDeg; //double oblique = 90 - (a1d1Ang - txtAng); //if (oblique < -85.0 || oblique > 85.0) oblique = Math.Sign(oblique) * 85; //att.ObliqueAngle = oblique; att.ObliqueAngle = attdef.ObliqueAngle; } else { att.Rotation = txtAng; att.WidthFactor = attdef.WidthFactor; att.ObliqueAngle = attdef.ObliqueAngle; } } }
private static void BlockAttributes() { DxfDocument dxf = new DxfDocument( ); Block block = new Block("BlockWithAttributes"); block.Layer = new Layer("BlockSample"); AttributeDefinition attdef = new AttributeDefinition("NewAttribute"); attdef.Text = "InfoText"; attdef.BasePoint = new Vector3d(1, 1, 1); attdef.Style.IsVertical = true; attdef.Rotation = 45; block.Attributes.Add(attdef.Id, attdef); block.Entities.Add(new Line(new Vector3d(-5, -5, 0), new Vector3d(5, 5, 0))); block.Entities.Add(new Line(new Vector3d(5, -5, 0), new Vector3d(-5, 5, 0))); Insert insert = new Insert(block, new Vector3d(5, 5, 5)); insert.Layer = new Layer("insert"); insert.Rotation = 45; insert.Layer.Color.Index = 4; insert.Attributes[0].Value = 24; Insert insert2 = new Insert(block, new Vector3d(-5, -5, -5)); insert2.Attributes[0].Value = 34; XData xdata1 = new XData(new ApplicationRegistry("netDxf")); xdata1.XDataRecord.Add(new XDataRecord(XDataCode.String, "extended data with netDxf")); xdata1.XDataRecord.Add(XDataRecord.OpenControlString); xdata1.XDataRecord.Add(new XDataRecord(XDataCode.WorldSpacePositionX, 0)); xdata1.XDataRecord.Add(new XDataRecord(XDataCode.WorldSpacePositionY, 0)); xdata1.XDataRecord.Add(new XDataRecord(XDataCode.WorldSpacePositionZ, 0)); xdata1.XDataRecord.Add(XDataRecord.CloseControlString); XData xdata2 = new XData(new ApplicationRegistry("other application")); xdata2.XDataRecord.Add(new XDataRecord(XDataCode.String, "extended data with netDxf")); xdata2.XDataRecord.Add(XDataRecord.OpenControlString); xdata2.XDataRecord.Add(new XDataRecord(XDataCode.String, "string record")); xdata2.XDataRecord.Add(new XDataRecord(XDataCode.Real, 15.5)); xdata2.XDataRecord.Add(new XDataRecord(XDataCode.Long, 350)); xdata2.XDataRecord.Add(XDataRecord.CloseControlString); insert.XData = new Dictionary<ApplicationRegistry, XData> { {xdata1.ApplicationRegistry, xdata1}, }; dxf.AddEntity(insert); dxf.AddEntity(insert2); Circle circle = new Circle(Vector3d.Zero, 5); circle.Layer = new Layer("circle"); circle.Layer.Color.Index = 2; circle.XData = new Dictionary<ApplicationRegistry, XData> { {xdata2.ApplicationRegistry, xdata2}, }; dxf.AddEntity(circle); dxf.Save("Block with attributes.dxf", DxfVersion.AutoCad2000); dxf.Load("Block with attributes.dxf"); dxf.Save("Block with attributes result.dxf", DxfVersion.AutoCad2000); // both results must be equal only the handles might be different }