admin 发表于 2024-3-14 20:56:29

[每日一码] 获取块的XCLIP边界

static BOOL drawAPlineWithPropertiesFromBlockRef(AcGePoint2dArray pts,

               AcDbBlockReference* ref, double elevation, AcGeVector3d& normal)

{

    AcDbPolyline *pl = new AcDbPolyline;

    AcDbObjectId owner;



    pl->setDatabaseDefaults();

    pl->setClosed(Adesk::kTrue);

    pl->setThickness(0.0);



    if (ref != NULL) {

      owner=ref->ownerId();

      pl->setPropertiesFrom(ref);

    }



    pl->setNormal(normal);



    for (int i=0; i < pts.length(); i++)

    {

      pl->addVertexAt(i, pts);

    }



    pl->setElevation(elevation);

    pl->setColorIndex(1); // Red



    AcDbBlockTableRecord *rec=NULL;

    acdbOpenObject(rec, owner, AcDb::kForWrite);

    if (rec != NULL)

    {

      AcDbObjectId id;

      rec->appendAcDbEntity(id, pl);

      pl->close();

      rec->close();

    }

    else

    {

      delete pl;

      return false;

    }

    return true;

} // End of drawAPlineWithPropertiesFromBlockRef()





// Get the boundary from a Block Reference given by the blk parameter.
// Transform that boundary to the WCS.
//-------------------------------------------------------------------
static BOOL GetBlockClippingPolyline(ads采用name blk)

{

    BOOL ret = FALSE;

    AcDbBlockReference *ref = NULL;

    AcDbObjectId insId = AcDbObjectId::kNull;

    acdbGetObjectId(insId, blk);

    if (acdbOpenObject(ref, insId, AcDb::kForRead) != Acad::eOk)

      return ret;



    // Find the clipping object (AcDbSpatialFilter) in the ExtDict of the BlockRef

    AcDbObjectId extDicId = ref->extensionDictionary();

    if( extDicId == AcDbObjectId::kNull )

      return ret;

    AcDbDictionary *extDict=NULL, *acadFilterDict=NULL;

    if (acdbOpenObject(extDict, extDicId, AcDb::kForRead) != Acad::eOk)

      return ret;

    Acad::ErrorStatus err = extDict->getAt(采用T("ACAD采用FILTER"), (AcDbObject*&)acadFilterDict, AcDb::kForRead);

    extDict->close();

    if( err != Acad::eOk )

      return ret;

    AcDbSpatialFilter *filter=NULL;

    err = acadFilterDict->getAt(采用T("SPATIAL"), (AcDbObject*&)filter, AcDb::kForRead);

    acadFilterDict->close();

    if ( err != Acad::eOk)

      return ret;



    // Get the transform matrix stored in the XClip boundary

    AcGeMatrix3d xformInBoundary = filter->getClipSpaceToWCSMatrix( xformInBoundary );

    // and the transform of the BlockRef at the time when the Filter was set

    AcGeMatrix3d xformRefOrig = filter->getOriginalInverseBlockXform( xformRefOrig );



    // Get the transform matrix that the current BlockRef has, so, we can find the difference

    //   with the xformRefOrig

    AcGeMatrix3d refMatrix = ref->blockTransform();

    refMatrix = refMatrix.postMultBy(xformRefOrig );



    // Calculate the final transform matrix which applies to the points

    // returned from filter->getDefinition().

    AcGeMatrix3d finalMatrix = refMatrix.postMultBy(xformInBoundary);



    AcGePoint2dArray pts;

    AcGePoint3dArray pts3d;



    AcGeVector3d normal;

    double elevation = 0, frontClip = 0, backClip = 0;

    Adesk::Boolean enabled= false;



    // Get all boundary points

    if (filter->getDefinition(pts, normal, elevation, frontClip, backClip, enabled) == Acad::eOk)

    {

      // Rectanglar boundary

      if (pts.length() == 2)

      {

      AcGePoint2d p1(pts.x, pts.y);

      AcGePoint2d p3(pts.x, pts.y);

      pts.insertAt(1, p1);

      pts.insertAt(3, p3);

      }



      // Transform all points with the transform matrix we calculated

      for(int i=0; i<pts.length(); i++)

      {

      AcGePoint2d pt2d;

      AcGePoint3d pt3d;

      pt2d = pts;

      pt3d = pt2d; pt3d = pt2d; pt3d = 0;

      pt3d.transformBy(finalMatrix);

      pts3d.append(pt3d);

      }

    }



    // Get the new normal and new ECS information for the polyline.

    AcGeVector3d xfnorm = normal.transformBy(finalMatrix);

    AcGeMatrix3d plineECS;



    AcDbPolyline* pline = new AcDbPolyline();

    pline->setNormal(xfnorm);

    pline->getEcs(plineECS);

    delete pline; pline = NULL;

    AcGeMatrix3d plineECSInv = plineECS.inverse();



    double xfelev = 0.0;

    for (int i = 0; i < pts.length(); i++)

    {

      pts.x = pts3d.x;

      pts.y = pts3d.y;



      if (i == 0)

      xfelev = pts3d.z;



      // Should be identical to within roundoff

      assert(fabs(xfelev - pts3d.z) < 1.0e-10);

    }



    // Show the boundary

    drawAPlineWithPropertiesFromBlockRef(pts, ref, xfelev, xfnorm);



    filter->close();

    ref->close();



    return true;

} // End of GetBlockClippingPolyline()






本帖隐藏的内容
// "MClip" test command for the GetBlockClippingPolyline() function.

static void MMRCplusplus采用MClip(void)

{

    ads采用name en;

    AcGePoint3d pt;

    if (acedEntSel(采用T("\nSelect an INSERT clipped by XCLIP command: "), en, asDblArray(pt)) != RTNORM)

    {

      acutPrintf(采用T("\nNothing selected"));

      return;

    }

    assert(GetBlockClippingPolyline(en)==TRUE);

}
页: [1]
查看完整版本: [每日一码] 获取块的XCLIP边界