Creating Alignment throws "Alignment ID is invalid" error

Creating Alignment throws "Alignment ID is invalid" error

f.rampf
Enthusiast Enthusiast
2,535 Views
8 Replies
Message 1 of 9

Creating Alignment throws "Alignment ID is invalid" error

f.rampf
Enthusiast
Enthusiast

I am developing an IFC (Industry Foundation Classes) Import/Export Add-In for Civil 3D, which I will publish as open source later this month). The export function works completely fine already. However, I still don't quite understand how to create objects in Civil 3D using .NET. My add-in is written in C#.

I tried the following, which is a official Autodesk example:

 

// Uses an existing Alignment Style named "Basic" and Label Set Style named "All Labels" (for example, from
// the _AutoCAD Civil 3D (Imperial) NCS.dwt template.  This call will fail if the named styles
// don't exist.  
// Uses layer 0, and no site (ObjectId.Null)
ObjectId testAlignmentID = Alignment.Create(doc, "New Alignment", ObjectId.Null, "0", "Basic", "All Labels");

source: https://knowledge.autodesk.com/support/autocad-civil-3d/learn-explore/caas/CloudHelp/cloudhelp/2017/...

 

However, whenever I try to run my code, I get the following error message: "Invalid Alignment ID.". My code looks like the following:

 

var civilDatabase = Application.DocumentManager.MdiActiveDocument.Database;
var civilDocument = CivilApplication.ActiveDocument;
using (Transaction civilTransactionManager =
                        civilDatabase.TransactionManager.StartTransaction())
{
    //Create C3D Alignment:
   ObjectId civilAlignment = Alignment.Create(civilDocument, "MyDesription", "" , "0", "Basic", "All Labels");

I also tried to replace  the "" that gives the site for the Alignment with null or ObjectID.Null, both does not work and replacing it with ObjectID.Null does even prevent me from compiling.

 

Anyone know what's going on?

 

Regards,

Felix

 

0 Likes
Accepted solutions (1)
2,536 Views
8 Replies
Replies (8)
Message 2 of 9

Jeff_M
Consultant
Consultant
Does an alignment with that name already exist? Do the alignment style and label set style exist? I seem to recall having issues when passing strings, all of my current code gets the appropriate ObjectIds for the objects to pass (Site, layer, style, styleset) and all works fine, including ObjectId.Null for the siteless alignments. Oh, and I also check for duplicate alignment name and change the new name to be unique by adding "(1)" to the provided named, which is what C3D does.
Jeff_M, also a frequent Swamper
EESignature
0 Likes
Message 3 of 9

f.rampf
Enthusiast
Enthusiast

I have just created an Alignment and checked all the properties while debugging and also the options given upon creating a new alignment within Civil 3D. Every value I am using is present within Civil 3D and called the same looking into the alignment object while debugging.

 

So you basically create objects of the type ObjectID first for every parameter needed for the Alignment.Create() method? How do you set the correct ObjectIDs. I reckon they will have to be "correct" to otherwise I will get the same error again.

 

Quite annoying since writing the IFC Early Binding, the Exporter and the Importer was rather tricky, I thought basically translating my IFC objects and creating the according Civil 3D objects would be fairly easy but seems it is not...

 

EDIT: no alignments exist in the drawing, but I will also implement a ckech to see wether an Alignment with the same name already exists.

 

Regards,

Felix

 

0 Likes
Message 4 of 9

Jeff_M
Consultant
Consultant
Can you provide a code snippet to test along with the drawing you are using? That error you get isn't one I recall seeing before. There are specific error messages for invalid arguments and duplicate name. So a small VS Project would be best to test with.
Jeff_M, also a frequent Swamper
EESignature
0 Likes
Message 5 of 9

f.rampf
Enthusiast
Enthusiast

Sure, here is my Project, that produces the error. Sorry if its a bit all over the place but I created that really quickly from my far bigger code, to recreate the error. Let me know if you need anything else to help.

 

Thanks in advance,

Felix

0 Likes
Message 6 of 9

Jeff_M
Consultant
Consultant

Felix, move the Alignment creation code out of the Command handler class. I created a small CommandMethod, using just your small bit of code to create the alignment and it works without error. Here's what one of our ribbon buttons looks like and the AdskCommandHandler that it calls, hopefully it will help you:

 

            rb = new RibbonButton();
            rb.Text = "Create\nAlign/Prof";
            rb.CommandParameter = "_.CreateAlignProf ";
            rb.ShowText = true;
            rb.ShowImage = true;
            rb.CommandHandler = new AdskCommandHandler();
            rb.Orientation = System.Windows.Controls.Orientation.Vertical;
            rb.Size = RibbonItemSize.Large;
            rb.Image = SincpacC3D.cap_small.ToBitmapImageFromPng();
            rb.LargeImage = SincpacC3D.cap.ToBitmapImageFromPng();
            rsb.Items.Add(rb);

    /// <summary>
    /// This class is designed to run a command string attached to a UI element such as a RibbonButton.
    /// The sending object should be passed in as the parameter, and it should have a Property
    /// called "CommandParameter", which should return the string to execute.
    /// </summary>
    public class AdskCommandHandler : ICommand
    {
        #region ICommand Members

        public bool CanExecute(object parameter)
        { return true; }

        public event System.EventHandler CanExecuteChanged;

        public void Execute(object parameter)
        {
            string esc = "";

            string cmds = (string)Application.GetSystemVariable("CMDNAMES");
            if (cmds.Length > 0)
            {
                int cmdNum = cmds.Split(new char[] { '\'' }).Length;

                for (int i = 0; i < cmdNum; i++)
                    esc += '\x03';
            }
            string cmdString = parameter.GetType().GetProperty("CommandParameter").GetValue(parameter, null) as string;
            
            if (!String.IsNullOrEmpty(cmdString))
                Application.DocumentManager.MdiActiveDocument.SendStringToExecute(esc + cmdString, true, false, true);
        }

        #endregion
    }
Jeff_M, also a frequent Swamper
EESignature
0 Likes
Message 7 of 9

f.rampf
Enthusiast
Enthusiast

Thank you very much for all your answers and help and sorry for my persistent questioning but I only started coding in May so everything is still pretty new to me.

 

Anyway, I moved the piece of code that creates the Alignment out of the ICommand class now and created the following instead:

 

[CommandMethod("ifc_in", CommandFlags.Session)]
        public static void ifc_in()
        {            
                var dlg = new OpenFileDialog();
                var result = dlg.ShowDialog();
                var ifcFile = dlg.FileName;

                //Start Import:
                var civilDatabase = Application.DocumentManager.MdiActiveDocument.Database;
                var civilDocument = CivilApplication.ActiveDocument;

                        //Create C3D Alignment:
                        ObjectId civilAlignment = Alignment.Create(civilDocument, "My Name (1)", "", "C-ROAD", "Proposed", "All Labels");
                    
          }           

I also added the following line to my import ribbon button and used your bit of code provided in the prior post:

 

CommandParameter = "ifc_in"

That is what you said to do, right?

However, I still get the same error. I have no clue why that happens.

 

Am I still doing something wrong?

 

Regards,

Felix

0 Likes
Message 8 of 9

Jeff_M
Consultant
Consultant
Accepted solution

Here is a complete cs file, using mostly your code, modified so it works without error. Note, you need to change the CopyLocal property of the Autodesk References to False. I also removed the Session flag from the IFC command.

 

using System;
using System.Windows.Controls;
using System.Windows.Input;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.Civil.ApplicationServices;
using Autodesk.Civil.DatabaseServices;
using Autodesk.Private.Windows;
using Autodesk.Windows;
using Application = Autodesk.AutoCAD.ApplicationServices.Application; 
using Microsoft.Win32;

namespace IfcC3DAddIn.main
{
    public class C3DIfcAlignmentAddIn
    {
        //added this command
        [CommandMethod("IFCImportTest")]
        public void ifcimporttest()
        {
            //Read my IFC File...
            var dlg = new OpenFileDialog();
            var result = dlg.ShowDialog();
            var ifcFile = dlg.FileName;

            if (result == true)
            {
                //Start Import:
                var civilDatabase = Application.DocumentManager.MdiActiveDocument.Database;
                var civilDocument = CivilApplication.ActiveDocument;

                //Create C3D Alignment:
                var civilAlignment = Alignment.Create(civilDocument, "My Name (1)", "", "C-ROAD", "Proposed", "All Labels");
            }

        }

        [CommandMethod("ifc")]
        public void Main()
        {
            
            var ribbon = ComponentManager.Ribbon; //Get C3D UI-Information

            var btab = ribbon.FindTab("CIVIL.ID_Civil3DAddins"); //Find the correct Ribbon

            //------------------  Check if the Panel already exists  ------------------------         
            if (btab != null)
            {
                if (btab.Panels != null)
                {
                    foreach (var panel in btab.Panels)
                    {
                        if (panel.UID == "UID_IfcPanel") //if the Panel already exists...
                        {
                            var removePnl = panel;


                            btab.Panels.Remove(removePnl); //...delete the Panel
                            break;
                        }
                    }
                }
            }
            //-------------------------------------------------------------------------------

            //------------------------  Create the new Button  ------------------------------
            var civilPanel = new RibbonPanel
            {
                UID = "UID_IfcPanel",
                Id = "ID_IfcPanel"
            };

            var source = new RibbonPanelSource
            {
                Id = "ID_IfcPanelSource",
                Name = "IfcPanelSource",
                Title = "IFC Alignment v1.1"
            }; //Create Panel Source
            civilPanel.Source = source; //... and bind it to the Panel

            var rbb1 = new RibbonButton
            {
                Name = "Export Ifc...",
                Text = "Ifc Export",
                GroupLocation = RibbonItemGroupLocation.Single,
                ResizeStyle = RibbonItemResizeStyles.HideText,
                Orientation = Orientation.Horizontal,
                ShowText = false,
                //CommandHandler = new ExportCmdHandler(),
                Id = "ID_TestButton",
                ShowImage = true,

                Size = RibbonItemSize.Large
            }; //Create Ribbon Button 1

            var rbn1Tt = new RibbonToolTip
            {
                Command = "IFC",
                Title = "Ifc-Export",
                Content = "This Add-in let's you export your current .dwg-file to an IFC 4 (.ifc) File.",
                ExpandedContent = "In the dialog box, navigate to the file directory you want to save your file."
            }; //Create Tooltip
            rbb1.ToolTip = rbn1Tt;

            var rbb2 = new RibbonButton
            {
                Name = "Import Ifc...",
                Text = "Ifc Import",
                GroupLocation = RibbonItemGroupLocation.Single,
                ResizeStyle = RibbonItemResizeStyles.HideText,
                Orientation = Orientation.Horizontal,
                ShowText = false,
                Id = "ID_TestButton",
                ShowImage = true,
                CommandHandler = new ImportCmdHandler(),
                Size = RibbonItemSize.Large,
                CommandParameter="_.IFCImportTest " //<<<<<<<<<<added this line
            }; //Create Ribbon Button 2
            //rbb2.CommandHandler = new MyCmdHandler();
            //Get Button Image

            var rbn2Tt = new RibbonToolTip
            {
                Command = "IFC",
                Title = "Ifc-Import",
                Content = "This Add-in let's you import a IFC 4 (.ifc) File to your current drawing.",
                ExpandedContent = "In the dialog box, navigate to the file directory your IFC-File ist stored."
            }; //Create Tooltip
            rbb2.ToolTip = rbn2Tt;

            var rbSplitButton = new RibbonSplitButton
            {
                Text = "Ifc Add-in",
                ShowText = true,
                Size = RibbonItemSize.Large,
                //LargeImage = GetBitmap("ifclogo.png"),
                //ShowImage = true,
                Name = "Ifc Add-in"
            }; //Create new Split-Button


            rbSplitButton.Items.Add(rbb1); //Add Button 1 to the Split-Button
            rbSplitButton.Items.Add(rbb2); //Add Button 2 to the Split-Button

            if (btab != null)
            {
                if (btab.Panels != null) btab.Panels.Add(civilPanel); //Add Panel to the Add-ins Tab
                btab.IsActive = true; //...and set as active
            }

            source.Items.Add(rbSplitButton); //Add Split-Button to the Panel
        }
        public class ImportCmdHandler : ICommand
        {
            public bool CanExecute(object parameter)
            {
                return true;
            }

            public event EventHandler CanExecuteChanged;

            public void Execute(object parameter)
            {
                if (parameter is RibbonButton) //if Button is clicked...
                {
                    //removed the original code, added the following:
                    string esc = "";

                    string cmds = (string)Application.GetSystemVariable("CMDNAMES");
                    if (cmds.Length > 0)
                    {
                        int cmdNum = cmds.Split(new char[] { '\'' }).Length;

                        for (int i = 0; i < cmdNum; i++)
                            esc += '\x03';
                    }
                    string cmdString = parameter.GetType().GetProperty("CommandParameter").GetValue(parameter, null) as string;

                    if (!String.IsNullOrEmpty(cmdString))
                        Application.DocumentManager.MdiActiveDocument.SendStringToExecute(esc + cmdString, true, false, true);
                    //end of added code
                }
            }
        }
    }
}
Jeff_M, also a frequent Swamper
EESignature
Message 9 of 9

f.rampf
Enthusiast
Enthusiast

Hello Jeff,

I used the code you provided and it works now. It really does look the same to what I had before (implementing your suggested changes), so I still don't really have a clue what was wrong. Thank you very much! I really appreciate you taking your time and helping me out. I will now try to import the rest of my entities in order to (hopefully) create a fully working IFC import.

 

Beste regards,

Felix

0 Likes