Hi, thanks for your time. I have tried to follow your instructions but still getting the same black result. Can't find the problem 😞
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Colors;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using ProjNet.CoordinateSystems;
using ProjNet.CoordinateSystems.Transformations;
[assembly: CommandClass(typeof(ExportToKML.Commands))]
namespace ExportToKML
{
public static class LayerColorMap
{
public static Color ByBlockColor { get; set; } = Color.FromColorIndex(ColorMethod.ByAci, 7); // Default light gray
private static Dictionary<ObjectId, Color> map = new Dictionary<ObjectId, Color>();
private static Color GetLayerColor(ObjectId layerTableRecordId)
{
if (!map.ContainsKey(layerTableRecordId))
{
Database db = layerTableRecordId.Database;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
LayerTable lt = tr.GetObject(db.LayerTableId, OpenMode.ForRead) as LayerTable;
foreach (ObjectId id in lt)
{
LayerTableRecord ltr = tr.GetObject(id, OpenMode.ForRead) as LayerTableRecord;
map[id] = ltr.Color;
}
tr.Commit();
}
}
return map[layerTableRecordId];
}
public static Color GetEffectiveColor(this Entity entity)
{
switch (entity.ColorIndex)
{
case 0: return ByBlockColor;
case 256: return GetLayerColor(entity.LayerId);
default: return entity.Color;
}
}
// KML uses AABBGGRR format (alpha, blue, green, red)
public static string ToKmlColor(this Color color, byte alpha = 255)
{
// Fixed method to properly handle different color types
byte red, green, blue;
if (color.ColorMethod == ColorMethod.ByAci)
{
// Get RGB from ACI color index directly
Autodesk.AutoCAD.Colors.ColorMethod oldMethod = color.ColorMethod;
short colorIndex = color.ColorIndex;
// Use Autodesk's built-in method to convert ACI to RGB
Color aciColor = Color.FromColorIndex(oldMethod, colorIndex);
red = aciColor.Red;
green = aciColor.Green;
blue = aciColor.Blue;
}
else if (color.ColorMethod == ColorMethod.ByColor)
{
red = color.Red;
green = color.Green;
blue = color.Blue;
}
else
{
// Default to white for any other color method
red = green = blue = 255;
}
// Ensure no black colors (fixes Google Earth display issue)
if (red == 0 && green == 0 && blue == 0)
{
red = green = blue = 1; // Near black but not exactly black
}
return alpha.ToString("X2") + blue.ToString("X2") + green.ToString("X2") + red.ToString("X2");
}
}
public class Commands
{
private static readonly ICoordinateTransformation transform;
private const double ShiftLonDegrees = -0.000075;
private const double ShiftLatDegrees = -0.000067;
static Commands()
{
CoordinateSystemFactory csFactory = new CoordinateSystemFactory();
var source = csFactory.CreateFromWkt("PROJCS[\"Israel 1993 / Israeli TM Grid\",GEOGCS[\"GCS_Israel_1993\",DATUM[\"D_Israel_1993\",SPHEROID[\"GRS_1980\",6378137,298.257222101],TOWGS84[-48,55,52,0,0,0,0]],PRIMEM[\"Greenwich\",0],UNIT[\"Degree\",0.0174532925199433]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",31.73439361111111],PARAMETER[\"central_meridian\",35.20451694444445],PARAMETER[\"scale_factor\",1.0000067],PARAMETER[\"false_easting\",219529.584],PARAMETER[\"false_northing\",626907.39],UNIT[\"Meter\",1]]");
var target = GeographicCoordinateSystem.WGS84;
transform = new CoordinateTransformationFactory().CreateFromCoordinateSystems(source, target);
}
[CommandMethod("KML")]
public void ExportSelectionToKML()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
Database db = doc.Database;
PromptSelectionResult psr = ed.GetSelection();
if (psr.Status != PromptStatus.OK)
return;
PromptSaveFileOptions saveOpts = new PromptSaveFileOptions("Select KML output path:");
saveOpts.Filter = "KML Files (*.kml)|*.kml";
PromptFileNameResult saveResult = ed.GetFileNameForSave(saveOpts);
if (saveResult.Status != PromptStatus.OK)
return;
string filePath = saveResult.StringResult;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
LayerTable lt = tr.GetObject(db.LayerTableId, OpenMode.ForRead) as LayerTable;
StringBuilder kml = new StringBuilder();
Dictionary<string, string> layerStyles = new Dictionary<string, string>();
List<string> placemarks = new List<string>();
kml.AppendLine("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
kml.AppendLine("<kml xmlns=\"http://www.opengis.net/kml/2.2\">");
kml.AppendLine("<Document>");
kml.AppendLine("<name>AutoCAD Export</name>");
kml.AppendLine("<description>Generated from AutoCAD</description>");
SelectionSet ss = psr.Value;
foreach (SelectedObject obj in ss)
{
if (obj == null) continue;
Entity ent = tr.GetObject(obj.ObjectId, OpenMode.ForRead) as Entity;
if (ent == null) continue;
string layerName = ent.Layer;
Color color = ent.GetEffectiveColor();
string kmlColor = color.ToKmlColor();
// Create a unique style ID for each entity to preserve exact colors
string styleId = "style_" + layerName.Replace(" ", "_") + "_" + obj.ObjectId.Handle.ToString();
// Create style for this entity
kml.AppendLine($"<Style id=\"{styleId}\">");
kml.AppendLine($" <LineStyle>");
kml.AppendLine($" <color>{kmlColor}</color>");
kml.AppendLine($" <width>2</width>");
kml.AppendLine($" </LineStyle>");
kml.AppendLine($" <PolyStyle>");
kml.AppendLine($" <color>{kmlColor}</color>");
kml.AppendLine($" <fill>0</fill>");
kml.AppendLine($" </PolyStyle>");
kml.AppendLine($" <IconStyle>");
kml.AppendLine($" <color>{kmlColor}</color>");
kml.AppendLine($" <scale>1.2</scale>");
kml.AppendLine($" <Icon><href>http://maps.google.com/mapfiles/kml/shapes/placemark_circle.png</href></Icon>");
kml.AppendLine($" </IconStyle>");
kml.AppendLine($" <LabelStyle><scale>0</scale></LabelStyle>");
kml.AppendLine("</Style>");
if (ent is DBPoint point)
{
WritePointToKML(kml, point.Position, layerName, "", styleId);
}
else if (ent is BlockReference blockRef)
{
string blockData = GetBlockAttributes(blockRef, tr);
WritePointToKML(kml, blockRef.Position, layerName, blockData, styleId);
}
else if (ent is Polyline poly)
{
List<Point3d> pts = SamplePolyline(poly);
WriteLineToKML(kml, pts, layerName, styleId);
}
else if (ent is Polyline3d poly3d)
{
List<Point3d> pts = new List<Point3d>();
foreach (ObjectId vtxId in poly3d)
{
PolylineVertex3d vtx = tr.GetObject(vtxId, OpenMode.ForRead) as PolylineVertex3d;
pts.Add(vtx.Position);
}
WriteLineToKML(kml, pts, layerName, styleId);
}
else if (ent is Line line)
{
WriteLineToKML(kml, new List<Point3d> { line.StartPoint, line.EndPoint }, layerName, styleId);
}
else if (ent is DBText text)
{
WritePointToKML(kml, text.Position, layerName, text.TextString, styleId);
}
else if (ent is Circle circle)
{
List<Point3d> pts = SampleCircle(circle);
WriteLineToKML(kml, pts, layerName + " (Circle)", styleId);
}
}
kml.AppendLine("</Document>");
kml.AppendLine("</kml>");
File.WriteAllText(filePath, kml.ToString(), Encoding.UTF8);
ed.WriteMessage($"\nKML saved to: {filePath}");
tr.Commit();
}
}
private static void WritePointToKML(StringBuilder kml, Point3d pt, string name, string description, string styleId)
{
var (lon, lat) = ConvertITMtoWGS84(pt.X, pt.Y);
kml.AppendLine("<Placemark>");
if (!string.IsNullOrEmpty(name)) kml.AppendLine($" <name>{name}</name>");
if (!string.IsNullOrEmpty(description)) kml.AppendLine($" <description><![CDATA[{description}]]></description>");
kml.AppendLine($" <styleUrl>#{styleId}</styleUrl>");
kml.AppendLine(" <Point>");
kml.AppendLine($" <coordinates>{lon},{lat},0</coordinates>");
kml.AppendLine(" </Point>");
kml.AppendLine("</Placemark>");
}
private static void WriteLineToKML(StringBuilder kml, List<Point3d> pts, string name, string styleId)
{
kml.AppendLine("<Placemark>");
kml.AppendLine($" <name>{name}</name>");
kml.AppendLine($" <styleUrl>#{styleId}</styleUrl>");
kml.AppendLine(" <LineString>");
kml.AppendLine(" <extrude>0</extrude>");
kml.AppendLine(" <tessellate>1</tessellate>");
kml.AppendLine(" <altitudeMode>clampToGround</altitudeMode>");
kml.AppendLine(" <coordinates>");
foreach (var pt in pts)
{
var (lon, lat) = ConvertITMtoWGS84(pt.X, pt.Y);
kml.AppendLine($" {lon},{lat},0");
}
kml.AppendLine(" </coordinates>");
kml.AppendLine(" </LineString>");
kml.AppendLine("</Placemark>");
}
private static List<Point3d> SamplePolyline(Polyline poly)
{
List<Point3d> pts = new List<Point3d>();
double length = poly.Length;
int segments = Math.Max((int)(length / 1.0), 2);
for (int i = 0; i <= segments; i++)
{
double param = poly.GetParameterAtDistance(length * i / segments);
pts.Add(poly.GetPointAtParameter(param));
}
return pts;
}
private static List<Point3d> SampleCircle(Circle circle)
{
List<Point3d> pts = new List<Point3d>();
int segments = 36;
for (int i = 0; i <= segments; i++)
{
double angle = 2 * Math.PI * i / segments;
Point3d pt = circle.Center + new Vector3d(Math.Cos(angle), Math.Sin(angle), 0) * circle.Radius;
pts.Add(pt);
}
return pts;
}
private static string GetBlockAttributes(BlockReference blkRef, Transaction tr)
{
StringBuilder desc = new StringBuilder();
foreach (ObjectId id in blkRef.AttributeCollection)
{
if (tr.GetObject(id, OpenMode.ForRead) is AttributeReference attRef)
{
desc.AppendLine($"{attRef.Tag}: {attRef.TextString}<br>");
}
}
return desc.ToString();
}
private static (double lon, double lat) ConvertITMtoWGS84(double x, double y)
{
double[] result = transform.MathTransform.Transform(new double[] { x, y });
return (result[0] + ShiftLonDegrees, result[1] + ShiftLatDegrees);
}
}
}