Message 1 of 1
Spatial proximity testing in Dbx using AcDbIndex AcDbFilter API
Not applicable
04-12-2009
10:53 AM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
I've been trying to find a good way to perform spatial proximity testing in
a Dbx environment. In Arx you can use selection sets but Dbx really seems to
be missing a good way to search for all the entities located within an
AcDbExtents. I had the idea of using AcDbSpatialIndex and AcDbSpatialFilter
to try to do this. But, I'm not sure if I've completely misunderstood how
the AcDbIndex/AcDbFilter API works or if I'm just doing it wrong. I've been
going through the blockorder and partialopen sample projects but there's
still a few things that I'm unsure about. Just to better understand the
AcDbIndex/AcDbFilter API, I wrote a command that asked the user for a
bounding box, then creates an AcDbSpatialFilter so that the only entities
returned from the AcDbCompositeFilteredBlockIterator are those that are
located within the bounding box. For some reason the
AcDbCompositeFilteredBlockIterator returns all the entities and no filtering
seems to be performed.
{code}
static void PsdbNeptune_SFilterTest(void)
{
int indexctl = 0;
VerifyOk(Arx::GetSysVar(ACRX_T("INDEXCTL"), indexctl));
if (indexctl < 2) {
acutPrintf(ACRX_T("\nError: INDEXCTL must be set to 2 or more!"));
return;
}
PsdbArxUiPrPoint firstPointPrompt(ACRX_T("Enter first point"), NULL);
if (firstPointPrompt.go() != PsdbArxUiPrBase::kOk)
return;
AcGePoint3d pt1 = firstPointPrompt.value();
PsdbArxUiPrCorner secondPointPrompt(ACRX_T("Enter second point"), pt1);
if (secondPointPrompt.go() != PsdbArxUiPrBase::kOk)
return;
AcGePoint3d pt2 = secondPointPrompt.value();
AcGeVector3d dcs;
VerifyOk(Arx::GetSysVar(ACRX_T("VIEWDIR"), dcs));
dcs.normalize();
VerifyOk(Arx::CoordTrans(pt1, Arx::kUcs, dcs, pt1));
VerifyOk(Arx::CoordTrans(pt2, Arx::kUcs, dcs, pt2));
AcGePoint2dArray boundingPoints;
boundingPoints.append(AcGePoint2d(min(pt1[0],pt2[0]),
min(pt1[1],pt2[1])));
boundingPoints.append(AcGePoint2d(max(pt1[0],pt2[0]),
max(pt1[1],pt2[1])));
AcDbSpatialFilter spatialFilter;
spatialFilter.setDefinition(boundingPoints, dcs, pt1,
ACDB_INFINITE_XCLIP_DEPTH,
-ACDB_INFINITE_XCLIP_DEPTH, Adesk::kTrue);
PsdbDbxObjectRef currentSpace =
acdbHostApplicationServices()->workingDatabase()->currentSpaceId();
AcDbCompositeFilteredBlockIterator* pBlockIterator =
AcDbCompositeFilteredBlockIterator::newIterator();
if (pBlockIterator == NULL) {
acutPrintf(ACRX_T("\nError: failed to create
AcDbCompositeFilteredBlockIterator!"));
return;
}
AcDbFilter* filterPtrs[1] = { &spatialFilter };
VerifyOk(pBlockIterator->init(filterPtrs, 1, currentSpace));
int entityCount = 0;
while (pBlockIterator->id() != AcDbObjectId::kNull) {
PsdbDbxObjectRef entity = pBlockIterator->id();
entity->list();
entityCount++;
pBlockIterator->next();
}
acutPrintf(ACRX_T("\nTotal entities = %d"), entityCount);
delete pBlockIterator;
}
{code}
Is anyone here familiar with the AcDbIndex/AcDbFilter API? Does anyone know
of a different/better way of performing spatial queries on a AcDbDatabase?
a Dbx environment. In Arx you can use selection sets but Dbx really seems to
be missing a good way to search for all the entities located within an
AcDbExtents. I had the idea of using AcDbSpatialIndex and AcDbSpatialFilter
to try to do this. But, I'm not sure if I've completely misunderstood how
the AcDbIndex/AcDbFilter API works or if I'm just doing it wrong. I've been
going through the blockorder and partialopen sample projects but there's
still a few things that I'm unsure about. Just to better understand the
AcDbIndex/AcDbFilter API, I wrote a command that asked the user for a
bounding box, then creates an AcDbSpatialFilter so that the only entities
returned from the AcDbCompositeFilteredBlockIterator are those that are
located within the bounding box. For some reason the
AcDbCompositeFilteredBlockIterator returns all the entities and no filtering
seems to be performed.
{code}
static void PsdbNeptune_SFilterTest(void)
{
int indexctl = 0;
VerifyOk(Arx::GetSysVar(ACRX_T("INDEXCTL"), indexctl));
if (indexctl < 2) {
acutPrintf(ACRX_T("\nError: INDEXCTL must be set to 2 or more!"));
return;
}
PsdbArxUiPrPoint firstPointPrompt(ACRX_T("Enter first point"), NULL);
if (firstPointPrompt.go() != PsdbArxUiPrBase::kOk)
return;
AcGePoint3d pt1 = firstPointPrompt.value();
PsdbArxUiPrCorner secondPointPrompt(ACRX_T("Enter second point"), pt1);
if (secondPointPrompt.go() != PsdbArxUiPrBase::kOk)
return;
AcGePoint3d pt2 = secondPointPrompt.value();
AcGeVector3d dcs;
VerifyOk(Arx::GetSysVar(ACRX_T("VIEWDIR"), dcs));
dcs.normalize();
VerifyOk(Arx::CoordTrans(pt1, Arx::kUcs, dcs, pt1));
VerifyOk(Arx::CoordTrans(pt2, Arx::kUcs, dcs, pt2));
AcGePoint2dArray boundingPoints;
boundingPoints.append(AcGePoint2d(min(pt1[0],pt2[0]),
min(pt1[1],pt2[1])));
boundingPoints.append(AcGePoint2d(max(pt1[0],pt2[0]),
max(pt1[1],pt2[1])));
AcDbSpatialFilter spatialFilter;
spatialFilter.setDefinition(boundingPoints, dcs, pt1
ACDB_INFINITE_XCLIP_DEPTH,
-ACDB_INFINITE_XCLIP_DEPTH, Adesk::kTrue);
PsdbDbxObjectRef
acdbHostApplicationServices()->workingDatabase()->currentSpaceId();
AcDbCompositeFilteredBlockIterator* pBlockIterator =
AcDbCompositeFilteredBlockIterator::newIterator();
if (pBlockIterator == NULL) {
acutPrintf(ACRX_T("\nError: failed to create
AcDbCompositeFilteredBlockIterator!"));
return;
}
AcDbFilter* filterPtrs[1] = { &spatialFilter };
VerifyOk(pBlockIterator->init(filterPtrs, 1, currentSpace));
int entityCount = 0;
while (pBlockIterator->id() != AcDbObjectId::kNull) {
PsdbDbxObjectRef
entity->list();
entityCount++;
pBlockIterator->next();
}
acutPrintf(ACRX_T("\nTotal entities = %d"), entityCount);
delete pBlockIterator;
}
{code}
Is anyone here familiar with the AcDbIndex/AcDbFilter API? Does anyone know
of a different/better way of performing spatial queries on a AcDbDatabase?