using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.BoundaryRepresentation;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using AcDb = Autodesk.AutoCAD.DatabaseServices;
namespace MeshSolid
{
public class MeshCreator
{
// Mesh a selected solid
[CommandMethod("SOLMESH")]
static public void MeshFromSolid()
{
Document doc =
Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
// Ask the user to select a solid
PromptEntityOptions peo =
new PromptEntityOptions("Select a 3D solid");
peo.SetRejectMessage("\nA 3D solid must be selected.");
peo.AddAllowedClass(typeof(Solid3d), true);
PromptEntityResult per = ed.GetEntity(peo);
if (per.Status != PromptStatus.OK)
return;
Transaction tr =
db.TransactionManager.StartTransaction();
using (tr)
{
BlockTable bt =
(BlockTable)tr.GetObject(
db.BlockTableId,
OpenMode.ForRead,
false
);
BlockTableRecord btr =
(BlockTableRecord)tr.GetObject(
bt[BlockTableRecord.ModelSpace],
OpenMode.ForWrite,
false
);
Solid3d sol =
tr.GetObject(
per.ObjectId,
OpenMode.ForRead
) as Solid3d;
// Calculate the approximate size of our solid
double length =
sol.GeometricExtents.MinPoint.GetVectorTo(
sol.GeometricExtents.MaxPoint
).Length;
try
{
using (Brep brp = new Brep(sol))
{
// Create and set our mesh control object
using (Mesh2dControl mc = new Mesh2dControl())
{
// These settings seem extreme, but only result
// in ~500 faces for a sphere (during my testing,
// anyway). Other control settings are available
mc.MaxNodeSpacing = length / 10000;
mc.MaxSubdivisions = 100000000;
// Create a mesh filter object
using (Mesh2dFilter mf = new Mesh2dFilter())
{
// Use it to map our control settings to the Brep
mf.Insert(brp, mc);
// Generate a mesh using the filter
using (Mesh2d m = new Mesh2d(mf))
{
// Extract individual faces from the mesh data
foreach (Element2d e in m.Element2ds)
{
Point3dCollection pts = new Point3dCollection();
foreach (Node n in e.Nodes)
{
pts.Add(n.Point);
}
// A face could be a triangle or a quadrilateral
// (the Booleans indicate the edge visibility)
AcDb.Face face = null;
if (pts.Count == 3)
face =
new AcDb.Face(
pts[0], pts[1], pts[2],
true, true, true, true
);
else if (pts.Count == 4)
face =
new AcDb.Face(
pts[0], pts[1], pts[2], pts[3],
true, true, true, true
);
// If we have a valid face, add it to the
// database and the transaction
if (face != null)
{
// Make each face yellow for visibility
face.ColorIndex = 2;
btr.AppendEntity(face);
tr.AddNewlyCreatedDBObject(face, true);
}
}
}
}
}
}
tr.Commit();
}
catch (System.Exception ex)
{
ed.WriteMessage("Exception: {0}", ex.Message);
}
}
}
}
}
Here’s what happens when we run the SOLMESH command, selecting a simple sphere (which I later moved to the side, for comparison):