Skip to content

Commit

Permalink
FIX: Pull request #124 fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
Michael Colonel authored and MichaelColonel committed Jan 7, 2020
1 parent 89834f5 commit 67f943b
Show file tree
Hide file tree
Showing 4 changed files with 156 additions and 208 deletions.
196 changes: 77 additions & 119 deletions Beams/MRML/vtkMRMLRTBeamNode.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -62,18 +62,25 @@ static const char* CONTOUR_BEV_REFERENCE_ROLE = "contourBEVRef";
namespace
{

typedef std::vector< std::pair< double, double > > PointVector;
typedef std::vector< std::array< double, 4 > > LeafDataVector;
typedef std::vector< std::pair< LeafDataVector::iterator, LeafDataVector::iterator > > SectionVector;
// visible multi-leaf collimator points
typedef std::vector< std::pair< double, double > > MLCVisiblePointVector;

// multi-leaf collimator boundary position parameters
typedef std::vector< std::array< double, 4 > > MLCBoundaryPositionVector;

// Start and stop border of multi-leaf collimator opened section
typedef std::vector< std::pair< MLCBoundaryPositionVector::iterator,
MLCBoundaryPositionVector::iterator > > MLCSectionVector;

typedef std::array< double, 6 > JawsParameters;
typedef std::pair< bool, bool > MLCType;

bool(*AreEqual)( double, double) = vtkSlicerRtCommon::AreEqualWithTolerance;

void
CreateMLCPointsFromSectionBorders( const JawsParameters& jawsParameters,
const MLCType& mlcType, const SectionVector::value_type& sectionBorder,
PointVector& side12)
CreateMLCPointsFromSectionBorder( const JawsParameters& jawsParameters,
const MLCType& mlcType, const MLCSectionVector::value_type& sectionBorder,
MLCVisiblePointVector& side12)
{
const double& jawBegin = jawsParameters[0];
const double& jawEnd = jawsParameters[1];
Expand All @@ -85,12 +92,12 @@ CreateMLCPointsFromSectionBorders( const JawsParameters& jawsParameters,
bool typeMLCX = mlcType.first;
bool typeMLCY = mlcType.second;

PointVector side1, side2; // temporary vectors to save visible points
MLCVisiblePointVector side1, side2; // temporary vectors to save visible points

LeafDataVector::iterator firstLeafIterator = sectionBorder.first;
LeafDataVector::iterator lastLeafIterator = sectionBorder.second;
LeafDataVector::iterator firstLeafIteratorJaws = firstLeafIterator;
LeafDataVector::iterator lastLeafIteratorJaws = lastLeafIterator;
MLCBoundaryPositionVector::iterator firstLeafIterator = sectionBorder.first;
MLCBoundaryPositionVector::iterator lastLeafIterator = sectionBorder.second;
MLCBoundaryPositionVector::iterator firstLeafIteratorJaws = firstLeafIterator;
MLCBoundaryPositionVector::iterator lastLeafIteratorJaws = lastLeafIterator;

// find first and last visible leaves using Jaws data
for ( auto it = firstLeafIterator; it <= lastLeafIterator; ++it)
Expand Down Expand Up @@ -142,7 +149,7 @@ CreateMLCPointsFromSectionBorders( const JawsParameters& jawsParameters,
}

// intersection between Jaws and MLC boundary (logical AND) lambda
auto intersectJawsMLC = [ jawBegin, jawEnd, typeMLCX, typeMLCY](PointVector::value_type& point)
auto intersectJawsMLC = [ jawBegin, jawEnd, typeMLCX, typeMLCY](MLCVisiblePointVector::value_type& point)
{
double& leafBoundary = point.second;
if (typeMLCX) // JawsY and MLCX
Expand Down Expand Up @@ -173,7 +180,7 @@ CreateMLCPointsFromSectionBorders( const JawsParameters& jawsParameters,
std::reverse( side2.begin(), side2.end());

// fill real points vector side12 without excessive points from side1 vector
PointVector::value_type& p = side1.front(); // start point
MLCVisiblePointVector::value_type& p = side1.front(); // start point
double& px = p.first; // x coordinate of p point
double& py = p.second; // y coordinate of p point
side12.push_back(p);
Expand Down Expand Up @@ -245,23 +252,22 @@ void vtkMRMLRTBeamNode::WriteXML(ostream& of, int nIndent)
Superclass::WriteXML(of, nIndent);

// Write all MRML node attributes into output stream
of << " BeamNumber=\"" << this->BeamNumber << "\"";
of << " BeamDescription=\"" << (this->BeamDescription ? BeamDescription : "") << "\"";
of << " BeamWeight=\"" << this->BeamWeight << "\"";

of << " X1Jaw=\"" << this->X1Jaw << "\"";
of << " X2Jaw=\"" << this->X2Jaw << "\"";
of << " Y1Jaw=\"" << this->Y1Jaw << "\"";
of << " Y2Jaw=\"" << this->Y2Jaw << "\"";
of << " SAD=\"" << this->SAD << "\"";

of << " SourceToJawsDistanceX=\"" << this->SourceToJawsDistanceX << "\"";
of << " SourceToJawsDistanceY=\"" << this->SourceToJawsDistanceY << "\"";
of << " SourceToMultiLeafCollimatorDistance=\"" << this->SourceToMultiLeafCollimatorDistance << "\"";

of << " GantryAngle=\"" << this->GantryAngle << "\"";
of << " CollimatorAngle=\"" << this->CollimatorAngle << "\"";
of << " CouchAngle=\"" << this->CouchAngle << "\"";
vtkMRMLWriteXMLBeginMacro(of);
vtkMRMLWriteXMLIntMacro( BeamNumber, BeamNumber);
vtkMRMLWriteXMLStringMacro( BeamDescription, BeamDescription);
vtkMRMLWriteXMLFloatMacro( BeamWeight, BeamWeight);
vtkMRMLWriteXMLFloatMacro( X1Jaw, X1Jaw);
vtkMRMLWriteXMLFloatMacro( X2Jaw, X2Jaw);
vtkMRMLWriteXMLFloatMacro( Y1Jaw, Y1Jaw);
vtkMRMLWriteXMLFloatMacro( Y2Jaw, Y2Jaw);
vtkMRMLWriteXMLFloatMacro( SAD, SAD);
vtkMRMLWriteXMLFloatMacro( SourceToJawsDistanceX, SourceToJawsDistanceX);
vtkMRMLWriteXMLFloatMacro( SourceToJawsDistanceY, SourceToJawsDistanceY);
vtkMRMLWriteXMLFloatMacro( SourceToMultiLeafCollimatorDistance, SourceToMultiLeafCollimatorDistance);
vtkMRMLWriteXMLFloatMacro( GantryAngle, GantryAngle);
vtkMRMLWriteXMLFloatMacro( CollimatorAngle, CollimatorAngle);
vtkMRMLWriteXMLFloatMacro( CouchAngle, CouchAngle);
vtkMRMLWriteXMLEndMacro();
}

//----------------------------------------------------------------------------
Expand All @@ -270,78 +276,30 @@ void vtkMRMLRTBeamNode::ReadXMLAttributes(const char** atts)
vtkMRMLNode::ReadXMLAttributes(atts);

// Read all MRML node attributes from two arrays of names and values
const char* attName = nullptr;
const char* attValue = nullptr;

while (*atts != nullptr)
{
attName = *(atts++);
attValue = *(atts++);

if (!strcmp(attName, "BeamNumber"))
{
this->BeamNumber = vtkVariant(attValue).ToInt();
}
else if (!strcmp(attName, "BeamDescription"))
{
this->SetBeamDescription(attValue);
}
else if (!strcmp(attName, "BeamWeight"))
{
this->BeamWeight = vtkVariant(attValue).ToDouble();
}
else if (!strcmp(attName, "X1Jaw"))
{
this->X1Jaw = vtkVariant(attValue).ToDouble();
}
else if (!strcmp(attName, "X2Jaw"))
{
this->X2Jaw = vtkVariant(attValue).ToDouble();
}
else if (!strcmp(attName, "Y1Jaw"))
{
this->Y1Jaw = vtkVariant(attValue).ToDouble();
}
else if (!strcmp(attName, "Y2Jaw"))
{
this->Y2Jaw = vtkVariant(attValue).ToDouble();
}
else if (!strcmp(attName, "SAD"))
{
this->SAD = vtkVariant(attValue).ToDouble();
}
else if (!strcmp(attName, "SourceToJawsDistanceX"))
{
this->SourceToJawsDistanceX = vtkVariant(attValue).ToDouble();
}
else if (!strcmp(attName, "SourceToJawsDistanceY"))
{
this->SourceToJawsDistanceY = vtkVariant(attValue).ToDouble();
}
else if (!strcmp(attName, "SourceToMultiLeafCollimatorDistance"))
{
this->SourceToMultiLeafCollimatorDistance = vtkVariant(attValue).ToDouble();
}
else if (!strcmp(attName, "GantryAngle"))
{
this->GantryAngle = vtkVariant(attValue).ToDouble();
}
else if (!strcmp(attName, "CollimatorAngle"))
{
this->CollimatorAngle = vtkVariant(attValue).ToDouble();
}
else if (!strcmp(attName, "CouchAngle"))
{
this->CouchAngle = vtkVariant(attValue).ToDouble();
}
}
vtkMRMLReadXMLBeginMacro(atts);
vtkMRMLReadXMLIntMacro( BeamNumber, BeamNumber);
vtkMRMLReadXMLStringMacro( BeamDescription, BeamDescription);
vtkMRMLReadXMLFloatMacro( BeamWeight, BeamWeight);
vtkMRMLReadXMLFloatMacro( X1Jaw, X1Jaw);
vtkMRMLReadXMLFloatMacro( X2Jaw, X2Jaw);
vtkMRMLReadXMLFloatMacro( Y1Jaw, Y1Jaw);
vtkMRMLReadXMLFloatMacro( Y2Jaw, Y2Jaw);
vtkMRMLReadXMLFloatMacro( SAD, SAD);
vtkMRMLReadXMLFloatMacro( SourceToJawsDistanceX, SourceToJawsDistanceX);
vtkMRMLReadXMLFloatMacro( SourceToJawsDistanceY, SourceToJawsDistanceY);
vtkMRMLReadXMLFloatMacro( SourceToMultiLeafCollimatorDistance, SourceToMultiLeafCollimatorDistance);
vtkMRMLReadXMLFloatMacro( GantryAngle, GantryAngle);
vtkMRMLReadXMLFloatMacro( CollimatorAngle, CollimatorAngle);
vtkMRMLReadXMLFloatMacro( CouchAngle, CouchAngle);
vtkMRMLReadXMLEndMacro();
}

//----------------------------------------------------------------------------
// Copy the node's attributes to this object.
// Does NOT copy: ID, FilePrefix, Name, VolumeID
void vtkMRMLRTBeamNode::Copy(vtkMRMLNode *anode)
{
int disabledModify = this->StartModify();
// Do not call Copy function of the direct model base class, as it copies the poly data too,
// which is undesired for beams, as they generate their own poly data from their properties.
vtkMRMLDisplayableNode::Copy(anode);
Expand Down Expand Up @@ -382,7 +340,8 @@ void vtkMRMLRTBeamNode::Copy(vtkMRMLNode *anode)
this->SetCollimatorAngle(node->GetCollimatorAngle());
this->SetCouchAngle(node->GetCouchAngle());

this->DisableModifiedEventOff();
this->EndModify(disabledModify);

this->InvokePendingModifiedEvent();
}

Expand Down Expand Up @@ -411,23 +370,22 @@ void vtkMRMLRTBeamNode::PrintSelf(ostream& os, vtkIndent indent)
{
Superclass::PrintSelf(os,indent);

os << indent << " BeamNumber: " << this->BeamNumber << "\n";
os << indent << " BeamDescription: " << (this->BeamDescription ? BeamDescription : "nullptr") << "\n";
os << indent << " BeamWeight: " << this->BeamWeight << "\n";

os << indent << " X1Jaw: " << this->X1Jaw << "\n";
os << indent << " X2Jaw: " << this->X2Jaw << "\n";
os << indent << " Y1Jaw: " << this->Y1Jaw << "\n";
os << indent << " Y2Jaw: " << this->Y2Jaw << "\n";
os << indent << " SAD: " << this->SAD << "\n";

os << indent << " SourceToJawsDistanceX: " << this->SourceToJawsDistanceX << "\n";
os << indent << " SourceToJawsDistanceY: " << this->SourceToJawsDistanceY << "\n";
os << indent << " SourceToMultiLeafCollimatorDistance: " << this->SourceToMultiLeafCollimatorDistance << "\n";

os << indent << " GantryAngle: " << this->GantryAngle << "\n";
os << indent << " CollimatorAngle: " << this->CollimatorAngle << "\n";
os << indent << " CouchAngle: " << this->CouchAngle << "\n";
vtkMRMLPrintBeginMacro(os, indent);
vtkMRMLPrintIntMacro(BeamNumber);
vtkMRMLPrintStringMacro(BeamDescription);
vtkMRMLPrintFloatMacro(BeamWeight);
vtkMRMLPrintFloatMacro(X1Jaw);
vtkMRMLPrintFloatMacro(X2Jaw);
vtkMRMLPrintFloatMacro(Y1Jaw);
vtkMRMLPrintFloatMacro(Y2Jaw);
vtkMRMLPrintFloatMacro(SAD);
vtkMRMLPrintFloatMacro(SourceToJawsDistanceX);
vtkMRMLPrintFloatMacro(SourceToJawsDistanceY);
vtkMRMLPrintFloatMacro(SourceToMultiLeafCollimatorDistance);
vtkMRMLPrintFloatMacro(GantryAngle);
vtkMRMLPrintFloatMacro(CollimatorAngle);
vtkMRMLPrintFloatMacro(CouchAngle);
vtkMRMLPrintEndMacro();
}

//----------------------------------------------------------------------------
Expand Down Expand Up @@ -741,7 +699,7 @@ void vtkMRMLRTBeamNode::CreateBeamPolyData(vtkPolyData* beamModelPolyData/*=null
// Check that we have MLC with Jaws opening
if (mlcTableNode && xOpened && yOpened)
{
LeafDataVector mlc; // temporary MLC vector (Boundary and Position)
MLCBoundaryPositionVector mlc;

const char* mlcName = mlcTableNode->GetName();
bool typeMLCX = !strncmp( "MLCX", mlcName, strlen("MLCX"));
Expand Down Expand Up @@ -776,7 +734,7 @@ void vtkMRMLRTBeamNode::CreateBeamPolyData(vtkPolyData* beamModelPolyData/*=null

// find first and last opened leaves visible within jaws
// and fill sections vector for further processing
SectionVector sections; // sections (first & last leaf iterator) of opened MLC
MLCSectionVector sections; // sections (first & last leaf iterator) of opened MLC
for ( auto it = mlc.begin(); it != mlc.end(); ++it)
{
double& pos1 = (*it)[2]; // leaf position "1"
Expand Down Expand Up @@ -824,27 +782,27 @@ void vtkMRMLRTBeamNode::CreateBeamPolyData(vtkPolyData* beamModelPolyData/*=null

// append one or more visible sections to beam model poly data
auto append = vtkSmartPointer<vtkAppendPolyData>::New();
for (const SectionVector::value_type& section : sections)
for (const MLCSectionVector::value_type& section : sections)
{
if (section.first != mlc.end() && section.second != mlc.end())
{
vtkSmartPointer<vtkPolyData> beamPolyData = vtkSmartPointer<vtkPolyData>::New();
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkCellArray> cellArray = vtkSmartPointer<vtkCellArray>::New();

PointVector side12; // real points for side "1" and "2"
MLCVisiblePointVector side12; // real points for side "1" and "2"
JawsParameters jawsParameters{ jawBegin, jawEnd, this->X1Jaw, this->X2Jaw, this->Y1Jaw, this->Y2Jaw };
MLCType mlcType{ typeMLCX, typeMLCY };

CreateMLCPointsFromSectionBorders( jawsParameters, mlcType,
CreateMLCPointsFromSectionBorder( jawsParameters, mlcType,
section, side12);

// fill vtk points
points->InsertPoint( 0, 0, 0, this->SAD); // source

// side "1" and "2" points vector
vtkIdType pointIds = 0;
for ( const PointVector::value_type& point : side12)
for ( const MLCVisiblePointVector::value_type& point : side12)
{
const double& x = point.first;
const double& y = point.second;
Expand Down
Loading

0 comments on commit 67f943b

Please sign in to comment.