cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
Showing results for 
Search instead for 
Did you mean: 
Developer forum

How to get the projected area through API function?

leilei
Enthusiast
Hi,

Does anyone know this question?If I have a 3D object and I want to get the projected area of this object, is there any way to get this area through the API function?

Best regards,
Leilei
1 ACCEPTED SOLUTION

Solution
Tibor Lorantfy
Graphisoft Alumni
Graphisoft Alumni
Ralph's right, you have to calculate this on your own.
But of course we are here to help you, so I wrote you a draft for this calculation:
#include	"ACAPinc.h"

#include	"basicgeometry.h"
#include	"Polygon2D.hpp"

static double CalculateProjectedAreaOfElem (const API_Guid& elemGuid)
{
	double			calculatedArea = 0.;
	GSErrCode		err = NoError;
	Geometry::Plane	floorPlanPlane;
	API_Elem_Head	elemHead = {};
	elemHead.guid = elemGuid;

	API_ElemInfo3D 	info3D;
	err = ACAPI_Element_Get3DInfo (elemHead, &info3D);
	if (DBERROR (err != NoError))
		return 0;

	Geometry::MultiPolygon2D projectedPolygon2DArray; 
	for (Int32 ibody = info3D.fbody; ibody <= info3D.lbody; ++ibody) {
		API_Component3D 	component = {};
		component.header.typeID = API_BodyID;
		component.header.index  = ibody;
		err = ACAPI_3D_GetComponent (&component);
		if (DBERROR (err != NoError))
			continue;

		Int32		nPgon = component.body.nPgon;
		API_Tranmat	tm = component.body.tranmat;

		for (Int32 iPgon = 1; iPgon <= nPgon; ++iPgon) {
			component.header.typeID = API_PgonID;
			component.header.index  = iPgon;
			err = ACAPI_3D_GetComponent (&component);
			if (DBERROR (err != NoError))
				continue;

			GS::Array<Coord>	pgonCoordsProjectedToFloorPlan;
			for (Int32 iEdge = component.pgon.fpedg; iEdge <= component.pgon.lpedg; ++iEdge) {
				component.header.typeID = API_EdgeID;
				component.header.index  = iEdge;
				err = ACAPI_3D_GetComponent (&component);
				if (DBERROR (err != NoError))
					continue;

				component.header.typeID = API_VertID;
				component.header.index  = component.edge.vert1;
				err = ACAPI_3D_GetComponent (&component);
				if (DBERROR (err != NoError))
					continue;

				Geometry::Coord3D	worldCoord;
				worldCoord.x = tm.tmx[0]*component.vert.x + tm.tmx[1]*component.vert.y + tm.tmx[2]*component.vert.z + tm.tmx[3];
				worldCoord.y = tm.tmx[4]*component.vert.x + tm.tmx[5]*component.vert.y + tm.tmx[6]*component.vert.z + tm.tmx[7];
				worldCoord.z = tm.tmx[8]*component.vert.x + tm.tmx[9]*component.vert.y + tm.tmx[10]*component.vert.z + tm.tmx[11];
				Geometry::Coord3D	projectedCoord = floorPlanPlane.ProjectToPlane (worldCoord);
				pgonCoordsProjectedToFloorPlan.PushNew (projectedCoord.x, projectedCoord.y);
			}

			Geometry::MultiPolygon2D polygon2DArray; 
			Geometry::Polygon2D::Create (pgonCoordsProjectedToFloorPlan, 0, polygon2DArray);
			projectedPolygon2DArray.Append (polygon2DArray);
		}
	}

	projectedPolygon2DArray.Unify (Geometry::WithoutHoles);
	for (const Geometry::Polygon2D& polygon2D : projectedPolygon2DArray)
		calculatedArea += polygon2D.CalcArea ();

	return calculatedArea;
}
This is based on Ralph's idea.

View solution in original post

5 REPLIES 5

Ralph Wessel
Mentor
Could you clarify whether you mean the total surface area of the 3D body or the area visible in the 3D window?
Ralph Wessel BArch

leilei
Enthusiast
Ralph wrote:
Could you clarify whether you mean the total surface area of the 3D body or the area visible in the 3D window?
Hi Ralph,
The area I want is like a projection on a floor plan.
Regards,
Leilei

Ralph Wessel
Mentor
I don't know if there's an easy answer to that. Bottom line, you could extract the faces of the 3D body, project them to 2D polygons in the view plane and merge them to result in the bounding polygon(s). Hopefully there is a simpler method.
Ralph Wessel BArch

Solution
Tibor Lorantfy
Graphisoft Alumni
Graphisoft Alumni
Ralph's right, you have to calculate this on your own.
But of course we are here to help you, so I wrote you a draft for this calculation:
#include	"ACAPinc.h"

#include	"basicgeometry.h"
#include	"Polygon2D.hpp"

static double CalculateProjectedAreaOfElem (const API_Guid& elemGuid)
{
	double			calculatedArea = 0.;
	GSErrCode		err = NoError;
	Geometry::Plane	floorPlanPlane;
	API_Elem_Head	elemHead = {};
	elemHead.guid = elemGuid;

	API_ElemInfo3D 	info3D;
	err = ACAPI_Element_Get3DInfo (elemHead, &info3D);
	if (DBERROR (err != NoError))
		return 0;

	Geometry::MultiPolygon2D projectedPolygon2DArray; 
	for (Int32 ibody = info3D.fbody; ibody <= info3D.lbody; ++ibody) {
		API_Component3D 	component = {};
		component.header.typeID = API_BodyID;
		component.header.index  = ibody;
		err = ACAPI_3D_GetComponent (&component);
		if (DBERROR (err != NoError))
			continue;

		Int32		nPgon = component.body.nPgon;
		API_Tranmat	tm = component.body.tranmat;

		for (Int32 iPgon = 1; iPgon <= nPgon; ++iPgon) {
			component.header.typeID = API_PgonID;
			component.header.index  = iPgon;
			err = ACAPI_3D_GetComponent (&component);
			if (DBERROR (err != NoError))
				continue;

			GS::Array<Coord>	pgonCoordsProjectedToFloorPlan;
			for (Int32 iEdge = component.pgon.fpedg; iEdge <= component.pgon.lpedg; ++iEdge) {
				component.header.typeID = API_EdgeID;
				component.header.index  = iEdge;
				err = ACAPI_3D_GetComponent (&component);
				if (DBERROR (err != NoError))
					continue;

				component.header.typeID = API_VertID;
				component.header.index  = component.edge.vert1;
				err = ACAPI_3D_GetComponent (&component);
				if (DBERROR (err != NoError))
					continue;

				Geometry::Coord3D	worldCoord;
				worldCoord.x = tm.tmx[0]*component.vert.x + tm.tmx[1]*component.vert.y + tm.tmx[2]*component.vert.z + tm.tmx[3];
				worldCoord.y = tm.tmx[4]*component.vert.x + tm.tmx[5]*component.vert.y + tm.tmx[6]*component.vert.z + tm.tmx[7];
				worldCoord.z = tm.tmx[8]*component.vert.x + tm.tmx[9]*component.vert.y + tm.tmx[10]*component.vert.z + tm.tmx[11];
				Geometry::Coord3D	projectedCoord = floorPlanPlane.ProjectToPlane (worldCoord);
				pgonCoordsProjectedToFloorPlan.PushNew (projectedCoord.x, projectedCoord.y);
			}

			Geometry::MultiPolygon2D polygon2DArray; 
			Geometry::Polygon2D::Create (pgonCoordsProjectedToFloorPlan, 0, polygon2DArray);
			projectedPolygon2DArray.Append (polygon2DArray);
		}
	}

	projectedPolygon2DArray.Unify (Geometry::WithoutHoles);
	for (const Geometry::Polygon2D& polygon2D : projectedPolygon2DArray)
		calculatedArea += polygon2D.CalcArea ();

	return calculatedArea;
}
This is based on Ralph's idea.

leilei
Enthusiast
Thanks Ralph and Tibor,

Still looking?

Browse more topics

Back to forum

See latest solutions

Accepted solutions

Start a new discussion!