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.

[newbie] stepping through the vertices of a polygon

stefan
Expert
My Radiance exporter is slowly getting born...

I am failing to step through the vertices of a polygon.
I am able to get access to the body of the 3D-objects.

The 3D-Test example shows how to step through all the vertices of the body and through all the edges, but to have something usable, I have to do this polygon by polygon.

I can get the amount of vertices, edges & polygons (I left out the error code):
API_Component3D 	component;
long		j, nVertices, nEdges, nPolygons;
GSErrCode	err;
BNZeroMemory (&component, sizeof (component));
component.header.typeID = API_BodyID;
component.header.index  = ibody;
ACAPI_3D_GetComponent (&component);
nVertices	= component.body.nVert;
nEdges		= component.body.nEdge;
nPolygons	= component.body.nPgon;
and then I step through all polygons:
for (j = 1; j <= nPolygons; j++)
{
	component.header.typeID = API_PgonID;
	component.header.index = j;
	ACAPI_3D_GetComponent(&component);
	long firstEdge, lastEdge;
	firstEdge = component.pgon.fpedg;
	lastEdge  = component.pgon.lpedg;
	// Walk through the edges
	for (long e = firstEdge; e < lastEdge; e++)
	{
		component.header.typeID = API_PedgID;
		component.header.index = e;
		ACAPI_3D_GetComponent(&component);
		// get the edge
		API_PedgType &edge = ??????????
	}
}
I'm not sure if I'm doing this correct, but I did this in about the same way as stepping through the other elements. So how do I get the list of vertices that is used in one particular polygon?
--- 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
13 REPLIES 13
Oleg
Expert
For every Pedge, you need to get API_EdgeType.
Absolute value of API_PedgType::pedge is an index for getting of the API_EdgeType. ( It may be =0 for holes, read the doc).
After you got the API_EdgeType, vert1 and vert2 fields are indexes for getting of the API_VertType. Direction of edge (from vert1 to vert2 or from vert2 to vert1) depends on the pedge sign.
stefan
Expert
I'm not sure if I understand all of this correctly...
I don't seem to get how I can access this "pedge" from API_PedgType... You say it's an index. Should I pass it into the component.header.index after I get the reference to the edge (from API_PedgID)?
for (long e = firstEdge; e <= lastEdge; e++)
{
	// Get Current edge
	component.header.typeID = API_EdgeID;
	component.header.index  = e;
	ACAPI_3D_GetComponent (&component);
	long vert1 = component.edge.vert1;
	long vert2 = component.edge.vert2;
	// Now get the vertices
	// vert1
	component.header.typeID = API_VertID;
	component.header.index  = vert1;
	ACAPI_3D_GetComponent (&component);
	WriteReport ("    vertex 1 index = %d coord (%Lf, %Lf, %Lf)",
		component.header.index,
		component.vert.x, component.vert.y, component.vert.z);
	// vert2 --> similar.......
}
When I do this, I can step through most of the vertices of the polygon, but the output seems not really usable... When I follow the vertices around in the output, I can see where they are coming from, but they don't seem to build up a real valid polygon. I guess the last point is automatically connected to the first, but in between them? Sometimes two consecutive edges are not connected and sometimes they are. I guess I'm forgetting to check on certain edges.
And in the example I'm testing (a simple 1meter long wall) the third polygon I get is identical to the first... And I only get three polygons while I expect 6 of them for this simple wall.
--- 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
for (long e = firstEdge; e <= lastEdge; e++)
{
// Get current Pedge
component.header.typeID = API_PedgID;
component.header.index = e;
ACAPI_3D_GetComponent(&component);
long edgeInd=component.pedg.pedg;
if (edgeInd==0)
{
// start of hole
// some action
...
continue;
}


// Get Current edge
component.header.typeID = API_EdgeID;
component.header.index = abs(edgeInd);
ACAPI_3D_GetComponent (&component);
long vert1 = component.edge.vert1;
long vert2 = component.edge.vert2;

if (edgeInd<0) // back direction of vertices
swap(vert1,vert2)


// Now get the vertices
// vert1
component.header.typeID = API_VertID;
component.header.index = vert1;
ACAPI_3D_GetComponent (&component);

WriteReport (" vertex 1 index = %d coord (%Lf, %Lf, %Lf)",
component.header.index,
component.vert.x, component.vert.y, component.vert.z);
// vert2 --> similar.......
}
I have inserted some lines in bold. Is it more clear now ?

PS: Bold tag doesnot work inside code tag
stefan
Expert
Thanks a lot! For simple geometry it seems to be working now. I can launch a Radiance rendering from inside ArchiCAD (but still need to get more accurate translation of geometry and then the full settings from Materials, Sun, Sky, Camera & Lights)...

But to me the proof-of-concept is working.
--- 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
Karl Ottenstein
Moderator
Thanks, Oleg! It will be fun to follow your progress, Stefan.

I'm glad you brought this up, and Oleg explained, as I had not studied this part of the API structures and theACAPI_3D_GetComponent call, so it was a good excuse to look further.

If I think of the database as a multi-linked data structure (lists of lists), it is very easy to visualize. Viewing it as the API presents it twists my brain a bit. I'm not sure I see why GS decided to have a PedgType "point" to the actual edge structure (with Pedg used both for the name of a structure and the name of an index field - should be different names IMHO) ... rather than just embedding the edge data into the unioned API_Component3D with a flag substituting for the overloaded function of the long Pedg (0=hole, +/- = edge component ref). I have to assume that the overly complex structure is to hide a performance 'hit' the happens in the implementation of retrieving edges. If not, I can't see why this is such a complicated process. What do you think?

Thank you again for sharing your time and knowledge, Oleg!

Karl
One of the forum moderators
AC 27 USA and earlier   •   macOS Ventura 13.6.6, MacBook Pro M2 Max 12CPU/30GPU cores, 32GB
Oleg
Expert
Karl wrote:
I have to assume that the overly complex structure is to hide a performance 'hit' the happens in the implementation of retrieving edges. If not, I can't see why this is such a complicated process. What do you think?
Karl
My opinion, that from the point of memory size and 3D transformation perfomance, it seems logical.
Each vertex can belong to different polygons.
The edge can belongs to two adjacent polygons (with an opposite direction).
Storage of identical vertices and edges for each polygon will demand a significant additional memory size.
Besides ( probably it is more important ) 3D transformation (apply matrix etc.) is vertex based, an uniform array of vertices can be processed faster.

So, all unique (not duplicated) vertices and edges of whole geometry are stored as arrays (not polygon related lists).
Pedges are required for definition of a polygon like list of pointers to edges of the polygon.

Unfortunately, API seems is very based on internal implementation, therefore we have such indirect process.
Though I am not sure, that any other approach would be easier or better for different tasks.

Just IMHO.
Karl Ottenstein
Moderator
Oleg wrote:
My opinion, that from the point of memory size and 3D transformation perfomance, it seems logical.
Each vertex can belong to different polygons.
The edge can belongs to two adjacent polygons (with an opposite direction).
...
Besides ( probably it is more important ) 3D transformation (apply matrix etc.) is vertex based, an uniform array of vertices can be processed faster.

Unfortunately, API seems is very based on internal implementation, therefore we have such indirect process.
Though I am not sure, that any other approach would be easier or better for different tasks.
Thanks, Oleg. That makes sense.

I was thinking less deeply ... and more in terms of what simple and clean functionality an appropriate collection of wrapper classes might provide to hide the internal complexities. Let there be common edges and vertices internally ... but let retrieving and traversing them be a more conventional process. (And similarly for other structures.)

Thanks again for the insight!

Karl
One of the forum moderators
AC 27 USA and earlier   •   macOS Ventura 13.6.6, MacBook Pro M2 Max 12CPU/30GPU cores, 32GB
stefan
Expert
Anyone knows if the Rendering-DevKit is more straightforward for this? It should, since it needs to step through all the geometry by default.
But that is even less clear how to use, so I'm not sure if I'll follow that road. Besides, I don't think you can integrate a closed set of tools (e.g. Radiance) unless you use the real sourcecode and try to hook that into a real rendering plugin. Although Radiance has become OpenSourced, I don't think it's a trivial task.

In fact, generating the correct text-files is much more straightforward, IMHO. I'll see. When I correctly translate most geometry (holes etc...) and the materials, it'll be fine.

Oh yes, the Camera setting is allready fine since last post 😉
--- 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
Ralph Wessel
Mentor
Karl wrote:
Oleg wrote:
My opinion, that from the point of memory size and 3D transformation perfomance, it seems logical.
I was thinking less deeply ... and more in terms of what simple and clean functionality an appropriate collection of wrapper classes might provide to hide the internal complexities.
Oleg is correct regarding the efficiencies of the internal implementation. I also agree with your observation regarding a wrapper class - I have implemented classes for this very purpose. It was more time-consuming to write up-front, but the long-term gain through ease of use has made it worthwhile. Very efficient too. The other main benefit is that we won't suffer so much if the API for this data changes - the differences should be absorbed by the wrapper and not everything based on it.
Ralph Wessel BArch
Learn and get certified!