Code Red > .NET

Laying a 3D Solid Flat to XY Plane

(1/3) > >>

Jonesy97:
Hi all,

I'm trying to take a 3D solid on any orientation, and lie it's largest face flat to the XY plane.

I have got as far as working out which face is largest using Brep.Faces and .GetArea.

My current thinking is to try and to calculate the angle of the normal vector of this face, and then rotate the 3d solid by this angle, but I can't quite figure out how to get this angle.

Any pointers would be much appreciated, or if you can think of a different way to achieve this. I've put my code so far below.

Thanks


--- Code - C#: ---      public void Test()      {                Document doc = ACAD_APP.DocumentManager.MdiActiveDocument;                Editor ed = doc.Editor;                Database db = HostApplicationServices.WorkingDatabase;                 using (DocumentLock docLoc = doc.LockDocument())                {                     PromptEntityOptions peo = new PromptEntityOptions("Select 3D solid.");                    peo.SetRejectMessage("\nInvalid selection...");                    peo.AddAllowedClass(typeof(Solid3d), true);                     PromptEntityResult per = ed.GetEntity(peo);                     if (per.Status != PromptStatus.OK)                                        {                                                return;                                        }                                        else                                        {                                                using (Transaction trans = db.TransactionManager.StartTransaction())                                                {                                                        Solid3d solid = trans.GetObject(per.ObjectId, OpenMode.ForRead) as Solid3d;                                                        ObjectId[] ids = new ObjectId[] { per.ObjectId };                                                         FullSubentityPath path = new FullSubentityPath(ids, new SubentityId(SubentityType.Null, IntPtr.Zero));                                                         using (Brep brep = new Brep(path))                                                        {                                                                var faceAreaList = new List<double>();                                                                foreach (Autodesk.AutoCAD.BoundaryRepresentation.Face face in brep.Faces)                                                                {                                                                         faceAreaList.Add(face.GetArea());                                                                                                                                        }                                                                faceAreaList.Sort();                                                                 foreach (Autodesk.AutoCAD.BoundaryRepresentation.Face face in brep.Faces)                                                                {                                                                        if (face.GetArea() == faceAreaList[0])                                                                        {                                                                                 Autodesk.AutoCAD.Geometry.Surface surf = face.Surface;                                                                                 ExternalBoundedSurface ebSurf = surf as ExternalBoundedSurface;                                                                          }                                                                 }                                                        }                                                }                                        }                 }        } 

It's Alive!:
I think you have to dill down to get the edges for the faces.
Edges have a Curve property, or you can get the vertexes, which have a point property
From the edges or vertexes you’ll want to get the direction of the edges, then you can cross product to get the normal.

I had a sample for doing cuboids, but I lost it.  With cuboids that have a common thickness, I.e. a door,  you can map out which face you want to use

Just add, you’ll want to make sure that your normal isn’t pointing towards the inside the solid

Jonesy97:
Update: I think I've managed to grab the normal vector of the largest face now, just not sure how to rotate the part by this vector yet.


--- Code - C#: ---      public void Test()      {                Document doc = ACAD_APP.DocumentManager.MdiActiveDocument;                Editor ed = doc.Editor;                Database db = HostApplicationServices.WorkingDatabase;                 using (DocumentLock docLoc = doc.LockDocument())                {                     PromptEntityOptions peo = new PromptEntityOptions("Select 3D solid.");                    peo.SetRejectMessage("\nInvalid selection...");                    peo.AddAllowedClass(typeof(Solid3d), true);                     PromptEntityResult per = ed.GetEntity(peo);                     if (per.Status != PromptStatus.OK)                                        {                                                return;                                        }                                        else                                        {                                                using (Transaction trans = db.TransactionManager.StartTransaction())                                                {                                                        Solid3d solid = trans.GetObject(per.ObjectId, OpenMode.ForRead) as Solid3d;                                                        ObjectId[] ids = new ObjectId[] { per.ObjectId };                                                         FullSubentityPath path = new FullSubentityPath(ids, new SubentityId(SubentityType.Null, IntPtr.Zero));                                                         using (Brep brep = new Brep(path))                                                        {                                                                var faceAreaList = new List<double>();                                                                foreach (Autodesk.AutoCAD.BoundaryRepresentation.Face face in brep.Faces)                                                                {                                                                         faceAreaList.Add(face.GetArea());                                                                                                                                        }                                                                faceAreaList.Sort();                                                                 foreach (Autodesk.AutoCAD.BoundaryRepresentation.Face face in brep.Faces)                                                                {                                                                        if (face.GetArea() == faceAreaList[0])                                                                        {                                                                                 Autodesk.AutoCAD.Geometry.Surface surf = face.Surface;                                                                                                                                                                 Interval[] box = surf.GetEnvelope();                                                                                double p1 = box[0].LowerBound + box[0].Length / 2.0;                                                                                double p2 = box[1].LowerBound + box[1].Length / 2.0;                                                                                Point2d ptParams = new Point2d(p1, p2);                                                                                PointOnSurface pos = new PointOnSurface(surf, ptParams);                                                                                Vector3d normal = pos.GetNormal(ptParams);                                                                         }                                                                 }                                                        }                                                }                                        }                 }        } 

It's Alive!:
One option is to build a matrix, then transformby

Jonesy97:
Thanks for the tips. So I've got this far making a matrix and then transforming by, however when I run the line "solidEnt.TransformBy(resultantMatrix);" my autocad freezes with no error message, despite the try catch (System.Exception ex).

Any ideas? Appreciate the help so far!


--- Code - C#: ---      public void Test()      {                Document doc = ACAD_APP.DocumentManager.MdiActiveDocument;                Editor ed = doc.Editor;                Database db = HostApplicationServices.WorkingDatabase;                 using (DocumentLock docLoc = doc.LockDocument())                {                        try                        {                                  PromptEntityOptions peo = new PromptEntityOptions("Select 3D solid.");                                peo.SetRejectMessage("\nInvalid selection...");                                peo.AddAllowedClass(typeof(Solid3d), true);                                 PromptEntityResult per = ed.GetEntity(peo);                                  if (per.Status != PromptStatus.OK)                                {                                        return;                                }                                else                                {                                                using (Transaction trans = db.TransactionManager.StartTransaction())                                                {                                                        Solid3d solid = trans.GetObject(per.ObjectId, OpenMode.ForRead) as Solid3d;                                                        ObjectId[] ids = new ObjectId[] { per.ObjectId };                                                         FullSubentityPath path = new FullSubentityPath(ids, new SubentityId(SubentityType.Null, IntPtr.Zero));                                                         using (Brep brep = new Brep(path))                                                        {                                                                //get biggest face by making list of areas, and then sorting                                                                var faceAreaList = new List<double>();                                                                foreach (Autodesk.AutoCAD.BoundaryRepresentation.Face face in brep.Faces)                                                                {                                                                         faceAreaList.Add(face.GetArea());                                                                                                                                        }                                                                faceAreaList.Sort();                                                                faceAreaList.Reverse();                                                                 foreach (Autodesk.AutoCAD.BoundaryRepresentation.Face face in brep.Faces)                                                                {                                                                        if (face.GetArea() == faceAreaList[0])                                                                        {                                                                                //get point in middle of biggest face, and normal vector                                                                                Autodesk.AutoCAD.Geometry.Surface surf = face.Surface;                                                                                                                                                                 Interval[] box = surf.GetEnvelope();                                                                                double p1 = box[0].LowerBound + box[0].Length / 2.0;                                                                                double p2 = box[1].LowerBound + box[1].Length / 2.0;                                                                                Point2d ptParams = new Point2d(p1, p2);                                                                                PointOnSurface pos = new PointOnSurface(surf, ptParams);                                                                                Vector3d normal = pos.GetNormal(ptParams);                                                                                Point3d pt = pos.GetPoint(ptParams);                                                                                                                                                                Matrix3d resultantMatrix = Matrix3d.Identity;                                                                                 //rotation around z axis                                                                                Plane xy = new Plane(Point3d.Origin, Vector3d.ZAxis);                                                                                  Matrix3d zAxisTrans = Matrix3d.Rotation(Vector3d.ZAxis.AngleOnPlane(xy) - normal.AngleOnPlane(xy),Vector3d.ZAxis,pt);                                                                                normal = normal.TransformBy(zAxisTrans);                                                                                resultantMatrix = resultantMatrix.PreMultiplyBy(zAxisTrans);                                                                                 //rotation around x axis                                                                                Plane yz = new Plane(Point3d.Origin, Vector3d.ZAxis);                                                                                 Matrix3d xAxisTrans = Matrix3d.Rotation(Vector3d.ZAxis.AngleOnPlane(yz) - normal.AngleOnPlane(yz), Vector3d.ZAxis, pt);                                                                                normal = normal.TransformBy(xAxisTrans);                                                                                resultantMatrix = resultantMatrix.PreMultiplyBy(xAxisTrans);                                                                                 //rotation around y axis                                                                                Plane xz = new Plane(Point3d.Origin, Vector3d.ZAxis);                                                                                 Matrix3d yAxisTrans = Matrix3d.Rotation(Vector3d.ZAxis.AngleOnPlane(xz) - normal.AngleOnPlane(xz), Vector3d.ZAxis, pt);                                                                                normal = normal.TransformBy(yAxisTrans);                                                                                resultantMatrix = resultantMatrix.PreMultiplyBy(yAxisTrans);                                                                                 solidEnt.TransformBy(resultantMatrix);                                                                                                                      }                                                                 }                                                        }                                                       trans.Commit();                                                }                                }                     }                    catch (System.Exception ex)                    {                             Autodesk.AutoCAD.ApplicationServices.Core.Application.ShowAlertDialog(ex.Message);                    }                 }        } 

Navigation

[0] Message Index

[#] Next page

Go to full version