HxUniformVectorField3* HxMovingLeastSquaresWarp::createOutputVectorDataSet() {
    HxUniformScalarField3* fromImage =
        dynamic_cast<HxUniformScalarField3*>(portFromImage.getSource());
    HxUniformVectorField3* output =
        dynamic_cast<HxUniformVectorField3*>(getResult(1));

    if (!fromImage)
        return (0);

    McDim3l dims;
    McBox3f bbox;

    if (fromImage) {
        dims = fromImage->lattice().getDims();
        bbox = fromImage->getBoundingBox();
    }
    if (!output || output->lattice().getDims() != dims)
        output = 0;

    if (!output) {
        output = new HxUniformVectorField3(dims, McPrimType::MC_FLOAT);
    }
    output->lattice().setBoundingBox(bbox);
    output->composeLabel(fromImage->getLabel(), "Displacement");
    setResult(1, output);
    return (output);
}
void MyComputeThreshold1::compute()
{
    // Access the input data object. The member portData (which is of
    // type HxConnection) is inherited from the base class HxModule.
    HxUniformScalarField3* field = (HxUniformScalarField3*) portData.source();

    // Check whether the input port is connected
    if (!field) return;

    // Get the input parameters from the user interface:
    float minValue = portRange.getValue(0);
    float maxValue = portRange.getValue(1);
    
    // Access size of data volume:
    const int* dims = field->lattice.dims();

    // Now loop through the whole field and count the pixels.
    int belowCnt=0, aboveCnt=0;
    for (int k=0; k<dims[2]; k++) {
	for (int j=0; j<dims[1]; j++) {
	    for (int i=0; i<dims[0]; i++) {
		// This function returns the value at this specfic grid node.
		// It implicitely casts the result to float if necessary.
		float value = field->evalReg(i,j,k);
		if (value<minValue)
		    belowCnt++;
		else if (value>maxValue)
		    aboveCnt++;
	    }
	}
    }

    // Finally print the result.
    theMsg->printf("%d voxels < %g, %d voxels > %g\n",
        belowCnt, minValue, aboveCnt, maxValue);
}
HxUniformScalarField3* HxMovingLeastSquaresWarp::createOutputDataSet() {
    HxUniformScalarField3* fromImage =
        dynamic_cast<HxUniformScalarField3*>(portFromImage.getSource());
    HxUniformScalarField3* toImage =
        dynamic_cast<HxUniformScalarField3*>(portToImage.getSource());
    HxUniformScalarField3* warpedImage =
        dynamic_cast<HxUniformScalarField3*>(getResult(0));

    if (!fromImage)
        return (0);

    McDim3l dims;
    McBox3f bbox;

    if (toImage) {
        dims = toImage->lattice().getDims();
        bbox = toImage->getBoundingBox();
    }
    if (!warpedImage || warpedImage->lattice().getDims()[0] != dims[0] ||
        warpedImage->lattice().getDims()[1] != dims[1] ||
        warpedImage->lattice().getDims()[2] != dims[2])
        warpedImage = 0;

    if (!warpedImage) {
        if (toImage->isOfType(HxUniformLabelField3::getClassTypeId())) {
            warpedImage = new HxUniformLabelField3(dims);
            ((HxUniformLabelField3*)warpedImage)->parameters =
                ((HxUniformLabelField3*)fromImage)->parameters;
        } else
            warpedImage =
                new HxUniformScalarField3(dims, fromImage->primType());
    }

    warpedImage->setBoundingBox(bbox);
    warpedImage->composeLabel(fromImage->getLabel(), "Warped");
    setResult(0, warpedImage);
    return (warpedImage);
}
void HxMovingLeastSquaresWarp::compute() {
    if (!portAction.wasHit())
        return;

    HxUniformScalarField3* fromImage =
        (HxUniformScalarField3*)portFromImage.getSource();

    HxLandmarkSet* pointSet = hxconnection_cast<HxLandmarkSet>(portData);

    if (!fromImage)
        return;

    /* It is ok to warp without landmarks, if method is rigid and
       input has a transformation */
    if (!pointSet) {
        return;
    } else if (pointSet->getNumSets() < 2) {
        theMsg->printf(
            "Error: LandmarkWarp data has to contain at least 2 sets.");
        return;
    }

    HxUniformScalarField3* outputImage;

    HxUniformVectorField3* outputVectorField = 0;

    outputImage = createOutputDataSet();
    outputVectorField = createOutputVectorDataSet();

    float* outputImageData = (float*)outputImage->lattice().dataPtr();

    McDArray<McVec2d> landmarks1, landmarks2;

    prepareLandmarks(landmarks1, landmarks2);

    MovingLeastSquares mls;
    mls.setAlpha(portAlpha.getValue());
    mls.setLandmarks(landmarks2, landmarks1);

    const McDim3l& dims = outputImage->lattice().getDims();

    McVec3f voxelSizeInOutputImage = outputImage->getVoxelSize();
    const McBox3f& bboxOfOutputImage = outputImage->getBoundingBox();
    const McBox3f& bboxOfFromImage = fromImage->getBoundingBox();
#ifdef _OPENMP
#pragma omp parallel for
#endif
    for (int i = 0; i < dims[0]; i++) {
        HxLocation3* locationInFromImage = fromImage->createLocation();
        std::cout << "\n" << i << " of " << dims[0];
        for (int j = 0; j < dims[1]; j++) {
            McVec2d currentPositionInOutput = McVec2d(
                bboxOfOutputImage[0] + (float)(i)*voxelSizeInOutputImage.x,
                bboxOfOutputImage[2] + (float)(j)*voxelSizeInOutputImage.y);
            McVec2d warpedCoordInFromImage =
                mls.interpolate(currentPositionInOutput);
            McVec3f displacement = McVec3f(
                warpedCoordInFromImage.x - currentPositionInOutput.x,
                warpedCoordInFromImage.y - currentPositionInOutput.y, 0);

            displacement = displacement * -1;
            locationInFromImage->move(McVec3f(warpedCoordInFromImage.x,
                                              warpedCoordInFromImage.y,
                                              bboxOfFromImage[4]));
            float resultValue[1];
            fromImage->eval(*locationInFromImage, resultValue);
            unsigned long pos = latticePos(i, j, 0, dims);
            outputImageData[pos] = resultValue[0];
            outputVectorField->lattice().set(i, j, 0, displacement.getValue());
        }
        delete locationInFromImage;
    }

    outputImage->touch();
    outputImage->fire();
}
void AssignEModulus::assignEModulus( GridType* grid )
{
	if ( !grid ) { return; }

	HxUniformScalarField3* image = dynamic_cast<HxUniformScalarField3*>( portImage.source() );
	if ( !image ) { return; }

	theWorkArea->startWorking( "Assigning Young's moduli to elements..." );
	theWorkArea->setProgressValue( 0.0 );

	OBLelement3D* FEelement = NULL;
	if ( dynamic_cast<HxTetraGrid*>(grid) )
	{
		FEelement = new OBLtetra;
	}
	if ( dynamic_cast<HxHexaGrid*>(grid) )
	{
		FEelement = new OBLhexa;
	}
	if ( !FEelement ) { return; }

	mculong totalElems = AmiraGrid::getNumberOfElements( grid );
	float* moduli = new float[totalElems];

	if ( portAveraging.getValue() == 0 )
	{
		HxLocation3* loc = image->createLocation();
		for ( mculong i = 0; i < totalElems; i++ )
		{
			theWorkArea->setProgressValue( (1.0*i)/totalElems );

			float intensity = 0;
			McDArray<McVec3f> vertices = AmiraGrid::getElementVertices( grid, i );
			McVec3f p = FEelement->getCenter( vertices );
			if ( loc->move( p[0], p[1], p[2] ) == 1 )
			{
				// image is valid for this location
				image->eval( loc, &intensity );
			}

			moduli[i] = this->getElasticityFromHU( intensity );
		}
		delete loc;
	}
	else if ( portAveraging.getValue() == 1 )	// Bonemat V1
	{
		// Create an instance of HxLoc3Regular instead of HxLocation3,
		// because we know we are dealing with a uniform scalar field and
		// we want access to the voxelindices
		//HxLoc3Regular* location = image->coords()->createLocation();
		HxLoc3Regular* location = (HxLoc3Regular*)image->createLocation();
		for ( mculong e = 0; e < totalElems; e++ )
		{
			theWorkArea->setProgressValue( (1.0*e)/totalElems );

			//float sum = 0.0;
			//int count = 0;
			//McVec3f pcoords;
			McDArray<McVec3f> vertices = AmiraGrid::getElementVertices( grid, e );

			//// determine bounding box of voxel indices within element
			//location->set( vertices[0][0], vertices[0][1], vertices[0][2] );
			//int indexbbox[6] = { location->ix, location->ix,
			//					location->iy, location->iy,
			//					location->iz, location->iz };
			//for ( int el = 1; el < 8; el++ )
			//{
			//	location->move( vertices[el][0], vertices[el][1], vertices[el][2] );
			//	if ( location->ix < indexbbox[0] ) { indexbbox[0] = location->ix; }
			//	if ( location->ix > indexbbox[1] ) { indexbbox[1] = location->ix; }
			//	if ( location->iy < indexbbox[2] ) { indexbbox[2] = location->iy; }
			//	if ( location->iy > indexbbox[3] ) { indexbbox[3] = location->iy; }
			//	if ( location->iz < indexbbox[4] ) { indexbbox[4] = location->iz; }
			//	if ( location->iz > indexbbox[5] ) { indexbbox[5] = location->iz; }
			//}

			//for ( int k = indexbbox[4]; k <= indexbbox[5]; k++ )
			//{
			//	for ( int j = indexbbox[2]; j <= indexbbox[3]; j++ )
			//	{
			//		for ( int i = indexbbox[0]; i <= indexbbox[1]; i++ )
			//		{
			//			float point[3];
			//			image->lattice.coords()->pos( i, j, k, point );
			//			int inside = FEelement->getIsoParam( vertices,
			//				McVec3f(point[0],point[1], point[2]), pcoords );
			//			if ( inside == 1 )
			//			{
			//				location->move( point );
			//				float value;
			//				image->eval( location, &value );
			//				sum += value;
			//				count++;
			//			}
			//		}
			//	}
			//}
			//float aveinten = 0.0;
			//if ( count > 0 )
			//{
			//	aveinten = sum/count;
			//}
			float aveinten = this->averageVoxels( FEelement, vertices, image );
			if ( aveinten == 0 )
			{
				McVec3f p = FEelement->getCenter( vertices );
				if ( location->move( p[0], p[1], p[2] ) == 1 )
				{
					// image is valid for this location
					image->eval( location, &aveinten );
				}
			}

			// ... then convert to elasticity
			moduli[e] = this->getElasticityFromHU( aveinten );
		}
		//theMsg->printf("indices range: %d %d %d %d %d %d", xmin, xmax, ymin, ymax, zmin, zmax );
		delete location;
	}
	else if ( portAveraging.getValue() == 2 )	// Bonemat V2
	{
		// determine boundary elements if requested
		McDArray<mclong> surface;
		if ( portBoundary.getValue() == 1 )
		{
			AmiraGrid::getSurfaceElements( grid, &surface );
		}

		for ( mclong i = 0; i < totalElems; i++ )
		{
			theWorkArea->setProgressValue( (1.0*i)/totalElems );

			// first determine average hounsfield unit for element...
			McDArray<McVec3f> vertices = AmiraGrid::getElementVertices( grid, i );
			float intensity = 0.0;
			if ( index( surface, i ) != -1 )
			{
				intensity = this->averageVoxels( FEelement, vertices, image );
			}
			else
			{
				intensity = this->sampleField( FEelement, vertices, image );
			}

			// ... then convert to elasticity
			moduli[i] = this->getElasticityFromHU( intensity );
		}
	}
	else if ( portAveraging.getValue() == 3 )	// Bonemat V3
	{
		// determine boundary elements if requested
		McDArray<mclong> surface;
		if ( portBoundary.getValue() == 1 )
		{
			AmiraGrid::getSurfaceElements( grid, &surface );
		}

		// first create temporarily image with hounsfield units converted into elasticity...
		//int size[3];
		//image->lattice.getSize( size[0], size[1], size[2] );
		//float bbox[6];
		//image->coords()->getBoundingBox( bbox );
		//mculong buffersize = size[0]*size[1]*size[2];
		//float* elasbuffer = new float[buffersize];
		//float HU = 0.0;
		//for ( int i = 0; i < buffersize; i++ )
		//{
		//	theWorkArea->setProgressValue( (0.3*i)/buffersize );

		//	image->lattice.eval( i, &HU );
		//	elasbuffer[i] = myParams[0] * pow((myParams[1]*(HU + myParams[2])
		//		+ myParams[3]), myParams[4]) + myParams[5];
		//}
		//HxUniformScalarField3* elasfield = new HxUniformScalarField3( size, McPrimType::mc_float, elasbuffer );
		//elasfield->lattice.setBoundingBox( bbox );

		HxUniformScalarField3* elasfield = this->convertHUtoElasField( image );

		// ... then determine the average of the field for each element
		int count = 0;
		for ( mclong i = 0; i < totalElems; i++ )
		{
			theWorkArea->setProgressValue( 0.3 + (0.7*i)/totalElems );

			McDArray<McVec3f> vertices = AmiraGrid::getElementVertices( grid, i );
			float intensity = 0.0;
			if ( index( surface, i ) != -1 )
			{
				moduli[i] = this->averageVoxels( FEelement, vertices, elasfield );
				if (moduli[i]==0)
				{
					//theMsg->printf("averageVoxels is zero for %d", i);
					count++;
				}
			}
			else
			{
				moduli[i] = this->sampleField( FEelement, vertices, elasfield );
				if (moduli[i]==0)
				{
					theMsg->printf("sampleField is zero for %d", i);
				}
			}
		}

		// create elasticity image if requested
		if ( portElasImage.getValue() == 1 )
		{
			setResult( numResults++, elasfield );
			elasfield->composeLabel( grid->getName(), "_elasticity" );
		}
		else
		{
			delete elasfield;
		}
	}

	if ( !FEelement ) { delete FEelement; FEelement = NULL; }

	this->createBins( portBins.getValue( 0 ), moduli, grid );

	// create data field if requested
	if ( portDataField.getValue() == 1 )
	{
		if ( HxTetraGrid* tetgrid = dynamic_cast<HxTetraGrid*>(grid) )
		{
			HxTetraScalarField3* scalardata = new HxTetraScalarField3( tetgrid,HxTetraData::PER_TETRA, moduli );
			setResult( numResults++, scalardata );
			scalardata->composeLabel( grid->getName(), "_youngs" );
		}
		if ( HxHexaGrid* hexgrid = dynamic_cast<HxHexaGrid*>(grid) )
		{
			HxHexaScalarField3* scalardata = new HxHexaScalarField3( hexgrid, HxHexaData::PER_HEXA, moduli );
			setResult( numResults++, scalardata );
			scalardata->composeLabel( grid->getName(), "_youngs" );
		}
	}
	else
	{
		delete [] moduli;
	}
}