.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Opening a Civil 3D drawing for edit in C# .Net

14 REPLIES 14
SOLVED
Reply
Message 1 of 15
JohnDutz
3463 Views, 14 Replies

Opening a Civil 3D drawing for edit in C# .Net

Here's a code snippet from a project I'm working on (processing a large number of surfaces from point files in Civil 3D):

 // Create and open a new drawing, from the specified template
 Document doc = AcApplication.DocumentManager.Add(templateFileName);
 AcApplication.DocumentManager.MdiActiveDocument = doc;
 Database db = doc.Database;

 // need to wait for Civil 3D to catch up!
 MessageBox.Show(surfacename);

 // Create the surface
 using (Transaction trans = db.TransactionManager.StartTransaction())
 {
    // get the point file format object, required for import:
    PointFileFormatCollection ptFileFormats = PointFileFormatCollection.GetPointFileFormats(db);
    PointFileFormat ptFormat = ptFileFormats[ptFileFormat];
    ObjectId styleId = GetStyleId(surfaceStyleName);

    ObjectId surfaceId = TinSurface.Create(filename, styleId);
    TinSurface surface = trans.GetObject(surfaceId, OpenMode.ForWrite) as TinSurface;

What's odd, is that this works, pretty much the way I want it to, except for the MessageBox.Show(surfacename);  line.

If I remove this line, or replace it with Thread.Sleep(30000); or for (int i=0; i<1000000; i++) {}, the program crashes on the TinSurface.Create(filename, styleId); line with a "Fail to create surface" error.  I've tried using TinSurface.Create(db, surfacename); and it still crashes.  I've also tried creating all of the drawing files first, then coming back and using DocumentManager.Open().  I can access existing surfaces using this technique, but I can't create them without the MessageBox.Show() statement.  When I simply add the surfaces to the active drawing, the program works perfectly, but I want to put the surfaces into separate drawings for performance reasons.

Does anyone know what the MessageBox.Show() statement is doing that could be replicated without actually stopping the program to request input from the user?  What part of the process did I miss?  Do I need to reset the UI, or something along those lines, and how would I go about doing so?

14 REPLIES 14
Message 2 of 15
Jeff_M
in reply to: JohnDutz

John, not sure if you know about it or not, but there is a forum specifically for Civil3D customization: http://forums.autodesk.com/t5/autocad-civil-3d-customization/bd-p/190
It looks like you are opening each drawing in the editor? I would suggest just creating a new side database, create the TinSurface in it (this is the reason for the TinSurface.Create(db, name) method), add the Pointfile, then save the db. I don't have an example right now, but if needed I think I could get one put together later on.
Jeff_M, also a frequent Swamper
EESignature
Message 3 of 15
Jeff_M
in reply to: Jeff_M

There seems to be an issue with that method. I was sure that I had it working at one time, though. Will keep trying....
Jeff_M, also a frequent Swamper
EESignature
Message 4 of 15
JohnDutz
in reply to: Jeff_M

Thanks Jeff,

 

I really appreciate you looking into this.  I was under the (possibly mistaken) understanding that the Civil namespaces didn't load unless you open the drawing in the editor and I wasn't able to find an example (except for Kean Walsley's discussion on the topic).  I haven't worked with a side database before.  I certainly don't need the UI, so I think approach would work.

 

How would I create the new file from a template, and then open it as a side database?

 

  Document doc = AcApplication.DocumentManager.Add(templateFileName​);  // <-- Need to change this line
// AcApplication.DocumentManager.MdiActiveDocument = doc; // <-- No longer required

  // Create a database and try to load the file 
Database db = new Database(false, true); using (db) { try { db.ReadDwgFile( filename, System.IO.FileShare.Read, false, "" ); } catch (System.Exception) { ed.WriteMessage("\nUnable to read drawing file."); return; } // ... do some stuff }

 

Message 5 of 15
JohnDutz
in reply to: Jeff_M

I suppose I could just copy the template file on the server, rename it and open it.  Or open the template and do a CloseAndSave.

 

Is there a better way?

 

Thanks again, for your feedback.

Message 6 of 15
Jeff_M
in reply to: JohnDutz

John, sorry for the delayed response. Was researching some other things and lost track of time. The following code works quite well and fast:

 

            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Title = "Select PointFiles to import";
            ofd.CheckFileExists = true;
            ofd.Multiselect = true;
            if (ofd.ShowDialog() != System.Windows.Forms.DialogResult.OK)
                return;
            dynamic prefs = Autodesk.AutoCAD.ApplicationServices.Application.Preferences;
            dynamic files = prefs.Files;
            string qnew = files.QNewTemplateFile;

            foreach (string file in ofd.FileNames)
            {
                string path = Path.GetDirectoryName(file);
                string filename = Path.GetFileNameWithoutExtension(file);
                string newname = path + "\\" + filename + ".dwg";
                using (Database db = new Database(false, true))
                {
                    db.ReadDwgFile(qnew, FileOpenMode.OpenForReadAndWriteNoShare, false, "");
                    using (Transaction tr = db.TransactionManager.StartTransaction())
                    {
                        CivilDocument civdoc = CivilDocument.GetCivilDocument(db);
                        ObjectId styleId = civdoc.Styles.SurfaceStyles["TDG - Border Only"];
                        ObjectId surfId = TinSurface.Create(db, filename);
                        TinSurface surf = (TinSurface)surfId.GetObject(OpenMode.ForWrite);
                        PointFileFormatCollection ptFileFormats = PointFileFormatCollection.GetPointFileFormats(db);
                        PointFileFormat ptFormat = ptFileFormats["PNEZD (comma delimited)"];
                        surf.StyleId = styleId;
                        surf.PointFilesDefinition.AddPointFile(file, ptFormat);
                        tr.Commit();
                    }
                    db.SaveAs(newname, DwgVersion.Current);
                }
            }

 

Jeff_M, also a frequent Swamper
EESignature
Message 7 of 15
Jeff_M
in reply to: Jeff_M

One thing that took a bit to figure out was that the help for the TinSurface.Create(db, name) constructor says that the surface is created using the Default style name. Well, it doesn't. I went into my DWT, setup the Drawing defaults just as I wanted, and it still created it with what I think is the first Style in the SurfaceStyles collection. So i just added the bit to get the style I wanted to use and set the surface's StyleId property to that.
Jeff_M, also a frequent Swamper
EESignature
Message 8 of 15
JohnDutz
in reply to: Jeff_M

That worked amazingly well, Jeff.

 

Thanks so much for your help.

Message 9 of 15
DRossger
in reply to: JohnDutz

I have some problems with creating of new surfaces. I tryed with this code, and it works if I type command "create"'

 

  public class Commands
{

[CommandMethod("create")]

 public void CreateTinSurfaceTest()

{

Document m_Doc = Application.DocumentManager.MdiActiveDocument;

Database db = m_Doc.Database;
Editor ed = m_Doc.Editor;
CivilDocument civilDoc = CivilApplication.ActiveDocument;


using (Transaction m_Tr = db.TransactionManager.StartTransaction())
{
try
{
//1. Variant: defintion styleproperties- and SurfaceName
m_SurfaceStyleId = civilDoc.Styles.SurfaceStyles["Rutnät och gräns"];
m_SurfaceId = TinSurface.Create("TIN_Surface_From_Contours", m_SurfaceStyleId);

//2. Variant definition SurfaceName
//m_SurfaceId = Autodesk.Civil.DatabaseServices.TinSurface.Create(db, "m_NewSurfaceName");
m_Surface = m_SurfaceId.GetObject(OpenMode.ForWrite) as TinSurface;
ed.WriteMessage("Import succeeded: {0} \n {1}", m_SurfaceId.ToString(), db.Filename);
}
catch (System.Exception e)
{
ed.WriteMessage("Import failed: {0}", e.Message);
}
m_Tr.Commit();
}
}

 

But if I call metod (CreateTinSurfaceTest()) from annother class like so

 

  Commands cmd = new Commands();
cmd.CreateTinSurfaceTest();

 

it doesn´t work. Anybody know why?

Message 10 of 15
Jeff_M
in reply to: DRossger

How doesn't it work? Error? Nothing happens?
Jeff_M, also a frequent Swamper
EESignature
Message 11 of 15
fieldguy
in reply to: DRossger

Is your call to "CreateTinSurfaceTest()"?  "create" is an acad command - not the same as the name of the method.

Message 12 of 15
DRossger
in reply to: Jeff_M

Thanx!

Problem is solved, it hade to do with implemented winformDialog. I could click button_ok and than TinSurface.Create()-metod was running. But the problem was I didn´t get a SurfaceId. The problem was, the dialog was open and so the metod couldn´t work right.

Message 13 of 15
kbarnettza
in reply to: DRossger

How did you get reference to Autodesk.AutoCAD.ApplicationServices.Application.Preferences ?

When I include a reference to ACMGD.DLL ... although it creates a DLL, ACCORE crashes on NETLOAD  : (

Message 14 of 15
Jeff_M
in reply to: kbarnettza

Kevin, make sure you have references to AcCoreMgd, AcDbMgd, & AcMgd
Jeff_M, also a frequent Swamper
EESignature
Message 15 of 15
kbarnettza
in reply to: Jeff_M

There needs to be levels of Kudos ... Jeff deserves Uber Kudos

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report

”Boost