Thanks to Philippe Leefsma, from our DevTech team in Europe, for providing the code for this post. Philippe kindly based his code on that provided in this previous post, which made it especially easy for me to format for posting. Thanks, Philippe! :-)
In the post linked to above we saw some code defining a SAP (SweepAlongPath) command. This post extends that to implement a complementary RAA (RevolveAroundAxis) command. Philippe’s original code asked the user for a line to define the axis of revolution. I generalised the code slightly to accept a curve: as we’re only using the vector between the start and endpoints to define the axis of revolution, this will work. This has the advantage of now working with polylines that cleanly define an axis (i.e. with a single straight segment) but has the disadvantage (or perhaps we can call it a dubious advantage :-) of working with other types of curve that do not (such as arcs, circles and multiline segment polylines). I could have coded more defensively to disallow certain axes being used, but ultimately the code runs just fine, and works very well according to the GIGO principle. :-)
Here’s the C# code:
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Geometry;
using System;
namespace SolidCreation
{
public class Commands
{
[CommandMethod("SAP")]
public void SweepAlongPath()
{
Document doc =
Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
// Ask the user to select a region to extrude
PromptEntityOptions peo1 =
new PromptEntityOptions(
"\nSelect profile or curve to sweep: "
);
peo1.SetRejectMessage(
"\nEntity must be a region, curve or planar surface."
);
peo1.AddAllowedClass(
typeof(Region), false);
peo1.AddAllowedClass(
typeof(Curve), false);
peo1.AddAllowedClass(
typeof(PlaneSurface), false);
PromptEntityResult per =
ed.GetEntity(peo1);
if (per.Status != PromptStatus.OK)
return;
ObjectId regId = per.ObjectId;
// Ask the user to select an extrusion path
PromptEntityOptions peo2 =
new PromptEntityOptions(
"\nSelect path along which to sweep: "
);
peo2.SetRejectMessage(
"\nEntity must be a curve."
);
peo2.AddAllowedClass(
typeof(Curve), false);
per = ed.GetEntity(peo2);
if (per.Status != PromptStatus.OK)
return;
ObjectId splId = per.ObjectId;
PromptKeywordOptions pko =
new PromptKeywordOptions(
"\nSweep a solid or a surface?"
);
pko.AllowNone = true;
pko.Keywords.Add("SOlid");
pko.Keywords.Add("SUrface");
pko.Keywords.Default = "SOlid";
PromptResult pkr =
ed.GetKeywords(pko);
bool createSolid = (pkr.StringResult == "SOlid");
if (pkr.Status != PromptStatus.OK)
return;
// Now let's create our swept surface
Transaction tr =
db.TransactionManager.StartTransaction();
using (tr)
{
try
{
Entity sweepEnt =
tr.GetObject(regId, OpenMode.ForRead) as Entity;
Curve pathEnt =
tr.GetObject(splId, OpenMode.ForRead) as Curve;
if (sweepEnt == null || pathEnt == null)
{
ed.WriteMessage(
"\nProblem opening the selected entities."
);
return;
}
// We use a builder object to create
// our SweepOptions
SweepOptionsBuilder sob =
new SweepOptionsBuilder();
// Align the entity to sweep to the path
sob.Align =
SweepOptionsAlignOption.AlignSweepEntityToPath;
// The base point is the start of the path
sob.BasePoint = pathEnt.StartPoint;
// The profile will rotate to follow the path
sob.Bank = true;
// Now generate the solid or surface...
Entity ent;
if (createSolid)
{
Solid3d sol = new Solid3d();
sol.RecordHistory = true;
sol.CreateSweptSolid(
sweepEnt,
pathEnt,
sob.ToSweepOptions()
);
ent = sol;
}
else
{
SweptSurface ss = new SweptSurface();
ss.CreateSweptSurface(
sweepEnt,
pathEnt,
sob.ToSweepOptions()
);
ent = ss;
}
// ... and add it to the modelspace
BlockTable bt =
(BlockTable)tr.GetObject(
db.BlockTableId,
OpenMode.ForRead
);
BlockTableRecord ms =
(BlockTableRecord)tr.GetObject(
bt[BlockTableRecord.ModelSpace],
OpenMode.ForWrite
);
ms.AppendEntity(ent);
tr.AddNewlyCreatedDBObject(ent, true);
tr.Commit();
}
catch
{ }
}
}
[CommandMethod("RAA")]
public void RevolveAroundAxis()
{
Document doc =
Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
// Ask the user to select a region to revolve
PromptEntityOptions peo1 =
new PromptEntityOptions(
"\nSelect profile or curve to revolve: "
);
peo1.SetRejectMessage(
"\nEntity must be a region, curve or planar surface."
);
peo1.AddAllowedClass(typeof(Region), false);
peo1.AddAllowedClass(typeof(Curve), false);
peo1.AddAllowedClass(typeof(PlaneSurface), false);
PromptEntityResult per1 = ed.GetEntity(peo1);
if (per1.Status != PromptStatus.OK)
return;
// Ask the user to select an axis of revolution
PromptEntityOptions peo2 =
new PromptEntityOptions(
"\nSelect axis of revolution: "
);
peo2.SetRejectMessage(
"\nEntity defining axis must be a curve."
);
peo2.AddAllowedClass(typeof(Curve), false);
PromptEntityResult per2 = ed.GetEntity(peo2);
if (per2.Status != PromptStatus.OK)
return;
Transaction tr =
db.TransactionManager.StartTransaction();
using (tr)
{
Entity prof =
(Entity)tr.GetObject(per1.ObjectId, OpenMode.ForRead);
Curve cur =
(Curve)tr.GetObject(per2.ObjectId, OpenMode.ForRead);
// Set up the options for our revolution
RevolveOptionsBuilder rob = new RevolveOptionsBuilder();
rob.CloseToAxis = false;
rob.DraftAngle = 0;
rob.TwistAngle = 0;
// Create our solid and revolve our profile
Solid3d sol = new Solid3d();
sol.RecordHistory = true;
sol.CreateRevolvedSolid(
prof,
cur.StartPoint,
cur.EndPoint.GetAsVector() - cur.StartPoint.GetAsVector(),
2 * Math.PI, // Go all the way round
0,
rob.ToRevolveOptions()
);
// We'll add the solid to 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);
tr.Commit();
}
}
}
}
Now let’s see the code in action. We’ll start by creating a simple closed polyline for our profile and a line defining our axis of revolution:
Calling the RAA command, we can select these objects to generate our solid:
And here are the results in a 3D view with the “conceptual” Visual Style set:
Vive la Révolution! :-)