This question came up recently on the AutoCAD .NET Discussion Group: how to create a Solid3d object which provides the user with the full set of grips to manipulate it (which I've abbreviated to "editable" in the title of this post :-). This comes down to a enhancements that were made in AutoCAD 2007 to allow better manipulation of solids via the user-interface via extended grips and a push-pull mechanism. These capabilities need to be enabled solids as you create them - and unfortunately cannot be retro-fitted to existing solid objects - by telling the solid that you would like it to record its history. And it's really that simple, you simply have to set the RecordHistory flag to true.
The below C# code demonstrates how this works, by exposing a command that prompts the user whether to set this flag to true, or not:
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Geometry;
namespace SolidCreation
{
public class Commands
{
[CommandMethod("CWH")]
public void CylinderWithHistory()
{
Document doc =
Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
// Ask the user whether to create history
// and where to place the cylinder
bool createHistory = false;
PromptKeywordOptions pko =
new PromptKeywordOptions(
"\nRecord history for this cylinder?"
);
pko.AllowNone = true;
pko.Keywords.Add("Yes");
pko.Keywords.Add("No");
pko.Keywords.Default = "Yes";
PromptResult pkr =
ed.GetKeywords(pko);
if (pkr.Status != PromptStatus.OK)
return;
if (pkr.StringResult == "Yes")
createHistory = true;
PromptPointResult ppr =
ed.GetPoint("\nSelect point: ");
if (ppr.Status != PromptStatus.OK)
return;
Point3d pt = ppr.Value;
Transaction tr =
db.TransactionManager.StartTransaction();
using (tr)
{
// Create the solid and set the history flag
Solid3d sol = new Solid3d();
sol.RecordHistory = createHistory;
// Hardcode the dimensions of the cylinder
// for the purpose of this example
sol.CreateFrustum(10, 3, 3, 3);
// Add the Solid3d to the modelspace
BlockTable bt =
(BlockTable)tr.GetObject(
db.BlockTableId,
OpenMode.ForRead
);
BlockTableRecord ms =
(BlockTableRecord)tr.GetObject(
bt[BlockTableRecord.ModelSpace],
OpenMode.ForWrite
);
ms.AppendEntity(sol);
tr.AddNewlyCreatedDBObject(sol, true);
// And transform it to the selected point
sol.TransformBy(
Matrix3d.Displacement(pt - Point3d.Origin)
);
tr.Commit();
}
}
}
}
Let's see the results of the CWH command - in this case we run it twice, selecting "No" to the question about history creation for the cylinder on the left and "Yes" to the same question for the cylinder on the right:
As pointed out in the thread on the discussion group, there are some limitations to the API around the history recording for solids: you cannot, for instance, programmatically manipulate the solid's history: it's only possible to create new solids that will then allow users to make use of editing operations that effect the history.
On a somewhat related note, back in this post I mentioned a hole in the .NET API around creating a swept solid. I've been informed by a friend in our Engineering team that we've now plugged it - and some other related holes - in the .NET API for AutoCAD 2010. You will now have the following methods available from the Solid3d class: CreateExtrudedSolid, CreateLoftedSolid, CreateRevolvedSolid and CreateSweptSolid (the equivalent .NET methods for Surfaces existed already, as well as the base C++ methods in ObjectARX). Thanks for the heads-up, Joel! :-)