How to insert coordinate elevation points into a certain layer
hello I currently possess an elevation file in XYZ format. My process involves reading the DWG file, filtering points within the specified range based on the TK layer range defined in the DWG file, and subsequently inserting the GCD layer into the DWG file. Prior to insertion, entities within the GCD layer are deleted. Simultaneously, two attributes are assigned to the inserted elevation points: one as an integer and the other as a decimal, corresponding to the integer and decimal portions of the Z coordinate, respectively. Furthermore, color mappings are utilized for visualization based on attribute values, rather than employing text annotations for display. Below is my code. Although the generated DWG file successfully inserts points into the GCD layer, it exhibits significant differences from the original DWG file, with many functionalities remaining unimplemented. 01.dwg represents the original DWG file, while 1.dwg corresponds to the file generated via my code. Could you please advise which areas require modification?
`using ACadSharp; using ACadSharp.Entities; using ACadSharp.IO; using ACadSharp.Tables; using CSMath; using System; using System.Collections.Generic; using System.IO; using System.Linq;
namespace DepthPointProcessor { public class DwgProcessor {
public static void ProcessDwgWithAttributedDepth(string inputDwgPath, string depthFilePath, string outputDwgPath)
{
Console.WriteLine($"开始处理DWG文件: {inputDwgPath}");
CadDocument doc = null;
try
{
doc = ReadDwgFile(inputDwgPath);
BoundingBox tkBounds = GetTkLayerBounds(doc);
List<XYZ> rawDepthPoints = ReadXYZDepthFile(depthFilePath);
List<XYZ> filteredDepthPoints = FilterPointsByBounds(rawDepthPoints, tkBounds);
Console.WriteLine($"在TK图层边界内筛选出 {filteredDepthPoints.Count} 个水深点。");
ClearLayerEntities(doc, "GCD");
AddAttributedDepthPoints(doc, filteredDepthPoints);
SaveDwgFile(doc, outputDwgPath);
Console.WriteLine($"处理完成,结果保存至: {outputDwgPath}");
}
catch (Exception ex)
{
Console.WriteLine($"处理过程中发生错误: {ex.Message}");
}
finally
{
}
}
private static CadDocument ReadDwgFile(string filePath)
{
using (var reader = new DwgReader(filePath))
{
Console.WriteLine($"正在读取DWG文件: {filePath}");
return reader.Read();
}
}
private static BoundingBox GetTkLayerBounds(CadDocument doc)
{
if (!doc.Layers.TryGetValue("TK", out Layer tkLayer))
{
throw new InvalidOperationException("DWG中找不到 'TK' 图层。");
}
var tkEntities = doc.ModelSpace.Entities.Where(e => e.Layer == tkLayer).ToList();
if (!tkEntities.Any())
{
throw new InvalidOperationException("TK图层中没有找到任何实体,无法确定边界。");
}
double minX = double.MaxValue, minY = double.MaxValue, minZ = double.MaxValue;
double maxX = double.MinValue, maxY = double.MinValue, maxZ = double.MinValue;
bool firstEntity = true;
foreach (var entity in tkEntities)
{
if (entity is LwPolyline lwPoly)
{
foreach (var vtx in lwPoly.Vertices)
{
if (firstEntity)
{
minX = vtx.Location.X; minY = vtx.Location.Y; minZ = 0; // Default Z value
maxX = vtx.Location.X; maxY = vtx.Location.Y; maxZ = 0; // Default Z value
firstEntity = false;
}
else
{
minX = Math.Min(minX, vtx.Location.X);
minY = Math.Min(minY, vtx.Location.Y);
minZ = Math.Min(minZ, 0); // Default Z value for XY type
maxX = Math.Max(maxX, vtx.Location.X);
maxY = Math.Max(maxY, vtx.Location.Y);
maxZ = Math.Max(maxZ, 0); // Default Z value for XY type
}
}
}
else if (entity is Point pt)
{
if (firstEntity)
{
minX = pt.Location.X; minY = pt.Location.Y; minZ = pt.Location.Z;
maxX = pt.Location.X; maxY = pt.Location.Y; maxZ = pt.Location.Z;
firstEntity = false;
}
else
{
minX = Math.Min(minX, pt.Location.X);
minY = Math.Min(minY, pt.Location.Y);
minZ = Math.Min(minZ, pt.Location.Z);
maxX = Math.Max(maxX, pt.Location.X);
maxY = Math.Max(maxY, pt.Location.Y);
maxZ = Math.Max(maxZ, pt.Location.Z);
}
}
}
if (firstEntity)
{
throw new InvalidOperationException("无法计算TK图层边界,可能TK图层中没有可计算边界的几何实体。");
}
Console.WriteLine($"TK图层边界确定:Min({minX:F2}, {minY:F2}), Max({maxX:F2}, {maxY:F2})");
return new BoundingBox(new XYZ(minX, minY, minZ), new XYZ(maxX, maxY, maxZ));
}
private static List<XYZ> ReadXYZDepthFile(string filePath)
{
var points = new List<XYZ>();
try
{
string[] lines = File.ReadAllLines(filePath);
foreach (string line in lines)
{
string[] parts = line.Split(' ', '\t');
if (parts.Length >= 2)
{
if (double.TryParse(parts[0], out double x) &&
double.TryParse(parts[1], out double y) &&
double.TryParse(parts[2], out double z)) // Z here is the depth
{
points.Add(new XYZ(x, y, z));
}
else
{
Console.WriteLine($"警告: 无法解析行 '{line}'。");
}
}
else
{
Console.WriteLine($"警告: 跳过格式不正确的行 '{line}'。");
}
}
}
catch (Exception ex)
{
Console.WriteLine($"读取水深文件时出错: {ex.Message}");
throw;
}
Console.WriteLine($"成功从 {filePath} 读取 {points.Count} 个水深点。");
return points;
}
private static List<XYZ> FilterPointsByBounds(List<XYZ> points, BoundingBox bounds)
{
return points.Where(p =>
p.X >= bounds.Min.X && p.X <= bounds.Max.X &&
p.Y >= bounds.Min.Y && p.Y <= bounds.Max.Y).ToList();
}
private static void ClearLayerEntities(CadDocument doc, string layerName) { if (!doc.Layers.TryGetValue(layerName, out Layer layer)) { Console.WriteLine($"图层 '{layerName}' 不存在,无需清除实体。"); return; }
var entitiesToRemove = doc.ModelSpace.Entities
.Where(e => e.Layer == layer)
.ToList();
int removedCount = 0;
foreach (var entity in entitiesToRemove)
{
// Console.WriteLine(entity.ExtendedDatas);
// Console.WriteLine(entity);
// Console.WriteLine(entity.GetType().Name);
doc.ModelSpace.Entities.Remove(entity);
removedCount++;
}
Console.WriteLine($"已从图层 '{layerName}' 删除 {removedCount} 个现有实体。");
int remainingCount = doc.ModelSpace.Entities.Count(e => e.Layer == layer);
if (remainingCount > 0)
{
Console.WriteLine($"警告: 清除后图层 '{layerName}' 仍有 {remainingCount} 个实体!");
}
}
private static Color GetColorByDepthParts(int integerPart, int decimalPart)
{
byte r = 0, g = 0, b = 0;
byte decFactor = (byte)(decimalPart * 2.55); // 0 -> 0, 99 -> ~252
if (integerPart < 1) // 0.xx
{
r = (byte)(0);
g = (byte)(decFactor / 2);
b = (byte)(255 - decFactor);
}
else if (integerPart == 1) // 1.xx
{
r = (byte)(decFactor);
g = (byte)(150 + decFactor / 2);
b = (byte)(0);
}
else if (integerPart == 2) // 2.xx
{
r = (byte)(255);
g = (byte)(255 - decFactor / 2);
b = (byte)(0);
}
else if (integerPart == 3) // 3.xx
{
r = (byte)(255);
g = (byte)(165 - decFactor / 2);
b = (byte)(0);
}
else // integerPart >= 4
{
r = (byte)(255 - decFactor / 2);
g = (byte)(0);
b = (byte)(0);
}
r = Math.Max((byte)0, Math.Min((byte)255, r));
g = Math.Max((byte)0, Math.Min((byte)255, g));
b = Math.Max((byte)0, Math.Min((byte)255, b));
Color color = new Color(r, g, b);
var rgb = color.GetRgb();
return Color.FromTrueColor((uint)((rgb[0] << 16) | (rgb[1] << 8) | rgb[2]));
}
private static void AddAttributedDepthPoints(CadDocument doc, List<XYZ> points) { Layer gcdLayer = GetOrCreateLayer(doc, "GCD");
SetPointStyle(doc);
string blockName = "gc000";
if (doc.BlockRecords.Contains(blockName))
{
doc.BlockRecords.Remove(blockName);
Console.WriteLine($"已移除旧的块定义 '{blockName}'。");
}
BlockRecord depthPointBlock = new BlockRecord(blockName);
doc.BlockRecords.Add(depthPointBlock); // 将新的块定义添加到文档中
Console.WriteLine($"已创建新的块定义 '{blockName}' 用于水深点。");
Point blockPoint = new Point
{
Location = XYZ.Zero,
Layer = gcdLayer,
Color = Color.ByLayer,
};
depthPointBlock.Entities.Add(blockPoint);
AttributeDefinition integerDepthAttributeDef = new AttributeDefinition
{
Tag = "integer",
Value = "0",
InsertPoint = new XYZ(1.0, 0.5, 0.0),
Height = 0.5,
HorizontalAlignment = TextHorizontalAlignment.Left,
VerticalAlignment = TextVerticalAlignmentType.Middle,
Layer = gcdLayer,
Color = Color.ByLayer
};
depthPointBlock.Entities.Add(integerDepthAttributeDef);
AttributeDefinition decimalDepthAttributeDef = new AttributeDefinition
{
Tag = "decimal",
Value = "00",
InsertPoint = new XYZ(1.0, -0.5, 0.0),
Height = 0.5,
HorizontalAlignment = TextHorizontalAlignment.Left,
VerticalAlignment = TextVerticalAlignmentType.Middle,
Layer = gcdLayer,
Color = Color.ByLayer
};
depthPointBlock.Entities.Add(decimalDepthAttributeDef);
int pointCounter = 0;
foreach (var p in points)
{
pointCounter++;
double depth = p.Z;
int integerPart = (int)Math.Floor(depth);
int decimalPart = (int)Math.Round((depth - integerPart) * 100);
Color entityColor = GetColorByDepthParts(integerPart, decimalPart);
Insert insert = new Insert(depthPointBlock)
{
InsertPoint = new XYZ(p.X, p.Y, p.Z),
Layer = gcdLayer,
Color = entityColor,
Rotation = 0,
};
AttributeEntity integerAttribute = new AttributeEntity
{
Tag = "integer",
Value = integerPart.ToString(),
InsertPoint = new XYZ(p.X , p.Y, p.Z),
Height = integerDepthAttributeDef.Height,
HorizontalAlignment = integerDepthAttributeDef.HorizontalAlignment,
VerticalAlignment = integerDepthAttributeDef.VerticalAlignment,
Layer = gcdLayer,
Color = entityColor
};
insert.Attributes.Add(integerAttribute);
AttributeEntity decimalAttribute = new AttributeEntity
{
Tag = "decimal",
Value = decimalPart.ToString("D2"),
InsertPoint = new XYZ(p.X, p.Y, p.Z),
Height = decimalDepthAttributeDef.Height,
HorizontalAlignment = decimalDepthAttributeDef.HorizontalAlignment,
VerticalAlignment = decimalDepthAttributeDef.VerticalAlignment,
Layer = gcdLayer,
Color = entityColor
};
insert.Attributes.Add(decimalAttribute);
doc.ModelSpace.Entities.Add(insert);
}
Console.WriteLine($"已成功添加 {pointCounter} 个带属性和颜色映射的水深点(块参照形式)到GCD图层。");
}
private static Layer GetOrCreateLayer(CadDocument doc, string layerName)
{
if (doc.Layers.TryGetValue(layerName, out Layer layer))
{
return layer;
}
layer = new Layer(layerName) { Color = Color.FromTrueColor(0x00FF00) }; // 新创建的图层默认绿色
doc.Layers.Add(layer);
Console.WriteLine($"图层 '{layerName}' 不存在,已创建。");
return layer;
}
private static void SetPointStyle(CadDocument doc)
{
// PointDisplayMode 35 for circle with cross, 99 for a simple dot.
// PointDisplaySize is in percentage of screen size.
doc.Header.PointDisplayMode = 3; // X mark
doc.Header.PointDisplaySize = 1.0; // Size in drawing units (example)
}
private static void SaveDwgFile(CadDocument doc, string filePath)
{
using (var writer = new DwgWriter(filePath, doc))
{
writer.OnNotification += NotificationHelper.LogConsoleNotification;
writer.Write();
}
}
}
public static class NotificationHelper { public static void LogConsoleNotification(object sender, NotificationEventArgs e) { Console.WriteLine($"[ACADSHARP NOTIFICATION] {e.Message}"); } }
class Program { static void Main(string[] args) {
string inputDwg = @"F:\cad\02.dwg";
string depthData = @"F:\cad\0530_北段_8m.xyz";
string outputDwg = @"1.dwg";
DwgProcessor.ProcessDwgWithAttributedDepth(inputDwg, depthData, outputDwg);
Console.ReadKey();
}
} } `