boundingBox of body

boundingBox of body

p_krola
Enthusiast Enthusiast
1,185 Views
4 Replies
Message 1 of 5

boundingBox of body

p_krola
Enthusiast
Enthusiast

How can I get the length, width and height of a selected body using C ++?

0 Likes
1,186 Views
4 Replies
Replies (4)
Message 2 of 5

BrianEkins
Mentor
Mentor

Whether you're using C++ or Python, there are two ways to get the bounding box. The first is to use the boundingBox property of the BRepBody. The second is to use the getOrientedBoundingBox method of the MeasureManager object. The box returned by boundingBox is always aligned with the base X-Y-Z planes of the world coordinate system. The box returned by getOrientedBoundingBox is oriented in any direction you want.

 

The sample code below illustrates the use of both, but in the case of the oriented bounding box, I'm specifying the same directions as the standard bounding box. I thought there are cases where the oriented bounding box will be a tighter fit to the body, but in my tests, I always got the same results, so I don't know if they're both tight fitting or I just didn't have a test case that illustrated the difference. In both cases the bounding box will always enclose the body, but there could be cases where it's not tight to the body and the bounding box is slightly larger.

 

#include <Core/CoreAll.h>
#include <Fusion/FusionAll.h>
#include <CAM/CAMAll.h>
#include <iostream>
#include <format>
#include <string>

using namespace adsk::core;
using namespace adsk::fusion;
using namespace adsk::cam;


Ptr<Application> app;
Ptr<UserInterface> ui;

extern "C" XI_EXPORT bool run(const char* context)
{
	app = Application::get();
	if (!app)
		return false;

	ui = app->userInterface();
	if (!ui)
		return false;

	// Have a body selected.
	Ptr<Selection> select = ui->selectEntity("Select a body", "Bodies");
	Ptr<BRepBody> body = select->entity();

	// Get the bounding box.
	Ptr<BoundingBox3D> bounds = body->boundingBox();

	// Display the results.
	app->log("Standard Bounding Box");
	app->log("Min Point: " + std::to_string(bounds->minPoint()->x()) + ", " +
							 std::to_string(bounds->minPoint()->y()) + ", " +
							 std::to_string(bounds->minPoint()->z()));

	app->log("Max Point: " + std::to_string(bounds->maxPoint()->x()) + ", " +
							 std::to_string(bounds->maxPoint()->y()) + ", " +
							 std::to_string(bounds->maxPoint()->z()));

	// Get an oriented bounding box.
	Ptr<MeasureManager> mm = app->measureManager();
	Ptr<Vector3D> lengthVec = adsk::core::Vector3D::create(1, 0, 0);
	Ptr<Vector3D> widthVec = adsk::core::Vector3D::create(0, 1, 0);
	Ptr<OrientedBoundingBox3D> tightBounds = mm->getOrientedBoundingBox(body, lengthVec, widthVec);

	app->log("Oriented Bounding Box");
	double minX = tightBounds->centerPoint()->x() - tightBounds->length() / 2;
	double minY = tightBounds->centerPoint()->y() - tightBounds->width() / 2;
	double minZ = tightBounds->centerPoint()->z() - tightBounds->height() / 2;
	app->log("Min Point: " + std::to_string(minX) + ", " +
					 		 std::to_string(minY) + ", " +
							 std::to_string(minZ));

	double maxX = tightBounds->centerPoint()->x() + tightBounds->length() / 2;
	double maxY = tightBounds->centerPoint()->y() + tightBounds->width() / 2;
	double maxZ = tightBounds->centerPoint()->z() + tightBounds->height() / 2;
	app->log("Max Point: " + std::to_string(maxX) + ", " +
					 		 std::to_string(maxY) + ", " +
							 std::to_string(maxZ));

	return true;
}

#ifdef XI_WIN

#include <windows.h>

BOOL APIENTRY DllMain(HMODULE hmodule, DWORD reason, LPVOID reserved)
{
	switch (reason)
	{
	case DLL_PROCESS_ATTACH:
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
	return TRUE;
}

#endif // XI_WIN

 

---------------------------------------------------------------
Brian Ekins
Inventor and Fusion 360 API Expert
Website/Blog: https://EkinsSolutions.com
Message 3 of 5

p_krola
Enthusiast
Enthusiast

Thank you very much for help. The script works very well. I have a problem if I want to use <SelectionCommandInput> in my Add-in. I've tried many ways and I always get (Error (active) E0135 class "adsk :: fusion :: BRepBodies" has no member "boundingBox")

#include <Core/CoreAll.h>
#include <Fusion/FusionAll.h>
#include <CAM/CAMAll.h>
#include <iostream>
#include <format>
#include <string>
#include <Fusion/BRep/BRepBody.h>


using namespace adsk::core;
using namespace adsk::fusion;
using namespace adsk::cam;

Ptr<Application> app;
Ptr<UserInterface> ui;

// Global command input declarations.
std::vector<Ptr<BRepBody> > selectedBodies;


class MySelectHandler : public SelectionEventHandler
{
public:
	void notify(const Ptr<SelectionEventArgs>& eventArgs) override
	{
		if (!eventArgs)
			return;
		Ptr<Selection> selection = eventArgs->selection();

		Ptr<BRepBodies> body = selection->entity();

		Ptr<BoundingBox3D> bounds = body->boundingBox();

		// Display the results.
		app->log("Standard Bounding Box");
		app->log("Min Point: " + std::to_string(bounds->minPoint()->x()) + ", " +
			std::to_string(bounds->minPoint()->y()) + ", " +
			std::to_string(bounds->minPoint()->z()));

		selectedBodies.emplace_back(body);
	}
};

// CommandExecuted event handler.
class OnExecuteEventHander : public adsk::core::CommandEventHandler
{
public:
	void notify(const Ptr<CommandEventArgs>& eventArgs) override
	{


		

	}
};
// CommandCreated event handler.
class CommandCreatedEventHandler : public adsk::core::CommandCreatedEventHandler
{
public:
	void notify(const Ptr<CommandCreatedEventArgs>& eventArgs) override
	{
		if (eventArgs)
		{
			Ptr<Command> cmd = eventArgs->command();
			if (cmd)
			{
				Ptr<Command> cmd = eventArgs->command();
				// Define the inputs.
				Ptr<CommandInputs> inputs = cmd->commandInputs();

				// Add an input to have a body selected.
				Ptr<SelectionCommandInput> bodiesInput = inputs->addSelectionInput("bodiesInput", "Bodies",
					"Select the bodies.");
				bodiesInput->addSelectionFilter("Bodies");


				// Connect to the command executed event.
				Ptr<CommandEvent> onExec = cmd->execute();
				bool isOk = onExec->add(&onExecuteHandler_);

			}
		}
	}

private:
	OnExecuteEventHander onExecuteHandler_;
	MySelectHandler m_selectHandler;
} _cmdCreated;
bool checkReturn(Ptr<Base> returnObj)
{
	if (returnObj)
		return true;
	else
		if (app && ui)
		{
			std::string errDesc;
			app->getLastError(&errDesc);
			ui->messageBox(errDesc);
			return false;
		}
		else
			return false;
}

extern "C" XI_EXPORT bool run(const char* context)
{
	app = Application::get();
	if (!app)
		return false;

	ui = app->userInterface();
	if (!ui)
		return false;


	// Create a command definition and add a button to the CREATE panel.
	Ptr<CommandDefinition> cmdDef = ui->commandDefinitions()->addButtonDefinition("sreliefCPPAddIn", "MMill relief", "a Mill relief component", "Resources/Mill relief");
	if (!checkReturn(cmdDef))
		return false;

	Ptr<ToolbarPanel> createPanel = ui->allToolbarPanels()->itemById("SolidModifyPanel");
	if (!checkReturn(createPanel))
		return false;

	Ptr<CommandControl> gearButton = createPanel->controls()->addCommand(cmdDef);
	if (!checkReturn(gearButton))
		return false;

	// Connect to the Command Created event.
	Ptr<CommandCreatedEvent> commandCreatedEvent = cmdDef->commandCreated();
	commandCreatedEvent->add(&_cmdCreated);



	std::string strContext = context;
	if (strContext.find("IsApplicationStartup", 0) != std::string::npos)
	{
		if (strContext.find("false", 0) != std::string::npos)
		{
			ui->messageBox("The \"Mill relief\" command has been added\nto the CREATE panel of the MODEL workspace.");
		}
	}


	return true;
}

extern "C" XI_EXPORT bool stop(const char* context)
{

	Ptr<ToolbarPanel> createPanel = ui->allToolbarPanels()->itemById("SolidModifyPanel");
	if (!checkReturn(createPanel))
		return false;

	Ptr<CommandControl> gearButton = createPanel->controls()->itemById("sreliefCPPAddIn");
	if (checkReturn(gearButton))
		gearButton->deleteMe();

	Ptr<CommandDefinition> cmdDef = ui->commandDefinitions()->itemById("sreliefCPPAddIn");
	if (checkReturn(cmdDef))
		cmdDef->deleteMe();
	return true;
}


#ifdef XI_WIN

#include <windows.h>

BOOL APIENTRY DllMain(HMODULE hmodule, DWORD reason, LPVOID reserved)
{
	switch (reason)
	{
	case DLL_PROCESS_ATTACH:
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
	return TRUE;
}

#endif // XI_WIN
0 Likes
Message 4 of 5

Jorge_Jaramillo
Collaborator
Collaborator

Hi,

 

Since you are getting a "adsk :: fusion :: BRepBodies" object from the selection, you need to iterate over its items (body->item(i)->boundingBox()), because more than one body could be selected.

 

Regards,

Jorge

Message 5 of 5

BrianEkins
Mentor
Mentor

I think the problem is line 30 in your code:

Ptr<BRepBodies> body = selection->entity();

 

it should be:

Ptr<BRepBody> body = selection->entity();

 

BRepBody instead of BrepBodies.

---------------------------------------------------------------
Brian Ekins
Inventor and Fusion 360 API Expert
Website/Blog: https://EkinsSolutions.com
0 Likes