using System.Globalization; using System.Text; using netDxf; using netDxf.Entities; using netDxf.Header; using netDxf.Objects; using netDxf.Tables; using netDxf.Units; using Attribute = netDxf.Entities.Attribute; using PointEntity = netDxf.Entities.Point; namespace DxfToCSharp.Core; public class DxfCodeGenerator { private static string F(double v) { // Always emit a representation that is unequivocally a double literal. // This avoids cases where values like 0 are rendered as "0" (an int literal), // which can cause runtime type mismatches when boxed into object (e.g., XData double requirements). var s = v.ToString("G17", CultureInfo.InvariantCulture); if (!s.Contains(".") && !s.Contains("e") && !s.Contains("E")) { s += ".0"; } return s; } private string GenerateEnumFlags(T enumValue) where T : Enum { var enumType = typeof(T); var enumName = enumType.Name; var value = Convert.ToInt32(enumValue); if (value == 0) { return $"{enumName}.None"; } var flags = new List(); foreach (var enumVal in Enum.GetValues(enumType)) { var intVal = Convert.ToInt32(enumVal); if (intVal != 0 && (value & intVal) == intVal) { flags.Add($"{enumName}.{enumVal}"); } } return flags.Count > 0 ? string.Join(" | ", flags) : $"{enumName}.None"; } private readonly HashSet _usedLayers = new(); private readonly HashSet _usedLinetypes = new(); private readonly HashSet _usedTextStyles = new(); private readonly HashSet _usedBlocks = new(); private readonly HashSet _usedDimensionStyles = new(); private readonly HashSet _usedMLineStyles = new(); private readonly HashSet _usedUCS = new(); private readonly HashSet _usedVPorts = new(); private readonly HashSet _usedViews = new(); private readonly HashSet _entitiesNeedingVariables = new(); private int _insertCounter; private int _entityCounter; public string Generate(DxfDocument doc, string? sourcePath, string? className = null, DxfCodeGenerationOptions? options = null) { // Use provided options or create default options ??= new DxfCodeGenerationOptions(); var allEntities = doc.Entities.All?.ToList() ?? new List(); // Clear collections for fresh generation _usedLayers.Clear(); _usedLinetypes.Clear(); _usedTextStyles.Clear(); _usedBlocks.Clear(); _usedDimensionStyles.Clear(); _usedMLineStyles.Clear(); _usedUCS.Clear(); _usedVPorts.Clear(); _insertCounter = 0; var sb = new StringBuilder(); // Use provided class name, options class name, or default var finalClassName = className ?? options.CustomClassName ?? "DxfDocumentGenerator"; // Determine base indentation based on whether we're generating a class var baseIndent = options.GenerateClass ? " " : ""; // Header and using statements GenerateHeader(sb, sourcePath, options); // Analyze what tables we need (only if generating any tables) if (options.GenerateLayers || options.GenerateLinetypes || options.GenerateTextStyles || options.GenerateBlocks || options.GenerateDimensionStyles || options.GenerateMLineStyles || options.GenerateUCS || options.GenerateVPorts) { AnalyzeUsedTables(allEntities, options); } // Analyze which entities need to be generated as variables (for group references) AnalyzeEntitiesReferencedByGroups(doc, options); // Class definition start (if enabled) if (options.GenerateClass) { sb.AppendLine($"public static class {finalClassName}"); sb.AppendLine("{"); sb.AppendLine(" public static DxfDocument Create()"); sb.AppendLine(" {"); } sb.AppendLine($"{baseIndent}var doc = new DxfDocument();"); sb.AppendLine(); // Generate header variables if (options.GenerateHeaderVariables) { GenerateHeaderVariables(sb, doc, options, baseIndent); } // Generate table definitions GenerateTableDefinitions(sb, doc, options, baseIndent); // Generate entities GenerateEntities(sb, allEntities, options, baseIndent); // Generate objects GenerateObjects(sb, doc, options, baseIndent); // Footer sb.AppendLine(); if (options.GenerateClass) { sb.AppendLine($"{baseIndent}return doc;"); sb.AppendLine(" }"); sb.AppendLine("}"); } else { sb.AppendLine($"{baseIndent}return doc;"); } return sb.ToString(); } private void GenerateHeader(StringBuilder sb, string? sourcePath, DxfCodeGenerationOptions options) { if (options.GenerateHeader) { sb.AppendLine("/// "); sb.AppendLine("/// This code was generated by DxfToCSharp."); if (!string.IsNullOrEmpty(sourcePath)) { sb.AppendLine($"/// Source: {Path.GetFileName(sourcePath)}"); } sb.AppendLine($"/// Generated: {DateTime.Now:yyyy-MM-dd HH:mm:ss}"); sb.AppendLine("/// "); } if (options.GenerateUsingStatements) { sb.AppendLine("using System;"); sb.AppendLine("using System.Collections.Generic;"); sb.AppendLine("using netDxf;"); sb.AppendLine("using netDxf.Entities;"); sb.AppendLine("using netDxf.Header;"); sb.AppendLine("using netDxf.Objects;"); sb.AppendLine("using netDxf.Tables;"); sb.AppendLine("using netDxf.Blocks;"); sb.AppendLine("using netDxf.Units;"); sb.AppendLine("using Attribute = netDxf.Entities.Attribute;"); sb.AppendLine(); } } private void GenerateHeaderVariables(StringBuilder sb, DxfDocument doc, DxfCodeGenerationOptions options, string baseIndent) { var headerVars = doc.DrawingVariables; var hasNonDefaultValues = false; // Check if any header variables have non-default values var tempSb = new StringBuilder(); // Generate Vector3 properties if (headerVars.InsBase != Vector3.Zero) { tempSb.AppendLine($"{baseIndent}doc.DrawingVariables.InsBase = new Vector3({F(headerVars.InsBase.X)}, {F(headerVars.InsBase.Y)}, {F(headerVars.InsBase.Z)});"); hasNonDefaultValues = true; } // Generate enum properties with public setters if (headerVars.AcadVer != DxfVersion.AutoCad2000) { tempSb.AppendLine($"{baseIndent}doc.DrawingVariables.AcadVer = DxfVersion.{headerVars.AcadVer};"); hasNonDefaultValues = true; } // Generate double properties if (Math.Abs(headerVars.Angbase - 0.0) > 1e-9) { tempSb.AppendLine($"{baseIndent}doc.DrawingVariables.Angbase = {F(headerVars.Angbase)};"); hasNonDefaultValues = true; } if (Math.Abs(headerVars.TextSize - 2.5) > 1e-9) { tempSb.AppendLine($"{baseIndent}doc.DrawingVariables.TextSize = {F(headerVars.TextSize)};"); hasNonDefaultValues = true; } if (Math.Abs(headerVars.LtScale - 1.0) > 1e-9) { tempSb.AppendLine($"{baseIndent}doc.DrawingVariables.LtScale = {F(headerVars.LtScale)};"); hasNonDefaultValues = true; } if (Math.Abs(headerVars.CeLtScale - 1.0) > 1e-9) { tempSb.AppendLine($"{baseIndent}doc.DrawingVariables.CeLtScale = {F(headerVars.CeLtScale)};"); hasNonDefaultValues = true; } if (Math.Abs(headerVars.PdSize - 0.0) > 1e-9) { tempSb.AppendLine($"{baseIndent}doc.DrawingVariables.PdSize = {F(headerVars.PdSize)};"); hasNonDefaultValues = true; } if (Math.Abs(headerVars.CMLScale - 20.0) > 1e-9) { tempSb.AppendLine($"{baseIndent}doc.DrawingVariables.CMLScale = {F(headerVars.CMLScale)};"); hasNonDefaultValues = true; } // Generate enum properties if (headerVars.Angdir != AngleDirection.CCW) { tempSb.AppendLine($"{baseIndent}doc.DrawingVariables.Angdir = AngleDirection.{headerVars.Angdir};"); hasNonDefaultValues = true; } if (headerVars.InsUnits != DrawingUnits.Unitless) { tempSb.AppendLine($"{baseIndent}doc.DrawingVariables.InsUnits = DrawingUnits.{headerVars.InsUnits};"); hasNonDefaultValues = true; } if (headerVars.AttMode != AttMode.Normal) { tempSb.AppendLine($"{baseIndent}doc.DrawingVariables.AttMode = AttMode.{headerVars.AttMode};"); hasNonDefaultValues = true; } if (headerVars.PdMode != PointShape.Dot) { tempSb.AppendLine($"{baseIndent}doc.DrawingVariables.PdMode = PointShape.{headerVars.PdMode};"); hasNonDefaultValues = true; } if (headerVars.CeLweight != Lineweight.ByLayer) { tempSb.AppendLine($"{baseIndent}doc.DrawingVariables.CeLweight = Lineweight.{headerVars.CeLweight};"); hasNonDefaultValues = true; } if (headerVars.AUnits != AngleUnitType.DecimalDegrees) { tempSb.AppendLine($"{baseIndent}doc.DrawingVariables.AUnits = AngleUnitType.{headerVars.AUnits};"); hasNonDefaultValues = true; } if (headerVars.LUnits != LinearUnitType.Decimal) { tempSb.AppendLine($"{baseIndent}doc.DrawingVariables.LUnits = LinearUnitType.{headerVars.LUnits};"); hasNonDefaultValues = true; } if (headerVars.CMLJust != MLineJustification.Top) { tempSb.AppendLine($"{baseIndent}doc.DrawingVariables.CMLJust = MLineJustification.{headerVars.CMLJust};"); hasNonDefaultValues = true; } // Generate AciColor properties if (headerVars.CeColor.Index != AciColor.ByLayer.Index) { if (headerVars.CeColor.Index is >= 0 and <= 255) { tempSb.AppendLine($"{baseIndent}doc.DrawingVariables.CeColor = new AciColor({headerVars.CeColor.Index});"); } else { tempSb.AppendLine($"{baseIndent}doc.DrawingVariables.CeColor = AciColor.ByLayer;"); } hasNonDefaultValues = true; } // Generate string properties if (!string.IsNullOrEmpty(headerVars.LastSavedBy) && headerVars.LastSavedBy != Environment.UserName) { tempSb.AppendLine($"{baseIndent}doc.DrawingVariables.LastSavedBy = \"{Escape(headerVars.LastSavedBy)}\";"); hasNonDefaultValues = true; } if (headerVars.CeLtype != "ByLayer") { tempSb.AppendLine($"{baseIndent}doc.DrawingVariables.CeLtype = \"{Escape(headerVars.CeLtype)}\";"); hasNonDefaultValues = true; } if (headerVars.CLayer != "0") { tempSb.AppendLine($"{baseIndent}doc.DrawingVariables.CLayer = \"{Escape(headerVars.CLayer)}\";"); hasNonDefaultValues = true; } if (headerVars.CMLStyle != "Standard") { tempSb.AppendLine($"{baseIndent}doc.DrawingVariables.CMLStyle = \"{Escape(headerVars.CMLStyle)}\";"); hasNonDefaultValues = true; } if (headerVars.DimStyle != "Standard") { tempSb.AppendLine($"{baseIndent}doc.DrawingVariables.DimStyle = \"{Escape(headerVars.DimStyle)}\";"); hasNonDefaultValues = true; } if (headerVars.TextStyle != "Standard") { tempSb.AppendLine($"{baseIndent}doc.DrawingVariables.TextStyle = \"{Escape(headerVars.TextStyle)}\";"); hasNonDefaultValues = true; } // Generate integer properties if (headerVars.AUprec != 0) { tempSb.AppendLine($"{baseIndent}doc.DrawingVariables.AUprec = {headerVars.AUprec};"); hasNonDefaultValues = true; } if (headerVars.LUprec != 4) { tempSb.AppendLine($"{baseIndent}doc.DrawingVariables.LUprec = {headerVars.LUprec};"); hasNonDefaultValues = true; } if (headerVars.PLineGen != 0) { tempSb.AppendLine($"{baseIndent}doc.DrawingVariables.PLineGen = {headerVars.PLineGen};"); hasNonDefaultValues = true; } if (headerVars.PsLtScale != 1) { tempSb.AppendLine($"{baseIndent}doc.DrawingVariables.PsLtScale = {headerVars.PsLtScale};"); hasNonDefaultValues = true; } if (headerVars.SplineSegs != 8) { tempSb.AppendLine($"{baseIndent}doc.DrawingVariables.SplineSegs = {headerVars.SplineSegs};"); hasNonDefaultValues = true; } if (headerVars.SurfU != 6) { tempSb.AppendLine($"{baseIndent}doc.DrawingVariables.SurfU = {headerVars.SurfU};"); hasNonDefaultValues = true; } if (headerVars.SurfV != 6) { tempSb.AppendLine($"{baseIndent}doc.DrawingVariables.SurfV = {headerVars.SurfV};"); hasNonDefaultValues = true; } // Generate boolean properties if (headerVars.MirrText) { tempSb.AppendLine($"{baseIndent}doc.DrawingVariables.MirrText = {headerVars.MirrText.ToString().ToLower()};"); hasNonDefaultValues = true; } if (headerVars.LwDisplay) { tempSb.AppendLine($"{baseIndent}doc.DrawingVariables.LwDisplay = {headerVars.LwDisplay.ToString().ToLower()};"); hasNonDefaultValues = true; } // Generate DateTime properties // Note: DateTime properties are initialized with DateTime.Now/UtcNow in HeaderVariables constructor, // so we only generate code if they have been explicitly set to specific values // We'll generate code for any DateTime that's not the current date/time (allowing some tolerance) var now = DateTime.Now; var utcNow = DateTime.UtcNow; // Only generate DateTime code if the values are significantly different from current time // or if they represent specific dates that should be preserved if (Math.Abs((headerVars.TdCreate - now).TotalMinutes) > 1) { tempSb.AppendLine($"{baseIndent}doc.DrawingVariables.TdCreate = new DateTime({headerVars.TdCreate.Year}, {headerVars.TdCreate.Month}, {headerVars.TdCreate.Day}, {headerVars.TdCreate.Hour}, {headerVars.TdCreate.Minute}, {headerVars.TdCreate.Second});"); hasNonDefaultValues = true; } if (Math.Abs((headerVars.TduCreate - utcNow).TotalMinutes) > 1) { tempSb.AppendLine($"{baseIndent}doc.DrawingVariables.TduCreate = new DateTime({headerVars.TduCreate.Year}, {headerVars.TduCreate.Month}, {headerVars.TduCreate.Day}, {headerVars.TduCreate.Hour}, {headerVars.TduCreate.Minute}, {headerVars.TduCreate.Second}, DateTimeKind.Utc);"); hasNonDefaultValues = true; } if (Math.Abs((headerVars.TdUpdate - now).TotalMinutes) > 1) { tempSb.AppendLine($"{baseIndent}doc.DrawingVariables.TdUpdate = new DateTime({headerVars.TdUpdate.Year}, {headerVars.TdUpdate.Month}, {headerVars.TdUpdate.Day}, {headerVars.TdUpdate.Hour}, {headerVars.TdUpdate.Minute}, {headerVars.TdUpdate.Second});"); hasNonDefaultValues = true; } if (Math.Abs((headerVars.TduUpdate - utcNow).TotalMinutes) > 1) { tempSb.AppendLine($"{baseIndent}doc.DrawingVariables.TduUpdate = new DateTime({headerVars.TduUpdate.Year}, {headerVars.TduUpdate.Month}, {headerVars.TduUpdate.Day}, {headerVars.TduUpdate.Hour}, {headerVars.TduUpdate.Minute}, {headerVars.TduUpdate.Second}, DateTimeKind.Utc);"); hasNonDefaultValues = true; } // Generate TimeSpan properties if (headerVars.TdinDwg != TimeSpan.Zero) { tempSb.AppendLine($"{baseIndent}doc.DrawingVariables.TdinDwg = new TimeSpan({headerVars.TdinDwg.Days}, {headerVars.TdinDwg.Hours}, {headerVars.TdinDwg.Minutes}, {headerVars.TdinDwg.Seconds});"); hasNonDefaultValues = true; } // Generate UCS properties if (headerVars.CurrentUCS != null && headerVars.CurrentUCS.Name != "Unnamed") { var ucs = headerVars.CurrentUCS; tempSb.AppendLine($"{baseIndent}doc.DrawingVariables.CurrentUCS = new UCS(\"{Escape(ucs.Name)}\", new Vector3({F(ucs.Origin.X)}, {F(ucs.Origin.Y)}, {F(ucs.Origin.Z)}), new Vector3({F(ucs.XAxis.X)}, {F(ucs.XAxis.Y)}, {F(ucs.XAxis.Z)}), new Vector3({F(ucs.YAxis.X)}, {F(ucs.YAxis.Y)}, {F(ucs.YAxis.Z)}));"); hasNonDefaultValues = true; } // Only add the header variables section if there are non-default values if (hasNonDefaultValues) { if (options.GenerateDetailedComments) { sb.AppendLine($"{baseIndent}// Header variables (drawing variables)"); } sb.Append(tempSb); sb.AppendLine(); } } private void AnalyzeUsedTables(List entities, DxfCodeGenerationOptions options) { foreach (var entity in entities) { if (options.GenerateLayers && entity.Layer != null) _usedLayers.Add(entity.Layer.Name); // Layers referenced by viewport FrozenLayers must be generated too if (options.GenerateLayers && entity is Viewport vp && vp.FrozenLayers != null && vp.FrozenLayers.Count > 0) { foreach (var l in vp.FrozenLayers) { if (l != null) _usedLayers.Add(l.Name); } } if (options.GenerateLinetypes && entity.Linetype != null) _usedLinetypes.Add(entity.Linetype.Name); // Check for text entities that use text styles if (options.GenerateTextStyles) { if (entity is Text { Style: not null } text) _usedTextStyles.Add(text.Style.Name); else if (entity is MText { Style: not null } mtext) _usedTextStyles.Add(mtext.Style.Name); } // Check for Insert entities that use blocks if (options.GenerateBlocks && entity is Insert { Block: not null } insert) _usedBlocks.Add(insert.Block.Name); // Check for Leader entities that use dimension styles if (options.GenerateDimensionStyles) { if (entity is Leader { Style: not null } leader) _usedDimensionStyles.Add(leader.Style.Name); // Check for Dimension entities that use dimension styles if (entity is Dimension { Style: not null } dimension) _usedDimensionStyles.Add(dimension.Style.Name); } // Check for MLine entities that use multiline styles if (options.GenerateMLineStyles && entity is MLine { Style: not null } mline) _usedMLineStyles.Add(mline.Style.Name); } // Analyze UCS objects (they are not directly referenced by entities but are part of document structure) if (options.GenerateUCS) { AnalyzeUsedUCS(entities, options); } // Analyze VPort objects (they are not directly referenced by entities but are part of document structure) if (options.GenerateVPorts) { AnalyzeUsedVPorts(entities, options); } // Analyze View objects (they are not directly referenced by entities but are part of document structure) if (options.GenerateViews) { AnalyzeUsedViews(entities, options); } } private void AnalyzeEntitiesReferencedByGroups(DxfDocument doc, DxfCodeGenerationOptions options) { if (!options.GenerateGroupObjects) return; foreach (var group in doc.Groups) { foreach (var entity in group.Entities) { _entitiesNeedingVariables.Add(entity.Handle); } } } private static bool HasXData(EntityObject entity) { try { return entity.XData != null && entity.XData.Count > 0; } catch { return false; } } private void AnalyzeUsedUCS(List entities, DxfCodeGenerationOptions options) { // For now, we'll include all UCS objects in the document since they are typically // standalone coordinate system definitions that may be referenced by name // In a more sophisticated implementation, we could track which UCS objects are actually used } private void AnalyzeUsedVPorts(List entities, DxfCodeGenerationOptions options) { // For now, we'll include all VPort objects in the document since they are typically // viewport definitions that may be referenced by name // In a more sophisticated implementation, we could track which VPort objects are actually used // Only include the active viewport (*Active) if it has been modified from defaults // This will be checked later in the generation phase } private void AnalyzeUsedViews(List entities, DxfCodeGenerationOptions options) { // For now, we'll include all View objects in the document since they are typically // view definitions that may be referenced by name // In a more sophisticated implementation, we could track which View objects are actually used // Note: Views collection is internal in netDxf, so we generate placeholder objects } private void GenerateTableDefinitions(StringBuilder sb, DxfDocument doc, DxfCodeGenerationOptions options, string baseIndent) { // Generate layer definitions if (options.GenerateLayers && _usedLayers.Count > 0) { if (options.GenerateDetailedComments) { sb.AppendLine($"{baseIndent}// Layer definitions"); } foreach (var layerName in _usedLayers.OrderBy(x => x)) { var layer = doc.Layers.FirstOrDefault(l => l.Name == layerName); if (layer != null) { sb.AppendLine($"{baseIndent}var layer{SafeName(layerName)} = new Layer(\"{Escape(layerName)}\")"); sb.AppendLine(baseIndent + "{"); if (layer.Color.Index != 7) // Default color is 7 (white) sb.AppendLine($"{baseIndent} Color = new AciColor({layer.Color.Index}),"); if (layer.Lineweight != Lineweight.Default) sb.AppendLine($"{baseIndent} Lineweight = Lineweight.{layer.Lineweight},"); if (!layer.IsVisible) sb.AppendLine($"{baseIndent} IsVisible = false,"); if (layer.IsFrozen) sb.AppendLine($"{baseIndent} IsFrozen = true,"); if (layer.IsLocked) sb.AppendLine($"{baseIndent} IsLocked = true,"); sb.AppendLine(baseIndent + "};"); sb.AppendLine($"{baseIndent}doc.Layers.Add(layer{SafeName(layerName)});"); sb.AppendLine(); } else if (layerName == "0") { // Handle default layer "0" which might not be in the layers collection sb.AppendLine($"{baseIndent}var layer{SafeName(layerName)} = doc.Layers[\"{layerName}\"];"); sb.AppendLine(); } } } if (options.GenerateLinetypes && options.GenerateTextStyles) { foreach (var linetypeName in _usedLinetypes) { var linetype = doc.Linetypes.FirstOrDefault(lt => lt.Name == linetypeName); if (linetype == null) { continue; } foreach (var segment in linetype.Segments) { if (segment is LinetypeTextSegment textSegment && textSegment.Style != null) { _usedTextStyles.Add(textSegment.Style.Name); } } } } // Generate text style definitions (if any custom ones) if (options.GenerateTextStyles && _usedTextStyles.Any(ts => ts != "Standard")) { if (options.GenerateDetailedComments) { sb.AppendLine($"{baseIndent}// Text style definitions"); } foreach (var styleName in _usedTextStyles.Where(ts => ts != "Standard").OrderBy(x => x)) { var style = doc.TextStyles.FirstOrDefault(ts => ts.Name == styleName); if (style != null) { var fontFile = !string.IsNullOrEmpty(style.FontFile) ? style.FontFile : TextStyle.DefaultFont; sb.AppendLine($"{baseIndent}var textStyle{SafeName(styleName)} = new TextStyle(\"{Escape(styleName)}\", \"{Escape(fontFile)}\");"); sb.AppendLine($"{baseIndent}doc.TextStyles.Add(textStyle{SafeName(styleName)});"); } } sb.AppendLine(); } // Generate shape style definitions (if any custom ones) if (options.GenerateShapeStyleObjects && doc.ShapeStyles.Count > 0) { if (options.GenerateDetailedComments) { sb.AppendLine($"{baseIndent}// ShapeStyle definitions"); } foreach (var shapeStyle in doc.ShapeStyles.OrderBy(s => s.Name)) { sb.AppendLine($"{baseIndent}var shapeStyle{SafeName(shapeStyle.Name)} = new ShapeStyle(\"{Escape(shapeStyle.Name)}\", \"{Escape(shapeStyle.File)}\");"); sb.AppendLine($"{baseIndent}doc.ShapeStyles.Add(shapeStyle{SafeName(shapeStyle.Name)});"); } sb.AppendLine(); } // Generate linetype definitions (if any custom ones) if (options.GenerateLinetypes && _usedLinetypes.Any(lt => lt != "Continuous" && lt != "ByLayer" && lt != "ByBlock")) { if (options.GenerateDetailedComments) { sb.AppendLine($"{baseIndent}// Linetype definitions"); } foreach (var linetypeName in _usedLinetypes.Where(lt => lt != "Continuous" && lt != "ByLayer" && lt != "ByBlock").OrderBy(x => x)) { var linetype = doc.Linetypes.FirstOrDefault(lt => lt.Name == linetypeName); if (linetype != null) { var linetypeVar = $"linetype{SafeName(linetypeName)}"; sb.AppendLine($"{baseIndent}var {linetypeVar} = new Linetype(\"{Escape(linetypeName)}\");"); if (!string.IsNullOrEmpty(linetype.Description)) { sb.AppendLine($"{baseIndent}{linetypeVar}.Description = \"{Escape(linetype.Description)}\";"); } if (linetype.Segments.Count > 0) { sb.AppendLine($"{baseIndent}{linetypeVar}.Segments.Clear();"); for (var i = 0; i < linetype.Segments.Count; i++) { var segment = linetype.Segments[i]; var segmentVar = $"{linetypeVar}Segment{i}"; switch (segment) { case LinetypeSimpleSegment simple: sb.AppendLine($"{baseIndent}var {segmentVar} = new LinetypeSimpleSegment({F(simple.Length)});"); sb.AppendLine($"{baseIndent}{linetypeVar}.Segments.Add({segmentVar});"); break; case LinetypeTextSegment textSegment: var styleRef = textSegment.Style?.Name == null || textSegment.Style.Name == "Standard" ? "TextStyle.Default" : $"textStyle{SafeName(textSegment.Style.Name)}"; sb.AppendLine($"{baseIndent}var {segmentVar} = new LinetypeTextSegment(\"{Escape(textSegment.Text)}\", {styleRef}, {F(textSegment.Length)})"); sb.AppendLine($"{baseIndent}{{"); if (Math.Abs(textSegment.Offset.X) > 1e-9 || Math.Abs(textSegment.Offset.Y) > 1e-9) sb.AppendLine($"{baseIndent} Offset = new Vector2({F(textSegment.Offset.X)}, {F(textSegment.Offset.Y)}),"); if (textSegment.RotationType != LinetypeSegmentRotationType.Relative) sb.AppendLine($"{baseIndent} RotationType = LinetypeSegmentRotationType.{textSegment.RotationType},"); if (Math.Abs(textSegment.Rotation) > 1e-9) sb.AppendLine($"{baseIndent} Rotation = {F(textSegment.Rotation)},"); if (Math.Abs(textSegment.Scale - 1.0) > 1e-9) sb.AppendLine($"{baseIndent} Scale = {F(textSegment.Scale)},"); sb.AppendLine($"{baseIndent}}};"); sb.AppendLine($"{baseIndent}{linetypeVar}.Segments.Add({segmentVar});"); break; case LinetypeShapeSegment shapeSegment: var shapeStyleVar = $"shapeStyle{SafeName(shapeSegment.Style.Name)}"; sb.AppendLine($"{baseIndent}var {segmentVar} = new LinetypeShapeSegment(\"{Escape(shapeSegment.Name)}\", {shapeStyleVar}, {F(shapeSegment.Length)})"); sb.AppendLine($"{baseIndent}{{"); if (Math.Abs(shapeSegment.Offset.X) > 1e-9 || Math.Abs(shapeSegment.Offset.Y) > 1e-9) sb.AppendLine($"{baseIndent} Offset = new Vector2({F(shapeSegment.Offset.X)}, {F(shapeSegment.Offset.Y)}),"); if (shapeSegment.RotationType != LinetypeSegmentRotationType.Relative) sb.AppendLine($"{baseIndent} RotationType = LinetypeSegmentRotationType.{shapeSegment.RotationType},"); if (Math.Abs(shapeSegment.Rotation) > 1e-9) sb.AppendLine($"{baseIndent} Rotation = {F(shapeSegment.Rotation)},"); if (Math.Abs(shapeSegment.Scale - 1.0) > 1e-9) sb.AppendLine($"{baseIndent} Scale = {F(shapeSegment.Scale)},"); sb.AppendLine($"{baseIndent}}};"); sb.AppendLine($"{baseIndent}{linetypeVar}.Segments.Add({segmentVar});"); break; } } } sb.AppendLine($"{baseIndent}doc.Linetypes.Add({linetypeVar});"); } } sb.AppendLine(); } // Generate block definitions (if any used) if (options.GenerateBlocks && _usedBlocks.Count > 0) { if (options.GenerateDetailedComments) { sb.AppendLine($"{baseIndent}// Block definitions"); } // For block entity generation, ignore per-entity enable/disable flags by overriding them to true var blockEntityOptions = options with { GenerateLineEntities = true, GenerateArcEntities = true, GenerateAttributeDefinitionEntities = true, GenerateCircleEntities = true, GeneratePolylineEntities = true, GeneratePolyline2DEntities = true, GeneratePolyline3DEntities = true, GenerateTextEntities = true, GenerateMTextEntities = true, GeneratePointEntities = true, GenerateInsertEntities = true, GenerateHatchEntities = true, GenerateDimensionEntities = true, GenerateLinearDimensionEntities = true, GenerateAlignedDimensionEntities = true, GenerateRadialDimensionEntities = true, GenerateDiametricDimensionEntities = true, GenerateAngular2LineDimensionEntities = true, GenerateAngular3PointDimensionEntities = true, GenerateOrdinateDimensionEntities = true, GenerateArcLengthDimensionEntities = true, GenerateLeaderEntities = true, GenerateSplineEntities = true, GenerateEllipseEntities = true, GenerateSolidEntities = true, GenerateFace3dEntities = true, GenerateMLineEntities = true, GenerateRayEntities = true, GenerateXLineEntities = true, GenerateWipeoutEntities = true, GenerateImageEntities = true, GenerateMeshEntities = true, GeneratePolyfaceMeshEntities = true, GeneratePolygonMeshEntities = true, GenerateShapeEntities = true, GenerateToleranceEntities = true, GenerateTraceEntities = true, GenerateUnderlayEntities = true, GenerateViewportEntities = true }; foreach (var blockName in _usedBlocks.OrderBy(x => x)) { var block = doc.Blocks.FirstOrDefault(b => b.Name == blockName); if (block != null) { sb.AppendLine($"{baseIndent}var block{SafeName(blockName)} = new Block(\"{Escape(blockName)}\")"); sb.AppendLine(baseIndent + "{"); sb.AppendLine($"{baseIndent} Origin = new Vector3({F(block.Origin.X)}, {F(block.Origin.Y)}, {F(block.Origin.Z)}),"); if (!string.IsNullOrEmpty(block.Description)) sb.AppendLine($"{baseIndent} Description = \"{Escape(block.Description)}\","); if (block.Layer?.Name != "0" && block.Layer != null) sb.AppendLine($"{baseIndent} Layer = new Layer(\"{Escape(block.Layer.Name)}\"),"); sb.AppendLine(baseIndent + "};"); // Add attribute definitions if any if (options.GenerateAttributeDefinitionEntities && block.AttributeDefinitions.Count > 0) { foreach (var attDef in block.AttributeDefinitions.Values) { var textStyleName = attDef.Style?.Name ?? "Standard"; if (textStyleName == "Standard") { sb.AppendLine($"{baseIndent}var attDef{SafeName(blockName)}{SafeName(attDef.Tag)} = new AttributeDefinition(\"{Escape(attDef.Tag)}\", {F(attDef.Height)}, TextStyle.Default)"); } else { sb.AppendLine($"{baseIndent}var attDef{SafeName(blockName)}{SafeName(attDef.Tag)} = new AttributeDefinition(\"{Escape(attDef.Tag)}\", {F(attDef.Height)}, textStyle{SafeName(textStyleName)})"); } sb.AppendLine(baseIndent + "{"); // Basic properties if (!string.IsNullOrEmpty(attDef.Prompt)) sb.AppendLine($"{baseIndent} Prompt = \"{Escape(attDef.Prompt)}\","); if (!string.IsNullOrEmpty(attDef.Value)) sb.AppendLine($"{baseIndent} Value = \"{Escape(attDef.Value)}\","); // Position and dimensions if (attDef.Position != Vector3.Zero) sb.AppendLine($"{baseIndent} Position = new Vector3({F(attDef.Position.X)}, {F(attDef.Position.Y)}, {F(attDef.Position.Z)}),"); if (Math.Abs(attDef.Height - 1.0) > 1e-10) sb.AppendLine($"{baseIndent} Height = {F(attDef.Height)},"); if (Math.Abs(attDef.Width - 1.0) > 1e-10) sb.AppendLine($"{baseIndent} Width = {F(attDef.Width)},"); if (Math.Abs(attDef.WidthFactor - 1.0) > 1e-10) sb.AppendLine($"{baseIndent} WidthFactor = {F(attDef.WidthFactor)},"); // Text formatting if (Math.Abs(attDef.Rotation) > 1e-12) sb.AppendLine($"{baseIndent} Rotation = {F(attDef.Rotation)},"); if (Math.Abs(attDef.ObliqueAngle) > 1e-10) sb.AppendLine($"{baseIndent} ObliqueAngle = {F(attDef.ObliqueAngle)},"); if (attDef.Alignment != TextAlignment.BaselineLeft) sb.AppendLine($"{baseIndent} Alignment = TextAlignment.{attDef.Alignment},"); if (attDef.IsBackward) sb.AppendLine($"{baseIndent} IsBackward = true,"); if (attDef.IsUpsideDown) sb.AppendLine($"{baseIndent} IsUpsideDown = true,"); // Style and flags if (attDef.Style != null && attDef.Style.Name != "Standard" && _usedTextStyles.Contains(attDef.Style.Name)) sb.AppendLine($"{baseIndent} Style = textStyle{SafeName(attDef.Style.Name)},"); if (attDef.Flags != AttributeFlags.None) sb.AppendLine($"{baseIndent} Flags = AttributeFlags.{attDef.Flags},"); // Entity properties (Layer, Color, etc.) if (attDef.Layer != null && _usedLayers.Contains(attDef.Layer.Name)) sb.AppendLine($"{baseIndent} Layer = layer{SafeName(attDef.Layer.Name)},"); if (attDef.Color.Index != 256) // Not ByLayer { if (attDef.Color.Index == 0) sb.AppendLine($"{baseIndent} Color = AciColor.ByBlock,"); else if (attDef.Color.Index is >= 1 and <= 255) sb.AppendLine($"{baseIndent} Color = new AciColor({attDef.Color.Index}),"); } if (attDef.Linetype != null && attDef.Linetype.Name != "ByLayer" && attDef.Linetype.Name != "Continuous") { if (attDef.Linetype.Name == "ByBlock") sb.AppendLine($"{baseIndent} Linetype = Linetype.ByBlock,"); else sb.AppendLine($"{baseIndent} Linetype = linetype{SafeName(attDef.Linetype.Name)},"); } if (attDef.Lineweight != Lineweight.ByLayer) sb.AppendLine($"{baseIndent} Lineweight = Lineweight.{attDef.Lineweight},"); if (Math.Abs(attDef.LinetypeScale - 1.0) > 1e-10) sb.AppendLine($"{baseIndent} LinetypeScale = {F(attDef.LinetypeScale)},"); if (!attDef.IsVisible) sb.AppendLine($"{baseIndent} IsVisible = false,"); if (attDef.Normal != Vector3.UnitZ) sb.AppendLine($"{baseIndent} Normal = new Vector3({F(attDef.Normal.X)}, {F(attDef.Normal.Y)}, {F(attDef.Normal.Z)}),"); sb.AppendLine(baseIndent + "};"); sb.AppendLine($"{baseIndent}block{SafeName(blockName)}.AttributeDefinitions.Add(attDef{SafeName(blockName)}{SafeName(attDef.Tag)});"); } sb.AppendLine(); } // Add block entities if (block.Entities.Count > 0) { foreach (var entity in block.Entities) { // Generate simplified entity code for block entities with all entity types enabled GenerateBlockEntity(sb, entity, blockName, blockEntityOptions, baseIndent); } sb.AppendLine(); } sb.AppendLine($"{baseIndent}doc.Blocks.Add(block{SafeName(blockName)});"); sb.AppendLine(); } } } // Generate dimension style definitions (if any custom ones) if (options.GenerateDimensionStyles && _usedDimensionStyles.Any(ds => ds != "Standard")) { if (options.GenerateDetailedComments) { sb.AppendLine($"{baseIndent}// Dimension style definitions"); } foreach (var styleName in _usedDimensionStyles.Where(ds => ds != "Standard")) { var style = doc.DimensionStyles.FirstOrDefault(ds => ds.Name == styleName); if (style != null) { sb.AppendLine($"{baseIndent}var dimStyle{SafeName(styleName)} = new DimensionStyle(\"{Escape(styleName)}\");"); sb.AppendLine($"{baseIndent}doc.DimensionStyles.Add(dimStyle{SafeName(styleName)});"); } } sb.AppendLine(); } // Generate multiline style definitions (if any custom ones) if (options.GenerateMLineStyles && _usedMLineStyles.Any(ms => ms != "Standard")) { if (options.GenerateDetailedComments) { sb.AppendLine($"{baseIndent}// Multiline style definitions"); } foreach (var styleName in _usedMLineStyles.Where(ms => ms != "Standard")) { var style = doc.MlineStyles.FirstOrDefault(ms => ms.Name == styleName); if (style != null) { GenerateMLineStyle(sb, style, baseIndent); } } sb.AppendLine(); } // Generate UCS definitions (if any custom ones) if (options.GenerateUCS && doc.UCSs.Count > 0) { if (options.GenerateDetailedComments) { sb.AppendLine($"{baseIndent}// UCS definitions"); } foreach (var ucs in doc.UCSs.Where(u => u.Name != "*ACTIVE")) { sb.AppendLine($"{baseIndent}var ucs{SafeName(ucs.Name)} = new UCS("); sb.AppendLine($"{baseIndent} \"{Escape(ucs.Name)}\","); sb.AppendLine($"{baseIndent} new Vector3({F(ucs.Origin.X)}, {F(ucs.Origin.Y)}, {F(ucs.Origin.Z)}),"); sb.AppendLine($"{baseIndent} new Vector3({F(ucs.XAxis.X)}, {F(ucs.XAxis.Y)}, {F(ucs.XAxis.Z)}),"); sb.AppendLine($"{baseIndent} new Vector3({F(ucs.YAxis.X)}, {F(ucs.YAxis.Y)}, {F(ucs.YAxis.Z)}));"); sb.AppendLine($"{baseIndent}doc.UCSs.Add(ucs{SafeName(ucs.Name)});"); sb.AppendLine(); } } // Generate VPort definitions (modify the active viewport) if (options.GenerateVPorts && doc.Viewport != null) { var vport = doc.Viewport; var hasNonDefaultValues = false; var viewportCode = new StringBuilder(); // Check if any properties differ from defaults and build the code if (vport.ViewCenter.X != 0 || vport.ViewCenter.Y != 0) { viewportCode.AppendLine($"{baseIndent}activeViewport.ViewCenter = new Vector2({F(vport.ViewCenter.X)}, {F(vport.ViewCenter.Y)});"); hasNonDefaultValues = true; } if (Math.Abs(vport.ViewHeight - 10) > 1e-6) // Default height is 10 { viewportCode.AppendLine($"{baseIndent}activeViewport.ViewHeight = {F(vport.ViewHeight)};"); hasNonDefaultValues = true; } if (Math.Abs(vport.ViewAspectRatio - 1.0) > 1e-6) // Default aspect ratio is 1.0 { viewportCode.AppendLine($"{baseIndent}activeViewport.ViewAspectRatio = {F(vport.ViewAspectRatio)};"); hasNonDefaultValues = true; } if (vport.ViewTarget.X != 0 || vport.ViewTarget.Y != 0 || vport.ViewTarget.Z != 0) { viewportCode.AppendLine($"{baseIndent}activeViewport.ViewTarget = new Vector3({F(vport.ViewTarget.X)}, {F(vport.ViewTarget.Y)}, {F(vport.ViewTarget.Z)});"); hasNonDefaultValues = true; } if (vport.ViewDirection.X != 0 || vport.ViewDirection.Y != 0 || Math.Abs(vport.ViewDirection.Z - 1) > 1e-6) // Default direction is UnitZ { viewportCode.AppendLine($"{baseIndent}activeViewport.ViewDirection = new Vector3({F(vport.ViewDirection.X)}, {F(vport.ViewDirection.Y)}, {F(vport.ViewDirection.Z)});"); hasNonDefaultValues = true; } if (!vport.ShowGrid) // Default is true { viewportCode.AppendLine($"{baseIndent}activeViewport.ShowGrid = false;"); hasNonDefaultValues = true; } if (vport.SnapMode) // Default is false { viewportCode.AppendLine($"{baseIndent}activeViewport.SnapMode = true;"); hasNonDefaultValues = true; } if (Math.Abs(vport.SnapSpacing.X - 0.5) > 1e-6 || Math.Abs(vport.SnapSpacing.Y - 0.5) > 1e-6) // Default is 0.5 { viewportCode.AppendLine($"{baseIndent}activeViewport.SnapSpacing = new Vector2({F(vport.SnapSpacing.X)}, {F(vport.SnapSpacing.Y)});"); hasNonDefaultValues = true; } if (Math.Abs(vport.GridSpacing.X - 10.0) > 1e-6 || Math.Abs(vport.GridSpacing.Y - 10.0) > 1e-6) // Default is 10.0 { viewportCode.AppendLine($"{baseIndent}activeViewport.GridSpacing = new Vector2({F(vport.GridSpacing.X)}, {F(vport.GridSpacing.Y)});"); hasNonDefaultValues = true; } if (vport.SnapBasePoint.X != 0 || vport.SnapBasePoint.Y != 0) { viewportCode.AppendLine($"{baseIndent}activeViewport.SnapBasePoint = new Vector2({F(vport.SnapBasePoint.X)}, {F(vport.SnapBasePoint.Y)});"); hasNonDefaultValues = true; } // Only generate the viewport variable and code if there are non-default values if (hasNonDefaultValues) { if (options.GenerateDetailedComments) { sb.AppendLine($"{baseIndent}// VPort (Viewport) configuration"); } sb.AppendLine($"{baseIndent}var activeViewport = doc.Viewport;"); sb.Append(viewportCode); sb.AppendLine(); } } // Generate ApplicationRegistry definitions (if any custom ones) if (options.GenerateApplicationRegistryObjects && doc.ApplicationRegistries.Count > 0) { var customAppRegs = doc.ApplicationRegistries.Where(ar => ar.Name != "ACAD").ToList(); if (customAppRegs.Any()) { if (options.GenerateDetailedComments) { sb.AppendLine($"{baseIndent}// ApplicationRegistry definitions"); } foreach (var appReg in customAppRegs) { sb.AppendLine($"{baseIndent}var appReg{SafeName(appReg.Name)} = new ApplicationRegistry(\"{Escape(appReg.Name)}\");"); sb.AppendLine($"{baseIndent}doc.ApplicationRegistries.Add(appReg{SafeName(appReg.Name)});"); } sb.AppendLine(); } } // Generate View definitions (if any custom ones) // Note: Views collection is internal in netDxf, but we can generate View objects // that could be used if the API becomes public in the future if (options.GenerateViews && _usedViews.Any()) { if (options.GenerateDetailedComments) { sb.AppendLine($"{baseIndent}// View definitions (Views collection is internal in netDxf)"); sb.AppendLine($"{baseIndent}// These View objects are generated for reference but cannot be added to the document"); } foreach (var viewName in _usedViews) { // Since we cannot access the actual View objects from the internal collection, // we generate placeholder View creation code with common properties GenerateViewPlaceholder(sb, viewName, baseIndent); } sb.AppendLine(); } } private void GenerateEntities(StringBuilder sb, List entities, DxfCodeGenerationOptions options, string baseIndent) { if (options.GenerateDetailedComments) { sb.AppendLine($"{baseIndent}// Entities"); } foreach (var entity in entities) { GenerateEntity(sb, entity, options, baseIndent); } } private void GenerateEntity(StringBuilder sb, EntityObject entity, DxfCodeGenerationOptions options, string baseIndent) { if (options.GenerateDetailedComments) { sb.AppendLine($"{baseIndent}// {entity.GetType().Name}: {entity.Handle}"); } // Check if this entity needs to be generated as a variable var needsVariable = _entitiesNeedingVariables.Contains(entity.Handle) || HasXData(entity); switch (entity) { case Line line when options.GenerateLineEntities: GenerateLine(sb, line, needsVariable, baseIndent); break; case Arc arc when options.GenerateArcEntities: GenerateArc(sb, arc, needsVariable, baseIndent); break; case Circle circle when options.GenerateCircleEntities: GenerateCircle(sb, circle, needsVariable, baseIndent); break; case PointEntity point when options.GeneratePointEntities: GeneratePoint(sb, point, needsVariable, baseIndent); break; case Polyline2D poly2d when options.GeneratePolyline2DEntities: GeneratePolyline2D(sb, poly2d, baseIndent); break; case Polyline3D poly3d when options.GeneratePolyline3DEntities: GeneratePolyline3D(sb, poly3d, needsVariable, baseIndent); break; case Spline spline when options.GenerateSplineEntities: GenerateSpline(sb, spline, baseIndent); break; case Text text when options.GenerateTextEntities: GenerateText(sb, text, needsVariable, baseIndent); break; case MText mtext when options.GenerateMTextEntities: GenerateMText(sb, mtext, needsVariable, baseIndent); break; case Ellipse ellipse when options.GenerateEllipseEntities: GenerateEllipse(sb, ellipse, needsVariable, baseIndent); break; case Insert insert when options.GenerateInsertEntities: GenerateInsert(sb, insert, needsVariable, baseIndent); break; case Hatch hatch when options.GenerateHatchEntities: GenerateHatch(sb, hatch, needsVariable, baseIndent); break; case Wipeout wipeout when options.GenerateWipeoutEntities: GenerateWipeout(sb, wipeout, needsVariable, baseIndent); break; case Leader leader when options.GenerateLeaderEntities: GenerateLeader(sb, leader, needsVariable, baseIndent); break; case Face3D face3d when options.GenerateFace3dEntities: GenerateFace3D(sb, face3d, baseIndent); break; case LinearDimension linearDim when options is { GenerateDimensionEntities: true, GenerateLinearDimensionEntities: true }: GenerateLinearDimension(sb, linearDim, baseIndent); break; case AlignedDimension alignedDim when options is { GenerateDimensionEntities: true, GenerateAlignedDimensionEntities: true }: GenerateAlignedDimension(sb, alignedDim, baseIndent); break; case RadialDimension radialDim when options is { GenerateDimensionEntities: true, GenerateRadialDimensionEntities: true }: GenerateRadialDimension(sb, radialDim, baseIndent); break; case DiametricDimension diametricDim when options is { GenerateDimensionEntities: true, GenerateDiametricDimensionEntities: true }: GenerateDiametricDimension(sb, diametricDim, baseIndent); break; case Angular2LineDimension angular2LineDim when options is { GenerateDimensionEntities: true, GenerateAngular2LineDimensionEntities: true }: GenerateAngular2LineDimension(sb, angular2LineDim, baseIndent); break; case Angular3PointDimension angular3PointDim when options is { GenerateDimensionEntities: true, GenerateAngular3PointDimensionEntities: true }: GenerateAngular3PointDimension(sb, angular3PointDim, baseIndent); break; case OrdinateDimension ordinateDim when options is { GenerateDimensionEntities: true, GenerateOrdinateDimensionEntities: true }: GenerateOrdinateDimension(sb, ordinateDim, baseIndent); break; case ArcLengthDimension arcLengthDim when options is { GenerateDimensionEntities: true, GenerateArcLengthDimensionEntities: true }: GenerateArcLengthDimension(sb, arcLengthDim, baseIndent); break; case Ray ray when options.GenerateRayEntities: GenerateRay(sb, ray, baseIndent); break; case XLine xline when options.GenerateXLineEntities: GenerateXLine(sb, xline, baseIndent); break; case Solid solid when options.GenerateSolidEntities: GenerateSolid(sb, solid, baseIndent); break; case MLine mline when options.GenerateMLineEntities: GenerateMLine(sb, mline, needsVariable, baseIndent); break; case Image image when options.GenerateImageEntities: GenerateImage(sb, image, needsVariable, baseIndent); break; case Mesh mesh when options.GenerateMeshEntities: GenerateMesh(sb, mesh, needsVariable, baseIndent); break; case PolyfaceMesh polyfaceMesh when options.GeneratePolyfaceMeshEntities: GeneratePolyfaceMesh(sb, polyfaceMesh, needsVariable, baseIndent); break; case PolygonMesh polygonMesh when options.GeneratePolygonMeshEntities: GeneratePolygonMesh(sb, polygonMesh, baseIndent); break; case Shape shape when options.GenerateShapeEntities: GenerateShape(sb, shape, baseIndent); break; case Tolerance tolerance when options.GenerateToleranceEntities: GenerateTolerance(sb, tolerance, baseIndent); break; case Trace trace when options.GenerateTraceEntities: GenerateTrace(sb, trace, baseIndent); break; case Underlay underlay when options.GenerateUnderlayEntities: GenerateUnderlay(sb, underlay, baseIndent); break; case Viewport viewport when options.GenerateViewportEntities: GenerateViewport(sb, viewport, baseIndent); break; default: if (options.GenerateDetailedComments) { sb.AppendLine($"{baseIndent}// Skipped entity type: {entity.GetType().Name}"); } break; } } private void GenerateObjects(StringBuilder sb, DxfDocument doc, DxfCodeGenerationOptions options, string baseIndent) { if (options.GenerateDetailedComments) { sb.AppendLine($"{baseIndent}// Objects"); } // Generate Groups if (options.GenerateGroupObjects && doc.Groups.Count > 0) { if (options.GenerateDetailedComments) { sb.AppendLine($"{baseIndent}// Groups"); } foreach (var group in doc.Groups) { GenerateGroup(sb, group, options, baseIndent); } sb.AppendLine(); } // Generate Layouts if (options.GenerateLayoutObjects && doc.Layouts.Count > 0) { // Skip the default "Model" layout as it's automatically created var customLayouts = doc.Layouts.Where(layout => !string.Equals(layout.Name, "Model", StringComparison.OrdinalIgnoreCase)).ToList(); if (customLayouts.Any()) { if (options.GenerateDetailedComments) { sb.AppendLine($"{baseIndent}// Layouts"); } foreach (var layout in customLayouts) { GenerateLayout(sb, layout, options, baseIndent); } sb.AppendLine(); } } // Generate Image Definitions if (options.GenerateImageDefinitionObjects) { var imageDefinitions = doc.ImageDefinitions.Items.Where(item => item != null).ToList(); if (imageDefinitions.Any()) { if (options.GenerateDetailedComments) { sb.AppendLine($"{baseIndent}// Image Definitions"); } foreach (var imageDef in imageDefinitions) { GenerateImageDefinition(sb, imageDef, options, baseIndent); } sb.AppendLine(); } } // Generate Underlay Definitions if (options.GenerateUnderlayDefinitionObjects) { var underlayDefinitions = doc.UnderlayDgnDefinitions.Items .Concat(doc.UnderlayDwfDefinitions.Items.Cast()) .Concat(doc.UnderlayPdfDefinitions.Items) .Where(item => item != null) .ToList(); if (underlayDefinitions.Any()) { if (options.GenerateDetailedComments) { sb.AppendLine($"{baseIndent}// Underlay Definitions"); } foreach (var underlayDef in underlayDefinitions) { GenerateUnderlayDefinition(sb, underlayDef, options, baseIndent); } sb.AppendLine(); } } // Generate RasterVariables if (options.GenerateRasterVariablesObjects && doc.RasterVariables != null) { if (options.GenerateDetailedComments) { sb.AppendLine($"{baseIndent}// Raster Variables"); } GenerateRasterVariables(sb, doc.RasterVariables, options, baseIndent); sb.AppendLine(); } // Generate LayerState objects if (options.GenerateLayerStateObjects) { GenerateLayerStatePlaceholder(sb, options, baseIndent); } // Generate PlotSettings objects if (options.GeneratePlotSettingsObjects) { GeneratePlotSettingsPlaceholder(sb, options, baseIndent); } // Generate XRecord objects if (options.GenerateXRecordObjects) { GenerateXRecordPlaceholder(sb, options, baseIndent); } // Generate Dictionary objects if (options.GenerateDictionaryObjects) { GenerateDictionaryObjectPlaceholder(sb, options, baseIndent); } // Generate MLineStyle objects if (options is { GenerateMLineStyleObjects: true, GenerateDetailedComments: true }) // Note: MLineStyle objects are typically stored in dictionaries // This is a placeholder for when MLineStyle access is available { sb.AppendLine($"{baseIndent}// MLineStyle objects (stored in dictionaries - not directly accessible)"); } } private void GenerateLine(StringBuilder sb, Line line, bool asVariable = false, string baseIndent = " ") { if (asVariable) { sb.AppendLine($"{baseIndent}var entity{line.Handle} = "); GenerateLineConstructor(sb, line, baseIndent + " "); sb.AppendLine($"{baseIndent} {{"); GenerateEntityPropertiesCore(sb, line, baseIndent + " "); sb.AppendLine($"{baseIndent} }};"); GenerateXData(sb, line, $"entity{line.Handle}", baseIndent); sb.AppendLine($"{baseIndent}doc.Entities.Add(entity{line.Handle});"); } else { sb.AppendLine($"{baseIndent}doc.Entities.Add("); GenerateLineConstructor(sb, line, baseIndent + " "); sb.AppendLine($"{baseIndent} {{"); GenerateEntityPropertiesCore(sb, line, baseIndent + " "); sb.AppendLine($"{baseIndent} }}"); sb.AppendLine($"{baseIndent});"); } } private void GenerateLineConstructor(StringBuilder sb, Line line, string indent) { sb.AppendLine($"{indent}new Line("); sb.AppendLine($"{indent} new Vector3({F(line.StartPoint.X)}, {F(line.StartPoint.Y)}, {F(line.StartPoint.Z)}),"); sb.AppendLine($"{indent} new Vector3({F(line.EndPoint.X)}, {F(line.EndPoint.Y)}, {F(line.EndPoint.Z)}))"); } private void GenerateArc(StringBuilder sb, Arc arc, bool asVariable = false, string baseIndent = " ") { if (asVariable) { sb.AppendLine($"{baseIndent}var entity{arc.Handle} = "); GenerateArcConstructor(sb, arc, baseIndent); sb.AppendLine($"{baseIndent}{{"); GenerateEntityPropertiesCore(sb, arc, baseIndent); sb.AppendLine($"{baseIndent}}};"); GenerateXData(sb, arc, $"entity{arc.Handle}", baseIndent); sb.AppendLine($"{baseIndent}doc.Entities.Add(entity{arc.Handle});"); } else { sb.AppendLine($"{baseIndent}doc.Entities.Add("); GenerateArcConstructor(sb, arc, baseIndent); sb.AppendLine($"{baseIndent}{{"); GenerateEntityPropertiesCore(sb, arc, baseIndent); sb.AppendLine($"{baseIndent}}}"); sb.AppendLine($"{baseIndent});"); } } private void GenerateArcConstructor(StringBuilder sb, Arc arc, string indent) { sb.AppendLine($"{indent}new Arc("); sb.AppendLine($"{indent} new Vector3({F(arc.Center.X)}, {F(arc.Center.Y)}, {F(arc.Center.Z)}),"); sb.AppendLine($"{indent} {F(arc.Radius)}, {F(arc.StartAngle)}, {F(arc.EndAngle)})"); } private void GenerateCircle(StringBuilder sb, Circle circle, bool asVariable = false, string baseIndent = " ") { if (asVariable) { sb.AppendLine($"{baseIndent}var entity{circle.Handle} = "); GenerateCircleConstructor(sb, circle, baseIndent); sb.AppendLine($"{baseIndent}{{"); GenerateEntityPropertiesCore(sb, circle, baseIndent); sb.AppendLine($"{baseIndent}}};"); GenerateXData(sb, circle, $"entity{circle.Handle}", baseIndent); sb.AppendLine($"{baseIndent}doc.Entities.Add(entity{circle.Handle});"); } else { sb.AppendLine($"{baseIndent}doc.Entities.Add("); GenerateCircleConstructor(sb, circle, baseIndent); sb.AppendLine($"{baseIndent}{{"); GenerateEntityPropertiesCore(sb, circle, baseIndent); sb.AppendLine($"{baseIndent}}}"); sb.AppendLine($"{baseIndent});"); } } private void GenerateCircleConstructor(StringBuilder sb, Circle circle, string indent) { sb.AppendLine($"{indent}new Circle("); sb.AppendLine($"{indent} new Vector3({F(circle.Center.X)}, {F(circle.Center.Y)}, {F(circle.Center.Z)}),"); sb.AppendLine($"{indent} {F(circle.Radius)})"); } private void GeneratePoint(StringBuilder sb, PointEntity point, bool asVariable = false, string baseIndent = " ") { if (asVariable) { sb.AppendLine($"{baseIndent}var entity{point.Handle} = "); sb.AppendLine($"{baseIndent}new Point("); sb.AppendLine($"{baseIndent} new Vector3({F(point.Position.X)}, {F(point.Position.Y)}, {F(point.Position.Z)}))"); sb.AppendLine($"{baseIndent}{{"); GenerateEntityPropertiesCore(sb, point, baseIndent + " "); sb.AppendLine($"{baseIndent}}};"); GenerateXData(sb, point, $"entity{point.Handle}", baseIndent); sb.AppendLine($"{baseIndent}doc.Entities.Add(entity{point.Handle});"); } else { sb.AppendLine($"{baseIndent}doc.Entities.Add("); sb.AppendLine($"{baseIndent}new Point("); sb.AppendLine($"{baseIndent} new Vector3({F(point.Position.X)}, {F(point.Position.Y)}, {F(point.Position.Z)}))"); sb.AppendLine($"{baseIndent}{{"); GenerateEntityPropertiesCore(sb, point, baseIndent + " "); sb.AppendLine($"{baseIndent}}}"); sb.AppendLine($"{baseIndent});"); } } private void GeneratePolyline2D(StringBuilder sb, Polyline2D poly2d, string baseIndent = " ") { sb.AppendLine($"{baseIndent}doc.Entities.Add("); GeneratePolyline2DConstructor(sb, poly2d, baseIndent); sb.AppendLine($"{baseIndent}{{"); GenerateEntityPropertiesCore(sb, poly2d, baseIndent); if (Math.Abs(poly2d.Elevation) > 1e-12) { sb.AppendLine($"{baseIndent} Elevation = {F(poly2d.Elevation)},"); } if (poly2d.LinetypeGeneration) { sb.AppendLine($"{baseIndent} LinetypeGeneration = true,"); } if (poly2d.SmoothType != PolylineSmoothType.NoSmooth) { sb.AppendLine($"{baseIndent} SmoothType = PolylineSmoothType.{poly2d.SmoothType},"); } sb.AppendLine($"{baseIndent}}}"); sb.AppendLine($"{baseIndent});"); } private void GeneratePolyline2DConstructor(StringBuilder sb, Polyline2D poly2d, string indent) { sb.AppendLine($"{indent}new Polyline2D(new List()"); sb.AppendLine($"{indent}{{"); foreach (var vertex in poly2d.Vertexes) { var vertexProps = new List(); if (Math.Abs(vertex.Bulge) > 1e-12) { vertexProps.Add($"Bulge = {F(vertex.Bulge)}"); } if (Math.Abs(vertex.StartWidth) > 1e-12) { vertexProps.Add($"StartWidth = {F(vertex.StartWidth)}"); } if (Math.Abs(vertex.EndWidth) > 1e-12) { vertexProps.Add($"EndWidth = {F(vertex.EndWidth)}"); } if (vertexProps.Count > 0) { sb.AppendLine($"{indent} new Polyline2DVertex({F(vertex.Position.X)}, {F(vertex.Position.Y)}) {{ {string.Join(", ", vertexProps)} }},"); } else { sb.AppendLine($"{indent} new Polyline2DVertex({F(vertex.Position.X)}, {F(vertex.Position.Y)}),"); } } sb.AppendLine($"{indent}}}, {(poly2d.IsClosed ? "true" : "false")})"); } private void GeneratePolyline3D(StringBuilder sb, Polyline3D poly3d, bool asVariable = false, string baseIndent = " ") { if (asVariable) { sb.AppendLine($"{baseIndent}var polyline3DEntity = new Polyline3D(new List()"); } else { sb.AppendLine($"{baseIndent}doc.Entities.Add(new Polyline3D(new List()"); } sb.AppendLine($"{baseIndent}{{"); foreach (var v in poly3d.Vertexes) { sb.AppendLine($"{baseIndent} new Vector3({F(v.X)}, {F(v.Y)}, {F(v.Z)}),"); } sb.AppendLine($"{baseIndent}}}, {(poly3d.IsClosed ? "true" : "false")})"); sb.AppendLine($"{baseIndent}{{"); GenerateEntityPropertiesCore(sb, poly3d, baseIndent); if (poly3d.LinetypeGeneration) { sb.AppendLine($"{baseIndent} LinetypeGeneration = true,"); } if (poly3d.SmoothType != PolylineSmoothType.NoSmooth) { sb.AppendLine($"{baseIndent} SmoothType = PolylineSmoothType.{poly3d.SmoothType},"); } sb.AppendLine($"{baseIndent}}}"); if (asVariable) { sb.AppendLine($"{baseIndent});"); } else { sb.AppendLine($"{baseIndent});"); } } private void GenerateSpline(StringBuilder sb, Spline spline, string baseIndent = " ") { // Generate spline with complete definition: control points, weights, and degree sb.AppendLine($"{baseIndent}{{"); sb.AppendLine($"{baseIndent} var controlPoints = new List"); sb.AppendLine($"{baseIndent} {{"); foreach (var cp in spline.ControlPoints) { sb.AppendLine($"{baseIndent} new Vector3({F(cp.X)}, {F(cp.Y)}, {F(cp.Z)}),"); } sb.AppendLine($"{baseIndent} }};"); sb.AppendLine(); sb.AppendLine($"{baseIndent} var weights = new List"); sb.AppendLine($"{baseIndent} {{"); foreach (var weight in spline.Weights) { sb.AppendLine($"{baseIndent} {F(weight)},"); } sb.AppendLine($"{baseIndent} }};"); sb.AppendLine(); sb.AppendLine($"{baseIndent} var knots = new List"); sb.AppendLine($"{baseIndent} {{"); foreach (var knot in spline.Knots) { sb.AppendLine($"{baseIndent} {F(knot)},"); } sb.AppendLine($"{baseIndent} }};"); sb.AppendLine(); if (spline.FitPoints is { Count: > 0 }) { sb.AppendLine($"{baseIndent} var splineFitPoints = new List"); sb.AppendLine($"{baseIndent} {{"); foreach (var fitPoint in spline.FitPoints) { sb.AppendLine($"{baseIndent} new Vector3({F(fitPoint.X)}, {F(fitPoint.Y)}, {F(fitPoint.Z)}),"); } sb.AppendLine($"{baseIndent} }};"); sb.AppendLine($"{baseIndent} _ = splineFitPoints; // Fit points retained for reference"); sb.AppendLine(); } var isClosedPeriodic = spline.IsClosedPeriodic ? "true" : "false"; sb.AppendLine($"{baseIndent} var splineEntity = new Spline(controlPoints, weights, knots, {spline.Degree}, {isClosedPeriodic});"); // Apply entity properties if (spline.Layer != null && _usedLayers.Contains(spline.Layer.Name)) { sb.AppendLine($"{baseIndent} splineEntity.Layer = layer{SafeName(spline.Layer.Name)};"); } // Color handling if (spline.Color.Index != 256) // Not ByLayer { if (spline.Color.Index == 0) sb.AppendLine($"{baseIndent} splineEntity.Color = AciColor.ByBlock;"); else if (spline.Color.Index is >= 1 and <= 255) sb.AppendLine($"{baseIndent} splineEntity.Color = new AciColor({spline.Color.Index});"); } // Linetype if (spline.Linetype != null && spline.Linetype.Name != "ByLayer" && spline.Linetype.Name != "Continuous") { if (spline.Linetype.Name == "ByBlock") sb.AppendLine($"{baseIndent} splineEntity.Linetype = Linetype.ByBlock;"); else sb.AppendLine($"{baseIndent} splineEntity.Linetype = linetype{SafeName(spline.Linetype.Name)};"); } // Lineweight if (spline.Lineweight != Lineweight.ByLayer) { sb.AppendLine($"{baseIndent} splineEntity.Lineweight = Lineweight.{spline.Lineweight};"); } // Linetype scale if (Math.Abs(spline.LinetypeScale - 1.0) > 1e-10) { sb.AppendLine($"{baseIndent} splineEntity.LinetypeScale = {F(spline.LinetypeScale)};"); } // Advanced spline properties GenerateSplineAdvancedProperties(sb, spline, baseIndent + " "); GenerateXData(sb, spline, "splineEntity", baseIndent + " "); sb.AppendLine($"{baseIndent} doc.Entities.Add(splineEntity);"); sb.AppendLine($"{baseIndent}}}"); } private void GenerateSplineConstructor(StringBuilder sb, Spline spline, string indent) { sb.AppendLine($"{indent}new Spline("); sb.AppendLine($"{indent} new List()"); sb.AppendLine($"{indent} {{"); foreach (var cp in spline.ControlPoints) { sb.AppendLine($"{indent} new Vector3({F(cp.X)}, {F(cp.Y)}, {F(cp.Z)}),"); } sb.AppendLine($"{indent} }},"); sb.AppendLine($"{indent} new List()"); sb.AppendLine($"{indent} {{"); foreach (var weight in spline.Weights) { sb.AppendLine($"{indent} {F(weight)},"); } sb.AppendLine($"{indent} }},"); sb.AppendLine($"{indent} new List()"); sb.AppendLine($"{indent} {{"); foreach (var knot in spline.Knots) { sb.AppendLine($"{indent} {F(knot)},"); } sb.AppendLine($"{indent} }},"); var closedPeriodicFlag = spline.IsClosedPeriodic ? "true" : "false"; sb.AppendLine($"{indent} {spline.Degree}, {closedPeriodicFlag})"); } private void GenerateText(StringBuilder sb, Text text, bool asVariable = false, string baseIndent = " ") { if (asVariable) { sb.AppendLine($"{baseIndent}var entity{text.Handle} = "); sb.AppendLine($"{baseIndent}new Text("); sb.AppendLine($"{baseIndent} \"{Escape(text.Value)}\","); sb.AppendLine($"{baseIndent} new Vector3({F(text.Position.X)}, {F(text.Position.Y)}, {F(text.Position.Z)}),"); sb.AppendLine($"{baseIndent} {F(text.Height)})"); sb.AppendLine($"{baseIndent}{{"); GenerateEntityPropertiesCore(sb, text, baseIndent); GenerateTextAdvancedProperties(sb, text, baseIndent); sb.AppendLine($"{baseIndent}}};"); GenerateXData(sb, text, $"entity{text.Handle}", baseIndent); sb.AppendLine($"{baseIndent}doc.Entities.Add(entity{text.Handle});"); } else { sb.AppendLine($"{baseIndent}doc.Entities.Add(new Text("); sb.AppendLine($"{baseIndent} \"{Escape(text.Value)}\","); sb.AppendLine($"{baseIndent} new Vector3({F(text.Position.X)}, {F(text.Position.Y)}, {F(text.Position.Z)}),"); sb.AppendLine($"{baseIndent} {F(text.Height)})"); sb.AppendLine($"{baseIndent}{{"); GenerateEntityPropertiesCore(sb, text, baseIndent); GenerateTextAdvancedProperties(sb, text, baseIndent); sb.AppendLine($"{baseIndent}}}"); sb.AppendLine($"{baseIndent});"); } } private void GenerateMText(StringBuilder sb, MText mtext, bool asVariable = false, string baseIndent = " ") { if (asVariable) { sb.AppendLine($"{baseIndent}var entity{mtext.Handle} = "); sb.AppendLine($"{baseIndent}new MText("); sb.AppendLine($"{baseIndent} \"{EscapeMText(mtext.Value)}\","); sb.AppendLine($"{baseIndent} new Vector3({F(mtext.Position.X)}, {F(mtext.Position.Y)}, {F(mtext.Position.Z)}),"); sb.AppendLine($"{baseIndent} {F(mtext.Height)})"); sb.AppendLine($"{baseIndent}{{"); GenerateEntityPropertiesCore(sb, mtext, baseIndent); if (mtext.Style?.Name != "Standard") { if (mtext.Style != null) { sb.AppendLine($"{baseIndent} Style = textStyle{SafeName(mtext.Style.Name)},"); } } if (mtext.RectangleWidth > 0) { sb.AppendLine($"{baseIndent} RectangleWidth = {F(mtext.RectangleWidth)},"); } if (mtext.AttachmentPoint != MTextAttachmentPoint.TopLeft) { sb.AppendLine($"{baseIndent} AttachmentPoint = MTextAttachmentPoint.{mtext.AttachmentPoint},"); } if (Math.Abs(mtext.Rotation) > 1e-12) { sb.AppendLine($"{baseIndent} Rotation = {F(mtext.Rotation)},"); } if (Math.Abs(mtext.LineSpacingFactor - 1.0) > 1e-12) { sb.AppendLine($"{baseIndent} LineSpacingFactor = {F(mtext.LineSpacingFactor)},"); } if (mtext.LineSpacingStyle != MTextLineSpacingStyle.AtLeast) { sb.AppendLine($"{baseIndent} LineSpacingStyle = MTextLineSpacingStyle.{mtext.LineSpacingStyle},"); } if (mtext.DrawingDirection != MTextDrawingDirection.ByStyle) { sb.AppendLine($"{baseIndent} DrawingDirection = MTextDrawingDirection.{mtext.DrawingDirection},"); } sb.AppendLine($"{baseIndent}}};"); GenerateXData(sb, mtext, $"entity{mtext.Handle}", baseIndent); sb.AppendLine($"{baseIndent}doc.Entities.Add(entity{mtext.Handle});"); } else { sb.AppendLine($"{baseIndent}doc.Entities.Add(new MText("); sb.AppendLine($"{baseIndent} \"{EscapeMText(mtext.Value)}\","); sb.AppendLine($"{baseIndent} new Vector3({F(mtext.Position.X)}, {F(mtext.Position.Y)}, {F(mtext.Position.Z)}),"); sb.AppendLine($"{baseIndent} {F(mtext.Height)})"); sb.AppendLine($"{baseIndent}{{"); GenerateEntityPropertiesCore(sb, mtext, baseIndent); if (mtext.Style?.Name != "Standard") { if (mtext.Style != null) { sb.AppendLine($"{baseIndent} Style = textStyle{SafeName(mtext.Style.Name!)},"); } } if (mtext.RectangleWidth > 0) { sb.AppendLine($"{baseIndent} RectangleWidth = {F(mtext.RectangleWidth)},"); } if (mtext.AttachmentPoint != MTextAttachmentPoint.TopLeft) { sb.AppendLine($"{baseIndent} AttachmentPoint = MTextAttachmentPoint.{mtext.AttachmentPoint},"); } if (Math.Abs(mtext.Rotation) > 1e-12) { sb.AppendLine($"{baseIndent} Rotation = {F(mtext.Rotation)},"); } if (Math.Abs(mtext.LineSpacingFactor - 1.0) > 1e-12) { sb.AppendLine($"{baseIndent} LineSpacingFactor = {F(mtext.LineSpacingFactor)},"); } if (mtext.LineSpacingStyle != MTextLineSpacingStyle.AtLeast) { sb.AppendLine($"{baseIndent} LineSpacingStyle = MTextLineSpacingStyle.{mtext.LineSpacingStyle},"); } if (mtext.DrawingDirection != MTextDrawingDirection.ByStyle) { sb.AppendLine($"{baseIndent} DrawingDirection = MTextDrawingDirection.{mtext.DrawingDirection},"); } sb.AppendLine($"{baseIndent}}}"); sb.AppendLine($"{baseIndent});"); } } private void GenerateEllipse(StringBuilder sb, Ellipse ellipse, bool asVariable = false, string baseIndent = " ") { if (asVariable) { sb.AppendLine($"{baseIndent}var entity{ellipse.Handle} = "); GenerateEllipseConstructor(sb, ellipse, baseIndent); sb.AppendLine($"{baseIndent}{{"); GenerateEntityPropertiesCore(sb, ellipse, baseIndent); if (Math.Abs(ellipse.StartAngle) > 1e-12 || Math.Abs(ellipse.EndAngle - 360) > 1e-12) { sb.AppendLine($"{baseIndent} StartAngle = {F(ellipse.StartAngle)},"); sb.AppendLine($"{baseIndent} EndAngle = {F(ellipse.EndAngle)},"); } sb.AppendLine($"{baseIndent}}};"); GenerateXData(sb, ellipse, $"entity{ellipse.Handle}", baseIndent); sb.AppendLine($"{baseIndent}doc.Entities.Add(entity{ellipse.Handle});"); } else { sb.AppendLine($"{baseIndent}doc.Entities.Add("); GenerateEllipseConstructor(sb, ellipse, baseIndent); sb.AppendLine($"{baseIndent}{{"); GenerateEntityPropertiesCore(sb, ellipse, baseIndent); if (Math.Abs(ellipse.StartAngle) > 1e-12 || Math.Abs(ellipse.EndAngle - 360) > 1e-12) { sb.AppendLine($"{baseIndent} StartAngle = {F(ellipse.StartAngle)},"); sb.AppendLine($"{baseIndent} EndAngle = {F(ellipse.EndAngle)},"); } sb.AppendLine($"{baseIndent}}}"); sb.AppendLine($"{baseIndent});"); } } private void GenerateEllipseConstructor(StringBuilder sb, Ellipse ellipse, string indent) { sb.AppendLine($"{indent}new Ellipse("); sb.AppendLine($"{indent} new Vector3({F(ellipse.Center.X)}, {F(ellipse.Center.Y)}, {F(ellipse.Center.Z)}),"); sb.AppendLine($"{indent} {F(ellipse.MajorAxis)}, {F(ellipse.MinorAxis)})"); } private void GenerateEntityPropertiesCore(StringBuilder sb, EntityObject entity, string baseIndent) { // Layer if (entity.Layer != null && _usedLayers.Contains(entity.Layer.Name)) { sb.AppendLine($"{baseIndent} Layer = layer{SafeName(entity.Layer.Name)},"); } // Color (if not ByLayer) if (entity.Color.UseTrueColor) { sb.AppendLine($"{baseIndent} Color = AciColor.FromTrueColor(System.Drawing.Color.FromArgb({entity.Color.R}, {entity.Color.G}, {entity.Color.B}).ToArgb()),"); } else if (entity.Color.Index != 256) // 256 = ByLayer { if (entity.Color.Index == 0) sb.AppendLine($"{baseIndent} Color = AciColor.ByBlock,"); else if (entity.Color.Index is >= 1 and <= 255) sb.AppendLine($"{baseIndent} Color = new AciColor({entity.Color.Index}),"); } // Linetype if (entity.Linetype != null && entity.Linetype.Name != "ByLayer" && entity.Linetype.Name != "Continuous") { if (entity.Linetype.Name == "ByBlock") { sb.AppendLine($"{baseIndent} Linetype = Linetype.ByBlock,"); } else { sb.AppendLine($"{baseIndent} Linetype = linetype{SafeName(entity.Linetype.Name)},"); } } // Lineweight if (entity.Lineweight != Lineweight.ByLayer) { sb.AppendLine($"{baseIndent} Lineweight = Lineweight.{entity.Lineweight},"); } // Linetype scale if (Math.Abs(entity.LinetypeScale - 1.0) > 1e-10) { sb.AppendLine($"{baseIndent} LinetypeScale = {F(entity.LinetypeScale)},"); } // Thickness (for entities that support it) if (entity is Line line && Math.Abs(line.Thickness) > 1e-10) { sb.AppendLine($"{baseIndent} Thickness = {F(line.Thickness)},"); } else if (entity is Arc arc && Math.Abs(arc.Thickness) > 1e-10) { sb.AppendLine($"{baseIndent} Thickness = {F(arc.Thickness)},"); } else if (entity is Circle circle && Math.Abs(circle.Thickness) > 1e-10) { sb.AppendLine($"{baseIndent} Thickness = {F(circle.Thickness)},"); } else if (entity is Polyline2D poly2d && Math.Abs(poly2d.Thickness) > 1e-10) { sb.AppendLine($"{baseIndent} Thickness = {F(poly2d.Thickness)},"); } else if (entity is PointEntity point && Math.Abs(point.Thickness) > 1e-10) { sb.AppendLine($"{baseIndent} Thickness = {F(point.Thickness)},"); } else if (entity is Ellipse ellipse && Math.Abs(ellipse.Thickness) > 1e-10) { sb.AppendLine($"{baseIndent} Thickness = {F(ellipse.Thickness)},"); } else if (entity is Shape shape && Math.Abs(shape.Thickness) > 1e-10) { sb.AppendLine($"{baseIndent} Thickness = {F(shape.Thickness)},"); } else if (entity is Trace trace && Math.Abs(trace.Thickness) > 1e-10) { sb.AppendLine($"{baseIndent} Thickness = {F(trace.Thickness)},"); } else if (entity is Solid solid && Math.Abs(solid.Thickness) > 1e-10) { sb.AppendLine($"{baseIndent} Thickness = {F(solid.Thickness)},"); } // Transparency (if not default ByLayer) if (entity.Transparency.Value != -1) { if (entity.Transparency.Value == 100) { sb.AppendLine($"{baseIndent} Transparency = Transparency.ByBlock,"); } else if (entity.Transparency.Value is >= 0 and <= 90) { sb.AppendLine($"{baseIndent} Transparency = new Transparency({entity.Transparency.Value}),"); } } // IsVisible (if not default true) if (!entity.IsVisible) { sb.AppendLine($"{baseIndent} IsVisible = false,"); } // Normal (if not default 0,0,1) var n = entity.Normal; if (Math.Abs(n.X) > 1e-12 || Math.Abs(n.Y) > 1e-12 || Math.Abs(n.Z - 1.0) > 1e-12) { sb.AppendLine($"{baseIndent} Normal = new Vector3({F(n.X)}, {F(n.Y)}, {F(n.Z)}),"); } // Reactors (if any exist) if (entity.Reactors is { Count: > 0 }) { sb.AppendLine($"{baseIndent} // Note: Reactors property is read-only and managed internally by netDxf"); sb.AppendLine($"{baseIndent} // {entity.Reactors.Count} reactor(s) attached to this entity"); } } private void GenerateAttributeProperties(StringBuilder sb, Attribute attribute, string baseIndent) { // Generate Layer property if (attribute.Layer != null && attribute.Layer.Name != "0") { sb.AppendLine($"{baseIndent}Layer = layer{SafeName(attribute.Layer.Name)},"); } // Generate Color property if (attribute.Color.Index != 256) // 256 is ByLayer { sb.AppendLine($"{baseIndent}Color = new AciColor({attribute.Color.Index}),"); } // Generate Linetype property if (attribute.Linetype != null && attribute.Linetype.Name != "ByLayer" && attribute.Linetype.Name != "Continuous") { if (attribute.Linetype.Name == "ByBlock") sb.AppendLine($"{baseIndent}Linetype = Linetype.ByBlock,"); else sb.AppendLine($"{baseIndent}Linetype = linetype{SafeName(attribute.Linetype.Name)},"); } // Generate Lineweight property if (attribute.Lineweight != Lineweight.ByLayer) { sb.AppendLine($"{baseIndent}Lineweight = Lineweight.{attribute.Lineweight},"); } // Generate LinetypeScale property if (Math.Abs(attribute.LinetypeScale - 1.0) > 1e-6) { sb.AppendLine($"{baseIndent}LinetypeScale = {attribute.LinetypeScale.ToString(CultureInfo.InvariantCulture)},"); } // Generate Transparency property if (attribute.Transparency.Value != 0) { sb.AppendLine($"{baseIndent}Transparency = new Transparency({attribute.Transparency.Value}),"); } // Generate IsVisible property if (!attribute.IsVisible) { sb.AppendLine($"{baseIndent}IsVisible = false,"); } // Generate Normal property (only if not default Z-axis) if (Math.Abs(attribute.Normal.X) > 1e-6 || Math.Abs(attribute.Normal.Y) > 1e-6 || Math.Abs(attribute.Normal.Z - 1.0) > 1e-6) { sb.AppendLine($"{baseIndent}Normal = new Vector3({attribute.Normal.X.ToString(CultureInfo.InvariantCulture)}, {attribute.Normal.Y.ToString(CultureInfo.InvariantCulture)}, {attribute.Normal.Z.ToString(CultureInfo.InvariantCulture)}),"); } } private void GenerateBlockEntity(StringBuilder sb, EntityObject entity, string blockName, DxfCodeGenerationOptions options, string baseIndent) { // Reuse existing entity generation methods by temporarily modifying the output var tempSb = new StringBuilder(); GenerateEntity(tempSb, entity, options, baseIndent); // Replace "doc.Entities.Add(" with "block{blockName}.Entities.Add(" var entityCode = tempSb.ToString(); var modifiedCode = entityCode.Replace("doc.Entities.Add(", $"block{SafeName(blockName)}.Entities.Add("); sb.Append(modifiedCode); } private void GenerateInsert(StringBuilder sb, Insert insert, bool asVariable = false, string baseIndent = " ") { var blkName = insert.Block?.Name; if (string.IsNullOrEmpty(blkName)) { return; } var safeBlk = SafeName(blkName); var insertVarName = $"ins_{safeBlk}_{_insertCounter++}"; if (asVariable) { sb.AppendLine($"{baseIndent}var entity{insert.Handle} = new Insert(block{safeBlk})"); sb.AppendLine($"{baseIndent}{{"); sb.AppendLine($"{baseIndent} Position = new Vector3({F(insert.Position.X)}, {F(insert.Position.Y)}, {F(insert.Position.Z)}),"); if (Math.Abs(insert.Scale.X - 1.0) > 1e-12 || Math.Abs(insert.Scale.Y - 1.0) > 1e-12 || Math.Abs(insert.Scale.Z - 1.0) > 1e-12) sb.AppendLine($"{baseIndent} Scale = new Vector3({F(insert.Scale.X)}, {F(insert.Scale.Y)}, {F(insert.Scale.Z)}),"); if (Math.Abs(insert.Rotation) > 1e-12) sb.AppendLine($"{baseIndent} Rotation = {F(insert.Rotation)},"); GenerateEntityPropertiesCore(sb, insert, baseIndent + " "); sb.AppendLine($"{baseIndent}}};"); // Attributes if (insert.Attributes is { Count: > 0 }) { foreach (var att in insert.Attributes) { // Assign value by tag when possible if (!string.IsNullOrEmpty(att.Tag)) { sb.AppendLine($"{baseIndent}var attr_{SafeName(att.Tag)} = entity{insert.Handle}.Attributes.AttributeWithTag(\"{Escape(att.Tag)}\");"); sb.AppendLine($"{baseIndent}if (attr_{SafeName(att.Tag)} != null) attr_{SafeName(att.Tag)}.Value = \"{Escape(att.Value)}\";"); } } } GenerateXData(sb, insert, $"entity{insert.Handle}", baseIndent); sb.AppendLine($"{baseIndent}doc.Entities.Add(entity{insert.Handle});"); } else { sb.AppendLine($"{baseIndent}var {insertVarName} = new Insert(block{safeBlk})"); sb.AppendLine($"{baseIndent}{{"); sb.AppendLine($"{baseIndent} Position = new Vector3({F(insert.Position.X)}, {F(insert.Position.Y)}, {F(insert.Position.Z)}),"); if (Math.Abs(insert.Scale.X - 1.0) > 1e-12 || Math.Abs(insert.Scale.Y - 1.0) > 1e-12 || Math.Abs(insert.Scale.Z - 1.0) > 1e-12) sb.AppendLine($"{baseIndent} Scale = new Vector3({F(insert.Scale.X)}, {F(insert.Scale.Y)}, {F(insert.Scale.Z)}),"); if (Math.Abs(insert.Rotation) > 1e-12) sb.AppendLine($"{baseIndent} Rotation = {F(insert.Rotation)},"); GenerateEntityPropertiesCore(sb, insert, baseIndent + " "); sb.AppendLine($"{baseIndent}}};"); // Attributes if (insert.Attributes is { Count: > 0 }) { foreach (var att in insert.Attributes) { // Assign value by tag when possible if (!string.IsNullOrEmpty(att.Tag)) { sb.AppendLine($"{baseIndent}var attr_{SafeName(att.Tag)} = {insertVarName}.Attributes.AttributeWithTag(\"{Escape(att.Tag)}\");"); sb.AppendLine($"{baseIndent}if (attr_{SafeName(att.Tag)} != null) attr_{SafeName(att.Tag)}.Value = \"{Escape(att.Value)}\";"); } } } sb.AppendLine($"{baseIndent}doc.Entities.Add({insertVarName});"); } sb.AppendLine(); } private static string Escape(string s) => s.Replace("\\", "\\\\").Replace("\"", "\\\""); private static string EscapeMText(string s) => s.Replace("\\", "\\\\").Replace("\"", "\\\"").Replace("\n", "\\P"); private static string SafeName(string name) { // Convert layer/table names to safe C# identifiers var result = new StringBuilder(); foreach (var c in name) { if (char.IsLetterOrDigit(c)) result.Append(c); else result.Append('_'); } var safeName = result.ToString(); if (char.IsDigit(safeName[0])) safeName = "_" + safeName; return safeName; } private void GenerateHatch(StringBuilder sb, Hatch hatch, bool asVariable = false, string baseIndent = " ") { // Generate Hatch with boundary paths reconstruction var patternName = hatch.Pattern?.Name ?? "SOLID"; var isSolid = string.Equals(patternName, "SOLID", StringComparison.OrdinalIgnoreCase) || string.Equals(patternName, "Solid", StringComparison.OrdinalIgnoreCase); sb.AppendLine($"{baseIndent}{{"); sb.AppendLine($"{baseIndent} // Hatch with boundary paths"); sb.AppendLine($"{baseIndent} var boundaryPaths = new List();"); // Reconstruct boundary paths from existing hatch boundary paths if (hatch.BoundaryPaths is { Count: > 0 }) { for (var i = 0; i < hatch.BoundaryPaths.Count; i++) { var path = hatch.BoundaryPaths[i]; sb.AppendLine($"{baseIndent} // Boundary path {i + 1}"); sb.AppendLine($"{baseIndent} var pathEntities{i} = new List();"); // Extract entities from the boundary path edges if (path.Edges.Count > 0) { foreach (var edge in path.Edges) { var entityObj = edge.ConvertTo(); if (entityObj != null) { GenerateBoundaryEntity(sb, entityObj, i, baseIndent); } } } sb.AppendLine($"{baseIndent} boundaryPaths.Add(new HatchBoundaryPath(pathEntities{i}));"); sb.AppendLine(); } } // Create the hatch with the pattern and boundaries if (isSolid) { sb.AppendLine($"{baseIndent} var hatchEntity = new Hatch(HatchPattern.Solid, boundaryPaths, {(hatch.Associative ? "true" : "false")});"); } else { // Check if it's a gradient pattern if (hatch.Pattern is HatchGradientPattern gradientPattern) { sb.AppendLine($"{baseIndent} var gradientPattern = new HatchGradientPattern("); if (gradientPattern.SingleColor) { sb.AppendLine($"{baseIndent} new AciColor({gradientPattern.Color1.Index}), {F(gradientPattern.Tint)}, HatchGradientPatternType.{gradientPattern.GradientType});"); } else { sb.AppendLine($"{baseIndent} new AciColor({gradientPattern.Color1.Index}), new AciColor({gradientPattern.Color2.Index}), HatchGradientPatternType.{gradientPattern.GradientType});"); } // Set gradient-specific properties if they differ from defaults if (Math.Abs(gradientPattern.Angle) > 1e-9) sb.AppendLine($"{baseIndent} gradientPattern.Angle = {F(gradientPattern.Angle)};"); if (Math.Abs(gradientPattern.Scale - 1.0) > 1e-9) sb.AppendLine($"{baseIndent} gradientPattern.Scale = {F(gradientPattern.Scale)};"); if (Math.Abs(gradientPattern.Origin.X) > 1e-9 || Math.Abs(gradientPattern.Origin.Y) > 1e-9) sb.AppendLine($"{baseIndent} gradientPattern.Origin = new Vector2({F(gradientPattern.Origin.X)}, {F(gradientPattern.Origin.Y)});"); if (!gradientPattern.Centered) sb.AppendLine($"{baseIndent} gradientPattern.Centered = false;"); sb.AppendLine($"{baseIndent} var hatchEntity = new Hatch(gradientPattern, boundaryPaths, {(hatch.Associative ? "true" : "false")});"); } else { sb.AppendLine($"{baseIndent} var pattern = new HatchPattern(\"{Escape(patternName)}\");"); if (hatch.Pattern != null) { if (!string.IsNullOrEmpty(hatch.Pattern.Description)) { sb.AppendLine($"{baseIndent} pattern.Description = \"{Escape(hatch.Pattern.Description)}\";"); } if (hatch.Pattern.Type != HatchType.UserDefined) { sb.AppendLine($"{baseIndent} pattern.Type = HatchType.{hatch.Pattern.Type};"); } // Set pattern properties if they differ from defaults if (Math.Abs(hatch.Pattern.Angle) > 1e-9) { sb.AppendLine($"{baseIndent} pattern.Angle = {F(hatch.Pattern.Angle)};"); } if (Math.Abs(hatch.Pattern.Scale - 1.0) > 1e-9) { sb.AppendLine($"{baseIndent} pattern.Scale = {F(hatch.Pattern.Scale)};"); } if (Math.Abs(hatch.Pattern.Origin.X) > 1e-9 || Math.Abs(hatch.Pattern.Origin.Y) > 1e-9) { sb.AppendLine( $"{baseIndent} pattern.Origin = new Vector2({F(hatch.Pattern.Origin.X)}, {F(hatch.Pattern.Origin.Y)});"); } if (hatch.Pattern.LineDefinitions.Count > 0) { sb.AppendLine($"{baseIndent} pattern.LineDefinitions.Clear();"); for (var i = 0; i < hatch.Pattern.LineDefinitions.Count; i++) { var lineDef = hatch.Pattern.LineDefinitions[i]; var lineVar = $"patternLineDef{i}"; sb.AppendLine($"{baseIndent} var {lineVar} = new HatchPatternLineDefinition"); sb.AppendLine($"{baseIndent} {{"); if (Math.Abs(lineDef.Angle) > 1e-9) sb.AppendLine($"{baseIndent} Angle = {F(lineDef.Angle)},"); if (Math.Abs(lineDef.Origin.X) > 1e-9 || Math.Abs(lineDef.Origin.Y) > 1e-9) sb.AppendLine($"{baseIndent} Origin = new Vector2({F(lineDef.Origin.X)}, {F(lineDef.Origin.Y)}),"); if (Math.Abs(lineDef.Delta.X) > 1e-9 || Math.Abs(lineDef.Delta.Y) > 1e-9) sb.AppendLine($"{baseIndent} Delta = new Vector2({F(lineDef.Delta.X)}, {F(lineDef.Delta.Y)}),"); sb.AppendLine($"{baseIndent} }};"); if (lineDef.DashPattern.Count > 0) { foreach (var dash in lineDef.DashPattern) { sb.AppendLine($"{baseIndent} {lineVar}.DashPattern.Add({F(dash)});"); } } sb.AppendLine($"{baseIndent} pattern.LineDefinitions.Add({lineVar});"); } } } sb.AppendLine($"{baseIndent} var hatchEntity = new Hatch(pattern, boundaryPaths, {(hatch.Associative ? "true" : "false")});"); } } sb.AppendLine($"{baseIndent} hatchEntity.Elevation = {F(hatch.Elevation)};"); // Apply entity properties if (hatch.Layer != null && _usedLayers.Contains(hatch.Layer.Name)) { sb.AppendLine($"{baseIndent} hatchEntity.Layer = layer{SafeName(hatch.Layer.Name)};"); } // Color handling if (hatch.Color.Index != 256) // Not ByLayer { if (hatch.Color.Index == 0) sb.AppendLine($"{baseIndent} hatchEntity.Color = AciColor.ByBlock;"); else sb.AppendLine($"{baseIndent} hatchEntity.Color = new AciColor({hatch.Color.Index});"); } if (!asVariable) { sb.AppendLine($"{baseIndent} doc.Entities.Add(hatchEntity);"); } else { // Allow attaching additional data (e.g., XData) before adding GenerateXData(sb, hatch, "hatchEntity", baseIndent + " "); sb.AppendLine($"{baseIndent} doc.Entities.Add(hatchEntity);"); } sb.AppendLine($"{baseIndent}}}"); sb.AppendLine(); } private void GenerateBoundaryEntity(StringBuilder sb, EntityObject entity, int pathIndex, string baseIndent) { // Generate entity creation code for boundary paths without properties sb.AppendLine($"{baseIndent} pathEntities{pathIndex}.Add("); switch (entity) { case Line line: GenerateLineConstructor(sb, line, baseIndent + " "); break; case Arc arc: GenerateArcConstructor(sb, arc, baseIndent + " "); break; case Circle circle: GenerateCircleConstructor(sb, circle, baseIndent + " "); break; case Polyline2D poly2d: GeneratePolyline2DConstructor(sb, poly2d, baseIndent + " "); break; case Ellipse ellipse: GenerateEllipseConstructor(sb, ellipse, baseIndent + " "); break; case Spline spline: GenerateSplineConstructor(sb, spline, baseIndent + " "); break; default: // Fallback for other entity types sb.AppendLine($"{baseIndent} // Unsupported boundary entity type: {entity.GetType().Name}"); sb.AppendLine($"{baseIndent} null"); break; } sb.AppendLine($"{baseIndent} );"); } private void GenerateWipeout(StringBuilder sb, Wipeout wipeout, bool asVariable = false, string baseIndent = "") { sb.AppendLine($"{baseIndent}{{"); sb.AppendLine($"{baseIndent} // Wipeout entity with clipping boundary"); sb.AppendLine($"{baseIndent} var boundaryVertices = new List();"); if (wipeout.ClippingBoundary != null && wipeout.ClippingBoundary.Vertexes.Count > 0) { foreach (var vertex in wipeout.ClippingBoundary.Vertexes) { sb.AppendLine($"{baseIndent} boundaryVertices.Add(new Vector2({F(vertex.X)}, {F(vertex.Y)}));"); } } var entityName = asVariable ? $"wipeout{_entityCounter++}" : "wipeoutEntity"; sb.AppendLine($"{baseIndent} var {entityName} = new Wipeout(boundaryVertices);"); // Apply entity properties if (wipeout.Layer != null && _usedLayers.Contains(wipeout.Layer.Name)) { sb.AppendLine($"{baseIndent} {entityName}.Layer = layer{SafeName(wipeout.Layer.Name)};"); } if (asVariable) { GenerateXData(sb, wipeout, entityName, baseIndent + " "); sb.AppendLine($"{baseIndent} doc.Entities.Add({entityName});"); } else { sb.AppendLine($"{baseIndent} doc.Entities.Add({entityName});"); } sb.AppendLine($"{baseIndent}}}"); sb.AppendLine(); } private void GenerateLeader(StringBuilder sb, Leader leader, bool asVariable = false, string baseIndent = "") { if (asVariable) { sb.AppendLine($"{baseIndent}var entity{leader.Handle} = new Leader(new List"); sb.AppendLine($"{baseIndent}{{"); if (leader.Vertexes is { Count: > 0 }) { for (var i = 0; i < leader.Vertexes.Count; i++) { var vertex = leader.Vertexes[i]; var comma = i < leader.Vertexes.Count - 1 ? "," : ""; sb.AppendLine($"{baseIndent} new Vector2({F(vertex.X)}, {F(vertex.Y)}){comma}"); } } sb.AppendLine($"{baseIndent}}});"); GenerateEntityPropertiesCore(sb, leader, baseIndent); GenerateLeaderAdvancedProperties(sb, leader, $"entity{leader.Handle}", baseIndent); GenerateXData(sb, leader, $"entity{leader.Handle}", baseIndent); sb.AppendLine($"{baseIndent}entities.Add(entity{leader.Handle});"); } else { sb.AppendLine($"{baseIndent}doc.Entities.Add(new Leader(new List"); sb.AppendLine($"{baseIndent}{{"); if (leader.Vertexes is { Count: > 0 }) { for (var i = 0; i < leader.Vertexes.Count; i++) { var vertex = leader.Vertexes[i]; var comma = i < leader.Vertexes.Count - 1 ? "," : ""; sb.AppendLine($"{baseIndent} new Vector2({F(vertex.X)}, {F(vertex.Y)}){comma}"); } } sb.AppendLine($"{baseIndent}}})"); sb.AppendLine($"{baseIndent}{{"); GenerateEntityPropertiesCore(sb, leader, baseIndent + " "); GenerateLeaderAdvancedProperties(sb, leader, null!, baseIndent + " "); sb.AppendLine($"{baseIndent}}});"); } } private void GenerateFace3D(StringBuilder sb, Face3D face3d, string baseIndent = " ") { sb.AppendLine($"{baseIndent}doc.Entities.Add(new Face3D("); sb.AppendLine($"{baseIndent} new Vector3({F(face3d.FirstVertex.X)}, {F(face3d.FirstVertex.Y)}, {F(face3d.FirstVertex.Z)}),"); sb.AppendLine($"{baseIndent} new Vector3({F(face3d.SecondVertex.X)}, {F(face3d.SecondVertex.Y)}, {F(face3d.SecondVertex.Z)}),"); sb.AppendLine($"{baseIndent} new Vector3({F(face3d.ThirdVertex.X)}, {F(face3d.ThirdVertex.Y)}, {F(face3d.ThirdVertex.Z)}),"); sb.AppendLine($"{baseIndent} new Vector3({F(face3d.FourthVertex.X)}, {F(face3d.FourthVertex.Y)}, {F(face3d.FourthVertex.Z)}))"); sb.AppendLine($"{baseIndent}{{"); GenerateEntityPropertiesCore(sb, face3d, baseIndent + " "); // EdgeFlags if (face3d.EdgeFlags != Face3DEdgeFlags.None) { var edgeFlagsStr = GenerateEnumFlags(face3d.EdgeFlags); sb.AppendLine($"{baseIndent} EdgeFlags = {edgeFlagsStr},"); } sb.AppendLine($"{baseIndent}}}"); sb.AppendLine($"{baseIndent});"); } private void GenerateLinearDimension(StringBuilder sb, LinearDimension dimension, string baseIndent = "") { var entityVar = $"linearDim{_entityCounter++}"; sb.AppendLine($"{baseIndent} var {entityVar} = new LinearDimension("); sb.AppendLine($"{baseIndent} new Vector2({F(dimension.FirstReferencePoint.X)}, {F(dimension.FirstReferencePoint.Y)}),"); sb.AppendLine($"{baseIndent} new Vector2({F(dimension.SecondReferencePoint.X)}, {F(dimension.SecondReferencePoint.Y)}),"); sb.AppendLine($"{baseIndent} {F(dimension.Offset)}, {F(dimension.Rotation)})"); sb.AppendLine($"{baseIndent} {{"); GenerateEntityPropertiesCore(sb, dimension, baseIndent + " "); GenerateDimensionStyleProperties(sb, dimension, baseIndent + " "); sb.AppendLine($"{baseIndent} }};"); GenerateDimensionStyleOverrides(sb, dimension, entityVar, baseIndent + " "); sb.AppendLine($"{baseIndent} doc.Entities.Add({entityVar});"); } private void GenerateAlignedDimension(StringBuilder sb, AlignedDimension dimension, string baseIndent = "") { var entityVar = $"alignedDim{_entityCounter++}"; sb.AppendLine($"{baseIndent} var {entityVar} = new AlignedDimension("); sb.AppendLine($"{baseIndent} new Vector2({F(dimension.FirstReferencePoint.X)}, {F(dimension.FirstReferencePoint.Y)}),"); sb.AppendLine($"{baseIndent} new Vector2({F(dimension.SecondReferencePoint.X)}, {F(dimension.SecondReferencePoint.Y)}),"); sb.AppendLine($"{baseIndent} {F(dimension.Offset)})"); sb.AppendLine($"{baseIndent} {{"); GenerateEntityPropertiesCore(sb, dimension, baseIndent + " "); GenerateDimensionStyleProperties(sb, dimension, baseIndent + " "); sb.AppendLine($"{baseIndent} }};"); GenerateDimensionStyleOverrides(sb, dimension, entityVar, baseIndent + " "); sb.AppendLine($"{baseIndent} doc.Entities.Add({entityVar});"); } private void GenerateRadialDimension(StringBuilder sb, RadialDimension dimension, string baseIndent = "") { var entityVar = $"radialDim{_entityCounter++}"; sb.AppendLine($"{baseIndent} var {entityVar} = new RadialDimension("); sb.AppendLine($"{baseIndent} new Vector2({F(dimension.CenterPoint.X)}, {F(dimension.CenterPoint.Y)}),"); sb.AppendLine($"{baseIndent} new Vector2({F(dimension.ReferencePoint.X)}, {F(dimension.ReferencePoint.Y)})"); sb.AppendLine($"{baseIndent} )"); sb.AppendLine($"{baseIndent} {{"); GenerateEntityPropertiesCore(sb, dimension, baseIndent + " "); GenerateDimensionStyleProperties(sb, dimension, baseIndent + " "); sb.AppendLine($"{baseIndent} }};"); GenerateDimensionStyleOverrides(sb, dimension, entityVar, baseIndent + " "); sb.AppendLine($"{baseIndent} doc.Entities.Add({entityVar});"); } private void GenerateDiametricDimension(StringBuilder sb, DiametricDimension dimension, string baseIndent = "") { var entityVar = $"diametricDim{_entityCounter++}"; sb.AppendLine($"{baseIndent} var {entityVar} = new DiametricDimension("); sb.AppendLine($"{baseIndent} new Vector2({F(dimension.CenterPoint.X)}, {F(dimension.CenterPoint.Y)}),"); sb.AppendLine($"{baseIndent} new Vector2({F(dimension.ReferencePoint.X)}, {F(dimension.ReferencePoint.Y)})"); sb.AppendLine($"{baseIndent} )"); sb.AppendLine($"{baseIndent} {{"); GenerateEntityPropertiesCore(sb, dimension, baseIndent + " "); GenerateDimensionStyleProperties(sb, dimension, baseIndent + " "); sb.AppendLine($"{baseIndent} }};"); GenerateDimensionStyleOverrides(sb, dimension, entityVar, baseIndent + " "); sb.AppendLine($"{baseIndent} doc.Entities.Add({entityVar});"); } private void GenerateAngular2LineDimension(StringBuilder sb, Angular2LineDimension dimension, string baseIndent = "") { sb.AppendLine($"{baseIndent} doc.Entities.Add(new Angular2LineDimension("); sb.AppendLine($"{baseIndent} new Vector2({F(dimension.StartFirstLine.X)}, {F(dimension.StartFirstLine.Y)}),"); sb.AppendLine($"{baseIndent} new Vector2({F(dimension.EndFirstLine.X)}, {F(dimension.EndFirstLine.Y)}),"); sb.AppendLine($"{baseIndent} new Vector2({F(dimension.StartSecondLine.X)}, {F(dimension.StartSecondLine.Y)}),"); sb.AppendLine($"{baseIndent} new Vector2({F(dimension.EndSecondLine.X)}, {F(dimension.EndSecondLine.Y)}),"); sb.AppendLine($"{baseIndent} {F(dimension.Offset)})"); sb.AppendLine($"{baseIndent} {{"); GenerateEntityPropertiesCore(sb, dimension, baseIndent + " "); GenerateDimensionStyleProperties(sb, dimension, baseIndent + " "); sb.AppendLine($"{baseIndent} }}"); sb.AppendLine($"{baseIndent} );"); } private void GenerateAngular3PointDimension(StringBuilder sb, Angular3PointDimension dimension, string baseIndent) { var entityVar = $"angular3PointDim{_entityCounter++}"; sb.AppendLine($"{baseIndent} var {entityVar} = new Angular3PointDimension("); sb.AppendLine($"{baseIndent} new Vector2({F(dimension.CenterPoint.X)}, {F(dimension.CenterPoint.Y)}),"); sb.AppendLine($"{baseIndent} new Vector2({F(dimension.StartPoint.X)}, {F(dimension.StartPoint.Y)}),"); sb.AppendLine($"{baseIndent} new Vector2({F(dimension.EndPoint.X)}, {F(dimension.EndPoint.Y)}),"); sb.AppendLine($"{baseIndent} {F(dimension.Offset)})"); sb.AppendLine($"{baseIndent} {{"); GenerateEntityPropertiesCore(sb, dimension, baseIndent + " "); GenerateDimensionStyleProperties(sb, dimension, baseIndent + " "); sb.AppendLine($"{baseIndent} }};"); GenerateDimensionStyleOverrides(sb, dimension, entityVar, baseIndent + " "); sb.AppendLine($"{baseIndent} doc.Entities.Add({entityVar});"); } private void GenerateOrdinateDimension(StringBuilder sb, OrdinateDimension dimension, string baseIndent) { var entityVar = $"ordinateDim{_entityCounter++}"; sb.AppendLine($"{baseIndent} var {entityVar} = new OrdinateDimension("); sb.AppendLine($"{baseIndent} Vector2.Zero,"); sb.AppendLine($"{baseIndent} new Vector2({F(dimension.FeaturePoint.X)}, {F(dimension.FeaturePoint.Y)}),"); sb.AppendLine($"{baseIndent} new Vector2({F(dimension.LeaderEndPoint.X)}, {F(dimension.LeaderEndPoint.Y)}),"); sb.AppendLine($"{baseIndent} OrdinateDimensionAxis.{dimension.Axis},"); // Add DimensionStyle parameter if (dimension.Style != null && dimension.Style.Name != "Standard" && _usedDimensionStyles.Contains(dimension.Style.Name)) { sb.AppendLine($"{baseIndent} dimStyle{SafeName(dimension.Style.Name)})"); } else { sb.AppendLine($"{baseIndent} DimensionStyle.Default)"); } sb.AppendLine($"{baseIndent} {{"); GenerateEntityPropertiesCore(sb, dimension, baseIndent + " "); GenerateDimensionStyleProperties(sb, dimension, baseIndent + " "); sb.AppendLine($"{baseIndent} }};"); GenerateDimensionStyleOverrides(sb, dimension, entityVar, baseIndent + " "); sb.AppendLine($"{baseIndent} doc.Entities.Add({entityVar});"); } private void GenerateArcLengthDimension(StringBuilder sb, ArcLengthDimension dimension, string baseIndent) { sb.AppendLine($"{baseIndent} doc.Entities.Add(new ArcLengthDimension("); sb.AppendLine($"{baseIndent} new Vector2({F(dimension.CenterPoint.X)}, {F(dimension.CenterPoint.Y)}),"); sb.AppendLine($"{baseIndent} {F(dimension.Radius)},"); sb.AppendLine($"{baseIndent} {F(dimension.StartAngle)},"); sb.AppendLine($"{baseIndent} {F(dimension.EndAngle)},"); sb.AppendLine($"{baseIndent} {F(dimension.Offset)})"); sb.AppendLine($"{baseIndent} {{"); GenerateEntityPropertiesCore(sb, dimension, baseIndent + " "); GenerateDimensionStyleProperties(sb, dimension, baseIndent + " "); sb.AppendLine($"{baseIndent} }}"); sb.AppendLine($"{baseIndent} );"); } private void GenerateRay(StringBuilder sb, Ray ray, string baseIndent) { sb.AppendLine($"{baseIndent} doc.Entities.Add(new Ray("); sb.AppendLine($"{baseIndent} new Vector3({F(ray.Origin.X)}, {F(ray.Origin.Y)}, {F(ray.Origin.Z)}),"); sb.AppendLine($"{baseIndent} new Vector3({F(ray.Direction.X)}, {F(ray.Direction.Y)}, {F(ray.Direction.Z)})"); sb.AppendLine($"{baseIndent} )"); sb.AppendLine($"{baseIndent} {{"); GenerateEntityPropertiesCore(sb, ray, baseIndent + " "); sb.AppendLine($"{baseIndent} }}"); sb.AppendLine($"{baseIndent} );"); } private void GenerateXLine(StringBuilder sb, XLine xline, string baseIndent) { sb.AppendLine($"{baseIndent} doc.Entities.Add(new XLine("); sb.AppendLine($"{baseIndent} new Vector3({F(xline.Origin.X)}, {F(xline.Origin.Y)}, {F(xline.Origin.Z)}),"); sb.AppendLine($"{baseIndent} new Vector3({F(xline.Direction.X)}, {F(xline.Direction.Y)}, {F(xline.Direction.Z)}))"); sb.AppendLine($"{baseIndent} {{"); GenerateEntityPropertiesCore(sb, xline, baseIndent + " "); sb.AppendLine($"{baseIndent} }}"); sb.AppendLine($"{baseIndent} );"); } private void GenerateSolid(StringBuilder sb, Solid solid, string baseIndent = " ") { sb.AppendLine($"{baseIndent}doc.Entities.Add(new Solid("); sb.AppendLine($"{baseIndent} new Vector2({F(solid.FirstVertex.X)}, {F(solid.FirstVertex.Y)}),"); sb.AppendLine($"{baseIndent} new Vector2({F(solid.SecondVertex.X)}, {F(solid.SecondVertex.Y)}),"); sb.AppendLine($"{baseIndent} new Vector2({F(solid.ThirdVertex.X)}, {F(solid.ThirdVertex.Y)}),"); sb.AppendLine($"{baseIndent} new Vector2({F(solid.FourthVertex.X)}, {F(solid.FourthVertex.Y)})"); sb.AppendLine($"{baseIndent})"); sb.AppendLine($"{baseIndent}{{"); GenerateEntityPropertiesCore(sb, solid, baseIndent + " "); sb.AppendLine($"{baseIndent}}}"); sb.AppendLine($"{baseIndent});"); } private void GenerateMLineStyle(StringBuilder sb, MLineStyle style, string baseIndent) { // Generate MLineStyle elements if any if (style.Elements.Count > 0) { var elementsVarName = $"elements{SafeName(style.Name)}"; sb.AppendLine($"{baseIndent}var {elementsVarName} = new List();"); foreach (var element in style.Elements) { sb.AppendLine($"{baseIndent}{elementsVarName}.Add(new MLineStyleElement({F(element.Offset)})"); sb.AppendLine($"{baseIndent}{{"); if (element.Color.Index != 256) // Not ByLayer { if (element.Color.Index == 0) sb.AppendLine($"{baseIndent} Color = AciColor.ByBlock,"); else sb.AppendLine($"{baseIndent} Color = new AciColor({element.Color.Index}),"); } if (element.Linetype != null && element.Linetype.Name != "Continuous" && element.Linetype.Name != "ByLayer" && element.Linetype.Name != "ByBlock") { sb.AppendLine($"{baseIndent} Linetype = linetype{SafeName(element.Linetype.Name)},"); } sb.AppendLine($"{baseIndent}}});"); } sb.AppendLine($"{baseIndent}var mlineStyle{SafeName(style.Name)} = new MLineStyle(\"{Escape(style.Name)}\", {elementsVarName});"); } else { sb.AppendLine($"{baseIndent}var mlineStyle{SafeName(style.Name)} = new MLineStyle(\"{Escape(style.Name)}\");"); } // Set additional properties if (!string.IsNullOrEmpty(style.Description)) { sb.AppendLine($"{baseIndent}mlineStyle{SafeName(style.Name)}.Description = \"{Escape(style.Description)}\";"); } if (style.FillColor.Index != 256) // Not ByLayer { if (style.FillColor.Index == 0) sb.AppendLine($"{baseIndent}mlineStyle{SafeName(style.Name)}.FillColor = AciColor.ByBlock;"); else sb.AppendLine($"{baseIndent}mlineStyle{SafeName(style.Name)}.FillColor = new AciColor({style.FillColor.Index});"); } if (Math.Abs(style.StartAngle - 90.0) > 1e-10) { sb.AppendLine($"{baseIndent}mlineStyle{SafeName(style.Name)}.StartAngle = {F(style.StartAngle)};"); } if (Math.Abs(style.EndAngle - 90.0) > 1e-10) { sb.AppendLine($"{baseIndent}mlineStyle{SafeName(style.Name)}.EndAngle = {F(style.EndAngle)};"); } sb.AppendLine($"{baseIndent}doc.MlineStyles.Add(mlineStyle{SafeName(style.Name)});"); } private void GenerateMLine(StringBuilder sb, MLine mline, bool asVariable = false, string baseIndent = "") { sb.AppendLine($"{baseIndent}{{"); sb.AppendLine($"{baseIndent} // MLine entity with vertices"); sb.AppendLine($"{baseIndent} var mlineVertices = new List();"); if (mline.Vertexes is { Count: > 0 }) { foreach (var vertex in mline.Vertexes) { sb.AppendLine($"{baseIndent} mlineVertices.Add(new Vector2({F(vertex.Position.X)}, {F(vertex.Position.Y)}));"); } } var entityName = asVariable ? $"mline{_entityCounter++}" : "mlineEntity"; sb.AppendLine($"{baseIndent} var {entityName} = new MLine(mlineVertices)"); sb.AppendLine($"{baseIndent} {{"); if (Math.Abs(mline.Scale - 1.0) > 1e-12) { sb.AppendLine($"{baseIndent} Scale = {F(mline.Scale)},"); } if (mline.Justification != MLineJustification.Zero) { sb.AppendLine($"{baseIndent} Justification = MLineJustification.{mline.Justification},"); } if (Math.Abs(mline.Elevation) > 1e-12) { sb.AppendLine($"{baseIndent} Elevation = {F(mline.Elevation)},"); } if (mline.IsClosed) { sb.AppendLine($"{baseIndent} IsClosed = true,"); } if (mline.NoStartCaps) { sb.AppendLine($"{baseIndent} NoStartCaps = true,"); } if (mline.NoEndCaps) { sb.AppendLine($"{baseIndent} NoEndCaps = true,"); } sb.AppendLine($"{baseIndent} }};"); // Apply MLineStyle if not default if (mline.Style != null && mline.Style.Name != "Standard" && _usedMLineStyles.Contains(mline.Style.Name)) { sb.AppendLine($"{baseIndent} {entityName}.Style = mlineStyle{SafeName(mline.Style.Name)};"); } // Apply entity properties if (mline.Layer != null && _usedLayers.Contains(mline.Layer.Name)) { sb.AppendLine($"{baseIndent} {entityName}.Layer = layer{SafeName(mline.Layer.Name)};"); } // Color handling if (mline.Color.Index != 256) // Not ByLayer { if (mline.Color.Index == 0) sb.AppendLine($"{baseIndent} {entityName}.Color = AciColor.ByBlock;"); else sb.AppendLine($"{baseIndent} {entityName}.Color = new AciColor({mline.Color.Index});"); } if (asVariable) { GenerateXData(sb, mline, entityName, baseIndent + " "); sb.AppendLine($"{baseIndent} entities.Add({entityName});"); } else { sb.AppendLine($"{baseIndent} doc.Entities.Add({entityName});"); } sb.AppendLine($"{baseIndent}}}"); sb.AppendLine(); } private void GenerateImage(StringBuilder sb, Image image, bool asVariable = false, string baseIndent = "") { sb.AppendLine($"{baseIndent}{{"); sb.AppendLine($"{baseIndent} var imageDefinition = new ImageDefinition(\"{image.Definition.Name}\", {image.Definition.Width}, {F(image.Definition.HorizontalResolution)}, {image.Definition.Height}, {F(image.Definition.VerticalResolution)}, ImageResolutionUnits.{image.Definition.ResolutionUnits});"); var entityName = asVariable ? $"image{_entityCounter++}" : "imageEntity"; sb.AppendLine($"{baseIndent} var {entityName} = new Image(imageDefinition,"); sb.AppendLine($"{baseIndent} new Vector3({F(image.Position.X)}, {F(image.Position.Y)}, {F(image.Position.Z)}),"); sb.AppendLine($"{baseIndent} {F(image.Width)}, {F(image.Height)});"); // Apply entity properties if (image.Layer != null && _usedLayers.Contains(image.Layer.Name)) { sb.AppendLine($"{baseIndent} {entityName}.Layer = layer{SafeName(image.Layer.Name)};"); } // Color handling if (image.Color.Index != 256) // Not ByLayer { if (image.Color.Index == 0) sb.AppendLine($"{baseIndent} {entityName}.Color = AciColor.ByBlock;"); else sb.AppendLine($"{baseIndent} {entityName}.Color = new AciColor({image.Color.Index});"); } // Image-specific properties if (image.Rotation != 0) { sb.AppendLine($"{baseIndent} {entityName}.Rotation = {F(image.Rotation)};"); } if (image.Brightness != 50) // Default brightness is 50 { sb.AppendLine($"{baseIndent} {entityName}.Brightness = {image.Brightness};"); } if (image.Contrast != 50) // Default contrast is 50 { sb.AppendLine($"{baseIndent} {entityName}.Contrast = {image.Contrast};"); } if (image.Fade != 0) // Default fade is 0 { sb.AppendLine($"{baseIndent} {entityName}.Fade = {image.Fade};"); } // Clipping state if (image.Clipping) { sb.AppendLine($"{baseIndent} {entityName}.Clipping = true;"); } // DisplayOptions (default is ShowImage | ShowImageWhenNotAlignedWithScreen | UseClippingBoundary = 7) var defaultDisplayOptions = ImageDisplayFlags.ShowImage | ImageDisplayFlags.ShowImageWhenNotAlignedWithScreen | ImageDisplayFlags.UseClippingBoundary; if (image.DisplayOptions != defaultDisplayOptions) { var flags = new List(); if ((image.DisplayOptions & ImageDisplayFlags.ShowImage) != 0) flags.Add("ImageDisplayFlags.ShowImage"); if ((image.DisplayOptions & ImageDisplayFlags.ShowImageWhenNotAlignedWithScreen) != 0) flags.Add("ImageDisplayFlags.ShowImageWhenNotAlignedWithScreen"); if ((image.DisplayOptions & ImageDisplayFlags.UseClippingBoundary) != 0) flags.Add("ImageDisplayFlags.UseClippingBoundary"); if ((image.DisplayOptions & ImageDisplayFlags.TransparencyOn) != 0) flags.Add("ImageDisplayFlags.TransparencyOn"); if (flags.Count > 0) { sb.AppendLine($"{baseIndent} {entityName}.DisplayOptions = {string.Join(" | ", flags)};"); } } // ClippingBoundary if (image.ClippingBoundary != null && image.ClippingBoundary.Vertexes.Count > 0) { if (image.ClippingBoundary.Type == ClippingBoundaryType.Rectangular && image.ClippingBoundary.Vertexes.Count == 2) { // Rectangular boundary with two opposite corners var firstCorner = image.ClippingBoundary.Vertexes[0]; var secondCorner = image.ClippingBoundary.Vertexes[1]; sb.AppendLine($"{baseIndent} {entityName}.ClippingBoundary = new ClippingBoundary(new Vector2({F(firstCorner.X)}, {F(firstCorner.Y)}), new Vector2({F(secondCorner.X)}, {F(secondCorner.Y)}));"); } else { // Polygonal boundary with 3 or more vertices sb.AppendLine($"{baseIndent} var clippingVertices = new List"); sb.AppendLine($"{baseIndent} {{"); for (var i = 0; i < image.ClippingBoundary.Vertexes.Count; i++) { var vertex = image.ClippingBoundary.Vertexes[i]; var comma = i < image.ClippingBoundary.Vertexes.Count - 1 ? "," : ""; sb.AppendLine($"{baseIndent} new Vector2({F(vertex.X)}, {F(vertex.Y)}){comma}"); } sb.AppendLine($"{baseIndent} }};"); sb.AppendLine($"{baseIndent} {entityName}.ClippingBoundary = new ClippingBoundary(clippingVertices);"); } } if (asVariable) { sb.AppendLine($"{baseIndent} entities.Add({entityName});"); } else { sb.AppendLine($"{baseIndent} doc.Entities.Add({entityName});"); } sb.AppendLine($"{baseIndent}}}"); sb.AppendLine(); } private void GenerateMesh(StringBuilder sb, Mesh mesh, bool asVariable = false, string baseIndent = "") { sb.AppendLine($"{baseIndent}var meshVertexes = new List"); sb.AppendLine($"{baseIndent}{{"); for (var i = 0; i < mesh.Vertexes.Count; i++) { var vertex = mesh.Vertexes[i]; sb.AppendLine($"{baseIndent} new Vector3({F(vertex.X)}, {F(vertex.Y)}, {F(vertex.Z)}){(i < mesh.Vertexes.Count - 1 ? "," : "")}"); } sb.AppendLine($"{baseIndent}}};"); sb.AppendLine(); sb.AppendLine($"{baseIndent}var meshFaces = new List"); sb.AppendLine($"{baseIndent}{{"); for (var i = 0; i < mesh.Faces.Count; i++) { var face = mesh.Faces[i]; sb.Append($"{baseIndent} new int[] {{ "); for (var j = 0; j < face.Length; j++) { sb.Append(face[j]); if (j < face.Length - 1) sb.Append(", "); } sb.AppendLine($" }}{(i < mesh.Faces.Count - 1 ? "," : "")}"); } sb.AppendLine($"{baseIndent}}};"); sb.AppendLine(); // Generate mesh edges if they exist var entityName = asVariable ? $"mesh{_entityCounter++}" : "mesh"; if (mesh.Edges is { Count: > 0 }) { sb.AppendLine($"{baseIndent}var meshEdges = new List"); sb.AppendLine($"{baseIndent}{{"); for (var i = 0; i < mesh.Edges.Count; i++) { var edge = mesh.Edges[i]; sb.AppendLine($"{baseIndent} new MeshEdge({edge.StartVertexIndex}, {edge.EndVertexIndex}){(i < mesh.Edges.Count - 1 ? "," : "")}"); } sb.AppendLine($"{baseIndent}}};"); sb.AppendLine(); sb.AppendLine($"{baseIndent}var {entityName} = new Mesh(meshVertexes, meshFaces, meshEdges)"); } else { sb.AppendLine($"{baseIndent}var {entityName} = new Mesh(meshVertexes, meshFaces)"); } sb.AppendLine($"{baseIndent}{{"); GenerateEntityPropertiesCore(sb, mesh, baseIndent + " "); sb.AppendLine($"{baseIndent} SubdivisionLevel = {mesh.SubdivisionLevel}"); sb.AppendLine($"{baseIndent}}};"); if (asVariable) { GenerateXData(sb, mesh, entityName, baseIndent); sb.AppendLine($"{baseIndent}entities.Add({entityName});"); } else { sb.AppendLine($"{baseIndent}doc.Entities.Add({entityName});"); } } private void GeneratePolyfaceMesh(StringBuilder sb, PolyfaceMesh polyfaceMesh, bool asVariable = false, string baseIndent = "") { sb.AppendLine($"{baseIndent}var polyfaceMeshVertexes = new Vector3[]"); sb.AppendLine($"{baseIndent}{{"); for (var i = 0; i < polyfaceMesh.Vertexes.Length; i++) { var vertex = polyfaceMesh.Vertexes[i]; var comma = i < polyfaceMesh.Vertexes.Length - 1 ? "," : ""; sb.AppendLine($"{baseIndent} new Vector3({F(vertex.X)}, {F(vertex.Y)}, {F(vertex.Z)}){comma}"); } sb.AppendLine($"{baseIndent}}};"); sb.AppendLine(); sb.AppendLine($"{baseIndent}var polyfaceMeshFaces = new PolyfaceMeshFace[]"); sb.AppendLine($"{baseIndent}{{"); for (var i = 0; i < polyfaceMesh.Faces.Count; i++) { var face = polyfaceMesh.Faces[i]; var comma = i < polyfaceMesh.Faces.Count - 1 ? "," : ""; var vertexIndexes = string.Join(", ", face.VertexIndexes); sb.AppendLine($"{baseIndent} new PolyfaceMeshFace(new short[] {{ {vertexIndexes} }}){comma}"); } sb.AppendLine($"{baseIndent}}};"); sb.AppendLine(); var entityName = asVariable ? $"polyfaceMesh{_entityCounter++}" : "polyfaceMesh"; sb.AppendLine($"{baseIndent}var {entityName} = new PolyfaceMesh(polyfaceMeshVertexes, polyfaceMeshFaces)"); sb.AppendLine($"{baseIndent}{{"); GenerateEntityPropertiesCore(sb, polyfaceMesh, baseIndent + " "); sb.AppendLine($"{baseIndent}}};"); if (asVariable) { GenerateXData(sb, polyfaceMesh, entityName, baseIndent); sb.AppendLine($"{baseIndent}entities.Add({entityName});"); } else { sb.AppendLine($"{baseIndent}doc.Entities.Add({entityName});"); } sb.AppendLine(); } private void GeneratePolygonMesh(StringBuilder sb, PolygonMesh polygonMesh, string baseIndent) { sb.AppendLine($"{baseIndent} // Generate PolygonMesh vertexes"); sb.AppendLine($"{baseIndent} var polygonMeshVertexes = new Vector3[]"); sb.AppendLine($"{baseIndent} {{"); for (var i = 0; i < polygonMesh.Vertexes.Length; i++) { var vertex = polygonMesh.Vertexes[i]; var comma = i < polygonMesh.Vertexes.Length - 1 ? "," : ""; sb.AppendLine($"{baseIndent} new Vector3({F(vertex.X)}, {F(vertex.Y)}, {F(vertex.Z)}){comma}"); } sb.AppendLine($"{baseIndent} }};"); sb.AppendLine(); sb.AppendLine($"{baseIndent} var polygonMesh = new PolygonMesh({polygonMesh.U}, {polygonMesh.V}, polygonMeshVertexes)"); sb.AppendLine($"{baseIndent} {{"); GenerateEntityPropertiesCore(sb, polygonMesh, baseIndent + " "); // Ensure DensityU and DensityV are within valid range (3-201) var densityU = (short)Math.Max(3, Math.Min(201, (int)polygonMesh.DensityU)); var densityV = (short)Math.Max(3, Math.Min(201, (int)polygonMesh.DensityV)); sb.AppendLine($"{baseIndent} DensityU = {densityU},"); sb.AppendLine($"{baseIndent} DensityV = {densityV},"); sb.AppendLine($"{baseIndent} SmoothType = PolylineSmoothType.{polygonMesh.SmoothType},"); sb.AppendLine($"{baseIndent} IsClosedInU = {polygonMesh.IsClosedInU.ToString().ToLower()},"); sb.AppendLine($"{baseIndent} IsClosedInV = {polygonMesh.IsClosedInV.ToString().ToLower()}"); sb.AppendLine($"{baseIndent} }};"); sb.AppendLine($"{baseIndent} doc.Entities.Add(polygonMesh);"); sb.AppendLine(); } private void GenerateShape(StringBuilder sb, Shape shape, string baseIndent) { sb.AppendLine($"{baseIndent} doc.Entities.Add(new Shape(\"{shape.Name}\","); sb.AppendLine($"{baseIndent} new ShapeStyle(\"{shape.Style.Name}\", \"{shape.Style.File}\"),"); sb.AppendLine($"{baseIndent} new Vector3({F(shape.Position.X)}, {F(shape.Position.Y)}, {F(shape.Position.Z)}),"); sb.AppendLine($"{baseIndent} {F(shape.Size)}, {F(shape.Rotation)})"); sb.AppendLine($"{baseIndent} {{"); GenerateEntityPropertiesCore(sb, shape, baseIndent + " "); sb.AppendLine($"{baseIndent} }});"); } private void GenerateAttribute(StringBuilder sb, Attribute attribute, DxfCodeGenerationOptions options, bool asVariable = false, string baseIndent = " ") { if (asVariable) { sb.AppendLine($"{baseIndent}var attribute{_insertCounter++} = new Attribute("); } else { sb.AppendLine($"{baseIndent}doc.Entities.Add(new Attribute("); } // Create AttributeDefinition if needed if (attribute.Definition != null && options.GenerateAttributeDefinitionEntities) { var styleName = attribute.Style?.Name ?? "Standard"; if (styleName == "Standard") { sb.AppendLine($"{baseIndent} new AttributeDefinition(\"{Escape(attribute.Tag)}\", {F(attribute.Height)}, TextStyle.Default)"); } else { sb.AppendLine($"{baseIndent} new AttributeDefinition(\"{Escape(attribute.Tag)}\", {F(attribute.Height)}, textStyle{SafeName(styleName)})"); } } else { sb.AppendLine($"{baseIndent} \"{Escape(attribute.Tag)}\""); } sb.AppendLine($"{baseIndent})"); sb.AppendLine($"{baseIndent}{{"); // Set attribute-specific properties if (!string.IsNullOrEmpty(attribute.Value)) { sb.AppendLine($"{baseIndent} Value = \"{Escape(attribute.Value)}\","); } if (attribute.Position != Vector3.Zero) { sb.AppendLine($"{baseIndent} Position = new Vector3({F(attribute.Position.X)}, {F(attribute.Position.Y)}, {F(attribute.Position.Z)}),"); } if (Math.Abs(attribute.Height - 1.0) > 1e-10) { sb.AppendLine($"{baseIndent} Height = {F(attribute.Height)},"); } if (Math.Abs(attribute.WidthFactor - 1.0) > 1e-10) { sb.AppendLine($"{baseIndent} WidthFactor = {F(attribute.WidthFactor)},"); } if (Math.Abs(attribute.Rotation) > 1e-10) { sb.AppendLine($"{baseIndent} Rotation = {F(attribute.Rotation)},"); } if (attribute.Alignment != TextAlignment.BaselineLeft) { sb.AppendLine($"{baseIndent} Alignment = TextAlignment.{attribute.Alignment},"); } if (attribute.Style != null && attribute.Style.Name != "Standard" && _usedTextStyles.Contains(attribute.Style.Name)) { sb.AppendLine($"{baseIndent} Style = textStyle{SafeName(attribute.Style.Name)},"); } if (attribute.IsBackward) { sb.AppendLine($"{baseIndent} IsBackward = true,"); } if (attribute.IsUpsideDown) { sb.AppendLine($"{baseIndent} IsUpsideDown = true,"); } if (Math.Abs(attribute.ObliqueAngle) > 1e-10) { sb.AppendLine($"{baseIndent} ObliqueAngle = {F(attribute.ObliqueAngle)},"); } if (attribute.Flags != AttributeFlags.None) { sb.AppendLine($"{baseIndent} Flags = AttributeFlags.{attribute.Flags},"); } // Generate common attribute properties GenerateAttributeProperties(sb, attribute, baseIndent + " "); if (asVariable) { sb.AppendLine($"{baseIndent}}});"); } else { sb.AppendLine($"{baseIndent}}});"); } } private void GenerateTolerance(StringBuilder sb, Tolerance tolerance, string baseIndent) { string? entry1Var = null; if (tolerance.Entry1 != null) { entry1Var = $"toleranceEntry{_entityCounter++}"; GenerateToleranceEntry(sb, tolerance.Entry1, entry1Var, baseIndent + " "); sb.AppendLine(); } string? entry2Var = null; if (tolerance.Entry2 != null) { entry2Var = $"toleranceEntry{_entityCounter++}"; GenerateToleranceEntry(sb, tolerance.Entry2, entry2Var, baseIndent + " "); sb.AppendLine(); } var toleranceVar = $"tolerance{_entityCounter++}"; var ctorEntryArg = entry1Var ?? "null"; sb.AppendLine($"{baseIndent} var {toleranceVar} = new Tolerance({ctorEntryArg}, new Vector3({F(tolerance.Position.X)}, {F(tolerance.Position.Y)}, {F(tolerance.Position.Z)}))"); sb.AppendLine($"{baseIndent} {{"); if (Math.Abs(tolerance.TextHeight - tolerance.Style.TextHeight) > 1e-9) { sb.AppendLine($"{baseIndent} TextHeight = {F(tolerance.TextHeight)},"); } if (Math.Abs(tolerance.Rotation) > 1e-9) { sb.AppendLine($"{baseIndent} Rotation = {F(tolerance.Rotation)},"); } GenerateEntityPropertiesCore(sb, tolerance, baseIndent + " "); sb.AppendLine($"{baseIndent} }};"); if (entry2Var != null) { sb.AppendLine($"{baseIndent} {toleranceVar}.Entry2 = {entry2Var};"); } if (!string.IsNullOrEmpty(tolerance.ProjectedToleranceZoneValue)) { sb.AppendLine($"{baseIndent} {toleranceVar}.ProjectedToleranceZoneValue = \"{Escape(tolerance.ProjectedToleranceZoneValue)}\";"); } if (tolerance.ShowProjectedToleranceZoneSymbol) { sb.AppendLine($"{baseIndent} {toleranceVar}.ShowProjectedToleranceZoneSymbol = true;"); } if (!string.IsNullOrEmpty(tolerance.DatumIdentifier)) { sb.AppendLine($"{baseIndent} {toleranceVar}.DatumIdentifier = \"{Escape(tolerance.DatumIdentifier)}\";"); } if (tolerance.Style != null && tolerance.Style.Name != "Standard" && _usedDimensionStyles.Contains(tolerance.Style.Name)) { sb.AppendLine($"{baseIndent} {toleranceVar}.Style = doc.DimensionStyles[\"{Escape(tolerance.Style.Name)}\"];"); } sb.AppendLine($"{baseIndent} doc.Entities.Add({toleranceVar});"); } private void GenerateToleranceEntry(StringBuilder sb, ToleranceEntry entry, string variableName, string baseIndent) { sb.AppendLine($"{baseIndent}var {variableName} = new ToleranceEntry();"); if (entry.GeometricSymbol != ToleranceGeometricSymbol.None) { sb.AppendLine($"{baseIndent}{variableName}.GeometricSymbol = ToleranceGeometricSymbol.{entry.GeometricSymbol};"); } if (entry.Tolerance1 != null) { var valueVar = $"{variableName}Value1"; GenerateToleranceValue(sb, entry.Tolerance1, valueVar, baseIndent); sb.AppendLine($"{baseIndent}{variableName}.Tolerance1 = {valueVar};"); } if (entry.Tolerance2 != null) { var valueVar = $"{variableName}Value2"; GenerateToleranceValue(sb, entry.Tolerance2, valueVar, baseIndent); sb.AppendLine($"{baseIndent}{variableName}.Tolerance2 = {valueVar};"); } if (entry.Datum1 != null) { var datumVar = $"{variableName}Datum1"; GenerateDatumReferenceValue(sb, entry.Datum1, datumVar, baseIndent); sb.AppendLine($"{baseIndent}{variableName}.Datum1 = {datumVar};"); } if (entry.Datum2 != null) { var datumVar = $"{variableName}Datum2"; GenerateDatumReferenceValue(sb, entry.Datum2, datumVar, baseIndent); sb.AppendLine($"{baseIndent}{variableName}.Datum2 = {datumVar};"); } if (entry.Datum3 != null) { var datumVar = $"{variableName}Datum3"; GenerateDatumReferenceValue(sb, entry.Datum3, datumVar, baseIndent); sb.AppendLine($"{baseIndent}{variableName}.Datum3 = {datumVar};"); } } private void GenerateToleranceValue(StringBuilder sb, ToleranceValue value, string variableName, string baseIndent) { sb.AppendLine($"{baseIndent}var {variableName} = new ToleranceValue();"); if (value.ShowDiameterSymbol) { sb.AppendLine($"{baseIndent}{variableName}.ShowDiameterSymbol = true;"); } if (!string.IsNullOrEmpty(value.Value)) { sb.AppendLine($"{baseIndent}{variableName}.Value = \"{Escape(value.Value)}\";"); } if (value.MaterialCondition != ToleranceMaterialCondition.None) { sb.AppendLine($"{baseIndent}{variableName}.MaterialCondition = ToleranceMaterialCondition.{value.MaterialCondition};"); } } private void GenerateDatumReferenceValue(StringBuilder sb, DatumReferenceValue datum, string variableName, string baseIndent) { sb.AppendLine($"{baseIndent}var {variableName} = new DatumReferenceValue();"); if (!string.IsNullOrEmpty(datum.Value)) { sb.AppendLine($"{baseIndent}{variableName}.Value = \"{Escape(datum.Value)}\";"); } if (datum.MaterialCondition != ToleranceMaterialCondition.None) { sb.AppendLine($"{baseIndent}{variableName}.MaterialCondition = ToleranceMaterialCondition.{datum.MaterialCondition};"); } } private void GenerateTrace(StringBuilder sb, Trace trace, string baseIndent) { sb.AppendLine($"{baseIndent} doc.Entities.Add(new Trace("); sb.AppendLine($"{baseIndent} new Vector2({F(trace.FirstVertex.X)}, {F(trace.FirstVertex.Y)}),"); sb.AppendLine($"{baseIndent} new Vector2({F(trace.SecondVertex.X)}, {F(trace.SecondVertex.Y)}),"); sb.AppendLine($"{baseIndent} new Vector2({F(trace.ThirdVertex.X)}, {F(trace.ThirdVertex.Y)}),"); sb.AppendLine($"{baseIndent} new Vector2({F(trace.FourthVertex.X)}, {F(trace.FourthVertex.Y)})"); sb.AppendLine($"{baseIndent} )"); sb.AppendLine($"{baseIndent} {{"); GenerateEntityPropertiesCore(sb, trace, baseIndent + " "); sb.AppendLine($"{baseIndent} }});"); } private void GenerateUnderlay(StringBuilder sb, Underlay underlay, string baseIndent) { sb.AppendLine($"{baseIndent} // Note: Underlay requires UnderlayDefinition to be added to document first"); sb.AppendLine($"{baseIndent} // Create underlay definition for {underlay.Definition.Type} type"); // Generate the correct underlay definition class name var definitionClassName = underlay.Definition.Type switch { UnderlayType.DGN => "UnderlayDgnDefinition", UnderlayType.DWF => "UnderlayDwfDefinition", UnderlayType.PDF => "UnderlayPdfDefinition", _ => $"Underlay{underlay.Definition.Type}Definition" }; sb.AppendLine($"{baseIndent} var underlayDef = new {definitionClassName}(\"{Escape(underlay.Definition.Name)}\", \"{Escape(underlay.Definition.File)}\");"); sb.AppendLine(); sb.AppendLine($"{baseIndent} doc.Entities.Add(new Underlay(underlayDef)"); sb.AppendLine($"{baseIndent} {{"); sb.AppendLine($"{baseIndent} Position = new Vector3({F(underlay.Position.X)}, {F(underlay.Position.Y)}, {F(underlay.Position.Z)}),"); sb.AppendLine($"{baseIndent} Scale = new Vector2({F(underlay.Scale.X)}, {F(underlay.Scale.Y)}),"); sb.AppendLine($"{baseIndent} Rotation = {F(underlay.Rotation)},"); sb.AppendLine($"{baseIndent} Contrast = {underlay.Contrast},"); sb.AppendLine($"{baseIndent} Fade = {underlay.Fade},"); sb.AppendLine($"{baseIndent} DisplayOptions = UnderlayDisplayFlags.{underlay.DisplayOptions},"); if (underlay.ClippingBoundary != null && underlay.ClippingBoundary.Vertexes.Count > 0) { if (underlay.ClippingBoundary.Type == ClippingBoundaryType.Rectangular && underlay.ClippingBoundary.Vertexes.Count == 2) { var firstCorner = underlay.ClippingBoundary.Vertexes[0]; var secondCorner = underlay.ClippingBoundary.Vertexes[1]; sb.AppendLine($"{baseIndent} ClippingBoundary = new ClippingBoundary(new Vector2({F(firstCorner.X)}, {F(firstCorner.Y)}), new Vector2({F(secondCorner.X)}, {F(secondCorner.Y)})),"); } else { sb.AppendLine($"{baseIndent} ClippingBoundary = new ClippingBoundary(new List"); sb.AppendLine($"{baseIndent} {{"); for (var i = 0; i < underlay.ClippingBoundary.Vertexes.Count; i++) { var v = underlay.ClippingBoundary.Vertexes[i]; var comma = i < underlay.ClippingBoundary.Vertexes.Count - 1 ? "," : ""; sb.AppendLine($"{baseIndent} new Vector2({F(v.X)}, {F(v.Y)}){comma}"); } sb.AppendLine($"{baseIndent} }}),"); } } GenerateEntityPropertiesCore(sb, underlay, baseIndent + " "); sb.AppendLine($"{baseIndent} }});"); sb.AppendLine(); } private void GenerateGroup(StringBuilder sb, Group group, DxfCodeGenerationOptions options, string baseIndent) { if (options.GenerateDetailedComments) { sb.AppendLine($"{baseIndent}// Group: {group.Name} ({group.Handle})"); } sb.AppendLine($"{baseIndent}var group{group.Handle} = new Group(\"{Escape(group.Name)}\");"); // Set description if not empty if (!string.IsNullOrEmpty(group.Description)) { sb.AppendLine($"{baseIndent}group{group.Handle}.Description = \"{Escape(group.Description)}\";"); } // Set IsSelectable if not default (true) if (!group.IsSelectable) { sb.AppendLine($"{baseIndent}group{group.Handle}.IsSelectable = false;"); } sb.AppendLine($"{baseIndent}doc.Groups.Add(group{group.Handle});"); // Add entities to group if any if (group.Entities.Count > 0) { foreach (var entity in group.Entities) { sb.AppendLine($"{baseIndent}group{group.Handle}.Entities.Add(entity{entity.Handle});"); } } sb.AppendLine(); } private void GenerateLayout(StringBuilder sb, Layout layout, DxfCodeGenerationOptions options, string baseIndent) { if (options.GenerateDetailedComments) { sb.AppendLine($"{baseIndent}// Layout: {layout.Name} ({layout.Handle})"); } sb.AppendLine($"{baseIndent}var layout{layout.Handle} = new Layout(\"{Escape(layout.Name)}\");"); // Set TabOrder if not default (0) if (layout.TabOrder != 0) { sb.AppendLine($"{baseIndent}layout{layout.Handle}.TabOrder = {layout.TabOrder};"); } // Set MinLimit if not default if (layout.MinLimit.X != 0 || layout.MinLimit.Y != 0) { sb.AppendLine($"{baseIndent}layout{layout.Handle}.MinLimit = new Vector2({F(layout.MinLimit.X)}, {F(layout.MinLimit.Y)});"); } // Set MaxLimit if not default if (layout.MaxLimit.X != 0 || layout.MaxLimit.Y != 0) { sb.AppendLine($"{baseIndent}layout{layout.Handle}.MaxLimit = new Vector2({F(layout.MaxLimit.X)}, {F(layout.MaxLimit.Y)});"); } // Set MinExtents if not default if (layout.MinExtents.X != 0 || layout.MinExtents.Y != 0 || layout.MinExtents.Z != 0) { sb.AppendLine($"{baseIndent}layout{layout.Handle}.MinExtents = new Vector3({F(layout.MinExtents.X)}, {F(layout.MinExtents.Y)}, {F(layout.MinExtents.Z)});"); } // Set MaxExtents if not default if (layout.MaxExtents.X != 0 || layout.MaxExtents.Y != 0 || layout.MaxExtents.Z != 0) { sb.AppendLine($"{baseIndent}layout{layout.Handle}.MaxExtents = new Vector3({F(layout.MaxExtents.X)}, {F(layout.MaxExtents.Y)}, {F(layout.MaxExtents.Z)});"); } // Set BasePoint if not default if (layout.BasePoint.X != 0 || layout.BasePoint.Y != 0 || layout.BasePoint.Z != 0) { sb.AppendLine($"{baseIndent}layout{layout.Handle}.BasePoint = new Vector3({F(layout.BasePoint.X)}, {F(layout.BasePoint.Y)}, {F(layout.BasePoint.Z)});"); } // Set Elevation if not default (0) if (Math.Abs(layout.Elevation) > 1e-12) { sb.AppendLine($"{baseIndent}layout{layout.Handle}.Elevation = {F(layout.Elevation)};"); } // Set UcsOrigin if not default if (layout.UcsOrigin.X != 0 || layout.UcsOrigin.Y != 0 || layout.UcsOrigin.Z != 0) { sb.AppendLine($"{baseIndent}layout{layout.Handle}.UcsOrigin = new Vector3({F(layout.UcsOrigin.X)}, {F(layout.UcsOrigin.Y)}, {F(layout.UcsOrigin.Z)});"); } // Set UcsXAxis if not default (1,0,0) if (Math.Abs(layout.UcsXAxis.X - 1.0) > 1e-12 || Math.Abs(layout.UcsXAxis.Y) > 1e-12 || Math.Abs(layout.UcsXAxis.Z) > 1e-12) { sb.AppendLine($"{baseIndent}layout{layout.Handle}.UcsXAxis = new Vector3({F(layout.UcsXAxis.X)}, {F(layout.UcsXAxis.Y)}, {F(layout.UcsXAxis.Z)});"); } // Set UcsYAxis if not default (0,1,0) if (Math.Abs(layout.UcsYAxis.X) > 1e-12 || Math.Abs(layout.UcsYAxis.Y - 1.0) > 1e-12 || Math.Abs(layout.UcsYAxis.Z) > 1e-12) { sb.AppendLine($"{baseIndent}layout{layout.Handle}.UcsYAxis = new Vector3({F(layout.UcsYAxis.X)}, {F(layout.UcsYAxis.Y)}, {F(layout.UcsYAxis.Z)});"); } // Note: IsPaperSpace is read-only and determined by the layout type, so we don't generate assignment code for it sb.AppendLine($"{baseIndent}doc.Layouts.Add(layout{layout.Handle});"); sb.AppendLine(); } private void GenerateImageDefinition(StringBuilder sb, ImageDefinition imageDef, DxfCodeGenerationOptions options, string baseIndent) { if (options.GenerateDetailedComments) { sb.AppendLine($"{baseIndent}// Image Definition: {imageDef.Name} ({imageDef.Handle})"); } sb.AppendLine($"{baseIndent}var imageDef{imageDef.Handle} = new ImageDefinition(\"{Escape(imageDef.Name)}\", \"{Escape(imageDef.File)}\", {imageDef.Width}, {F(imageDef.HorizontalResolution)}, {imageDef.Height}, {F(imageDef.VerticalResolution)}, ImageResolutionUnits.{imageDef.ResolutionUnits});"); sb.AppendLine($"{baseIndent}doc.ImageDefinitions.Add(imageDef{imageDef.Handle});"); sb.AppendLine(); } private void GenerateUnderlayDefinition(StringBuilder sb, UnderlayDefinition underlayDef, DxfCodeGenerationOptions options, string baseIndent) { if (options.GenerateDetailedComments) { sb.AppendLine($"{baseIndent}// Underlay Definition: {underlayDef.Name} ({underlayDef.Handle})"); } var typeName = underlayDef.GetType().Name; sb.AppendLine($"{baseIndent}var underlayDef{underlayDef.Handle} = new {typeName}(\"{Escape(underlayDef.Name)}\", \"{Escape(underlayDef.File)}\");"); // Add to appropriate collection based on type if (underlayDef is UnderlayDgnDefinition) { sb.AppendLine($"{baseIndent}doc.UnderlayDgnDefinitions.Add((UnderlayDgnDefinition)underlayDef{underlayDef.Handle});"); } else if (underlayDef is UnderlayDwfDefinition) { sb.AppendLine($"{baseIndent}doc.UnderlayDwfDefinitions.Add((UnderlayDwfDefinition)underlayDef{underlayDef.Handle});"); } else if (underlayDef is UnderlayPdfDefinition) { sb.AppendLine($"{baseIndent}doc.UnderlayPdfDefinitions.Add((UnderlayPdfDefinition)underlayDef{underlayDef.Handle});"); } sb.AppendLine(); } private void GenerateRasterVariables(StringBuilder sb, RasterVariables rasterVars, DxfCodeGenerationOptions options, string baseIndent) { if (options.GenerateDetailedComments) { sb.AppendLine($"{baseIndent}// Raster Variables ({rasterVars.Handle})"); } // Check if any properties differ from defaults var hasNonDefaultValues = !rasterVars.DisplayFrame || rasterVars.DisplayQuality != ImageDisplayQuality.High || rasterVars.Units != ImageUnits.Unitless; if (hasNonDefaultValues) { // Only set properties if they differ from defaults if (!rasterVars.DisplayFrame) { sb.AppendLine($"{baseIndent}doc.RasterVariables.DisplayFrame = false;"); } if (rasterVars.DisplayQuality != ImageDisplayQuality.High) { sb.AppendLine($"{baseIndent}doc.RasterVariables.DisplayQuality = ImageDisplayQuality.{rasterVars.DisplayQuality};"); } if (rasterVars.Units != ImageUnits.Unitless) { sb.AppendLine($"{baseIndent}doc.RasterVariables.Units = ImageUnits.{rasterVars.Units};"); } } else if (options.GenerateDetailedComments) { sb.AppendLine($"{baseIndent}// RasterVariables uses default values"); } } private void GenerateLayerState(StringBuilder sb, LayerState layerState, DxfCodeGenerationOptions options, string baseIndent) { if (options.GenerateDetailedComments) { sb.AppendLine($"{baseIndent}// Layer State: {layerState.Name}"); } sb.AppendLine($"{baseIndent}var layerState = new LayerState(\"{Escape(layerState.Name)}\");"); // Set description if not empty if (!string.IsNullOrEmpty(layerState.Description)) { sb.AppendLine($"{baseIndent}layerState.Description = \"{Escape(layerState.Description)}\";"); } // Set current layer if specified if (!string.IsNullOrEmpty(layerState.CurrentLayer)) { sb.AppendLine($"{baseIndent}layerState.CurrentLayer = \"{Escape(layerState.CurrentLayer)}\";"); } // Set paper space flag if true if (layerState.PaperSpace) { sb.AppendLine($"{baseIndent}layerState.PaperSpace = true;"); } // Add layer state properties if any if (layerState.Properties.Count > 0) { if (options.GenerateDetailedComments) { sb.AppendLine($"{baseIndent}// Layer state properties"); } foreach (var kvp in layerState.Properties) { var layerName = kvp.Key; var props = kvp.Value; sb.AppendLine($"{baseIndent}layerState.Properties.Add(\"{Escape(layerName)}\", new LayerStateProperties(\"{Escape(layerName)}\")"); sb.AppendLine($"{baseIndent}{{"); sb.AppendLine($"{baseIndent} Color = AciColor.FromCadIndex({props.Color.Index}),"); sb.AppendLine($"{baseIndent} Lineweight = Lineweight.{props.Lineweight},"); sb.AppendLine($"{baseIndent} LinetypeName = \"{Escape(props.LinetypeName)}\","); sb.AppendLine($"{baseIndent} Flags = LayerPropertiesFlags.{props.Flags},"); sb.AppendLine($"{baseIndent} Transparency = new Transparency({props.Transparency.Value})"); sb.AppendLine($"{baseIndent}}});"); } } sb.AppendLine(); } private void GeneratePlotSettings(StringBuilder sb, PlotSettings plotSettings, DxfCodeGenerationOptions options, string baseIndent) { if (options.GenerateDetailedComments) { sb.AppendLine($"{baseIndent}// Plot Settings"); } sb.AppendLine($"{baseIndent}var plotSettings = new PlotSettings();"); // Set page setup name if not empty if (!string.IsNullOrEmpty(plotSettings.PageSetupName)) { sb.AppendLine($"{baseIndent}plotSettings.PageSetupName = \"{Escape(plotSettings.PageSetupName)}\";"); } // Set plotter name if not empty if (!string.IsNullOrEmpty(plotSettings.PlotterName)) { sb.AppendLine($"{baseIndent}plotSettings.PlotterName = \"{Escape(plotSettings.PlotterName)}\";"); } // Set paper size name if not empty if (!string.IsNullOrEmpty(plotSettings.PaperSizeName)) { sb.AppendLine($"{baseIndent}plotSettings.PaperSizeName = \"{Escape(plotSettings.PaperSizeName)}\";"); } // Set view name if not empty if (!string.IsNullOrEmpty(plotSettings.ViewName)) { sb.AppendLine($"{baseIndent}plotSettings.ViewName = \"{Escape(plotSettings.ViewName)}\";"); } // Set current style sheet if not empty if (!string.IsNullOrEmpty(plotSettings.CurrentStyleSheet)) { sb.AppendLine($"{baseIndent}plotSettings.CurrentStyleSheet = \"{Escape(plotSettings.CurrentStyleSheet)}\";"); } // Set paper margin if not default if (plotSettings.PaperMargin.Left != 0 || plotSettings.PaperMargin.Bottom != 0 || plotSettings.PaperMargin.Right != 0 || plotSettings.PaperMargin.Top != 0) { sb.AppendLine($"{baseIndent}plotSettings.PaperMargin = new PaperMargin({F(plotSettings.PaperMargin.Left)}, {F(plotSettings.PaperMargin.Bottom)}, {F(plotSettings.PaperMargin.Right)}, {F(plotSettings.PaperMargin.Top)});"); } // Set paper size if not default if (plotSettings.PaperSize.X != 0 || plotSettings.PaperSize.Y != 0) { sb.AppendLine($"{baseIndent}plotSettings.PaperSize = new Vector2({F(plotSettings.PaperSize.X)}, {F(plotSettings.PaperSize.Y)});"); } // Set origin if not default if (plotSettings.Origin.X != 0 || plotSettings.Origin.Y != 0) { sb.AppendLine($"{baseIndent}plotSettings.Origin = new Vector2({F(plotSettings.Origin.X)}, {F(plotSettings.Origin.Y)});"); } // Set scale to fit if true if (plotSettings.ScaleToFit) { sb.AppendLine($"{baseIndent}plotSettings.ScaleToFit = true;"); } // Set scale if not 1:1 if (plotSettings.PrintScaleNumerator != 1.0 || plotSettings.PrintScaleDenominator != 1.0) { sb.AppendLine($"{baseIndent}plotSettings.PrintScaleNumerator = {F(plotSettings.PrintScaleNumerator)};"); sb.AppendLine($"{baseIndent}plotSettings.PrintScaleDenominator = {F(plotSettings.PrintScaleDenominator)};"); } // Set plot type if not default if (plotSettings.PlotType != PlotType.DrawingExtents) { sb.AppendLine($"{baseIndent}plotSettings.PlotType = PlotType.{plotSettings.PlotType};"); } // Set paper units if not default if (plotSettings.PaperUnits != PlotPaperUnits.Milimeters) { sb.AppendLine($"{baseIndent}plotSettings.PaperUnits = PlotPaperUnits.{plotSettings.PaperUnits};"); } // Set rotation if not default if (plotSettings.PaperRotation != PlotRotation.NoRotation) { sb.AppendLine($"{baseIndent}plotSettings.PaperRotation = PlotRotation.{plotSettings.PaperRotation};"); } sb.AppendLine(); } private void GenerateDictionaryObjectPlaceholder(StringBuilder sb, DxfCodeGenerationOptions options, string baseIndent) { // DictionaryObject is an internal class in netDxf and is not exposed in the public API // It is used internally for managing dictionary entries in DXF files // Dictionary objects are typically created and managed automatically by the netDxf library // when working with named object dictionaries and are not intended for direct user generation // Always generate the basic comment sb.AppendLine($"{baseIndent}// Dictionary objects are internal to netDxf and not directly accessible"); if (options.GenerateDetailedComments) { sb.AppendLine($"{baseIndent}// Dictionary objects store key-value pairs for named objects"); sb.AppendLine($"{baseIndent}// They are used internally for organizing objects like layer states"); sb.AppendLine($"{baseIndent}// Example structure:"); sb.AppendLine($"{baseIndent}// Handle: [object handle]"); sb.AppendLine($"{baseIndent}// Entries: Dictionary of handle/name pairs"); sb.AppendLine($"{baseIndent}// IsHardOwner: [boolean indicating ownership type]"); sb.AppendLine($"{baseIndent}// Cloning: [DictionaryCloningFlags]"); sb.AppendLine($"{baseIndent}// Note: DictionaryObject is internal to netDxf and not available for direct generation"); } } private void GenerateLayerStatePlaceholder(StringBuilder sb, DxfCodeGenerationOptions options, string baseIndent) { if (options.GenerateDetailedComments) { sb.AppendLine($"{baseIndent}// LayerState objects are internal to netDxf and not directly accessible"); sb.AppendLine($"{baseIndent}// LayerState objects store layer property snapshots"); sb.AppendLine($"{baseIndent}// Name: [layer state name]"); sb.AppendLine($"{baseIndent}// Description: [optional description]"); sb.AppendLine($"{baseIndent}// LayerProperties: Dictionary of layer names and their saved properties"); sb.AppendLine($"{baseIndent}// Create a LayerState to save and restore layer properties"); } sb.AppendLine($"{baseIndent}var layerState = new LayerState(\"MyLayerState\")"); sb.AppendLine($"{baseIndent}{{"); sb.AppendLine($"{baseIndent} Description = \"Sample layer state description\","); sb.AppendLine($"{baseIndent} CurrentLayer = \"0\","); sb.AppendLine($"{baseIndent} PaperSpace = false"); sb.AppendLine($"{baseIndent}}};\n"); if (options.GenerateDetailedComments) { sb.AppendLine($"{baseIndent}// Add layer properties to the layer state"); } sb.AppendLine($"{baseIndent}var layerProperties = new LayerStateProperties(\"0\")"); sb.AppendLine($"{baseIndent}{{"); sb.AppendLine($"{baseIndent} Flags = LayerPropertiesFlags.Plot,"); sb.AppendLine($"{baseIndent} LinetypeName = \"Continuous\","); sb.AppendLine($"{baseIndent} Color = AciColor.Default,"); sb.AppendLine($"{baseIndent} Lineweight = Lineweight.Default,"); sb.AppendLine($"{baseIndent} Transparency = new Transparency(0)"); sb.AppendLine($"{baseIndent}}};\n"); sb.AppendLine($"{baseIndent}layerState.Properties.Add(layerProperties.Name, layerProperties);\n"); if (options.GenerateDetailedComments) { sb.AppendLine($"{baseIndent}// Add the layer state to the document's layer state manager"); } sb.AppendLine($"{baseIndent}doc.Layers.StateManager.Add(layerState);"); } private void GeneratePlotSettingsPlaceholder(StringBuilder sb, DxfCodeGenerationOptions options, string baseIndent) { if (options.GenerateDetailedComments) { sb.AppendLine($"{baseIndent}// PlotSettings objects are internal to netDxf and not directly accessible"); sb.AppendLine($"{baseIndent}// PlotSettings objects store plot configuration data"); sb.AppendLine($"{baseIndent}// PlotConfigurationName: [plotter configuration name]"); sb.AppendLine($"{baseIndent}// PaperSize: [paper size name]"); sb.AppendLine($"{baseIndent}// PlotArea: [plot area type]"); sb.AppendLine($"{baseIndent}// Create plot settings for layout configuration"); } sb.AppendLine($"{baseIndent}var plotSettings = new PlotSettings()"); sb.AppendLine($"{baseIndent}{{"); sb.AppendLine($"{baseIndent} PageSetupName = \"MyPageSetup\","); sb.AppendLine($"{baseIndent} PlotterName = \"DWG To PDF.pc3\","); sb.AppendLine($"{baseIndent} PaperSizeName = \"ISO_A4_(210.00_x_297.00_MM)\","); sb.AppendLine($"{baseIndent} ViewName = string.Empty,"); sb.AppendLine($"{baseIndent} CurrentStyleSheet = \"monochrome.ctb\","); sb.AppendLine($"{baseIndent} PaperMargin = new PaperMargin(7.5, 20.0, 7.5, 20.0),"); sb.AppendLine($"{baseIndent} PaperSize = new Vector2(210.0, 297.0),"); sb.AppendLine($"{baseIndent} Origin = Vector2.Zero,"); sb.AppendLine($"{baseIndent} WindowUpRight = Vector2.Zero,"); sb.AppendLine($"{baseIndent} WindowBottomLeft = Vector2.Zero,"); sb.AppendLine($"{baseIndent} ScaleToFit = true,"); sb.AppendLine($"{baseIndent} PrintScaleNumerator = 1.0,"); sb.AppendLine($"{baseIndent} PrintScaleDenominator = 1.0,"); sb.AppendLine($"{baseIndent} Flags = PlotFlags.DrawViewportsFirst | PlotFlags.PrintLineweights | PlotFlags.PlotPlotStyles | PlotFlags.UseStandardScale,"); sb.AppendLine($"{baseIndent} PlotType = PlotType.DrawingExtents,"); sb.AppendLine($"{baseIndent} PaperUnits = PlotPaperUnits.Milimeters,"); sb.AppendLine($"{baseIndent} PaperRotation = PlotRotation.Degrees90,"); sb.AppendLine($"{baseIndent} ShadePlotMode = ShadePlotMode.AsDisplayed,"); sb.AppendLine($"{baseIndent} ShadePlotResolutionMode = ShadePlotResolutionMode.Normal,"); sb.AppendLine($"{baseIndent} ShadePlotDPI = 300,"); sb.AppendLine($"{baseIndent} PaperImageOrigin = Vector2.Zero"); sb.AppendLine($"{baseIndent}}};\n"); if (options.GenerateDetailedComments) { sb.AppendLine($"{baseIndent}// Note: PlotSettings is typically used with Layout objects"); sb.AppendLine($"{baseIndent}// Example: layout.PlotSettings = plotSettings;"); } } private void GenerateXRecordPlaceholder(StringBuilder sb, DxfCodeGenerationOptions options, string baseIndent) { // XRecord objects are internal to netDxf and not exposed in the public API // They are used internally for storing arbitrary data and are not meant for direct user generation // Always generate basic comment to satisfy tests sb.AppendLine($"{baseIndent}// XRecord objects are internal to netDxf and not directly accessible"); if (options.GenerateDetailedComments) { sb.AppendLine($"{baseIndent}// XRecord objects contain arbitrary data as key-value pairs"); sb.AppendLine($"{baseIndent}// Note: XRecord objects are internal to netDxf and cannot be directly created by users"); sb.AppendLine($"{baseIndent}// They are used internally for storing arbitrary data in DXF files"); } } private void GenerateViewPlaceholder(StringBuilder sb, string viewName, string baseIndent) { sb.AppendLine($"{baseIndent}// View: {Escape(viewName)} (Views collection is internal in netDxf)"); sb.AppendLine($"{baseIndent}var view{SafeName(viewName)} = new View(\"{Escape(viewName)}\");"); sb.AppendLine($"{baseIndent}view{SafeName(viewName)}.Target = new Vector3(0, 0, 0);"); sb.AppendLine($"{baseIndent}view{SafeName(viewName)}.Camera = new Vector3(0, 0, 1);"); sb.AppendLine($"{baseIndent}view{SafeName(viewName)}.Height = 10.0;"); sb.AppendLine($"{baseIndent}view{SafeName(viewName)}.Width = 10.0;"); sb.AppendLine($"{baseIndent}view{SafeName(viewName)}.Rotation = 0.0;"); sb.AppendLine($"{baseIndent}view{SafeName(viewName)}.ViewMode = ViewModeFlags.Off;"); sb.AppendLine($"{baseIndent}view{SafeName(viewName)}.FieldOfView = 40.0;"); sb.AppendLine($"{baseIndent}view{SafeName(viewName)}.FrontClippingPlane = 0.0;"); sb.AppendLine($"{baseIndent}view{SafeName(viewName)}.BackClippingPlane = 0.0;"); sb.AppendLine($"{baseIndent}// Note: Cannot add to doc.Views as it is internal - doc.Views.Add(view{SafeName(viewName)});"); } private void GenerateViewport(StringBuilder sb, Viewport viewport, string baseIndent) { var statusFlags = GenerateViewportStatusFlags(viewport.Status); if (statusFlags.Length > 80) // If the line is too long, use a variable { sb.AppendLine($"{baseIndent} var viewportStatus = {statusFlags};"); } var vpVar = $"viewport{_entityCounter++}"; sb.AppendLine($"{baseIndent} var {vpVar} = new Viewport("); sb.AppendLine($"{baseIndent} new Vector2({F(viewport.Center.X)}, {F(viewport.Center.Y)}),"); sb.AppendLine($"{baseIndent} {F(viewport.Width)}, {F(viewport.Height)})"); sb.AppendLine($"{baseIndent} {{"); GenerateEntityPropertiesCore(sb, viewport, baseIndent + " "); // Set Center property if Z coordinate is not zero if (Math.Abs(viewport.Center.Z) > 1e-6) { sb.AppendLine($"{baseIndent} Center = new Vector3({F(viewport.Center.X)}, {F(viewport.Center.Y)}, {F(viewport.Center.Z)}),"); } sb.AppendLine($"{baseIndent} ViewCenter = new Vector2({F(viewport.ViewCenter.X)}, {F(viewport.ViewCenter.Y)}),"); sb.AppendLine($"{baseIndent} ViewHeight = {F(viewport.ViewHeight)},"); sb.AppendLine($"{baseIndent} ViewTarget = new Vector3({F(viewport.ViewTarget.X)}, {F(viewport.ViewTarget.Y)}, {F(viewport.ViewTarget.Z)}),"); sb.AppendLine($"{baseIndent} ViewDirection = new Vector3({F(viewport.ViewDirection.X)}, {F(viewport.ViewDirection.Y)}, {F(viewport.ViewDirection.Z)}),"); sb.AppendLine($"{baseIndent} LensLength = {F(viewport.LensLength)},"); sb.AppendLine($"{baseIndent} TwistAngle = {F(viewport.TwistAngle)},"); sb.AppendLine($"{baseIndent} CircleZoomPercent = {viewport.CircleZoomPercent},"); if (statusFlags.Length > 80) { sb.AppendLine($"{baseIndent} Status = viewportStatus,"); } else { sb.AppendLine($"{baseIndent} Status = {statusFlags},"); } // Additional properties if (Math.Abs(viewport.SnapBase.X) > 1e-12 || Math.Abs(viewport.SnapBase.Y) > 1e-12) { sb.AppendLine($"{baseIndent} SnapBase = new Vector2({F(viewport.SnapBase.X)}, {F(viewport.SnapBase.Y)}),"); } if (Math.Abs(viewport.SnapSpacing.X - 10.0) > 1e-12 || Math.Abs(viewport.SnapSpacing.Y - 10.0) > 1e-12) { sb.AppendLine($"{baseIndent} SnapSpacing = new Vector2({F(viewport.SnapSpacing.X)}, {F(viewport.SnapSpacing.Y)}),"); } if (Math.Abs(viewport.GridSpacing.X - 10.0) > 1e-12 || Math.Abs(viewport.GridSpacing.Y - 10.0) > 1e-12) { sb.AppendLine($"{baseIndent} GridSpacing = new Vector2({F(viewport.GridSpacing.X)}, {F(viewport.GridSpacing.Y)}),"); } if (Math.Abs(viewport.FrontClipPlane) > 1e-12) { sb.AppendLine($"{baseIndent} FrontClipPlane = {F(viewport.FrontClipPlane)},"); } if (Math.Abs(viewport.BackClipPlane) > 1e-12) { sb.AppendLine($"{baseIndent} BackClipPlane = {F(viewport.BackClipPlane)},"); } if (Math.Abs(viewport.SnapAngle) > 1e-12) { sb.AppendLine($"{baseIndent} SnapAngle = {F(viewport.SnapAngle)},"); } if (Math.Abs(viewport.UcsOrigin.X) > 1e-12 || Math.Abs(viewport.UcsOrigin.Y) > 1e-12 || Math.Abs(viewport.UcsOrigin.Z) > 1e-12) { sb.AppendLine($"{baseIndent} UcsOrigin = new Vector3({F(viewport.UcsOrigin.X)}, {F(viewport.UcsOrigin.Y)}, {F(viewport.UcsOrigin.Z)}),"); } if (Math.Abs(viewport.UcsXAxis.X - 1.0) > 1e-12 || Math.Abs(viewport.UcsXAxis.Y) > 1e-12 || Math.Abs(viewport.UcsXAxis.Z) > 1e-12) { sb.AppendLine($"{baseIndent} UcsXAxis = new Vector3({F(viewport.UcsXAxis.X)}, {F(viewport.UcsXAxis.Y)}, {F(viewport.UcsXAxis.Z)}),"); } if (Math.Abs(viewport.UcsYAxis.X) > 1e-12 || Math.Abs(viewport.UcsYAxis.Y - 1.0) > 1e-12 || Math.Abs(viewport.UcsYAxis.Z) > 1e-12) { sb.AppendLine($"{baseIndent} UcsYAxis = new Vector3({F(viewport.UcsYAxis.X)}, {F(viewport.UcsYAxis.Y)}, {F(viewport.UcsYAxis.Z)}),"); } if (Math.Abs(viewport.Elevation) > 1e-12) { sb.AppendLine($"{baseIndent} Elevation = {F(viewport.Elevation)},"); } // Clipping boundary (non-rectangular) if (viewport.ClippingBoundary != null) { // We will try to rebuild the clipping boundary entity if possible // For now support Polyline2D and Circle boundaries sb.AppendLine($"{baseIndent} ClippingBoundary = "); if (viewport.ClippingBoundary is Polyline2D poly2d) { GeneratePolyline2DConstructor(sb, poly2d, baseIndent + " "); sb.AppendLine(";"); } else if (viewport.ClippingBoundary is Circle circle) { GenerateCircleConstructor(sb, circle, baseIndent + " "); sb.AppendLine(";"); } else { sb.AppendLine($"{baseIndent} null,"); } } sb.AppendLine($"{baseIndent} }};"); // Add viewport to document before modifying collections that require ownership sb.AppendLine($"{baseIndent} doc.Entities.Add({vpVar});"); // Frozen layers (requires viewport to be owned by document) if (viewport.FrozenLayers is { Count: > 0 }) { foreach (var layer in viewport.FrozenLayers) { sb.AppendLine($"{baseIndent} {vpVar}.FrozenLayers.Add(doc.Layers[\"{Escape(layer.Name)}\"]);"); } } // Some properties may be overridden when the entity is added to the document. // Ensure Elevation matches the source after ownership is established. if (Math.Abs(viewport.Elevation) > 1e-12) { sb.AppendLine($"{baseIndent} {vpVar}.Elevation = {F(viewport.Elevation)};"); } } private string GenerateViewportStatusFlags(ViewportStatusFlags flags) { if ((int)flags == 0) return "(ViewportStatusFlags)0"; var flagNames = new List(); foreach (ViewportStatusFlags flag in Enum.GetValues(typeof(ViewportStatusFlags))) { if ((int)flag != 0 && flags.HasFlag(flag)) { flagNames.Add($"ViewportStatusFlags.{flag}"); } } return flagNames.Count > 0 ? string.Join(" | ", flagNames) : "(ViewportStatusFlags)0"; } private void GenerateDimensionStyleProperties(StringBuilder sb, Dimension dimension, string baseIndent) { // Generate dimension style properties if they differ from defaults if (dimension.Style != null && dimension.Style.Name != "Standard") { sb.AppendLine($"{baseIndent}Style = doc.DimensionStyles[\"{dimension.Style.Name}\"],"); } // Generate text rotation if not zero if (Math.Abs(dimension.TextRotation) > 1e-6) { sb.AppendLine($"{baseIndent}TextRotation = {F(dimension.TextRotation)},"); } // Generate user text if specified if (!string.IsNullOrEmpty(dimension.UserText)) { sb.AppendLine($"{baseIndent}UserText = \"{Escape(dimension.UserText)}\","); } // Generate attachment point if not default if (dimension.AttachmentPoint != MTextAttachmentPoint.TopLeft) { sb.AppendLine($"{baseIndent}AttachmentPoint = MTextAttachmentPoint.{dimension.AttachmentPoint},"); } // Generate line spacing properties if not default if (dimension.LineSpacingStyle != MTextLineSpacingStyle.AtLeast) { sb.AppendLine($"{baseIndent}LineSpacingStyle = MTextLineSpacingStyle.{dimension.LineSpacingStyle},"); } if (Math.Abs(dimension.LineSpacingFactor - 1.0) > 1e-6) { sb.AppendLine($"{baseIndent}LineSpacingFactor = {F(dimension.LineSpacingFactor)},"); } // Generate elevation if not zero if (Math.Abs(dimension.Elevation) > 1e-6) { sb.AppendLine($"{baseIndent}Elevation = {F(dimension.Elevation)},"); } } private void GenerateDimensionStyleOverrides(StringBuilder sb, Dimension dimension, string entityVariableName, string baseIndent) { // Generate style overrides if any exist if (dimension.StyleOverrides is { Count: > 0 }) { sb.AppendLine($"{baseIndent}// Style overrides:"); foreach (var kvp in dimension.StyleOverrides) { var overrideValue = FormatStyleOverrideValue(kvp.Value.Value); sb.AppendLine($"{baseIndent}{entityVariableName}.StyleOverrides.Add(DimensionStyleOverrideType.{kvp.Key}, {overrideValue});"); } } } private string FormatStyleOverrideValue(object? value) { if (value == null) return "null"; switch (value) { case double d: return F(d); case float f: return F(f); case int i: return i.ToString(); case bool b: return b.ToString().ToLower(); case string s: return $"\"{Escape(s)}\""; case AciColor color: if (color.IsByLayer) return "AciColor.ByLayer"; if (color.IsByBlock) return "AciColor.ByBlock"; return $"new AciColor({color.Index})"; case Linetype linetype: return $"doc.Linetypes[\"{linetype.Name}\"]"; case Lineweight lineweight: return $"Lineweight.{lineweight}"; case netDxf.Blocks.Block block: return $"doc.Blocks[\"{block.Name}\"]"; case TextStyle textStyle: return $"doc.TextStyles[\"{textStyle.Name}\"]"; case FractionFormatType fractionType: return $"FractionFormatType.{fractionType}"; case LinearUnitType linearUnit: return $"LinearUnitType.{linearUnit}"; case AngleUnitType angleUnit: return $"AngleUnitType.{angleUnit}"; case Enum enumValue: return $"{enumValue.GetType().Name}.{enumValue}"; default: return value.ToString() ?? string.Empty; } } private void GenerateSplineAdvancedProperties(StringBuilder sb, Spline spline, string baseIndent) { // Generate fit tolerance if not default if (Math.Abs(spline.FitTolerance - 0.0000000001) > 1e-15) { sb.AppendLine($"{baseIndent}splineEntity.FitTolerance = {F(spline.FitTolerance)};"); } // Generate control point tolerance if not default if (Math.Abs(spline.CtrlPointTolerance - 0.0000001) > 1e-10) { sb.AppendLine($"{baseIndent}splineEntity.CtrlPointTolerance = {F(spline.CtrlPointTolerance)};"); } // Generate knot parameterization if not default if (spline.KnotParameterization != SplineKnotParameterization.FitChord) { sb.AppendLine($"{baseIndent}splineEntity.KnotParameterization = SplineKnotParameterization.{spline.KnotParameterization};"); } // Generate start tangent if specified if (spline.StartTangent.HasValue) { var tangent = spline.StartTangent.Value; sb.AppendLine($"{baseIndent}splineEntity.StartTangent = new Vector3({F(tangent.X)}, {F(tangent.Y)}, {F(tangent.Z)});"); } // Generate end tangent if specified if (spline.EndTangent.HasValue) { var tangent = spline.EndTangent.Value; sb.AppendLine($"{baseIndent}splineEntity.EndTangent = new Vector3({F(tangent.X)}, {F(tangent.Y)}, {F(tangent.Z)});"); } } private void GenerateTextAdvancedProperties(StringBuilder sb, Text text, string baseIndent) { // Style if (text.Style != null) { if (text.Style.Name != "Standard") { sb.AppendLine($"{baseIndent} Style = textStyle{SafeName(text.Style.Name!)},"); } } // Rotation if (Math.Abs(text.Rotation) > 1e-12) { sb.AppendLine($"{baseIndent} Rotation = {F(text.Rotation)},"); } // WidthFactor (default is 1.0) if (Math.Abs(text.WidthFactor - 1.0) > 1e-12) { sb.AppendLine($"{baseIndent} WidthFactor = {F(text.WidthFactor)},"); } // ObliqueAngle (default is 0.0) if (Math.Abs(text.ObliqueAngle) > 1e-12) { sb.AppendLine($"{baseIndent} ObliqueAngle = {F(text.ObliqueAngle)},"); } // IsBackward (default is false) if (text.IsBackward) { sb.AppendLine($"{baseIndent} IsBackward = true,"); } // IsUpsideDown (default is false) if (text.IsUpsideDown) { sb.AppendLine($"{baseIndent} IsUpsideDown = true,"); } } private void GenerateLeaderAdvancedProperties(StringBuilder sb, Leader leader, string entityName, string baseIndent) { // Style property if (leader.Style != null) { if (leader.Style.Name != "Standard") { if (string.IsNullOrEmpty(entityName)) { sb.AppendLine($"{baseIndent} Style = dimStyle{SafeName(leader.Style.Name!)},"); } else { sb.AppendLine($"{baseIndent}{entityName}.Style = dimStyle{SafeName(leader.Style.Name!)};"); } } } // ShowArrowhead property (default is true) if (!leader.ShowArrowhead) { if (string.IsNullOrEmpty(entityName)) { sb.AppendLine($"{baseIndent} ShowArrowhead = false,"); } else { sb.AppendLine($"{baseIndent}{entityName}.ShowArrowhead = false;"); } } // PathType property (default is StraightLineSegments) if (leader.PathType != LeaderPathType.StraightLineSegments) { if (string.IsNullOrEmpty(entityName)) { sb.AppendLine($"{baseIndent} PathType = LeaderPathType.{leader.PathType},"); } else { sb.AppendLine($"{baseIndent}{entityName}.PathType = LeaderPathType.{leader.PathType};"); } } // HasHookline property (default is false) if (leader.HasHookline) { if (string.IsNullOrEmpty(entityName)) { sb.AppendLine($"{baseIndent} HasHookline = true,"); } else { sb.AppendLine($"{baseIndent}{entityName}.HasHookline = true;"); } } // LineColor property (default is ByLayer) if (leader.LineColor.Index != 256) // Not ByLayer { if (leader.LineColor.Index == 0) { if (string.IsNullOrEmpty(entityName)) { sb.AppendLine($"{baseIndent} LineColor = AciColor.ByBlock,"); } else { sb.AppendLine($"{baseIndent}{entityName}.LineColor = AciColor.ByBlock;"); } } else { if (string.IsNullOrEmpty(entityName)) { sb.AppendLine($"{baseIndent} LineColor = new AciColor({leader.LineColor.Index}),"); } else { sb.AppendLine($"{baseIndent}{entityName}.LineColor = new AciColor({leader.LineColor.Index});"); } } } // Elevation property (default is 0.0) if (Math.Abs(leader.Elevation) > 1e-12) { if (string.IsNullOrEmpty(entityName)) { sb.AppendLine($"{baseIndent} Elevation = {F(leader.Elevation)},"); } else { sb.AppendLine($"{baseIndent}{entityName}.Elevation = {F(leader.Elevation)};"); } } // Offset property (default is Vector2.Zero) if (Math.Abs(leader.Offset.X) > 1e-12 || Math.Abs(leader.Offset.Y) > 1e-12) { if (string.IsNullOrEmpty(entityName)) { sb.AppendLine($"{baseIndent} Offset = new Vector2({F(leader.Offset.X)}, {F(leader.Offset.Y)}),"); } else { sb.AppendLine($"{baseIndent}{entityName}.Offset = new Vector2({F(leader.Offset.X)}, {F(leader.Offset.Y)});"); } } // Direction property (default is Vector2.UnitX) if (Math.Abs(leader.Direction.X - 1.0) > 1e-12 || Math.Abs(leader.Direction.Y) > 1e-12) { if (string.IsNullOrEmpty(entityName)) { sb.AppendLine($"{baseIndent} Direction = new Vector2({F(leader.Direction.X)}, {F(leader.Direction.Y)}),"); } else { sb.AppendLine($"{baseIndent}{entityName}.Direction = new Vector2({F(leader.Direction.X)}, {F(leader.Direction.Y)});"); } } } private void GenerateXData(StringBuilder sb, EntityObject entity, string entityVarName, string baseIndent) { if (entity.XData == null || entity.XData.Count == 0) return; foreach (var xdata in entity.XData.Values) { var xdVar = $"xdata{_entityCounter++}"; sb.AppendLine($"{baseIndent}var {xdVar} = new XData(doc.ApplicationRegistries[\"{Escape(xdata.ApplicationRegistry.Name)}\"]);"); foreach (var record in xdata.XDataRecord) { // Ensure we emit literals with the exact types required by XDataCode string valueStr; switch (record.Code) { case XDataCode.Int16: // Explicit short cast to avoid boxing as int when value is a constant like 0 or 1 valueStr = $"(short){Convert.ToInt16(record.Value, CultureInfo.InvariantCulture)}"; break; case XDataCode.Real: case XDataCode.RealX: case XDataCode.RealY: case XDataCode.RealZ: valueStr = F(Convert.ToDouble(record.Value, CultureInfo.InvariantCulture)); break; default: valueStr = record.Value switch { string s => $"\"{Escape(s)}\"", double d => F(d), float f => F(f), short sh => $"(short){sh}", int i => i.ToString(CultureInfo.InvariantCulture), byte[] arr => $"new byte[] {{ {string.Join(", ", arr)} }}", _ => $"\"{Escape(record.Value?.ToString() ?? string.Empty)}\"" }; break; } sb.AppendLine($"{baseIndent}{xdVar}.XDataRecord.Add(new XDataRecord(XDataCode.{record.Code}, {valueStr}));"); } sb.AppendLine($"{baseIndent}{entityVarName}.XData.Add({xdVar});"); } } }