Highlighting Nested Block References

The example that follows shows highlighting nested block references. As shown in the following figure, the example creates six entities: three polys (a custom entity) and three boxes. It also creates three block references (inserts). Insert 3 (ins3) is an insert of a block that contains poly3 and box3. Insert 2 (ins2) is an insert of a block that contains poly2, box2, and ins3. Insert 1 (ins1) is an insert of a block that contains poly1, box1, and ins2.

After the inserts are created, the example highlights the different components.

void 
createInsert()
{
    // Create a nested insert and try highlighting its
    // various subcomponents.
    //
    // There are six entities in total -- three polys and
    // three boxes (solids). We've named them: poly1, poly2,
    // poly3, and box1, box2, box3. We also have three
    // inserts: ins1, ins2, ins3.
    //
    // ins3 is an insert of a block that contains (poly3, box3)
    // ins2 is an insert of a block that contains (poly2, box2,
    // ins3).
    // ins1 is an insert of a block that contains (poly1, box1,
    // ins2).
    //
    // Let's create these entities first.
    //
    // Polys
    //
    AsdkPoly *poly1, *poly2, *poly3;
    AcGeVector3d norm(0, 0, 1);
    if ((poly1=new AsdkPoly)==NULL){
        acutPrintf("\nOut of Memory.");
        return;
    }
    if (poly1->set(AcGePoint2d(2, 8),AcGePoint2d(4, 8), 6, norm,
        "POLY1",0)!=Acad::eOk){
        acutPrintf("\nCannot create object with given parameters.");
        delete poly1;
        return;
    }
    if ((poly2=new AsdkPoly)==NULL){
        acutPrintf("\nOut of Memory.");
        delete poly1;
        return;
    }
    if (poly2->set(AcGePoint2d(7, 8), AcGePoint2d(9, 8), 6, norm,
        "POLY2",0)!=Acad::eOk){
        acutPrintf("\nCannot create object with given parameters.");
        delete poly1;
        delete poly2;
        return;
    }
    if ((poly3=new AsdkPoly)==NULL){
        acutPrintf("\nOut of Memory.");
        delete poly1;
        delete poly2;
        return;
    }
    if (poly3->set(AcGePoint2d(12, 8),AcGePoint2d(14, 8), 6, norm,
        "POLY3",0)!=Acad::eOk){
        acutPrintf("\nCannot create object with given parameters.");
        delete poly1;
        delete poly2;
        delete poly3;
        return;
    }
    postToDb(poly1);
    postToDb(poly2);
    postToDb(poly3);
    // Boxes
    //
    AcDb3dSolid *box1, *box2, *box3;
    box1 = new AcDb3dSolid(); 
    box2 = new AcDb3dSolid();
    box3 = new AcDb3dSolid();
    box1->createBox(2, 2, 2);
    box2->createBox(2, 2, 2);
    box3->createBox(2, 2, 2);
    AcGeMatrix3d mat;
    mat(0, 3) = 2; mat(1, 3) = 2;
    box1->transformBy(mat);
    mat(0, 3) = 7; mat(1, 3) = 2;
    box2->transformBy(mat);
    mat(0, 3) = 12; mat(1, 3) = 2;
    box3->transformBy(mat);
    postToDb(box1);
    postToDb(box2);
    postToDb(box3);
    // Inserts
    //
    // Arguments to BLOCK are:
    //      blockname,
    //      insert point, 
    //      select objects,
    //      empty string for selection complete
    // Arguments to INSERT are:
    //      blockname,
    //      insertion point,
    //      xscale,
    //      yscale,
    //      rotation angle
    //
    acedCommandS_command(RTSTR, "_globcheck", RTSHORT, 0, RTNONE);
    acedCommandS(RTSTR, "BLOCK", RTSTR, "blk3", RTSTR, "0,0",
                RTSTR, "14,8", RTSTR, "11,1", RTSTR, "",
                RTNONE);
    acedCommandS(RTSTR, "INSERT", RTSTR, "blk3", RTSTR,
                "0,0", RTSHORT, 1, RTSHORT, 1, RTSHORT,
                0, RTNONE);
    acedCommandS(RTSTR, "BLOCK", RTSTR, "blk2", RTSTR, "0,0",
                RTSTR, "9,8", RTSTR, "6,1", RTSTR, "11,1",
                RTSTR, "", RTNONE);
    acedCommandS(RTSTR, "INSERT", RTSTR, "blk2", RTSTR,
                "0,0", RTSHORT, 1, RTSHORT, 1, RTSHORT,
                0, RTNONE);
    acedCommandS(RTSTR, "BLOCK", RTSTR, "blk1", RTSTR, "0,0",
                RTSTR, "4,8", RTSTR, "1,1", RTSTR, "6,1",
                RTSTR, "", RTNONE);
    acedCommandS(RTSTR, "INSERT", RTSTR, "blk1", RTSTR,
                "0,0", RTSHORT, 1, RTSHORT, 1, RTSHORT,
                0, RTNONE);
    return;
}
void 
hilitInsert()
{
    Adesk::Boolean interrupted = Adesk::kFalse;
    acutPrintf("\nSelect an insert");
    Acad::ErrorStatus es = Acad::eOk;
    AcDbEntity  *ent = NULL;
    AcDbEntity  *ent2 = NULL;
    AcDbBlockReference *blRef = NULL;
    AcDbObjectId objectId, blRefId;
    ads_name     ename, sset;
    for (;;) {
        switch (acedSSGet(NULL, NULL, NULL, NULL, sset)) {
        case RTNORM:
        {
            struct resbuf *rb;
            if (acedSSNameX(&rb, sset, 0) != RTNORM) {
                acutPrintf("\n acedSSNameX failed");
                acedSSFree(sset);
                return;
            }
            int            sel_method;
            ads_name       subname;
            short          marker;
            AcGePoint3d    pickpnt;
            AcGeVector3d   pickvec;
            if (!extractEntityInfo(rb,
                              sel_method,
                              ename,
                              subname,
                              marker,
                              pickpnt,
                              pickvec)) {
                acutPrintf("\nextractEntityInfo failed");
                acedSSFree(sset);
                return;
            }
            acedSSFree(sset);
            assert(marker != 0);
            if (marker == 0) {
                acutPrintf("\nmarker == 0");
                return;
            }
            // Get the insert first.
            //
            AOK(acdbGetObjectId(blRefId, ename));
            AOK(acdbOpenAcDbEntity(ent, blRefId,
                AcDb::kForRead));
            assert(ent != NULL);
            blRef = AcDbBlockReference::cast(ent);
            if (blRef == NULL) {
                acutPrintf("\nNot an insert.");
                AOK(ent->close());
                continue;
            }
            struct resbuf *insStack;
            ads_point pickpoint;
            ads_matrix adsmat;
            pickpoint[0] = pickpnt[0];
            pickpoint[1] = pickpnt[1];
            pickpoint[2] = pickpnt[2];
            // Now get details on the entity that was
            // selected.
            // 
            if (acedNEntSelP(NULL, ename, pickpoint, TRUE,
                adsmat, &insStack) != RTNORM)
            {
                acutPrintf("\nFailure in acedNEntSelP");
                return;
            }
            assert(insStack != NULL);
            AOK(acdbGetObjectId(objectId, ename));
            AOK(acdbOpenAcDbEntity(ent2, objectId,
                AcDb::kForRead));
            assert(ent2 != NULL);
            // Make an array of AcDbObjectIds from the
            // insertStack.  Don't use the "smart array" 
            // AcDbObjectIdArray class, because the 
            // getSubentPathsAtGsMarker() function expects argument
            // eight to be of type AcDbObjectId*. Just 
            // make room for approximately 100 IDs in the array.
            //
            AcDbObjectId *idArray = new AcDbObjectId[100];
            int count = 0;
            struct resbuf *rbIter = insStack; 
            AcDbObjectId objId;
            acdbGetObjectId(objId, ename);
            idArray[count++] = objId;
            while (rbIter != NULL) {
                ename[0] = rbIter->resval.rlname[0];
                ename[1] = rbIter->resval.rlname[1];
                acdbGetObjectId(objId, ename);
                idArray[count++] = objId;
                rbIter = rbIter->rbnext;
            }
            count--;
            acutRelRb(insStack);
            // First, we'll highlight an edge.
            //
            int                  numPaths;
            AcDbFullSubentPath  *subentPaths;
            AcGeMatrix3d         xform;
            es = blRef->getSubentPathsAtGsMarker(
                AcDb::kEdgeSubentType,
                marker,
                pickpnt,
                xform,
                numPaths,
                subentPaths,
                count,
                idArray);
            assert(numPaths == 1);
            // Highlight and unhighlight the selected edge.
            //
            acutPrintf("\nHighlighting the first edge.");
            es = blRef->highlight(subentPaths[0]);
            pressEnterToContinue();
            es = blRef->unhighlight(subentPaths[0]);
            // If this is a solid, it will have faces.
            // In this case, let's highlight them.
            //
            if(ent2->isKindOf(AcDb3dSolid::desc())) {
                es = blRef->getSubentPathsAtGsMarker(
                    AcDb::kFaceSubentType,
                    marker,
                    pickpnt,
                    xform,
                    numPaths,
                    subentPaths,
                    count,
                    idArray);
                assert(numPaths == 2);
                // Highlight and unhighlight the selected
                // faces.
                //
                acutPrintf("\nHighlighting the first"
                    " face.");
                es = blRef->highlight(subentPaths[0]);
                pressEnterToContinue();
                es = blRef->unhighlight(subentPaths[0]);
                acutPrintf("\nHighlighting the next face.");
                es = blRef->highlight(subentPaths[1]);
                pressEnterToContinue();
                es = blRef->unhighlight(subentPaths[1]);
            }
            delete []subentPaths;
            // Now, let's highlight the whole entity.
            //
            acutPrintf("\nHighlighting the entire entity");
            AcDbFullSubentPath subPath;
            for (int i = count; i >= 0; i--) {
                subPath.objectIds().append(idArray[i]);
            }
            es = blRef->highlight(subPath);
            pressEnterToContinue();
            es = blRef->unhighlight(subPath);
            // Finally, let's highlight each enclosing
            // insert.
            //
            for (i = count -1; i >= 0; i --) {
                subPath.objectIds().removeAt(
                    subPath.objectIds().length() - 1);
                acutPrintf("\nHighlighting insert layer %d",
                    i + 1);
                blRef->highlight(subPath);
                pressEnterToContinue();
                es = blRef->unhighlight(subPath);
            }
        }      // case RTNORM
            break;
        case RTNONE:
        case RTCAN:
            return;
        default:
            continue;
        } // switch
        break;
    } //for (;;)
    AOK(ent->close());
    AOK(ent2->close());
    return;
}