Kapalı Çizgilerin Ağırlık Merkezini İşaretleme
AutoCAD ortamında kapalı bir nesnenin ağırlık merkezini bulmak istediğimizde, önce nesneyi bir bölgeye (region) çevirir, daha sonra da MASSPROP (Tools->Inquiry->Region/Mass Properties) komutuyla bu bölgenin özelliklerini komut satırında listeleriz. Aşağıda kaynak kodunu verdiğim FindCentroid(…) fonksiyonu, AcDbPolyline, AcDb2dPolyline, AcDb3dPolyline (kapalı olmaları koşuluyla) ve AcDbCircle nesnelerini, MASSPROP komutunu kullanmanıza gerek kalmaksızın bir bölgeye çevirip ağırlık merkezine bir nokta yerleştiriyor.
void Centroid::FindCentroid(bool drawRegion, ACHAR *regionLayer, ACHAR *pointLayer)
{
ads_name objName;
ads_point pickpt;
Acad::ErrorStatus es;
AcDbEntity* pEntity = NULL;
AcDbObjectId objId = AcDbObjectId::kNull;
// AcDbRegion getAreaProp(...) metodu için gerekli değişkenler
AcDbVoidPtrArray curveSegs, regions;
double perimeter, area;
AcGePoint3d origin;
AcGeVector3d xAxis, yAxis;
AcGePoint2d centroid;
double momInertia[2], prodInertia, prinMoments[2], radiiGyration[2];
AcGeVector2d prinAxes[2];
AcGePoint2d extentsLow, extentsHigh;
AcGePlane plane;
// Ağırlık merkezi araştırılacak nesnenin seçilmesi
if(acedEntSel(_T("\nSelect object: "), objName, pickpt) != RTNORM)
{
acutPrintf(_T("\nNothing selected."));
return;
} else
{
// Nesne isminin elde edilmesi
if(acdbGetObjectId(objId, objName) != Acad::eOk)
return;
// Nesnenin okuma amaçlı açılması
es = acdbOpenAcDbEntity(pEntity, objId, AcDb::kForRead);
if (es == Acad::eOk)
{
// Nesnenin istenilen tipte olup olmadığının araştırılması
if (pEntity->isKindOf(AcDbPolyline::desc())
|| pEntity->isKindOf(AcDb3dPolyline::desc())
|| pEntity->isKindOf(AcDb2dPolyline::desc())
|| pEntity->isKindOf(AcDbCircle::desc())
)
{
curveSegs.append(static_cast<void*>(pEntity));
}
else
{
pEntity->close();
acutPrintf(_T("\nError: Invalid object."));
return;
}
}
else
{
acutPrintf(_T("\nError: Can not obtain object."));
return;
}
es = AcDbRegion::createFromCurves(curveSegs, regions);
if (es != Acad::eOk)
{
pEntity->close();
acutPrintf(_T("\nError: Select a closed line."));
return;
}
else
{
// AcDbRegion'un oluşturulması
AcDbRegion *pRegion;
pRegion = static_cast<AcDbRegion*>(regions[0]);
pRegion->getPlane(plane);
plane.getCoordSystem(origin, xAxis, yAxis);
origin.x = 0.0;
origin.y = 0.0;
// AcDbRegion alan özelliklerinin elde edilmesi
es = pRegion->getAreaProp(origin, xAxis, yAxis, perimeter, area, centroid, momInertia,
prodInertia, prinMoments, prinAxes, radiiGyration, extentsLow, extentsHigh);
// Blok tablosuna eklenecek nesneler için AcDbBlockTableRecord işaretçisine erişim
AcDbBlockTable *pBlockTable;
acdbHostApplicationServices()->workingDatabase()->getSymbolTable(pBlockTable, AcDb::kForRead);
AcDbBlockTableRecord *pBlockTableRecord;
pBlockTable->getAt(ACDB_MODEL_SPACE, pBlockTableRecord, AcDb::kForWrite);
pBlockTable->close();
// AcDbRegion nesnesinin blok tablosuna eklenmesi
if(drawRegion)
{
AcDbObjectId regionId;
pRegion->setLayer(regionLayer);
es = pBlockTableRecord->appendAcDbEntity(regionId, pRegion);
}
// Ağırlık merkezini işaretlemek için AcDbPoint
// oluşturulması ve blok tablosuna eklenmesi
AcDbPoint *pPnt = new AcDbPoint;
pPnt->setDatabaseDefaults();
pPnt->setPosition(AcGePoint3d::AcGePoint3d(centroid.x,centroid.y,0.0));
pPnt->setLayer(pointLayer);
AcDbObjectId pointId;
pBlockTableRecord->appendAcDbEntity(pointId, pPnt);
// Blok tablo kaydının kapatılması
pBlockTableRecord->close();
// Nesnelerin kapatılması
pPnt->close();
pRegion->close();
pEntity->close();
if(es == Acad::eOk)
{
acutPrintf(_T("\nCentroid (X, Y, Z) = (%.4f, %.4f, %.4f)"), centroid.x, centroid.y, origin.z);
acutPrintf(_T("\nArea = %.4f | Perimeter = %.4f"), area, perimeter);
}
// Görünümün güncellemesi
actrTransactionManager->flushGraphics();
acedUpdateDisplay();
}
}
return;
}
FindCentroid(…) fonksiyonunun kullanımı için hazırladığım diyalog kutusuna ait MarkCentroidDialog.cpp dosyası ise aşağıdaki gibi:
//-----------------------------------------------------------------------------
//----- MarkCentroidDialog.cpp : Implementation of MarkCentroidDialog
//-----------------------------------------------------------------------------
#include "StdAfx.h"
#include "resource.h"
#include "MarkCentroidDialog.h"
#include "Centroid.h"
//-----------------------------------------------------------------------------
IMPLEMENT_DYNAMIC (MarkCentroidDialog, CAcUiDialog)
BEGIN_MESSAGE_MAP(MarkCentroidDialog, CAcUiDialog)
ON_MESSAGE(WM_ACAD_KEEPFOCUS, OnAcadKeepFocus)
ON_BN_CLICKED(IDC_BUTTON_SELECT_OBJECT, MarkCentroidDialog::OnClickedButtonSelectObject)
ON_BN_CLICKED(IDC_CHECK_DRAW_REGION, MarkCentroidDialog::OnClickedCheckDrawRegion)
END_MESSAGE_MAP()
//-----------------------------------------------------------------------------
MarkCentroidDialog::MarkCentroidDialog (CWnd *pParent /*=NULL*/, HINSTANCE hInstance /*=NULL*/) : CAcUiDialog (MarkCentroidDialog::IDD, pParent, hInstance) {
}
//-----------------------------------------------------------------------------
void MarkCentroidDialog::DoDataExchange (CDataExchange *pDX) {
CAcUiDialog::DoDataExchange (pDX) ;
DDX_Control(pDX, IDC_BUTTON_SELECT_OBJECT, m_btnSelect);
DDX_Control(pDX, IDC_CHECK_DRAW_REGION, m_drawRegion);
DDX_Control(pDX, IDC_COMBO_POINT_LAYER, m_pntLayerList);
DDX_Control(pDX, IDC_COMBO_REGION_LAYER, m_regionLayerList);
}
//-----------------------------------------------------------------------------
//----- Needed for modeless dialogs to keep focus.
//----- Return FALSE to not keep the focus, return TRUE to keep the focus
LRESULT MarkCentroidDialog::OnAcadKeepFocus (WPARAM, LPARAM) {
return (TRUE) ;
}
BOOL MarkCentroidDialog::OnInitDialog()
{
SetDialogName(_T("PolylineProperties:MarkCentroidDialog"));
CAcUiDialog::OnInitDialog();
m_btnSelect.AutoLoad();
GetLayerNames();
GetData();
return TRUE; // return TRUE unless you set the focus to a control
}
void MarkCentroidDialog::GetLayerNames()
{
AcDbLayerTable *pLayerTable;
acdbHostApplicationServices()->workingDatabase()->getSymbolTable(pLayerTable, AcDb::kForRead);
const ACHAR *pName;
AcDbLayerTableIterator *pItr;
if (pLayerTable->newIterator(pItr) == Acad::eOk)
{
while (!pItr->done())
{
AcDbLayerTableRecord *pRecord;
if (pItr->getRecord(pRecord, AcDb::kForRead) == Acad::eOk)
{
pRecord->getName(pName);
m_pntLayerList.InsertString(-1, pName);
m_regionLayerList.InsertString(-1, pName);
pRecord->close();
}
pItr->step();
}
}
pLayerTable->close();
}
void MarkCentroidDialog::OnClickedButtonSelectObject()
{
int nIndexPoint = m_pntLayerList.GetCurSel();
int nIndexRegion = m_regionLayerList.GetCurSel();
CString regionLayer = _T("");
CString pointLayer= _T("");
m_regionLayerList.GetLBText(nIndexRegion, regionLayer);
m_pntLayerList.GetLBText(nIndexPoint, pointLayer);
BeginEditorCommand();
Centroid cen;
cen.FindCentroid(m_drawRegion.GetCheck() ? true:false,
regionLayer.GetBuffer(regionLayer.GetLength()),
pointLayer.GetBuffer(pointLayer.GetLength()));
CompleteEditorCommand();
}
void MarkCentroidDialog::OnOK()
{
CAcUiDialog::OnOK();
SetData();
}
void MarkCentroidDialog::SetData()
{
int nIndexPoint = m_pntLayerList.GetCurSel();
int nIndexRegion = m_regionLayerList.GetCurSel();
CString regionLayer = _T("");
CString pointLayer= _T("");
m_regionLayerList.GetLBText(nIndexRegion, regionLayer);
m_pntLayerList.GetLBText(nIndexPoint, pointLayer);
SetDialogData(_T("REGIONLAYER"), regionLayer.GetBuffer(regionLayer.GetLength()));
SetDialogData(_T("POINTLAYER"), pointLayer.GetBuffer(pointLayer.GetLength()));
SetDialogData(_T("DRAWREGION"), m_drawRegion.GetCheck() ? 1:0);
}
void MarkCentroidDialog::GetData(void)
{
CString regionLayer;
if (GetDialogData(_T("REGIONLAYER"), regionLayer))
{
int nIndexRegion = m_regionLayerList.FindString(-1, regionLayer);
if (nIndexRegion == CB_ERR)
{
m_regionLayerList.SetCurSel(0);
}
else
{
m_regionLayerList.SetCurSel(nIndexRegion);
}
}
CString pointLayer;
if (GetDialogData(_T("POINTLAYER"), pointLayer))
{
int nIndexPoint = m_pntLayerList.FindString(-1, pointLayer);
if (nIndexPoint == CB_ERR)
{
m_pntLayerList.SetCurSel(0);
}
else
{
m_pntLayerList.SetCurSel(nIndexPoint);
}
}
DWORD drawRegion;
if (GetDialogData(_T("DRAWREGION"), drawRegion))
{
m_drawRegion.SetCheck(drawRegion);
if(drawRegion == 1)
m_regionLayerList.EnableWindow(true);
else
m_regionLayerList.EnableWindow(false);
}
else
{
m_drawRegion.SetCheck(0);
m_regionLayerList.EnableWindow(false);
}
}
void MarkCentroidDialog::OnClickedCheckDrawRegion()
{
if((m_drawRegion.GetCheck() ? true:false) == true)
m_regionLayerList.EnableWindow(true);
else
m_regionLayerList.EnableWindow(false);
}
Yorum yapın