Hexagon Geospatial
MENU

Developer Discussions

Discuss topics with other Hexagon Geospatial Power Portfolio developers and experts to get the most out of our products.
Showing results for 
Search instead for 
Do you mean 
Reply
Frequent Contributor
Posts: 116
Registered: ‎10-14-2015
Accepted Solution

Spatial Modeler SDK 2016 - Exercise that creates an Operator from Example1

Dear Community,

 

I'm starting to use the Spatial Modeler SDK 2016 and I really like the spatial modeler guide. I've build the third example (sm_ ExternalProcessExample) and was able to create an operator and use it in Erdas Imagine 2016. This example is very usefull to me.

 

However the spatial modeler guide jumps from using the spatial modeler in c++ (example1 NDVI), to saving it to a gmdx (example2 Report) to creating an operator in the third example (ExternalProcess).

 

What I miss is an example that combines the first/second exersice and the third exercise. I would like to see an example that creates an operator from using the spatial modeler in c++. This example should create for instance the ndvi exercise into a NDVI operator. Can someone help me with that one.

 

Thank you,

Wim

Highlighted
Technical Evangelist
Posts: 53
Registered: ‎09-16-2015

Re: Spatial Modeler SDK 2016 - Exercise that creates an Operator from Example1

[ Edited ]

Wim,

 

Below is the the contents of a .cpp file for implementing the NDVI model as a C++ operator by embedding other Spatial Model operators in the new operator. 

 

#include "NDVIOperator.h"
#include <sbrasterlib/RasterInfo.h>

ERDAS_SB_DEBUG_NAMESPACE_USE
ERDAS_SBLIB_NAMESPACE_USE
ERDAS_SBRASTERLIB_NAMESPACE_USE

NDVIOperator::NDVIOperator()
{
}

NDVIOperator::~NDVIOperator()
{
}

void
NDVIOperator::Init()
{
	// Create the ports.
	CreatePort<RasterInfoData>(L"RasterBand1", SB_PORT_INPUT);
	CreatePort<RasterInfoData>(L"RasterBand2", SB_PORT_INPUT);
	CreatePort<RasterInfoData>(L"NDVI", SB_PORT_OUTPUT);
}

void
NDVIOperator::OnExecute()
{
	// Get the ports.
	PortPtr band1Port = GetPort(L"RasterBand1");
	PortPtr band2Port = GetPort(L"RasterBand2");
	PortPtr ndviPort = GetPort(L"NDVI");

	// Get the rasterInfo from the input ports and verify that they are single bands.
	RasterInfoPtr rasterInfoBand1 = band1Port->GetDataPtr<RasterInfoData>();
	RasterInfoPtr rasterInfoBand2 = band2Port->GetDataPtr<RasterInfoData>();
	if (rasterInfoBand1->GetPlaneCount() > 1 || 
		rasterInfoBand2->GetPlaneCount() > 1)
		SetErrorMessage(L"Input raster bands must be single bands");

	// Create the internal operators.
	m_FloatBand1 = OperatorFactory::Create(L"IMAGINE", L"Float");
	m_FloatBand2 = OperatorFactory::Create(L"IMAGINE", L"Float");
	m_Add = OperatorFactory::Create(L"IMAGINE", L"Add");
	m_Subtract = OperatorFactory::Create(L"IMAGINE", L"Subtract");
	m_Divide = OperatorFactory::Create(L"IMAGINE", L"Divide");

	// Connect the input ports of this operator to the internal Float operators.
	m_FloatBand1->ConnectParent(band1Port, m_FloatBand1->GetPort(L"Input"));
	m_FloatBand2->ConnectParent(band2Port, m_FloatBand2->GetPort(L"Input"));

	// Connect up the internal operators.
	m_Subtract->ConnectParent(m_FloatBand1->GetPort(L"Output"), m_Subtract->GetPort(L"Input1"));
	m_Subtract->ConnectParent(m_FloatBand2->GetPort(L"Output"), m_Subtract->GetPort(L"Input2"));
	m_Add->ConnectParent(m_FloatBand1->GetPort(L"Output"), m_Add->GetPort(L"Input1"));
	m_Add->ConnectParent(m_FloatBand2->GetPort(L"Output"), m_Add->GetPort(L"Input2"));
	m_Divide->ConnectParent(m_Subtract->GetPort(L"Output"), m_Divide->GetPort(L"Input1"));
	m_Divide->ConnectParent(m_Add->GetPort(L"Output"), m_Divide->GetPort(L"Input2"));

	// Set the RasterInfo from the Divide operator as the RasterInfo of this operator.
	RasterInfoPtr rasterInfo = m_Divide->GetPort(L"Output")->GetDataPtr<RasterInfoData>();
	ndviPort->SetDataPtr<RasterInfoData>(rasterInfo);
}

void
NDVIOperator::ProcessBlock(const ERDAS_SBLIB_NAMESPACE::PortPtr & port, const ERDAS_SBRASTERLIB_NAMESPACE::RasterRequestPtr & rasterOp)
{
	// Set the Tile from the Divide operator as the output Tile of this operator.
	port->SetDataPtr<TileData>(rasterOp, m_Divide->GetPort(L"Output")->GetDataPtr<TileData>(rasterOp, Port::ThrowIfEmpty));
}

  

Note that in general we recommend against implementing C++ operators as simply a combination of other operators.  You may want to embed an existing operator or two in new operator as part of your algorithm; however, if the entire algorithm can be implemented with existing operators, we recommend that you create and save a model and use that.  If you want to use it as an operator in a larger model, we recommend using the Spatial Model operator (in the General category--or just search for Spatial Model--in the Operators pane in the Spatial Model Editor), which lets you specify a Spatial Model to be run in line in your model (basically like a submodel).  If the algorithm of your model-operator is proprietary, and you do not wish for others to be able to see what you’ve done (which is one reason why you might think that a C++ operator is the way to go), you can use “Export Encrypted Model” from the popup list in the Share group on the Spatial Modeler tab.  Just don’t forget to save the model-operator as a “regular” model first, because you will not be able to reopen the encrypted model for editing.  :-)

 

Ruth

Do you need immediate support?
Please submit a Ticket through our
Development Ticket Portal.