In a recent query from a developer, the axis end points of a cylindrical solid were needed to be retrieved. For this, it is required to get the circular edges that make the cylinder and find its center points. I remembered Gilles Chanteau's elegant code snippet in a discussion forum post that made use of Linq query with BRep API and went in search of it and found this. It turned out that the code could be made to retrieve the axis end points of a cylindrical solid with minimal change.
So here is the modified code snippet and thanks to Gilles.
[CommandMethod("FindCylinderAxis" )]
public void FindCylinderAxis()
{
Document doc
= Application.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
PromptEntityOptions peo
= new PromptEntityOptions("Pick a cylinder : " );
peo.SetRejectMessage
("\\nA 3d solid of cylindrical shape must be selected." );
peo.AddAllowedClass(
typeof (Autodesk.AutoCAD.DatabaseServices.Solid3d), true );
PromptEntityResult per = ed.GetEntity(peo);
if (per.Status != PromptStatus.OK)
return ;
using (Transaction tr
= doc.Database.TransactionManager.StartTransaction())
{
Solid3d sld = tr.GetObject(
per.ObjectId, OpenMode.ForRead, false ) as Solid3d;
Point3d axisPt1 = Point3d.Origin;
Point3d axisPt2 = Point3d.Origin;
if (GetCylinderAxis(sld, ref axisPt1, ref axisPt2))
{
ed.WriteMessage(String.Format("{0}Axis points : {1} {2}" ,
Environment.NewLine,
axisPt1.ToString(), axisPt2.ToString()));
}
else
ed.WriteMessage(String.Format("{0}Not a cylinder." ,
Environment.NewLine));
tr.Commit();
}
}
private bool GetCylinderAxis(
Solid3d solid, ref Point3d axisPt1, ref Point3d axisPt2)
{
bool isCylinder = false ;
axisPt1 = Point3d.Origin;
axisPt2 = Point3d.Origin;
using (Brep brep = new Brep(solid))
{
if (brep.Complexes.Count() != 1)
return false ;
if (brep.Faces.Count() != 3)
return false ;
BrepEdgeCollection edges = brep.Edges;
if (edges.Count() != 2)
return false ;
CircularArc3d[] circles = brep.Edges
.Select(edge =>
((ExternalCurve3d)edge.Curve).NativeCurve
as CircularArc3d)
.Where(circle => circle != null )
.ToArray();
if (circles.Length != 2)
isCylinder = false ;
else
{
isCylinder =
(circles[0].Radius == circles[1].Radius &&
circles[0].Normal.IsParallelTo(circles[1].Normal));
axisPt1 = circles[0].Center;
axisPt2 = circles[1].Center;
}
}
return isCylinder;
}