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

29/05/2013

Получение информации о гранях из AcDbPolyFaceMesh и AcDbPolygonMesh

Вопрос:

Я бы хотел получить информацию о гранях для примитивов полигональных и многогранных сетей. Есть ли пример как это можно сделать?

Ответ:

Следующие примеры кода рисуют отрезки поперёк всех граней выбранных примитивов полигональной и многогранной сетей.

Код - C++: [Выделить]
  1. static void AEN1ArxAcDbPolyFaceMesh_PolyFace(void)
  2. {
  3.   int ret;
  4.   ads_name name;
  5.   ads_point pt;
  6.  
  7.   if (acedEntSel(_T("\nВыберите многогранную сеть: "), name, pt) != RTNORM)
  8.     return;
  9.  
  10.   AcDbObjectId id;
  11.   if(acdbGetObjectId(id, name) != Acad::eOk)
  12.     return;
  13.  
  14.   AcDbObjectPointer<AcDbPolyFaceMesh> mesh(id, AcDb::kForRead); 
  15.   if (mesh.openStatus() != Acad::eOk)
  16.     return;
  17.  
  18.   AcArray<AcDbObjectId> vertexIds;
  19.   AcArray<AcDbLine*> lines;
  20.   AcDbObjectIterator * iter = mesh->vertexIterator();
  21.   for (; !iter->done(); iter->step())
  22.   {
  23.     if (iter->objectId().objectClass() ==
  24.       AcDbPolyFaceMeshVertex::desc())
  25.     {
  26.       vertexIds.append(iter->objectId()); 
  27.  
  28.       // Вы можете получить здесь положения вершин вместо того, чтобы
  29.       // отбирать ObjectId вершин
  30.     }
  31.     else if (iter->objectId().objectClass() ==
  32.       AcDbFaceRecord::desc())
  33.     {
  34.       // Получаем вершины из записи грани
  35.  
  36.       AcDbObjectPointer<AcDbFaceRecord>
  37.         face(iter->objectId(), AcDb::kForRead);
  38.       AcGePoint3d pts[4];
  39.       for (Adesk::UInt16 i = 0; i < 4; i++)
  40.       {
  41.         // Индекс вершины начинается с 1, что соответствует 0
  42.         // в списке вершин, так что нам нужно вычесть 1
  43.         // Возвращаемый индекс будет отрицательным, если она скрыта.
  44.         // Так что получим положительное значение, используя abs()
  45.  
  46.         Adesk::Int16 vertexIndex;
  47.         if (face->getVertexAt(i, vertexIndex) == Acad::eOk)
  48.         {
  49.           AcDbObjectPointer<AcDbPolyFaceMeshVertex>
  50.             vertex(vertexIds[abs(vertexIndex) - 1], AcDb::kForRead);
  51.           pts[i] = vertex->position();
  52.         }
  53.       }
  54.  
  55.       // Создаём два отрезка перекрещивающих грань для целей тестирования
  56.  
  57.       AcDbLine * line1 = new AcDbLine(pts[0], pts[2]);
  58.       AcDbLine * line2 = new AcDbLine(pts[1], pts[3]);
  59.       lines.append(line1);
  60.       lines.append(line2);
  61.     }
  62.   }
  63.  
  64.   delete iter;
  65.  
  66.   // Добавляем тестовые отрезки в пространство модели
  67.  
  68.   AcDbDatabase * pDb =
  69.     acdbHostApplicationServices()->workingDatabase();
  70.   AcDbBlockTableRecordPointer
  71.     ms(ACDB_MODEL_SPACE, pDb, AcDb::kForWrite);
  72.  
  73.   for (int i = 0; i < lines.length(); i++)
  74.   {
  75.     ms->appendAcDbEntity(lines[i]);
  76.     lines[i]->close();
  77.   }
  78. }
  79.  
  80. static void AEN1ArxAcDbPolyFaceMesh_Polygon(void)
  81. {
  82.   int ret;
  83.   ads_name name;
  84.   ads_point pt;
  85.  
  86.   if (acedEntSel(_T("\nВыберите полигональную сеть: "), name, pt) != RTNORM)
  87.     return;
  88.  
  89.   AcDbObjectId id;
  90.   if(acdbGetObjectId(id, name) != Acad::eOk)
  91.     return;
  92.  
  93.   AcDbObjectPointer<AcDbPolygonMesh> mesh(id, AcDb::kForRead); 
  94.   if (mesh.openStatus() != Acad::eOk)
  95.     return;
  96.  
  97.   Adesk::Int16 M;
  98.   Adesk::Int16 N;
  99.  
  100.   if (mesh->polyMeshType() == AcDb::kSimpleMesh)
  101.   {
  102.     M = mesh->mSize();
  103.     N = mesh->nSize();    
  104.   }
  105.   else
  106.   {
  107.     M = mesh->mSurfaceDensity();
  108.     N = mesh->nSurfaceDensity();
  109.   }
  110.  
  111.   // Собираем точки
  112.  
  113.   AcArray<AcGePoint3d> pts;
  114.  
  115.   AcDbObjectIterator * iter = mesh->vertexIterator();
  116.   Adesk::Int16 m = 0, n = 0;
  117.   for (int i = 0; !iter->done(); iter->step(), i++)
  118.   {
  119.     if (iter->objectId().objectClass() ==
  120.       AcDbPolygonMeshVertex::desc())
  121.     {
  122.       AcDbObjectPointer<AcDbPolygonMeshVertex>
  123.         vertex(iter->objectId(), AcDb::kForRead);
  124.  
  125.       if (vertex->vertexType() == AcDb::k3dSimpleVertex ||
  126.           vertex->vertexType() == AcDb::k3dFitVertex
  127.          )
  128.         pts.append(vertex->position());
  129.     }
  130.   }
  131.  
  132.   delete iter;
  133.  
  134.   // Создаём перекрещивающиеся отрезки
  135.  
  136.   AcArray<AcDbLine*> lines;
  137.  
  138.   for (m = 0; m < M - 1; m++)
  139.     for (n = 0; n < N - 1; n++)
  140.     {
  141.       // Индексы вершин грани могут быть легко посчитаны
  142.       // Если верхний левый – m и n, тогда верхний правый -
  143.       // m, n + 1, нижний правый -  m + 1, n + 1, и
  144.       // нижний левый -  m + 1, n
  145.  
  146.       AcDbLine * line1 =
  147.         new AcDbLine(
  148.           pts[(m * N) + (n)],
  149.           pts[((m + 1) * N) + (n + 1)]);
  150.       AcDbLine * line2 =
  151.         new AcDbLine(
  152.           pts[((m + 1) * N) + (n)],
  153.           pts[(m * N) + (n + 1)]);
  154.       lines.append(line1);
  155.       lines.append(line2);
  156.     }
  157.  
  158.   // Добавляем тестовые линии в пространство модели
  159.  
  160.   AcDbDatabase * pDb = acdbHostApplicationServices()->workingDatabase();
  161.   AcDbBlockTableRecordPointer ms(ACDB_MODEL_SPACE, pDb, AcDb::kForWrite);
  162.  
  163.   for (int i = 0; i < lines.length(); i++)
  164.   {
  165.     ms->appendAcDbEntity(lines[i]);
  166.     lines[i]->close();
  167.   }
  168. }

 

Источник: http://adndevblog.typepad.com/autocad/2012/07/get-facet-information-from-acdbpolyfacemesh-and-acdbpolygonmesh.html

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

Опубликовано 29.05.2013
Отредактировано 08.06.2013 в 00:57:52