A shell is a list of faces that might be connected and can have holes in them. The shell is specified by the number of unique vertices, a list of vertices (pVertexList), the number of faces (faceListSize), and a face list, which consists of the number of points in a given face followed by the index in the vertex list of each vertex for that face. The signature for the shell() function is:
virtual Adesk::Boolean AcGiWorldGeometry::shell( const Adesk::UInt32 nbVertex, const AcGePoint3d* pVertexList, const Adesk::UInt32 faceListSize, const Adesk::Int32* pFaceList, const AcGiEdgeData* pEdgeData = NULL, const AcGiFaceData* pFaceData = NULL, const AcGiVertexData* pVertexData = NULL const struct resbuf* pResBuf = NULL) const = 0;
A negative vertex count indicates a hole in the shell. Holes must be in the same plane as the face in which they reside. The holes must not touch each other and must be completely inside the containing face. The shell() function is a costly operation because it requires the use of a triangulator to break the containing face and the holes down into component triangles.
AcGi polygons and shells with faces of five or more sides are also broken down into triangles before being sent to be displayed. Having the AcGi triangulate a polygon or shell face can be costly in terms of memory and speed, so it's recommended you use three- or four-sided faces in shells to build up faces or polygons with five or more sides. That way, the primitive will not be put through the slow triangulator step.
The triangulator is used only on polygons of five sides or more, shell faces of five sides or more, shell faces with holes, and filled text.
Vertices in a given face must be coplanar. There is no implied connectivity between faces.
Edge data for a shell is listed in the order implied by the face list. For example, in the first face, vertex0 to vertex1 specifies the first edge, vertex1 to vertex2 specifies the second edge, and so on until the last vertex of the face, which connects to the first vertex, as shown below.
If the same edge is used in two different faces, properties may conflict. In such cases, you can set one of the edges to be invisible or make the properties match for each edge.
The order of face data, if present, follows the ordering of the face list for the shell.
The following is an example of a shell with color data attached to edges and faces and visibility data attached to edges. The shell is composed of two triangles in different planes that share a common edge. The common edge has silhouette visibility. This means that when the HIDE command is in effect and the AutoCAD variable DISPSILH equals 1 (display silhouettes is on), the common edge between the faces is drawn only if both faces in the viewport are on the same side of the common edge. In this case, one face is behind the other, so it is not drawn:
Adesk::Boolean AsdkShellSamp::subWorldDraw(AcGiWorldDraw* pW) { // Fill the faces with the current color. // pW->subEntityTraits().setFillType (kAcGiFillAlways); // Create vertices. // Adesk::UInt32 numVerts = 4; AcGePoint3d *pVerts = new AcGePoint3d[numVerts]; pVerts[0] = AcGePoint3d (0.0, 0.0, 0.0); pVerts[1] = AcGePoint3d(0.0, 1.0, 0.0); pVerts[2] = AcGePoint3d(1.0, 1.0, 0.0); pVerts[3] = AcGePoint3d(1.0, 0.0, 2.0); // Create 2 faces. // Adesk::UInt32 faceListSize = 8; Adesk::Int32 *pFaceList = new Adesk::Int32[faceListSize]; // Assign vertices for face #1. // pFaceList[0] = 3; // 3 vertices in the face pFaceList[1] = 0; // pVerts[0] pFaceList[2] = 1; // pVerts[1] pFaceList[3] = 2; // pVerts[2] // assign vertices for face #2. // pFaceList[4] = 3; // 3 vertices in the face pFaceList[5] = 0; // pVerts[0] pFaceList[6] = 2; // pVerts[2] pFaceList[7] = 3; // pVerts[3] // Apply colors to edges. // AcGiEdgeData edgeData; int numEdges = 6; short *pEdgeColorArray = new short[numEdges]; pEdgeColorArray[0] = kRed; pEdgeColorArray[1] = kYellow; pEdgeColorArray[2] = kGreen; pEdgeColorArray[3] = kCyan; pEdgeColorArray[4] = kBlue; pEdgeColorArray[5] = kMagenta; edgeData.setColors(pEdgeColorArray); // Apply visibility to edges and make common edge // between two faces have silhouette visibility during // the HIDE command with ACAD variable DISPSILH = 1. // Adesk::UInt8 *pEdgeVisArray = new Adesk::UInt8[numEdges]; edgeData.setVisibility(pEdgeVisArray); pEdgeVisArray[0] = kAcGiVisible; pEdgeVisArray[1] = kAcGiVisible; pEdgeVisArray[2] = kAcGiSilhouette; pEdgeVisArray[3] = kAcGiSilhouette; pEdgeVisArray[4] = kAcGiVisible; pEdgeVisArray[5] = kAcGiVisible; // Apply colors to faces. // AcGiFaceData faceData; int numFaces = 2; short *pFaceColorArray = new short [numFaces]; pFaceColorArray[0] = kBlue; pFaceColorArray[1] = kRed; faceData.setColors(pFaceColorArray); pW->geometry().shell (numVerts, pVerts, faceListSize, pFaceList, &edgeData, &faceData); delete [] pVerts; delete [] pFaceList; delete [] pEdgeColorArray; delete [] pFaceColorArray; return Adesk::kTrue; }
An AcGiVertexData object contains a single flag that specifies how vertices in a shell are ordered. This flag is set and queried with the following functions:
virtual void AcGiVertexData::setOrientationFlag( const AcGiOrientationType oflag); virtual AcGiOrientationType AcGiVertexData::orientationFlag() const;
This flag is not used for meshes because the ordering of vertices specifying a mesh is fixed. Values for the flag are
The orientation of vertices in a shell's face list indicates the visible side of the face. For example, if the vertices are specified as clockwise and the vertices for a given face are listed in clockwise order, then that face is visible. In this case, faces with vertices in counterclockwise order are invisible.