26/01/2015
Просмотр нормалей к граням сети
Недавно я получил чертеж от одного из программистов, который содержал сеть (SubDMesh), созданную при помощи кода, использующего информацию о вершинах и гранях. В таких сетях нормали к граням зависят от порядка вершин, определяющих грани, так что нужно было убедиться, что с нормалями всё в порядке.В этом случае желательно было увидеть нормали к сети. Следующий код показывает как это сделать:
Код - C++: [Выделить]
- Acad::ErrorStatus es;
- ads_name name;
- AcGePoint3d pt;
- int ret = acedEntSel(_T("\nВыберите сеть (SubDMesh): " ), name, asDblArray(pt));
- if (ret != RTNORM)
- {
- acutPrintf(_T("\nНичего не выбрано" ));
- return ;
- }
- AcDbObjectId id;
- acdbGetObjectId(id, name);
- if (id.objectClass() != AcDbSubDMesh::desc())
- {
- acutPrintf(_T("\nВыбрана не сеть (SubDMesh)" ));
- return ;
- }
- AcDbObjectPointer<AcDbSubDMesh> mesh(id, AcDb::kForRead);
- AcDbFullSubentPathArray subentPaths;
- es = mesh->getSubentPath(-1, kFaceSubentType, subentPaths);
- AcGePoint3dArray vertices;
- es = mesh->getSubDividedVertices(vertices);
- AcArray<Adesk::Int32> faceInfo;
- es = mesh->getSubDividedFaceArray(faceInfo);
- // Содердимое списка граней имеет вид:
- // [Число вершин в следующей грани],
- // <ИндексВершины1, ИндексВершины2, и т.д.>,
- // т.е. [4], <1, 2, 3, 4>, [3], <1, 2, 3>, и т.д.
- AcDbDatabase * pDb =
- acdbHostApplicationServices()->workingDatabase();
- AcDbBlockTableRecordPointer ms(ACDB_MODEL_SPACE, pDb, AcDb::kForWrite);
- AcDbVoidPtrArray lineArray;
- int face = 0;
- int numVerticesInFace = 0;
- for (int i = 0; i < faceInfo.length(); i += numVerticesInFace + 1, face++)
- {
- numVerticesInFace = faceInfo.at(i);
- AcGePlane facePlane;
- es = mesh->getFacePlane(subentPaths.at(face).subentId(), facePlane);
- AcGeBoundBlock3d boundBox;
- for (int j = 0; j < numVerticesInFace; j++)
- {
- AcGePoint3d pt1 =
- vertices.at(faceInfo.at(i + j + 1));
- AcGePoint3d pt2 =
- vertices.at(
- faceInfo.at(i + ((j + 1) % numVerticesInFace) + 1));
- if (j == 0)
- boundBox.set(pt1, pt2);
- else
- {
- boundBox.extend(pt1);
- boundBox.extend(pt2);
- }
- // Если требуются еще и ребра
- //AcDbObjectPointer<AcDbLine> line;
- //line.create();
- //line->setStartPoint(pt1);
- //line->setEndPoint(pt2);
- //ms->appendAcDbEntity(line);
- }
- AcGePoint3d minPt;
- AcGePoint3d maxPt;
- boundBox.getMinMaxPoints(minPt, maxPt);
- AcGeVector3d normalLen = maxPt - minPt;
- AcGeVector3d normal = facePlane.normal();
- // Стрелка
- AcDbLine *pArrow = new AcDbLine;
- pArrow->setColorIndex(2);
- AcGePoint3d sp = minPt + normalLen * 0.5;
- pArrow->setStartPoint(sp);
- AcGePoint3d ep = sp
- + normal.normalize() * normalLen.length();
- pArrow->setEndPoint(ep);
- ms->appendAcDbEntity(pArrow);
- pArrow->close();
- // Окончание стрелки
- double arrowLen = normalLen.length() * 0.2;
- AcDb3dSolid *pArrowHead = new AcDb3dSolid;
- es = pArrowHead->createFrustum(
- arrowLen,
- arrowLen / 3.0,
- arrowLen / 3.0,
- 0.0);
- AcGeVector3d zd = (ep - sp).normalize();
- AcGeVector3d yd = zd.perpVector().normalize();
- AcGeVector3d xd = yd.crossProduct(zd).normalize();
- AcGeMatrix3d mat;
- mat.setCoordSystem(ep, xd, yd, zd);
- pArrowHead->transformBy(mat);
- ms->appendAcDbEntity(pArrowHead);
- pArrowHead->close();
- }
Вот так выглядят нормали к простому параллелепипеду:
Источник: http://adndevblog.typepad.com/autocad/2015/01/viewing-face-normals-of-a-mesh.html
Обсуждение: http://adn-cis.org/forum/index.php?topic=1799
Опубликовано 26.01.2015Отредактировано 26.01.2015 в 01:31:53