ObjectARX

ObjectARX

Reply
Contributor
xeri0n
Posts: 19
Registered: ‎11-21-2011
Message 1 of 24 (548 Views)

Accessing point cloud entity loaded from a .pcg file

548 Views, 23 Replies
04-25-2012 05:38 PM

Hello,

 

I had a look at the objectArx header files and I saw that there is a AcPointCloud.h file hinting at some Point cloud processing functions. 

What I want to do is obtain the point cloud points for specific extents. In essence the points that are located in a bounding box. The function to do that is acdbProcessPointCloudData which requires 4 parameters.

 

One of the input parameters is the point cloud of course. Is there a way to get the AcDbEntity of the .pcg loaded file, if we assume its only one for simplicity, so I can work with it ?

 

In AcDbPointcloud.h it is stated that it is the Api for AcDbPointCloud, however I see no class for AcDbPointCloud. Am I missing something ?

 

Thanks in advance! 

Distinguished Mentor
owenwengerd
Posts: 620
Registered: ‎08-06-2002
Message 2 of 24 (543 Views)

Re: Accessing point cloud entity loaded from a .pcg file

04-25-2012 09:58 PM in reply to: xeri0n

It looks like Autodesk chose to not expose the AcDbPointCloud class, and instead have provided opaque functions to work with point cloud entities. You can still use the AcRxClass base class, even though the derived class is not documented.

--
Owen Wengerd
ManuSoft
Contributor
xeri0n
Posts: 19
Registered: ‎11-21-2011
Message 3 of 24 (541 Views)

Re: Accessing point cloud entity loaded from a .pcg file

04-25-2012 10:04 PM in reply to: owenwengerd

Thank you for your reply,

 

That is what I am trying out now. I am looping through the entities and checking if the AcRxClass->name() is "AcDbPointCloud". I guess then I can do whatever I want with it.

Distinguished Mentor
owenwengerd
Posts: 620
Registered: ‎08-06-2002
Message 4 of 24 (536 Views)

Re: Accessing point cloud entity loaded from a .pcg file

04-25-2012 10:39 PM in reply to: xeri0n

Better to look up the point cloud AcRxClass object in the class dictionary and use it for your comparison:

AcRxClass* pRxPointCloud = (AcRxClass*)acrxClassDictionary->at( ACRX_T("AcDbPointCloud") );

 

--
Owen Wengerd
ManuSoft
Contributor
xeri0n
Posts: 19
Registered: ‎11-21-2011
Message 5 of 24 (534 Views)

Re: Accessing point cloud entity loaded from a .pcg file

04-25-2012 11:11 PM in reply to: owenwengerd

I guesss that way I can save iterating through the whole block table record. Much better ! 

 

I guess then the actual difficult part will be to implement the abstract base classes

IAcPcPointFilter

IAcPcDataBuffer

IAcPcPointProcessor

 

unless I am missing something?

 

Cheers ! 

Contributor
xeri0n
Posts: 19
Registered: ‎11-21-2011
Message 6 of 24 (526 Views)

Re: Accessing point cloud entity loaded from a .pcg file

04-26-2012 07:34 AM in reply to: xeri0n

I quickly hacked something in order to test the concept and see if it works.

 

Here is what I came up with and how I implmented the classes derived from the abstract implementations.

 

class ACDB_PORT AcPcPointFilter : public IAcPcPointFilter
{
public:
	AcPcPointFilter(){}

	void doFilter(const IAcPcDataBuffer& inBuffer, IAcPcDataBuffer& outBuffer){	}
};

class ACDB_PORT AcPcDataBuffer  : public IAcPcDataBuffer
{
public:
	AcPcDataBuffer(){	}

	///<summary>Indicate if the points are in single or double precision.</summary>
	bool nativeDbl(){return true;}
	
	///<summary>Resize the buffer. This may be a destructive operation.</summary>
	bool resize(DWORD size)
	{
		try
		{
			this->AcPcPointDoubleArray.resize(size);
		}
		catch (...)
		{
			return false;
		}

		return true;
	};

	///<summary>Shrink the buffer without destroying its contents.</summary>
	bool shrink(DWORD size)
	{
		try
		{
			// just discard excess capacity
			this->AcPcPointDoubleArray.shrink_to_fit();
		}
		catch (...)
		{
			return false;
		}

		return true;
	}
	
	/// <summary>Return the number of points in the buffer.</summary>
	DWORD size() const
	{
		return (DWORD)this->AcPcPointDoubleArray.size();
	}

	/// <summary>Return a array of single precision points.
	/// This may return NULL if the buffer is not single precision.</summary>
	AcPcPointFloat*  floatPoints (){return NULL;}

	/// <summary>Return a array of double precision points.
	/// This may return NULL if the buffer is not double precision.</summary>
	AcPcPointDouble* doublePoints()
	{
		return &this->AcPcPointDoubleArray[0];
	}

	/// <summary>Return a point in single precision.
	/// This will work regardless of the native precision of the buffer.</summary>
	bool floatPoint(DWORD ptIx, AcPcPointFloat& pt) const
	{
		if (ptIx < this->AcPcPointDoubleArray.size())
		{
			pt = (AcPcPointFloat&)this->AcPcPointDoubleArray[ptIx];
			return true;
		}

		return false;
	}

	/// <summary>Return a point in double precision.
	/// This will work regardless of the native precision of the buffer.</summary>
	bool doublePoint (DWORD ptIx, AcPcPointDouble& pt) const
	{
		if (ptIx < this->AcPcPointDoubleArray.size())
		{
			pt = this->AcPcPointDoubleArray[ptIx];
			return true;
		}

		return false;
	}

	/// <summary>Set a point in single precision.
	/// This will work regardless of the native precision of the buffer.</summary>
	bool setFloatPoint(DWORD ptIx, AcPcPointFloat&  pt)
	{
		if (ptIx < this->AcPcPointDoubleArray.size())
		{
			this->AcPcPointDoubleArray[ptIx] = (AcPcPointDouble&)pt;
			return true;
		}

		return false;
	}

	/// <summary>Set a point in double precision.
	/// This will work regardless of the native precision of the buffer.</summary>
	bool setDoublePoint (DWORD ptIx, AcPcPointDouble& pt)
	{
		if (ptIx < this->AcPcPointDoubleArray.size())
		{
			this->AcPcPointDoubleArray[ptIx] = pt;
			return true;
		}

		return true;
	}

	/// <summary>Get the translation offset of the points.
	/// This offset needs to be added to each point in order to get the 
	/// original location of the point in the point cloud</summary>
	bool offset(double& x, double& y, double& z) const
	{
		return true;
	}
	/// <summary>This transform needs to be applied to the points to
	/// get the points in world space.</summary>
	bool entityTransform(AcGeMatrix3d& matrix) const
	{
		return true;
	}

	/// <summary>Copy the contents of the given buffer.</summary>
	void copyFrom(IAcPcDataBuffer const & from)
	{
		this->AcPcPointDoubleArray.clear();
		AcPcPointDouble temp;

		for (DWORD i = 0 ; i < from.size(); i++)
		{
			from.doublePoint(i,temp);
			this->AcPcPointDoubleArray.push_back( temp );
		}
	}

public:
	std::vector<AcPcPointDouble> AcPcPointDoubleArray;
};

class ACDB_PORT AcPcPointProcessor : public IAcPcPointProcessor
{
public:
	AcPcPointProcessor()
	{
		AcPcDataBuffer *buf = new AcPcDataBuffer();
		this->setBuffer(buf);

		this->bCancel = false;
		this->ptFilter = NULL;
	};

	~AcPcPointProcessor()
	{
		if (this->buffer())
			delete this->buffer();
	}

	/// <summary>Return true to cancel processing.</summary>
	bool cancel(){return false;}

	bool setCancel(bool b) {this->bCancel = b;}

	/// <summary>Called to abort the process</summary>
	void abort(){}

	/// <summary>Called after the last call to ProcessPoints</summary>
	void finished(){}

	/// <summary>Process point in buffer. This will be called repeatedly with 
	/// new buffer contents until all points have been processed.</summary>
	bool processPoints(){return true;}

	/// <summary>Filter, if available, to filter points.
	/// Called before processPoints() on the next batch of points.</summary>
	IAcPcPointFilter*  filter()
	{
		if (ptFilter)
			return this->ptFilter;
		else
			return NULL;
	}

	/// <summary> Set Filter, to filter points.
	void setFilter(IAcPcPointFilter* newfilter){this->ptFilter = newfilter;}

private:
	bool bCancel;
	IAcPcPointFilter* ptFilter;
};

  And here is how I call the acdbProcessPointCloudData function

 

// set bounding box - just testing so nothing useful
AcGePoint3d ptmin(0,0,0);
AcGePoint3d ptmax(1000000000,1000000000,2000000);
const AcDbExtents boundingBox( ptmin, ptmax);
		
// init AcPcPointProcessor
AcPcPointProcessor* ptProc = new AcPcPointProcessor();

Acad::ErrorStatus err = acdbProcessPointCloudData(pEntity, boundingBox, 100, ptProc);

 

While the function returns eOK and the size of the buffer seems fine the actual data in the vector is garbage.

Do you see anything suspicious ?

 

Any idea is appreciated ! 

Distinguished Mentor
owenwengerd
Posts: 620
Registered: ‎08-06-2002
Message 7 of 24 (520 Views)

Re: Accessing point cloud entity loaded from a .pcg file

04-26-2012 09:17 AM in reply to: xeri0n

I think you're supposed to let the point cloud engine allocate and manage the data buffer.

--
Owen Wengerd
ManuSoft
Contributor
xeri0n
Posts: 19
Registered: ‎11-21-2011
Message 8 of 24 (511 Views)

Re: Accessing point cloud entity loaded from a .pcg file

04-26-2012 04:30 PM in reply to: owenwengerd

This is actually something that I initially tried and it does not work. The class is abstract so I cannot really pass anything else apart from a null pointer and hope that autocad has derived classes (not exposed) to handle it.

 

 

IAcPcPointProcessor* iptProc = 0;
Acad::ErrorStatus err = acdbProcessPointCloudData(pEntity, boundingBox, 100, iptProc);

However the above call results in an error of "eNullPtr"...


Distinguished Mentor
owenwengerd
Posts: 620
Registered: ‎08-06-2002
Message 9 of 24 (506 Views)

Re: Accessing point cloud entity loaded from a .pcg file

04-26-2012 08:14 PM in reply to: xeri0n

Of course you need to provide a IAcPcPointProcessor, but let AutoCAD allocate and manage its data buffer.

--
Owen Wengerd
ManuSoft
Contributor
xeri0n
Posts: 19
Registered: ‎11-21-2011
Message 10 of 24 (504 Views)

Re: Accessing point cloud entity loaded from a .pcg file

04-26-2012 08:33 PM in reply to: owenwengerd

Thanks again for your reply.

 

That sounds interesting and for some reason the buffer is initialised as I can see in the debugger. I dont know if its just a random memory position or actually initialised as I have not way to check that since its an abstract class. I cannot get access to any of the size(), or parse the array at all to check the contents.

 

Your help is greatly appreciated ! 

 

Announcements
Are you familiar with the Autodesk Expert Elites? The Expert Elite program is made up of customers that help other customers by sharing knowledge and exemplifying an engaging style of collaboration. To learn more, please visit our Expert Elite website.
Need installation help?

Start with some of our most frequented solutions or visit the Installation and Licensing Forum to get help installing your software.