BIM Coordinator Program (INT) April 22, 2024
Find the next step in your career as a Graphisoft Certified BIM Coordinator!
Archicad C++ API
About Archicad add-on development using the C++ API.

ACAPI_3D_DecomposePgon

stefan
Expert
I've done it again... I've relooked at my Radiance exporter and am stumbling on the decomposition of the Archicad polygon into a set of valid convex polygons.

I think it is a strictly C++ question, but the sparse documentation leaves me not much choice.

The docs tell me:
ACAPI_3D_DecomposePgon(long ipgon, long ***cpoly)
This function is used to decompose a polygon into convex polygons.
The polygon is defined by ipgon index.
The decomposed polygon is returned in the cpoly long array,
which contains the following values:
[-n], [-m1], i1, i2, ... i(m1), [-m2], j1, j2, ... j(m2)...
And now the question:
Do I need to set up an array for the function to fill, or does the function allocates memory itself? I hate code that uses more then one * after eachother 😉
When I try the following, it compiles and runs, but somehow the array seems to be gone... Or at least the cpoly is pointing to nowhere:
//j is allready referencing the current polygon
long * Verts = new long[100]; // array of 100 longs (seems stupid)
long ** cpoly = &Verts; // a pointer to this array
GSErrCode TriangulationError = ACAPI_3D_DecomposePgon(j, &cpoly);
When I do this, Archicad goes through, but I cannot do anything with the results... Do I miss something? Do I need to allocate memory? Or do I need an array with pointers to longs? Or is it actually an array of verts?

The documentation is rather vague and unfortunately I have no working example available...

(If I should go back to my first C++-class, then please tell me so)
--- stefan boeykens --- bim-expert-architect-engineer-musician ---
Archicad27/Revit2023/Rhino8/Unity/Solibri/Zoom
MBP2023:14"M2MAX/Sonoma+Win11
Archicad-user since 1998
my Archicad Book
5 REPLIES 5
Oleg
Expert
cpoly is a pointer to handle.

long** cpoly=0; // this is handle
bool ok = ACAPI_3D_DecomposePgon( id, &cpoly ) == NoError;
... and after using 
BMhKill((GSHandle*)&cpoly );
PS: One more open source renderer for you http://www.cs.berkeley.edu/~okan/Pixie/pixie.htm
stefan
Expert
Thanks again!

Now, do I need to allocate memory myself or is that the responsability of the DecomposPgn function?

And lastly, I'm still struggling on getting access to the actual array that should be referenced by the cpoly.

Would *cpoly give me acces to it? Or do I need to cast it to a (GSHandle*) and then work through the handle?

----

Bytheway... the Pixie renderer seems nice. And (in contrast with BMRT) the source is included, so it might be possible to link that to an executable. This did work more or less with BMRT, but only single-threaded, not debug and it also gave library conflicts. So I gave up that time.
--- stefan boeykens --- bim-expert-architect-engineer-musician ---
Archicad27/Revit2023/Rhino8/Unity/Solibri/Zoom
MBP2023:14"M2MAX/Sonoma+Win11
Archicad-user since 1998
my Archicad Book
Oleg
Expert
stefan wrote:
Thanks again!

Now, do I need to allocate memory myself or is that the responsability of the DecomposPgn function?

And lastly, I'm still struggling on getting access to the actual array that should be referenced by the cpoly.

Would *cpoly give me acces to it? Or do I need to cast it to a (GSHandle*) and then work through the handle?
You dont need to allocate memory, but you need to release the memory ( kill the handle ).

You can access it as (*cpoly) or to create a pointer for easy using like
long* poly = *cpoly;
and then use it just poly

PS: Actually the handle should be locked if you did the pointer like poly ( above ), but it seem it is not required for MacOSX now and I think it was never need for Win.
stefan
Expert
OK, I'm starting to see the light now...

For convex polygons, ACAPI_3D_DecomposePgon doesn't give an error, but returns the cpoly as NULL. Then I don't need it.

When cpoly != NULL I can step through the array as follows:
long n = (*cpoly)[0] * -1; // number of sub-polygons
if (n > 0)
{
	for (long poly = 0; poly < n; ++poly)
	{
		++count;
		long m = (*cpoly)[count] * -1; // number of vertices in current subpolygon
		if (m > 0)
		{
			// get indices to the vertices
			for (long vert = 0; vert < m; ++vert)
			{
				++count;
				long vertindex = (*cpoly)[count];
				// get the actual vertex
				component.header.typeID = API_VertID;
				component.header.index  = vertindex;
				err = ACAPI_3D_GetComponent (&component);
				if (err == NoError)
				{
					double xx, yy, zz;
					xx = component.vert.x;
					yy = component.vert.y;
					zz = component.vert.z;
					// transform it into world coordinates
					Geometry::TMPoint(&tranmat_struct, &xx, &yy, &zz);
					// export...
				} // end if no error getting vertex
			} // end for vert
		} // end if m > 0
	} // end for poly
} // end if n > 0
Well, one step closer to heaven 😉
--- stefan boeykens --- bim-expert-architect-engineer-musician ---
Archicad27/Revit2023/Rhino8/Unity/Solibri/Zoom
MBP2023:14"M2MAX/Sonoma+Win11
Archicad-user since 1998
my Archicad Book
stefan
Expert
Not quite...

The vertex-index that is retrieved from the cpoly-array is a 0-based index while ArchiCAD uses 1-based indices to get to the real component.vert !

So you have to do the following:
long vertindex = (*cpoly)[count];
vertindex +=1;
before you get the actual vertex (API_VertID)

Is this a bug? Or are they falling in their own booby-traps?
--- stefan boeykens --- bim-expert-architect-engineer-musician ---
Archicad27/Revit2023/Rhino8/Unity/Solibri/Zoom
MBP2023:14"M2MAX/Sonoma+Win11
Archicad-user since 1998
my Archicad Book
Learn and get certified!

Didn't find the answer?

Check other topics in this Forum

Back to Forum

Read the latest accepted solutions!

Accepted Solutions

Start a new conversation!