|
// get the view port information - see parameter list
static bool GetActiveViewPortInfo (AcDbDatabase *pDb, ads_real &height, ads_real &width,
AcGePoint3d &target, AcGeVector3d &viewDir,
ads_real &viewTwist,
AcDbObjectId ¤tVsId,
bool getViewCenter)
{
// if not ok
if (pDb == NULL)
return false;
// get the current document associated with the PDb database and set it current
AcApDocument *pDoc = acDocManager->document(pDb);
acDocManager->setCurDocument(pDoc);
acDocManager->lockDocument(pDoc);
// make sure the active view port is uptodate
acedVports2VportTableRecords();
// open the view port records
AcDbViewportTablePointer pVTable(pDb->viewportTableId(), AcDb::kForRead);
// if we opened them ok
if (pVTable.openStatus() == Acad::eOk)
{
AcDbViewportTableRecord *pViewPortRec = NULL;
Acad::ErrorStatus es = pVTable->getAt (_T("*Active"), pViewPortRec, AcDb::kForRead);
if (es == Acad::eOk)
{
// get the height of the view
height = pViewPortRec->height ();
// get the width
width = pViewPortRec->width ();
// if the user wants the center of the viewport used
if (getViewCenter == true)
{
struct resbuf rb;
memset (&rb, 0, sizeof (struct resbuf));
// get the system var VIEWCTR
acedGetVar (_T("VIEWCTR"), &rb);
// set that as the target
target = AcGePoint3d (rb.resval.rpoint[X], rb.resval.rpoint[Y], rb.resval.rpoint[Z]);
}
// we want the viewport's camera target setting
else
{
// get the target of the view
target = pViewPortRec->target ();
}
// get the view direction
viewDir = pViewPortRec->viewDirection ();
// get the view twist of the viewport
viewTwist = pViewPortRec->viewTwist ();
// return the current Visual Style
currentVsId = pViewPortRec->visualStyle();
}
// close after use
pViewPortRec->close();
}
acDocManager->unlockDocument(pDoc);
// now restore the original document
acDocManager->setCurDocument(acDocManager->mdiActiveDocument());
return (true);
}
//////////////////////////////////////////////////////////////////////////
// set the passed AcGsView to the *Active* AutoCAD AcDbDatabase view
static AcDbObjectId SetViewTo(AcGsView *pView, AcDbDatabase *pDb, AcGeMatrix3d& viewMat)
{
// we are going to set the view to the current view of the drawing
// The overall approach is to calculate the extents of the database in the coordinate system of the view
// Calculate the extents in WCS
AcGePoint3d extMax = pDb->extmax();
AcGePoint3d extMin = pDb->extmin();
// initialize it with sensible numbers - even if there is no entity
if (extMin.distanceTo(extMax) > 1e20)
{
extMin.set(0, 0, 0);
extMax.set(100, 100, 100);
}
// get the view port information - see parameter list
ads_real height = 0.0, width = 0.0, viewTwist = 0.0;
AcGePoint3d targetView;
AcGeVector3d viewDir;
AcDbObjectId currentVsId;
GetActiveViewPortInfo (pDb, height, width, targetView, viewDir, viewTwist, currentVsId, true);
// we are only interested in the directions of the view, not the sizes, so we normalise.
viewDir = viewDir.normal();
//**********************************************
// Our view coordinate space consists of z direction
// get a perp vector off the z direction
// Make sure its normalised
AcGeVector3d viewXDir = viewDir.perpVector ().normal();
// correct the x angle by applying the twist
viewXDir = viewXDir.rotateBy (viewTwist, -viewDir);
// now we can work out y, this is of course perp to the x and z directions. No need to normalise this,
// as we know that x and z are of unit length, and perpendicular, so their cross product must be on unit length
AcGeVector3d viewYDir = viewDir.crossProduct (viewXDir);
// find a nice point around which to transform the view. We'll use the same point as the center of the view.
AcGePoint3d boxCenter = extMin + 0.5 * ( extMax - extMin );
//**********************************************
// create a transform from WCS to View space
// this represents the transformation from WCS to the view space. (Actually not quite since
// we are keeping the fixed point as the center of the box for convenience )
viewMat = AcGeMatrix3d::alignCoordSys (boxCenter, AcGeVector3d::kXAxis, AcGeVector3d::kYAxis, AcGeVector3d::kZAxis,
boxCenter, viewXDir, viewYDir, viewDir).inverse();
AcDbExtents wcsExtents(extMin, extMax);
// now we have the view Extents
AcDbExtents viewExtents = wcsExtents;
// transforms the extents in WCS->view space
viewExtents.transformBy (viewMat);
//**********************************************
// get the extents of the AutoCAD view
double xMax = fabs(viewExtents.maxPoint ().x - viewExtents.minPoint ().x);
double yMax = fabs(viewExtents.maxPoint ().y - viewExtents.minPoint ().y);
//**********************************************
// setup the view
AcGePoint3d eye = boxCenter + viewDir;
// upvector
pView->setView(eye, boxCenter, viewYDir, xMax, yMax);
// update the gsView
refreshView(pView);
return currentVsId;
}
static void refreshView(AcGsView *pView)
{
if (pView != NULL)
{
pView->invalidate();
pView->update();
}
}
static Acad::ErrorStatus CreateAnonBlock(AcArray<AcDbObjectId> &selectedIds, AcDbObjectId &idAnonBlock)
{
Acad::ErrorStatus es;
AcDbBlockTable *pBlockTable = NULL;
AcDbDatabase *pDb = acdbHostApplicationServices()->workingDatabase();
AcDbBlockTableRecord *pAnonBlock = NULL;
if( idAnonBlock == AcDbObjectId::kNull )
{
if ((es = pDb->getBlockTable(pBlockTable, AcDb::kForWrite))
!= Acad::eOk)
{
acutPrintf(L"Could not open block table.\n");
return es;
}
AcDbBlockTableRecord* pAnonBlock = new AcDbBlockTableRecord;
if(!pAnonBlock)
{
acutPrintf(L"Could not create new block table record.\n");
return Acad::eNullObjectPointer;
}
if((es = pAnonBlock->setName(_T("*U"))) != Acad::eOk)
{
acutPrintf(L"Could not name anonymous block.\n");
return es;
}
if((es = pBlockTable->add(idAnonBlock, pAnonBlock)) != Acad::eOk)
{
acutPrintf(L"Could not add anonymous block to block table.\n");
return es;
}
if((es = pBlockTable->close()) != Acad::eOk)
{
acutPrintf(L"Could not close block table.\n");
return es;
}
if((es = pAnonBlock->close()) != Acad::eOk)
{
acutPrintf(L"Could not close block table record.\n");
return es;
}
}
AcDbObjectPointer<AcDbBlockTableRecord> pAnonBlockObjectPtr(idAnonBlock, AcDb::kForWrite);
if((es = pAnonBlockObjectPtr.openStatus()) != Acad::eOk)
{
acutPrintf(L"Could not open anonymous block.\n");
return es;
}
for(int cnt = 0; cnt < selectedIds.length(); cnt++)
{
AcDbObjectId entId = selectedIds.at(cnt);
AcDbObjectPointer<AcDbEntity> pEntity(entId, AcDb::kForRead);
if(Acad::eOk == pEntity.openStatus())
{
AcDbEntity *pCloneEnt = (AcDbEntity *) pEntity->clone();
if((es = pAnonBlockObjectPtr->appendAcDbEntity(pCloneEnt)) != Acad::eOk)
{
acutPrintf(L"Could not append entity to anonymous block.\n");
return es;
}
if((es = pCloneEnt->close()) != Acad::eOk)
{
acutPrintf(L"Could not close entity.\n");
return es;
}
}
}
return Acad::eOk;
}
static bool CreateAtilImage(AcGsView *pView,
int width, int height,
int colorDepth, int paletteSize,
ACHAR *pFileName)
{
bool done = false;
AcGsDCRect screenRect(0,width,0, height);
// get the screen rect from the gsview
pView->getViewport(screenRect);
try
{
// we want colorDepth to be either 24 or 32
if (colorDepth < 24)
colorDepth = 24;
if (colorDepth > 24)
colorDepth = 32;
// create rbgmodel 32 bit true color
Atil::RgbModel rgbModel(colorDepth);
Atil::ImagePixel initialColor(rgbModel.pixelType());
// create the Atil image on the stack
Atil::Image imgSource(Atil::Size(width, height), &rgbModel, initialColor);
// get a snapshot of the GsView
pView->getSnapShot(&imgSource, screenRect.m_min);
// if ok
if (imgSource.isValid())
{
Atil::RowProviderInterface *pPipe = imgSource.read(imgSource.size(), Atil::Offset(0,0),Atil::kBottomUpLeftRight);
if(pPipe != NULL)
{
TCHAR drive[_MAX_DRIVE];
TCHAR dir[_MAX_DIR];
TCHAR fname[_MAX_FNAME];
TCHAR ext[_MAX_EXT];
// find out what extension we have
_tsplitpath_s(pFileName, drive, dir, fname, ext);
Atil::ImageFormatCodec *pCodec = NULL;
// create the codec depending on what the user chose
if (CString(ext) == _T(".jpg"))
pCodec = new JfifFormatCodec();
else if (CString(ext) == _T(".png"))
pCodec = new PngFormatCodec();
else if (CString(ext) == _T(".tif"))
pCodec = new TiffFormatCodec();
else if (CString(ext) == _T(".bmp"))
pCodec = new BmpFormatCodec();
// if we have a new codec
if (pCodec != NULL)
{
// and it is compatible
if (Atil::FileWriteDescriptor::isCompatibleFormatCodec(pCodec, &(pPipe->dataModel()), pPipe->size()))
{
// create a new file output object
Atil::FileWriteDescriptor fileWriter(pCodec);
Atil::FileSpecifier fs(Atil::StringBuffer((lstrlen(pFileName) + 1) * sizeof(TCHAR),
(const Atil::Byte *)pFileName, Atil::StringBuffer::kUTF_16), Atil::FileSpecifier::kFilePath);
// if the file already exists
// we better delete it because setFileSpecifier will fail otherwise
_tremove(pFileName);
if (fileWriter.setFileSpecifier(fs))
{
fileWriter.createImageFrame(pPipe->dataModel(), pPipe->size());
// At any rate you want to fetch the property from the write file descriptor then alter it and set it in…
Atil::FormatCodecPropertyInterface *pProp = fileWriter.getProperty(Atil::FormatCodecPropertyInterface::kCompression);
if (pProp != NULL)
{
if (CString(ext) == _T(".jpg"))
{
Atil::FormatCodecIntProperty *pComp = dynamic_cast<Atil::FormatCodecIntProperty*>(pProp);
if (pComp != NULL)
{
int min=0, max=0;
pComp->getPropertyLimits(min, max);
// set the quality to 90%
pComp->setValue((int)((double)max * .9));
// apply any changes we have made
fileWriter.setProperty(pComp);
}
}
else if (CString(ext) == _T(".png"))
{
PngCompression *pComp = dynamic_cast<PngCompression*>(pProp);
if (pComp != NULL)
{
// Why not compress all we can?
pComp->selectCompression(PngCompressionType::kHigh);
// apply any changes we have made
fileWriter.setProperty(pComp);
}
}
else if (CString(ext) == _T(".tif"))
{
// All image types can be compressed using kNone, kLZW, and kDeflate.
// If it is 8 bit (palette'd or gray scale) the kPackbits is available.
// If it is 1 bit (bi-tonal) then the CCITT family of kCCITT_* compression of which the kCCITT_FAX4 is the best are available.
// If it is 24 bit (3 channel RGB) then kJPEG is available which will use JPEG DCT compression in the TIFF file.
TiffCompression *pComp = dynamic_cast<TiffCompression*>(pProp);
if (pComp != NULL)
{
// G4 is only valid for 1 bit images.
if (pComp->selectCompression(TiffCompressionType::kCCITT_FAX4) == false)
{
// So if that fails, resort to LZW now that it is patent free
if (pComp->selectCompression(TiffCompressionType::kLZW) == false)
{
// If that fails (and is shouldn’t, be) then set none.
pComp->selectCompression(TiffCompressionType::kNone);
}
}
// apply any changes we have made
fileWriter.setProperty(pComp);
}
}
// clean up
delete pProp;
pProp = NULL;
}
}
// be sure that the format has all the information it needs to write the file.
// In ATIL every property is required to have a valid default value.
// So if a certain property is REQUIRED by the codec to save the file, then it is safe
// and proper to simply loop over all the possible properties, enquire if it is required
// and simply set it with it’s default value
Atil::FormatCodecPropertySetIterator* pPropsIter = fileWriter.newPropertySetIterator();
// if ok
if (pPropsIter)
{
for (pPropsIter->start(); !pPropsIter->endOfList(); pPropsIter->step())
{
Atil::FormatCodecPropertyInterface* pProp = pPropsIter->openProperty();
if (pProp->isRequired())
{
fileWriter.setProperty(pProp);
}
pPropsIter->closeProperty();
}
delete pPropsIter;
}
// ok - ready to write it
fileWriter.writeImageFrame(pPipe);
done = true;
}
}
delete pCodec;
}
}
}
catch ( Atil::ATILException e )
{
const Atil::StringBuffer *pStringMsg =e.getMessage();
}
return done;
}
static void AdskMyTestTSSARX()
{
AcArray<AcDbObjectId> selectedIds;
while(true)
{
ads_name ename;
ads_point pickPt;
acedInitGet(NULL, NULL);
int rc = acedEntSel(_T("\nSelect Entity"), ename, pickPt);
if(rc == RTCAN || rc == RTERROR)
break;
if(rc == RTNORM)
{
AcDbObjectId entId;
acdbGetObjectId(entId, ename);
selectedIds.append(entId);
}
}
if(selectedIds.length() == 0)
return;
AcDbObjectId annonBlockId = AcDbObjectId::kNull;
CreateAnonBlock(selectedIds, annonBlockId);
AcGsManager *gsManager = acgsGetGsManager();
struct resbuf screensize;
acedGetVar(_T("SCREENSIZE"), &screensize);
double screenSizeX = screensize.resval.rpoint[0];
double screenSizeY = screensize.resval.rpoint[1];
int width = screenSizeX;
int height = screenSizeY;
AcGsDevice *offDevice = gsManager->createAutoCADOffScreenDevice();
offDevice->onSize(width, height);
AcGsClassFactory *pGSFactory = gsManager->getGSClassFactory();
AcGsView *pView = pGSFactory->createView();
offDevice->add(pView);
offDevice->update();
AcGsModel *pModel = gsManager->createAutoCADModel();
AcDbBlockTableRecordPointer annonblk(annonBlockId, AcDb::kForRead);
if (annonblk.openStatus() == Acad::eOk)
{
pView->add(annonblk, pModel);
AcDbExtents extents;
extents.addBlockExt(annonblk);
_extMin = extents.minPoint();
_extMax = extents.maxPoint();
AcDbDatabase *pDb = acdbHostApplicationServices()->workingDatabase();
AcGeMatrix3d viewMat;
SetViewTo(pView, pDb, viewMat);
}
refreshView(pView);
AcGsDCRect screenRect(0,width,0, height);
pView->getViewport(screenRect);
CWnd *gsViewWnd = acedGetAcadDwgView();
if (gsViewWnd != NULL)
{
CRect sizeRect;
gsViewWnd->GetClientRect(&sizeRect);
int colorDepth = 32;
int paletteSize = 0;
CreateAtilImage(pView, sizeRect.Width(), sizeRect.Height(), colorDepth, paletteSize, ACRX_T("C:\\Temp\\Test_Arx.bmp"));
}
pView->eraseAll();
offDevice->erase(pView);
pGSFactory->deleteView(pView);
pGSFactory->deleteModel(pModel);
}
};
AcGePoint3d CMyTest1App::_extMin;
AcGePoint3d CMyTest1App::_extMax; |
|