Changing LayerNames in C3D files while side loading database breaks the c3d file and sends it to recovery

Changing LayerNames in C3D files while side loading database breaks the c3d file and sends it to recovery

heyimsp12
Enthusiast Enthusiast
102 Views
4 Replies
Message 1 of 5

Changing LayerNames in C3D files while side loading database breaks the c3d file and sends it to recovery

heyimsp12
Enthusiast
Enthusiast

Hi,

 

I have been trying to rename layers in my drawing using following method. It runs perfectly on my AutoCAD files. However, when I have any of the Civil3D Drawings, the method is able to rename the layers in it just fine. However, because side loading the drawing into a database doesn't read the civil3d styles automatically. it breaks the hard references of the layers in AEC objects like alignment styles, corridor styles, etc. I have tried resetting the styles directly in using .net as well, but while sideloading the database, it doesn't read any styles in the drawing.

Am i missing something?

public static void UpdateLayerNamesInDrawings(this List<DrawingModel> dwgModels)
{
    foreach (var dwgModel in dwgModels)
    {
        try
        {
            // Use .NET API for AutoCAD Files.
            var trDel = new TransactionDelegates();
            using (var extDb = new Database(true, false))
            {
                extDb.ReadDwgFile(dwgModel.Path, System.IO.FileShare.ReadWrite, true, "");
                extDb.CloseInput(true);

                trDel.UsingLayerTable((tr, layerTable) =>
                {
                    layerTable.UpgradeOpen();

                    // Update layer name to layerModel.UpdateLayerNameTo and change status -> changed.
                    foreach (var lm in dwgModel.LayerModels)
                    {
                        try
                        {
                            if (!IsLayerNameUpdatable(layerTable, lm))
                                continue;

                            // Update layer name
                            var layer = (LayerTableRecord)tr.GetObject(layerTable[lm.OriginalName], OpenMode.ForWrite);
                            layer.Name = lm.UpdateNameTo;

                            // Change status to Updated Name only.
                            lm.LayerNameChangeStatus = LayerModel.Changestatus.UpdatedNameOnly;
                        }
                        catch (Exception ex)
                        {
                            lm.AppendComment($"Error Occured: {ex.Message}");
                        }
                    }

                }, extDb);

                /// Save drawing
                extDb.SaveAs(dwgModel.Path, DwgVersion.Current); // Save a copy.
            }
        }
        catch (Exception ex)
        {
            // Return original layerModels
            foreach (var lm in dwgModel.LayerModels)
                lm.AppendComment($"Failed to run Autopilot on Document Level {ex.Message}");
        }
    }
}

 

I have wrapped the boilerplate transaction related code in a delegate, if anyone is interested in that here it is:

public void UsingLayerTable(Action<Transaction, LayerTable> action, Database db)
{
    if (db == null) db = Active.Database;

    using (var tr = db.TransactionManager.StartTransaction())
    {
        // Open layer table
        var layerTable = (LayerTable)tr.GetObject(db.LayerTableId, OpenMode.ForRead);

        action(tr, layerTable);

        tr.Commit();
    }
}

 

0 Likes
Accepted solutions (2)
103 Views
4 Replies
Replies (4)
Message 2 of 5

BlackBox_
Advisor
Advisor

@heyimsp12 wrote:

when I have any of the Civil3D Drawings, the method is able to rename the layers in it just fine. However, because side loading the drawing into a database doesn't read the civil3d styles automatically. it breaks the hard references of the layers in AEC objects like alignment styles, corridor styles, etc. I have tried resetting the styles directly in using .net as well, but while sideloading the database, it doesn't read any styles in the drawing.


Civil 3D binding AECC Object elements to Layers disparate of AutoCAD's layer table wasn't the best decision on Autodesk's part. 

 

That said, if you could post your code for iterating Styles in side db, it might help us offer something useful.

 

Conversationally, have you tried iterating the C3D Styles using Reflection, so you don't have to hard-code each-and-every-single possible Style and their individual settings/components/enums? 


 

As example, in C3D 2026.1 Drawing Settings, Object Layers now include the drainage tech preview object like Channel, Pond, etc - which you can modify right there in the UI - but are all completely missing from the API's enum. 

 


"How we think determines what we do, and what we do determines what we get."

Sincpac C3D ~ Autodesk Exchange Apps

0 Likes
Message 3 of 5

heyimsp12
Enthusiast
Enthusiast

Thank you for the reply. 

Here's what I've got in terms of accessing the Styles. However, I haven't been able to test any of the code yet because when I read the database using Database.ReadDwgFile(), and then do CivilDocument.GetCivilDocument(db), I get no styles at all. I however am 100% sure my drawing has styles in it. 

private static void RestoreLayerInC3dStyleDefinitions(Database extDb, List<LayerModel> layerModels)
{
    try
    {
        var trDel = new TransactionDelegates(); trDel.UsingTransaction((tr) =>
        {
            var civDoc = CivilDocument.GetCivilDocument(extDb);
            if (civDoc == null) return;

            var layerTable = (LayerTable)tr.GetObject(extDb.LayerTableId, OpenMode.ForRead);
            if (layerTable == null) return;

            //Alignment Styles 
            foreach (ObjectId styleId in civDoc.Styles.AlignmentStyles)
            {
                var alignmentStyle = (AlignmentStyle)tr.GetObject(styleId, OpenMode.ForRead);
                if (alignmentStyle == null) continue;

                /// AlignmentStyle supports: Plan, Model, Section and Profile Views. 
                // Plan Display Styles
                var line = alignmentStyle.GetDisplayStylePlan(AlignmentDisplayStyleType.Line);
                if (line != null)
                    line.Layer = layerModels.Where(lm => lm.OriginalName == line.Layer).FirstOrDefault().MappedName;

                var curve = alignmentStyle.GetDisplayStylePlan(AlignmentDisplayStyleType.Curve);
                if (curve != null) curve.Layer = layerModels.Where(lm => lm.OriginalName == curve.Layer).FirstOrDefault().MappedName;

                var spiral = alignmentStyle.GetDisplayStylePlan(AlignmentDisplayStyleType.Spiral);
                if (spiral != null) spiral.Layer = layerModels.Where(lm => lm.OriginalName == spiral.Layer).FirstOrDefault().MappedName;

                var arrow = alignmentStyle.GetDisplayStylePlan(AlignmentDisplayStyleType.Curve);
                if (arrow != null) arrow.Layer = layerModels.Where(lm => lm.OriginalName == arrow.Layer).FirstOrDefault().MappedName;

                var lineExt = alignmentStyle.GetDisplayStylePlan(AlignmentDisplayStyleType.Curve);
                if (lineExt != null) lineExt.Layer = layerModels.Where(lm => lm.OriginalName == lineExt.Layer).FirstOrDefault().MappedName;

                var curveExt = alignmentStyle.GetDisplayStylePlan(AlignmentDisplayStyleType.Curve);
                if (curveExt != null) curveExt.Layer = layerModels.Where(lm => lm.OriginalName == curveExt.Layer).FirstOrDefault().MappedName;

                var tangentExt = alignmentStyle.GetDisplayStylePlan(AlignmentDisplayStyleType.Curve);
                if (tangentExt != null) tangentExt.Layer = layerModels.Where(lm => lm.OriginalName == tangentExt.Layer).FirstOrDefault().MappedName;

                var warningSym = alignmentStyle.GetDisplayStylePlan(AlignmentDisplayStyleType.Curve);
                if (warningSym != null) warningSym.Layer = layerModels.Where(lm => lm.OriginalName == warningSym.Layer).FirstOrDefault().MappedName;
            }
        }, extDb);
    }
    catch (Exception) { throw; }
}

// This is where I'm calling it in one of my previous method:
using (var extDb = new Database(true, false))
{
    extDb.ReadDwgFile(dwgModel.Path, FileOpenMode.OpenForReadAndWriteNoShare, true, "");
    extDb.CloseInput(true);

// Some code


                        if (HelperFunctions.IsCivil3DHost())
                            RestoreLayerInC3dStyleDefinitions(extDb, dwgModel.LayerModels);

                        /// Save drawing
                        extDb.SaveAs(dwgModel.Path, DwgVersion.Current); // Save a copy.
}



0 Likes
Message 4 of 5

BlackBox_
Advisor
Advisor
Accepted solution

Thanks for posting the code.

 

First thing that jumped out is that the AlignmentStyle is OpenMode.ForRead, in lieu of ForWrite.

 

Also, consider using () for the sideDb, replaced your TransactionDelegates with using () StartTransaction, then invoking SaveAs() on the sideDb. 

 

I was able to produce code that successfully iterated AlignmentStyles, made the changes, and saved them, using these few changes (I didn't have your *Model types, etc). 

 

HTH

 

        [CommandMethod("FOO", CommandFlags.Modal)]
        public static void Foo()
        {
            var doc = Application.DocumentManager.MdiActiveDocument;
            var db = doc.Database;
            var ed = doc.Editor;

            string dwg = "SomeFilePath\\SomeDrawing.dwg";

            try
            {
                var layerName = "Defpoints";      
				
				using (var sideDb = new Database(true, false))
				{
					sideDb.ReadDwgFile(dwg, FileOpenMode.OpenForReadAndWriteNoShare, true, "");
					sideDb.CloseInput(true);

					using (var tr = sideDb.TransactionManager.StartTransaction())
					{
						var civDoc = CivilDocument.GetCivilDocument(sideDb);
						if (civDoc == null) return;

						LayerTable layerTable = (LayerTable)tr.GetObject(sideDb.LayerTableId, OpenMode.ForRead);
						if (layerTable == null) return;
						
                        if (!layerTable.Has(layerName))
                            return;

                        //Alignment Styles 
                        foreach (acDb.ObjectId styleId in civDoc.Styles.AlignmentStyles)
                        {
                            AlignmentStyle alignmentStyle = (AlignmentStyle)tr.GetObject(styleId, OpenMode.ForWrite);
                            if (alignmentStyle == null) continue;

                            /// AlignmentStyle supports: Plan, Model, Section and Profile Views. 
                            // Plan Display Styles
                            DisplayStyle line = alignmentStyle.GetDisplayStylePlan(AlignmentDisplayStyleType.Line);
                            if (line != null)
                                //line.Layer = layerModels.Where(lm => lm.OriginalName == line.Layer).FirstOrDefault().MappedName;
                                line.Layer = layerName;

                            DisplayStyle curve = alignmentStyle.GetDisplayStylePlan(AlignmentDisplayStyleType.Curve);
                            if (curve != null) 
                                //curve.Layer = layerModels.Where(lm => lm.OriginalName == curve.Layer).FirstOrDefault().MappedName;
                                curve.Layer = layerName;

                            DisplayStyle spiral = alignmentStyle.GetDisplayStylePlan(AlignmentDisplayStyleType.Spiral);
                            if (spiral != null) 
                                //spiral.Layer = layerModels.Where(lm => lm.OriginalName == spiral.Layer).FirstOrDefault().MappedName;
                                spiral.Layer = layerName;

                            DisplayStyle arrow = alignmentStyle.GetDisplayStylePlan(AlignmentDisplayStyleType.Curve);
                            if (arrow != null) 
                                //arrow.Layer = layerModels.Where(lm => lm.OriginalName == arrow.Layer).FirstOrDefault().MappedName;
                                arrow.Layer = layerName;
                            
                            DisplayStyle lineExt = alignmentStyle.GetDisplayStylePlan(AlignmentDisplayStyleType.Curve);
                            if (lineExt != null) 
                                //lineExt.Layer = layerModels.Where(lm => lm.OriginalName == lineExt.Layer).FirstOrDefault().MappedName;
                                lineExt.Layer = layerName;

                            DisplayStyle curveExt = alignmentStyle.GetDisplayStylePlan(AlignmentDisplayStyleType.Curve);
                            if (curveExt != null) 
                                //curveExt.Layer = layerModels.Where(lm => lm.OriginalName == curveExt.Layer).FirstOrDefault().MappedName;
                                curveExt.Layer = layerName;

                            DisplayStyle tangentExt = alignmentStyle.GetDisplayStylePlan(AlignmentDisplayStyleType.Curve);
                            if (tangentExt != null) 
                                //tangentExt.Layer = layerModels.Where(lm => lm.OriginalName == tangentExt.Layer).FirstOrDefault().MappedName;
                                tangentExt.Layer = layerName;

                            DisplayStyle warningSym = alignmentStyle.GetDisplayStylePlan(AlignmentDisplayStyleType.Curve);
                            if (warningSym != null) 
                                //warningSym.Layer = layerModels.Where(lm => lm.OriginalName == warningSym.Layer).FirstOrDefault().MappedName;
                                warningSym.Layer = layerName;
                        }

						tr.Commit();
					}

					sideDb.SaveAs(dwg, DwgVersion.Current);
				}
			}
			catch (System.Exception ex)
            {
                ed.WriteMessage($"\nFatal: {ex.Message}");
            }
        }

 


"How we think determines what we do, and what we do determines what we get."

Sincpac C3D ~ Autodesk Exchange Apps

0 Likes
Message 5 of 5

heyimsp12
Enthusiast
Enthusiast
Accepted solution

Hi @BlackBox_  - Thank you so much. 

 

You're right - I was doing mostly the same things that you're suggesting here except - OpenMode.ForWrite. 

I really appreciate the response and have marked it as an accepted solution for anyone looking for the same issue in the future. In addition to that, I am directly looping through the enum for cleaner implementation. I'm sharing my code below, but anyone looking at this in the future, please ensure you're closing the transaction and saving the database like @BlackBox_  has suggested in the previous reply. In my case, I'm doing all that in parent method that calls this:

private static void RestoreAlignmentStylesInC3dStyles(Database extDb, List<LayerModel> layerModels)
{
    try
    {
        var trDel = new TransactionDelegates(); trDel.UsingTransaction((tr) =>
        {
            var civDoc = CivilDocument.GetCivilDocument(extDb);
            if (civDoc == null) return;

            var layerTable = (LayerTable)tr.GetObject(extDb.LayerTableId, OpenMode.ForRead);
            if (layerTable == null) return;

            //Alignment Styles 
            foreach (ObjectId styleId in civDoc.Styles.AlignmentStyles)
            {
                var alignmentStyle = (AlignmentStyle)tr.GetObject(styleId, OpenMode.ForWrite);
                if (alignmentStyle == null) continue;

                /// AlignmentStyle supports: Plan, Model, Section and LineMarkerDisplayStyleSection
                /// AlignmentDiplayStyleType supports: Line, Curve, Spiral, Arrow, LineExtension, CurveExtension, TangentExtension, WarningSymbol
                foreach (AlignmentDisplayStyleType styleType in Enum.GetValues(typeof(AlignmentDisplayStyleType)))
                {
                    // Plan
                    var planComponent = alignmentStyle.GetDisplayStylePlan(styleType);
                    if (planComponent != null)
                        planComponent.Layer = layerModels.MappedLayerNameForStyle(planComponent.Layer, layerTable);

                    // Model
                    var modelComponent = alignmentStyle.GetDisplayStyleModel(styleType);
                    if (modelComponent != null)
                        modelComponent.Layer = layerModels.MappedLayerNameForStyle(modelComponent.Layer, layerTable);

                    // Section
                    var sectionComponent = alignmentStyle.GetDisplayStyleSection();
                    if (sectionComponent != null)
                        sectionComponent.Layer = layerModels.MappedLayerNameForStyle(sectionComponent.Layer, layerTable);

                    // Profile
                    var lineMarkerDispSecComp = alignmentStyle.GetLineMarkerDisplayStyleSection();
                    if (lineMarkerDispSecComp != null)
                        lineMarkerDispSecComp.Layer = layerModels.MappedLayerNameForStyle(lineMarkerDispSecComp.Layer, layerTable);
                }
            }
        }, extDb);
    }
    catch (Exception) { throw; }
}