ADN Open CIS
Сообщество программистов Autodesk в СНГ

30/05/2013

Получение нормали к грани 3D-тела с помощью BREP .NET API

Следующая C#-статья иллюстрирует как получить нормаль к грани 3D-тела с помощью функционала BRep .NET API:

Код - C#: [Выделить]
  1. // Возвращаем вектор нормали к грани 3D-тела [Philippe Leefsma, 7/11/2012]
  2. [CommandMethod("FaceNormal")]
  3. public void FaceNormal()
  4. {
  5.     Document doc = Application.DocumentManager.MdiActiveDocument;
  6.     Database db = doc.Database;
  7.     Editor ed = doc.Editor;
  8.  
  9.     PromptEntityOptions peo = new PromptEntityOptions(
  10.         "\nВыберите 3D-тело: ");
  11.  
  12.     peo.SetRejectMessage("\nОшибочный выбор...");
  13.     peo.AddAllowedClass(typeof(Solid3d), true);
  14.  
  15.     PromptEntityResult per = ed.GetEntity(peo);
  16.  
  17.     if (per.Status != PromptStatus.OK)
  18.         return;
  19.  
  20.     PromptPointOptions ppo = new PromptPointOptions(
  21.         "\nВыберите точку на грани: ");
  22.  
  23.     ppo.AllowArbitraryInput = false;
  24.  
  25.     PromptPointResult ppr = ed.GetPoint(ppo);
  26.  
  27.     if (ppr.Status != PromptStatus.OK)
  28.         return;
  29.  
  30.     Point3d point = ppr.Value;
  31.  
  32.     using (Transaction Tx = db.TransactionManager.StartTransaction())
  33.     {
  34.         Solid3d solid = Tx.GetObject(per.ObjectId, OpenMode.ForRead)
  35.             as Solid3d;
  36.  
  37.         ObjectId[] ids = new ObjectId[] { per.ObjectId };
  38.  
  39.         FullSubentityPath path = new FullSubentityPath(
  40.             ids, new SubentityId(SubentityType.Null, IntPtr.Zero));
  41.  
  42.         using (Brep brep = new Brep(path))
  43.         {
  44.             foreach (Autodesk.AutoCAD.BoundaryRepresentation.Face face in
  45.                 brep.Faces)
  46.             {
  47.                 PointContainment ptContainment = new PointContainment();
  48.  
  49.                 using (BrepEntity brepEnt = face.GetPointContainment(
  50.                     point,
  51.                     out ptContainment))
  52.                 {
  53.                     if (ptContainment == PointContainment.Inside ||
  54.                         ptContainment == PointContainment.OnBoundary)
  55.                     {
  56.                         ed.WriteMessage("\nНормаль к грани в точке " +
  57.                             PointToStr(point) + " = " +
  58.                             VectToStr(GetFaceNormal(face, point)));
  59.                     }
  60.                 }
  61.             }
  62.         }
  63.  
  64.         Tx.Commit();
  65.     }
  66. }
  67.  
  68. // Небольшие вспомогательные методы
  69. private string VectToStr(Vector3d v)
  70. {
  71.     return "[" +
  72.         v.X.ToString("F2") + ", " +
  73.         v.Y.ToString("F2") + ", " +
  74.         v.Z.ToString("F2")
  75.         + "]";
  76. }
  77.  
  78. Vector3d GetFaceNormal(
  79.     Autodesk.AutoCAD.BoundaryRepresentation.Face face,
  80.     Point3d point)
  81. {
  82.     PointOnSurface ptOnSurf = face.Surface.GetClosestPointTo(point);
  83.  
  84.     Point2d param = ptOnSurf.Parameter;
  85.  
  86.     Vector3d normal = ptOnSurf.GetNormal(param);
  87.  
  88.     // Похоже, что мы не можем доверять свойству
  89.     // face.Surface.IsNormalReversed property,
  90.     // так что я сделал небольшое смещение точки от поверхности
  91.     // и проверяю, что смещенная точка внутри 3D-тела
  92.     // В случае если точка внутри (или на поверхности),
  93.     // нормаль должна быть инвертирована
  94.  
  95.     Vector3d normalTest = normal.MultiplyBy(1E-6 / normal.Length);
  96.   
  97.     Point3d ptTest = point.Add(normalTest);
  98.  
  99.     PointContainment ptContainment = new PointContainment();
  100.  
  101.     bool reverse = false;
  102.  
  103.     using(BrepEntity brepEnt =
  104.         face.Brep.GetPointContainment(
  105.             ptTest,
  106.             out ptContainment))
  107.     {
  108.         if(ptContainment != PointContainment.Outside)
  109.         {
  110.             reverse = true;
  111.         }
  112.     }
  113.  
  114.     return normal.MultiplyBy(reverse ? -1.0 : 1.0);
  115. }

 

Источник: http://adndevblog.typepad.com/autocad/2012/07/retrieving-a-solid3d-face-normal-through-brep-api.html

Обсуждение: http://adn-cis.org/forum/index.php?topic=71.0

Опубликовано 30.05.2013
Отредактировано 08.06.2013 в 01:18:47