Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "mitkPlanarPolygon.h"
00020 #include "mitkGeometry2D.h"
00021 #include "mitkProperties.h"
00022
00023
00024 #include <algorithm>
00025
00026
00027 mitk::PlanarPolygon::PlanarPolygon()
00028 : FEATURE_ID_CIRCUMFERENCE( this->AddFeature( "Circumference", "mm" ) ),
00029 FEATURE_ID_AREA( this->AddFeature( "Area", "mm^2" ) )
00030 {
00031
00032 this->ResetNumberOfControlPoints( 2 );
00033
00034
00035 this->SetProperty( "closed", mitk::BoolProperty::New( true ) );
00036
00037 m_PolyLines->InsertElement( 0, VertexContainerType::New());
00038 }
00039
00040
00041 mitk::PlanarPolygon::~PlanarPolygon()
00042 {
00043 }
00044
00045
00046 void mitk::PlanarPolygon::SetClosed( bool closed )
00047 {
00048 this->SetProperty( "closed", mitk::BoolProperty::New( closed ) );
00049
00050 if ( !closed )
00051 {
00052
00053 this->SetFeatureName( FEATURE_ID_CIRCUMFERENCE, "Length" );
00054 this->DeactivateFeature( FEATURE_ID_AREA );
00055 }
00056 else
00057 {
00058
00059 this->SetFeatureName( FEATURE_ID_CIRCUMFERENCE, "Circumference" );
00060 this->ActivateFeature( FEATURE_ID_AREA );
00061 }
00062
00063 this->Modified();
00064 }
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094 void mitk::PlanarPolygon::GeneratePolyLine()
00095 {
00096
00097 if ( m_PolyLines->ElementAt( 0 )->size() < this->GetNumberOfControlPoints() )
00098 {
00099 m_PolyLines->ElementAt( 0 )->Reserve( this->GetNumberOfControlPoints() );
00100 }
00101
00102 else if (m_PolyLines->ElementAt( 0 )->size() > this->GetNumberOfControlPoints())
00103 {
00104 m_PolyLines->ElementAt( 0 )->clear();
00105 }
00106
00107
00108
00109 m_PolyLines->ElementAt( 0 )->Reserve( this->GetNumberOfControlPoints() );
00110 for ( unsigned int i = 0; i < this->GetNumberOfControlPoints(); ++i )
00111 {
00112 m_PolyLines->ElementAt( 0 )->ElementAt( i ) = m_ControlPoints->ElementAt( i );
00113 }
00114 }
00115
00116 void mitk::PlanarPolygon::GenerateHelperPolyLine(double , unsigned int )
00117 {
00118
00119 }
00120
00121 void mitk::PlanarPolygon::EvaluateFeaturesInternal()
00122 {
00123
00124 double circumference = 0.0;
00125 unsigned int i,j;
00126 for ( i = 0; i < this->GetNumberOfControlPoints() - 1; ++i )
00127 {
00128 circumference += this->GetWorldControlPoint( i ).EuclideanDistanceTo(
00129 this->GetWorldControlPoint( i + 1 ) );
00130 }
00131
00132 if ( this->IsClosed() )
00133 {
00134 circumference += this->GetWorldControlPoint( i ).EuclideanDistanceTo(
00135 this->GetWorldControlPoint( 0 ) );
00136 }
00137
00138 this->SetQuantity( FEATURE_ID_CIRCUMFERENCE, circumference );
00139
00140
00141
00142 double area = 0.0;
00143 bool intersection = false;
00144
00145 if ( this->IsClosed() && (this->GetGeometry2D() != NULL) )
00146 {
00147
00148 unsigned int numberOfPoints = (unsigned int)GetNumberOfControlPoints();
00149 if( numberOfPoints >= 4)
00150 {
00151 for ( i = 0; i < (numberOfPoints - 1); ++i )
00152 {
00153
00154 Point2D p0 = this->GetControlPoint( i );
00155 Point2D p1 = this->GetControlPoint(i + 1);
00156
00157
00158 for (j = i+1; j < (numberOfPoints - 1); ++j )
00159 {
00160 Point2D p2 = this->GetControlPoint(j);
00161 Point2D p3 = this->GetControlPoint(j + 1);
00162 intersection = CheckForLineIntersection(p0,p1,p2,p3);
00163 if (intersection) break;
00164 }
00165 if (intersection) break;
00166
00167
00168 Point2D p2 = this->GetControlPoint(0);
00169 Point2D p3 = this->GetControlPoint(numberOfPoints - 1);
00170
00171 intersection = CheckForLineIntersection(p0,p1,p2,p3);
00172 if (intersection) break;
00173 }
00174 }
00175
00176
00177 for ( i = 0; i < this->GetNumberOfControlPoints(); ++i )
00178 {
00179 Point2D p0 = this->GetControlPoint( i );
00180 Point2D p1 = this->GetControlPoint( (i + 1) % this->GetNumberOfControlPoints() );
00181
00182 area += p0[0] * p1[1] - p1[0] * p0[1];
00183 }
00184 area /= 2.0;
00185 }
00186
00187
00188 if(this->IsClosed() && !intersection)
00189 {
00190 SetQuantity( FEATURE_ID_AREA, fabs( area ) );
00191 this->ActivateFeature( FEATURE_ID_AREA );
00192 }
00193 else
00194 {
00195 SetQuantity( FEATURE_ID_AREA, 0 );
00196 this->DeactivateFeature( FEATURE_ID_AREA );
00197 }
00198 }
00199
00200
00201 void mitk::PlanarPolygon::PrintSelf( std::ostream& os, itk::Indent indent) const
00202 {
00203 Superclass::PrintSelf( os, indent );
00204
00205 if (this->IsClosed())
00206 os << indent << "Polygon is closed\n";
00207 else
00208 os << indent << "Polygon is not closed\n";
00209 }
00210
00211
00212
00213 bool mitk::PlanarPolygon::CheckForLineIntersection(Point2D p1, Point2D p2, Point2D p3, Point2D p4)
00214 {
00215
00216 if(p1 == p2 || p1 == p3 || p1 == p4 ||
00217 p2 == p3 || p2 == p4 ||
00218 p3 == p4)
00219 return false;
00220
00221
00222
00223
00224 float x1 = p1[0], x2 = p2[0], x3 = p3[0], x4 = p4[0];
00225 float y1 = p1[1], y2 = p2[1], y3 = p3[1], y4 = p4[1];
00226
00227 float d = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
00228
00229
00230 if (d == 0) return false;
00231
00232
00233 float pre = (x1*y2 - y1*x2), post = (x3*y4 - y3*x4);
00234 float x = ( pre * (x3 - x4) - (x1 - x2) * post ) / d;
00235 float y = ( pre * (y3 - y4) - (y1 - y2) * post ) / d;
00236
00237
00238 if ( x < std::min(x1, x2) || x > std::max(x1, x2) ||
00239 x < std::min(x3, x4) || x > std::max(x3, x4) ) return false;
00240 if ( y < std::min(y1, y2) || y > std::max(y1, y2) ||
00241 y < std::min(y3, y4) || y > std::max(y3, y4) ) return false;
00242
00243
00244 Point2D ret; ret[0] = x; ret[1] = y;
00245 return true;
00246 }