A blog for developers programming with Autodesk platforms, particularly AutoCAD and Forge. With a special focus on AR/VR and IoT.

April 09, 2007

Taking a snapshot of the AutoCAD model using .NET

This topic is a follow-up to the previous post dealing with offscreen rendering, and was suggested (and is based on code provided) by Fenton Webb, a member of DevTech Americas who has just moved across to San Rafael. Fenton was until recently part of DevTech EMEA, working from the UK.

The basic technique is similar to the one used in the previous post: we use the graphics system to create an "offscreen device", which we then set up and request to create a snapshot of our model. This can work on graphical objects stored in any AutoCAD database, but in this case we use it to capture an image of the contents of the active drawing's modelspace (after, once again, adding a sphere to it).

To spice up the results a little, I added the option to specify a particular visual style for the output. I've inserted the created images at the bottom (as before, you will need to add a particular material to the current drawing in order to get exactly the same results I as I have).

Here's the C# code:

using Autodesk.AutoCAD.ApplicationServices;

using Autodesk.AutoCAD.DatabaseServices;

using Autodesk.AutoCAD.EditorInput;

using Autodesk.AutoCAD.GraphicsInterface;

using Autodesk.AutoCAD.GraphicsSystem;

using Autodesk.AutoCAD.Runtime;

using Autodesk.AutoCAD.Interop;

using System.Drawing;

namespace OffscreenImageCreation

{

publicclassCommands

{

[CommandMethod("OSS")]

staticpublicvoid OffscreenSnapshot()

{

CreateSphere();

SnapshotToFile(

"c:\\sphere-Wireframe2D.png",

VisualStyleType.Wireframe2D

);

SnapshotToFile(

"c:\\sphere-Hidden.png",

VisualStyleType.Hidden

);

SnapshotToFile(

"c:\\sphere-Basic.png",

VisualStyleType.Basic

);

SnapshotToFile(

"c:\\sphere-ColorChange.png",

VisualStyleType.ColorChange

);

SnapshotToFile(

"c:\\sphere-Conceptual.png",

VisualStyleType.Conceptual

);

SnapshotToFile(

"c:\\sphere-Flat.png",

VisualStyleType.Flat

);

SnapshotToFile(

"c:\\sphere-Gouraud.png",

VisualStyleType.Gouraud

);

SnapshotToFile(

"c:\\sphere-Realistic.png",

VisualStyleType.Realistic

);

}

staticpublicvoid CreateSphere()

{

Document doc =

Application.DocumentManager.MdiActiveDocument;

Database db = doc.Database;

Editor ed = doc.Editor;

Transaction tr =

doc.TransactionManager.StartTransaction();

using (tr)

{

BlockTable bt =

(BlockTable)tr.GetObject(

db.BlockTableId,

OpenMode.ForRead

);

BlockTableRecord btr =

(BlockTableRecord)tr.GetObject(

bt[BlockTableRecord.ModelSpace],

OpenMode.ForWrite

);

Solid3d sol = newSolid3d();

sol.CreateSphere(10.0);

conststring matname =

"Sitework.Paving - Surfacing.Riverstone.Mortared";

DBDictionary matdict =

(DBDictionary)tr.GetObject(

db.MaterialDictionaryId,

OpenMode.ForRead

);

if (matdict.Contains(matname))

{

sol.Material = matname;

}

else

{

ed.WriteMessage(

"\nMaterial (" + matname + ") not found" +

" - sphere will be rendered without it.",

matname

);

}

btr.AppendEntity(sol);

tr.AddNewlyCreatedDBObject(sol, true);

tr.Commit();

}

AcadApplication acadApp =

(AcadApplication)Application.AcadApplication;

acadApp.ZoomExtents();

}

staticpublicvoid SnapshotToFile(

string filename,

VisualStyleType vst

)

{

Document doc =

Application.DocumentManager.MdiActiveDocument;

Editor ed = doc.Editor;

Database db = doc.Database;

Manager gsm = doc.GraphicsManager;

// Get some AutoCAD system variables

int vpn =

System.Convert.ToInt32(

Application.GetSystemVariable("CVPORT")

);

// Get AutoCAD's GS view for this document...

View gsv =

doc.GraphicsManager.GetGsView(vpn, true);

// ... but create a new one for the actual snapshot

using (View view = newView())

{

// Set the view to be just like the one

// in the AutoCAD editor

view.Viewport = gsv.Viewport;

view.SetView(

gsv.Position,

gsv.Target,

gsv.UpVector,

gsv.FieldWidth,

gsv.FieldHeight

);

// Set the visual style to the one passed in

view.VisualStyle = newVisualStyle(vst);

Device dev =

gsm.CreateAutoCADOffScreenDevice();

using (dev)

{

dev.OnSize(gsm.DisplaySize);

// Set the render type and the background color

dev.DeviceRenderType = RendererType.Default;

dev.BackgroundColor = Color.White;

// Add the view to the device and update it

dev.Add(view);

dev.Update();

using (Model model = gsm.CreateAutoCADModel())

{

Transaction tr =

db.TransactionManager.StartTransaction();

using (tr)

{

// Add the modelspace to the view

// It's a container but also a drawable

BlockTable bt =

(BlockTable)tr.GetObject(

db.BlockTableId,

OpenMode.ForRead

);

BlockTableRecord btr =

(BlockTableRecord)tr.GetObject(

bt[BlockTableRecord.ModelSpace],

OpenMode.ForRead

);

view.Add(btr, model);

tr.Commit();

}

// Take the snapshot

Rectangle rect = view.Viewport;

using (Bitmap bitmap = view.GetSnapshot(rect))

{

bitmap.Save(filename);

ed.WriteMessage(

"\nSnapshot image saved to: " +

filename

);

// Clean up

view.EraseAll();

dev.Erase(view);

}

}

}

}

}

}

}

And here are the images created by the OSS command, listed by their visual style type...