On a different platform, I created a "Show Area" tool that takes a point input, finds the boundaries around it, creates a temporary hatch, gets the area from that hatch and displays it for the user (deleting the hatch afterwards).
I can see that I could perhaps use HATCH or BOUNDARY, and they will give me the areas I want. So to quickly display the area of any enclosed space, I could use a similar approach to avoid 'polluting' the drawing with random hatches or polylines (i.e., use them to get the area then delete them).
Just to be sure I'm not missing a trick though - is there a better approach?
Aha! acedTraceBoundary!
However, from the docs:
So this very nearly does what I want - but can acedTraceBoundary be made to recognise splines? How does BOUNDARY do it?
BPOLY or -BOUNDARY can return Polyline or Region types.
For the closed areas made of Spline, it returns a Region, you might need to convert Spline to Polyline.
HTH
As I said earlier in the thread - I know how BOUNDARY works, but I'm trying to automate it. I could send command options to -BOUNDARY, but the region thing requires an extra response to accept, making the automation tricky. I would then have to find the just-added boundary, get it's area then remove the extraneous entity(s).
acedTraceBoundary appears to be as near an API equivalent of the BOUNDARY command as exists, but doesn't work the same way (i.e., it doesn't recognise splines).
What I'm asking (the AutoDesk guys, I guess) - is there a simple API method of replicating the initial function of BOUNDARY? (that is, the part that finds the boundary, including splines - I don't actually need (or want) to create the polys or regions)
I do not post here that often, so did not elaborate at all on my previous post.
I just had the time to do a test, using C# (have been a long time that do not use ARX), anyway.
TraceBoundary works for me on enclosed areas that include Splines, so on an example made with lines, that form an U shape on one of the ends the edge it is a spline, and inside for islands a rectangle and a circle.
If I use TraceBoundary, after the internal point, and true for island detection, returns 3 items, I just go and loop into each of these objects, returns a Region and two Polylines.
For the Region, I use Brep (AcBrBrep) and extract the area with brep.GetSurfaceArea().
For the other two Polylines, I convert them to Curve, then check if are curve.Closed, then I extract their area with curve.Area.
I can do this without adding to the database any of the items.
Also, to me the larger area will be the outer one, any other one returned will be islands, or maybe you can test if the internal point is not inside of any of these islands, but guess it is overhead.
HTH.-
Interesting - that's definitely not the case with CPP ObjectArx. This for example:
AcGePoint3d startpt;
acedInitGet(NULL, NULL);
AcArray<int> viewportNumbers;
AcGiTransientManager* pTransientManager = acgiGetTransientManager();
while (acedGetPoint(NULL, _T("\nSelect point in area: "), (double*)(&startpt)) == RTNORM)
{
bool b = pTransientManager->eraseTransients(kAcGiHighlight, 0, viewportNumbers);
acedUpdateDisplay();
AcDbVoidPtrArray Boundaries;
bool detectIslands = Adesk::kTrue;
es = acedTraceBoundary(startpt, detectIslands, Boundaries);
if (es == Acad::eOk)
{
double dAreaTotal = 0.0L, dMaxArea = 0.0L, dArea = 0.0L;
AcDbPolyline* poly = NULL;
// Subtract the islands
for (int i = 0; i < Boundaries.length(); i++)
{
AcDbEntity *pEnt = static_cast<AcDbEntity *>(Boundaries[i]);
b = pTransientManager->addTransient(pEnt, kAcGiHighlight, 0, viewportNumbers);
acedUpdateDisplay();
poly = (AcDbPolyline*)Boundaries[i];
es = poly->getArea(dArea);
dAreaTotal += dArea;
if (dArea > dMaxArea)
{
dMaxArea = dArea;
}
}
acutPrintf(_T(" %.3f"), dMaxArea - (dAreaTotal - dMaxArea));
}
acedInitGet(NULL, NULL);
}
bool b = pTransientManager->eraseTransients(kAcGiHighlight, 0, viewportNumbers);
Doesn't detect splines, ellipses or elliptical arcs, but is fine with lines, normal arcs and arced polyline segments.
So it seems like the interface and the C# function don't use acedTraceBoundary. We are just theorising here, hence the need for some weigh-in from the AutoDesk peeps.
I give it a try also with ARX, I am rusty now, last time was 10+ years ago, but the code below works for me (it is just something in progress), was curios too.
Works with a closed area formed with splines, ellipse, and normal lines too, and island entities with circle and rectangle.
static void MyGroupTest1() {
AcGePoint3d seedPt;
acedGetPoint(NULL, ACRX_T("\nSelect internal point: "), asDblArray(seedPt));
AcDbVoidPtrArray Boundaries;
bool detectIslands = Adesk::kTrue;
if (acedTraceBoundary(seedPt, detectIslands, Boundaries) == Acad::eOk) {
AcDbBlockTableRecordPointer pCurSpace(acdbCurDwg()->currentSpaceId(), AcDb::kForWrite);
vector<double> areas;
if (pCurSpace.openStatus() == Acad::eOk) {
for (int i = 0; i < Boundaries.length(); i++) {
AcDbCurve *pCurve = static_cast<AcDbCurve *>(Boundaries[i]);
if (pCurve->isKindOf(AcDbRegion::desc()))
{
AcDbRegion *pRegion = static_cast<AcDbRegion *>(Boundaries[i]);;
AcBrBrep* pBrep = new AcBrBrep();
if (AcBr::eOk == pBrep->set(*pRegion))
{
double area = 0.0f;
if (AcBr::eOk == pBrep->getSurfaceArea(area))
{
areas.push_back(area);
}
}
}
else
{
double polyArea = 0.0f;
if (Acad::eOk == pCurve->getArea(polyArea))
{
areas.push_back(polyArea);
}
}
pCurSpace->appendAcDbEntity(pCurve);
pCurve->close();
}
}
}
}
OK - I'm not using that Brep stuff, and it's not recognised by my build environment. Some investigation required!
Try to first use the traceBoundary normally, with the AcDbCurve objects, to double check works by adding the new boundaries (this function will return Polylines and Regions, that's why the use of Brep Api for the region(s)).
For Brep, I end up adding these two libs under Linker/Input: acgex22.lib;acbr22.lib - these are under Utils/Brep
End up also adding all these includes in the .cpp entrypoint:
#include <brbrep.h>
#include <brbetrav.h>
#include <bredge.h>
#include "brgbl.h"
#include "brvtx.h"
#include "gegbl.h"
#include "brprops.h"
#include "brface.h"
#include "brtrav.h"
#include "brbetrav.h"
#include "rxobject.h"
#include "rxboiler.h"
#include "brbftrav.h"
#include "brbvtrav.h"
#include "brvetrav.h"
#include "brvltrav.h"
#include "brloop.h"
#include "breltrav.h"
#include "brfltrav.h"
#include "brletrav.h"
#include "gesurf.h"
#include <ol_errno.h>
#include <brgbl.h>
Just to make it work for me, I know there can be the arx wizard that can allow this: #define _BREP_SUPPORT_
HTH!
I must be missing something - I've tried using curves and with BREP support, I just can't get it to recognise splines.
With four lines and a spline:
I only ever get this polyline boundary returned, no regions.
I have no idea why this should be the case - but it was the transaction that made the difference. If I don't put my code inside a transaction, it detects the spline and returns regions.
Thanks for you input - at least I now have some workable code!
EDIT: Well mostly working! I find my transient highlighting (as above) doesn't work / interact with ellipses or elliptical arcs (though the regions involved there still give the correct area).
Hi @Kyudos
I have gone through the discussion.
Should I understand your question as acedTraceBoundary doesn't work with Ellipses, Elliptical Arcs and Splines?
Let me know if you need help on this.
@moogalm acedTraceBoundary doesn't seem to work with Ellipses, Elliptical Arcs and Splines when used inside a transaction.
If this is intentional (although I can't see why it would be) it should be explained in the documentation.
But, otherwise I now have it mostly working well (without a transaction). I am having some issues with the transient highlighting (as in the code above), but I think that might be a separate issue (in which case it probably deserves a seprate topic).
Can't find what you're looking for? Ask the community or share your knowledge.