|
bool COperaBlockCutting::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[i]);
}
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;
}
bool COperaBlockCutting::GetBlockClippingPolyline(ads_name blk, AcGePoint2dArray& pts)
{
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[1].x, pts[0].y);
AcGePoint2d p3(pts[0].x, pts[1].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[i];
pt3d[0] = pt2d[0]; pt3d[1] = pt2d[1]; pt3d[2] = 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[i].x = pts3d[i].x;
pts[i].y = pts3d[i].y;
if (i == 0)
xfelev = pts3d[i].z;
// Should be identical to within roundoff
assert(fabs(xfelev - pts3d[i].z) < 1.0e-10);
}
// Show the boundary
//drawAPlineWithPropertiesFromBlockRef(pts, ref, xfelev, xfnorm);
filter->close();
ref->close();
return true;
}
test:
ads_point pt1;
ads_name ent;
if (acedEntSel(_T("请选择裁剪的块:"), ent, pt1) != RTNORM)
return;
AcGePoint2dArray pts;
if (!GetBlockClippingPolyline(ent, pts))
return; |
|