• Industries
  • Products
  • Buy
  • Services & Support
  • Communities
  • Discussion Groups

    .NET

    Reply
    Contributor
    Posts: 25
    Registered: ‎06-10-2008
    Accepted Solution

    Is there a way to create a 3D DWF from a drawing using VB.Net

    271 Views, 11 Replies
    07-13-2012 07:02 AM

    Is there a way to create a 3D DWF from a drawing using VB.Net?  I have a program that processes hundreds of drawings and creates a PDF and DWF of each drawing.  I'd like to also create a 3D DWF file, but haven't find anything on it anywhere.  I'm not sure if this would be a Save As, Export or something else.

     

    Thanks,

    Ken

    Please use plain text.
    Member
    Posts: 3
    Registered: ‎02-23-2008

    Re: Is there a way to create a 3D DWF from a drawing using VB.Net

    07-13-2012 08:07 AM in reply to: ken.washburn

    Hi Ken,

     

    If it appropriate and you are happy using the command line then use "3DDWF"

     

    Adam

    Please use plain text.
    Contributor
    Posts: 25
    Registered: ‎06-10-2008

    Re: Is there a way to create a 3D DWF from a drawing using VB.Net

    07-13-2012 08:22 AM in reply to: adam

    Adam,

    I thought about that, but the SendStringToExecute doesn't run until everything else has finished in vb.net (which doesn't work when batch processing).  And since moving to the 2013 API, I've found that emulating the vba "ThisDrawing.SendCommand" is spotty at best.  Though, I may have to go this route if there is not a direct way to access it.

     

     

    Thanks,
    Ken

    Please use plain text.
    *Expert Elite*
    Posts: 1,639
    Registered: ‎04-29-2006

    Re : Is there a way to create a 3D DWF from a drawing using VB.Net

    07-14-2012 04:33 PM in reply to: ken.washburn

    Hi,

     

    You can P/Invoke acedCmd which is synchronous.

     

    Here's another way, in pure .NET. Maybe it isn't the best one but it works fine for me.

    It creates a DSD file and publish it.

    In this example, all layouts are published to DWF and the Model to 3d DWF

     

    using System.IO;
    using System.Text;
    using Autodesk.AutoCAD.DatabaseServices;
    using Autodesk.AutoCAD.EditorInput;
    using Autodesk.AutoCAD.Geometry;
    using Autodesk.AutoCAD.PlottingServices;
    using Autodesk.AutoCAD.Publishing;
    using Autodesk.AutoCAD.Runtime;
    using AcAp = Autodesk.AutoCAD.ApplicationServices.Application;
    
    namespace Publish3dDwf
    {
        public class PublishDwf
        {
            // Private fields
            private string dwgFile, dwfFile, dsdFile, tmpFile, title, outputDir;
            private int numOfSections;
            private Database db = HostApplicationServices.WorkingDatabase;
            private Editor ed = AcAp.DocumentManager.MdiActiveDocument.Editor;
            const string FN_PUBLOG = "publish.log";
    
            // Constructor
            public PublishDwf()
            {
                dwgFile = db.Filename;
                outputDir = Path.GetDirectoryName(dwgFile);
                if (!Directory.Exists(outputDir))
                    Directory.CreateDirectory(outputDir);
                title = Path.GetFileNameWithoutExtension(dwgFile);
                dwfFile = Path.ChangeExtension(dwgFile, "dwf");
                dsdFile = Path.ChangeExtension(dwgFile, "dsd");
                tmpFile = Path.Combine(outputDir, "temp.dsd");
                numOfSections = 0;
            }
    
            // Publishes all layouts, displays a progress bar
            private void Publish()
            {
                try
                {
                    Publisher publisher = AcAp.Publisher;
                    PlotProgressDialog plotDlg = new PlotProgressDialog(false, numOfSections, true);
                    publisher.PublishDsd(dsdFile, plotDlg);
                    plotDlg.Destroy();
                }
                catch (System.Exception ex)
                {
                    ed.WriteMessage("\nErreur: {0}\n{1}", ex.Message, ex.StackTrace);
                }
            }
    
            // Creates a DSD file (template)
            private void CreateDSD()
            {
                using (DsdData dsd = new DsdData())
                using (DsdEntryCollection dsdEntCol = CreateDsdEntryCollection())
                {
                    numOfSections = dsdEntCol.Count;
    
                    dsd.SetDsdEntryCollection(dsdEntCol);
    
                    dsd.SetUnrecognizedData("PwdProtectPublishedDWF", "FALSE");
                    dsd.SetUnrecognizedData("PromptForPwd", "FALSE");
                    dsd.SheetType = SheetType.MultiDwf;
                    dsd.NoOfCopies = 1;
                    dsd.DestinationName = dwfFile;
                    dsd.IsHomogeneous = false;
                    dsd.LogFilePath = Path.Combine(outputDir, FN_PUBLOG);
    
                    PostProcessDSD(dsd);
                }
            }
    
            // Creates an entry collection (one per layout) for the DSD file
            private DsdEntryCollection CreateDsdEntryCollection()
            {
                DsdEntryCollection dsdEntCol = new DsdEntryCollection();
    
                using (Transaction tr = db.TransactionManager.StartTransaction())
                {
                    DBDictionary layoutDict = (DBDictionary)tr.GetObject(db.LayoutDictionaryId, OpenMode.ForRead);
                    foreach (DBDictionaryEntry layoutEntry in layoutDict)
                    {
                        Layout layout = (Layout)tr.GetObject(layoutEntry.Value, OpenMode.ForRead);
                        DsdEntry dsdEntry = new DsdEntry();
                        dsdEntry.DwgName = dwgFile;
                        dsdEntry.Layout = layout.LayoutName.ToString();
                        dsdEntry.Title = title + "-" + layout.LayoutName;
                        dsdEntry.Nps = layout.TabOrder.ToString();
                        dsdEntCol.Add(dsdEntry);
                    }
                }
                return dsdEntCol;
            }
    
            // Writes the definitive DSD file from the template and additional infos
            private void PostProcessDSD(DsdData dsd)
            {
                string str, newStr;
    
                try
                {
                    dsd.WriteDsd(tmpFile);
                    bool isModel = false;
    
                    using (StreamReader reader = new StreamReader(tmpFile, Encoding.Default))
                    using (StreamWriter writer = new StreamWriter(dsdFile, false, Encoding.Default))
                    {
                        while (!reader.EndOfStream)
                        {
                            str = reader.ReadLine();
                            if (str == "Layout=Model")
                            {
                                isModel = true;
                            }
                            if (str.Contains("Has3DDWF"))
                            {
                                newStr = isModel ? "Has3DDWF=1" : "Has3DDWF=0"; // <- 3dDwf if Model layout
                                isModel = false;
                            }
                            else if (str.Contains("OriginalSheetPath"))
                            {
                                newStr = "OriginalSheetPath=" + dwgFile;
                            }
                            else if (str.Contains("Type"))
                            {
                                newStr = "Type=0"; // <- 6 for DwgToPdf
                            }
                            else if (str.Contains("OUT"))
                            {
                                newStr = "OUT=" + outputDir;
                            }
                            else if (str.Contains("IncludeLayer"))
                            {
                                newStr = "IncludeLayer=TRUE";
                            }
                            else if (str.Contains("PromptForDwfName"))
                            {
                                newStr = "PromptForDwfName=FALSE";
                            }
                            else if (str.Contains("LogFilePath"))
                            {
                                newStr = "LogFilePath=" + Path.Combine(outputDir, FN_PUBLOG);
                            }
                            else
                            {
                                newStr = str;
                            }
                            writer.WriteLine(newStr);
                        }
                    }
                }
                catch (System.Exception e)
                {
                    ed.WriteMessage("\nErreur: {0}\n{1}", e.Message, e.StackTrace);
                }
            }
    
            // Deletes the DSD files
            private void Cleanup()
            {
                try
                {
                    if (File.Exists(dsdFile))
                    {
                        File.Delete(dsdFile);
                    }
    
                    if (File.Exists(tmpFile))
                    {
                        File.Delete(tmpFile);
                    }
                }
                catch (System.Exception e)
                {
                    ed.WriteMessage("\nErreur: {0}\n{1}", e.Message, e.StackTrace);
                }
            }
    
            // Command
            [CommandMethod("PublishToDwf")]
            public void PublishToDwf()
            {
                short bgp = (short)AcAp.GetSystemVariable("BACKGROUNDPLOT");
                AcAp.SetSystemVariable("BACKGROUNDPLOT", 0);
                CreateDSD();
                Publish();
                Cleanup();
                AcAp.SetSystemVariable("BACKGROUNDPLOT", bgp);
            }
        }
    }

     

    Gilles Chanteau
    Please use plain text.
    *Expert Elite*
    Posts: 1,639
    Registered: ‎04-29-2006

    Re : Is there a way to create a 3D DWF from a drawing using VB.Net

    07-15-2012 06:57 AM in reply to: _gile

    The upper code is a quick (and dirty) adaptation of the one I used to plot layouts to a PDF file.

     

    Publishing a 3d DWF may be a little more simple (removing unsefull lines).

     

    Here's a little class you can instanciate to call the Publish() method:

     

    Dim plot3d As New PlotTo3dDwf("C:\Temp")
    plot3d.Publish()

     C#

    using System.IO;
    using System.Text;
    using Autodesk.AutoCAD.ApplicationServices;
    using Autodesk.AutoCAD.PlottingServices;
    
    namespace Plottings
    {
        public class PlotTo3dDwf
        {
            private string dwgFile, dwfFile, dsdFile, title, outputDir;
    
            public PlotTo3dDwf()
            {
                outputDir = (string)Application.GetSystemVariable("DWGPREFIX");
                string name = (string)Application.GetSystemVariable("DWGNAME");
                dwgFile = Path.Combine(outputDir, name);
                title = Path.GetFileNameWithoutExtension(name);
                dwfFile = Path.ChangeExtension(dwgFile, "dwf");
                dsdFile = Path.ChangeExtension(dwfFile, ".dsd");
            }
    
            public PlotTo3dDwf(string outputDir) : this ()
            {
                this.outputDir = outputDir;
            }
    
            public void Publish()
            {
                short bgPlot = (short)Application.GetSystemVariable("BACKGROUNDPLOT");
                Application.SetSystemVariable("BACKGROUNDPLOT", 0);
    
                if (!Directory.Exists(outputDir))
                    Directory.CreateDirectory(outputDir);
    
                using (DsdData dsd = new DsdData())
                using (DsdEntryCollection dsdEntries = new DsdEntryCollection())
                {
                    // add the Model layout to the entry collection
                    DsdEntry dsdEntry = new DsdEntry();
                    dsdEntry.DwgName = dwgFile;
                    dsdEntry.Layout = "Model";
                    dsdEntry.Title = title;
                    dsdEntry.Nps = "0";
                    dsdEntries.Add(dsdEntry);
                    dsd.SetDsdEntryCollection(dsdEntries);
    
                    // set DsdData
                    dsd.Dwf3dOptions.PublishWithMaterials = true;
                    dsd.Dwf3dOptions.GroupByXrefHierarchy = true;
                    dsd.SetUnrecognizedData("PwdProtectPublishedDWF", "FALSE");
                    dsd.SetUnrecognizedData("PromptForPwd", "FALSE");
                    dsd.SheetType = SheetType.SingleDwf;
                    dsd.NoOfCopies = 1;
                    dsd.ProjectPath = outputDir;
                    dsd.IsHomogeneous = true;
    
                    if (File.Exists(dsdFile)) 
                        File.Delete(dsdFile);
    
                    // write the DsdData file
                    dsd.WriteDsd(dsdFile);
    
                    // get the Dsd File contents
                    string str;
                    using (StreamReader sr = new StreamReader(dsdFile, Encoding.Default))
                    {
                        str = sr.ReadToEnd();
                    }
                    // edit the contents
                    str = str.Replace("Has3DDWF=0", "Has3DDWF=1");
                    str = str.Replace("PromptForDwfName=TRUE", "PromptForDwfName=FALSE");
                    // rewrite the Dsd file
                    using (StreamWriter sw = new StreamWriter(dsdFile, false, Encoding.Default))
                    {
                        sw.Write(str);
                    }
    
                    // import the Dsd file contents in the DsdData
                    dsd.ReadDsd(dsdFile);
    
                    File.Delete(dsdFile);
    
                    PlotConfig pc = PlotConfigManager.SetCurrentConfig("DWF6 ePlot.pc3");
                    Application.Publisher.PublishExecute(dsd, pc);
                    Application.SetSystemVariable("BACKGROUNDPLOT", bgPlot);
                }
            }
        }
    }

     VB

    Imports System.IO
    Imports System.Text
    Imports Autodesk.AutoCAD.ApplicationServices
    Imports Autodesk.AutoCAD.PlottingServices
    
    Namespace Plottings
        Public Class PlotTo3dDwf
            Private dwgFile, dwfFile, dsdFile, title, outputDir As String
    
            Public Sub New()
                outputDir = DirectCast(Application.GetSystemVariable("DWGPREFIX"), String)
                Dim name As String = DirectCast(Application.GetSystemVariable("DWGNAME"), String)
                dwgFile = Path.Combine(outputDir, name)
                title = Path.GetFileNameWithoutExtension(name)
                dwfFile = Path.ChangeExtension(dwgFile, "dwf")
                dsdFile = Path.ChangeExtension(dwfFile, ".dsd")
            End Sub
    
            Public Sub New(outputDir As String)
                Me.New()
                Me.outputDir = outputDir
            End Sub
    
            Public Sub Publish()
                Dim bgPlot As Short = CShort(Application.GetSystemVariable("BACKGROUNDPLOT"))
                Application.SetSystemVariable("BACKGROUNDPLOT", 0)
    
                If Not Directory.Exists(outputDir) Then
                    Directory.CreateDirectory(outputDir)
                End If
    
                Using dsd As New DsdData()
                    Using dsdEntries As New DsdEntryCollection()
                        ' add the Model layout to the entry collection
                        Dim dsdEntry As New DsdEntry()
                        dsdEntry.DwgName = dwgFile
                        dsdEntry.Layout = "Model"
                        dsdEntry.Title = title
                        dsdEntry.Nps = "0"
                        dsdEntries.Add(dsdEntry)
                        dsd.SetDsdEntryCollection(dsdEntries)
    
                        ' set DsdData data
                        dsd.Dwf3dOptions.PublishWithMaterials = True
                        dsd.Dwf3dOptions.GroupByXrefHierarchy = True
                        dsd.SetUnrecognizedData("PwdProtectPublishedDWF", "FALSE")
                        dsd.SetUnrecognizedData("PromptForPwd", "FALSE")
                        dsd.SheetType = SheetType.SingleDwf
                        dsd.NoOfCopies = 1
                        dsd.ProjectPath = outputDir
                        dsd.IsHomogeneous = True
    
                        If File.Exists(dsdFile) Then
                            File.Delete(dsdFile)
                        End If
    
                        ' write the DsdData file
                        dsd.WriteDsd(dsdFile)
    
                        ' get the Dsd File contents
                        Dim str As String
                        Using sr As New StreamReader(dsdFile, Encoding.[Default])
                            str = sr.ReadToEnd()
                        End Using
                        ' edit the contents
                        str = str.Replace("Has3DDWF=0", "Has3DDWF=1")
                        str = str.Replace("PromptForDwfName=TRUE", "PromptForDwfName=FALSE")
                        ' rewrite the Dsd file
                        Using sw As New StreamWriter(dsdFile, False, Encoding.[Default])
                            sw.Write(str)
                        End Using
    
                        ' import the Dsd file new contents in the DsdData
                        dsd.ReadDsd(dsdFile)
    
                        File.Delete(dsdFile)
    
                        Dim pc As PlotConfig = PlotConfigManager.SetCurrentConfig("DWF6 ePlot.pc3")
                        Application.Publisher.PublishExecute(dsd, pc)
                        Application.SetSystemVariable("BACKGROUNDPLOT", bgPlot)
                    End Using
                End Using
            End Sub
        End Class
    End Namespace

     

    Gilles Chanteau
    Please use plain text.
    Contributor
    Posts: 25
    Registered: ‎06-10-2008

    Re : Is there a way to create a 3D DWF from a drawing using VB.Net

    07-16-2012 06:54 AM in reply to: _gile

    _gile, thanks for the code!  I will try this when I get time later this week.

     

    Ken

    Please use plain text.
    Contributor
    Posts: 25
    Registered: ‎06-10-2008

    Re : Is there a way to create a 3D DWF from a drawing using VB.Net

    07-16-2012 09:56 AM in reply to: ken.washburn

    _gile, I got a chance to try your second set of code this morning, and it appears to work, as far as creating a dwf file.  However, the dwf file it creates I can't open (see attached) - it hangs up after starting to open.  I'm using Map 3D 2013.  Note that I can create 3DDWF from the command line (so I know that the drivers are there and working - unless this uses something different).

     

    Also, I'm not familiar with working with DSD files and have the following questions:

    1. I want the 3D DWF file to have a different name than the drawing (as I will already have a 2D DWF file in the folder) - somthing like Drawingname-3D.dwf.  So where would I change that?  I tried changing the "name" variable and the "dwfFile" variable, but neither worked (i.e. it didn't create the file).

     

    2. Since the folder that I'm creating the new 3D DWF file in may already have an existing (older) 3D DWF, I want to overwrite the older file.  While I can write something to check for the file and delete it, I was wondering if there was something in your Publish() code section that could force an overwrite and supress any dialog boxes (that ask you if you want to overwrite the file).

     

    Thanks again for your help on this.

    Ken

     

    Please use plain text.
    *Expert Elite*
    Posts: 1,639
    Registered: ‎04-29-2006

    Re : Is there a way to create a 3D DWF from a drawing using VB.Net

    07-16-2012 12:29 PM in reply to: ken.washburn

    I can open your 3d DWF file, but it looks like empty, I can't say why.

     

    1. Try this in the constructor :

                dwfFile = Path.Combine(outputDir, title & "-3d.dwf")

     

    2. Add this at the begining of the Publish() code:

                    If File.Exists(dwfFile) Then
                        File.Delete(dwfFile)
                    End If
    
    Gilles Chanteau
    Please use plain text.
    Contributor
    Posts: 25
    Registered: ‎06-10-2008

    Re: Is there a way to create a 3D DWF from a drawing using VB.Net

    07-16-2012 02:36 PM in reply to: ken.washburn

    _gile, thanks for the suggestions.  I just tried Publish within Autocad and I get the same results (i.e. the dwf is blank).  However, 3DDWF does work.  I think I had the problem with both Publish and 3DDWF not working when I first installed Map 3D 2013 and got 3DDWF working after re-installing.  I will try a reinstall to see if I can get that piece working.

     

    Otherwise, I think your code works fine.

     

     

    Thanks again for your help!

     

    Ken

    Please use plain text.
    Contributor
    Posts: 25
    Registered: ‎06-10-2008

    Re: Is there a way to create a 3D DWF from a drawing using VB.Net

    07-17-2012 07:56 AM in reply to: ken.washburn

    _gile, one more question.  I have everything working (the reinstall worked on the Publish command), except the naming (i.e. to drawingname-3D.dwf).  I don't see where in the Publish sub where it actually uses the dwfFile variable.  I see that it uses the dwgFile variable, but not the dwfFile variable. 

     

    Thanks,

    Ken

    Please use plain text.