diff --git a/src/app/qgsoptions.cpp b/src/app/qgsoptions.cpp index cfdc2d10b327..eeb30dffa8cf 100644 --- a/src/app/qgsoptions.cpp +++ b/src/app/qgsoptions.cpp @@ -198,19 +198,19 @@ QgsOptions::QgsOptions( QWidget *parent, Qt::WFlags fl ) : mDefaultSnappingToleranceSpinBox->setValue( settings.value( "/qgis/digitizing/default_snapping_tolerance", 0 ).toDouble() ); mSearchRadiusVertexEditSpinBox->setValue( settings.value( "/qgis/digitizing/search_radius_vertex_edit", 10 ).toDouble() ); int index; - if (settings.value( "/qgis/digitizing/default_snapping_tolerance_unit", 0 ).toInt() == QgsTolerance::MapUnits) + if ( settings.value( "/qgis/digitizing/default_snapping_tolerance_unit", 0 ).toInt() == QgsTolerance::MapUnits ) { index = mDefaultSnappingToleranceComboBox->findText( tr( "map units" ) ); - } + } else { index = mDefaultSnappingToleranceComboBox->findText( tr( "pixels" ) ); } mDefaultSnappingToleranceComboBox->setCurrentIndex( index ); - if (settings.value( "/qgis/digitizing/search_radius_vertex_edit_unit", 0 ).toInt() == QgsTolerance::MapUnits) + if ( settings.value( "/qgis/digitizing/search_radius_vertex_edit_unit", 0 ).toInt() == QgsTolerance::MapUnits ) { index = mSearchRadiusVertexEditComboBox->findText( tr( "map units" ) ); - } + } else { index = mSearchRadiusVertexEditComboBox->findText( tr( "pixels" ) ); @@ -242,19 +242,19 @@ QgsOptions::QgsOptions( QWidget *parent, Qt::WFlags fl ) : groupBox_5->setEnabled( false ); #endif //Q_WS_MAC - //overlay placement algorithm - mOverlayAlgorithmComboBox->insertItem(0, tr("Central point (fastest)")); - mOverlayAlgorithmComboBox->insertItem(1, tr("Chain (fast)")); - mOverlayAlgorithmComboBox->insertItem(2, tr("Popmusic tabu chain (slow)")); - mOverlayAlgorithmComboBox->insertItem(3, tr("Popmusic tabu (slow)")); - mOverlayAlgorithmComboBox->insertItem(4, tr("Popmusic chain (very slow)")); - - QString overlayAlgorithmString = settings.value( "qgis/overlayPlacementAlgorithm", "Central point").toString(); - if(overlayAlgorithmString == "Chain"){mOverlayAlgorithmComboBox->setCurrentIndex(1);} - else if(overlayAlgorithmString == "Popmusic tabu chain"){mOverlayAlgorithmComboBox->setCurrentIndex(2);} - else if(overlayAlgorithmString == "Popmusic tabu"){mOverlayAlgorithmComboBox->setCurrentIndex(3);} - else if(overlayAlgorithmString == "Popmusic chain"){mOverlayAlgorithmComboBox->setCurrentIndex(4);} - else{mOverlayAlgorithmComboBox->setCurrentIndex(0);} //default is central point + //overlay placement algorithm + mOverlayAlgorithmComboBox->insertItem( 0, tr( "Central point (fastest)" ) ); + mOverlayAlgorithmComboBox->insertItem( 1, tr( "Chain (fast)" ) ); + mOverlayAlgorithmComboBox->insertItem( 2, tr( "Popmusic tabu chain (slow)" ) ); + mOverlayAlgorithmComboBox->insertItem( 3, tr( "Popmusic tabu (slow)" ) ); + mOverlayAlgorithmComboBox->insertItem( 4, tr( "Popmusic chain (very slow)" ) ); + + QString overlayAlgorithmString = settings.value( "qgis/overlayPlacementAlgorithm", "Central point" ).toString(); + if ( overlayAlgorithmString == "Chain" ) {mOverlayAlgorithmComboBox->setCurrentIndex( 1 );} + else if ( overlayAlgorithmString == "Popmusic tabu chain" ) {mOverlayAlgorithmComboBox->setCurrentIndex( 2 );} + else if ( overlayAlgorithmString == "Popmusic tabu" ) {mOverlayAlgorithmComboBox->setCurrentIndex( 3 );} + else if ( overlayAlgorithmString == "Popmusic chain" ) {mOverlayAlgorithmComboBox->setCurrentIndex( 4 );} + else {mOverlayAlgorithmComboBox->setCurrentIndex( 0 );} //default is central point } //! Destructor @@ -346,25 +346,25 @@ void QgsOptions::saveOptions() //overlay placement method int overlayIndex = mOverlayAlgorithmComboBox->currentIndex(); - if(overlayIndex == 1) + if ( overlayIndex == 1 ) { - settings.setValue( "qgis/overlayPlacementAlgorithm", "Chain"); + settings.setValue( "qgis/overlayPlacementAlgorithm", "Chain" ); } - else if(overlayIndex == 2) + else if ( overlayIndex == 2 ) { - settings.setValue( "qgis/overlayPlacementAlgorithm", "Popmusic tabu chain"); + settings.setValue( "qgis/overlayPlacementAlgorithm", "Popmusic tabu chain" ); } - else if(overlayIndex == 3) + else if ( overlayIndex == 3 ) { - settings.setValue( "qgis/overlayPlacementAlgorithm", "Popmusic tabu"); + settings.setValue( "qgis/overlayPlacementAlgorithm", "Popmusic tabu" ); } - else if(overlayIndex == 4) + else if ( overlayIndex == 4 ) { - settings.setValue( "qgis/overlayPlacementAlgorithm", "Popmusic chain"); + settings.setValue( "qgis/overlayPlacementAlgorithm", "Popmusic chain" ); } else { - settings.setValue( "qgis/overlayPlacementAlgorithm", "Central point" ); + settings.setValue( "qgis/overlayPlacementAlgorithm", "Central point" ); } if ( cmbTheme->currentText().length() == 0 ) @@ -431,10 +431,10 @@ void QgsOptions::saveOptions() settings.setValue( "/qgis/digitizing/default_snap_mode", defaultSnapModeString ); settings.setValue( "/qgis/digitizing/default_snapping_tolerance", mDefaultSnappingToleranceSpinBox->value() ); settings.setValue( "/qgis/digitizing/search_radius_vertex_edit", mSearchRadiusVertexEditSpinBox->value() ); - settings.setValue( "/qgis/digitizing/default_snapping_tolerance_unit", - (mDefaultSnappingToleranceComboBox->currentIndex() == 0 ? QgsTolerance::MapUnits : QgsTolerance::Pixels ) ); - settings.setValue( "/qgis/digitizing/search_radius_vertex_edit_unit", - (mSearchRadiusVertexEditComboBox->currentIndex() == 0 ? QgsTolerance::MapUnits : QgsTolerance::Pixels ) ); + settings.setValue( "/qgis/digitizing/default_snapping_tolerance_unit", + ( mDefaultSnappingToleranceComboBox->currentIndex() == 0 ? QgsTolerance::MapUnits : QgsTolerance::Pixels ) ); + settings.setValue( "/qgis/digitizing/search_radius_vertex_edit_unit", + ( mSearchRadiusVertexEditComboBox->currentIndex() == 0 ? QgsTolerance::MapUnits : QgsTolerance::Pixels ) ); QString markerComboText = mMarkerStyleComboBox->currentText(); diff --git a/src/app/qgspluginregistry.cpp b/src/app/qgspluginregistry.cpp index 552837b311dd..e45daf1949f8 100644 --- a/src/app/qgspluginregistry.cpp +++ b/src/app/qgspluginregistry.cpp @@ -442,11 +442,11 @@ bool QgsPluginRegistry::isPythonPluginCompatible( QString packageName ) QList QgsPluginRegistry::pluginData() { - QList resultList; - QMap::iterator it = mPlugins.begin(); - for(; it != mPlugins.end(); ++it) - { - resultList.push_back(&(it.value())); - } - return resultList; + QList resultList; + QMap::iterator it = mPlugins.begin(); + for ( ; it != mPlugins.end(); ++it ) + { + resultList.push_back( &( it.value() ) ); + } + return resultList; } diff --git a/src/app/qgspluginregistry.h b/src/app/qgspluginregistry.h index c2ca1e33c96e..6604be434e29 100644 --- a/src/app/qgspluginregistry.h +++ b/src/app/qgspluginregistry.h @@ -86,7 +86,7 @@ class QgsPluginRegistry //! Returns metadata of all loaded plugins QList pluginData(); - + protected: //! protected constructor QgsPluginRegistry(); diff --git a/src/app/qgsprojectproperties.cpp b/src/app/qgsprojectproperties.cpp index df8039d62bc5..d388ddad7adb 100644 --- a/src/app/qgsprojectproperties.cpp +++ b/src/app/qgsprojectproperties.cpp @@ -314,7 +314,7 @@ void QgsProjectProperties::apply() { layerIdList << layerEntryIt.key(); toleranceList << QString::number( layerEntryIt->tolerance, 'f' ); - toleranceUnitList << QString::number( (int)layerEntryIt->toleranceUnit ); + toleranceUnitList << QString::number(( int )layerEntryIt->toleranceUnit ); if ( layerEntryIt->checked ) { enabledList << "enabled"; diff --git a/src/app/qgssnappingdialog.cpp b/src/app/qgssnappingdialog.cpp index 2ada458f1082..1b79467cffd7 100644 --- a/src/app/qgssnappingdialog.cpp +++ b/src/app/qgssnappingdialog.cpp @@ -95,10 +95,10 @@ QgsSnappingDialog::QgsSnappingDialog( QgsMapCanvas* canvas, const QMapfindText( tr( "to vertex and segment" ) ); } snapToComboBox->setCurrentIndex( index ); - if ( settingIt.value().toleranceUnit == 0 )//map units + if ( settingIt.value().toleranceUnit == 0 )//map units { index = toleranceUnitsComboBox->findText( tr( "map units" ) ); - } + } else { index = toleranceUnitsComboBox->findText( tr( "pixels" ) ); diff --git a/src/app/qgsvectorlayerproperties.cpp b/src/app/qgsvectorlayerproperties.cpp index 72dfaa5d1927..fe8b88bc4c58 100644 --- a/src/app/qgsvectorlayerproperties.cpp +++ b/src/app/qgsvectorlayerproperties.cpp @@ -129,13 +129,13 @@ QgsVectorLayerProperties::QgsVectorLayerProperties( QList overlayPluginList = overlayPlugins(); QList::const_iterator it = overlayPluginList.constBegin(); - for(; it != overlayPluginList.constEnd(); ++it) - { - QgsApplyDialog* d = (*it)->dialog(lyr); - position = tabWidget->addTab(d, (*it)->name()); - tabWidget->setCurrentIndex(position); //ugly, but otherwise the properties dialog is a mess - mOverlayDialogs.push_back(d); - } + for ( ; it != overlayPluginList.constEnd(); ++it ) + { + QgsApplyDialog* d = ( *it )->dialog( lyr ); + position = tabWidget->addTab( d, ( *it )->name() ); + tabWidget->setCurrentIndex( position ); //ugly, but otherwise the properties dialog is a mess + mOverlayDialogs.push_back( d ); + } tabWidget->setCurrentIndex( 0 ); } // QgsVectorLayerProperties ctor @@ -616,10 +616,10 @@ void QgsVectorLayerProperties::apply() layer->setTransparency( static_cast < unsigned int >( 255 - sliderTransparency->value() ) ); //apply overlay dialogs - for(QList::iterator it = mOverlayDialogs.begin(); it != mOverlayDialogs.end(); ++it) - { - (*it)->apply(); - } + for ( QList::iterator it = mOverlayDialogs.begin(); it != mOverlayDialogs.end(); ++it ) + { + ( *it )->apply(); + } // update symbology emit refreshLegend( layer->getLayerID(), false ); @@ -1058,21 +1058,21 @@ QList QgsVectorLayerProperties::overlayPlugins() const QgsVectorOverlayPlugin* theOverlayPlugin = 0; QList pluginData = QgsPluginRegistry::instance()->pluginData(); - for(QList::iterator it = pluginData.begin(); it != pluginData.end(); ++it) - { - if(*it) + for ( QList::iterator it = pluginData.begin(); it != pluginData.end(); ++it ) + { + if ( *it ) { - thePlugin = (*it)->plugin(); - if(thePlugin && thePlugin->type() == QgisPlugin::VECTOR_OVERLAY) - { - theOverlayPlugin = dynamic_cast(thePlugin); - if(theOverlayPlugin) + thePlugin = ( *it )->plugin(); + if ( thePlugin && thePlugin->type() == QgisPlugin::VECTOR_OVERLAY ) + { + theOverlayPlugin = dynamic_cast( thePlugin ); + if ( theOverlayPlugin ) { - pluginList.push_back(theOverlayPlugin); + pluginList.push_back( theOverlayPlugin ); } - } - } + } } + } return pluginList; } diff --git a/src/core/pal/feature.cpp b/src/core/pal/feature.cpp index 21f0b2393e61..cccda123975b 100644 --- a/src/core/pal/feature.cpp +++ b/src/core/pal/feature.cpp @@ -58,782 +58,884 @@ #define M_PI 3.14159265358979323846 #endif -namespace pal { +namespace pal +{ - Feature::Feature (Feat *feat, Layer *layer, int part, int nPart, PalGeometry *userGeom) : - layer (layer), nPart (nPart), part (part), userGeom (userGeom) { + Feature::Feature( Feat *feat, Layer *layer, int part, int nPart, PalGeometry *userGeom ) : + layer( layer ), nPart( nPart ), part( part ), userGeom( userGeom ) + { - this->uid = new char[strlen (feat->id) +1]; - strcpy (this->uid, feat->id); + this->uid = new char[strlen( feat->id ) +1]; + strcpy( this->uid, feat->id ); - label_x = -1; - label_y = -1; + label_x = -1; + label_y = -1; - xmin = feat->minmax[0]; - xmax = feat->minmax[2]; - ymin = feat->minmax[1]; - ymax = feat->minmax[3]; + xmin = feat->minmax[0]; + xmax = feat->minmax[2]; + ymin = feat->minmax[1]; + ymax = feat->minmax[3]; - nbPoints = feat->nbPoints; - x = feat->x; - y = feat->y; + nbPoints = feat->nbPoints; + x = feat->x; + y = feat->y; - int i; + int i; - nbSelfObs = feat->nbHoles; - selfObs = feat->holes; + nbSelfObs = feat->nbHoles; + selfObs = feat->holes; - holeOf = NULL; - for (i = 0;i < nbSelfObs;i++) { - selfObs[i]->holeOf = this; - } + holeOf = NULL; + for ( i = 0;i < nbSelfObs;i++ ) + { + selfObs[i]->holeOf = this; + } - this->type = feat->type; + this->type = feat->type; #ifdef _DEBUG_ - std::cout << "Corrdinates for " << layer->name << "/" << uid << " :" << nbPoints << " pts" << std::endl; - for (i = 0;i < nbPoints;i++) { - std::cout << x[i] << ";" << y[i] << std::endl; - } -#endif - - distlabel = 0; - currentAccess = 0; - - accessMutex = new SimpleMutex(); + std::cout << "Corrdinates for " << layer->name << "/" << uid << " :" << nbPoints << " pts" << std::endl; + for ( i = 0;i < nbPoints;i++ ) + { + std::cout << x[i] << ";" << y[i] << std::endl; } +#endif + distlabel = 0; + currentAccess = 0; - Feature::~Feature() { - if (x || y) { - std::cout << "Warning: coordinates not released: " << layer->name << "/" << uid << std::endl; - } - - if (uid) { - delete[] uid; - } + accessMutex = new SimpleMutex(); + } - if (nbSelfObs) { - int i; - for (i = 0;i < nbSelfObs;i++) { - if (selfObs[i]->x || selfObs[i]->y) { - std::cout << "Warning: hole coordinates not released" << std::endl; - } - delete selfObs[i]; - } - delete[] selfObs; - } - delete accessMutex; + Feature::~Feature() + { + if ( x || y ) + { + std::cout << "Warning: coordinates not released: " << layer->name << "/" << uid << std::endl; } - Layer *Feature::getLayer() { - return layer; + if ( uid ) + { + delete[] uid; } - - const char * Feature::getUID() { - return uid; + if ( nbSelfObs ) + { + int i; + for ( i = 0;i < nbSelfObs;i++ ) + { + if ( selfObs[i]->x || selfObs[i]->y ) + { + std::cout << "Warning: hole coordinates not released" << std::endl; + } + delete selfObs[i]; + } + delete[] selfObs; } - int Feature::setPositionForPoint (double x, double y, double scale, LabelPosition ***lPos, double delta_width) { + delete accessMutex; + } -#ifdef _DEBUG_ - std::cout << "SetPosition (point) : " << layer->name << "/" << uid << std::endl; -#endif + Layer *Feature::getLayer() + { + return layer; + } - int dpi = layer->pal->dpi; + const char * Feature::getUID() + { + return uid; + } - double xrm; - double yrm; + int Feature::setPositionForPoint( double x, double y, double scale, LabelPosition ***lPos, double delta_width ) + { - xrm = unit_convert(label_x, - layer->label_unit, - layer->pal->map_unit, - dpi, scale, delta_width); - - yrm = unit_convert(label_y, - layer->label_unit, - layer->pal->map_unit, - dpi, scale, delta_width); - - int nbp = layer->pal->point_p; +#ifdef _DEBUG_ + std::cout << "SetPosition (point) : " << layer->name << "/" << uid << std::endl; +#endif - //std::cout << "Nbp : " << nbp << std::endl; + int dpi = layer->pal->dpi; - int i; - int icost = 0; - int inc = 2; - double alpha; - double beta = 2 * M_PI / nbp; /* angle bw 2 pos */ + double xrm; + double yrm; - // uncomment for Wolff 2 position model test on RailwayStation - //if (nbp==2) - // beta = M_PI/2; + xrm = unit_convert( label_x, + layer->label_unit, + layer->pal->map_unit, + dpi, scale, delta_width ); - double distlabel = unit_convert(this->distlabel, - pal::PIXEL, - layer->pal->map_unit, - dpi, scale, delta_width); + yrm = unit_convert( label_y, + layer->label_unit, + layer->pal->map_unit, + dpi, scale, delta_width ); - double lx, ly; /* label pos */ + int nbp = layer->pal->point_p; - /* various alpha */ - double a90 = M_PI / 2; - double a180 = M_PI; - double a270 = a180 + a90; - double a360 = 2 * M_PI; + //std::cout << "Nbp : " << nbp << std::endl; + int i; + int icost = 0; + int inc = 2; - double gamma1, gamma2; + double alpha; + double beta = 2 * M_PI / nbp; /* angle bw 2 pos */ - if (distlabel > 0) { - gamma1 = atan2 (yrm / 2, distlabel + xrm / 2); - gamma2 = atan2 (xrm / 2, distlabel + yrm / 2); - } else { - gamma1 = gamma2 = a90 / 3.0; - } + // uncomment for Wolff 2 position model test on RailwayStation + //if (nbp==2) + // beta = M_PI/2; + double distlabel = unit_convert( this->distlabel, + pal::PIXEL, + layer->pal->map_unit, + dpi, scale, delta_width ); - if (gamma1 > a90 / 3.0) - gamma1 = a90 / 3.0; + double lx, ly; /* label pos */ - if (gamma2 > a90 / 3.0) - gamma2 = a90 / 3.0; + /* various alpha */ + double a90 = M_PI / 2; + double a180 = M_PI; + double a270 = a180 + a90; + double a360 = 2 * M_PI; - if (gamma1 == 0 || gamma2 == 0) { - std::cout << "Oups... label size error..." << std::endl; - } + double gamma1, gamma2; - *lPos = new LabelPosition *[nbp]; - - for (i = 0, alpha = M_PI / 4;i < nbp;i++, alpha += beta) { - lx = x; - ly = y; - - if (alpha > a360) - alpha -= a360; - - if (alpha < gamma1 || alpha > a360 - gamma1) { // on the right - lx += distlabel; - double iota = (alpha + gamma1); - if (iota > a360 - gamma1) - iota -= a360; - - //ly += -yrm/2.0 + tan(alpha)*(distlabel + xrm/2); - ly += -yrm + yrm * iota / (2 * gamma1); - } else if (alpha < a90 - gamma2) { // top-right - lx += distlabel * cos (alpha); - ly += distlabel * sin (alpha); - } else if (alpha < a90 + gamma2) { // top - //lx += -xrm/2.0 - tan(alpha+a90)*(distlabel + yrm/2); - lx += -xrm * (alpha - a90 + gamma2) / (2 * gamma2) ; - ly += distlabel; - } else if (alpha < a180 - gamma1) { // top left - lx += distlabel * cos (alpha) - xrm; - ly += distlabel * sin (alpha); - } else if (alpha < a180 + gamma1) { // left - lx += -distlabel - xrm; - //ly += -yrm/2.0 - tan(alpha)*(distlabel + xrm/2); - ly += - (alpha - a180 + gamma1) * yrm / (2 * gamma1); - } else if (alpha < a270 - gamma2) { // down - left - lx += distlabel * cos (alpha) - xrm; - ly += distlabel * sin (alpha) - yrm; - } else if (alpha < a270 + gamma2) { // down - ly += -distlabel - yrm; - //lx += -xrm/2.0 + tan(alpha+a90)*(distlabel + yrm/2); - lx += -xrm + (alpha - a270 + gamma2) * xrm / (2 * gamma2); - } else if (alpha < a360) { - lx += distlabel * cos (alpha); - ly += distlabel * sin (alpha) - yrm; - } + if ( distlabel > 0 ) + { + gamma1 = atan2( yrm / 2, distlabel + xrm / 2 ); + gamma2 = atan2( xrm / 2, distlabel + yrm / 2 ); + } + else + { + gamma1 = gamma2 = a90 / 3.0; + } - double cost; - if (nbp == 1) - cost = 0.0001; - else - cost = 0.0001 + 0.0020 * double (icost) / double (nbp - 1); + if ( gamma1 > a90 / 3.0 ) + gamma1 = a90 / 3.0; - (*lPos) [i] = new LabelPosition (i, lx, ly, xrm, yrm, 0, cost, this); + if ( gamma2 > a90 / 3.0 ) + gamma2 = a90 / 3.0; - icost += inc; - if (icost == nbp) { - icost = nbp - 1; - inc = -2; - } else if (icost > nbp) { - icost = nbp - 2; - inc = -2; - } + if ( gamma1 == 0 || gamma2 == 0 ) + { + std::cout << "Oups... label size error..." << std::endl; + } - } + *lPos = new LabelPosition *[nbp]; + + for ( i = 0, alpha = M_PI / 4;i < nbp;i++, alpha += beta ) + { + lx = x; + ly = y; + + if ( alpha > a360 ) + alpha -= a360; + + if ( alpha < gamma1 || alpha > a360 - gamma1 ) // on the right + { + lx += distlabel; + double iota = ( alpha + gamma1 ); + if ( iota > a360 - gamma1 ) + iota -= a360; + + //ly += -yrm/2.0 + tan(alpha)*(distlabel + xrm/2); + ly += -yrm + yrm * iota / ( 2 * gamma1 ); + } + else if ( alpha < a90 - gamma2 ) // top-right + { + lx += distlabel * cos( alpha ); + ly += distlabel * sin( alpha ); + } + else if ( alpha < a90 + gamma2 ) // top + { + //lx += -xrm/2.0 - tan(alpha+a90)*(distlabel + yrm/2); + lx += -xrm * ( alpha - a90 + gamma2 ) / ( 2 * gamma2 ) ; + ly += distlabel; + } + else if ( alpha < a180 - gamma1 ) // top left + { + lx += distlabel * cos( alpha ) - xrm; + ly += distlabel * sin( alpha ); + } + else if ( alpha < a180 + gamma1 ) // left + { + lx += -distlabel - xrm; + //ly += -yrm/2.0 - tan(alpha)*(distlabel + xrm/2); + ly += - ( alpha - a180 + gamma1 ) * yrm / ( 2 * gamma1 ); + } + else if ( alpha < a270 - gamma2 ) // down - left + { + lx += distlabel * cos( alpha ) - xrm; + ly += distlabel * sin( alpha ) - yrm; + } + else if ( alpha < a270 + gamma2 ) // down + { + ly += -distlabel - yrm; + //lx += -xrm/2.0 + tan(alpha+a90)*(distlabel + yrm/2); + lx += -xrm + ( alpha - a270 + gamma2 ) * xrm / ( 2 * gamma2 ); + } + else if ( alpha < a360 ) + { + lx += distlabel * cos( alpha ); + ly += distlabel * sin( alpha ) - yrm; + } + + double cost; + + if ( nbp == 1 ) + cost = 0.0001; + else + cost = 0.0001 + 0.0020 * double( icost ) / double( nbp - 1 ); + + ( *lPos )[i] = new LabelPosition( i, lx, ly, xrm, yrm, 0, cost, this ); + + icost += inc; + + if ( icost == nbp ) + { + icost = nbp - 1; + inc = -2; + } + else if ( icost > nbp ) + { + icost = nbp - 2; + inc = -2; + } - return nbp; } + return nbp; + } + // TODO work with squared distance by remonving call to sqrt or dist_euc2d - int Feature::setPositionForLine (double scale, LabelPosition ***lPos, PointSet *mapShape, double delta_width) { + int Feature::setPositionForLine( double scale, LabelPosition ***lPos, PointSet *mapShape, double delta_width ) + { #ifdef _DEBUG_ - std::cout << "SetPosition (line) : " << layer->name << "/" << uid << std::endl; + std::cout << "SetPosition (line) : " << layer->name << "/" << uid << std::endl; #endif - int i; - int dpi = layer->pal->dpi; - double xrm, yrm; + int i; + int dpi = layer->pal->dpi; + double xrm, yrm; - xrm = unit_convert(label_x, - layer->label_unit, - layer->pal->map_unit, - dpi, scale, delta_width); + xrm = unit_convert( label_x, + layer->label_unit, + layer->pal->map_unit, + dpi, scale, delta_width ); - yrm = unit_convert(label_y, - layer->label_unit, - layer->pal->map_unit, - dpi, scale, delta_width); + yrm = unit_convert( label_y, + layer->label_unit, + layer->pal->map_unit, + dpi, scale, delta_width ); - double distlabel = unit_convert(this->distlabel, - pal::PIXEL, - layer->pal->map_unit, - dpi, scale, delta_width); + double distlabel = unit_convert( this->distlabel, + pal::PIXEL, + layer->pal->map_unit, + dpi, scale, delta_width ); - double *d; // segments lengths distance bw pt[i] && pt[i+1] - double *ad; // absolute distance bw pt[0] and pt[i] along the line - double ll; // line length - double dist; - double bx, by, ex, ey; - int nbls; - double alpha; - double cost; + double *d; // segments lengths distance bw pt[i] && pt[i+1] + double *ad; // absolute distance bw pt[0] and pt[i] along the line + double ll; // line length + double dist; + double bx, by, ex, ey; + int nbls; + double alpha; + double cost; - //LinkedList *shapes_final; + //LinkedList *shapes_final; - //shapes_final = new LinkedList(ptrPSetCompare); + //shapes_final = new LinkedList(ptrPSetCompare); - LinkedList *positions = new LinkedList (ptrLPosCompare); + LinkedList *positions = new LinkedList ( ptrLPosCompare ); - int nbPoints; - double *x; - double *y; + int nbPoints; + double *x; + double *y; - PointSet * line = mapShape; + PointSet * line = mapShape; #ifdef _DEBUG_FULL_ - std::cout << "New line of " << line->nbPoints << " points with label " << xrm << "x" << yrm << std::endl; + std::cout << "New line of " << line->nbPoints << " points with label " << xrm << "x" << yrm << std::endl; #endif - nbPoints = line->nbPoints; - x = line->x; - y = line->y; + nbPoints = line->nbPoints; + x = line->x; + y = line->y; - d = new double[nbPoints-1]; - ad = new double[nbPoints]; + d = new double[nbPoints-1]; + ad = new double[nbPoints]; - ll = 0.0; // line length - for (i = 0;i < line->nbPoints - 1;i++) { - if (i == 0) - ad[i] = 0; - else - ad[i] = ad[i-1] + d[i-1]; + ll = 0.0; // line length + for ( i = 0;i < line->nbPoints - 1;i++ ) + { + if ( i == 0 ) + ad[i] = 0; + else + ad[i] = ad[i-1] + d[i-1]; - d[i] = dist_euc2d (x[i], y[i], x[i+1], y[i+1]); - ll += d[i]; - } + d[i] = dist_euc2d( x[i], y[i], x[i+1], y[i+1] ); + ll += d[i]; + } - ad[line->nbPoints-1] = ll; + ad[line->nbPoints-1] = ll; - nbls = (int) (ll / xrm); // ratio bw line length and label width + nbls = ( int )( ll / xrm ); // ratio bw line length and label width #ifdef _DEBUG_FULL_ - std::cout << "line length :" << ll << std::endl; - std::cout << "nblp :" << nbls << std::endl; + std::cout << "line length :" << ll << std::endl; + std::cout << "nblp :" << nbls << std::endl; #endif - dist = (ll - xrm); + dist = ( ll - xrm ); - double l; + double l; - if (nbls > 0) { - //dist /= nbls; - l = 0; - dist = min (yrm, xrm); - } else { // line length < label with => centering label position - l = - (xrm - ll) / 2.0; - dist = xrm; - ll = xrm; - } + if ( nbls > 0 ) + { + //dist /= nbls; + l = 0; + dist = min( yrm, xrm ); + } + else // line length < label with => centering label position + { + l = - ( xrm - ll ) / 2.0; + dist = xrm; + ll = xrm; + } - double birdfly; - double beta; - i = 0; - //for (i=0;i bx, by - line->getPoint (d, ad, l, &bx, &by); - // same but l = l+xrm - line->getPoint (d, ad, l + xrm, &ex, &ey); - - // Label is bigger than line ... - if (l < 0) - birdfly = sqrt ( (x[nbPoints-1] - x[0]) * (x[nbPoints-1] - x[0]) - + (y[nbPoints-1] - y[0]) * (y[nbPoints-1] - y[0])); - else - birdfly = sqrt ( (ex - bx) * (ex - bx) + (ey - by) * (ey - by)); + while ( l < ll - xrm ) + { + // => bx, by + line->getPoint( d, ad, l, &bx, &by ); + // same but l = l+xrm + line->getPoint( d, ad, l + xrm, &ex, &ey ); + + // Label is bigger than line ... + if ( l < 0 ) + birdfly = sqrt(( x[nbPoints-1] - x[0] ) * ( x[nbPoints-1] - x[0] ) + + ( y[nbPoints-1] - y[0] ) * ( y[nbPoints-1] - y[0] ) ); + else + birdfly = sqrt(( ex - bx ) * ( ex - bx ) + ( ey - by ) * ( ey - by ) ); + + cost = birdfly / xrm; + if ( cost > 0.98 ) + cost = 0.0001; + else + cost = ( 1 - cost ) / 100; + + + if (( vabs( ey - by ) < EPSILON ) && ( vabs( ex - bx ) < EPSILON ) ) + { + std::cout << "EPSILON " << EPSILON << std::endl; + std::cout << "b: " << bx << ";" << by << std::endl; + std::cout << "e: " << ex << ";" << ey << std::endl; + alpha = 0.0; + } + else + alpha = atan2( ey - by, ex - bx ); + + beta = alpha + M_PI / 2; - cost = birdfly / xrm; - if (cost > 0.98) - cost = 0.0001; - else - cost = (1 - cost) / 100; +#ifdef _DEBUG_FULL_ + std::cout << " Create new label" << std::endl; +#endif + if ( layer->arrangement == P_LINE_AROUND ) + { + positions->push_back( new LabelPosition( i, bx + cos( beta ) *distlabel , by + sin( beta ) *distlabel, xrm, yrm, alpha, cost, this ) ); // Line + positions->push_back( new LabelPosition( i, bx - cos( beta ) * ( distlabel + yrm ) , by - sin( beta ) * ( distlabel + yrm ), xrm, yrm, alpha, cost, this ) ); // Line + } + /*else if (layer->arrangement == P_HORIZ){ // TODO add P_HORIZ + positions->push_back (new LabelPosition (i, bx -yrm/2, by - yrm*sin(beta)/2, xrm, yrm, alpha, cost, this, line)); // Line + line->aliveCandidates++; + }*/ + else + { + positions->push_back( new LabelPosition( i, bx - yrm*cos( beta ) / 2, by - yrm*sin( beta ) / 2, xrm, yrm, alpha, cost, this ) ); // Line + } + + l += dist; + + i++; + + if ( nbls == 0 ) + break; + } + + //delete line; + delete[] d; + delete[] ad; - if ( (vabs (ey - by) < EPSILON) && (vabs (ex - bx) < EPSILON)) { - std::cout << "EPSILON " << EPSILON << std::endl; - std::cout << "b: " << bx << ";" << by << std::endl; - std::cout << "e: " << ex << ";" << ey << std::endl; - alpha = 0.0; - } else - alpha = atan2 (ey - by, ex - bx); + int nbp = positions->size(); + *lPos = new LabelPosition *[nbp]; + i = 0; + while ( positions->size() > 0 ) + { + ( *lPos )[i] = positions->pop_front(); + i++; + } - beta = alpha + M_PI / 2; + delete positions; -#ifdef _DEBUG_FULL_ - std::cout << " Create new label" << std::endl; + return nbp; + } + + + /* + * seg 2 + * pt3 ____________pt2 + * ¦ ¦ + * ¦ ¦ + * seg 3 ¦ BBOX ¦ seg 1 + * ¦ ¦ + * ¦____________¦ + * pt0 seg 0 pt1 + * + */ + + int Feature::setPositionForPolygon( double scale, LabelPosition ***lPos, PointSet *mapShape, double delta_width ) + { + +#ifdef _DEBUG_ + std::cout << "SetPosition (polygon) : " << layer->name << "/" << uid << std::endl; #endif - if (layer->arrangement == P_LINE_AROUND) { - positions->push_back (new LabelPosition (i, bx + cos (beta) *distlabel , by + sin (beta) *distlabel, xrm, yrm, alpha, cost, this)); // Line - positions->push_back (new LabelPosition (i, bx - cos (beta) * (distlabel + yrm) , by - sin (beta) * (distlabel + yrm), xrm, yrm, alpha, cost, this)); // Line - } - /*else if (layer->arrangement == P_HORIZ){ // TODO add P_HORIZ - positions->push_back (new LabelPosition (i, bx -yrm/2, by - yrm*sin(beta)/2, xrm, yrm, alpha, cost, this, line)); // Line - line->aliveCandidates++; - }*/ - else { - positions->push_back (new LabelPosition (i, bx - yrm*cos (beta) / 2, by - yrm*sin (beta) / 2, xrm, yrm, alpha, cost, this)); // Line - } - l += dist; + int i; + int j; - i++; + double xrm; + double yrm; - if (nbls == 0) - break; - } + xrm = unit_convert( label_x, + layer->label_unit, + layer->pal->map_unit, + layer->pal->dpi, scale, delta_width ); - //delete line; + yrm = unit_convert( label_y, + layer->label_unit, + layer->pal->map_unit, + layer->pal->dpi, scale, delta_width ); - delete[] d; - delete[] ad; + //print(); - int nbp = positions->size(); - *lPos = new LabelPosition *[nbp]; - i = 0; - while (positions->size() > 0) { - (*lPos) [i] = positions->pop_front(); - i++; - } + //LinkedList *shapes_toCut; + LinkedList *shapes_toProcess; + LinkedList *shapes_final; - delete positions; + //shapes_toCut = new LinkedList(ptrPSetCompare); + shapes_toProcess = new LinkedList ( ptrPSetCompare ); + shapes_final = new LinkedList ( ptrPSetCompare ); - return nbp; - } + mapShape->parent = NULL; + shapes_toProcess->push_back( mapShape ); - /* - * seg 2 - * pt3 ____________pt2 - * ¦ ¦ - * ¦ ¦ - * seg 3 ¦ BBOX ¦ seg 1 - * ¦ ¦ - * ¦____________¦ - * pt0 seg 0 pt1 - * - */ + splitPolygons( shapes_toProcess, shapes_final, xrm, yrm, uid ); - int Feature::setPositionForPolygon (double scale, LabelPosition ***lPos, PointSet *mapShape, double delta_width) { -#ifdef _DEBUG_ - std::cout << "SetPosition (polygon) : " << layer->name << "/" << uid << std::endl; -#endif + delete shapes_toProcess; - int i; - int j; + int nbp; - double xrm; - double yrm; + if ( shapes_final->size() > 0 ) + { + LinkedList *positions = new LinkedList ( ptrLPosCompare ); + int it; - xrm = unit_convert(label_x, - layer->label_unit, - layer->pal->map_unit, - layer->pal->dpi, scale, delta_width); + double dlx, dly; // delta from label center and bottom-left corner + double alpha; // rotation for the label + double px, py; + double dx; + double dy; + int bbid; + double beta; + double diago = sqrt( xrm * xrm / 4.0 + yrm * yrm / 4 ); + double rx, ry; + CHullBox **boxes = new CHullBox*[shapes_final->size()]; + j = 0; - yrm = unit_convert(label_y, - layer->label_unit, - layer->pal->map_unit, - layer->pal->dpi, scale, delta_width); + // Compute bounding box foreach finalShape + while ( shapes_final->size() > 0 ) + { + PointSet *shape = shapes_final->pop_front(); + boxes[j] = shape->compute_chull_bbox(); - //print(); + if ( shape->parent ) + delete shape; - //LinkedList *shapes_toCut; - LinkedList *shapes_toProcess; - LinkedList *shapes_final; + j++; + } - //shapes_toCut = new LinkedList(ptrPSetCompare); - shapes_toProcess = new LinkedList (ptrPSetCompare); - shapes_final = new LinkedList (ptrPSetCompare); + it = 0; + dx = dy = min( yrm, xrm ) / 2; - mapShape->parent = NULL; + int num_try = 0; + int max_try = 10; + do + { + for ( bbid = 0;bbid < j;bbid++ ) + { + CHullBox *box = boxes[bbid]; - shapes_toProcess->push_back (mapShape); + if (( box->length * box->width ) > ( xmax - xmin ) * ( ymax - ymin ) *5 ) + { + std::cout << "Very Large BBOX (should never occurs : bug-report please)" << std::endl; + std::cout << " Box size: " << box->length << "/" << box->width << std::endl; + std::cout << " Alpha: " << alpha << " " << alpha * 180 / M_PI << std::endl; + std::cout << " Dx;Dy: " << dx << " " << dy << std::endl; + std::cout << " LabelSizerm: " << xrm << " " << yrm << std::endl; + std::cout << " LabelSizeUn: " << label_x << " " << label_y << std::endl; + continue; + } - splitPolygons (shapes_toProcess, shapes_final, xrm, yrm, uid); +#ifdef _DEBUG_FULL_ + std::cout << "New BBox : " << bbid << std::endl; + for ( i = 0;i < 4;i++ ) + { + std::cout << box->x[i] << "\t" << box->y[i] << std::endl; + } +#endif + bool enoughPlace = false; + if ( layer->getArrangement() == P_FREE ) + { + enoughPlace = true; + px = ( box->x[0] + box->x[2] ) / 2 - xrm; + py = ( box->y[0] + box->y[2] ) / 2 - yrm; + int i, j; + + // Virtual label: center on bbox center, label size = 2x original size + // alpha = 0. + // If all corner are in bbox then place candidates horizontaly + for ( rx = px, i = 0; i < 2; rx = rx + 2 * xrm, i++ ) + { + for ( ry = py, j = 0; j < 2; ry = ry + 2 * yrm, j++ ) + { + // TODO should test with the polyone insteand of the bbox + if ( !isPointInPolygon( 4, box->x, box->y, rx, ry ) ) + { + enoughPlace = false; + break; + } + } + if ( !enoughPlace ) + { + break; + } + } - delete shapes_toProcess; + } // arrangement== FREE ? + + if ( layer->getArrangement() == P_HORIZ || enoughPlace ) + { + alpha = 0.0; // HORIZ + } + else if ( box->length > 1.5*xrm && box->width > 1.5*xrm ) + { + if ( box->alpha <= M_PI / 4 ) + { + alpha = box->alpha; + } + else + { + alpha = box->alpha - M_PI / 2; + } + } + else if ( box->length > box->width ) + { + alpha = box->alpha - M_PI / 2; + } + else + { + alpha = box->alpha; + } - int nbp; + beta = atan2( yrm, xrm ) + alpha; - if (shapes_final->size() > 0) { - LinkedList *positions = new LinkedList (ptrLPosCompare); - int it; - double dlx, dly; // delta from label center and bottom-left corner - double alpha; // rotation for the label - double px, py; - double dx; - double dy; - int bbid; - double beta; - double diago = sqrt (xrm * xrm / 4.0 + yrm * yrm / 4); - double rx, ry; - CHullBox **boxes = new CHullBox*[shapes_final->size() ]; - j = 0; + //alpha = box->alpha; - // Compute bounding box foreach finalShape - while (shapes_final->size() > 0) { - PointSet *shape = shapes_final->pop_front(); - boxes[j] = shape->compute_chull_bbox (); + // delta from label center and down-left corner + dlx = cos( beta ) * diago; + dly = sin( beta ) * diago; - if (shape->parent) - delete shape; - j++; - } + double px0, py0; - it = 0; - dx = dy = min (yrm, xrm) / 2; - - int num_try = 0; - int max_try = 10; - do { - for (bbid = 0;bbid < j;bbid++) { - CHullBox *box = boxes[bbid]; - - if ( (box->length * box->width) > (xmax - xmin) * (ymax - ymin) *5) { - std::cout << "Very Large BBOX (should never occurs : bug-report please)" << std::endl; - std::cout << " Box size: " << box->length << "/" << box->width << std::endl; - std::cout << " Alpha: " << alpha << " " << alpha * 180 / M_PI << std::endl; - std::cout << " Dx;Dy: " << dx << " " << dy << std::endl; - std::cout << " LabelSizerm: " << xrm << " " << yrm << std::endl; - std::cout << " LabelSizeUn: " << label_x << " " << label_y << std::endl; - continue; - } + px0 = box->width / 2.0; + py0 = box->length / 2.0; -#ifdef _DEBUG_FULL_ - std::cout << "New BBox : " << bbid << std::endl; - for (i = 0;i < 4;i++) { - std::cout << box->x[i] << "\t" << box->y[i] << std::endl; - } -#endif + px0 -= ceil( px0 / dx ) * dx; + py0 -= ceil( py0 / dy ) * dy; - bool enoughPlace = false; - if (layer->getArrangement() == P_FREE) { - enoughPlace = true; - px = (box->x[0] + box->x[2]) / 2 - xrm; - py = (box->y[0] + box->y[2]) / 2 - yrm; - int i, j; - - // Virtual label: center on bbox center, label size = 2x original size - // alpha = 0. - // If all corner are in bbox then place candidates horizontaly - for (rx = px, i = 0; i < 2; rx = rx + 2 * xrm, i++) { - for (ry = py, j = 0; j < 2; ry = ry + 2 * yrm, j++) { - // TODO should test with the polyone insteand of the bbox - if (!isPointInPolygon (4, box->x, box->y, rx, ry)) { - enoughPlace = false; - break; - } - } - if (!enoughPlace) { - break; - } - } - - } // arrangement== FREE ? - - if (layer->getArrangement() == P_HORIZ || enoughPlace) { - alpha = 0.0; // HORIZ - } else if (box->length > 1.5*xrm && box->width > 1.5*xrm) { - if (box->alpha <= M_PI / 4) { - alpha = box->alpha; - } else { - alpha = box->alpha - M_PI / 2; - } - } else if (box->length > box->width) { - alpha = box->alpha - M_PI / 2; - } else { - alpha = box->alpha; - } - - beta = atan2 (yrm, xrm) + alpha; - - - //alpha = box->alpha; - - // delta from label center and down-left corner - dlx = cos (beta) * diago; - dly = sin (beta) * diago; - - - double px0, py0; - - px0 = box->width / 2.0; - py0 = box->length / 2.0; - - px0 -= ceil(px0/dx) * dx; - py0 -= ceil(py0/dy) * dy; - - for (px = px0;px <= box->width;px += dx) { - for (py = py0;py <= box->length;py += dy) { - - rx = cos (box->alpha) * px + cos (box->alpha - M_PI / 2) * py; - ry = sin (box->alpha) * px + sin (box->alpha - M_PI / 2) * py; - - rx += box->x[0]; - ry += box->y[0]; - - // Only accept candidate that center is in the polygon - if (isPointInPolygon (mapShape->nbPoints, mapShape->x, mapShape->y, rx, ry)) { - positions->push_back (new LabelPosition (0, rx - dlx, ry - dly , xrm, yrm, alpha, 0.0001, this)); // Polygon - } - } - } - } // forall box - - nbp = positions->size(); - if (nbp == 0) { - dx /= 2; - dy /= 2; - num_try++; - } - } while (nbp == 0 && num_try < max_try); + for ( px = px0;px <= box->width;px += dx ) + { + for ( py = py0;py <= box->length;py += dy ) + { - nbp = positions->size(); + rx = cos( box->alpha ) * px + cos( box->alpha - M_PI / 2 ) * py; + ry = sin( box->alpha ) * px + sin( box->alpha - M_PI / 2 ) * py; - (*lPos) = new LabelPosition*[nbp]; - for (i = 0;i < nbp;i++) { - (*lPos) [i] = positions->pop_front(); - (*lPos) [i]->id = i; - } + rx += box->x[0]; + ry += box->y[0]; - for (bbid = 0;bbid < j;bbid++) { - delete boxes[bbid]; + // Only accept candidate that center is in the polygon + if ( isPointInPolygon( mapShape->nbPoints, mapShape->x, mapShape->y, rx, ry ) ) + { + positions->push_back( new LabelPosition( 0, rx - dlx, ry - dly , xrm, yrm, alpha, 0.0001, this ) ); // Polygon + } } - - delete[] boxes; - delete positions; - } else { - nbp = 0; + } + } // forall box + + nbp = positions->size(); + if ( nbp == 0 ) + { + dx /= 2; + dy /= 2; + num_try++; } + } + while ( nbp == 0 && num_try < max_try ); - delete shapes_final; + nbp = positions->size(); -#ifdef _DEBUG_FULL_ - std::cout << "NbLabelPosition: " << nbp << std::endl; -#endif - return nbp; + ( *lPos ) = new LabelPosition*[nbp]; + for ( i = 0;i < nbp;i++ ) + { + ( *lPos )[i] = positions->pop_front(); + ( *lPos )[i]->id = i; + } + + for ( bbid = 0;bbid < j;bbid++ ) + { + delete boxes[bbid]; + } + + delete[] boxes; + delete positions; + } + else + { + nbp = 0; } - void Feature::print() { - int i, j; - std::cout << "Geometry id : " << uid << std::endl; - std::cout << "Type: " << type << std::endl; - if (x && y) { - for (i = 0;i < nbPoints;i++) - std::cout << x[i] << ", " << y[i] << std::endl; - std::cout << "Obstacle: " << nbSelfObs << std::endl; - for (i = 0;i < nbSelfObs;i++) { - std::cout << " obs " << i << std::endl; - for (j = 0;j < selfObs[i]->nbPoints;j++) { - std::cout << selfObs[i]->x[j] << ";" << selfObs[i]->y[j] << std::endl; - } - } - } + delete shapes_final; - std::cout << std::endl; +#ifdef _DEBUG_FULL_ + std::cout << "NbLabelPosition: " << nbp << std::endl; +#endif + return nbp; + } + + void Feature::print() + { + int i, j; + std::cout << "Geometry id : " << uid << std::endl; + std::cout << "Type: " << type << std::endl; + if ( x && y ) + { + for ( i = 0;i < nbPoints;i++ ) + std::cout << x[i] << ", " << y[i] << std::endl; + std::cout << "Obstacle: " << nbSelfObs << std::endl; + for ( i = 0;i < nbSelfObs;i++ ) + { + std::cout << " obs " << i << std::endl; + for ( j = 0;j < selfObs[i]->nbPoints;j++ ) + { + std::cout << selfObs[i]->x[j] << ";" << selfObs[i]->y[j] << std::endl; + } + } } - int Feature::setPosition (double scale, LabelPosition ***lPos, - double bbox_min[2], double bbox_max[2], - PointSet *mapShape, RTree *candidates + std::cout << std::endl; + } + + int Feature::setPosition( double scale, LabelPosition ***lPos, + double bbox_min[2], double bbox_max[2], + PointSet *mapShape, RTree *candidates #ifdef _EXPORT_MAP_ - , std::ofstream &svgmap + , std::ofstream &svgmap #endif - ) { - int nbp = 0; - int i; - double bbox[4]; + ) + { + int nbp = 0; + int i; + double bbox[4]; #ifdef _EXPORT_MAP_ - int dpi = layer->pal->getDpi(); + int dpi = layer->pal->getDpi(); #endif - bbox[0] = bbox_min[0]; - bbox[1] = bbox_min[1]; - bbox[2] = bbox_max[0]; - bbox[3] = bbox_max[1]; + bbox[0] = bbox_min[0]; + bbox[1] = bbox_min[1]; + bbox[2] = bbox_max[0]; + bbox[3] = bbox_max[1]; - double delta = bbox_max[0] - bbox_min[0]; + double delta = bbox_max[0] - bbox_min[0]; - switch (type) { - case GEOS_POINT: - fetchCoordinates (); - nbp = setPositionForPoint (x[0], y[0], scale, lPos, delta); + switch ( type ) + { + case GEOS_POINT: + fetchCoordinates(); + nbp = setPositionForPoint( x[0], y[0], scale, lPos, delta ); #ifdef _EXPORT_MAP_ - toSVGPath (nbPoints, type, x, y, dpi , scale, - convert2pt (bbox_min[0], scale, dpi), - convert2pt (bbox_max[1], scale, dpi), - layer->name, uid, svgmap); + toSVGPath( nbPoints, type, x, y, dpi , scale, + convert2pt( bbox_min[0], scale, dpi ), + convert2pt( bbox_max[1], scale, dpi ), + layer->name, uid, svgmap ); #endif - releaseCoordinates(); + releaseCoordinates(); + break; + case GEOS_LINESTRING: + nbp = setPositionForLine( scale, lPos, mapShape, delta ); + break; + + case GEOS_POLYGON: + switch ( layer->getArrangement() ) + { + case P_POINT: + double cx, cy; + mapShape->getCentroid( cx, cy ); + nbp = setPositionForPoint( cx, cy, scale, lPos, delta ); break; - case GEOS_LINESTRING: - nbp = setPositionForLine (scale, lPos, mapShape, delta); + case P_LINE: + case P_LINE_AROUND: + nbp = setPositionForLine( scale, lPos, mapShape, delta ); + break; + default: + nbp = setPositionForPolygon( scale, lPos, mapShape, delta ); break; - - case GEOS_POLYGON: - switch (layer->getArrangement()) { - case P_POINT: - double cx, cy; - mapShape->getCentroid (cx, cy); - nbp = setPositionForPoint (cx, cy, scale, lPos, delta); - break; - case P_LINE: - case P_LINE_AROUND: - nbp = setPositionForLine (scale, lPos, mapShape, delta); - break; - default: - nbp = setPositionForPolygon (scale, lPos, mapShape, delta); - break; - } - } - - int rnbp = nbp; - - // purge candidates that are outside the bbox - for (i = 0;i < nbp;i++) { - if (! (*lPos) [i]->isIn (bbox)) { - rnbp--; - (*lPos) [i]->cost = DBL_MAX; - } else { // this one is OK - (*lPos) [i]->insertIntoIndex (candidates); - } - } - - sort ( (void**) (*lPos), nbp, costGrow); - - for (i = rnbp;i < nbp;i++) { - delete (*lPos) [i]; } - - return rnbp; } + int rnbp = nbp; + + // purge candidates that are outside the bbox + for ( i = 0;i < nbp;i++ ) + { + if ( !( *lPos )[i]->isIn( bbox ) ) + { + rnbp--; + ( *lPos )[i]->cost = DBL_MAX; + } + else // this one is OK + { + ( *lPos )[i]->insertIntoIndex( candidates ); + } + } - void Feature::fetchCoordinates() { - accessMutex->lock(); - layer->pal->tmpTime -= clock(); - if (!x && !y) { - //std::cout << "fetch feat " << layer->name << "/" << uid << std::endl; - the_geom = userGeom->getGeosGeometry(); - LinkedList *feats = splitGeom (the_geom, this->uid); - int id = 0; - while (feats->size() > 0) { - Feat *f = feats->pop_front(); - if (id == this->part) { - x = f->x; - y = f->y; - int i; - for (i = 0;i < nbSelfObs;i++) { - selfObs[i]->x = f->holes[i]->x; - selfObs[i]->y = f->holes[i]->y; - f->holes[i]->x = NULL; - f->holes[i]->y = NULL; - delete f->holes[i]; - selfObs[i]->holeOf = this; - } - if (f->holes) - delete[] f->holes; - delete f; - } else { - delete[] f->x; - delete[] f->y; - int i; - for (i = 0;i < f->nbHoles;i++) - delete f->holes[i]; - if (f->holes) - delete[] f->holes; - delete f; - } + sort(( void** )( *lPos ), nbp, costGrow ); - id++; - } - delete feats; - } - currentAccess++; - layer->pal->tmpTime += clock(); - accessMutex->unlock(); + for ( i = rnbp;i < nbp;i++ ) + { + delete( *lPos )[i]; } - - void Feature::deleteCoord() { - if (x && y) { - int i; - delete[] x; - delete[] y; - x = NULL; - y = NULL; - for (i = 0;i < nbSelfObs;i++) { - delete[] selfObs[i]->x; - delete[] selfObs[i]->y; - selfObs[i]->x = NULL; - selfObs[i]->y = NULL; - } + return rnbp; + } + + + void Feature::fetchCoordinates() + { + accessMutex->lock(); + layer->pal->tmpTime -= clock(); + if ( !x && !y ) + { + //std::cout << "fetch feat " << layer->name << "/" << uid << std::endl; + the_geom = userGeom->getGeosGeometry(); + LinkedList *feats = splitGeom( the_geom, this->uid ); + int id = 0; + while ( feats->size() > 0 ) + { + Feat *f = feats->pop_front(); + if ( id == this->part ) + { + x = f->x; + y = f->y; + int i; + for ( i = 0;i < nbSelfObs;i++ ) + { + selfObs[i]->x = f->holes[i]->x; + selfObs[i]->y = f->holes[i]->y; + f->holes[i]->x = NULL; + f->holes[i]->y = NULL; + delete f->holes[i]; + selfObs[i]->holeOf = this; + } + if ( f->holes ) + delete[] f->holes; + delete f; + } + else + { + delete[] f->x; + delete[] f->y; + int i; + for ( i = 0;i < f->nbHoles;i++ ) + delete f->holes[i]; + if ( f->holes ) + delete[] f->holes; + delete f; } + + id++; + } + delete feats; + } + currentAccess++; + layer->pal->tmpTime += clock(); + accessMutex->unlock(); + } + + + void Feature::deleteCoord() + { + if ( x && y ) + { + int i; + delete[] x; + delete[] y; + x = NULL; + y = NULL; + for ( i = 0;i < nbSelfObs;i++ ) + { + delete[] selfObs[i]->x; + delete[] selfObs[i]->y; + selfObs[i]->x = NULL; + selfObs[i]->y = NULL; + } } + } - void Feature::releaseCoordinates() { - accessMutex->lock(); - //std::cout << "release (" << currentAccess << ")" << std::endl; - if (x && y && currentAccess == 1) { - deleteCoord(); - userGeom->releaseGeosGeometry (the_geom); - } - currentAccess--; - accessMutex->unlock(); + void Feature::releaseCoordinates() + { + accessMutex->lock(); + //std::cout << "release (" << currentAccess << ")" << std::endl; + if ( x && y && currentAccess == 1 ) + { + deleteCoord(); + userGeom->releaseGeosGeometry( the_geom ); } + currentAccess--; + accessMutex->unlock(); + } } // end namespace pal diff --git a/src/core/pal/feature.h b/src/core/pal/feature.h index 6daf8a0f6e42..667ccfb507b4 100644 --- a/src/core/pal/feature.h +++ b/src/core/pal/feature.h @@ -46,198 +46,200 @@ #include "util.h" -namespace pal { - - class Pal; - class Layer; - class LabelPosition; - class SimpleMutex; - - /** - * \brief Main class to handle feature - */ - class Feature : public PointSet { - - friend class Pal; - friend class Layer; - friend class Problem; - friend class LabelPosition; - - friend bool extractFeatCallback (Feature *ft_ptr, void *ctx); - friend bool pruneLabelPositionCallback (LabelPosition *lp, void *ctx); - friend bool obstacleCallback (PointSet *feat, void *ctx); - //friend void setCost (int nblp, LabelPosition **lPos, int max_p, RTree *obstacles, double bbx[4], double bby[4]); - friend void releaseAllInIndex (RTree*); - friend bool releaseCallback (PointSet *pset, void *ctx); - friend bool filteringCallback (PointSet*, void*); +namespace pal +{ + + class Pal; + class Layer; + class LabelPosition; + class SimpleMutex; + + /** + * \brief Main class to handle feature + */ + class Feature : public PointSet + { + + friend class Pal; + friend class Layer; + friend class Problem; + friend class LabelPosition; + + friend bool extractFeatCallback( Feature *ft_ptr, void *ctx ); + friend bool pruneLabelPositionCallback( LabelPosition *lp, void *ctx ); + friend bool obstacleCallback( PointSet *feat, void *ctx ); + //friend void setCost (int nblp, LabelPosition **lPos, int max_p, RTree *obstacles, double bbx[4], double bby[4]); + friend void releaseAllInIndex( RTree* ); + friend bool releaseCallback( PointSet *pset, void *ctx ); + friend bool filteringCallback( PointSet*, void* ); protected: - //int id; /* feature no id into layer */ - double label_x; - double label_y; - - int nbSelfObs; - PointSet **selfObs; - - char *uid; - Layer *layer; - - int distlabel; - - GEOSGeometry *the_geom; - int currentAccess; - - int nPart; - int part; - - PalGeometry *userGeom; - - SimpleMutex *accessMutex; - - /** - * \brief generate candidates for point feature - * Generate candidates for point features - * \param x x coordinates of the point - * \param y y coordinates of the point - * \param scale map scale is 1:scale - * \param lPos pointer to an array of candidates, will be filled by generated candidates - * \return the number of generated cadidates - */ - int setPositionForPoint (double x, double y, double scale, LabelPosition ***lPos, double delta_width); - - /** - * \brief generate candidates for line feature - * Generate candidates for line features - * \param scale map scale is 1:scale - * \param lPos pointer to an array of candidates, will be filled by generated candidates - * \param mapShape a pointer to the line - * \return the number of generated cadidates - */ - int setPositionForLine (double scale, LabelPosition ***lPos, PointSet *mapShape, double delta_width); - - /** - * \brief generate candidates for point feature - * Generate candidates for point features - * \param scale map scale is 1:scale - * \param lPos pointer to an array of candidates, will be filled by generated candidates - * \param mapShape a pointer to the polygon - * \return the number of generated cadidates - */ - int setPositionForPolygon (double scale, LabelPosition ***lPos, PointSet *mapShape, double delta_width); - - - - /** - * \brief Feature against problem bbox - * \param bbox[0] problem x min - * \param bbox[1] problem x max - * \param bbox[2] problem y min - * \param bbox[3] problem y max - * return A set of feature which are in the bbox or null if the feature is in the bbox - */ - //LinkedList *splitFeature( double bbox[4]); - - - /** - * \brief create a new generic feature - * - * \param feat a pointer for a Feat which contains the spatial entites - * \param layer feature is in this layer - * \param part which part of the collection is this feature for ? - * \param nPart how many feats have same uid (MULTI..., Collection) - */ - Feature (Feat *feat, Layer *layer, int part, int nPart, PalGeometry *userGeom); - - - /** - * \brief Used to load pre-computed feature - * \param file the file open by Pal::Pal(const char *pal_file) + //int id; /* feature no id into layer */ + double label_x; + double label_y; + + int nbSelfObs; + PointSet **selfObs; + + char *uid; + Layer *layer; + + int distlabel; + + GEOSGeometry *the_geom; + int currentAccess; + + int nPart; + int part; + + PalGeometry *userGeom; + + SimpleMutex *accessMutex; + + /** + * \brief generate candidates for point feature + * Generate candidates for point features + * \param x x coordinates of the point + * \param y y coordinates of the point + * \param scale map scale is 1:scale + * \param lPos pointer to an array of candidates, will be filled by generated candidates + * \return the number of generated cadidates + */ + int setPositionForPoint( double x, double y, double scale, LabelPosition ***lPos, double delta_width ); + + /** + * \brief generate candidates for line feature + * Generate candidates for line features + * \param scale map scale is 1:scale + * \param lPos pointer to an array of candidates, will be filled by generated candidates + * \param mapShape a pointer to the line + * \return the number of generated cadidates + */ + int setPositionForLine( double scale, LabelPosition ***lPos, PointSet *mapShape, double delta_width ); + + /** + * \brief generate candidates for point feature + * Generate candidates for point features + * \param scale map scale is 1:scale + * \param lPos pointer to an array of candidates, will be filled by generated candidates + * \param mapShape a pointer to the polygon + * \return the number of generated cadidates + */ + int setPositionForPolygon( double scale, LabelPosition ***lPos, PointSet *mapShape, double delta_width ); + + + + /** + * \brief Feature against problem bbox + * \param bbox[0] problem x min + * \param bbox[1] problem x max + * \param bbox[2] problem y min + * \param bbox[3] problem y max + * return A set of feature which are in the bbox or null if the feature is in the bbox + */ + //LinkedList *splitFeature( double bbox[4]); + + + /** + * \brief create a new generic feature + * + * \param feat a pointer for a Feat which contains the spatial entites * \param layer feature is in this layer + * \param part which part of the collection is this feature for ? + * \param nPart how many feats have same uid (MULTI..., Collection) */ - Feature (std::ifstream *file, Layer *layer); - - /** - * \brief Delete the feature - */ - virtual ~Feature(); - - /** - * \brief return the feature id - * \return the feature id - */ - //int getId(); - - /** - * \brief return the layer that feature belongs to - * \return the layer of the feature - */ - Layer * getLayer(); - - /** - * \brief save the feature into file - * Called by Pal::save() - * \param file the file to write - */ - //void save(std::ofstream *file); - - /** - * \brief generic method to generate candidates - * This method will call either setPositionFromPoint(), setPositionFromLine or setPositionFromPolygon - * \param scale the map scale is 1:scale - * \param lPos pointer to candidates array in which candidates will be put - * \param bbox_min min values of the map extent - * \param bbox_max max values of the map extent - * \param mapShape generate candidates for this spatial entites - * \param candidates index for candidates - * \param svgmap svg map file - * \return the number of candidates in *lPos - */ - int setPosition (double scale, LabelPosition ***lPos, double bbox_min[2], double bbox_max[2], PointSet *mapShape, RTree*candidates + Feature( Feat *feat, Layer *layer, int part, int nPart, PalGeometry *userGeom ); + + + /** + * \brief Used to load pre-computed feature + * \param file the file open by Pal::Pal(const char *pal_file) + * \param layer feature is in this layer + */ + Feature( std::ifstream *file, Layer *layer ); + + /** + * \brief Delete the feature + */ + virtual ~Feature(); + + /** + * \brief return the feature id + * \return the feature id + */ + //int getId(); + + /** + * \brief return the layer that feature belongs to + * \return the layer of the feature + */ + Layer * getLayer(); + + /** + * \brief save the feature into file + * Called by Pal::save() + * \param file the file to write + */ + //void save(std::ofstream *file); + + /** + * \brief generic method to generate candidates + * This method will call either setPositionFromPoint(), setPositionFromLine or setPositionFromPolygon + * \param scale the map scale is 1:scale + * \param lPos pointer to candidates array in which candidates will be put + * \param bbox_min min values of the map extent + * \param bbox_max max values of the map extent + * \param mapShape generate candidates for this spatial entites + * \param candidates index for candidates + * \param svgmap svg map file + * \return the number of candidates in *lPos + */ + int setPosition( double scale, LabelPosition ***lPos, double bbox_min[2], double bbox_max[2], PointSet *mapShape, RTree*candidates #ifdef _EXPORT_MAP_ - , std::ofstream &svgmap + , std::ofstream &svgmap #endif - ); - - /** - * \brief get the unique id of the feature - * \return the feature unique identifier - */ - const char *getUID(); - - - /** - * \brief Print feature informations - * Print feature unique id, geometry type, points, and holes on screen - */ - void print(); - - //void toSVGPath(std::ostream &out, double scale, int xmin, int ymax, bool exportInfo); - /** - * \brief Draw the feature and its candidates in a svg file - * The svg file will be uid-scale-text.svg. For DEBUG Purpose - * \param text a text to append on filename - * \param scale the scale of the drawing - * \param nbp number of candidats in lPos - * \param lPos array of candidates - */ - //void toSvg(char *text, double scale, int nbp, LabelPosition **lPos); - - /** - * \brief Draw the feature and the convexe polygon bounding box - * The svg file will be uid-scale-text.svg. For DEBUG purpose - * \param text a text to append on filename - * \param scale the scale of the drawing - * \param nbp number of candidats in lPos - * \param lPos array of candidates - */ - //void toSvg(char *text, double scale, int nb_bb, CHullBox **bbox); - - - void deleteCoord(); - - void fetchCoordinates(); - void releaseCoordinates(); - }; + ); + + /** + * \brief get the unique id of the feature + * \return the feature unique identifier + */ + const char *getUID(); + + + /** + * \brief Print feature informations + * Print feature unique id, geometry type, points, and holes on screen + */ + void print(); + + //void toSVGPath(std::ostream &out, double scale, int xmin, int ymax, bool exportInfo); + /** + * \brief Draw the feature and its candidates in a svg file + * The svg file will be uid-scale-text.svg. For DEBUG Purpose + * \param text a text to append on filename + * \param scale the scale of the drawing + * \param nbp number of candidats in lPos + * \param lPos array of candidates + */ + //void toSvg(char *text, double scale, int nbp, LabelPosition **lPos); + + /** + * \brief Draw the feature and the convexe polygon bounding box + * The svg file will be uid-scale-text.svg. For DEBUG purpose + * \param text a text to append on filename + * \param scale the scale of the drawing + * \param nbp number of candidats in lPos + * \param lPos array of candidates + */ + //void toSvg(char *text, double scale, int nb_bb, CHullBox **bbox); + + + void deleteCoord(); + + void fetchCoordinates(); + void releaseCoordinates(); + }; } // end namespace pal diff --git a/src/core/pal/geomfunction.cpp b/src/core/pal/geomfunction.cpp index 81fbb6fec967..bedb8b1ead64 100644 --- a/src/core/pal/geomfunction.cpp +++ b/src/core/pal/geomfunction.cpp @@ -38,519 +38,591 @@ #include "feature.h" #include "util.h" -namespace pal { - - void heapsort (int *sid, int *id, const double* const x, int N) { - unsigned int n = N, i = n / 2, parent, child; - int tx; - for (;;) { - if (i > 0) { - i--; - tx = sid[i]; - } else { - n--; - if (n == 0) return; - tx = sid[n]; - sid[n] = sid[0]; - } - parent = i; - child = i * 2 + 1; - while (child < n) { - if (child + 1 < n && x[id[sid[child + 1]]] > x[id[sid[child]]]) { - child++; - } - if (x[id[sid[child]]] > x[id[tx]]) { - sid[parent] = sid[child]; - parent = child; - child = parent * 2 + 1; - } else { - break; - } - } - sid[parent] = tx; +namespace pal +{ + + void heapsort( int *sid, int *id, const double* const x, int N ) + { + unsigned int n = N, i = n / 2, parent, child; + int tx; + for ( ;; ) + { + if ( i > 0 ) + { + i--; + tx = sid[i]; + } + else + { + n--; + if ( n == 0 ) return; + tx = sid[n]; + sid[n] = sid[0]; + } + parent = i; + child = i * 2 + 1; + while ( child < n ) + { + if ( child + 1 < n && x[id[sid[child + 1]]] > x[id[sid[child]]] ) + { + child++; } + if ( x[id[sid[child]]] > x[id[tx]] ) + { + sid[parent] = sid[child]; + parent = child; + child = parent * 2 + 1; + } + else + { + break; + } + } + sid[parent] = tx; } - - - void heapsort2 (int *x, double* heap, int N) { - unsigned int n = N, i = n / 2, parent, child; - double t; - int tx; - for (;;) { - if (i > 0) { - i--; - t = heap[i]; - tx = x[i]; - } else { - n--; - if (n == 0) return; - t = heap[n]; - tx = x[n]; - heap[n] = heap[0]; - x[n] = x[0]; - } - parent = i; - child = i * 2 + 1; - while (child < n) { - if (child + 1 < n && heap[child + 1] > heap[child]) { - child++; - } - if (heap[child] > t) { - heap[parent] = heap[child]; - x[parent] = x[child]; - parent = child; - child = parent * 2 + 1; - } else { - break; - } - } - heap[parent] = t; - x[parent] = tx; + } + + + void heapsort2( int *x, double* heap, int N ) + { + unsigned int n = N, i = n / 2, parent, child; + double t; + int tx; + for ( ;; ) + { + if ( i > 0 ) + { + i--; + t = heap[i]; + tx = x[i]; + } + else + { + n--; + if ( n == 0 ) return; + t = heap[n]; + tx = x[n]; + heap[n] = heap[0]; + x[n] = x[0]; + } + parent = i; + child = i * 2 + 1; + while ( child < n ) + { + if ( child + 1 < n && heap[child + 1] > heap[child] ) + { + child++; + } + if ( heap[child] > t ) + { + heap[parent] = heap[child]; + x[parent] = x[child]; + parent = child; + child = parent * 2 + 1; } + else + { + break; + } + } + heap[parent] = t; + x[parent] = tx; } + } + + /* + * \brief return true if the two seg intersect + */ + bool isSegIntersects( double x1, double y1, double x2, double y2, // 1st segment + double x3, double y3, double x4, double y4 ) // 2nd segment + { /* - * \brief return true if the two seg intersect - */ - - bool isSegIntersects (double x1, double y1, double x2, double y2, // 1st segment - double x3, double y3, double x4, double y4) { // 2nd segment - /* - std::cout << "SegInrersect ? " << std::endl; - std::cout << " cp1 : " << cross_product (x1, y1, x2, y2, x3, y3) << std::endl; - std::cout << " cp2 : " << cross_product (x1, y1, x2, y2, x4, y4) << std::endl; - std::cout << " cp3 : " << cross_product (x3, y3, x4, y4, x1, y1) << std::endl; - std::cout << " cp4 : " << cross_product (x3, y3, x4, y4, x2, y2) << std::endl; - */ - return (cross_product (x1, y1, x2, y2, x3, y3) * cross_product (x1, y1, x2, y2, x4, y4) < 0 - && cross_product (x3, y3, x4, y4, x1, y1) * cross_product (x3, y3, x4, y4, x2, y2) < 0); - } + std::cout << "SegInrersect ? " << std::endl; + std::cout << " cp1 : " << cross_product (x1, y1, x2, y2, x3, y3) << std::endl; + std::cout << " cp2 : " << cross_product (x1, y1, x2, y2, x4, y4) << std::endl; + std::cout << " cp3 : " << cross_product (x3, y3, x4, y4, x1, y1) << std::endl; + std::cout << " cp4 : " << cross_product (x3, y3, x4, y4, x2, y2) << std::endl; + */ + return ( cross_product( x1, y1, x2, y2, x3, y3 ) * cross_product( x1, y1, x2, y2, x4, y4 ) < 0 + && cross_product( x3, y3, x4, y4, x1, y1 ) * cross_product( x3, y3, x4, y4, x2, y2 ) < 0 ); + } - /* - */ + /* + */ - bool computeSegIntersectionExt (double x1, double y1, double x2, double y2, double xs1, double ys1, // 1st (segment) - double x3, double y3, double x4, double y4, double xs2, double ys2, // 2nd segment - double *x, double *y) { - double cp1, cp2, cp3, cp4; - cp1 = cross_product (x1, y1, x2, y2, x3, y3); - cp2 = cross_product (x1, y1, x2, y2, x4, y4); - cp3 = cross_product (x3, y3, x4, y4, x1, y1); - cp4 = cross_product (x3, y3, x4, y4, x2, y2); + bool computeSegIntersectionExt( double x1, double y1, double x2, double y2, double xs1, double ys1, // 1st (segment) + double x3, double y3, double x4, double y4, double xs2, double ys2, // 2nd segment + double *x, double *y ) + { + double cp1, cp2, cp3, cp4; + cp1 = cross_product( x1, y1, x2, y2, x3, y3 ); + cp2 = cross_product( x1, y1, x2, y2, x4, y4 ); + cp3 = cross_product( x3, y3, x4, y4, x1, y1 ); + cp4 = cross_product( x3, y3, x4, y4, x2, y2 ); - if (cp1 == 0 && cp2 == 0 && cp3 == 0 && cp4 == 0) { + if ( cp1 == 0 && cp2 == 0 && cp3 == 0 && cp4 == 0 ) + { #ifdef _DEBUG_FULL_ - std::cout << "coolineaire..." << std::endl; + std::cout << "coolineaire..." << std::endl; #endif - return false; - } + return false; + } - // 1 ter - if (cp1 == 0 && cp3 == 0) { + // 1 ter + if ( cp1 == 0 && cp3 == 0 ) + { #ifdef _DEBUG_FULL_ - std::cout << "cp1 = cp3 = 0 => ignoring..." << std::endl; + std::cout << "cp1 = cp3 = 0 => ignoring..." << std::endl; #endif - return false; - } + return false; + } - // 1 bis - if (cp1 == 0 && cp4 == 0) { + // 1 bis + if ( cp1 == 0 && cp4 == 0 ) + { #ifdef _DEBUG_FULL_ - std::cout << "cp1 = cp4 = 0 => ignoring..." << std::endl; + std::cout << "cp1 = cp4 = 0 => ignoring..." << std::endl; #endif - return false; - } + return false; + } - // 1 bis - if (cp2 == 0 && cp3 == 0) { + // 1 bis + if ( cp2 == 0 && cp3 == 0 ) + { #ifdef _DEBUG_FULL_ - std::cout << "cp2 = cp3 = 0 => ignoring..." << std::endl; + std::cout << "cp2 = cp3 = 0 => ignoring..." << std::endl; #endif - return false; - } + return false; + } - // 2bis and 3bis - if (cp1 == 0 || cp3 == 0) { + // 2bis and 3bis + if ( cp1 == 0 || cp3 == 0 ) + { #ifdef _DEBUG_FULL_ - std::cout << "skip..." << std::endl; + std::cout << "skip..." << std::endl; #endif - return false; - } - - // case 3 - if (cp4 == 0 && cp1 * cp1 < 0) { - if (cross_product (x3, y3, x4, y4, xs1, ys1) * cp3 < 0) { - *x = x2; - *y = y2; - return true; - } else - return false; - } + return false; + } - // case 2 - if (cp2 == 0 && cp3 * cp4 < 0) { - if (cross_product (x1, y1, x2, y2, xs2, ys2) * cp1 < 0) { - *x = x4; - *y = y4; - return true; - } else - return false; - } + // case 3 + if ( cp4 == 0 && cp1 * cp1 < 0 ) + { + if ( cross_product( x3, y3, x4, y4, xs1, ys1 ) * cp3 < 0 ) + { + *x = x2; + *y = y2; + return true; + } + else + return false; + } - // case 1 - if (cp2 == 0 && cp4 == 0) { - double distance[4]; - double cx, cy; - double dx, dy; - double nx[4], ny[4]; - double toDist; - double ratio; - int i; + // case 2 + if ( cp2 == 0 && cp3 * cp4 < 0 ) + { + if ( cross_product( x1, y1, x2, y2, xs2, ys2 ) * cp1 < 0 ) + { + *x = x4; + *y = y4; + return true; + } + else + return false; + } - cx = x2; - cy = y2; + // case 1 + if ( cp2 == 0 && cp4 == 0 ) + { + double distance[4]; + double cx, cy; + double dx, dy; + double nx[4], ny[4]; + double toDist; + double ratio; + int i; - nx[0] = x1; - ny[0] = y1; + cx = x2; + cy = y2; - nx[1] = xs1; - ny[1] = ys1; + nx[0] = x1; + ny[0] = y1; - nx[2] = x3; - ny[2] = y3; + nx[1] = xs1; + ny[1] = ys1; - nx[3] = xs2; - ny[3] = ys2; + nx[2] = x3; + ny[2] = y3; - distance[0] = dist_euc2d (cx, cy, x1, y1); // i - toDist = distance[0]; + nx[3] = xs2; + ny[3] = ys2; - distance[1] = dist_euc2d (cx, cy, xs1, ys1);// j2 - toDist = max (toDist, distance[1]); + distance[0] = dist_euc2d( cx, cy, x1, y1 ); // i + toDist = distance[0]; - distance[2] = dist_euc2d (cx, cy, x3, y3);// k - toDist = max (toDist, distance[2]); + distance[1] = dist_euc2d( cx, cy, xs1, ys1 );// j2 + toDist = max( toDist, distance[1] ); - distance[3] = dist_euc2d (cx, cy, xs2, ys2); // l2 - toDist = max (toDist, distance[3]); + distance[2] = dist_euc2d( cx, cy, x3, y3 );// k + toDist = max( toDist, distance[2] ); - for (i = 0;i < 4;i++) { - dx = nx[i] - cx; - dy = ny[i] - cy; + distance[3] = dist_euc2d( cx, cy, xs2, ys2 ); // l2 + toDist = max( toDist, distance[3] ); - ratio = toDist / distance[i]; + for ( i = 0;i < 4;i++ ) + { + dx = nx[i] - cx; + dy = ny[i] - cy; - nx[i] = cx + dx * ratio; - ny[i] = cy + dy * ratio; - } + ratio = toDist / distance[i]; - bool return_val = computeSegIntersection (nx[0], ny[0], nx[1], ny[1], nx[2], ny[2], nx[3], ny[3], x, y); + nx[i] = cx + dx * ratio; + ny[i] = cy + dy * ratio; + } - return return_val; - } + bool return_val = computeSegIntersection( nx[0], ny[0], nx[1], ny[1], nx[2], ny[2], nx[3], ny[3], x, y ); - if (cp1 * cp2 <= 0 - && cp3 *cp4 <= 0) { - return computeLineIntersection (x1, y1, x2, y2, x3, y3, x4, y4, x, y); - } + return return_val; + } - return false; + if ( cp1 * cp2 <= 0 + && cp3 *cp4 <= 0 ) + { + return computeLineIntersection( x1, y1, x2, y2, x3, y3, x4, y4, x, y ); } + return false; + } - /* - * \brief Intersection bw a line and a segment - * \return true if the point exist false otherwise - */ - bool computeLineSegIntersection (double x1, double y1, double x2, double y2, // 1st line - double x3, double y3, double x4, double y4, // 2nd segment - double *x, double *y) { - double cp1, cp2; - cp1 = cross_product (x1, y1, x2, y2, x3, y3); - cp2 = cross_product (x1, y1, x2, y2, x4, y4); - - if (cp1 * cp2 <= 0) - return computeLineIntersection (x1, y1, x2, y2, x3, y3, x4, y4, x, y); - return false; - } + /* + * \brief Intersection bw a line and a segment + * \return true if the point exist false otherwise + */ + bool computeLineSegIntersection( double x1, double y1, double x2, double y2, // 1st line + double x3, double y3, double x4, double y4, // 2nd segment + double *x, double *y ) + { + double cp1, cp2; + cp1 = cross_product( x1, y1, x2, y2, x3, y3 ); + cp2 = cross_product( x1, y1, x2, y2, x4, y4 ); + if ( cp1 * cp2 <= 0 ) + return computeLineIntersection( x1, y1, x2, y2, x3, y3, x4, y4, x, y ); + return false; + } - /* - * \brief compute the point wherre two segment intersects - * \return true if the point exist false otherwise - */ - - bool computeSegIntersection (double x1, double y1, double x2, double y2, // 1st (segment) - double x3, double y3, double x4, double y4, // 2nd segment - double *x, double *y) { - double cp1, cp2, cp3, cp4; - cp1 = cross_product (x1, y1, x2, y2, x3, y3); - cp2 = cross_product (x1, y1, x2, y2, x4, y4); - cp3 = cross_product (x3, y3, x4, y4, x1, y1); - cp4 = cross_product (x3, y3, x4, y4, x2, y2); - - if (cp1 * cp2 <= 0 - && cp3 *cp4 <= 0) - return computeLineIntersection (x1, y1, x2, y2, x3, y3, x4, y4, x, y); - return false; - } - /* - * \brief compute the point wherre two lines intersects - * \return true if the ok false if line are parallel - */ - bool computeLineIntersection (double x1, double y1, double x2, double y2, // 1st line (segment) - double x3, double y3, double x4, double y4, // 2nd line segment - double *x, double *y) { - - double a1, a2, b1, b2, c1, c2; - double denom; - - a1 = y2 - y1; - b1 = x1 - x2; - c1 = x2 * y1 - x1 * y2; - - a2 = y4 - y3; - b2 = x3 - x4; - c2 = x4 * y3 - x3 * y4; - - if ( (denom = a1 * b2 - a2 * b1) == 0) { - return false; - } else { - *x = (b1 * c2 - b2 * c1) / denom; - *y = (a2 * c1 - a1 * c2) / denom; - } + /* + * \brief compute the point wherre two segment intersects + * \return true if the point exist false otherwise + */ - return true; + bool computeSegIntersection( double x1, double y1, double x2, double y2, // 1st (segment) + double x3, double y3, double x4, double y4, // 2nd segment + double *x, double *y ) + { + double cp1, cp2, cp3, cp4; + cp1 = cross_product( x1, y1, x2, y2, x3, y3 ); + cp2 = cross_product( x1, y1, x2, y2, x4, y4 ); + cp3 = cross_product( x3, y3, x4, y4, x1, y1 ); + cp4 = cross_product( x3, y3, x4, y4, x2, y2 ); - } + if ( cp1 * cp2 <= 0 + && cp3 *cp4 <= 0 ) + return computeLineIntersection( x1, y1, x2, y2, x3, y3, x4, y4, x, y ); + return false; + } + /* + * \brief compute the point wherre two lines intersects + * \return true if the ok false if line are parallel + */ + bool computeLineIntersection( double x1, double y1, double x2, double y2, // 1st line (segment) + double x3, double y3, double x4, double y4, // 2nd line segment + double *x, double *y ) + { - /* - * \brief Compute the convex hull in O(n·log(n)) - * \param id set of point (i.e. point no 0 is (x,y) = x[id[0]],y[id[0]]) - * \param x x coordinates - * \param y y coordinates - * \param n Size of subset (vector id) - * \param cHull returns the point id (id of id's vector...) whom are parts of the convex hull - * \return convexHull's size - */ - int convexHullId (int *id, const double* const x, const double* const y, int n, int *&cHull) { - int i; - - cHull = new int[n]; - for (i = 0;i < n;i++) { - cHull[i] = i; - } + double a1, a2, b1, b2, c1, c2; + double denom; + + a1 = y2 - y1; + b1 = x1 - x2; + c1 = x2 * y1 - x1 * y2; + a2 = y4 - y3; + b2 = x3 - x4; + c2 = x4 * y3 - x3 * y4; - if (n <= 3) return n; + if (( denom = a1 * b2 - a2 * b1 ) == 0 ) + { + return false; + } + else + { + *x = ( b1 * c2 - b2 * c1 ) / denom; + *y = ( a2 * c1 - a1 * c2 ) / denom; + } - int* stack = new int[n]; - double* tan = new double [n]; - int ref; + return true; - int second, top; - double result; + } - // find the lowest y value - heapsort (cHull, id, y, n); - // find the lowest x value from the lowest y - ref = 1; - while (ref < n && vabs (y[id[cHull[ref]]] - y[id[cHull[0]]]) < EPSILON) ref++; - heapsort (cHull, id, x, ref); + /* + * \brief Compute the convex hull in O(n·log(n)) + * \param id set of point (i.e. point no 0 is (x,y) = x[id[0]],y[id[0]]) + * \param x x coordinates + * \param y y coordinates + * \param n Size of subset (vector id) + * \param cHull returns the point id (id of id's vector...) whom are parts of the convex hull + * \return convexHull's size + */ + int convexHullId( int *id, const double* const x, const double* const y, int n, int *&cHull ) + { + int i; - // the first point is now for sure in the hull as well as the ref one - for (i = ref; i < n; i++) { - if (vabs (y[id[cHull[i]]] - y[id[cHull[0]]]) < EPSILON) - tan[i] = FLT_MAX; - else - tan[i] = (x[id[cHull[0]]] - x[id[cHull[i]]]) / (y[id[cHull[i]]] - y[id[cHull[0]]]); - } + cHull = new int[n]; + for ( i = 0;i < n;i++ ) + { + cHull[i] = i; + } - if (ref < n) - heapsort2 (cHull + ref, tan + ref, n - ref); - - // the second point is in too - stack[0] = cHull[0]; - if (ref == 1) { - stack[1] = cHull[1]; - ref++; - } else - stack[1] = cHull[ref-1]; - - - top = 1; - second = 0; - - for (i = ref; i < n; i++) { - result = cross_product (x[id[stack[second]]], y[id[stack[second]]], - x[id[stack[top]]], y[id[stack[top]]], x[id[cHull[i]]], y[id[cHull[i]]]); - // Coolineaire !! garder le plus éloigné - if (vabs (result) < EPSILON) { - if (dist_euc2d_sq (x[id[stack[second]]], y[id[stack[second]]], x[id[cHull[i]]], y[id[cHull[i]]]) - > dist_euc2d_sq (x[id[stack[second]]], y[id[stack[second]]], x[id[stack[top]]], y[id[stack[top]]])) { - stack[top] = cHull[i]; - } - } else if (result > 0) { //convexe - second++; - top++; - stack[top] = cHull[i]; - } else { - while (result < 0 && top > 1) { - second--; - top--; - result = cross_product (x[id[stack[second]]], - y[id[stack[second]]], x[id[stack[top]]], - y[id[stack[top]]], x[id[cHull[i]]], y[id[cHull[i]]]); - } - second++; - top++; - stack[top] = cHull[i]; - } - } - for (i = 0;i <= top;i++) { - cHull[i] = stack[i]; - } + if ( n <= 3 ) return n; + + int* stack = new int[n]; + double* tan = new double [n]; + int ref; + + int second, top; + double result; + + // find the lowest y value + heapsort( cHull, id, y, n ); - delete[] stack; - delete[] tan; + // find the lowest x value from the lowest y + ref = 1; + while ( ref < n && vabs( y[id[cHull[ref]]] - y[id[cHull[0]]] ) < EPSILON ) ref++; - return top + 1; + heapsort( cHull, id, x, ref ); + + // the first point is now for sure in the hull as well as the ref one + for ( i = ref; i < n; i++ ) + { + if ( vabs( y[id[cHull[i]]] - y[id[cHull[0]]] ) < EPSILON ) + tan[i] = FLT_MAX; + else + tan[i] = ( x[id[cHull[0]]] - x[id[cHull[i]]] ) / ( y[id[cHull[i]]] - y[id[cHull[0]]] ); } -// reorder points to have cross prod ((x,y)[i], (x,y)[i+1), point) > 0 when point is outside - int reorderPolygon (int nbPoints, double *x, double *y) { - int inc = 0; - int *cHull; - int cHullSize; - int i; - - int *pts = new int[nbPoints]; - for (i = 0;i < nbPoints;i++) - pts[i] = i; - - - cHullSize = convexHullId (pts, x, y, nbPoints, cHull); - - if (pts[cHull[0]] < pts[cHull[1]] && pts[cHull[1]] < pts[cHull[2]]) - inc = 1; - else if (pts[cHull[0]] > pts[cHull[1]] && pts[cHull[1]] > pts[cHull[2]]) - inc = -1; - else if (pts[cHull[0]] > pts[cHull[1]] && pts[cHull[1]] < pts[cHull[2]] && pts[cHull[2]] < pts[cHull[0]]) - inc = 1; - else if (pts[cHull[0]] > pts[cHull[1]] && pts[cHull[1]] < pts[cHull[2]] && pts[cHull[2]] > pts[cHull[0]]) - inc = -1; - else if (pts[cHull[0]] < pts[cHull[1]] && pts[cHull[1]] > pts[cHull[2]] && pts[cHull[2]] > pts[cHull[0]]) - inc = -1; - else if (pts[cHull[0]] < pts[cHull[1]] && pts[cHull[1]] > pts[cHull[2]] && pts[cHull[2]] < pts[cHull[0]]) - inc = 1; - else { - std::cout << "Warning wrong cHull -> geometry: " << nbPoints << std::endl; - for (i = 0;i < nbPoints;i++) { - std::cout << x[i] << ";" << y[i] << std::endl; - } - std::cout << "hull : " << cHullSize << std::endl; - for (i = 0;i < cHullSize;i++) { - std::cout << pts[cHull[i]] << " "; - } - std::cout << std::endl; - delete[] cHull; - delete[] pts; - return -1; - } + if ( ref < n ) + heapsort2( cHull + ref, tan + ref, n - ref ); - if (inc == -1) { // re-order points - double tmp; - int j; - for (i = 0, j = nbPoints - 1;i <= j;i++, j--) { - tmp = x[i]; - x[i] = x[j]; - x[j] = tmp; - - tmp = y[i]; - y[i] = y[j]; - y[j] = tmp; - } + // the second point is in too + stack[0] = cHull[0]; + if ( ref == 1 ) + { + stack[1] = cHull[1]; + ref++; + } + else + stack[1] = cHull[ref-1]; + + + top = 1; + second = 0; + + for ( i = ref; i < n; i++ ) + { + result = cross_product( x[id[stack[second]]], y[id[stack[second]]], + x[id[stack[top]]], y[id[stack[top]]], x[id[cHull[i]]], y[id[cHull[i]]] ); + // Coolineaire !! garder le plus éloigné + if ( vabs( result ) < EPSILON ) + { + if ( dist_euc2d_sq( x[id[stack[second]]], y[id[stack[second]]], x[id[cHull[i]]], y[id[cHull[i]]] ) + > dist_euc2d_sq( x[id[stack[second]]], y[id[stack[second]]], x[id[stack[top]]], y[id[stack[top]]] ) ) + { + stack[top] = cHull[i]; + } + } + else if ( result > 0 ) //convexe + { + second++; + top++; + stack[top] = cHull[i]; + } + else + { + while ( result < 0 && top > 1 ) + { + second--; + top--; + result = cross_product( x[id[stack[second]]], + y[id[stack[second]]], x[id[stack[top]]], + y[id[stack[top]]], x[id[cHull[i]]], y[id[cHull[i]]] ); } + second++; + top++; + stack[top] = cHull[i]; + } + } + for ( i = 0;i <= top;i++ ) + { + cHull[i] = stack[i]; + } - delete[] cHull; - delete[] pts; + delete[] stack; + delete[] tan; - return 0; + return top + 1; + } +// reorder points to have cross prod ((x,y)[i], (x,y)[i+1), point) > 0 when point is outside + int reorderPolygon( int nbPoints, double *x, double *y ) + { + int inc = 0; + int *cHull; + int cHullSize; + int i; + + int *pts = new int[nbPoints]; + for ( i = 0;i < nbPoints;i++ ) + pts[i] = i; + + + cHullSize = convexHullId( pts, x, y, nbPoints, cHull ); + + if ( pts[cHull[0]] < pts[cHull[1]] && pts[cHull[1]] < pts[cHull[2]] ) + inc = 1; + else if ( pts[cHull[0]] > pts[cHull[1]] && pts[cHull[1]] > pts[cHull[2]] ) + inc = -1; + else if ( pts[cHull[0]] > pts[cHull[1]] && pts[cHull[1]] < pts[cHull[2]] && pts[cHull[2]] < pts[cHull[0]] ) + inc = 1; + else if ( pts[cHull[0]] > pts[cHull[1]] && pts[cHull[1]] < pts[cHull[2]] && pts[cHull[2]] > pts[cHull[0]] ) + inc = -1; + else if ( pts[cHull[0]] < pts[cHull[1]] && pts[cHull[1]] > pts[cHull[2]] && pts[cHull[2]] > pts[cHull[0]] ) + inc = -1; + else if ( pts[cHull[0]] < pts[cHull[1]] && pts[cHull[1]] > pts[cHull[2]] && pts[cHull[2]] < pts[cHull[0]] ) + inc = 1; + else + { + std::cout << "Warning wrong cHull -> geometry: " << nbPoints << std::endl; + for ( i = 0;i < nbPoints;i++ ) + { + std::cout << x[i] << ";" << y[i] << std::endl; + } + std::cout << "hull : " << cHullSize << std::endl; + for ( i = 0;i < cHullSize;i++ ) + { + std::cout << pts[cHull[i]] << " "; + } + std::cout << std::endl; + delete[] cHull; + delete[] pts; + return -1; } + if ( inc == -1 ) // re-order points + { + double tmp; + int j; + for ( i = 0, j = nbPoints - 1;i <= j;i++, j-- ) + { + tmp = x[i]; + x[i] = x[j]; + x[j] = tmp; + + tmp = y[i]; + y[i] = y[j]; + y[j] = tmp; + } + } - bool isPointInPolygon (int npol, double *xp, double *yp, double x, double y) { - // code from Randolph Franklin (found at http://local.wasp.uwa.edu.au/~pbourke/geometry/insidepoly/) - int i, j; - bool c = false; - for (i = 0, j = npol - 1; i < npol; j = i++) { - if ( ( ( (yp[i] <= y) && (y < yp[j])) || - ( (yp[j] <= y) && (y < yp[i]))) - && (x < (xp[j] - xp[i]) * (y - yp[i]) / (yp[j] - yp[i]) + xp[i])) { - c = !c; - } - } - return c; + delete[] cHull; + delete[] pts; + + return 0; + + } + + + bool isPointInPolygon( int npol, double *xp, double *yp, double x, double y ) + { + // code from Randolph Franklin (found at http://local.wasp.uwa.edu.au/~pbourke/geometry/insidepoly/) + int i, j; + bool c = false; + + for ( i = 0, j = npol - 1; i < npol; j = i++ ) + { + if (((( yp[i] <= y ) && ( y < yp[j] ) ) || + (( yp[j] <= y ) && ( y < yp[i] ) ) ) + && ( x < ( xp[j] - xp[i] ) * ( y - yp[i] ) / ( yp[j] - yp[i] ) + xp[i] ) ) + { + c = !c; + } } + return c; + } #ifdef _EXPORT_MAP_ - void toSVGPath (int nbPoints, int geomType, double *x, double *y, - int dpi, double scale, int xmin, int ymax, - char *layername, char *objectID, - std::ostream &out) { - int i; - - if (nbPoints > 1) { - out << " \n"; - } else { - int cx = convert2pt (x[0], scale, dpi) - xmin; - int cy = ymax - convert2pt (y[0], scale, dpi); - out << " \n"; - } + void toSVGPath( int nbPoints, int geomType, double *x, double *y, + int dpi, double scale, int xmin, int ymax, + char *layername, char *objectID, + std::ostream &out ) + { + int i; + + if ( nbPoints > 1 ) + { + out << " \n"; + } + else + { + int cx = convert2pt( x[0], scale, dpi ) - xmin; + int cy = ymax - convert2pt( y[0], scale, dpi ); + out << " \n"; } + } #endif diff --git a/src/core/pal/geomfunction.h b/src/core/pal/geomfunction.h index b18f1b678716..f2ff106dcd99 100644 --- a/src/core/pal/geomfunction.h +++ b/src/core/pal/geomfunction.h @@ -36,141 +36,148 @@ #include "util.h" -namespace pal { - - /* - * o(x2,y2) - * / - * cp > 0 / - * / cp < 0 - * / - * / - * o (x1, y1) - */ - inline double cross_product (double x1, double y1, double x2, double y2, double x3, double y3) { - return (x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1); - } - - inline double dist_euc2d (double x1, double y1, double x2, double y2) { - return sqrt ( (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)); - } - - inline double dist_euc2d_sq (double x1, double y1, double x2, double y2) { - return (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1); +namespace pal +{ + + /* + * o(x2,y2) + * / + * cp > 0 / + * / cp < 0 + * / + * / + * o (x1, y1) + */ + inline double cross_product( double x1, double y1, double x2, double y2, double x3, double y3 ) + { + return ( x2 - x1 ) * ( y3 - y1 ) - ( x3 - x1 ) * ( y2 - y1 ); + } + + inline double dist_euc2d( double x1, double y1, double x2, double y2 ) + { + return sqrt(( x2 - x1 ) * ( x2 - x1 ) + ( y2 - y1 ) * ( y2 - y1 ) ); + } + + inline double dist_euc2d_sq( double x1, double y1, double x2, double y2 ) + { + return ( x2 - x1 ) * ( x2 - x1 ) + ( y2 - y1 ) * ( y2 - y1 ); + } + + bool isPointInPolygon( int npol, double *xp, double *yp, double x, double y ); + /* + // code from Randolph Franklin (found at http://local.wasp.uwa.edu.au/~pbourke/geometry/insidepoly/) + int i, j; + bool c = false; + + for (i = 0, j = npol-1; i < npol; j = i++){ + if ((( (yp[i] <= y) && (y < yp[j])) || + ((yp[j] <= y) && (y < yp[i]))) + && (x < (xp[j] - xp[i]) * (y - yp[i]) / (yp[j] - yp[i]) + xp[i])){ + c = !c; + } + } + return c; + }*/ + + + inline int nbLabelPointInPolygon( int npol, double *xp, double *yp, double x[4], double y[4] ) + { + int a, k, count = 0; + double px, py; + + // cheack each corner + for ( k = 0;k < 4;k++ ) + { + px = x[k]; + py = y[k]; + + for ( a = 0;a < 2;a++ ) // and each middle of segment + { + if ( isPointInPolygon( npol, xp, yp, px, py ) ) + count++; + px = ( x[k] + x[( k+1 ) %4] ) / 2.0; + py = ( y[k] + y[( k+1 ) %4] ) / 2.0; + } } - bool isPointInPolygon (int npol, double *xp, double *yp, double x, double y); - /* - // code from Randolph Franklin (found at http://local.wasp.uwa.edu.au/~pbourke/geometry/insidepoly/) - int i, j; - bool c = false; - - for (i = 0, j = npol-1; i < npol; j = i++){ - if ((( (yp[i] <= y) && (y < yp[j])) || - ((yp[j] <= y) && (y < yp[i]))) - && (x < (xp[j] - xp[i]) * (y - yp[i]) / (yp[j] - yp[i]) + xp[i])){ - c = !c; - } - } - return c; - }*/ - - - inline int nbLabelPointInPolygon (int npol, double *xp, double *yp, double x[4], double y[4]) { - int a, k, count = 0; - double px, py; - - // cheack each corner - for (k = 0;k < 4;k++) { - px = x[k]; - py = y[k]; - - for (a = 0;a < 2;a++) { // and each middle of segment - if (isPointInPolygon (npol, xp, yp, px, py)) - count++; - px = (x[k] + x[ (k+1) %4]) / 2.0; - py = (y[k] + y[ (k+1) %4]) / 2.0; - } - } + px = ( x[0] + x[2] ) / 2.0; + py = ( y[0] + y[2] ) / 2.0; - px = (x[0] + x[2]) / 2.0; - py = (y[0] + y[2]) / 2.0; + // and the label center + if ( isPointInPolygon( npol, xp, yp, px, py ) ) + count += 4; // virtually 4 points - // and the label center - if (isPointInPolygon (npol, xp, yp, px, py)) - count += 4; // virtually 4 points + return count; + } - return count; - } + int convexHull( int *id, const double* const x, const double* const y, int n ); - int convexHull (int *id, const double* const x, const double* const y, int n); + int convexHullId( int *id, const double* const x, const double* const y, int n, int *&cHull ); - int convexHullId (int *id, const double* const x, const double* const y, int n, int *&cHull); + bool isSegIntersects( double x1, double y1, double x2, double y2, // 1st segment + double x3, double y3, double x4, double y4 ); // 2nd segment - bool isSegIntersects (double x1, double y1, double x2, double y2, // 1st segment - double x3, double y3, double x4, double y4); // 2nd segment + bool computeSegIntersectionExt( double x1, double y1, double x2, double y2, double xs1, double ys1, // 1st (segment) + double x3, double y3, double x4, double y4, double xs2, double ys2, // 2nd segment + double *x, double *y ); - bool computeSegIntersectionExt (double x1, double y1, double x2, double y2, double xs1, double ys1, // 1st (segment) - double x3, double y3, double x4, double y4, double xs2, double ys2, // 2nd segment - double *x, double *y); + /* + * \brief Intersection bw a line and a segment + * \return true if the point exist false otherwise + */ + bool computeLineSegIntersection( double x1, double y1, double x2, double y2, // 1st line + double x3, double y3, double x4, double y4, // 2nd segment + double *x, double *y ); - /* - * \brief Intersection bw a line and a segment - * \return true if the point exist false otherwise - */ - bool computeLineSegIntersection (double x1, double y1, double x2, double y2, // 1st line - double x3, double y3, double x4, double y4, // 2nd segment - double *x, double *y); - - /* - * \brief compute the point wherre two segmentss intersects - * \return true if the point exists - */ - bool computeSegIntersection (double x1, double y1, double x2, double y2, // 1st line (segment) - double x3, double y3, double x4, double y4, // 2nd line segment - double *x, double *y); + /* + * \brief compute the point wherre two segmentss intersects + * \return true if the point exists + */ + bool computeSegIntersection( double x1, double y1, double x2, double y2, // 1st line (segment) + double x3, double y3, double x4, double y4, // 2nd line segment + double *x, double *y ); - /* - * \brief compute the point wherre two lines intersects - * \return true if the ok false if line are parallel - */ - bool computeLineIntersection (double x1, double y1, double x2, double y2, // 1st line (segment) - double x3, double y3, double x4, double y4, // 2nd line segment - double *x, double *y); + /* + * \brief compute the point wherre two lines intersects + * \return true if the ok false if line are parallel + */ + bool computeLineIntersection( double x1, double y1, double x2, double y2, // 1st line (segment) + double x3, double y3, double x4, double y4, // 2nd line segment + double *x, double *y ); #ifdef _EXPORT_MAP_ - /** - * \brief generate SVG code for a geometry - * - * @param nbPoints # points in x and y vector - * @param typeID from geos - * @param x x coordinates - * @param y y coordinates - * @param dpi map resolution - * @param scale map scale is 1:scale - * @param xmin minimum x value in mapExtent - * @param ymax maximum y value in mapExtent - * @param layername SVG layer name - * @param objectID SVG ID - * @param out stream to write - */ - void toSVGPath (int nbPoints, int geomType, - double *x, double *y, - int dpi, double scale, - int xmin, int ymax, - char *layername, - char *objectID, - std::ostream &out); + /** + * \brief generate SVG code for a geometry + * + * @param nbPoints # points in x and y vector + * @param typeID from geos + * @param x x coordinates + * @param y y coordinates + * @param dpi map resolution + * @param scale map scale is 1:scale + * @param xmin minimum x value in mapExtent + * @param ymax maximum y value in mapExtent + * @param layername SVG layer name + * @param objectID SVG ID + * @param out stream to write + */ + void toSVGPath( int nbPoints, int geomType, + double *x, double *y, + int dpi, double scale, + int xmin, int ymax, + char *layername, + char *objectID, + std::ostream &out ); #endif - int reorderPolygon (int nbPoints, double *x, double *y); + int reorderPolygon( int nbPoints, double *x, double *y ); } // end namespace diff --git a/src/core/pal/internalexception.h b/src/core/pal/internalexception.h index 20f18c374095..60b1e3216d04 100644 --- a/src/core/pal/internalexception.h +++ b/src/core/pal/internalexception.h @@ -36,54 +36,66 @@ #include -namespace pal { +namespace pal +{ - /** \brief Various Exceptions - */ - class InternalException { + /** \brief Various Exceptions + */ + class InternalException + { public: - /** \brief Thrown when something is added in a Full set - */ - class Full : public std::exception { - const char* what() const throw() { - return "This set is full..."; - } - }; + /** \brief Thrown when something is added in a Full set + */ + class Full : public std::exception + { + const char* what() const throw() + { + return "This set is full..."; + } + }; - /** \brief Thrown when trying to access an empty dada set - */ - class Empty : public std::exception { - const char* what() const throw() { - return "This set is empty..."; - } - }; + /** \brief Thrown when trying to access an empty dada set + */ + class Empty : public std::exception + { + const char* what() const throw() + { + return "This set is empty..."; + } + }; - /** \brief Thrown when a geometry type is not like expected - */ - class WrongGeometry : public std::exception { - const char* what() const throw() { - return "GeometryTypeId is not expected..."; - } - }; + /** \brief Thrown when a geometry type is not like expected + */ + class WrongGeometry : public std::exception + { + const char* what() const throw() + { + return "GeometryTypeId is not expected..."; + } + }; - /** \brief Thrown when a geometry type is not like expected - */ - class UnknownGeometry : public std::exception { - const char* what() const throw() { - return "Geometry Type is unknow"; - } - }; + /** \brief Thrown when a geometry type is not like expected + */ + class UnknownGeometry : public std::exception + { + const char* what() const throw() + { + return "Geometry Type is unknow"; + } + }; - /** \brief Throw an exception when it's impossible to compute labelPOsition - */ - class NoLabelPosition : public std::exception { - const char * what() const throw() { - return "No way to compute positions"; - } - }; - }; + /** \brief Throw an exception when it's impossible to compute labelPOsition + */ + class NoLabelPosition : public std::exception + { + const char * what() const throw() + { + return "No way to compute positions"; + } + }; + }; } // end namespace diff --git a/src/core/pal/label.cpp b/src/core/pal/label.cpp index 579386ee965d..696f153cf41b 100644 --- a/src/core/pal/label.cpp +++ b/src/core/pal/label.cpp @@ -38,58 +38,70 @@ #include #include -namespace pal { +namespace pal +{ - Label::Label (double x[4], double y[4], double alpha, const char *ftid, const char *lyrName, PalGeometry *userGeom) : a (alpha), userGeom (userGeom) { + Label::Label( double x[4], double y[4], double alpha, const char *ftid, const char *lyrName, PalGeometry *userGeom ) : a( alpha ), userGeom( userGeom ) + { - for (int i = 0;i < 4;i++) { - this->x[i] = x[i]; - this->y[i] = y[i]; - } - - featureId = new char[strlen (ftid) +1]; - strcpy (featureId, ftid); - - this->lyrName = new char[strlen (lyrName) +1]; - strcpy (this->lyrName, lyrName); - } - - Label::~Label() { - delete[] featureId; - delete[] lyrName; - } - - double Label::getOrigX() { - return x[0]; - } - - double Label::getOrigY() { - return y[0]; - } - - double Label::getX (size_t i) { - return (i < 4 ? x[i] : -1); + for ( int i = 0;i < 4;i++ ) + { + this->x[i] = x[i]; + this->y[i] = y[i]; } - double Label::getY (size_t i) { - return (i < 4 ? y[i] : -1); - } - - PalGeometry *Label::getGeometry() { - return userGeom; - } - - double Label::getRotation() { - return a; - } - - const char *Label::getLayerName() { - return lyrName; - } - - const char *Label::getFeatureId() { - return featureId; - } + featureId = new char[strlen( ftid ) +1]; + strcpy( featureId, ftid ); + + this->lyrName = new char[strlen( lyrName ) +1]; + strcpy( this->lyrName, lyrName ); + } + + Label::~Label() + { + delete[] featureId; + delete[] lyrName; + } + + double Label::getOrigX() + { + return x[0]; + } + + double Label::getOrigY() + { + return y[0]; + } + + double Label::getX( size_t i ) + { + return ( i < 4 ? x[i] : -1 ); + } + + double Label::getY( size_t i ) + { + return ( i < 4 ? y[i] : -1 ); + } + + PalGeometry *Label::getGeometry() + { + return userGeom; + } + + double Label::getRotation() + { + return a; + } + + const char *Label::getLayerName() + { + return lyrName; + } + + const char *Label::getFeatureId() + { + return featureId; + } } // end namespace diff --git a/src/core/pal/label.h b/src/core/pal/label.h index c546c04c7542..4c5a16ee8e56 100644 --- a/src/core/pal/label.h +++ b/src/core/pal/label.h @@ -34,96 +34,98 @@ #ifndef _LABEL_H #define _LABEL_H -namespace pal { +namespace pal +{ - class LabelPosition; - class PalGeometry; + class LabelPosition; + class PalGeometry; - /** - * \brief Represent a label to be displayed - */ - class Label { + /** + * \brief Represent a label to be displayed + */ + class Label + { - friend class LabelPosition; + friend class LabelPosition; private: - double x[4]; - double y[4]; + double x[4]; + double y[4]; - double a; + double a; - char *featureId; - char *lyrName; + char *featureId; + char *lyrName; - PalGeometry *userGeom; + PalGeometry *userGeom; - /** - * \brief Create a new label - * - * @param x x coordinate of down-left label corner - * @param y y coordinate of down-left label corner - * @param alpha rotation to aplay to the text - * @param ftid id of the corresponding feature - * @param lyrName name of the corresponding layer - * @param userGeom PalGeometry of the feature - */ - Label (double x[4], double y[4], double alpha, const char *ftid, const char *lyrName, PalGeometry *userGeom); + /** + * \brief Create a new label + * + * @param x x coordinate of down-left label corner + * @param y y coordinate of down-left label corner + * @param alpha rotation to aplay to the text + * @param ftid id of the corresponding feature + * @param lyrName name of the corresponding layer + * @param userGeom PalGeometry of the feature + */ + Label( double x[4], double y[4], double alpha, const char *ftid, const char *lyrName, PalGeometry *userGeom ); public: - /** - * \brief delete a label - */ - ~Label(); - - /** - * \brief return the down-left x coordinate - * @return x coordinate - */ - double getOrigX(); - - /** - * \brief return the down-left y coordinate - * @return y coordinate - */ - double getOrigY(); - - /** - * \brief get a specific x coordinate - * @param i 0 => down-left, 1=>down-right, 2=>up-right 3=> up-left - * @return the i'th x coordinate - */ - double getX (size_t i); - - /** - * \brief get a specific y coordinate - * @param i 0 => down-left, 1=>down-right, 2=>up-right 3=> up-left - * @return the i'th y coordinate - */ - double getY (size_t i); - - /** - * \brief return the label orientation - * @return alpha in rad, couterclockwise - */ - double getRotation(); - - /** - * \brief return the name of the layer wich contains the feature - * @return the layer's name - */ - const char *getLayerName(); - - /** - * \brief return the feature's unique id - * @return the feature's id - */ - const char *getFeatureId(); - - /** - * \brief return user geometry (pal::Layer::registerFeature()) - * @return pointer to the user geometry - */ - PalGeometry * getGeometry(); - }; + /** + * \brief delete a label + */ + ~Label(); + + /** + * \brief return the down-left x coordinate + * @return x coordinate + */ + double getOrigX(); + + /** + * \brief return the down-left y coordinate + * @return y coordinate + */ + double getOrigY(); + + /** + * \brief get a specific x coordinate + * @param i 0 => down-left, 1=>down-right, 2=>up-right 3=> up-left + * @return the i'th x coordinate + */ + double getX( size_t i ); + + /** + * \brief get a specific y coordinate + * @param i 0 => down-left, 1=>down-right, 2=>up-right 3=> up-left + * @return the i'th y coordinate + */ + double getY( size_t i ); + + /** + * \brief return the label orientation + * @return alpha in rad, couterclockwise + */ + double getRotation(); + + /** + * \brief return the name of the layer wich contains the feature + * @return the layer's name + */ + const char *getLayerName(); + + /** + * \brief return the feature's unique id + * @return the feature's id + */ + const char *getFeatureId(); + + /** + * \brief return user geometry (pal::Layer::registerFeature()) + * @return pointer to the user geometry + */ + PalGeometry * getGeometry(); + }; } // end namespace pal diff --git a/src/core/pal/labelposition.cpp b/src/core/pal/labelposition.cpp index 73e5eac5382b..a579a6cc9715 100644 --- a/src/core/pal/labelposition.cpp +++ b/src/core/pal/labelposition.cpp @@ -52,495 +52,556 @@ #endif -namespace pal { +namespace pal +{ - LabelPosition::LabelPosition (int id, double x1, double y1, double w, double h, double alpha, double cost, Feature *feature) : id (id), cost (cost), /*workingCost (0),*/ alpha (alpha), feature (feature), nbOverlap (0), w (w), h (h) { + LabelPosition::LabelPosition( int id, double x1, double y1, double w, double h, double alpha, double cost, Feature *feature ) : id( id ), cost( cost ), /*workingCost (0),*/ alpha( alpha ), feature( feature ), nbOverlap( 0 ), w( w ), h( h ) + { - // alpha take his value bw 0 and 2*pi rad - while (this->alpha > 2*M_PI) - this->alpha -= 2 * M_PI; + // alpha take his value bw 0 and 2*pi rad + while ( this->alpha > 2*M_PI ) + this->alpha -= 2 * M_PI; - while (this->alpha < 0) - this->alpha += 2 * M_PI; + while ( this->alpha < 0 ) + this->alpha += 2 * M_PI; - register double beta = this->alpha + (M_PI / 2); + register double beta = this->alpha + ( M_PI / 2 ); - double dx1, dx2, dy1, dy2; + double dx1, dx2, dy1, dy2; - double tx, ty; + double tx, ty; - dx1 = cos (this->alpha) * w; - dy1 = sin (this->alpha) * w; + dx1 = cos( this->alpha ) * w; + dy1 = sin( this->alpha ) * w; - dx2 = cos (beta) * h; - dy2 = sin (beta) * h; + dx2 = cos( beta ) * h; + dy2 = sin( beta ) * h; - x[0] = x1; - y[0] = y1; + x[0] = x1; + y[0] = y1; - x[1] = x1 + dx1; - y[1] = y1 + dy1; + x[1] = x1 + dx1; + y[1] = y1 + dy1; - x[2] = x1 + dx1 + dx2; - y[2] = y1 + dy1 + dy2; + x[2] = x1 + dx1 + dx2; + y[2] = y1 + dy1 + dy2; - x[3] = x1 + dx2; - y[3] = y1 + dy2; + x[3] = x1 + dx2; + y[3] = y1 + dy2; - // upside down ? - if (this->alpha > M_PI / 2 && this->alpha <= 3*M_PI / 2) { - tx = x[0]; - ty = y[0]; + // upside down ? + if ( this->alpha > M_PI / 2 && this->alpha <= 3*M_PI / 2 ) + { + tx = x[0]; + ty = y[0]; - x[0] = x[2]; - y[0] = y[2]; + x[0] = x[2]; + y[0] = y[2]; - x[2] = tx; - y[2] = ty; + x[2] = tx; + y[2] = ty; - tx = x[1]; - ty = y[1]; + tx = x[1]; + ty = y[1]; - x[1] = x[3]; - y[1] = y[3]; + x[1] = x[3]; + y[1] = y[3]; - x[3] = tx; - y[3] = ty; + x[3] = tx; + y[3] = ty; - if (this->alpha < M_PI) - this->alpha += M_PI; - else - this->alpha -= M_PI; - } + if ( this->alpha < M_PI ) + this->alpha += M_PI; + else + this->alpha -= M_PI; } + } - bool LabelPosition::isIn (double *bbox) { - int i; - - for (i = 0;i < 4;i++) { - if (x[i] >= bbox[0] && x[i] <= bbox[2] && - y[i] >= bbox[1] && y[i] <= bbox[3]) - return true; - } - - return false; - - } + bool LabelPosition::isIn( double *bbox ) + { + int i; - void LabelPosition::print() { - std::cout << feature->getLayer()->getName() << "/" << feature->getUID() << "/" << id; - std::cout << " cost: " << cost; - std::cout << " alpha" << alpha << std::endl; - std::cout << x[0] << ", " << y[0] << std::endl; - std::cout << x[1] << ", " << y[1] << std::endl; - std::cout << x[2] << ", " << y[2] << std::endl; - std::cout << x[3] << ", " << y[3] << std::endl; - std::cout << std::endl; + for ( i = 0;i < 4;i++ ) + { + if ( x[i] >= bbox[0] && x[i] <= bbox[2] && + y[i] >= bbox[1] && y[i] <= bbox[3] ) + return true; } - bool LabelPosition::isInConflict (LabelPosition *ls) { - int i, i2, j; - int d1, d2; - - if (this->probFeat == ls->probFeat) // bugfix #1 - return false; // always overlaping itself ! - - double cp1, cp2; - - - //std::cout << "Check intersect" << std::endl; - for (i = 0;i < 4;i++) { - i2 = (i + 1) % 4; - d1 = -1; - d2 = -1; - //std::cout << "new seg..." << std::endl; - for (j = 0;j < 4;j++) { - cp1 = cross_product (x[i], y[i], x[i2], y[i2], ls->x[j], ls->y[j]); - if (cp1 > 0) { - d1 = 1; - //std::cout << " cp1: " << cp1 << std::endl; - } - cp2 = cross_product (ls->x[i], ls->y[i], - ls->x[i2], ls->y[i2], - x[j], y[j]); - - if (cp2 > 0) { - d2 = 1; - //std::cout << " cp2 " << cp2 << std::endl; - } - } - - if (d1 == -1 || d2 == -1) // disjoint - return false; + return false; + + } + + void LabelPosition::print() + { + std::cout << feature->getLayer()->getName() << "/" << feature->getUID() << "/" << id; + std::cout << " cost: " << cost; + std::cout << " alpha" << alpha << std::endl; + std::cout << x[0] << ", " << y[0] << std::endl; + std::cout << x[1] << ", " << y[1] << std::endl; + std::cout << x[2] << ", " << y[2] << std::endl; + std::cout << x[3] << ", " << y[3] << std::endl; + std::cout << std::endl; + } + + bool LabelPosition::isInConflict( LabelPosition *ls ) + { + int i, i2, j; + int d1, d2; + + if ( this->probFeat == ls->probFeat ) // bugfix #1 + return false; // always overlaping itself ! + + double cp1, cp2; + + + //std::cout << "Check intersect" << std::endl; + for ( i = 0;i < 4;i++ ) + { + i2 = ( i + 1 ) % 4; + d1 = -1; + d2 = -1; + //std::cout << "new seg..." << std::endl; + for ( j = 0;j < 4;j++ ) + { + cp1 = cross_product( x[i], y[i], x[i2], y[i2], ls->x[j], ls->y[j] ); + if ( cp1 > 0 ) + { + d1 = 1; + //std::cout << " cp1: " << cp1 << std::endl; } - return true; - } + cp2 = cross_product( ls->x[i], ls->y[i], + ls->x[i2], ls->y[i2], + x[j], y[j] ); + + if ( cp2 > 0 ) + { + d2 = 1; + //std::cout << " cp2 " << cp2 << std::endl; + } + } - int LabelPosition::getId() { - return id; + if ( d1 == -1 || d2 == -1 ) // disjoint + return false; } + return true; + } + + int LabelPosition::getId() + { + return id; + } + + double LabelPosition::getX() + { + return x[0]; + } + + double LabelPosition::getY() + { + return y[0]; + } + + double LabelPosition::getAlpha() + { + return alpha; + } + + double LabelPosition::getCost() + { + return cost; + } + + Feature * LabelPosition::getFeature() + { + return feature; + } + + bool xGrow( void *l, void *r ) + { + return (( LabelPosition* ) l )->x[0] > (( LabelPosition* ) r )->x[0]; + } + + bool yGrow( void *l, void *r ) + { + return (( LabelPosition* ) l )->y[0] > (( LabelPosition* ) r )->y[0]; + } + + bool xShrink( void *l, void *r ) + { + return (( LabelPosition* ) l )->x[0] < (( LabelPosition* ) r )->x[0]; + } + + bool yShrink( void *l, void *r ) + { + return (( LabelPosition* ) l )->y[0] < (( LabelPosition* ) r )->y[0]; + } + + bool costShrink( void *l, void *r ) + { + return (( LabelPosition* ) l )->cost < (( LabelPosition* ) r )->cost; + } + + bool costGrow( void *l, void *r ) + { + return (( LabelPosition* ) l )->cost > (( LabelPosition* ) r )->cost; + } + + /* + bool workingCostShrink (void *l, void *r){ + return ((LabelPosition*)l)->workingCost < ((LabelPosition*)r)->workingCost; + } + + bool workingCostGrow (void *l, void *r){ + return ((LabelPosition*)l)->workingCost > ((LabelPosition*)r)->workingCost; + } + */ + + Label *LabelPosition::toLabel( bool active ) + { + + //double x[4], y; + + //x = this->x[0]; + //y = this->y[0]; - double LabelPosition::getX() { - return x[0]; - } +//#warning retourner les coord projeté ou pas ? + //feature->layer->pal->proj->getLatLong(this->x[0], this->y[0], &x, &y); - double LabelPosition::getY() { - return y[0]; - } + return new Label( this->x, this->y, alpha, feature->uid, feature->layer->name, feature->userGeom ); + } - double LabelPosition::getAlpha() { - return alpha; - } - double LabelPosition::getCost() { - return cost; - } + bool obstacleCallback( PointSet *feat, void *ctx ) + { + LabelPosition::PolygonCostCalculator *pCost = ( LabelPosition::PolygonCostCalculator* ) ctx; - Feature * LabelPosition::getFeature() { - return feature; + LabelPosition *lp = pCost->getLabel(); + if (( feat == lp->feature ) || ( feat->holeOf && feat->holeOf != lp->feature ) ) + { + return true; } - bool xGrow (void *l, void *r) { - return ( (LabelPosition*) l)->x[0] > ( (LabelPosition*) r)->x[0]; + // if the feature is not a hole we have to fetch corrdinates + // otherwise holes coordinates are still in memory (feature->selfObs) + if ( feat->holeOf == NULL ) + { + (( Feature* ) feat )->fetchCoordinates(); } - bool yGrow (void *l, void *r) { - return ( (LabelPosition*) l)->y[0] > ( (LabelPosition*) r)->y[0]; - } + pCost->update( feat ); - bool xShrink (void *l, void *r) { - return ( (LabelPosition*) l)->x[0] < ( (LabelPosition*) r)->x[0]; - } - bool yShrink (void *l, void *r) { - return ( (LabelPosition*) l)->y[0] < ( (LabelPosition*) r)->y[0]; + if ( feat->holeOf == NULL ) + { + (( Feature* ) feat )->releaseCoordinates(); } - bool costShrink (void *l, void *r) { - return ( (LabelPosition*) l)->cost < ( (LabelPosition*) r)->cost; - } - bool costGrow (void *l, void *r) { - return ( (LabelPosition*) l)->cost > ( (LabelPosition*) r)->cost; - } + return true; + } - /* - bool workingCostShrink (void *l, void *r){ - return ((LabelPosition*)l)->workingCost < ((LabelPosition*)r)->workingCost; - } + void LabelPosition::setCostFromPolygon( RTree *obstacles, double bbx[4], double bby[4] ) + { - bool workingCostGrow (void *l, void *r){ - return ((LabelPosition*)l)->workingCost > ((LabelPosition*)r)->workingCost; - } - */ - - Label *LabelPosition::toLabel (bool active) { + double amin[2]; + double amax[2]; - //double x[4], y; - //x = this->x[0]; - //y = this->y[0]; + LabelPosition::PolygonCostCalculator *pCost = new LabelPosition::PolygonCostCalculator( this ); + //cost = getCostFromPolygon (feat, dist_sq); -//#warning retourner les coord projeté ou pas ? - //feature->layer->pal->proj->getLatLong(this->x[0], this->y[0], &x, &y); + // center + //cost = feat->getDistInside((this->x[0] + this->x[2])/2.0, (this->y[0] + this->y[2])/2.0 ); - return new Label (this->x, this->y, alpha, feature->uid, feature->layer->name, feature->userGeom); - } + feature->fetchCoordinates(); + pCost->update( feature ); + PointSet *extent = new PointSet( 4, bbx, bby ); - bool obstacleCallback (PointSet *feat, void *ctx) { - LabelPosition::PolygonCostCalculator *pCost = (LabelPosition::PolygonCostCalculator*) ctx; + pCost->update( extent ); - LabelPosition *lp = pCost->getLabel(); - if ( (feat == lp->feature) || (feat->holeOf && feat->holeOf != lp->feature)) { - return true; - } + delete extent; - // if the feature is not a hole we have to fetch corrdinates - // otherwise holes coordinates are still in memory (feature->selfObs) - if (feat->holeOf == NULL) { - ( (Feature*) feat)->fetchCoordinates(); - } + // TODO Comment + /*if (cost > (w*w + h*h) / 4.0) { + double dist = sqrt (cost); + amin[0] = (x[0] + x[2]) / 2.0 - dist; + amin[1] = (y[0] + y[2]) / 2.0 - dist; + amax[0] = amin[0] + 2 * dist; + amax[1] = amin[1] + 2 * dist; + } else {*/ + amin[0] = feature->xmin; + amin[1] = feature->ymin; + amax[0] = feature->xmax; + amax[1] = feature->ymax; + //} - pCost->update(feat); + //std::cout << amin[0] << " " << amin[1] << " " << amax[0] << " " << amax[1] << std::endl; + obstacles->Search( amin, amax, obstacleCallback, pCost ); + cost = pCost->getCost(); - if (feat->holeOf == NULL) { - ( (Feature*) feat)->releaseCoordinates(); - } + feature->releaseCoordinates(); + delete pCost; + } + void LabelPosition::removeFromIndex( RTree *index ) + { + double amin[2]; + double amax[2]; + int c; - return true; + amin[0] = DBL_MAX; + amax[0] = -DBL_MAX; + amin[1] = DBL_MAX; + amax[1] = -DBL_MAX; + for ( c = 0;c < 4;c++ ) + { + if ( x[c] < amin[0] ) + amin[0] = x[c]; + if ( x[c] > amax[0] ) + amax[0] = x[c]; + if ( y[c] < amin[1] ) + amin[1] = y[c]; + if ( y[c] > amax[1] ) + amax[1] = y[c]; } - void LabelPosition::setCostFromPolygon (RTree *obstacles, double bbx[4], double bby[4]){ - - double amin[2]; - double amax[2]; - - - LabelPosition::PolygonCostCalculator *pCost = new LabelPosition::PolygonCostCalculator(this); - //cost = getCostFromPolygon (feat, dist_sq); - - // center - //cost = feat->getDistInside((this->x[0] + this->x[2])/2.0, (this->y[0] + this->y[2])/2.0 ); - - feature->fetchCoordinates(); - pCost->update(feature); - - PointSet *extent = new PointSet(4, bbx, bby); - - pCost->update(extent); - - delete extent; - - // TODO Comment - /*if (cost > (w*w + h*h) / 4.0) { - double dist = sqrt (cost); - amin[0] = (x[0] + x[2]) / 2.0 - dist; - amin[1] = (y[0] + y[2]) / 2.0 - dist; - amax[0] = amin[0] + 2 * dist; - amax[1] = amin[1] + 2 * dist; - } else {*/ - amin[0] = feature->xmin; - amin[1] = feature->ymin; - amax[0] = feature->xmax; - amax[1] = feature->ymax; - //} - - //std::cout << amin[0] << " " << amin[1] << " " << amax[0] << " " << amax[1] << std::endl; - obstacles->Search (amin, amax, obstacleCallback, pCost); - - cost = pCost->getCost(); - - feature->releaseCoordinates(); - delete pCost; - } - - void LabelPosition::removeFromIndex (RTree *index) { - double amin[2]; - double amax[2]; - int c; - - amin[0] = DBL_MAX; - amax[0] = -DBL_MAX; - amin[1] = DBL_MAX; - amax[1] = -DBL_MAX; - for (c = 0;c < 4;c++) { - if (x[c] < amin[0]) - amin[0] = x[c]; - if (x[c] > amax[0]) - amax[0] = x[c]; - if (y[c] < amin[1]) - amin[1] = y[c]; - if (y[c] > amax[1]) - amax[1] = y[c]; - } - - index->Remove (amin, amax, this); + index->Remove( amin, amax, this ); + } + + + void LabelPosition::insertIntoIndex( RTree *index ) + { + double amin[2]; + double amax[2]; + int c; + + amin[0] = DBL_MAX; + amax[0] = -DBL_MAX; + amin[1] = DBL_MAX; + amax[1] = -DBL_MAX; + for ( c = 0;c < 4;c++ ) + { + if ( x[c] < amin[0] ) + amin[0] = x[c]; + if ( x[c] > amax[0] ) + amax[0] = x[c]; + if ( y[c] < amin[1] ) + amin[1] = y[c]; + if ( y[c] > amax[1] ) + amax[1] = y[c]; } + index->Insert( amin, amax, this ); + } - void LabelPosition::insertIntoIndex (RTree *index) { - double amin[2]; - double amax[2]; - int c; - - amin[0] = DBL_MAX; - amax[0] = -DBL_MAX; - amin[1] = DBL_MAX; - amax[1] = -DBL_MAX; - for (c = 0;c < 4;c++) { - if (x[c] < amin[0]) - amin[0] = x[c]; - if (x[c] > amax[0]) - amax[0] = x[c]; - if (y[c] < amin[1]) - amin[1] = y[c]; - if (y[c] > amax[1]) - amax[1] = y[c]; - } - - index->Insert (amin, amax, this); - } + void LabelPosition::setCost( int nblp, LabelPosition **lPos, int max_p, RTree *obstacles, double bbx[4], double bby[4] ) + { + //std::cout << "setCost:" << std::endl; + //clock_t clock_start = clock(); - void LabelPosition::setCost (int nblp, LabelPosition **lPos, int max_p, RTree *obstacles, double bbx[4], double bby[4]) { - //std::cout << "setCost:" << std::endl; - //clock_t clock_start = clock(); + int i; - int i; - - double normalizer; - // compute raw cost + double normalizer; + // compute raw cost #ifdef _DEBUG_ - std::cout << "LabelPosition for feat: " << lPos[0]->feature->uid << std::endl; + std::cout << "LabelPosition for feat: " << lPos[0]->feature->uid << std::endl; #endif - for (i = 0;i < nblp;i++) - lPos[i]->setCostFromPolygon (obstacles, bbx, bby); + for ( i = 0;i < nblp;i++ ) + lPos[i]->setCostFromPolygon( obstacles, bbx, bby ); - // lPos with big values came fisrts (value = min distance from label to Polygon's Perimeter) - //sort ( (void**) lPos, nblp, costGrow); - sort ( (void**) lPos, nblp, costShrink); + // lPos with big values came fisrts (value = min distance from label to Polygon's Perimeter) + //sort ( (void**) lPos, nblp, costGrow); + sort(( void** ) lPos, nblp, costShrink ); - // define the value's range - double cost_max = lPos[0]->cost; - double cost_min = lPos[max_p-1]->cost; + // define the value's range + double cost_max = lPos[0]->cost; + double cost_min = lPos[max_p-1]->cost; - cost_max -= cost_min; + cost_max -= cost_min; - if (cost_max > EPSILON){ - normalizer = 0.0020 / cost_max; - } - else{ - normalizer = 1; - } - - // adjust cost => the best is 0.0001, the sorst is 0.0021 - // others are set proportionally between best and worst - for (i = 0;i < max_p;i++) { + if ( cost_max > EPSILON ) + { + normalizer = 0.0020 / cost_max; + } + else + { + normalizer = 1; + } + + // adjust cost => the best is 0.0001, the sorst is 0.0021 + // others are set proportionally between best and worst + for ( i = 0;i < max_p;i++ ) + { #ifdef _DEBUG_ - std::cout << " lpos[" << i << "] = " << lPos[i]->cost; + std::cout << " lpos[" << i << "] = " << lPos[i]->cost; #endif - //if (cost_max - cost_min < EPSILON) - if (cost_max > EPSILON){ - lPos[i]->cost = 0.0021 - (lPos[i]->cost - cost_min) * normalizer; - } - else{ - //lPos[i]->cost = 0.0001 + (lPos[i]->cost - cost_min) * normalizer; - lPos[i]->cost = 0.0001; - } + //if (cost_max - cost_min < EPSILON) + if ( cost_max > EPSILON ) + { + lPos[i]->cost = 0.0021 - ( lPos[i]->cost - cost_min ) * normalizer; + } + else + { + //lPos[i]->cost = 0.0001 + (lPos[i]->cost - cost_min) * normalizer; + lPos[i]->cost = 0.0001; + } #ifdef _DEBUG_ - std::cout << " ==> " << lPos[i]->cost << std::endl; + std::cout << " ==> " << lPos[i]->cost << std::endl; #endif - } - //clock_t clock_2; - //std::cout << "AfterSetCostFromPolygon (" << nblp << "x): " << clock_2 = (clock() - clock_1) << std::endl; } + //clock_t clock_2; + //std::cout << "AfterSetCostFromPolygon (" << nblp << "x): " << clock_2 = (clock() - clock_1) << std::endl; + } + + LabelPosition::PolygonCostCalculator::PolygonCostCalculator( LabelPosition *lp ) : lp( lp ) + { + int i; + double hyp = max( lp->feature->xmax - lp->feature->xmin, lp->feature->ymax - lp->feature->ymin ); + hyp *= 10; + + px = ( lp->x[0] + lp->x[2] ) / 2.0; + py = ( lp->y[0] + lp->y[2] ) / 2.0; + dLp[0] = lp->w / 2; + dLp[1] = lp->h / 2; + dLp[2] = dLp[0] / cos( M_PI / 4 ); - LabelPosition::PolygonCostCalculator::PolygonCostCalculator (LabelPosition *lp) : lp(lp) { - int i; - double hyp = max(lp->feature->xmax - lp->feature->xmin, lp->feature->ymax - lp->feature->ymin); - hyp *= 10; - - px = (lp->x[0] + lp->x[2]) / 2.0; - py = (lp->y[0] + lp->y[2]) / 2.0; - dLp[0] = lp->w / 2; - dLp[1] = lp->h / 2; - dLp[2] = dLp[0] / cos (M_PI / 4); - - /* - 3 2 1 - \ | / - 4 --x -- 0 - / | \ - 5 6 7 - */ - - double alpha = lp->getAlpha(); - for (i = 0;i < 8;i++, alpha+=M_PI/4) { - dist[i] = DBL_MAX; - ok[i] = false; - rpx[i] = px + cos(alpha)*hyp; - rpy[i] = py + sin(alpha)*hyp; - } + /* + 3 2 1 + \ | / + 4 --x -- 0 + / | \ + 5 6 7 + */ + + double alpha = lp->getAlpha(); + for ( i = 0;i < 8;i++, alpha += M_PI / 4 ) + { + dist[i] = DBL_MAX; + ok[i] = false; + rpx[i] = px + cos( alpha ) * hyp; + rpy[i] = py + sin( alpha ) * hyp; } + } - void LabelPosition::PolygonCostCalculator::update (PointSet *pset) { - if (pset->type == GEOS_POINT){ - updatePoint(pset); - } - else{ - double rx,ry; - if (pset->getDist (px, py, &rx, &ry) < updateLinePoly(pset)){ - PointSet *point = new PointSet (ry, ry); - update (point); - delete point; - } - } + void LabelPosition::PolygonCostCalculator::update( PointSet *pset ) + { + if ( pset->type == GEOS_POINT ) + { + updatePoint( pset ); } + else + { + double rx, ry; + if ( pset->getDist( px, py, &rx, &ry ) < updateLinePoly( pset ) ) + { + PointSet *point = new PointSet( ry, ry ); + update( point ); + delete point; + } + } + } - void LabelPosition::PolygonCostCalculator::updatePoint (PointSet *pset) { - double beta = atan2(pset->y[0] - py, pset->x[0] - px) - lp->getAlpha(); + void LabelPosition::PolygonCostCalculator::updatePoint( PointSet *pset ) + { + double beta = atan2( pset->y[0] - py, pset->x[0] - px ) - lp->getAlpha(); - while (beta < 0){ - beta += 2*M_PI; - } + while ( beta < 0 ) + { + beta += 2 * M_PI; + } - double a45 = M_PI/4; - - int i =(int)(beta/a45); - - for (int j=0;j<2;j++, i=(i+1)%8){ - double rx, ry; - rx = px - rpy[i] + py; - ry = py + rpx[i] - px; - double ix, iy; // the point that we look for - if (computeLineIntersection(px, py, rpx[i], rpy[i], pset->x[0], pset->y[0], rx, ry, &ix, &iy)){ - double d = dist_euc2d_sq(px, py, ix, iy); - if (d < dist[i]){ - dist[i] = d; - ok[i] = true; - } - } - else{ - std::cout << "this shouldn't occurs !!!" << std::endl; - } + double a45 = M_PI / 4; + + int i = ( int )( beta / a45 ); + + for ( int j = 0;j < 2;j++, i = ( i + 1 ) % 8 ) + { + double rx, ry; + rx = px - rpy[i] + py; + ry = py + rpx[i] - px; + double ix, iy; // the point that we look for + if ( computeLineIntersection( px, py, rpx[i], rpy[i], pset->x[0], pset->y[0], rx, ry, &ix, &iy ) ) + { + double d = dist_euc2d_sq( px, py, ix, iy ); + if ( d < dist[i] ) + { + dist[i] = d; + ok[i] = true; } + } + else + { + std::cout << "this shouldn't occurs !!!" << std::endl; + } } - - double LabelPosition::PolygonCostCalculator::updateLinePoly (PointSet *pset) { - int i, j, k; - int nbP = (pset->type == GEOS_POLYGON ? pset->nbPoints : pset->nbPoints-1); - double min_dist = DBL_MAX; - - for (i = 0;i < nbP;i++) { - j = (i + 1) % pset->nbPoints; - - for (k = 0;k < 8;k++) { - double ix, iy; - if (computeSegIntersection (px, py, rpx[k], rpy[k], pset->x[i], pset->y[i], pset->x[j], pset->y[j], &ix, &iy)) { - double d = dist_euc2d_sq (px, py, ix, iy); - if (d < dist[k]) { - dist[k] = d; - ok[k] = true; - } - if (d < min_dist){ - min_dist = d; - } - } - } + } + + double LabelPosition::PolygonCostCalculator::updateLinePoly( PointSet *pset ) + { + int i, j, k; + int nbP = ( pset->type == GEOS_POLYGON ? pset->nbPoints : pset->nbPoints - 1 ); + double min_dist = DBL_MAX; + + for ( i = 0;i < nbP;i++ ) + { + j = ( i + 1 ) % pset->nbPoints; + + for ( k = 0;k < 8;k++ ) + { + double ix, iy; + if ( computeSegIntersection( px, py, rpx[k], rpy[k], pset->x[i], pset->y[i], pset->x[j], pset->y[j], &ix, &iy ) ) + { + double d = dist_euc2d_sq( px, py, ix, iy ); + if ( d < dist[k] ) + { + dist[k] = d; + ok[k] = true; + } + if ( d < min_dist ) + { + min_dist = d; + } } - return min_dist; + } } - - LabelPosition* LabelPosition::PolygonCostCalculator::getLabel () { - return lp; + return min_dist; + } + + LabelPosition* LabelPosition::PolygonCostCalculator::getLabel() + { + return lp; + } + + double LabelPosition::PolygonCostCalculator::getCost() + { + int i; + + for ( i = 0;i < 8;i++ ) + { + dist[i] -= (( i % 2 ) ? dLp[2] : (( i == 0 || i == 4 ) ? dLp[0] : dLp[1] ) ); + if ( !ok[i] || dist[i] < 0.1 ) + { + dist[i] = 0.1; + } } - double LabelPosition::PolygonCostCalculator::getCost () { - int i; + double a, b, c, d; - for (i = 0;i < 8;i++) { - dist[i] -= ((i%2) ? dLp[2] : ((i==0||i==4)? dLp[0]: dLp[1])); - if (!ok[i] || dist[i] < 0.1){ - dist[i] = 0.1; - } - } - - double a,b,c,d; + a = min( dist[0], dist[4] ); + b = min( dist[1], dist[5] ); + c = min( dist[2], dist[6] ); + d = min( dist[3], dist[7] ); - a = min(dist[0], dist[4]); - b = min(dist[1], dist[5]); - c = min(dist[2], dist[6]); - d = min(dist[3], dist[7]); - - //return (a+b+c+d); - return (a*b*c*d); - } + //return (a+b+c+d); + return ( a*b*c*d ); + } } // end namespace diff --git a/src/core/pal/labelposition.h b/src/core/pal/labelposition.h index 12a7a399e2e3..ed3c03a0177f 100644 --- a/src/core/pal/labelposition.h +++ b/src/core/pal/labelposition.h @@ -39,248 +39,251 @@ #include "rtree.hpp" -namespace pal { - - class Feature; - class Pal; - class Label; - class PriorityQueue; - - - /** - * \brief LabelPositon is a candidate feature label position - */ - class LabelPosition { - - friend bool extractFeatCallback (Feature *ft_ptr, void*ctx); - friend bool xGrow (void *l, void *r); - friend bool yGrow (void *l, void *r); - friend bool xShrink (void *l, void *r); - friend bool yShrink (void *l, void *r); - friend bool costShrink (void *l, void *r); - friend bool costGrow (void *l, void *r); - friend bool pruneLabelPositionCallback (LabelPosition *lp, void *ctx); - //friend void setCost (int nblp, LabelPosition **lPos, int max_p, RTree *obstacles, double bbx[4], double bby[4]); - friend bool countOverlapCallback (LabelPosition *lp, void *ctx); - friend bool countFullOverlapCallback (LabelPosition *lp, void *ctx); - friend bool removeOverlapCallback (LabelPosition *lp, void *ctx); - friend bool falpCallback1 (LabelPosition *lp, void * ctx); - friend bool falpCallback2 (LabelPosition *lp, void * ctx); - friend bool subPartCallback (LabelPosition *lp, void *ctx); - friend bool chainCallback (LabelPosition *lp, void *context); - friend void ignoreLabel (LabelPosition*, PriorityQueue*, RTree*); - friend bool obstacleCallback (PointSet *feat, void *ctx); - - friend bool updateCandidatesCost (LabelPosition *lp, void *context); - friend bool nokCallback (LabelPosition*, void*); - - friend class Pal; - friend class Problem; - friend class Feature; - friend double dist_pointToLabel (double, double, LabelPosition*); +namespace pal +{ + + class Feature; + class Pal; + class Label; + class PriorityQueue; + + + /** + * \brief LabelPositon is a candidate feature label position + */ + class LabelPosition + { + + friend bool extractFeatCallback( Feature *ft_ptr, void*ctx ); + friend bool xGrow( void *l, void *r ); + friend bool yGrow( void *l, void *r ); + friend bool xShrink( void *l, void *r ); + friend bool yShrink( void *l, void *r ); + friend bool costShrink( void *l, void *r ); + friend bool costGrow( void *l, void *r ); + friend bool pruneLabelPositionCallback( LabelPosition *lp, void *ctx ); + //friend void setCost (int nblp, LabelPosition **lPos, int max_p, RTree *obstacles, double bbx[4], double bby[4]); + friend bool countOverlapCallback( LabelPosition *lp, void *ctx ); + friend bool countFullOverlapCallback( LabelPosition *lp, void *ctx ); + friend bool removeOverlapCallback( LabelPosition *lp, void *ctx ); + friend bool falpCallback1( LabelPosition *lp, void * ctx ); + friend bool falpCallback2( LabelPosition *lp, void * ctx ); + friend bool subPartCallback( LabelPosition *lp, void *ctx ); + friend bool chainCallback( LabelPosition *lp, void *context ); + friend void ignoreLabel( LabelPosition*, PriorityQueue*, RTree* ); + friend bool obstacleCallback( PointSet *feat, void *ctx ); + + friend bool updateCandidatesCost( LabelPosition *lp, void *context ); + friend bool nokCallback( LabelPosition*, void* ); + + friend class Pal; + friend class Problem; + friend class Feature; + friend double dist_pointToLabel( double, double, LabelPosition* ); private: - //LabelPosition **overlaped; - //int nbOverlap; - - int id; - double cost; - //double workingCost; - double x[4], y[4]; - - double alpha; - Feature *feature; - - // bug # 1 (maxence 10/23/2008) - int probFeat; - - int nbOverlap; - - double w; - double h; - - //LabelPosition (int id, double x1, double y1, double w, double h, double cost, Feature *feature); - //LabelPosition (int id, int nbPart, double *x, double *y, double *alpha, - - /** - * \brief create a new LabelPosition - * - * \param id id of this labelposition - * \param x1 down-left x coordinate - * \param y1 down-left y coordinate - * \param w label width - * \param h label height - * \param alpha rotation in rad - * \param cost geographic cost - * \param feature labelpos owners - */ - LabelPosition (int id, double x1, double y1, - double w, double h, - double alpha, double cost, - Feature *feature); - - /** - * \brief load a stored labelposition - * - * Load a labelPosition from a file - * \param id id of this labelPosition - * \param feature this labelposition is for feature - * \param file load from this stream - */ - LabelPosition (int id, Feature *feature, std::ifstream *file); - - /** - * \brief Set cost to the smallest distance between lPos's centroid and a polygon stored in geoetry field - */ - void setCostFromPolygon (RTree *obstacles, double bbx[4], double bby[4]); - - static void setCost (int nblp, LabelPosition **lPos, int max_p, RTree *obstacles, double bbx[4], double bby[4]); - - - - /** - * \brief is the labelposition in the bounding-box ? - * - *\param bbox the bounding-box double[4] = {xmin, ymin, xmax, ymax} - */ - bool isIn (double *bbox); - - /** - * \brief Check whether or not this overlap with another labelPosition - * - * \param ls other labelposition - * \return true or false - */ - bool isInConflict (LabelPosition *ls); - - /** \brief return id - * \return id - */ - int getId(); - - /** \brief return the feature id which the labelposition is - * \return feature id - */ - //int getFeatureId(); - - - /** \brief return the feature corresponding to this labelposition - * \return the feature - */ - Feature * getFeature(); - - /** - * \brief get the down-left x coordinate - * \return x coordinate - */ - double getX(); - /** - * \brief get the down-left y coordinate - * \return y coordinate - */ - double getY(); - - - /** - * \brief get alpha - * \return alpha to rotate text (in rad) - */ - double getAlpha(); - /** - * \brief get the position geographical cost - * \return geographical cost - */ - double getCost(); - - /** - * \brief get a final lable from this - * \return a new Label() object - */ - Label* toLabel (bool active); - - void print(); - - void removeFromIndex (RTree *index); - void insertIntoIndex (RTree *index); - - /** - * \brief Data structure to compute polygon's candidates costs - * - * eight segment from center of candidat to (rpx,rpy) points (0°, 45°, 90°, ..., 315°) - * dist store the shortest square distance from the center to an object - * ok[i] is the to true whether the corresponding dist[i] is set - */ - class PolygonCostCalculator{ - LabelPosition *lp; - double px, py; - double dist[8]; - double rpx[8]; - double rpy[8]; - bool ok[8]; - - double dLp[3]; - - void updatePoint(PointSet *pset); - double updateLinePoly(PointSet *pset); + //LabelPosition **overlaped; + //int nbOverlap; + + int id; + double cost; + //double workingCost; + double x[4], y[4]; + + double alpha; + Feature *feature; + + // bug # 1 (maxence 10/23/2008) + int probFeat; + + int nbOverlap; + + double w; + double h; + + //LabelPosition (int id, double x1, double y1, double w, double h, double cost, Feature *feature); + //LabelPosition (int id, int nbPart, double *x, double *y, double *alpha, + + /** + * \brief create a new LabelPosition + * + * \param id id of this labelposition + * \param x1 down-left x coordinate + * \param y1 down-left y coordinate + * \param w label width + * \param h label height + * \param alpha rotation in rad + * \param cost geographic cost + * \param feature labelpos owners + */ + LabelPosition( int id, double x1, double y1, + double w, double h, + double alpha, double cost, + Feature *feature ); + + /** + * \brief load a stored labelposition + * + * Load a labelPosition from a file + * \param id id of this labelPosition + * \param feature this labelposition is for feature + * \param file load from this stream + */ + LabelPosition( int id, Feature *feature, std::ifstream *file ); + + /** + * \brief Set cost to the smallest distance between lPos's centroid and a polygon stored in geoetry field + */ + void setCostFromPolygon( RTree *obstacles, double bbx[4], double bby[4] ); + + static void setCost( int nblp, LabelPosition **lPos, int max_p, RTree *obstacles, double bbx[4], double bby[4] ); + + + + /** + * \brief is the labelposition in the bounding-box ? + * + *\param bbox the bounding-box double[4] = {xmin, ymin, xmax, ymax} + */ + bool isIn( double *bbox ); + + /** + * \brief Check whether or not this overlap with another labelPosition + * + * \param ls other labelposition + * \return true or false + */ + bool isInConflict( LabelPosition *ls ); + + /** \brief return id + * \return id + */ + int getId(); + + /** \brief return the feature id which the labelposition is + * \return feature id + */ + //int getFeatureId(); + + + /** \brief return the feature corresponding to this labelposition + * \return the feature + */ + Feature * getFeature(); + + /** + * \brief get the down-left x coordinate + * \return x coordinate + */ + double getX(); + /** + * \brief get the down-left y coordinate + * \return y coordinate + */ + double getY(); + + + /** + * \brief get alpha + * \return alpha to rotate text (in rad) + */ + double getAlpha(); + /** + * \brief get the position geographical cost + * \return geographical cost + */ + double getCost(); + + /** + * \brief get a final lable from this + * \return a new Label() object + */ + Label* toLabel( bool active ); + + void print(); + + void removeFromIndex( RTree *index ); + void insertIntoIndex( RTree *index ); + + /** + * \brief Data structure to compute polygon's candidates costs + * + * eight segment from center of candidat to (rpx,rpy) points (0°, 45°, 90°, ..., 315°) + * dist store the shortest square distance from the center to an object + * ok[i] is the to true whether the corresponding dist[i] is set + */ + class PolygonCostCalculator + { + LabelPosition *lp; + double px, py; + double dist[8]; + double rpx[8]; + double rpy[8]; + bool ok[8]; + + double dLp[3]; + + void updatePoint( PointSet *pset ); + double updateLinePoly( PointSet *pset ); public: - PolygonCostCalculator (LabelPosition *lp); - - void update (PointSet *pset); - - double getCost(); - - LabelPosition *getLabel(); - }; - - - - }; - - /** - * \brief LabelPosition cmp - * - * \return true if l.id < r.id - * \see Util::sort() - */ - bool idGrow (void *l, void *r); - /** - * \brief LabelPosition cmp - * - * \return true if l.id < r.id - * \see sort - */ - bool xGrow (void *l, void *r); - /** - * \brief LabelPosition cmp - * - * \return true if l.id > r.id - * \see sort - */ - bool yGrow (void *l, void *r); - /** - * \brief LabelPosition cmp - * - * \return true if l.id < r.id - * \see sort - */ - bool xShrink (void *l, void *r); - /** - * \brief LabelPosition cmp - * - * \return true if l.id < r.id - * \see sort - */ - bool yShrink (void *l, void *r); - /** - * \brief LabelPosition cmp - * - * \return true if l.id < r.id - * \see sort - */ + PolygonCostCalculator( LabelPosition *lp ); + + void update( PointSet *pset ); + + double getCost(); + + LabelPosition *getLabel(); + }; + + + + }; + + /** + * \brief LabelPosition cmp + * + * \return true if l.id < r.id + * \see Util::sort() + */ + bool idGrow( void *l, void *r ); + /** + * \brief LabelPosition cmp + * + * \return true if l.id < r.id + * \see sort + */ + bool xGrow( void *l, void *r ); + /** + * \brief LabelPosition cmp + * + * \return true if l.id > r.id + * \see sort + */ + bool yGrow( void *l, void *r ); + /** + * \brief LabelPosition cmp + * + * \return true if l.id < r.id + * \see sort + */ + bool xShrink( void *l, void *r ); + /** + * \brief LabelPosition cmp + * + * \return true if l.id < r.id + * \see sort + */ + bool yShrink( void *l, void *r ); + /** + * \brief LabelPosition cmp + * + * \return true if l.id < r.id + * \see sort + */ //bool nboGrow (void *l, void *r); - bool costShrink (void *l, void *r); - bool costGrow (void *l, void *r); + bool costShrink( void *l, void *r ); + bool costGrow( void *l, void *r ); } // end namespac diff --git a/src/core/pal/layer.cpp b/src/core/pal/layer.cpp index 07fb8b7ac4bd..8acd805f04c6 100644 --- a/src/core/pal/layer.cpp +++ b/src/core/pal/layer.cpp @@ -54,450 +54,506 @@ #include "simplemutex.h" -namespace pal { +namespace pal +{ - Layer::Layer (const char *lyrName, double min_scale, double max_scale, Arrangement arrangement, Units label_unit, double defaultPriority, bool obstacle, bool active, bool toLabel, Pal *pal) : pal (pal), obstacle (obstacle), active (active), toLabel (toLabel), label_unit (label_unit), min_scale (min_scale), max_scale (max_scale), arrangement (arrangement) { + Layer::Layer( const char *lyrName, double min_scale, double max_scale, Arrangement arrangement, Units label_unit, double defaultPriority, bool obstacle, bool active, bool toLabel, Pal *pal ) : pal( pal ), obstacle( obstacle ), active( active ), toLabel( toLabel ), label_unit( label_unit ), min_scale( min_scale ), max_scale( max_scale ), arrangement( arrangement ) + { - this->name = new char[strlen (lyrName) +1]; - strcpy (this->name, lyrName); + this->name = new char[strlen( lyrName ) +1]; + strcpy( this->name, lyrName ); - modMutex = new SimpleMutex(); + modMutex = new SimpleMutex(); - //rtreeFile = new char[strlen(lyrName)+7]; - //sprintf (rtreeFile, "%s.rtree", lyrName); + //rtreeFile = new char[strlen(lyrName)+7]; + //sprintf (rtreeFile, "%s.rtree", lyrName); - rtree = new RTree(); - hashtable = new HashTable*> (5281); + rtree = new RTree(); + hashtable = new HashTable*> ( 5281 ); - if (defaultPriority < 0.0001) - this->defaultPriority = 0.0001; - else if (defaultPriority > 1.0) - this->defaultPriority = 1.0; - else - this->defaultPriority = defaultPriority; + if ( defaultPriority < 0.0001 ) + this->defaultPriority = 0.0001; + else if ( defaultPriority > 1.0 ) + this->defaultPriority = 1.0; + else + this->defaultPriority = defaultPriority; - features = new LinkedList (ptrFeatureCompare); - } + features = new LinkedList ( ptrFeatureCompare ); + } - Layer::~Layer() { - modMutex->lock(); + Layer::~Layer() + { + modMutex->lock(); - if (features) { - while (features->size()) { - delete features->pop_front(); - } - delete features; - } + if ( features ) + { + while ( features->size() ) + { + delete features->pop_front(); + } + delete features; + } - if (name) - delete[] name; + if ( name ) + delete[] name; - delete rtree; + delete rtree; - delete hashtable; - delete modMutex; - } + delete hashtable; + delete modMutex; + } - /* - Feature *Layer::getFeature(int i){ - if (i<0 || i >=int(features->size())) - return NULL; - return features->at(i); - }*/ + /* + Feature *Layer::getFeature(int i){ + if (i<0 || i >=int(features->size())) + return NULL; + return features->at(i); + }*/ - bool Layer::isScaleValid (double scale) { - return (scale >= min_scale || min_scale == -1) - && (scale <= max_scale || max_scale == -1); - } + bool Layer::isScaleValid( double scale ) + { + return ( scale >= min_scale || min_scale == -1 ) + && ( scale <= max_scale || max_scale == -1 ); + } // PUBLIC method ! - int Layer::getNbFeatures() { - return features->size(); - } + int Layer::getNbFeatures() + { + return features->size(); + } // TODO avoid : // first -> name = layer->getName() // then -> layer->rename("..."); // so -> name is broken !!! - void Layer::rename (char *name) { - if (name && strlen (this->name) > 0) { - delete[] this->name; - name = new char[strlen (name) +1]; - strcpy (this->name, name); - } + void Layer::rename( char *name ) + { + if ( name && strlen( this->name ) > 0 ) + { + delete[] this->name; + name = new char[strlen( name ) +1]; + strcpy( this->name, name ); } + } // TODO see rename() - const char *Layer::getName() { - return name; - } - - Arrangement Layer::getArrangement() { - return arrangement; - } - - void Layer::setArrangement (Arrangement arrangement) { - this->arrangement = arrangement; - } - - - bool Layer::isObstacle() { - return obstacle; - } - - bool Layer::isToLabel() { - return toLabel; - } - - bool Layer::isActive() { - return active; - } - - - double Layer::getMinScale() { - return min_scale; - } - - double Layer::getMaxScale() { - return max_scale; - } - - double Layer::getPriority() { - return defaultPriority; - } - - void Layer::setObstacle (bool obstacle) { - this->obstacle = obstacle; - } - - void Layer::setActive (bool active) { - this->active = active; - } - - void Layer::setToLabel (bool toLabel) { - this->toLabel = toLabel; - } - - void Layer::setMinScale (double min_scale) { - this->min_scale = min_scale; - } - - void Layer::setMaxScale (double max_scale) { - this->max_scale = max_scale; - } - - void Layer::setPriority (double priority) { - if (priority >= 1.0) // low priority - defaultPriority = 1.0; - else if (priority <= 0.0001) - defaultPriority = 0.0001; // high priority - else - defaultPriority = priority; - } + const char *Layer::getName() + { + return name; + } + + Arrangement Layer::getArrangement() + { + return arrangement; + } + + void Layer::setArrangement( Arrangement arrangement ) + { + this->arrangement = arrangement; + } + + + bool Layer::isObstacle() + { + return obstacle; + } + + bool Layer::isToLabel() + { + return toLabel; + } + + bool Layer::isActive() + { + return active; + } + + + double Layer::getMinScale() + { + return min_scale; + } + + double Layer::getMaxScale() + { + return max_scale; + } + + double Layer::getPriority() + { + return defaultPriority; + } + + void Layer::setObstacle( bool obstacle ) + { + this->obstacle = obstacle; + } + + void Layer::setActive( bool active ) + { + this->active = active; + } + + void Layer::setToLabel( bool toLabel ) + { + this->toLabel = toLabel; + } + + void Layer::setMinScale( double min_scale ) + { + this->min_scale = min_scale; + } + + void Layer::setMaxScale( double max_scale ) + { + this->max_scale = max_scale; + } + + void Layer::setPriority( double priority ) + { + if ( priority >= 1.0 ) // low priority + defaultPriority = 1.0; + else if ( priority <= 0.0001 ) + defaultPriority = 0.0001; // high priority + else + defaultPriority = priority; + } #if 0 //inline Feat *splitButterflyPolygon (Feat *f, int pt_a, int pt_b, double cx, double cy){ - int i, k; - Feat *new_feat = new Feat(); + int i, k; + Feat *new_feat = new Feat(); #ifdef _DEBUG_ - // std::cout << "splitButterFly " << f->nbPoints << " " << pt_a << " " << pt_b << std::endl; + // std::cout << "splitButterFly " << f->nbPoints << " " << pt_a << " " << pt_b << std::endl; #endif - new_feat->geom = f->geom; + new_feat->geom = f->geom; - new_feat->id = f->id; - new_feat->type = geos::geom::GEOS_POLYGON; + new_feat->id = f->id; + new_feat->type = geos::geom::GEOS_POLYGON; - if (pt_a < pt_b) - new_feat->nbPoints = pt_b - pt_a + 1; - else - new_feat->nbPoints = f->nbPoints - pt_a + pt_b + 1; + if ( pt_a < pt_b ) + new_feat->nbPoints = pt_b - pt_a + 1; + else + new_feat->nbPoints = f->nbPoints - pt_a + pt_b + 1; #ifdef _DEBUG_FULL_ - std::cout << "nbpoints:" << new_feat->nbPoints << std::endl; + std::cout << "nbpoints:" << new_feat->nbPoints << std::endl; #endif - new_feat->x = new double[new_feat->nbPoints]; - new_feat->y = new double[new_feat->nbPoints]; + new_feat->x = new double[new_feat->nbPoints]; + new_feat->y = new double[new_feat->nbPoints]; - new_feat->minmax[0] = cx; - new_feat->minmax[1] = cy; - new_feat->minmax[2] = cx; - new_feat->minmax[3] = cy; + new_feat->minmax[0] = cx; + new_feat->minmax[1] = cy; + new_feat->minmax[2] = cx; + new_feat->minmax[3] = cy; - new_feat->x[0] = cx; - new_feat->y[0] = cy; + new_feat->x[0] = cx; + new_feat->y[0] = cy; #ifdef _DEBUG_FULL_ - std::cout << new_feat->x[0] << ";" << new_feat->y[0] << std::endl; + std::cout << new_feat->x[0] << ";" << new_feat->y[0] << std::endl; #endif - for (i = pt_a, k = 1;i != pt_b;i = (i + 1) % f->nbPoints, k++) { - new_feat->x[k] = f->x[i]; - new_feat->y[k] = f->y[i]; + for ( i = pt_a, k = 1;i != pt_b;i = ( i + 1 ) % f->nbPoints, k++ ) + { + new_feat->x[k] = f->x[i]; + new_feat->y[k] = f->y[i]; - new_feat->minmax[0] = new_feat->x[k] < new_feat->minmax[0] ? new_feat->x[k] : new_feat->minmax[0]; - new_feat->minmax[2] = new_feat->x[k] > new_feat->minmax[2] ? new_feat->x[k] : new_feat->minmax[2]; + new_feat->minmax[0] = new_feat->x[k] < new_feat->minmax[0] ? new_feat->x[k] : new_feat->minmax[0]; + new_feat->minmax[2] = new_feat->x[k] > new_feat->minmax[2] ? new_feat->x[k] : new_feat->minmax[2]; - new_feat->minmax[1] = new_feat->y[k] < new_feat->minmax[1] ? new_feat->y[k] : new_feat->minmax[1]; - new_feat->minmax[3] = new_feat->y[k] > new_feat->minmax[3] ? new_feat->y[k] : new_feat->minmax[3]; + new_feat->minmax[1] = new_feat->y[k] < new_feat->minmax[1] ? new_feat->y[k] : new_feat->minmax[1]; + new_feat->minmax[3] = new_feat->y[k] > new_feat->minmax[3] ? new_feat->y[k] : new_feat->minmax[3]; #ifdef _DEBUG_FULL_ - std::cout << new_feat->x[k] << ";" << new_feat->y[k] << std::endl; + std::cout << new_feat->x[k] << ";" << new_feat->y[k] << std::endl; #endif - } - - if (f->nbHoles > 0) { - // TODO check in which part are each hole ! - new_feat->nbHoles = f->nbHoles; - new_feat->holes = new PointSet*[f->nbHoles]; - for (i = 0;i < f->nbHoles;i++) { - new_feat->holes[i] = new PointSet (*f->holes[i]); - } - } else { - new_feat->nbHoles = 0; - new_feat->holes = NULL; - } + } + + if ( f->nbHoles > 0 ) + { + // TODO check in which part are each hole ! + new_feat->nbHoles = f->nbHoles; + new_feat->holes = new PointSet*[f->nbHoles]; + for ( i = 0;i < f->nbHoles;i++ ) + { + new_feat->holes[i] = new PointSet( *f->holes[i] ); + } + } + else + { + new_feat->nbHoles = 0; + new_feat->holes = NULL; + } #ifdef _DEBUG_FULL_ - std::cout << " go to reorder ..." << std::endl; + std::cout << " go to reorder ..." << std::endl; #endif - reorderPolygon (new_feat->nbPoints, new_feat->x, new_feat->y); + reorderPolygon( new_feat->nbPoints, new_feat->x, new_feat->y ); #ifdef _DEBUG_FULL_ - std::cout << "split ok ..." << std::endl; + std::cout << "split ok ..." << std::endl; #endif - return new_feat; + return new_feat; } #endif -void Layer::registerFeature (const char *geom_id, PalGeometry *userGeom, double label_x, double label_y) { - int j; +void Layer::registerFeature( const char *geom_id, PalGeometry *userGeom, double label_x, double label_y ) +{ + int j; - if (geom_id && label_x >= 0 && label_y >= 0) { - modMutex->lock(); - j = features->size(); + if ( geom_id && label_x >= 0 && label_y >= 0 ) + { + modMutex->lock(); + j = features->size(); - if (hashtable->find (geom_id)) { - modMutex->unlock(); - throw new PalException::FeatureExists(); - return; - } + if ( hashtable->find( geom_id ) ) + { + modMutex->unlock(); + throw new PalException::FeatureExists(); + return; + } - /* Split MULTI GEOM and Collection in simple geometries*/ - GEOSGeometry *the_geom = userGeom->getGeosGeometry(); + /* Split MULTI GEOM and Collection in simple geometries*/ + GEOSGeometry *the_geom = userGeom->getGeosGeometry(); - LinkedList *finalQueue = splitGeom (the_geom, geom_id); + LinkedList *finalQueue = splitGeom( the_geom, geom_id ); - int nGeom = finalQueue->size(); - int part = 0; + int nGeom = finalQueue->size(); + int part = 0; - bool first_feat = true; + bool first_feat = true; - while (finalQueue->size() > 0) { - Feat *f = finalQueue->pop_front(); + while ( finalQueue->size() > 0 ) + { + Feat *f = finalQueue->pop_front(); #ifdef _DEBUG_FULL_ - std::cout << "f-> popped" << std::endl; + std::cout << "f-> popped" << std::endl; #endif - Feature *ft; - - switch (f->type) { - case GEOS_POINT: - case GEOS_LINESTRING: - case GEOS_POLYGON: - //case geos::geom::GEOS_POINT: - //case geos::geom::GEOS_LINESTRING: - //case geos::geom::GEOS_POLYGON: + Feature *ft; + + switch ( f->type ) + { + case GEOS_POINT: + case GEOS_LINESTRING: + case GEOS_POLYGON: + //case geos::geom::GEOS_POINT: + //case geos::geom::GEOS_LINESTRING: + //case geos::geom::GEOS_POLYGON: #ifdef _DEBUG_FULL_ - std::cout << "Create Feat" << std::endl; + std::cout << "Create Feat" << std::endl; #endif - ft = new Feature (f, this, part, nGeom, userGeom); - ft->deleteCoord(); + ft = new Feature( f, this, part, nGeom, userGeom ); + ft->deleteCoord(); #ifdef _DEBUG_FULL_ - std::cout << "Feature created" << std::endl; + std::cout << "Feature created" << std::endl; #endif - break; - default: + break; + default: #ifdef _VERBOSE_ - std::cerr << "Wrong geometry type, should never occurs !!" << std::endl; + std::cerr << "Wrong geometry type, should never occurs !!" << std::endl; #endif - exit (-1); - } + exit( -1 ); + } - double bmin[2]; - double bmax[2]; - bmin[0] = ft->xmin; - bmin[1] = ft->ymin; + double bmin[2]; + double bmax[2]; + bmin[0] = ft->xmin; + bmin[1] = ft->ymin; - bmax[0] = ft->xmax; - bmax[1] = ft->ymax; + bmax[0] = ft->xmax; + bmax[1] = ft->ymax; - ft->label_x = label_x; - ft->label_y = label_y; + ft->label_x = label_x; + ft->label_y = label_y; - features->push_back (ft); + features->push_back( ft ); - if (first_feat) { - hashtable->insertItem (geom_id, features->last); - first_feat = false; - } + if ( first_feat ) + { + hashtable->insertItem( geom_id, features->last ); + first_feat = false; + } #ifdef _DEBUG_FULL_ - std::cout << "Feat box : " << bmin[0] << " " << bmin[1] << " " << bmax[0] << " " << bmax[1] << std::endl; + std::cout << "Feat box : " << bmin[0] << " " << bmin[1] << " " << bmax[0] << " " << bmax[1] << std::endl; #endif - rtree->Insert (bmin, bmax, ft); + rtree->Insert( bmin, bmax, ft ); #ifdef _DEBUG_FULL_ - std::cout << "feature inserted :-)" << std::endl; + std::cout << "feature inserted :-)" << std::endl; #endif - delete f; + delete f; #ifdef _DEBUG_FULL_ - std::cout << "f deleted..." << std::endl; + std::cout << "f deleted..." << std::endl; #endif - part++; - } - delete finalQueue; - - userGeom->releaseGeosGeometry (the_geom); + part++; } - modMutex->unlock(); -} - + delete finalQueue; -Cell* Layer::getFeatureIt (const char * geom_id) { - Cell** it = hashtable->find (geom_id); - - if (it) - return *it; - else - return NULL; + userGeom->releaseGeosGeometry( the_geom ); + } + modMutex->unlock(); } -void Layer::setFeatureDistlabel (const char * geom_id, int distlabel) { - int i; - if (distlabel < 0) { - std::cerr << "setFeatureDistlabel : invalid size : " << distlabel << std::endl; - throw new PalException::ValueNotInRange(); - return; - } - - modMutex->lock(); - Cell* it = getFeatureIt (geom_id); +Cell* Layer::getFeatureIt( const char * geom_id ) +{ + Cell** it = hashtable->find( geom_id ); - if (it) { - // log - Feature *feat = it->item; - int nb = feat->nPart; - - for (i = 0;i < nb;i++) { - feat = it->item; - feat->distlabel = distlabel; - it = it->next; - } - } else { - std::cerr << "setFeatureDistlabel " << geom_id << " not found" << std::endl; - modMutex->unlock(); - throw new PalException::UnknownFeature(); - } - modMutex->unlock(); + if ( it ) + return *it; + else + return NULL; } - -int Layer::getFeatureDistlabel (const char *geom_id) { - modMutex->lock(); - Cell* it = getFeatureIt (geom_id); - - int ret = -1; - if (it) - ret = it->item->distlabel; - else { - modMutex->unlock(); - throw new PalException::UnknownFeature(); - } - +void Layer::setFeatureDistlabel( const char * geom_id, int distlabel ) +{ + int i; + + if ( distlabel < 0 ) + { + std::cerr << "setFeatureDistlabel : invalid size : " << distlabel << std::endl; + throw new PalException::ValueNotInRange(); + return; + } + + modMutex->lock(); + Cell* it = getFeatureIt( geom_id ); + + if ( it ) + { + // log + Feature *feat = it->item; + int nb = feat->nPart; + + for ( i = 0;i < nb;i++ ) + { + feat = it->item; + feat->distlabel = distlabel; + it = it->next; + } + } + else + { + std::cerr << "setFeatureDistlabel " << geom_id << " not found" << std::endl; modMutex->unlock(); - return ret; + throw new PalException::UnknownFeature(); + } + modMutex->unlock(); } -void Layer::setFeatureLabelSize (const char * geom_id, double label_x, double label_y) { - int i; - if (label_x < 0 || label_y < 0) { - std::cerr << "setFeatureLabelSize : invalid size : " << label_x << ";" << label_y << std::endl; - throw new PalException::ValueNotInRange(); - return; - } +int Layer::getFeatureDistlabel( const char *geom_id ) +{ + modMutex->lock(); + Cell* it = getFeatureIt( geom_id ); - modMutex->lock(); - Cell* it = getFeatureIt (geom_id); + int ret = -1; + if ( it ) + ret = it->item->distlabel; + else + { + modMutex->unlock(); + throw new PalException::UnknownFeature(); + } - if (it) { - Feature *feat = it->item; - int nb = feat->nPart; + modMutex->unlock(); + return ret; +} - for (i = 0;i < nb;i++) { - feat = it->item; - feat->label_x = label_x; - feat->label_y = label_y; - it = it->next; - } - } else { - std::cerr << "setFeaturelabelSizeFeature " << geom_id << " not found" << std::endl; - modMutex->unlock(); - throw new PalException::UnknownFeature(); - } +void Layer::setFeatureLabelSize( const char * geom_id, double label_x, double label_y ) +{ + int i; + + if ( label_x < 0 || label_y < 0 ) + { + std::cerr << "setFeatureLabelSize : invalid size : " << label_x << ";" << label_y << std::endl; + throw new PalException::ValueNotInRange(); + return; + } + + modMutex->lock(); + Cell* it = getFeatureIt( geom_id ); + + if ( it ) + { + Feature *feat = it->item; + int nb = feat->nPart; + + for ( i = 0;i < nb;i++ ) + { + feat = it->item; + feat->label_x = label_x; + feat->label_y = label_y; + it = it->next; + } + } + else + { + std::cerr << "setFeaturelabelSizeFeature " << geom_id << " not found" << std::endl; modMutex->unlock(); + throw new PalException::UnknownFeature(); + } + modMutex->unlock(); } -double Layer::getFeatureLabelHeight (const char *geom_id) { - modMutex->lock(); - Cell* it = getFeatureIt (geom_id); - - double ret = -1; +double Layer::getFeatureLabelHeight( const char *geom_id ) +{ + modMutex->lock(); + Cell* it = getFeatureIt( geom_id ); - if (it) - ret = it->item->label_y; - else { - modMutex->unlock(); - throw new PalException::UnknownFeature(); - } + double ret = -1; + if ( it ) + ret = it->item->label_y; + else + { modMutex->unlock(); + throw new PalException::UnknownFeature(); + } - return ret; + modMutex->unlock(); + + return ret; } -double Layer::getFeatureLabelWidth (const char *geom_id) { - modMutex->lock(); - Cell* it = getFeatureIt (geom_id); - double ret = -1; - - if (it) - ret = it->item->label_x; - else { - modMutex->unlock(); - throw new PalException::UnknownFeature(); - } +double Layer::getFeatureLabelWidth( const char *geom_id ) +{ + modMutex->lock(); + Cell* it = getFeatureIt( geom_id ); + double ret = -1; + + if ( it ) + ret = it->item->label_x; + else + { modMutex->unlock(); - return ret; + throw new PalException::UnknownFeature(); + } + modMutex->unlock(); + return ret; } - void Layer::setLabelUnit (Units label_unit) { - if (label_unit == PIXEL || label_unit == METER) - this->label_unit = label_unit; - } +void Layer::setLabelUnit( Units label_unit ) +{ + if ( label_unit == PIXEL || label_unit == METER ) + this->label_unit = label_unit; +} - Units Layer::getLabelUnit () { - return label_unit; - } +Units Layer::getLabelUnit() +{ + return label_unit; +} diff --git a/src/core/pal/layer.h b/src/core/pal/layer.h index fba7baa6fc3c..aec8c94ffb87 100644 --- a/src/core/pal/layer.h +++ b/src/core/pal/layer.h @@ -40,303 +40,305 @@ #include -namespace pal { +namespace pal +{ //#include - template class LinkedList; - template class Cell; - template class HashTable; + template class LinkedList; + template class Cell; + template class HashTable; - template class RTree; + template class RTree; - class Feature; - class Pal; - class SimpleMutex; + class Feature; + class Pal; + class SimpleMutex; - class Feat; + class Feat; - /** - * \brief A layer of spacial entites - * - * a layer is a bog of feature with some data which influence the labelling process - * - * \author Maxence Laurent - */ - class Layer { - friend class Pal; - friend class Feature; + /** + * \brief A layer of spacial entites + * + * a layer is a bog of feature with some data which influence the labelling process + * + * \author Maxence Laurent + */ + class Layer + { + friend class Pal; + friend class Feature; - friend class Problem; + friend class Problem; - friend class LabelPosition; - friend bool extractFeatCallback (Feature *ft_ptr, void *ctx); - friend bool pruneLabelPositionCallback (LabelPosition *lp, void *ctx); - friend bool obstacleCallback (PointSet *feat, void *ctx); - friend void toSVGPath (int nbPoints, double *x, double *y, int dpi, Layer *layer, int type, char *uid, std::ostream &out, double scale, int xmin, int ymax, bool exportInfo, char *color); - friend bool filteringCallback (PointSet*, void*); + friend class LabelPosition; + friend bool extractFeatCallback( Feature *ft_ptr, void *ctx ); + friend bool pruneLabelPositionCallback( LabelPosition *lp, void *ctx ); + friend bool obstacleCallback( PointSet *feat, void *ctx ); + friend void toSVGPath( int nbPoints, double *x, double *y, int dpi, Layer *layer, int type, char *uid, std::ostream &out, double scale, int xmin, int ymax, bool exportInfo, char *color ); + friend bool filteringCallback( PointSet*, void* ); protected: - char *name; /* unique */ + char *name; /* unique */ - LinkedList *features; + LinkedList *features; - Pal *pal; + Pal *pal; - double defaultPriority; + double defaultPriority; - bool obstacle; - bool active; - bool toLabel; + bool obstacle; + bool active; + bool toLabel; - Units label_unit; + Units label_unit; - double min_scale; - double max_scale; + double min_scale; + double max_scale; - Arrangement arrangement; + Arrangement arrangement; - // indexes (spatial and id) - RTree *rtree; - HashTable*> *hashtable; + // indexes (spatial and id) + RTree *rtree; + HashTable*> *hashtable; - SimpleMutex *modMutex; + SimpleMutex *modMutex; - /** - * \brief Create a new layer - * - * @param lyrName layer's name - * @param min_scale bellow this scale: no labeling - * @param max_scale above this scale: no labeling - * @param arrangement Arrangement mode : how to place candidates - * @param label_unit Unit for labels sizes - * @param defaultPriority layer's prioriry (0 is the best, 1 the worst) - * @param obstacle 'true' will discourage other label to be placed above features of this layer - * @param active is the layer is active (currently displayed) - * @param toLabel the layer will be labeled whether toLablel is true - * @param pal pointer to the pal object - * - */ - Layer (const char *lyrName, double min_scale, double max_scale, Arrangement arrangement, Units label_unit, double defaultPriority, bool obstacle, bool active, bool toLabel, Pal *pal); + /** + * \brief Create a new layer + * + * @param lyrName layer's name + * @param min_scale bellow this scale: no labeling + * @param max_scale above this scale: no labeling + * @param arrangement Arrangement mode : how to place candidates + * @param label_unit Unit for labels sizes + * @param defaultPriority layer's prioriry (0 is the best, 1 the worst) + * @param obstacle 'true' will discourage other label to be placed above features of this layer + * @param active is the layer is active (currently displayed) + * @param toLabel the layer will be labeled whether toLablel is true + * @param pal pointer to the pal object + * + */ + Layer( const char *lyrName, double min_scale, double max_scale, Arrangement arrangement, Units label_unit, double defaultPriority, bool obstacle, bool active, bool toLabel, Pal *pal ); - /** - * \brief Delete the layer - */ - virtual ~Layer(); + /** + * \brief Delete the layer + */ + virtual ~Layer(); - /** - * \brief look up for a feature in layer and return an iterator pointing to the feature - * @param geom_id unique identifier of the feature - * @return an iterator pointng to the feature or NULL if the feature does not exists - */ - Cell *getFeatureIt (const char * geom_id); + /** + * \brief look up for a feature in layer and return an iterator pointing to the feature + * @param geom_id unique identifier of the feature + * @return an iterator pointng to the feature or NULL if the feature does not exists + */ + Cell *getFeatureIt( const char * geom_id ); - /** - * \brief check if the scal is in the scale range min_scale -> max_scale - * @param scale the scale to check - */ - bool isScaleValid (double scale); + /** + * \brief check if the scal is in the scale range min_scale -> max_scale + * @param scale the scale to check + */ + bool isScaleValid( double scale ); public: - /** - * \brief get the number of features into layer - */ - int getNbFeatures(); - - /** - * \brief get layer's name - */ - const char * getName(); - - - /** - * \brief rename the layer - * @param name the new name - */ - void rename (char *name); - - /** - * \brief get arrangement policy - */ - Arrangement getArrangement(); - - /** - * \brief set arrangement policy - * - * @param arrangement arrangement policy - */ - void setArrangement (Arrangement arrangement); - - /** - * \brief get units for label size - */ - Units getLabelUnit (); - - /** - * \brief set unit for label size - * - */ - void setLabelUnit (Units label_unit); - - /** - * \brief activate or desactivate the layer - * - * active means "is currently display". When active is false - * feature of this layer will never be used (neither for - * labelling nor as obstacles) - * - * @param active turn the layer active (true) or inactive (false) - */ - void setActive (bool active); - - /** - * \brief return the layer's activity status - */ - bool isActive(); - - - /** - * \brief tell pal whether the layer has to be labelled. - * - * The layer will be labelled if and only if toLabel and isActive were set to true - * - * @param toLabel set to false disable lbelling this layer - */ - void setToLabel (bool toLabel); - - - /** - * \brief return if the layer will be labelled or not - */ - bool isToLabel(); - - - /** - * \brief mark layer's features as obstacles - * - * Avoid putting labels over obstalces. - * isActive must also be true to consider feature as obstacles, - * otherwise they will be ignored - */ - void setObstacle (bool obstacle); - - /** - * \brief return the obstacle status - */ - bool isObstacle(); - - /** - * \brief set the minimum valid scale, below this scale the layer will not be labelled - * - * Use -1 to disable - */ - void setMinScale (double min_scale); - - /** - * \brief return the minimum valid scale - */ - double getMinScale(); - - - /** - * \brief set the maximum valid scale, upon this scale the layer will not be labelled - * - * use -1 to disable - */ - void setMaxScale (double max_scale); - - - /** - * \brief return the maximum valid scale - */ - double getMaxScale(); - - - /** - * \ brief set the layer priority - * - * The best priority is 0, the worst is 1 - * Should be links with a slider in a nice gui - */ - void setPriority (double priority); - - - /** - * return the layer's priority - */ - double getPriority(); - - /** - * \brief register a feature in the layer - * - * @param geom_id unique identifier - * @param label_x label width - * @param label_y label height - * @param userGeom user's geometry that implements the PalGeometry interface - * - * @throws PalException::FeatureExists - */ - void registerFeature (const char *geom_id, PalGeometry *userGeom, double label_x =-1, double label_y = -1); - - // TODO implement - //void unregisterFeature (const char *geom_id); - - // TODO call that when a geometry change (a moveing points, etc) - //void updateFeature(); - - /** - * \brief change the label size for a feature - * - * @param geom_id unique identifier of the feature - * @param label_x new label width - * @param label_y new label height - * - * @throws PalException::UnknownFeature - * @throws PalException::ValueNotInRange - */ - void setFeatureLabelSize (const char *geom_id, double label_x, double label_y); - - /** - * \brief get the label height for a specific feature - * - * @param geom_id unique of the feature - * - * @throws PalException::UnknownFeature - */ - double getFeatureLabelHeight (const char *geom_id); - - /** - * \brief get the label width for a specific feature - * - * @param geom_id unique of the feature - * - * @throws PalException::UnknownFeature - */ - double getFeatureLabelWidth (const char *geom_id); - - - /** - * \brief set the symbol size (pixel) for a specific feature - * - * @param geom_id unique od of the feaiture - * @param distlabel symbol size (point radius or line width) - * - * @throws PalException::UnknownFeature - * @throws PalException::ValueNotInRange - */ - void setFeatureDistlabel (const char *geom_id, int distlabel); - - /** - * \brief get the symbol size (pixel) for a specific feature - * - * @param geom_id unique of of the feature - * @return the symbol size (point radius or line width) - * - * @throws PalException::UnknownFeature - */ - int getFeatureDistlabel (const char *geom_id); - - }; + /** + * \brief get the number of features into layer + */ + int getNbFeatures(); + + /** + * \brief get layer's name + */ + const char * getName(); + + + /** + * \brief rename the layer + * @param name the new name + */ + void rename( char *name ); + + /** + * \brief get arrangement policy + */ + Arrangement getArrangement(); + + /** + * \brief set arrangement policy + * + * @param arrangement arrangement policy + */ + void setArrangement( Arrangement arrangement ); + + /** + * \brief get units for label size + */ + Units getLabelUnit(); + + /** + * \brief set unit for label size + * + */ + void setLabelUnit( Units label_unit ); + + /** + * \brief activate or desactivate the layer + * + * active means "is currently display". When active is false + * feature of this layer will never be used (neither for + * labelling nor as obstacles) + * + * @param active turn the layer active (true) or inactive (false) + */ + void setActive( bool active ); + + /** + * \brief return the layer's activity status + */ + bool isActive(); + + + /** + * \brief tell pal whether the layer has to be labelled. + * + * The layer will be labelled if and only if toLabel and isActive were set to true + * + * @param toLabel set to false disable lbelling this layer + */ + void setToLabel( bool toLabel ); + + + /** + * \brief return if the layer will be labelled or not + */ + bool isToLabel(); + + + /** + * \brief mark layer's features as obstacles + * + * Avoid putting labels over obstalces. + * isActive must also be true to consider feature as obstacles, + * otherwise they will be ignored + */ + void setObstacle( bool obstacle ); + + /** + * \brief return the obstacle status + */ + bool isObstacle(); + + /** + * \brief set the minimum valid scale, below this scale the layer will not be labelled + * + * Use -1 to disable + */ + void setMinScale( double min_scale ); + + /** + * \brief return the minimum valid scale + */ + double getMinScale(); + + + /** + * \brief set the maximum valid scale, upon this scale the layer will not be labelled + * + * use -1 to disable + */ + void setMaxScale( double max_scale ); + + + /** + * \brief return the maximum valid scale + */ + double getMaxScale(); + + + /** + * \ brief set the layer priority + * + * The best priority is 0, the worst is 1 + * Should be links with a slider in a nice gui + */ + void setPriority( double priority ); + + + /** + * return the layer's priority + */ + double getPriority(); + + /** + * \brief register a feature in the layer + * + * @param geom_id unique identifier + * @param label_x label width + * @param label_y label height + * @param userGeom user's geometry that implements the PalGeometry interface + * + * @throws PalException::FeatureExists + */ + void registerFeature( const char *geom_id, PalGeometry *userGeom, double label_x = -1, double label_y = -1 ); + + // TODO implement + //void unregisterFeature (const char *geom_id); + + // TODO call that when a geometry change (a moveing points, etc) + //void updateFeature(); + + /** + * \brief change the label size for a feature + * + * @param geom_id unique identifier of the feature + * @param label_x new label width + * @param label_y new label height + * + * @throws PalException::UnknownFeature + * @throws PalException::ValueNotInRange + */ + void setFeatureLabelSize( const char *geom_id, double label_x, double label_y ); + + /** + * \brief get the label height for a specific feature + * + * @param geom_id unique of the feature + * + * @throws PalException::UnknownFeature + */ + double getFeatureLabelHeight( const char *geom_id ); + + /** + * \brief get the label width for a specific feature + * + * @param geom_id unique of the feature + * + * @throws PalException::UnknownFeature + */ + double getFeatureLabelWidth( const char *geom_id ); + + + /** + * \brief set the symbol size (pixel) for a specific feature + * + * @param geom_id unique od of the feaiture + * @param distlabel symbol size (point radius or line width) + * + * @throws PalException::UnknownFeature + * @throws PalException::ValueNotInRange + */ + void setFeatureDistlabel( const char *geom_id, int distlabel ); + + /** + * \brief get the symbol size (pixel) for a specific feature + * + * @param geom_id unique of of the feature + * @return the symbol size (point radius or line width) + * + * @throws PalException::UnknownFeature + */ + int getFeatureDistlabel( const char *geom_id ); + + }; } // end namespace pal diff --git a/src/core/pal/pal.cpp b/src/core/pal/pal.cpp index 65b4cf222ebd..1801bc08f7cc 100644 --- a/src/core/pal/pal.cpp +++ b/src/core/pal/pal.cpp @@ -58,1134 +58,1241 @@ #include "simplemutex.h" #include "util.h" -namespace pal { - - typedef struct { - //LabelPosition *lp; - double scale; - Pal* pal; - PointSet *obstacle; - } PruneCtx; - - void geosError (const char *fmt, ...) { - va_list list; - va_start (list, fmt); - vfprintf (stderr, fmt, list); - } - - void geosNotice (const char *fmt, ...) { - va_list list; - va_start (list, fmt); - vfprintf (stdout, fmt, list); - } - - Pal::Pal() { - initGEOS (geosNotice, geosError); - - layers = new std::list(); - - lyrsMutex = new SimpleMutex(); - - ejChainDeg = 50; - tenure = 10; - candListSize = 0.2; - - tabuMinIt = 3; - tabuMaxIt = 4; - searchMethod = POPMUSIC_CHAIN; - popmusic_r = 30; - - searchMethod = CHAIN; - - setSearch (CHAIN); - - dpi = 72; - point_p = 8; - line_p = 8; - poly_p = 8; - - this->map_unit = pal::METER; - - std::cout.precision (12); - std::cerr.precision (12); - - tmpTime = 0; - } - - std::list *Pal::getLayers () { - // TODO make const ! or whatever else - return layers; - } - - Layer *Pal::getLayer (const char *lyrName) { - lyrsMutex->lock(); - for (std::list::iterator it = layers->begin(); it != layers->end();it++) - if (strcmp ( (*it)->name, lyrName) == 0) { - lyrsMutex->unlock(); - return *it; - } - - lyrsMutex->unlock(); - throw new PalException::UnknownLayer(); - return NULL; - } - - - void Pal::removeLayer (Layer *layer) { - lyrsMutex->lock(); - if (layer) { - layers->remove (layer); - delete layer; - } +namespace pal +{ + + typedef struct + { + //LabelPosition *lp; + double scale; + Pal* pal; + PointSet *obstacle; + } PruneCtx; + + void geosError( const char *fmt, ... ) + { + va_list list; + va_start( list, fmt ); + vfprintf( stderr, fmt, list ); + } + + void geosNotice( const char *fmt, ... ) + { + va_list list; + va_start( list, fmt ); + vfprintf( stdout, fmt, list ); + } + + Pal::Pal() + { + initGEOS( geosNotice, geosError ); + + layers = new std::list(); + + lyrsMutex = new SimpleMutex(); + + ejChainDeg = 50; + tenure = 10; + candListSize = 0.2; + + tabuMinIt = 3; + tabuMaxIt = 4; + searchMethod = POPMUSIC_CHAIN; + popmusic_r = 30; + + searchMethod = CHAIN; + + setSearch( CHAIN ); + + dpi = 72; + point_p = 8; + line_p = 8; + poly_p = 8; + + this->map_unit = pal::METER; + + std::cout.precision( 12 ); + std::cerr.precision( 12 ); + + tmpTime = 0; + } + + std::list *Pal::getLayers() + { + // TODO make const ! or whatever else + return layers; + } + + Layer *Pal::getLayer( const char *lyrName ) + { + lyrsMutex->lock(); + for ( std::list::iterator it = layers->begin(); it != layers->end();it++ ) + if ( strcmp(( *it )->name, lyrName ) == 0 ) + { lyrsMutex->unlock(); + return *it; + } + + lyrsMutex->unlock(); + throw new PalException::UnknownLayer(); + return NULL; + } + + + void Pal::removeLayer( Layer *layer ) + { + lyrsMutex->lock(); + if ( layer ) + { + layers->remove( layer ); + delete layer; } + lyrsMutex->unlock(); + } - Pal::~Pal() { + Pal::~Pal() + { - std::cout << "Acces/Concvert time: " << (double) tmpTime / CLOCKS_PER_SEC << std::endl; + std::cout << "Acces/Concvert time: " << ( double ) tmpTime / CLOCKS_PER_SEC << std::endl; - lyrsMutex->lock(); - while (layers->size() > 0) { - delete layers->front(); - layers->pop_front(); - } + lyrsMutex->lock(); + while ( layers->size() > 0 ) + { + delete layers->front(); + layers->pop_front(); + } - delete layers; - delete lyrsMutex; + delete layers; + delete lyrsMutex; - finishGEOS(); - } + finishGEOS(); + } - Layer * Pal::addLayer (const char *lyrName, double min_scale, double max_scale, Arrangement arrangement, Units label_unit, double defaultPriority, bool obstacle, bool active, bool toLabel) { + Layer * Pal::addLayer( const char *lyrName, double min_scale, double max_scale, Arrangement arrangement, Units label_unit, double defaultPriority, bool obstacle, bool active, bool toLabel ) + { - Layer *lyr; - lyrsMutex->lock(); + Layer *lyr; + lyrsMutex->lock(); #ifdef _DEBUG_ - std::cout << "Pal::addLayer" << std::endl; - std::cout << "lyrName:" << lyrName << std::endl; - std::cout << "nbLayers:" << layers->size() << std::endl; + std::cout << "Pal::addLayer" << std::endl; + std::cout << "lyrName:" << lyrName << std::endl; + std::cout << "nbLayers:" << layers->size() << std::endl; #endif - for (std::list::iterator it = layers->begin(); it != layers->end();it++) { - if (strcmp ( (*it)->name, lyrName) == 0) { // if layer already known - lyrsMutex->unlock(); - throw new PalException::LayerExists(); - } - } + for ( std::list::iterator it = layers->begin(); it != layers->end();it++ ) + { + if ( strcmp(( *it )->name, lyrName ) == 0 ) // if layer already known + { + lyrsMutex->unlock(); + throw new PalException::LayerExists(); + } + } - lyr = new Layer (lyrName, min_scale, max_scale, arrangement, label_unit, defaultPriority, obstacle, active, toLabel, this); - layers->push_back (lyr); + lyr = new Layer( lyrName, min_scale, max_scale, arrangement, label_unit, defaultPriority, obstacle, active, toLabel, this ); + layers->push_back( lyr ); - lyrsMutex->unlock(); + lyrsMutex->unlock(); - return lyr; - } + return lyr; + } - typedef struct _featCbackCtx { - Layer *layer; - double scale; - LinkedList *fFeats; - RTree *obstacles; - RTree *candidates; - double priority; - double bbox_min[2]; - double bbox_max[2]; + typedef struct _featCbackCtx + { + Layer *layer; + double scale; + LinkedList *fFeats; + RTree *obstacles; + RTree *candidates; + double priority; + double bbox_min[2]; + double bbox_max[2]; #ifdef _EXPORT_MAP_ - std::ofstream *svgmap; + std::ofstream *svgmap; #endif - } FeatCallBackCtx; + } FeatCallBackCtx; - /* - * Callback function - * - * Extract a specific shape from indexes - */ - bool extractFeatCallback (Feature *ft_ptr, void *ctx) { + /* + * Callback function + * + * Extract a specific shape from indexes + */ + bool extractFeatCallback( Feature *ft_ptr, void *ctx ) + { - double min[2]; - double max[2]; + double min[2]; + double max[2]; - FeatCallBackCtx *context = (FeatCallBackCtx*) ctx; + FeatCallBackCtx *context = ( FeatCallBackCtx* ) ctx; #ifdef _EXPORT_MAP_ - bool svged = false; // is the feature has been written into the svg map ? - int dpi = context->layer->pal->getDpi(); + bool svged = false; // is the feature has been written into the svg map ? + int dpi = context->layer->pal->getDpi(); #endif #ifdef _DEBUG_FULL_ - std::cout << "extract feat : " << ft_ptr->layer->name << "/" << ft_ptr->uid << std::endl; + std::cout << "extract feat : " << ft_ptr->layer->name << "/" << ft_ptr->uid << std::endl; #endif - // all feature which are obstacle will be inserted into obstacles - if (context->layer->obstacle) { - min[0] = ft_ptr->xmin; - min[1] = ft_ptr->ymin; - max[0] = ft_ptr->xmax; - max[1] = ft_ptr->ymax; - context->obstacles->Insert (min, max, ft_ptr); - - ft_ptr->fetchCoordinates (); - } + // all feature which are obstacle will be inserted into obstacles + if ( context->layer->obstacle ) + { + min[0] = ft_ptr->xmin; + min[1] = ft_ptr->ymin; + max[0] = ft_ptr->xmax; + max[1] = ft_ptr->ymax; + context->obstacles->Insert( min, max, ft_ptr ); + ft_ptr->fetchCoordinates(); + } - // feature has to be labeled ? - if (context->layer->toLabel) { - // is the feature well defined ? // TODO Check epsilon - if (ft_ptr->label_x > 0.0000001 && ft_ptr->label_y > 0.0000001) { - int i; - // Hole of the feature are obstacles - for (i = 0;i < ft_ptr->nbSelfObs;i++) { - min[0] = ft_ptr->selfObs[i]->xmin; - min[1] = ft_ptr->selfObs[i]->ymin; - max[0] = ft_ptr->selfObs[i]->xmax; - max[1] = ft_ptr->selfObs[i]->ymax; - context->obstacles->Insert (min, max, ft_ptr->selfObs[i]); + // feature has to be labeled ? + if ( context->layer->toLabel ) + { + // is the feature well defined ? // TODO Check epsilon + if ( ft_ptr->label_x > 0.0000001 && ft_ptr->label_y > 0.0000001 ) + { - if (!ft_ptr->selfObs[i]->holeOf) { - std::cout << "ERROR: SHOULD HAVE A PARENT!!!!!" << std::endl; - } - } + int i; + // Hole of the feature are obstacles + for ( i = 0;i < ft_ptr->nbSelfObs;i++ ) + { + min[0] = ft_ptr->selfObs[i]->xmin; + min[1] = ft_ptr->selfObs[i]->ymin; + max[0] = ft_ptr->selfObs[i]->xmax; + max[1] = ft_ptr->selfObs[i]->ymax; + context->obstacles->Insert( min, max, ft_ptr->selfObs[i] ); + + if ( !ft_ptr->selfObs[i]->holeOf ) + { + std::cout << "ERROR: SHOULD HAVE A PARENT!!!!!" << std::endl; + } + } - LinkedList *feats = new LinkedList (ptrFeatsCompare); + LinkedList *feats = new LinkedList ( ptrFeatsCompare ); - if ( (ft_ptr->type == GEOS_LINESTRING) - || ft_ptr->type == GEOS_POLYGON) { + if (( ft_ptr->type == GEOS_LINESTRING ) + || ft_ptr->type == GEOS_POLYGON ) + { - double bbx[4], bby[4]; + double bbx[4], bby[4]; - bbx[0] = context->bbox_min[0]; bbx[1] = context->bbox_max[0]; - bbx[2] = context->bbox_max[0]; bbx[3] = context->bbox_min[0]; + bbx[0] = context->bbox_min[0]; bbx[1] = context->bbox_max[0]; + bbx[2] = context->bbox_max[0]; bbx[3] = context->bbox_min[0]; - bby[0] = context->bbox_min[1]; bby[1] = context->bbox_min[1]; - bby[2] = context->bbox_max[1]; bby[3] = context->bbox_max[1]; + bby[0] = context->bbox_min[1]; bby[1] = context->bbox_min[1]; + bby[2] = context->bbox_max[1]; bby[3] = context->bbox_max[1]; - LinkedList *shapes = new LinkedList (ptrPSetCompare); - bool outside, inside; + LinkedList *shapes = new LinkedList ( ptrPSetCompare ); + bool outside, inside; - // Fetch coordinates - ft_ptr->fetchCoordinates (); - PointSet *shape = ft_ptr->createProblemSpecificPointSet (bbx, bby, &outside, &inside); - ft_ptr->releaseCoordinates(); + // Fetch coordinates + ft_ptr->fetchCoordinates(); + PointSet *shape = ft_ptr->createProblemSpecificPointSet( bbx, bby, &outside, &inside ); + ft_ptr->releaseCoordinates(); - if (inside) { - // no extra treatment required - shapes->push_back (shape); - } else { - // feature isn't completly in the math - if (ft_ptr->type == GEOS_LINESTRING) - PointSet::reduceLine (shape, shapes, bbx, bby); - else { - PointSet::reducePolygon (shape, shapes, bbx, bby); - } - } + if ( inside ) + { + // no extra treatment required + shapes->push_back( shape ); + } + else + { + // feature isn't completly in the math + if ( ft_ptr->type == GEOS_LINESTRING ) + PointSet::reduceLine( shape, shapes, bbx, bby ); + else + { + PointSet::reducePolygon( shape, shapes, bbx, bby ); + } + } - while (shapes->size() > 0) { - shape = shapes->pop_front(); - Feats *ft = new Feats(); - ft->feature = ft_ptr; - ft->shape = shape; - feats->push_back (ft); + while ( shapes->size() > 0 ) + { + shape = shapes->pop_front(); + Feats *ft = new Feats(); + ft->feature = ft_ptr; + ft->shape = shape; + feats->push_back( ft ); #ifdef _EXPORT_MAP_ - if (!svged) { - toSVGPath (shape->nbPoints, shape->type, shape->x, shape->y, - dpi , context->scale, - convert2pt (context->bbox_min[0], context->scale, dpi), - convert2pt (context->bbox_max[1], context->scale, dpi), - context->layer->name, ft_ptr->uid, *context->svgmap); - } + if ( !svged ) + { + toSVGPath( shape->nbPoints, shape->type, shape->x, shape->y, + dpi , context->scale, + convert2pt( context->bbox_min[0], context->scale, dpi ), + convert2pt( context->bbox_max[1], context->scale, dpi ), + context->layer->name, ft_ptr->uid, *context->svgmap ); + } #endif - } - delete shapes; - } else { - // Feat is a point - Feats *ft = new Feats(); - ft->feature = ft_ptr; - ft->shape = NULL; - feats->push_back (ft); - } - - // for earch feature part extracted : generate candidates - while (feats->size() > 0) { - Feats *ft = feats->pop_front(); + } + delete shapes; + } + else + { + // Feat is a point + Feats *ft = new Feats(); + ft->feature = ft_ptr; + ft->shape = NULL; + feats->push_back( ft ); + } + + // for earch feature part extracted : generate candidates + while ( feats->size() > 0 ) + { + Feats *ft = feats->pop_front(); #ifdef _DEBUG_ - std::cout << "Compute candidates for feat " << ft->feature->layer->name << "/" << ft->feature->uid << std::endl; + std::cout << "Compute candidates for feat " << ft->feature->layer->name << "/" << ft->feature->uid << std::endl; #endif - ft->nblp = ft->feature->setPosition (context->scale, & (ft->lPos), context->bbox_min, context->bbox_max, ft->shape, context->candidates + ft->nblp = ft->feature->setPosition( context->scale, & ( ft->lPos ), context->bbox_min, context->bbox_max, ft->shape, context->candidates #ifdef _EXPORT_MAP_ - , *context->svgmap + , *context->svgmap #endif - ); + ); - delete ft->shape; - ft->shape = NULL; + delete ft->shape; + ft->shape = NULL; - if (ft->nblp > 0) { - // valid features are added to fFeats - ft->priority = context->priority; - context->fFeats->push_back (ft); + if ( ft->nblp > 0 ) + { + // valid features are added to fFeats + ft->priority = context->priority; + context->fFeats->push_back( ft ); #ifdef _DEBUG_ - std::cout << ft->nblp << " labelPositions for feature : " << ft->feature->layer->name << "/" << ft->feature->uid << std::endl; + std::cout << ft->nblp << " labelPositions for feature : " << ft->feature->layer->name << "/" << ft->feature->uid << std::endl; #endif - } else { - // Others are deleted + } + else + { + // Others are deleted #ifdef _VERBOSE_ - std::cout << "Unable to generate labelPosition for feature : " << ft->feature->layer->name << "/" << ft->feature->uid << std::endl; + std::cout << "Unable to generate labelPosition for feature : " << ft->feature->layer->name << "/" << ft->feature->uid << std::endl; #endif - delete[] ft->lPos; - delete ft; - } - } - delete feats; - } else { // check labelsize + delete[] ft->lPos; + delete ft; + } + } + delete feats; + } + else // check labelsize + { #ifdef _VERBOSE_ - std::cerr << "Feature " << ft_ptr->layer->name << "/" << ft_ptr->uid << " is skipped (label size = 0)" << std::endl; + std::cerr << "Feature " << ft_ptr->layer->name << "/" << ft_ptr->uid << " is skipped (label size = 0)" << std::endl; #endif - } - } - return true; + } } + return true; + } - double dist_pointToLabel (double xp, double yp, LabelPosition *lp) { + double dist_pointToLabel( double xp, double yp, LabelPosition *lp ) + { - int i; - int j; - - double mx[4]; - double my[4]; + int i; + int j; - double dist_min = DBL_MAX; - double dist; + double mx[4]; + double my[4]; - for (i = 0;i < 4;i++) { - j = (i + 1) % 4; - mx[i] = (lp->x[i] + lp->x[j]) / 2.0; - my[i] = (lp->y[i] + lp->y[j]) / 2.0; - } + double dist_min = DBL_MAX; + double dist; + for ( i = 0;i < 4;i++ ) + { + j = ( i + 1 ) % 4; + mx[i] = ( lp->x[i] + lp->x[j] ) / 2.0; + my[i] = ( lp->y[i] + lp->y[j] ) / 2.0; + } - if (vabs (cross_product (mx[0], my[0], my[2], my[2], xp, yp) / lp->h) < lp->w / 2) { - dist = cross_product (lp->x[0], lp->y[0], lp->x[1], lp->y[1], xp, yp) / lp->w; - if (vabs (dist) < vabs (dist_min)) - dist_min = dist; - dist = cross_product (lp->x[2], lp->y[2], lp->x[3], lp->y[3], xp, yp) / lp->w; - if (vabs (dist) < vabs (dist_min)) - dist_min = dist; - } + if ( vabs( cross_product( mx[0], my[0], my[2], my[2], xp, yp ) / lp->h ) < lp->w / 2 ) + { + dist = cross_product( lp->x[0], lp->y[0], lp->x[1], lp->y[1], xp, yp ) / lp->w; + if ( vabs( dist ) < vabs( dist_min ) ) + dist_min = dist; - if (vabs (cross_product (mx[1], my[1], my[3], my[3], xp, yp) / lp->w) < lp->h / 2) { - dist = cross_product (lp->x[1], lp->y[1], lp->x[2], lp->y[2], xp, yp) / lp->h; - if (vabs (dist) < vabs (dist_min)) - dist_min = dist; + dist = cross_product( lp->x[2], lp->y[2], lp->x[3], lp->y[3], xp, yp ) / lp->w; + if ( vabs( dist ) < vabs( dist_min ) ) + dist_min = dist; + } - dist = cross_product (lp->x[3], lp->y[3], lp->x[0], lp->y[0], xp, yp) / lp->h; - if (vabs (dist) < vabs (dist_min)) - dist_min = dist; - } + if ( vabs( cross_product( mx[1], my[1], my[3], my[3], xp, yp ) / lp->w ) < lp->h / 2 ) + { + dist = cross_product( lp->x[1], lp->y[1], lp->x[2], lp->y[2], xp, yp ) / lp->h; + if ( vabs( dist ) < vabs( dist_min ) ) + dist_min = dist; - for (i = 0;i < 4;i++) { - dist = dist_euc2d (lp->x[i], lp->y[i], xp, yp); - if (vabs (dist) < vabs (dist_min)) - dist_min = dist; - } + dist = cross_product( lp->x[3], lp->y[3], lp->x[0], lp->y[0], xp, yp ) / lp->h; + if ( vabs( dist ) < vabs( dist_min ) ) + dist_min = dist; + } - return dist_min; + for ( i = 0;i < 4;i++ ) + { + dist = dist_euc2d( lp->x[i], lp->y[i], xp, yp ); + if ( vabs( dist ) < vabs( dist_min ) ) + dist_min = dist; } + return dist_min; + } - /* - * Check wheter the candidate in ctx overlap with obstacle feat - */ - bool pruneLabelPositionCallback (LabelPosition *lp, void *ctx) { - PointSet *feat = ( (PruneCtx*) ctx)->obstacle; - double scale = ( (PruneCtx*) ctx)->scale; - Pal* pal = ( (PruneCtx*) ctx)->pal; + /* + * Check wheter the candidate in ctx overlap with obstacle feat + */ + bool pruneLabelPositionCallback( LabelPosition *lp, void *ctx ) + { - if ( (feat == lp->feature) || (feat->holeOf && feat->holeOf != lp->feature)) { - return true; - } + PointSet *feat = (( PruneCtx* ) ctx )->obstacle; + double scale = (( PruneCtx* ) ctx )->scale; + Pal* pal = (( PruneCtx* ) ctx )->pal; - int n; + if (( feat == lp->feature ) || ( feat->holeOf && feat->holeOf != lp->feature ) ) + { + return true; + } - int i, j; - double ca, cb; + int n; - n = 0; + int i, j; + double ca, cb; - //if (!feat->holeOf) - //((Feature*)feat)->fetchCoordinates(); + n = 0; - double dist; + //if (!feat->holeOf) + //((Feature*)feat)->fetchCoordinates(); - double distlabel = unit_convert(double(lp->feature->distlabel), - pal::PIXEL, - pal->map_unit, - pal->dpi, scale, 1); + double dist; + double distlabel = unit_convert( double( lp->feature->distlabel ), + pal::PIXEL, + pal->map_unit, + pal->dpi, scale, 1 ); - switch (feat->type) { - //case geos::geom::GEOS_POINT: - case GEOS_POINT: + + switch ( feat->type ) + { + //case geos::geom::GEOS_POINT: + case GEOS_POINT: #ifdef _DEBUG_FULL - std::cout << " POINT" << std::endl; + std::cout << " POINT" << std::endl; #endif - dist = dist_pointToLabel (feat->x[0], feat->y[0], lp); + dist = dist_pointToLabel( feat->x[0], feat->y[0], lp ); - if (dist < 0) - n = 2; - else if (dist < distlabel) - n = 1; - else - n = 0; + if ( dist < 0 ) + n = 2; + else if ( dist < distlabel ) + n = 1; + else + n = 0; - break; + break; - //case geos::geom::GEOS_LINESTRING: - case GEOS_LINESTRING: + //case geos::geom::GEOS_LINESTRING: + case GEOS_LINESTRING: #ifdef _DEBUG_FULL - std::cout << " LINE" << std::endl; + std::cout << " LINE" << std::endl; #endif - // Is one of label's boarder cross the line ? - for (i = 0;i < 4;i++) { - for (j = 0;j < feat->nbPoints - 1;j++) { - ca = cross_product (lp->x[i], lp->y[i], lp->x[ (i+1) %4], lp->y[ (i+1) %4], - feat->x[j], feat->y[j]); - cb = cross_product (lp->x[i], lp->y[i], lp->x[ (i+1) %4], lp->y[ (i+1) %4], - feat->x[j+1], feat->y[j+1]); - - if ( (ca < 0 && cb > 0) || (ca > 0 && cb < 0)) { - ca = cross_product (feat->x[j], feat->y[j], feat->x[j+1], feat->y[j+1], - lp->x[i], lp->y[i]); - cb = cross_product (feat->x[j], feat->y[j], feat->x[j+1], feat->y[j+1], - lp->x[ (i+1) %4], lp->y[ (i+1) %4]); - if ( (ca < 0 && cb > 0) || (ca > 0 && cb < 0)) { - n = 1; - i = 4; - break; - } - } - } + // Is one of label's boarder cross the line ? + for ( i = 0;i < 4;i++ ) + { + for ( j = 0;j < feat->nbPoints - 1;j++ ) + { + ca = cross_product( lp->x[i], lp->y[i], lp->x[( i+1 ) %4], lp->y[( i+1 ) %4], + feat->x[j], feat->y[j] ); + cb = cross_product( lp->x[i], lp->y[i], lp->x[( i+1 ) %4], lp->y[( i+1 ) %4], + feat->x[j+1], feat->y[j+1] ); + + if (( ca < 0 && cb > 0 ) || ( ca > 0 && cb < 0 ) ) + { + ca = cross_product( feat->x[j], feat->y[j], feat->x[j+1], feat->y[j+1], + lp->x[i], lp->y[i] ); + cb = cross_product( feat->x[j], feat->y[j], feat->x[j+1], feat->y[j+1], + lp->x[( i+1 ) %4], lp->y[( i+1 ) %4] ); + if (( ca < 0 && cb > 0 ) || ( ca > 0 && cb < 0 ) ) + { + n = 1; + i = 4; + break; + } } - break; - //case geos::geom::GEOS_POLYGON: - case GEOS_POLYGON: + } + } + break; + //case geos::geom::GEOS_POLYGON: + case GEOS_POLYGON: #ifdef _DEBUG_FULL - std::cout << " POLY" << std::endl; + std::cout << " POLY" << std::endl; #endif - n = nbLabelPointInPolygon (feat->nbPoints, feat->x, feat->y, lp->x, lp->y); + n = nbLabelPointInPolygon( feat->nbPoints, feat->x, feat->y, lp->x, lp->y ); - //n<1?n=0:n=1; - break; - } + //n<1?n=0:n=1; + break; + } - // label cost is penalized - lp->cost += double (n); + // label cost is penalized + lp->cost += double( n ); - //if (!feat->holeOf) - //((Feature*)feat)->releaseCoordinates(); + //if (!feat->holeOf) + //((Feature*)feat)->releaseCoordinates(); - return true; - } + return true; + } - bool releaseCallback (PointSet *pset, void *ctx) { - if (pset->holeOf == NULL) { - ( (Feature*) pset)->releaseCoordinates(); - } - return true; + bool releaseCallback( PointSet *pset, void *ctx ) + { + if ( pset->holeOf == NULL ) + { + (( Feature* ) pset )->releaseCoordinates(); } + return true; + } - void releaseAllInIndex (RTree *obstacles) { - /* - RTree::Iterator it; - for (obstacles->GetFirst(it) ; it.IsNotNull(); obstacles->GetNext(it)){ - if (!(*it)->holeOf){ - std::cout << "Release obs:" << ((Feature*)(*it))->layer->getName() << "/" << ((Feature*)(*it))->uid << std::endl; - ((Feature*)(*it))->releaseCoordinates(); - } + void releaseAllInIndex( RTree *obstacles ) + { + /* + RTree::Iterator it; + for (obstacles->GetFirst(it) ; it.IsNotNull(); obstacles->GetNext(it)){ + if (!(*it)->holeOf){ + std::cout << "Release obs:" << ((Feature*)(*it))->layer->getName() << "/" << ((Feature*)(*it))->uid << std::endl; + ((Feature*)(*it))->releaseCoordinates(); } - */ - + } + */ - double amin[2]; - double amax[2]; - amin[0] = amin[1] = -DBL_MAX; - amax[0] = amax[1] = DBL_MAX; + double amin[2]; + double amax[2]; - obstacles->Search (amin, amax, releaseCallback, NULL); - } + amin[0] = amin[1] = -DBL_MAX; + amax[0] = amax[1] = DBL_MAX; + obstacles->Search( amin, amax, releaseCallback, NULL ); + } - typedef struct _filterContext { - RTree *cdtsIndex; - double scale; - Pal* pal; - } FilterContext; - bool filteringCallback (PointSet *pset, void *ctx) { + typedef struct _filterContext + { + RTree *cdtsIndex; + double scale; + Pal* pal; + } FilterContext; - RTree *cdtsIndex = ( (FilterContext*) ctx)->cdtsIndex; - double scale = ( (FilterContext*) ctx)->scale; - Pal* pal = ((FilterContext*)ctx)->pal; + bool filteringCallback( PointSet *pset, void *ctx ) + { - if (pset->holeOf == NULL) { - ( (Feature*) pset)->fetchCoordinates(); - } else { - ( (Feature*) pset->holeOf)->fetchCoordinates(); - } + RTree *cdtsIndex = (( FilterContext* ) ctx )->cdtsIndex; + double scale = (( FilterContext* ) ctx )->scale; + Pal* pal = (( FilterContext* )ctx )->pal; - double amin[2], amax[2]; + if ( pset->holeOf == NULL ) + { + (( Feature* ) pset )->fetchCoordinates(); + } + else + { + (( Feature* ) pset->holeOf )->fetchCoordinates(); + } - amin[0] = pset->xmin; - amin[1] = pset->ymin; - amax[0] = pset->xmax; - amax[1] = pset->ymax; + double amin[2], amax[2]; - PruneCtx pruneContext; + amin[0] = pset->xmin; + amin[1] = pset->ymin; + amax[0] = pset->xmax; + amax[1] = pset->ymax; - pruneContext.scale = scale; - pruneContext.obstacle = pset; - pruneContext.pal = pal; - cdtsIndex->Search (amin, amax, pruneLabelPositionCallback, (void*) &pruneContext); + PruneCtx pruneContext; - if (pset->holeOf == NULL) { - ( (Feature*) pset)->releaseCoordinates(); - } else { - ( (Feature*) pset->holeOf)->releaseCoordinates(); - } + pruneContext.scale = scale; + pruneContext.obstacle = pset; + pruneContext.pal = pal; + cdtsIndex->Search( amin, amax, pruneLabelPositionCallback, ( void* ) &pruneContext ); - return true; + if ( pset->holeOf == NULL ) + { + (( Feature* ) pset )->releaseCoordinates(); + } + else + { + (( Feature* ) pset->holeOf )->releaseCoordinates(); } + return true; + } - /** - * \Brief Problem Factory - * Select features from user's choice layers within - * a specific bounding box - * param nbLayers # wanted layers - * param layersFactor layers importance - * param layersName layers in problem - * param lambda_min west bbox - * param phi_min south bbox - * param lambda_max east bbox - * param phi_max north bbox - * param scale the scale - */ - Problem* Pal::extract (int nbLayers, char **layersName, double *layersFactor, double lambda_min, double phi_min, double lambda_max, double phi_max, double scale, std::ofstream *svgmap) { - // to store obstacles - RTree *obstacles = new RTree(); - Problem *prob = new Problem(); + /** + * \Brief Problem Factory + * Select features from user's choice layers within + * a specific bounding box + * param nbLayers # wanted layers + * param layersFactor layers importance + * param layersName layers in problem + * param lambda_min west bbox + * param phi_min south bbox + * param lambda_max east bbox + * param phi_max north bbox + * param scale the scale + */ + Problem* Pal::extract( int nbLayers, char **layersName, double *layersFactor, double lambda_min, double phi_min, double lambda_max, double phi_max, double scale, std::ofstream *svgmap ) + { + // to store obstacles + RTree *obstacles = new RTree(); + + Problem *prob = new Problem(); - int i, j, c; + int i, j, c; - double bbx[4]; - double bby[4]; + double bbx[4]; + double bby[4]; - double amin[2]; - double amax[2]; + double amin[2]; + double amax[2]; - int max_p = 0; + int max_p = 0; - LabelPosition* lp; + LabelPosition* lp; - bbx[0] = bbx[3] = amin[0] = prob->bbox[0] = lambda_min; - bby[0] = bby[1] = amin[1] = prob->bbox[1] = phi_min; - bbx[1] = bbx[2] = amax[0] = prob->bbox[2] = lambda_max; - bby[2] = bby[3] = amax[1] = prob->bbox[3] = phi_max; + bbx[0] = bbx[3] = amin[0] = prob->bbox[0] = lambda_min; + bby[0] = bby[1] = amin[1] = prob->bbox[1] = phi_min; + bbx[1] = bbx[2] = amax[0] = prob->bbox[2] = lambda_max; + bby[2] = bby[3] = amax[1] = prob->bbox[3] = phi_max; - prob->scale = scale; - prob->pal = this; + prob->scale = scale; + prob->pal = this; - LinkedList *fFeats = new LinkedList (ptrFeatsCompare); + LinkedList *fFeats = new LinkedList ( ptrFeatsCompare ); - FeatCallBackCtx *context = new FeatCallBackCtx(); - context->fFeats = fFeats; - context->scale = scale; - context->obstacles = obstacles; - context->candidates = prob->candidates; + FeatCallBackCtx *context = new FeatCallBackCtx(); + context->fFeats = fFeats; + context->scale = scale; + context->obstacles = obstacles; + context->candidates = prob->candidates; - context->bbox_min[0] = amin[0]; - context->bbox_min[1] = amin[1]; + context->bbox_min[0] = amin[0]; + context->bbox_min[1] = amin[1]; - context->bbox_max[0] = amax[0]; - context->bbox_max[1] = amax[1]; + context->bbox_max[0] = amax[0]; + context->bbox_max[1] = amax[1]; #ifdef _EXPORT_MAP_ - context->svgmap = svgmap; + context->svgmap = svgmap; #endif #ifdef _VERBOSE_ - std::cout << nbLayers << "/" << layers->size() << " layers to extract " << std::endl; - std::cout << "scale is 1:" << scale << std::endl << std::endl; + std::cout << nbLayers << "/" << layers->size() << " layers to extract " << std::endl; + std::cout << "scale is 1:" << scale << std::endl << std::endl; #endif - /* First step : extract feature from layers - * - * */ - int oldNbft = 0; - Layer *layer; - - std::list *labLayers = new std::list(); - - lyrsMutex->lock(); - for (i = 0;i < nbLayers;i++) { - for (std::list::iterator it = layers->begin(); it != layers->end();it++) { // iterate on pal->layers - layer = *it; - // Only select those who are active and labellable (with scale constraint) or those who are active and which must be treated as obstaclewhich must be treated as obstacle - if (layer->active - && (layer->obstacle || (layer->toLabel && layer->isScaleValid (scale)))) { - - // check if this selected layers has been selected by user - if (strcmp (layersName[i], layer->name) == 0) { - context->layer = layer; - context->priority = layersFactor[i]; - // lookup for feature (and generates candidates list) + /* First step : extract feature from layers + * + * */ + int oldNbft = 0; + Layer *layer; + + std::list *labLayers = new std::list(); + + lyrsMutex->lock(); + for ( i = 0;i < nbLayers;i++ ) + { + for ( std::list::iterator it = layers->begin(); it != layers->end();it++ ) // iterate on pal->layers + { + layer = *it; + // Only select those who are active and labellable (with scale constraint) or those who are active and which must be treated as obstaclewhich must be treated as obstacle + if ( layer->active + && ( layer->obstacle || ( layer->toLabel && layer->isScaleValid( scale ) ) ) ) + { + + // check if this selected layers has been selected by user + if ( strcmp( layersName[i], layer->name ) == 0 ) + { + context->layer = layer; + context->priority = layersFactor[i]; + // lookup for feature (and generates candidates list) #ifdef _EXPORT_MAP_ - *svgmap << "name << "\"" << std::endl - << " inkscape:groupmode=\"layer\"" << std::endl - << " id=\"" << layer->name << "\">" << std::endl << std::endl; + *svgmap << "name << "\"" << std::endl + << " inkscape:groupmode=\"layer\"" << std::endl + << " id=\"" << layer->name << "\">" << std::endl << std::endl; #endif - context->layer->modMutex->lock(); - context->layer->rtree->Search (amin, amax, extractFeatCallback, (void*) context); - context->layer->modMutex->unlock(); + context->layer->modMutex->lock(); + context->layer->rtree->Search( amin, amax, extractFeatCallback, ( void* ) context ); + context->layer->modMutex->unlock(); #ifdef _EXPORT_MAP_ - *svgmap << "" << std::endl << std::endl; + *svgmap << "" << std::endl << std::endl; #endif #ifdef _VERBOSE_ - std::cout << "Layer's name: " << layer->getName() << std::endl; - std::cout << " scale range: " << layer->getMinScale() << "->" << layer->getMaxScale() << std::endl; - std::cout << " active:" << layer->isToLabel() << std::endl; - std::cout << " obstacle:" << layer->isObstacle() << std::endl; - std::cout << " toLabel:" << layer->isToLabel() << std::endl; - std::cout << " # features: " << layer->getNbFeatures() << std::endl; - std::cout << " # extracted features: " << context->fFeats->size() - oldNbft << std::endl; + std::cout << "Layer's name: " << layer->getName() << std::endl; + std::cout << " scale range: " << layer->getMinScale() << "->" << layer->getMaxScale() << std::endl; + std::cout << " active:" << layer->isToLabel() << std::endl; + std::cout << " obstacle:" << layer->isObstacle() << std::endl; + std::cout << " toLabel:" << layer->isToLabel() << std::endl; + std::cout << " # features: " << layer->getNbFeatures() << std::endl; + std::cout << " # extracted features: " << context->fFeats->size() - oldNbft << std::endl; #endif - if (context->fFeats->size() - oldNbft > 0) { - char *name = new char[strlen (layer->getName()) +1]; - strcpy (name, layer->getName()); - labLayers->push_back (name); - } - oldNbft = context->fFeats->size(); + if ( context->fFeats->size() - oldNbft > 0 ) + { + char *name = new char[strlen( layer->getName() ) +1]; + strcpy( name, layer->getName() ); + labLayers->push_back( name ); + } + oldNbft = context->fFeats->size(); - break; - } - } - } + break; + } } - delete context; - lyrsMutex->unlock(); + } + } + delete context; + lyrsMutex->unlock(); - prob->nbLabelledLayers = labLayers->size(); - prob->labelledLayersName = new char*[prob->nbLabelledLayers]; - for (i = 0;i < prob->nbLabelledLayers;i++) { - prob->labelledLayersName[i] = labLayers->front(); - labLayers->pop_front(); - } + prob->nbLabelledLayers = labLayers->size(); + prob->labelledLayersName = new char*[prob->nbLabelledLayers]; + for ( i = 0;i < prob->nbLabelledLayers;i++ ) + { + prob->labelledLayersName[i] = labLayers->front(); + labLayers->pop_front(); + } - delete labLayers; + delete labLayers; - if (fFeats->size() == 0) { + if ( fFeats->size() == 0 ) + { #ifdef _VERBOSE_ - std::cout << std::endl << "Empty problem" << std::endl; + std::cout << std::endl << "Empty problem" << std::endl; #endif - delete fFeats; - delete prob; - releaseAllInIndex (obstacles); - delete obstacles; - return NULL; - } + delete fFeats; + delete prob; + releaseAllInIndex( obstacles ); + delete obstacles; + return NULL; + } - prob->nbft = fFeats->size(); - prob->nblp = 0; - prob->featNbLp = new int [prob->nbft]; - prob->featStartId = new int [prob->nbft]; - prob->inactiveCost = new double[prob->nbft]; + prob->nbft = fFeats->size(); + prob->nblp = 0; + prob->featNbLp = new int [prob->nbft]; + prob->featStartId = new int [prob->nbft]; + prob->inactiveCost = new double[prob->nbft]; - Feats *feat; + Feats *feat; - std::cout << "FIRSST NBFT : " << prob->nbft << std::endl; + std::cout << "FIRSST NBFT : " << prob->nbft << std::endl; - // Filtering label positions against obstacles - amin[0] = amin[1] = -DBL_MAX; - amax[0] = amax[1] = DBL_MAX; - FilterContext filterCtx; - filterCtx.cdtsIndex = prob->candidates; - filterCtx.scale = prob->scale; - filterCtx.pal = this; - obstacles->Search (amin, amax, filteringCallback, (void*) &filterCtx); + // Filtering label positions against obstacles + amin[0] = amin[1] = -DBL_MAX; + amax[0] = amax[1] = DBL_MAX; + FilterContext filterCtx; + filterCtx.cdtsIndex = prob->candidates; + filterCtx.scale = prob->scale; + filterCtx.pal = this; + obstacles->Search( amin, amax, filteringCallback, ( void* ) &filterCtx ); - int idlp = 0; - for (i = 0;i < prob->nbft;i++) { /* foreach feature into prob */ - feat = fFeats->pop_front(); + int idlp = 0; + for ( i = 0;i < prob->nbft;i++ ) /* foreach feature into prob */ + { + feat = fFeats->pop_front(); #ifdef _DEBUG_FULL_ - std::cout << "Feature:" << feat->feature->layer->name << "/" << feat->feature->uid << std::endl; + std::cout << "Feature:" << feat->feature->layer->name << "/" << feat->feature->uid << std::endl; #endif - prob->featStartId[i] = idlp; - prob->inactiveCost[i] = pow (2, 10 - 10 * feat->priority); - - switch (feat->feature->type) { - case GEOS_POINT: - max_p = point_p; - break; - case GEOS_LINESTRING: - max_p = line_p; - break; - case GEOS_POLYGON: - max_p = poly_p; - break; - } - - // If candidates list is smaller than expected - if (max_p > feat->nblp) - max_p = feat->nblp; - // - // sort candidates list, best label to worst - sort ( (void**) feat->lPos, feat->nblp, costGrow); - - // try to exclude all conflitual labels (good ones have cost < 1 by pruning) - double discrim = 0.0; - int stop; - do { - discrim += 1.0; - for (stop = 0;stop < feat->nblp && feat->lPos[stop]->cost < discrim;stop++); - } while (stop == 0 && discrim < feat->lPos[feat->nblp-1]->cost + 2.0); - - if (discrim > 1.5) { - int k; - for (k = 0;k < stop;k++) - feat->lPos[k]->cost = 0.0021; - } + prob->featStartId[i] = idlp; + prob->inactiveCost[i] = pow( 2, 10 - 10 * feat->priority ); - if (max_p > stop) - max_p = stop; + switch ( feat->feature->type ) + { + case GEOS_POINT: + max_p = point_p; + break; + case GEOS_LINESTRING: + max_p = line_p; + break; + case GEOS_POLYGON: + max_p = poly_p; + break; + } + + // If candidates list is smaller than expected + if ( max_p > feat->nblp ) + max_p = feat->nblp; + // + // sort candidates list, best label to worst + sort(( void** ) feat->lPos, feat->nblp, costGrow ); + + // try to exclude all conflitual labels (good ones have cost < 1 by pruning) + double discrim = 0.0; + int stop; + do + { + discrim += 1.0; + for ( stop = 0;stop < feat->nblp && feat->lPos[stop]->cost < discrim;stop++ ); + } + while ( stop == 0 && discrim < feat->lPos[feat->nblp-1]->cost + 2.0 ); + + if ( discrim > 1.5 ) + { + int k; + for ( k = 0;k < stop;k++ ) + feat->lPos[k]->cost = 0.0021; + } + + if ( max_p > stop ) + max_p = stop; #ifdef _DEBUG_FULL_ - std::cout << "Nblabel kept for feat " << feat->feature->uid << "/" << feat->feature->layer->name << ": " << max_p << "/" << feat->nblp << std::endl; + std::cout << "Nblabel kept for feat " << feat->feature->uid << "/" << feat->feature->layer->name << ": " << max_p << "/" << feat->nblp << std::endl; #endif - // Sets costs for candidates of polygon - if (feat->feature->type == GEOS_POLYGON && (feat->feature->layer->arrangement == P_FREE || feat->feature->layer->arrangement == P_HORIZ)) - LabelPosition::setCost (stop, feat->lPos, max_p, obstacles, bbx, bby); + // Sets costs for candidates of polygon + if ( feat->feature->type == GEOS_POLYGON && ( feat->feature->layer->arrangement == P_FREE || feat->feature->layer->arrangement == P_HORIZ ) ) + LabelPosition::setCost( stop, feat->lPos, max_p, obstacles, bbx, bby ); #ifdef _DEBUG_FULL_ - std::cout << "All Cost are setted" << std::endl; + std::cout << "All Cost are setted" << std::endl; #endif - // only keep the 'max_p' best candidates - for (j = max_p;j < feat->nblp;j++) { - // TODO remove from index - feat->lPos[j]->removeFromIndex (prob->candidates); - delete feat->lPos[j]; - } - feat->nblp = max_p; - - // update problem's # candidate - prob->featNbLp[i] = feat->nblp; - prob->nblp += feat->nblp; - - // add all candidates into a rtree (to speed up conflicts searching) - for (j = 0;j < feat->nblp;j++, idlp++) { - lp = feat->lPos[j]; - //lp->insertIntoIndex(prob->candidates); - lp->id = idlp; - lp->probFeat = i; // bugfix #1 (maxence 10/23/2008) - } - fFeats->push_back (feat); - } + // only keep the 'max_p' best candidates + for ( j = max_p;j < feat->nblp;j++ ) + { + // TODO remove from index + feat->lPos[j]->removeFromIndex( prob->candidates ); + delete feat->lPos[j]; + } + feat->nblp = max_p; + + // update problem's # candidate + prob->featNbLp[i] = feat->nblp; + prob->nblp += feat->nblp; + + // add all candidates into a rtree (to speed up conflicts searching) + for ( j = 0;j < feat->nblp;j++, idlp++ ) + { + lp = feat->lPos[j]; + //lp->insertIntoIndex(prob->candidates); + lp->id = idlp; + lp->probFeat = i; // bugfix #1 (maxence 10/23/2008) + } + fFeats->push_back( feat ); + } #ifdef _DEBUG_FULL_ - std::cout << "Malloc problem...." << std::endl; + std::cout << "Malloc problem...." << std::endl; #endif - idlp = 0; - int nbOverlaps = 0; - prob->labelpositions = new LabelPosition*[prob->nblp]; - //prob->feat = new int[prob->nblp]; + idlp = 0; + int nbOverlaps = 0; + prob->labelpositions = new LabelPosition*[prob->nblp]; + //prob->feat = new int[prob->nblp]; #ifdef _DEBUG_FULL_ - std::cout << "problem malloc'd" << std::endl; + std::cout << "problem malloc'd" << std::endl; #endif - j = 0; - while (fFeats->size() > 0) { // foreach feature - feat = fFeats->pop_front(); - for (i = 0;i < feat->nblp;i++, idlp++) { // foreach label candidate - lp = feat->lPos[i]; - lp->nbOverlap = 0; - - if (lp->cost >= 1) { - std::cout << " Warning: lp->cost == " << lp->cost << " (from feat: " << lp->feature->uid << "/" << lp->feature->layer->name << ")" << std::endl; - lp->cost -= int (lp->cost); // label cost up to 1 - } - - prob->labelpositions[idlp] = lp; - //prob->feat[idlp] = j; - - - amin[0] = DBL_MAX; - amax[0] = -DBL_MAX; - amin[1] = DBL_MAX; - amax[1] = -DBL_MAX; - for (c = 0;c < 4;c++) { - if (lp->x[c] < amin[0]) - amin[0] = lp->x[c]; - if (lp->x[c] > amax[0]) - amax[0] = lp->x[c]; - if (lp->y[c] < amin[1]) - amin[1] = lp->y[c]; - if (lp->y[c] > amax[1]) - amax[1] = lp->y[c]; - } - // lookup for overlapping candidate - prob->candidates->Search (amin, amax, countOverlapCallback, (void*) lp); - - nbOverlaps += lp->nbOverlap; + j = 0; + while ( fFeats->size() > 0 ) // foreach feature + { + feat = fFeats->pop_front(); + for ( i = 0;i < feat->nblp;i++, idlp++ ) // foreach label candidate + { + lp = feat->lPos[i]; + lp->nbOverlap = 0; + + if ( lp->cost >= 1 ) + { + std::cout << " Warning: lp->cost == " << lp->cost << " (from feat: " << lp->feature->uid << "/" << lp->feature->layer->name << ")" << std::endl; + lp->cost -= int ( lp->cost ); // label cost up to 1 + } + + prob->labelpositions[idlp] = lp; + //prob->feat[idlp] = j; + + + amin[0] = DBL_MAX; + amax[0] = -DBL_MAX; + amin[1] = DBL_MAX; + amax[1] = -DBL_MAX; + for ( c = 0;c < 4;c++ ) + { + if ( lp->x[c] < amin[0] ) + amin[0] = lp->x[c]; + if ( lp->x[c] > amax[0] ) + amax[0] = lp->x[c]; + if ( lp->y[c] < amin[1] ) + amin[1] = lp->y[c]; + if ( lp->y[c] > amax[1] ) + amax[1] = lp->y[c]; + } + // lookup for overlapping candidate + prob->candidates->Search( amin, amax, countOverlapCallback, ( void* ) lp ); + + nbOverlaps += lp->nbOverlap; #ifdef _DEBUG_FULL_ - std::cout << "Nb overlap for " << idlp << "/" << prob->nblp - 1 << " : " << lp->nbOverlap << std::endl; + std::cout << "Nb overlap for " << idlp << "/" << prob->nblp - 1 << " : " << lp->nbOverlap << std::endl; #endif - } - j++; - delete[] feat->lPos; - delete feat; - } - delete fFeats; + } + j++; + delete[] feat->lPos; + delete feat; + } + delete fFeats; - //delete candidates; - releaseAllInIndex (obstacles); - delete obstacles; + //delete candidates; + releaseAllInIndex( obstacles ); + delete obstacles; - nbOverlaps /= 2; - prob->all_nblp = prob->nblp; - prob->nbOverlap = nbOverlaps; + nbOverlaps /= 2; + prob->all_nblp = prob->nblp; + prob->nbOverlap = nbOverlaps; #ifdef _VERBOSE_ - std::cout << "nbOverlap: " << prob->nbOverlap << std::endl; - std::cerr << scale << "\t" - << prob->nbft << "\t" - << prob->nblp << "\t" - << prob->nbOverlap << "\t"; + std::cout << "nbOverlap: " << prob->nbOverlap << std::endl; + std::cerr << scale << "\t" + << prob->nbft << "\t" + << prob->nblp << "\t" + << prob->nbOverlap << "\t"; #endif - prob->reduce(); + prob->reduce(); #ifdef _VERBOSE_ - std::cerr << prob->nblp << "\t" - << prob->nbOverlap; + std::cerr << prob->nblp << "\t" + << prob->nbOverlap; #endif - return prob; - } + return prob; + } - std::list* Pal::labeller (double scale, double bbox[4], PalStat **stats, bool displayAll) { + std::list* Pal::labeller( double scale, double bbox[4], PalStat **stats, bool displayAll ) + { #ifdef _DEBUG_FULL_ - std::cout << "LABELLER (active)" << std::endl; + std::cout << "LABELLER (active)" << std::endl; #endif - int i; - - lyrsMutex->lock(); - int nbLayers = layers->size(); - - char **layersName = new char*[nbLayers]; - double *priorities = new double[nbLayers]; - Layer *layer; - i = 0; - for (std::list::iterator it = layers->begin(); it != layers->end();it++) { - layer = *it; - layersName[i] = layer->name; - priorities[i] = layer->defaultPriority; - i++; - } - lyrsMutex->unlock(); + int i; + + lyrsMutex->lock(); + int nbLayers = layers->size(); + + char **layersName = new char*[nbLayers]; + double *priorities = new double[nbLayers]; + Layer *layer; + i = 0; + for ( std::list::iterator it = layers->begin(); it != layers->end();it++ ) + { + layer = *it; + layersName[i] = layer->name; + priorities[i] = layer->defaultPriority; + i++; + } + lyrsMutex->unlock(); - std::list * solution = labeller (nbLayers, layersName, priorities, scale, bbox, stats, displayAll); + std::list * solution = labeller( nbLayers, layersName, priorities, scale, bbox, stats, displayAll ); - delete[] layersName; - delete[] priorities; - return solution; - } + delete[] layersName; + delete[] priorities; + return solution; + } - /* - * BIG MACHINE - */ - std::list* Pal::labeller (int nbLayers, char **layersName , double *layersFactor, double scale, double bbox[4], PalStat **stats, bool displayAll) { + /* + * BIG MACHINE + */ + std::list* Pal::labeller( int nbLayers, char **layersName , double *layersFactor, double scale, double bbox[4], PalStat **stats, bool displayAll ) + { #ifdef _DEBUG_ - std::cout << "LABELLER (selection)" << std::endl; + std::cout << "LABELLER (selection)" << std::endl; #endif - Problem *prob; + Problem *prob; - SearchMethod old_searchMethod = searchMethod; + SearchMethod old_searchMethod = searchMethod; - if (displayAll) { - setSearch (POPMUSIC_TABU); - } + if ( displayAll ) + { + setSearch( POPMUSIC_TABU ); + } #ifdef _VERBOSE_ - clock_t start = clock(); - double create_time; - std::cout << std::endl << "bbox: " << bbox[0] << " " << bbox[1] << " " << bbox[2] << " " << bbox[3] << std::endl; + clock_t start = clock(); + double create_time; + std::cout << std::endl << "bbox: " << bbox[0] << " " << bbox[1] << " " << bbox[2] << " " << bbox[3] << std::endl; #endif #ifdef _EXPORT_MAP_ - // TODO this is not secure - std::ofstream svgmap ("pal-map.svg"); - - svgmap << "" << std::endl - << "" << std::endl; // TODO xmax ymax + // TODO this is not secure + std::ofstream svgmap( "pal-map.svg" ); + + svgmap << "" << std::endl + << "" << std::endl; // TODO xmax ymax #endif - // First, extract the problem - // TODO which is the minimum scale ? (> 0, >= 0, >= 1, >1 ) - if (scale < 1 || (prob = extract (nbLayers, layersName, layersFactor, bbox[0], bbox[1], bbox[2], bbox[3], scale, + // First, extract the problem + // TODO which is the minimum scale ? (> 0, >= 0, >= 1, >1 ) + if ( scale < 1 || ( prob = extract( nbLayers, layersName, layersFactor, bbox[0], bbox[1], bbox[2], bbox[3], scale, #ifdef _EXPORT_MAP_ - & svgmap + & svgmap #else - NULL + NULL #endif - )) == NULL) { + ) ) == NULL ) + { #ifdef _VERBOSE_ - if (scale < 1) - std::cout << "Scale is 1:" << scale << std::endl; - else - std::cout << "empty problem... finishing" << std::endl; + if ( scale < 1 ) + std::cout << "Scale is 1:" << scale << std::endl; + else + std::cout << "empty problem... finishing" << std::endl; #endif #ifdef _EXPORT_MAP_ - svgmap << "" << std::endl; - svgmap.close(); + svgmap << "" << std::endl; + svgmap.close(); #endif - // nothing to be done => return an empty result set - if (stats) - (*stats) = new PalStat(); - return new std::list(); - } + // nothing to be done => return an empty result set + if ( stats ) + ( *stats ) = new PalStat(); + return new std::list(); + } - prob->displayAll = displayAll; + prob->displayAll = displayAll; #ifdef _VERBOSE_ - create_time = double (clock() - start) / double (CLOCKS_PER_SEC); + create_time = double( clock() - start ) / double( CLOCKS_PER_SEC ); - std::cout << std::endl << "Problem : " << prob->nblp << " candidates for " << prob->nbft << " features makes " << prob->nbOverlap << " overlaps" << std::endl; - std::cout << std::endl << "Times:" << std::endl << " to create problem: " << create_time << std::endl; + std::cout << std::endl << "Problem : " << prob->nblp << " candidates for " << prob->nbft << " features makes " << prob->nbOverlap << " overlaps" << std::endl; + std::cout << std::endl << "Times:" << std::endl << " to create problem: " << create_time << std::endl; #endif - // search a solution - if (searchMethod != CHAIN) - prob->popmusic(); - else - prob->chain_search(); + // search a solution + if ( searchMethod != CHAIN ) + prob->popmusic(); + else + prob->chain_search(); - // Post-Optimization - //prob->post_optimization(); + // Post-Optimization + //prob->post_optimization(); - std::list * solution = prob->getSolution (displayAll); + std::list * solution = prob->getSolution( displayAll ); - if (stats) - *stats = prob->getStats(); + if ( stats ) + *stats = prob->getStats(); #ifdef _EXPORT_MAP_ - prob->drawLabels (svgmap); - svgmap << "" << std::endl; - svgmap.close(); + prob->drawLabels( svgmap ); + svgmap << "" << std::endl; + svgmap.close(); #endif #ifdef _VERBOSE_ - clock_t total_time = clock() - start; - std::cout << " Total time: " << double (total_time) / double (CLOCKS_PER_SEC) << std::endl; - std::cerr << "\t" << create_time << "\t" << double (total_time) / double (CLOCKS_PER_SEC) << std::endl; + clock_t total_time = clock() - start; + std::cout << " Total time: " << double( total_time ) / double( CLOCKS_PER_SEC ) << std::endl; + std::cerr << "\t" << create_time << "\t" << double( total_time ) / double( CLOCKS_PER_SEC ) << std::endl; #endif - delete prob; + delete prob; - if (displayAll) { - setSearch (old_searchMethod); - } - - return solution; + if ( displayAll ) + { + setSearch( old_searchMethod ); } - void Pal::setPointP (int point_p) { - if (point_p > 0) - this->point_p = point_p; - } - - void Pal::setLineP (int line_p) { - if (line_p > 0) - this->line_p = line_p; - } - - void Pal::setPolyP (int poly_p) { - if (poly_p > 0) - this->poly_p = poly_p; - } - - - void Pal::setMinIt (int min_it) { - if (min_it >= 0) - tabuMinIt = min_it; - } - - void Pal::setMaxIt (int max_it) { - if (max_it > 0) - tabuMaxIt = max_it; - } - - void Pal::setPopmusicR (int r) { - if (r > 0) - popmusic_r = r; - } - - void Pal::setEjChainDeg (int degree) { - this->ejChainDeg = degree; - } - - void Pal::setTenure (int tenure) { - this->tenure = tenure; - } - - void Pal::setCandListSize (double fact) { - this->candListSize = fact; - } - - - void Pal::setDpi (int dpi) { - if (dpi > 0) - this->dpi = dpi; - } - - int Pal::getPointP () { - return point_p; - } - - int Pal::getLineP () { - return line_p; - } - - int Pal::getPolyP () { - return poly_p; - } - - int Pal::getMinIt () { - return tabuMaxIt; - } - - int Pal::getMaxIt () { - return tabuMinIt; - } - - int Pal::getDpi () { - return dpi; - } - - SearchMethod Pal::getSearch() { - return searchMethod; - } - - void Pal::setSearch (SearchMethod method) { - switch (method) { - case POPMUSIC_CHAIN: - searchMethod = method; - popmusic_r = 30; - tabuMinIt = 2; - tabuMaxIt = 4; - tenure = 10; - ejChainDeg = 50; - candListSize = 0.2; - break; - case CHAIN: - searchMethod = method; - ejChainDeg = 50; - break; - case POPMUSIC_TABU: - searchMethod = method; - popmusic_r = 25; - tabuMinIt = 2; - tabuMaxIt = 4; - tenure = 10; - ejChainDeg = 50; - candListSize = 0.2; - break; - case POPMUSIC_TABU_CHAIN: - searchMethod = method; - popmusic_r = 25; - tabuMinIt = 2; - tabuMaxIt = 4; - tenure = 10; - ejChainDeg = 50; - candListSize = 0.2; - break; - default: - std::cerr << "Unknown search method..." << std::endl; - } - } - - - /** - * \brief get current map unit - */ - Units Pal::getMapUnit(){ - return map_unit; + return solution; + } + + void Pal::setPointP( int point_p ) + { + if ( point_p > 0 ) + this->point_p = point_p; + } + + void Pal::setLineP( int line_p ) + { + if ( line_p > 0 ) + this->line_p = line_p; + } + + void Pal::setPolyP( int poly_p ) + { + if ( poly_p > 0 ) + this->poly_p = poly_p; + } + + + void Pal::setMinIt( int min_it ) + { + if ( min_it >= 0 ) + tabuMinIt = min_it; + } + + void Pal::setMaxIt( int max_it ) + { + if ( max_it > 0 ) + tabuMaxIt = max_it; + } + + void Pal::setPopmusicR( int r ) + { + if ( r > 0 ) + popmusic_r = r; + } + + void Pal::setEjChainDeg( int degree ) + { + this->ejChainDeg = degree; + } + + void Pal::setTenure( int tenure ) + { + this->tenure = tenure; + } + + void Pal::setCandListSize( double fact ) + { + this->candListSize = fact; + } + + + void Pal::setDpi( int dpi ) + { + if ( dpi > 0 ) + this->dpi = dpi; + } + + int Pal::getPointP() + { + return point_p; + } + + int Pal::getLineP() + { + return line_p; + } + + int Pal::getPolyP() + { + return poly_p; + } + + int Pal::getMinIt() + { + return tabuMaxIt; + } + + int Pal::getMaxIt() + { + return tabuMinIt; + } + + int Pal::getDpi() + { + return dpi; + } + + SearchMethod Pal::getSearch() + { + return searchMethod; + } + + void Pal::setSearch( SearchMethod method ) + { + switch ( method ) + { + case POPMUSIC_CHAIN: + searchMethod = method; + popmusic_r = 30; + tabuMinIt = 2; + tabuMaxIt = 4; + tenure = 10; + ejChainDeg = 50; + candListSize = 0.2; + break; + case CHAIN: + searchMethod = method; + ejChainDeg = 50; + break; + case POPMUSIC_TABU: + searchMethod = method; + popmusic_r = 25; + tabuMinIt = 2; + tabuMaxIt = 4; + tenure = 10; + ejChainDeg = 50; + candListSize = 0.2; + break; + case POPMUSIC_TABU_CHAIN: + searchMethod = method; + popmusic_r = 25; + tabuMinIt = 2; + tabuMaxIt = 4; + tenure = 10; + ejChainDeg = 50; + candListSize = 0.2; + break; + default: + std::cerr << "Unknown search method..." << std::endl; } - - /** - * \brief set map unit - */ - void Pal::setMapUnit(Units map_unit){ - if (map_unit == pal::PIXEL || map_unit == pal::METER - || map_unit == pal::FOOT || map_unit == pal::DEGREE){ - this->map_unit = map_unit; - } + } + + + /** + * \brief get current map unit + */ + Units Pal::getMapUnit() + { + return map_unit; + } + + /** + * \brief set map unit + */ + void Pal::setMapUnit( Units map_unit ) + { + if ( map_unit == pal::PIXEL || map_unit == pal::METER + || map_unit == pal::FOOT || map_unit == pal::DEGREE ) + { + this->map_unit = map_unit; } + } diff --git a/src/core/pal/pal.h b/src/core/pal/pal.h index dc9da161945f..9bdaae9e19d1 100644 --- a/src/core/pal/pal.h +++ b/src/core/pal/pal.h @@ -55,357 +55,362 @@ * */ -namespace pal { - - template class LinkedList; - - class Layer; - class LabelPosition; - class Problem; - class PointSet; - class SimpleMutex; - - /** Units for label sizes and distlabel */ - enum _Units { - PIXEL = 0, /**< pixel [px]*/ - METER, /**< meter [m]*/ - FOOT, /**< foot [ft]*/ - DEGREE /**< degree [°] */ - }; - - /** Typedef for _Units enumeration */ - typedef enum _Units Units; - - /** Search method to use */ - enum _searchMethod { - CHAIN = 0, /**< is the worst but fastest method */ - POPMUSIC_TABU_CHAIN = 1, /**< is the best but slowest */ - POPMUSIC_TABU = 2, /**< is a little bit better than CHAIN but slower*/ - POPMUSIC_CHAIN = 3 /**< is slower and best than TABU, worse and faster than TABU_CHAIN */ - }; - - /** Typedef for _Units enumeration */ - typedef enum _searchMethod SearchMethod; - - /** The way to arrange labels against spatial entities - * - * \image html arrangement.png "Arrangement modes" width=7cm - * */ - enum _arrangement { - P_POINT = 0, /**< arranges candidates around a point (centroid for polygon)*/ - P_LINE, /**< Only for lines and polygons, arranges candidates over the line or the polygon perimeter */ - P_HORIZ, /**< Only for polygon, arranges candidates horizontaly */ - P_FREE, /**< Only for polygon, arranges candidates with respect of polygon orientation */ - P_LINE_AROUND /**< Only for lines and polygons, arranges candidates above and below the line or the polygon perimeter */ - }; - - /** typedef for _arrangement enumeration */ - typedef enum _arrangement Arrangement; - - - /** - * \brief Pal main class. - * - * A pal object will contains layers and global informations such as which search method - * will be used, the map resolution (dpi) .... - * - * \author Maxence Laurent - */ - class Pal { - friend class Problem; - friend class Feature; - friend class Layer; - friend class LabelPosition; - friend class PointSet; - friend bool pruneLabelPositionCallback (LabelPosition *lp, void *ctx); +namespace pal +{ + + template class LinkedList; + + class Layer; + class LabelPosition; + class Problem; + class PointSet; + class SimpleMutex; + + /** Units for label sizes and distlabel */ + enum _Units + { + PIXEL = 0, /**< pixel [px]*/ + METER, /**< meter [m]*/ + FOOT, /**< foot [ft]*/ + DEGREE /**< degree [°] */ + }; + + /** Typedef for _Units enumeration */ + typedef enum _Units Units; + + /** Search method to use */ + enum _searchMethod + { + CHAIN = 0, /**< is the worst but fastest method */ + POPMUSIC_TABU_CHAIN = 1, /**< is the best but slowest */ + POPMUSIC_TABU = 2, /**< is a little bit better than CHAIN but slower*/ + POPMUSIC_CHAIN = 3 /**< is slower and best than TABU, worse and faster than TABU_CHAIN */ + }; + + /** Typedef for _Units enumeration */ + typedef enum _searchMethod SearchMethod; + + /** The way to arrange labels against spatial entities + * + * \image html arrangement.png "Arrangement modes" width=7cm + * */ + enum _arrangement + { + P_POINT = 0, /**< arranges candidates around a point (centroid for polygon)*/ + P_LINE, /**< Only for lines and polygons, arranges candidates over the line or the polygon perimeter */ + P_HORIZ, /**< Only for polygon, arranges candidates horizontaly */ + P_FREE, /**< Only for polygon, arranges candidates with respect of polygon orientation */ + P_LINE_AROUND /**< Only for lines and polygons, arranges candidates above and below the line or the polygon perimeter */ + }; + + /** typedef for _arrangement enumeration */ + typedef enum _arrangement Arrangement; + + + /** + * \brief Pal main class. + * + * A pal object will contains layers and global informations such as which search method + * will be used, the map resolution (dpi) .... + * + * \author Maxence Laurent + */ + class Pal + { + friend class Problem; + friend class Feature; + friend class Layer; + friend class LabelPosition; + friend class PointSet; + friend bool pruneLabelPositionCallback( LabelPosition *lp, void *ctx ); private: - std::list * layers; - - SimpleMutex *lyrsMutex; - - // TODO remove after tests !!! - clock_t tmpTime; - - Units map_unit; - - /** - * \brief maximum # candidates for a point - */ - int point_p; - - /** - * \brief maximum # candidates for a line - */ - int line_p; - - /** - * \brief maximum # candidates for a polygon - */ - int poly_p; - - SearchMethod searchMethod; - - /* - * POPMUSIC Tuning - */ - int popmusic_r; - - int tabuMaxIt; - int tabuMinIt; - - int dpi; - - int ejChainDeg; - int tenure; - double candListSize; - - /** - * \brief Problem factory - * Extract features to label and generates candidates for them, - * respects to a bounding box and a map scale - * - * @param nbLayers number of layers to extract - * @param layersName layers name to be extracted - * @param layersFactor layer's factor (priority between layers, 0 is the best, 1 the worst) - * @param lambda_min xMin bounding-box - * @param phi_min yMin bounding-box - * @param lambda_max xMax bounding-box - * @param phi_max yMax bounding-box - * @param scale the scale (1:scale) - * @param svgmap stream to wrtie the svg map (need _EXPORT_MAP_ #defined to work) - */ - Problem* extract (int nbLayers, char **layersName, double *layersFactor, - double lambda_min, double phi_min, - double lambda_max, double phi_max, - double scale, std::ofstream *svgmap); - - - /** - * \brief Choose the size of popmusic subpart's - * @param r subpart size - */ - void setPopmusicR (int r); - - - - /** - * \brief minimum # of iteration for search method POPMUSIC_TABU, POPMUSIC_CHAIN and POPMUSIC_TABU_CHAIN - * @param min_it Sub part optimization min # of iteration - */ - void setMinIt (int min_it); - - /** - * \brief maximum \# of iteration for search method POPMUSIC_TABU, POPMUSIC_CHAIN and POPMUSIC_TABU_CHAIN - * @param max_it Sub part optimization max # of iteration - */ - void setMaxIt (int max_it); - - /** - * \brief For tabu search : how many iteration a feature will be tabu - * @param tenure consiser a feature as tabu for tenure iteration after updating feature in solution - */ - void setTenure (int tenure); - - /** - * \brief For *CHAIN, select the max size of a transformation chain - * @param degree maximum soze of a transformation chain - */ - void setEjChainDeg (int degree); - - /** - * \brief How many candidates will be tested by a tabu iteration - * @param fact the ration (0..1) of candidates to test - */ - void setCandListSize (double fact); - - - /** - * \brief Get the minimum # of iteration doing in POPMUSIC_TABU, POPMUSIC_CHAIN and POPMUSIC_TABU_CHAIN - * @return minimum # of iteration - */ - int getMinIt (); - /** - * \brief Get the maximum # of iteration doing in POPMUSIC_TABU, POPMUSIC_CHAIN and POPMUSIC_TABU_CHAIN - * @return maximum # of iteration - */ - int getMaxIt (); + std::list * layers; + + SimpleMutex *lyrsMutex; + + // TODO remove after tests !!! + clock_t tmpTime; + + Units map_unit; + + /** + * \brief maximum # candidates for a point + */ + int point_p; + + /** + * \brief maximum # candidates for a line + */ + int line_p; + + /** + * \brief maximum # candidates for a polygon + */ + int poly_p; + + SearchMethod searchMethod; + + /* + * POPMUSIC Tuning + */ + int popmusic_r; + + int tabuMaxIt; + int tabuMinIt; + + int dpi; + + int ejChainDeg; + int tenure; + double candListSize; + + /** + * \brief Problem factory + * Extract features to label and generates candidates for them, + * respects to a bounding box and a map scale + * + * @param nbLayers number of layers to extract + * @param layersName layers name to be extracted + * @param layersFactor layer's factor (priority between layers, 0 is the best, 1 the worst) + * @param lambda_min xMin bounding-box + * @param phi_min yMin bounding-box + * @param lambda_max xMax bounding-box + * @param phi_max yMax bounding-box + * @param scale the scale (1:scale) + * @param svgmap stream to wrtie the svg map (need _EXPORT_MAP_ #defined to work) + */ + Problem* extract( int nbLayers, char **layersName, double *layersFactor, + double lambda_min, double phi_min, + double lambda_max, double phi_max, + double scale, std::ofstream *svgmap ); + + + /** + * \brief Choose the size of popmusic subpart's + * @param r subpart size + */ + void setPopmusicR( int r ); + + + + /** + * \brief minimum # of iteration for search method POPMUSIC_TABU, POPMUSIC_CHAIN and POPMUSIC_TABU_CHAIN + * @param min_it Sub part optimization min # of iteration + */ + void setMinIt( int min_it ); + + /** + * \brief maximum \# of iteration for search method POPMUSIC_TABU, POPMUSIC_CHAIN and POPMUSIC_TABU_CHAIN + * @param max_it Sub part optimization max # of iteration + */ + void setMaxIt( int max_it ); + + /** + * \brief For tabu search : how many iteration a feature will be tabu + * @param tenure consiser a feature as tabu for tenure iteration after updating feature in solution + */ + void setTenure( int tenure ); + + /** + * \brief For *CHAIN, select the max size of a transformation chain + * @param degree maximum soze of a transformation chain + */ + void setEjChainDeg( int degree ); + + /** + * \brief How many candidates will be tested by a tabu iteration + * @param fact the ration (0..1) of candidates to test + */ + void setCandListSize( double fact ); + + + /** + * \brief Get the minimum # of iteration doing in POPMUSIC_TABU, POPMUSIC_CHAIN and POPMUSIC_TABU_CHAIN + * @return minimum # of iteration + */ + int getMinIt(); + /** + * \brief Get the maximum # of iteration doing in POPMUSIC_TABU, POPMUSIC_CHAIN and POPMUSIC_TABU_CHAIN + * @return maximum # of iteration + */ + int getMaxIt(); public: - /** - * \brief Create an new pal instance - */ - Pal(); - - /** - * \brief delete an instance - */ - ~Pal(); - - /** - * \brief add a new layer - * - * @param lyrName layer's name - * @param min_scale bellow this scale: no labelling (-1 to disable) - * @param max_scale above this scale: no labelling (-1 to disable) - * @param arrangement Howto place candidates - * @param label_unit Unit for labels sizes - * @param defaultPriority layer's prioriry (0 is the best, 1 the worst) - * @param obstacle 'true' will discourage other label to be placed above features of this layer - * @param active is the layer is active (currently displayed) - * @param toLabel the layer will be labeled only if toLablel is true - * - * @throws PalException::LayerExists - * - * @todo add symbolUnit - */ - Layer * addLayer (const char *lyrName, double min_scale, double max_scale, Arrangement arrangement, Units label_unit, double defaultPriority, bool obstacle, bool active, bool toLabel); - - /** - * \brief Look for a layer - * - * @param lyrName name of layer to search - * - * @throws PalException::UnkownLayer - * - * @return a pointer on layer or NULL if layer not exist - */ - Layer *getLayer (const char *lyrName); - - /** - * \brief get all layers - * - * @return a list of all layers - */ - std::list *getLayers (); - - /** - * \brief remove a layer - * - * @param layer layer to remove - */ - void removeLayer (Layer *layer); - - /** - * \brief the labeling machine - * Will extract all active layers - * - * @param scale map scale is 1:scale - * @param bbox map extent - * @param stats A PalStat object (can be NULL) - * @param displayAll if true, all feature will be labelled evan though overlaps occurs - * - * @return A list of label to display on map - */ - std::list *labeller (double scale, double bbox[4], PalStat **stats, bool displayAll); - - - /** - * \brief the labeling machine - * Active layers are specifiend through layersName array - * @todo add obstacles and tolabel arrays - * - * @param nbLayers # layers - * @param layersName names of layers to label - * @param layersFactor layers priorities array - * @param scale map scale is '1:scale' - * @param bbox map extent - * @param stat will be filled with labelling process statistics, can be NULL - * @param displayAll if true, all feature will be labelled evan though overlaps occurs - * - * @todo UnknownLayer will be ignored ? should throw exception or not ??? - * - * @return A list of label to display on map - */ - std::list *labeller (int nbLayers, - char **layersName, - double *layersFactor, - double scale, double bbox[4], - PalStat **stat, - bool displayAll); - - /** - * \brief Set map resolution - * - * @param dpi map resolution (dot per inch) - */ - void setDpi (int dpi); - - /** - * \brief get map resolution - * - * @return map resolution (dot per inch) - */ - int getDpi (); - - - - /** - * \brief set # candidates to generate for points features - * Higher the value is, longer Pal::labeller will spend time - * - * @param point_p # candidates for a point - */ - void setPointP (int point_p); - - /** - * \brief set maximum # candidates to generate for lines features - * Higher the value is, longer Pal::labeller will spend time - * - * @param line_p maximum # candidates for a line - */ - void setLineP (int line_p); - - /** - * \brief set maximum # candidates to generate for polygon features - * Higher the value is, longer Pal::labeller will spend time - * - * @param poly_p maximum # candidate for a polygon - */ - void setPolyP (int poly_p); - - /** - * \brief get # candidates to generate for point features - */ - int getPointP (); - - /** - * \brief get maximum # candidates to generate for line features - */ - int getLineP (); - - /** - * \brief get maximum # candidates to generate for polygon features - */ - int getPolyP (); - - /** - * \brief get current map unit - */ - Units getMapUnit(); - - /** - * \brief set map unit - */ - void setMapUnit(Units map_unit); - - /** - * \brief Select the search method to use. - * - * For interactive mapping using CHAIN is a good - * idea because it is the fastest. Other methods, ordered by speedness, are POPMUSIC_TABU, - * POPMUSIC_CHAIN and POPMUSIC_TABU_CHAIN, defined in pal::_searchMethod enumeration - * @param method the method to use - */ - void setSearch (SearchMethod method); - - /** - * \brief get the search method in use - * - * @return the search method - */ - SearchMethod getSearch(); - }; + /** + * \brief Create an new pal instance + */ + Pal(); + + /** + * \brief delete an instance + */ + ~Pal(); + + /** + * \brief add a new layer + * + * @param lyrName layer's name + * @param min_scale bellow this scale: no labelling (-1 to disable) + * @param max_scale above this scale: no labelling (-1 to disable) + * @param arrangement Howto place candidates + * @param label_unit Unit for labels sizes + * @param defaultPriority layer's prioriry (0 is the best, 1 the worst) + * @param obstacle 'true' will discourage other label to be placed above features of this layer + * @param active is the layer is active (currently displayed) + * @param toLabel the layer will be labeled only if toLablel is true + * + * @throws PalException::LayerExists + * + * @todo add symbolUnit + */ + Layer * addLayer( const char *lyrName, double min_scale, double max_scale, Arrangement arrangement, Units label_unit, double defaultPriority, bool obstacle, bool active, bool toLabel ); + + /** + * \brief Look for a layer + * + * @param lyrName name of layer to search + * + * @throws PalException::UnkownLayer + * + * @return a pointer on layer or NULL if layer not exist + */ + Layer *getLayer( const char *lyrName ); + + /** + * \brief get all layers + * + * @return a list of all layers + */ + std::list *getLayers(); + + /** + * \brief remove a layer + * + * @param layer layer to remove + */ + void removeLayer( Layer *layer ); + + /** + * \brief the labeling machine + * Will extract all active layers + * + * @param scale map scale is 1:scale + * @param bbox map extent + * @param stats A PalStat object (can be NULL) + * @param displayAll if true, all feature will be labelled evan though overlaps occurs + * + * @return A list of label to display on map + */ + std::list *labeller( double scale, double bbox[4], PalStat **stats, bool displayAll ); + + + /** + * \brief the labeling machine + * Active layers are specifiend through layersName array + * @todo add obstacles and tolabel arrays + * + * @param nbLayers # layers + * @param layersName names of layers to label + * @param layersFactor layers priorities array + * @param scale map scale is '1:scale' + * @param bbox map extent + * @param stat will be filled with labelling process statistics, can be NULL + * @param displayAll if true, all feature will be labelled evan though overlaps occurs + * + * @todo UnknownLayer will be ignored ? should throw exception or not ??? + * + * @return A list of label to display on map + */ + std::list *labeller( int nbLayers, + char **layersName, + double *layersFactor, + double scale, double bbox[4], + PalStat **stat, + bool displayAll ); + + /** + * \brief Set map resolution + * + * @param dpi map resolution (dot per inch) + */ + void setDpi( int dpi ); + + /** + * \brief get map resolution + * + * @return map resolution (dot per inch) + */ + int getDpi(); + + + + /** + * \brief set # candidates to generate for points features + * Higher the value is, longer Pal::labeller will spend time + * + * @param point_p # candidates for a point + */ + void setPointP( int point_p ); + + /** + * \brief set maximum # candidates to generate for lines features + * Higher the value is, longer Pal::labeller will spend time + * + * @param line_p maximum # candidates for a line + */ + void setLineP( int line_p ); + + /** + * \brief set maximum # candidates to generate for polygon features + * Higher the value is, longer Pal::labeller will spend time + * + * @param poly_p maximum # candidate for a polygon + */ + void setPolyP( int poly_p ); + + /** + * \brief get # candidates to generate for point features + */ + int getPointP(); + + /** + * \brief get maximum # candidates to generate for line features + */ + int getLineP(); + + /** + * \brief get maximum # candidates to generate for polygon features + */ + int getPolyP(); + + /** + * \brief get current map unit + */ + Units getMapUnit(); + + /** + * \brief set map unit + */ + void setMapUnit( Units map_unit ); + + /** + * \brief Select the search method to use. + * + * For interactive mapping using CHAIN is a good + * idea because it is the fastest. Other methods, ordered by speedness, are POPMUSIC_TABU, + * POPMUSIC_CHAIN and POPMUSIC_TABU_CHAIN, defined in pal::_searchMethod enumeration + * @param method the method to use + */ + void setSearch( SearchMethod method ); + + /** + * \brief get the search method in use + * + * @return the search method + */ + SearchMethod getSearch(); + }; } // end namespace pal #endif diff --git a/src/core/pal/palexception.h b/src/core/pal/palexception.h index 04fcef92ff77..d49a7a001cba 100644 --- a/src/core/pal/palexception.h +++ b/src/core/pal/palexception.h @@ -37,67 +37,81 @@ #include -namespace pal { +namespace pal +{ - /** \brief Various Exceptions - */ - class PalException { + /** \brief Various Exceptions + */ + class PalException + { public: - /** \brief Thrown when a feature is not yet implemented - */ - class NotImplemented : public std::exception { - const char * what() const throw() { - return "Not yet implemented... sorry"; - } - }; + /** \brief Thrown when a feature is not yet implemented + */ + class NotImplemented : public std::exception + { + const char * what() const throw() + { + return "Not yet implemented... sorry"; + } + }; - /** \brief Try to access an unknown feature - */ - class UnknownFeature : public std::exception { - const char * what() const throw() { - return "Feature not found"; - } - }; + /** \brief Try to access an unknown feature + */ + class UnknownFeature : public std::exception + { + const char * what() const throw() + { + return "Feature not found"; + } + }; - /** \brief Try to access an unknown layer - */ - class UnknownLayer : public std::exception { - const char * what() const throw() { - return "Layer not found"; - } - }; + /** \brief Try to access an unknown layer + */ + class UnknownLayer : public std::exception + { + const char * what() const throw() + { + return "Layer not found"; + } + }; - /** \brief layer already exists - */ - class LayerExists : public std::exception { - const char * what() const throw() { - return "Layers names must be unique"; - } - }; + /** \brief layer already exists + */ + class LayerExists : public std::exception + { + const char * what() const throw() + { + return "Layers names must be unique"; + } + }; - /** \brief features already exists - */ - class FeatureExists : public std::exception { - const char * what() const throw() { - return "Features IDs must be unique within a layer"; - } - }; + /** \brief features already exists + */ + class FeatureExists : public std::exception + { + const char * what() const throw() + { + return "Features IDs must be unique within a layer"; + } + }; - /** \brief thrown when a value is not in the valid scale range - * - * It can be thrown by : - * - * - pal::Layer::setFeatureLabelSize if either the height or the width of the label is < 0 - * - * - pal::Layer::setFeatureDistlabel is distlable < 0 - */ - class ValueNotInRange : public std::exception { - const char * what() const throw() { - return "value not allowed"; - } - }; - }; + /** \brief thrown when a value is not in the valid scale range + * + * It can be thrown by : + * + * - pal::Layer::setFeatureLabelSize if either the height or the width of the label is < 0 + * + * - pal::Layer::setFeatureDistlabel is distlable < 0 + */ + class ValueNotInRange : public std::exception + { + const char * what() const throw() + { + return "value not allowed"; + } + }; + }; } // namespace diff --git a/src/core/pal/palgeometry.h b/src/core/pal/palgeometry.h index 1e85a3a4a31c..e02c09272c04 100644 --- a/src/core/pal/palgeometry.h +++ b/src/core/pal/palgeometry.h @@ -34,53 +34,55 @@ #include #include -namespace pal { +namespace pal +{ - /** - * \brief Interface that allow Pal to acces user's geometries - */ - class PalGeometry { + /** + * \brief Interface that allow Pal to acces user's geometries + */ + class PalGeometry + { public: - /* - * \brief get the geometry in WKB hexa format - * This method is called by Pal each time it needs a geom's coordinates - * - * @return WKB Hex buffer - */ - //virtual char * getWkbHexBuffer() = 0; + /* + * \brief get the geometry in WKB hexa format + * This method is called by Pal each time it needs a geom's coordinates + * + * @return WKB Hex buffer + */ + //virtual char * getWkbHexBuffer() = 0; - /** - * \brief get the GEOSGeometry of the feature - * This method is called by Pal each time it needs a geom's coordinates - * - * @return GEOSGeometry * a pointer the the geos geom - */ - virtual GEOSGeometry* getGeosGeometry() = 0; + /** + * \brief get the GEOSGeometry of the feature + * This method is called by Pal each time it needs a geom's coordinates + * + * @return GEOSGeometry * a pointer the the geos geom + */ + virtual GEOSGeometry* getGeosGeometry() = 0; - /** - * \brief Called by Pal when it doesn't need the coordinates anymore - * @param the_geom is the geoms geom from PalGeometry::getfeomGeometry() - */ - virtual void releaseGeosGeometry (GEOSGeometry *the_geom) = 0; + /** + * \brief Called by Pal when it doesn't need the coordinates anymore + * @param the_geom is the geoms geom from PalGeometry::getfeomGeometry() + */ + virtual void releaseGeosGeometry( GEOSGeometry *the_geom ) = 0; - /* - * \brief Called by Pal when it doesn't need the coordinates anymore - * @param wkbBuffer is the WkbBuffer from PalGeometry::getWkbHexBuffer() - */ - //virtual void releaseWkbHexBuffer(char *wkbBuffer) = 0; + /* + * \brief Called by Pal when it doesn't need the coordinates anymore + * @param wkbBuffer is the WkbBuffer from PalGeometry::getWkbHexBuffer() + */ + //virtual void releaseWkbHexBuffer(char *wkbBuffer) = 0; - /* - * \brief Give back a label to display - * Pal call this method when label will no move anymore. - * - * @param label the label to disploy - */ - //virtual void addLabel(Label *label) = 0; + /* + * \brief Give back a label to display + * Pal call this method when label will no move anymore. + * + * @param label the label to disploy + */ + //virtual void addLabel(Label *label) = 0; - virtual ~PalGeometry() {} - }; + virtual ~PalGeometry() {} + }; } // end namespace pal diff --git a/src/core/pal/palstat.cpp b/src/core/pal/palstat.cpp index 222ec10870c7..2cc06252d32b 100644 --- a/src/core/pal/palstat.cpp +++ b/src/core/pal/palstat.cpp @@ -34,63 +34,73 @@ #include #include -namespace pal { - - PalStat::PalStat() { - nbLayers = 0; - nbObjects = 0; - nbLabelledObjects = 0; - layersName = NULL; - layersNbObjects = NULL; - layersNbLabelledObjects = NULL; +namespace pal +{ + + PalStat::PalStat() + { + nbLayers = 0; + nbObjects = 0; + nbLabelledObjects = 0; + layersName = NULL; + layersNbObjects = NULL; + layersNbLabelledObjects = NULL; + } + + PalStat::~PalStat() + { + int i; + + for ( i = 0;i < nbLayers;i++ ) + { + delete[] layersName[i]; } - PalStat::~PalStat() { - int i; - - for (i = 0;i < nbLayers;i++) { - delete[] layersName[i]; - } - - delete[] layersName; - delete[] layersNbObjects; - delete[] layersNbLabelledObjects; - } - - int PalStat::getNbObjects() { - return nbObjects; - } - - int PalStat::getNbLabelledObjects() { - return nbLabelledObjects; - } - - int PalStat::getNbLayers() { - return nbLayers; - } - - const char * PalStat::getLayerName (int layerId) { - if (layerId >= 0 && layerId < nbLayers) - return layersName[layerId]; - else - return NULL; - } - - - int PalStat::getLayerNbObjects (int layerId) { - if (layerId >= 0 && layerId < nbLayers) - return layersNbObjects[layerId]; - else - return -1; - } - - - int PalStat::getLayerNbLabelledObjects (int layerId) { - if (layerId >= 0 && layerId < nbLayers) - return layersNbLabelledObjects[layerId]; - else - return -1; - } + delete[] layersName; + delete[] layersNbObjects; + delete[] layersNbLabelledObjects; + } + + int PalStat::getNbObjects() + { + return nbObjects; + } + + int PalStat::getNbLabelledObjects() + { + return nbLabelledObjects; + } + + int PalStat::getNbLayers() + { + return nbLayers; + } + + const char * PalStat::getLayerName( int layerId ) + { + if ( layerId >= 0 && layerId < nbLayers ) + return layersName[layerId]; + else + return NULL; + } + + + int PalStat::getLayerNbObjects( int layerId ) + { + if ( layerId >= 0 && layerId < nbLayers ) + return layersNbObjects[layerId]; + else + return -1; + } + + + int PalStat::getLayerNbLabelledObjects( int layerId ) + { + if ( layerId >= 0 && layerId < nbLayers ) + return layersNbLabelledObjects[layerId]; + else + return -1; + } } // namespace diff --git a/src/core/pal/palstat.h b/src/core/pal/palstat.h index 5055f1f114a9..822f62529259 100644 --- a/src/core/pal/palstat.h +++ b/src/core/pal/palstat.h @@ -35,66 +35,68 @@ #define _PALSTAT_H_ -namespace pal { +namespace pal +{ - /** - * Summury of problem - */ - class PalStat { + /** + * Summury of problem + */ + class PalStat + { - friend class Pal; - friend class Problem; + friend class Pal; + friend class Problem; private: - int nbObjects; - int nbLabelledObjects; + int nbObjects; + int nbLabelledObjects; - int nbLayers; + int nbLayers; - char **layersName; //[nbLayers] - int *layersNbObjects; // [nbLayers] - int *layersNbLabelledObjects; // [nbLayers] + char **layersName; //[nbLayers] + int *layersNbObjects; // [nbLayers] + int *layersNbLabelledObjects; // [nbLayers] - PalStat(); + PalStat(); public: - /** - * \brief delete stats - */ - ~PalStat(); - - - /** - * \brief the number of object in problem - */ - int getNbObjects(); - - /** - * \brief the number of objects which are labelled - */ - int getNbLabelledObjects(); - - /** - * \brief how many layersare labelled ? - */ - int getNbLayers(); - - /** - * \brief get a name of the labelled layer 'layerId' - */ - const char * getLayerName (int layerId); - - /** - * \brief get the number of object in layer 'layerId' - */ - int getLayerNbObjects (int layerId); - - /** - * \brief get the number of object in layer 'layerId' which are labelled - */ - int getLayerNbLabelledObjects (int layerId); - }; + /** + * \brief delete stats + */ + ~PalStat(); + + + /** + * \brief the number of object in problem + */ + int getNbObjects(); + + /** + * \brief the number of objects which are labelled + */ + int getNbLabelledObjects(); + + /** + * \brief how many layersare labelled ? + */ + int getNbLayers(); + + /** + * \brief get a name of the labelled layer 'layerId' + */ + const char * getLayerName( int layerId ); + + /** + * \brief get the number of object in layer 'layerId' + */ + int getLayerNbObjects( int layerId ); + + /** + * \brief get the number of object in layer 'layerId' which are labelled + */ + int getLayerNbLabelledObjects( int layerId ); + }; } // end namespace pal diff --git a/src/core/pal/pointset.cpp b/src/core/pal/pointset.cpp index db418efb1b74..1fc6c2810df0 100644 --- a/src/core/pal/pointset.cpp +++ b/src/core/pal/pointset.cpp @@ -46,1350 +46,1519 @@ #include "geomfunction.h" -namespace pal { - - - PointSet::PointSet() { - nbPoints = cHullSize = 0; - x = NULL; - y = NULL; - status = NULL; - cHull = NULL; - type = -1; +namespace pal +{ + + + PointSet::PointSet() + { + nbPoints = cHullSize = 0; + x = NULL; + y = NULL; + status = NULL; + cHull = NULL; + type = -1; + } + + PointSet::PointSet( int nbPoints, double *x, double *y ) + { + this->nbPoints = nbPoints; + this->x = new double[nbPoints]; + this->y = new double[nbPoints]; + int i; + + for ( i = 0;i < nbPoints;i++ ) + { + this->x[i] = x[i]; + this->y[i] = y[i]; } - - PointSet::PointSet (int nbPoints, double *x, double *y){ - this->nbPoints = nbPoints; - this->x = new double[nbPoints]; - this->y = new double[nbPoints]; - int i; - - for (i=0;ix[i] = x[i]; - this->y[i] = y[i]; - } - type = GEOS_POLYGON; - status = NULL; - cHull = NULL; + type = GEOS_POLYGON; + status = NULL; + cHull = NULL; + } + + PointSet::PointSet( double x, double y ) + { + nbPoints = cHullSize = 1; + this->x = new double[1]; + this->y = new double[1]; + this->x[0] = x; + this->y[0] = y; + + status = NULL; + cHull = NULL; + parent = NULL; + holeOf = NULL; + + type = GEOS_POINT; + } + + PointSet::PointSet( PointSet &ps ) + { + int i; + + nbPoints = ps.nbPoints; + x = new double[nbPoints]; + y = new double[nbPoints]; + + if ( ps.status ) + status = new int[nbPoints]; + else + status = NULL; + + + for ( i = 0;i < nbPoints;i++ ) + { + x[i] = ps.x[i]; + y[i] = ps.y[i]; + if ( status ) + status[i] = ps.status[i]; } - PointSet::PointSet(double x, double y){ - nbPoints = cHullSize = 1; - this->x = new double[1]; - this->y = new double[1]; - this->x[0] = x; - this->y[0] = y; - - status = NULL; - cHull = NULL; - parent = NULL; - holeOf = NULL; - - type = GEOS_POINT; + if ( ps.cHull ) + { + cHullSize = ps.cHullSize; + for ( i = 0;i < cHullSize;i++ ) + { + cHull[i] = ps.cHull[i]; + } + } + else + { + cHull = NULL; + cHullSize = 0; } - PointSet::PointSet (PointSet &ps) { - int i; - - nbPoints = ps.nbPoints; - x = new double[nbPoints]; - y = new double[nbPoints]; - - if (ps.status) - status = new int[nbPoints]; - else - status = NULL; - - - for (i = 0;i < nbPoints;i++) { - x[i] = ps.x[i]; - y[i] = ps.y[i]; - if (status) - status[i] = ps.status[i]; - } - - if (ps.cHull) { - cHullSize = ps.cHullSize; - for (i = 0;i < cHullSize;i++) { - cHull[i] = ps.cHull[i]; - } - } else { - cHull = NULL; - cHullSize = 0; - } - - type = ps.type; + type = ps.type; - holeOf = ps.holeOf; - } + holeOf = ps.holeOf; + } - PointSet::~PointSet() { - if (x) - delete[] x; - if (y) - delete[] y; + PointSet::~PointSet() + { + if ( x ) + delete[] x; + if ( y ) + delete[] y; - if (status) - delete[] status; - if (cHull) - delete[] cHull; - } + if ( status ) + delete[] status; + if ( cHull ) + delete[] cHull; + } - int PointSet::getPath (int start, int stop, int *path_val) { - int nbPt = 0; - int i; + int PointSet::getPath( int start, int stop, int *path_val ) + { + int nbPt = 0; + int i; #ifdef _DEBUG_FULL_ - std::cout << "start: " << start << std::endl; - std::cout << "stop: " << stop << std::endl; - std::cout << "nbPoints: " << nbPoints << std::endl; + std::cout << "start: " << start << std::endl; + std::cout << "stop: " << stop << std::endl; + std::cout << "nbPoints: " << nbPoints << std::endl; #endif - for (i = start; i != stop; i = (i + 1) % nbPoints, nbPt++) { - if (status[i] < 10 && status[i] != *path_val) - *path_val = 0; - } + for ( i = start; i != stop; i = ( i + 1 ) % nbPoints, nbPt++ ) + { + if ( status[i] < 10 && status[i] != *path_val ) + *path_val = 0; + } #ifdef _DEBUG_FULL_ - std::cout << "new nbPoints: " << nbPt << std::endl; + std::cout << "new nbPoints: " << nbPt << std::endl; #endif - return nbPt; - } + return nbPt; + } - PointSet * PointSet::extractPath (int path, int nbPtPath, int nbBboxPt, double bbx[4], double bby[4], Crossing *start, Crossing *stop, int startPt) { + PointSet * PointSet::extractPath( int path, int nbPtPath, int nbBboxPt, double bbx[4], double bby[4], Crossing *start, Crossing *stop, int startPt ) + { - if (path == -1 || path == 0) { - int k, j, l; - PointSet *newShape = new PointSet(); - newShape->nbPoints = nbPtPath + nbBboxPt + 2; - newShape->x = new double[newShape->nbPoints]; - newShape->y = new double[newShape->nbPoints]; - newShape->status = new int[newShape->nbPoints]; - newShape->type = GEOS_POLYGON; - k = 0; + if ( path == -1 || path == 0 ) + { + int k, j, l; + PointSet *newShape = new PointSet(); + newShape->nbPoints = nbPtPath + nbBboxPt + 2; + newShape->x = new double[newShape->nbPoints]; + newShape->y = new double[newShape->nbPoints]; + newShape->status = new int[newShape->nbPoints]; + newShape->type = GEOS_POLYGON; + k = 0; #ifdef _DEBUG_FULL_ - std::cout << "Keep # ot: " << newShape->nbPoints << " :: " << path << std::endl; - std::cout << "path point:" << nbPtPath << std::endl; + std::cout << "Keep # ot: " << newShape->nbPoints << " :: " << path << std::endl; + std::cout << "path point:" << nbPtPath << std::endl; #endif - // start => b - // stop => a + // start => b + // stop => a - newShape->xmin = DBL_MAX; - newShape->xmax = -DBL_MAX; - newShape->ymin = DBL_MAX; - newShape->ymax = -DBL_MAX; + newShape->xmin = DBL_MAX; + newShape->xmax = -DBL_MAX; + newShape->ymin = DBL_MAX; + newShape->ymax = -DBL_MAX; - for (k = 0, j = startPt; k < nbPtPath; j = (j + 1) % nbPoints, k++) { - newShape->x[k] = x[j]; - newShape->y[k] = y[j]; - newShape->status[k] = status[j]; + for ( k = 0, j = startPt; k < nbPtPath; j = ( j + 1 ) % nbPoints, k++ ) + { + newShape->x[k] = x[j]; + newShape->y[k] = y[j]; + newShape->status[k] = status[j]; #ifdef _DEBUG_FULL_ - std::cout << " " << x[j] << ";" << y[j] << std::endl; + std::cout << " " << x[j] << ";" << y[j] << std::endl; #endif - newShape->xmin = (newShape->xmin < x[j] ? newShape->xmin : x[j]); - newShape->xmax = (newShape->xmax > x[j] ? newShape->xmax : x[j]); - newShape->ymin = (newShape->ymin < y[j] ? newShape->ymin : y[j]); - newShape->ymax = (newShape->ymax > y[j] ? newShape->ymax : y[j]); + newShape->xmin = ( newShape->xmin < x[j] ? newShape->xmin : x[j] ); + newShape->xmax = ( newShape->xmax > x[j] ? newShape->xmax : x[j] ); + newShape->ymin = ( newShape->ymin < y[j] ? newShape->ymin : y[j] ); + newShape->ymax = ( newShape->ymax > y[j] ? newShape->ymax : y[j] ); + } + + /* + if (start->pt != stop->pt){ + newShape->x[k] = x[j]; + newShape->y[k] = y[j]; + newShape->status[k] = status[j]; + #ifdef _DEBUG_ + std::cout << " " << x[j] << ";" << y[j] << std::endl; + #endif + k++; } - - /* - if (start->pt != stop->pt){ - newShape->x[k] = x[j]; - newShape->y[k] = y[j]; - newShape->status[k] = status[j]; - #ifdef _DEBUG_ - std::cout << " " << x[j] << ";" << y[j] << std::endl; - #endif - k++; - } - */ + */ #ifdef _DEBUG_FULL_ - std::cout << "pta:" << std::endl; + std::cout << "pta:" << std::endl; #endif - newShape->x[k] = stop->x; - newShape->y[k] = stop->y; + newShape->x[k] = stop->x; + newShape->y[k] = stop->y; - newShape->xmin = (newShape->xmin < stop->x ? newShape->xmin : stop->x); - newShape->xmax = (newShape->xmax > stop->x ? newShape->xmax : stop->x); - newShape->ymin = (newShape->ymin < stop->y ? newShape->ymin : stop->y); - newShape->ymax = (newShape->ymax > stop->y ? newShape->ymax : stop->y); + newShape->xmin = ( newShape->xmin < stop->x ? newShape->xmin : stop->x ); + newShape->xmax = ( newShape->xmax > stop->x ? newShape->xmax : stop->x ); + newShape->ymin = ( newShape->ymin < stop->y ? newShape->ymin : stop->y ); + newShape->ymax = ( newShape->ymax > stop->y ? newShape->ymax : stop->y ); - if (stop->way == -1) - newShape->status[k] = stop->nextCorner + 10; - else - newShape->status[k] = ( (stop->nextCorner + 3) % 4) + 10; - k++; + if ( stop->way == -1 ) + newShape->status[k] = stop->nextCorner + 10; + else + newShape->status[k] = (( stop->nextCorner + 3 ) % 4 ) + 10; + k++; #ifdef _DEBUG_FULL_ - std::cout << " " << stop->x << ";" << stop->y << std::endl; - std::cout << "corner:" << std::endl; + std::cout << " " << stop->x << ";" << stop->y << std::endl; + std::cout << "corner:" << std::endl; #endif - for (j = 0, l = stop->nextCorner;j < nbBboxPt;j++, l = (l + stop->way + 4) % 4, k++) { - newShape->x[k] = bbx[l]; - newShape->y[k] = bby[l]; - newShape->status[k] = 15; + for ( j = 0, l = stop->nextCorner;j < nbBboxPt;j++, l = ( l + stop->way + 4 ) % 4, k++ ) + { + newShape->x[k] = bbx[l]; + newShape->y[k] = bby[l]; + newShape->status[k] = 15; #ifdef _DEBUG_FULL_ - std::cout << " " << bbx[l] << ";" << bby[l] << std::endl; + std::cout << " " << bbx[l] << ";" << bby[l] << std::endl; #endif - newShape->xmin = (newShape->xmin < bbx[l] ? newShape->xmin : bbx[l]); - newShape->xmax = (newShape->xmax > bbx[l] ? newShape->xmax : bbx[l]); - newShape->ymin = (newShape->ymin < bby[l] ? newShape->ymin : bby[l]); - newShape->ymax = (newShape->ymax > bby[l] ? newShape->ymax : bby[l]); - } + newShape->xmin = ( newShape->xmin < bbx[l] ? newShape->xmin : bbx[l] ); + newShape->xmax = ( newShape->xmax > bbx[l] ? newShape->xmax : bbx[l] ); + newShape->ymin = ( newShape->ymin < bby[l] ? newShape->ymin : bby[l] ); + newShape->ymax = ( newShape->ymax > bby[l] ? newShape->ymax : bby[l] ); + } - newShape->x[k] = start->x; - newShape->y[k] = start->y; + newShape->x[k] = start->x; + newShape->y[k] = start->y; - newShape->xmin = (newShape->xmin < start->x ? newShape->xmin : start->x); - newShape->xmax = (newShape->xmax > start->x ? newShape->xmax : start->x); - newShape->ymin = (newShape->ymin < start->y ? newShape->ymin : start->y); - newShape->ymax = (newShape->ymax > start->y ? newShape->ymax : start->y); + newShape->xmin = ( newShape->xmin < start->x ? newShape->xmin : start->x ); + newShape->xmax = ( newShape->xmax > start->x ? newShape->xmax : start->x ); + newShape->ymin = ( newShape->ymin < start->y ? newShape->ymin : start->y ); + newShape->ymax = ( newShape->ymax > start->y ? newShape->ymax : start->y ); - if (start->way == -1) - newShape->status[k] = start->nextCorner + 10; - else - newShape->status[k] = ( (start->nextCorner + 3) % 4) + 10; + if ( start->way == -1 ) + newShape->status[k] = start->nextCorner + 10; + else + newShape->status[k] = (( start->nextCorner + 3 ) % 4 ) + 10; #ifdef _DEBUG_FULL_ - std::cout << "ptb:" << std::endl; - std::cout << " " << start->x << ";" << start->y << std::endl; - std::cout << "k: " << k << " nbPoints: " << newShape->nbPoints << std::endl; + std::cout << "ptb:" << std::endl; + std::cout << " " << start->x << ";" << start->y << std::endl; + std::cout << "k: " << k << " nbPoints: " << newShape->nbPoints << std::endl; #endif - return newShape; - } else - return NULL; + return newShape; } + else + return NULL; + } - void PointSet::reduceLine (PointSet *line, - LinkedList *shapes_final, - double bbx[4], double bby[4]) { + void PointSet::reduceLine( PointSet *line, + LinkedList *shapes_final, + double bbx[4], double bby[4] ) + { #ifdef _DEBUG_ - std::cout << "reduceLine" << std::endl; + std::cout << "reduceLine" << std::endl; #endif - int i, j; - int ba, bb; - Crossing *crossing; - double crossingX, crossingY; - LinkedList *crossings = new LinkedList (ptrCrossingCompare); + int i, j; + int ba, bb; + Crossing *crossing; + double crossingX, crossingY; + LinkedList *crossings = new LinkedList ( ptrCrossingCompare ); - int nbPoints = line->nbPoints; - double *x = line->x; - double *y = line->y; - int *status = line->status; + int nbPoints = line->nbPoints; + double *x = line->x; + double *y = line->y; + int *status = line->status; #ifdef _DEBUG_FULL_ - std::cout << "Coord:" << std::endl; - for (i = 0;i < nbPoints;i++) { - std::cout << x[i] << ";" << y[i] << std::endl; - } + std::cout << "Coord:" << std::endl; + for ( i = 0;i < nbPoints;i++ ) + { + std::cout << x[i] << ";" << y[i] << std::endl; + } #endif - for (i = 0, j = i + 1;i < nbPoints - 1;i++, j++) { - for (ba = 0;ba < 4;ba++) { // for each bbox segement - bb = (ba + 1) % 4; + for ( i = 0, j = i + 1;i < nbPoints - 1;i++, j++ ) + { + for ( ba = 0;ba < 4;ba++ ) // for each bbox segement + { + bb = ( ba + 1 ) % 4; #ifdef _DEBUG_FULL_ - std::cout << "Test: " << i << "->" << j << " and " << ba << "-->" << bb << std::endl; + std::cout << "Test: " << i << "->" << j << " and " << ba << "-->" << bb << std::endl; #endif - if (computeSegIntersection (x[i], y[i], x[j], y[j], - bbx[ba], bby[ba], bbx[bb], bby[bb], - &crossingX, &crossingY)) { // seg[i->j] crossing bbox[ba->bb] - - crossing = new Crossing(); - crossing->pt = i; - crossing->x = crossingX; // cross coordinate - crossing->y = crossingY; + if ( computeSegIntersection( x[i], y[i], x[j], y[j], + bbx[ba], bby[ba], bbx[bb], bby[bb], + &crossingX, &crossingY ) ) // seg[i->j] crossing bbox[ba->bb] + { + + crossing = new Crossing(); + crossing->pt = i; + crossing->x = crossingX; // cross coordinate + crossing->y = crossingY; #ifdef _DEBUG_FULL_ - std::cout << "Crossing: " << std::endl; - std::cout << " cross point: " << crossingX << ";" << crossingY << std::endl; - std::cout << " pt: " << i << " (" << status[i] << ")" << std::endl; + std::cout << "Crossing: " << std::endl; + std::cout << " cross point: " << crossingX << ";" << crossingY << std::endl; + std::cout << " pt: " << i << " (" << status[i] << ")" << std::endl; #endif - crossings->push_back (crossing); - } - - } + crossings->push_back( crossing ); } + } + } - if (crossings->size() > 0) { - int start, stop; - double startX, startY; - double stopX, stopY; - - bool seg_complete; - - Crossing *crossing; - startX = x[0]; - startY = y[0]; - start = 1; - while (crossings->size() > 0) { - crossing = crossings->pop_front(); - - // TODO - if (status[crossing->pt] == -1) { // inside - stop = crossing->pt; - stopX = crossing->x; - stopY = crossing->y; - PointSet *new_line = new PointSet(); - new_line->nbPoints = stop - start + 3; - new_line->type = GEOS_LINESTRING; - new_line->x = new double [new_line->nbPoints]; - new_line->y = new double [new_line->nbPoints]; - - new_line->x[0] = startX; - new_line->y[0] = startY; - - new_line->xmin = new_line->x[0]; - new_line->xmax = new_line->x[0]; - - new_line->ymin = new_line->y[0]; - new_line->ymax = new_line->y[0]; - - for (j = start, i = 1;j <= stop;j++, i++) { - new_line->x[i] = x[j]; - new_line->y[i] = y[j]; - - new_line->xmin = (new_line->xmin < x[j] ? new_line->xmin : x[j]); - new_line->xmax = (new_line->xmax > x[j] ? new_line->xmax : x[j]); - new_line->ymin = (new_line->ymin < y[j] ? new_line->ymin : y[j]); - new_line->ymax = (new_line->ymax > y[j] ? new_line->ymax : y[j]); - } - new_line->x[new_line->nbPoints-1] = stopX; - new_line->y[new_line->nbPoints-1] = stopY; - - new_line->xmin = (new_line->xmin < stopX ? new_line->xmin : stopX); - new_line->xmax = (new_line->xmax > stopX ? new_line->xmax : stopX); - new_line->ymin = (new_line->ymin < stopY ? new_line->ymin : stopY); - new_line->ymax = (new_line->ymax > stopY ? new_line->ymax : stopY); - - shapes_final->push_back (new_line); - seg_complete = true; - } else { - start = crossing->pt + 1; - startX = crossing->x; - startY = crossing->y; - seg_complete = false; - } - delete crossing; - } - if (!seg_complete) { - PointSet * new_line = new PointSet(); - new_line->type = GEOS_LINESTRING; - new_line->nbPoints = nbPoints - start + 1; - new_line->x = new double[new_line->nbPoints]; - new_line->y = new double[new_line->nbPoints]; - new_line->x[0] = startX; - new_line->y[0] = startY; - - new_line->xmin = startX; - new_line->xmax = startX; - - new_line->ymin = startY; - new_line->ymax = startY; - - for (j = start, i = 1;j < nbPoints;j++, i++) { - new_line->x[i] = x[j]; - new_line->y[i] = y[j]; - - new_line->xmin = (new_line->xmin < x[j] ? new_line->xmin : x[j]); - new_line->xmax = (new_line->xmax > x[j] ? new_line->xmax : x[j]); - new_line->ymin = (new_line->ymin < y[j] ? new_line->ymin : y[j]); - new_line->ymax = (new_line->ymax > y[j] ? new_line->ymax : y[j]); - } - shapes_final->push_back (new_line); - } + if ( crossings->size() > 0 ) + { + int start, stop; + double startX, startY; + double stopX, stopY; + + bool seg_complete; + + Crossing *crossing; + startX = x[0]; + startY = y[0]; + start = 1; + while ( crossings->size() > 0 ) + { + crossing = crossings->pop_front(); + + // TODO + if ( status[crossing->pt] == -1 ) // inside + { + stop = crossing->pt; + stopX = crossing->x; + stopY = crossing->y; + PointSet *new_line = new PointSet(); + new_line->nbPoints = stop - start + 3; + new_line->type = GEOS_LINESTRING; + new_line->x = new double [new_line->nbPoints]; + new_line->y = new double [new_line->nbPoints]; + + new_line->x[0] = startX; + new_line->y[0] = startY; + + new_line->xmin = new_line->x[0]; + new_line->xmax = new_line->x[0]; + + new_line->ymin = new_line->y[0]; + new_line->ymax = new_line->y[0]; + + for ( j = start, i = 1;j <= stop;j++, i++ ) + { + new_line->x[i] = x[j]; + new_line->y[i] = y[j]; + + new_line->xmin = ( new_line->xmin < x[j] ? new_line->xmin : x[j] ); + new_line->xmax = ( new_line->xmax > x[j] ? new_line->xmax : x[j] ); + new_line->ymin = ( new_line->ymin < y[j] ? new_line->ymin : y[j] ); + new_line->ymax = ( new_line->ymax > y[j] ? new_line->ymax : y[j] ); + } + new_line->x[new_line->nbPoints-1] = stopX; + new_line->y[new_line->nbPoints-1] = stopY; + + new_line->xmin = ( new_line->xmin < stopX ? new_line->xmin : stopX ); + new_line->xmax = ( new_line->xmax > stopX ? new_line->xmax : stopX ); + new_line->ymin = ( new_line->ymin < stopY ? new_line->ymin : stopY ); + new_line->ymax = ( new_line->ymax > stopY ? new_line->ymax : stopY ); + + shapes_final->push_back( new_line ); + seg_complete = true; + } + else + { + start = crossing->pt + 1; + startX = crossing->x; + startY = crossing->y; + seg_complete = false; + } + delete crossing; + } + + if ( !seg_complete ) + { + PointSet * new_line = new PointSet(); + new_line->type = GEOS_LINESTRING; + new_line->nbPoints = nbPoints - start + 1; + new_line->x = new double[new_line->nbPoints]; + new_line->y = new double[new_line->nbPoints]; + new_line->x[0] = startX; + new_line->y[0] = startY; + + new_line->xmin = startX; + new_line->xmax = startX; + + new_line->ymin = startY; + new_line->ymax = startY; + + for ( j = start, i = 1;j < nbPoints;j++, i++ ) + { + new_line->x[i] = x[j]; + new_line->y[i] = y[j]; + + new_line->xmin = ( new_line->xmin < x[j] ? new_line->xmin : x[j] ); + new_line->xmax = ( new_line->xmax > x[j] ? new_line->xmax : x[j] ); + new_line->ymin = ( new_line->ymin < y[j] ? new_line->ymin : y[j] ); + new_line->ymax = ( new_line->ymax > y[j] ? new_line->ymax : y[j] ); + } + shapes_final->push_back( new_line ); + } - delete line; - } else { - // line is out + delete line; + } + else + { + // line is out #ifdef _DEBUG_FULL_ - std::cout << "Line is completely outside" << std::endl; + std::cout << "Line is completely outside" << std::endl; #endif - delete line; - } - - delete crossings; + delete line; } - /** - * \brief takes shapes from shapes_toProcess, compute intersection with bbox - * and puts new shapes into shapes_final - * - */ - void PointSet::reducePolygon (PointSet *shape_toProcess, LinkedList *shapes_final, double bbx[4], double bby[4]) { + delete crossings; + } + + /** + * \brief takes shapes from shapes_toProcess, compute intersection with bbox + * and puts new shapes into shapes_final + * + */ + void PointSet::reducePolygon( PointSet *shape_toProcess, LinkedList *shapes_final, double bbx[4], double bby[4] ) + { //#define _DEBUG_ //#define _DEBUG_FULL_ #ifdef _DEBUG_ - std::cout << "reducePolygon" << std::endl; + std::cout << "reducePolygon" << std::endl; #endif - int i, j; + int i, j; - int nbCrossingIter = 0; + int nbCrossingIter = 0; - LinkedList *shapes_toProcess = new LinkedList (ptrPSetCompare); - LinkedList *crossings = new LinkedList (ptrCrossingCompare); + LinkedList *shapes_toProcess = new LinkedList ( ptrPSetCompare ); + LinkedList *crossings = new LinkedList ( ptrCrossingCompare ); - shapes_toProcess->push_back (shape_toProcess); + shapes_toProcess->push_back( shape_toProcess ); - // only keep inside bbox part of feature - PointSet *shape; - while (shapes_toProcess->size() > 0) { // foreach feature in toProcess - nbCrossingIter++; - double crossingX, crossingY; + // only keep inside bbox part of feature + PointSet *shape; + while ( shapes_toProcess->size() > 0 ) // foreach feature in toProcess + { + nbCrossingIter++; + double crossingX, crossingY; - int ba, bb; - int k; - Crossing *crossing; + int ba, bb; + int k; + Crossing *crossing; - shape = shapes_toProcess->pop_front(); + shape = shapes_toProcess->pop_front(); #ifdef _DEBUG_FULL_ - std::cout << "ShapeToReduce:" << std::endl; + std::cout << "ShapeToReduce:" << std::endl; #endif - // search point where polygon and bbox cross - for (i = 0;i < shape->nbPoints;i++) { // foreach polygon segment + // search point where polygon and bbox cross + for ( i = 0;i < shape->nbPoints;i++ ) // foreach polygon segment + { #ifdef _DEBUG_FULL_ - std::cout << shape->x[i] << ";" << shape->y[i] << std::endl; + std::cout << shape->x[i] << ";" << shape->y[i] << std::endl; #endif - j = (i + 1) % shape->nbPoints; - for (ba = 0;ba < 4;ba++) { // for each bbox segement - bb = (ba + 1) % 4; - - if (computeSegIntersection (shape->x[i], shape->y[i], shape->x[j], shape->y[j], - bbx[ba], bby[ba], bbx[bb], bby[bb], - &crossingX, &crossingY)) { // seg[i->j] crossing bbox[ba->bb] - - if (vabs (cross_product (bbx[ba], bby[ba], bbx[bb], bby[bb], shape->x[i], shape->y[i])) > 0.00001) { - // perhaps shape had previuosly been splitted - // => new points generated by this operation are on the bbox border - // => avoid to consider this cross as valid ('status' for these new points are == bboxSegNumber + 10 and 15 for bbox corner - if (shape->status[i] != ba + 10 && shape->status[j] != ba + 10 - && shape->status[i] != 15 && shape->status[j] != 15) { - - crossing = new Crossing(); - crossing->pt = i; - crossing->x = crossingX; // cross coordinate - crossing->y = crossingY; - crossing->seg = ba; // wich bbox edge ? 0=south, 1 = east, 2 = west, 3=west - - // cross->nextCorner denote on which bbox corner we fall first when following bbox inside the polygon - if (cross_product (shape->x[crossing->pt], shape->y[crossing->pt], - shape->x[ (crossing->pt+1) %shape->nbPoints], - shape->y[ (crossing->pt+1) %shape->nbPoints], - bbx[ba], bby[ba]) > 0) { - crossing->nextCorner = ba; // next corner is ba - crossing->way = -1; // have to go counter-clockwise - } else { - crossing->nextCorner = bb; // next corner is bb - crossing->way = 1; // go clockwise - } - crossings->push_back (crossing); - //break; - } - } - } + j = ( i + 1 ) % shape->nbPoints; + for ( ba = 0;ba < 4;ba++ ) // for each bbox segement + { + bb = ( ba + 1 ) % 4; + + if ( computeSegIntersection( shape->x[i], shape->y[i], shape->x[j], shape->y[j], + bbx[ba], bby[ba], bbx[bb], bby[bb], + &crossingX, &crossingY ) ) // seg[i->j] crossing bbox[ba->bb] + { + + if ( vabs( cross_product( bbx[ba], bby[ba], bbx[bb], bby[bb], shape->x[i], shape->y[i] ) ) > 0.00001 ) + { + // perhaps shape had previuosly been splitted + // => new points generated by this operation are on the bbox border + // => avoid to consider this cross as valid ('status' for these new points are == bboxSegNumber + 10 and 15 for bbox corner + if ( shape->status[i] != ba + 10 && shape->status[j] != ba + 10 + && shape->status[i] != 15 && shape->status[j] != 15 ) + { + + crossing = new Crossing(); + crossing->pt = i; + crossing->x = crossingX; // cross coordinate + crossing->y = crossingY; + crossing->seg = ba; // wich bbox edge ? 0=south, 1 = east, 2 = west, 3=west + + // cross->nextCorner denote on which bbox corner we fall first when following bbox inside the polygon + if ( cross_product( shape->x[crossing->pt], shape->y[crossing->pt], + shape->x[( crossing->pt+1 ) %shape->nbPoints], + shape->y[( crossing->pt+1 ) %shape->nbPoints], + bbx[ba], bby[ba] ) > 0 ) + { + crossing->nextCorner = ba; // next corner is ba + crossing->way = -1; // have to go counter-clockwise + } + else + { + crossing->nextCorner = bb; // next corner is bb + crossing->way = 1; // go clockwise } + crossings->push_back( crossing ); + //break; + } } - - - i = 0; - int crossingTabSize = crossings->size(); - Crossing ** crossingTab = new Crossing*[crossingTabSize]; - - // put crosses in crossTab - while (crossings->size() > 0) { - crossing = crossings->pop_front(); - crossingTab[i] = crossing; - i++; + } + } + } + + + i = 0; + int crossingTabSize = crossings->size(); + Crossing ** crossingTab = new Crossing*[crossingTabSize]; + + // put crosses in crossTab + while ( crossings->size() > 0 ) + { + crossing = crossings->pop_front(); + crossingTab[i] = crossing; + i++; + } + + if ( crossingTabSize > 1 ) + { + double initialDist; + double nextX; + double nextY; + double startX; + double startY; + + initialDist = 0; + + // sort cross points, order counterclockwise by following bbox from down-left corner + for ( k = 0;k < 4;k++ ) + { + startX = bbx[k]; + startY = bby[k]; + nextX = bbx[( k+1 ) %4]; + nextY = bby[( k+1 ) %4]; + + for ( j = 0;j < crossingTabSize;j++ ) + { + // if the crossing point is colinear with bbox seg + if ( crossingTab[j]->seg == k ) + { + crossingTab[j]->d = initialDist + dist_euc2d_sq( startX, startY, crossingTab[j]->x, crossingTab[j]->y ); } + } + initialDist += dist_euc2d_sq( startX, startY, nextX, nextY ); + } + sort(( void** ) crossingTab, crossingTabSize, crossingDist ); - if (crossingTabSize > 1) { - double initialDist; - double nextX; - double nextY; - double startX; - double startY; - - initialDist = 0; - - // sort cross points, order counterclockwise by following bbox from down-left corner - for (k = 0;k < 4;k++) { - startX = bbx[k]; - startY = bby[k]; - nextX = bbx[ (k+1) %4]; - nextY = bby[ (k+1) %4]; - - for (j = 0;j < crossingTabSize;j++) { - // if the crossing point is colinear with bbox seg - if (crossingTab[j]->seg == k) { - crossingTab[j]->d = initialDist + dist_euc2d_sq (startX, startY, crossingTab[j]->x, crossingTab[j]->y); - } - } - initialDist += dist_euc2d_sq (startX, startY, nextX, nextY); - } - sort ( (void**) crossingTab, crossingTabSize, crossingDist); - - // crossing are sorted + // crossing are sorted #ifdef _DEBUG_FULL_ - for (i = 0;i < crossingTabSize;i++) { - std::cout << "Crossing # " << i << ":" << std::endl; - std::cout << " pt: " << crossingTab[i]->pt << std::endl; - std::cout << " d: " << crossingTab[i]->d << std::endl; - std::cout << " (x,y): (" << crossingTab[i]->x << "," << crossingTab[i]->y << ")" << std::endl; - std::cout << " next corner: " << crossingTab[i]->nextCorner << std::endl; - std::cout << " way: " << crossingTab[i]->way << std::endl; - std::cout << std::endl; - } + for ( i = 0;i < crossingTabSize;i++ ) + { + std::cout << "Crossing # " << i << ":" << std::endl; + std::cout << " pt: " << crossingTab[i]->pt << std::endl; + std::cout << " d: " << crossingTab[i]->d << std::endl; + std::cout << " (x,y): (" << crossingTab[i]->x << "," << crossingTab[i]->y << ")" << std::endl; + std::cout << " next corner: " << crossingTab[i]->nextCorner << std::endl; + std::cout << " way: " << crossingTab[i]->way << std::endl; + std::cout << std::endl; + } #endif - // select tros crosses - Crossing *a = crossingTab[0]; - Crossing *b = crossingTab[ (a->way + crossingTabSize) %crossingTabSize]; + // select tros crosses + Crossing *a = crossingTab[0]; + Crossing *b = crossingTab[( a->way + crossingTabSize ) %crossingTabSize]; - if (vabs (a->x - b->x) > 0.00001 || vabs (a->y - b->y) > 0.00001) { + if ( vabs( a->x - b->x ) > 0.00001 || vabs( a->y - b->y ) > 0.00001 ) + { #ifdef _DEBUG_FULL_ - std::cout << "crossing: " << a->x << ";" << a->y << std::endl; - std::cout << "d: " << a->d << std::endl; - std::cout << "a: 0 " << " b: " << (a->way + crossingTabSize) % crossingTabSize << std::endl; + std::cout << "crossing: " << a->x << ";" << a->y << std::endl; + std::cout << "d: " << a->d << std::endl; + std::cout << "a: 0 " << " b: " << ( a->way + crossingTabSize ) % crossingTabSize << std::endl; #endif - int cornerA = a->nextCorner; - j = 1; - while (cornerA != b->nextCorner) { - j++; - cornerA = (cornerA + a->way + 4) % 4; - } - - if (j == 4) { - if (isSegIntersects (a->x, a->y, - bbx[a->nextCorner], bby[a->nextCorner], - shape->x[b->pt], shape->y[b->pt], - shape->x[ (b->pt + 1) %shape->nbPoints], shape->y[ (b->pt + 1) %shape->nbPoints])) { - j = 0; - } - } + int cornerA = a->nextCorner; + j = 1; + while ( cornerA != b->nextCorner ) + { + j++; + cornerA = ( cornerA + a->way + 4 ) % 4; + } + + if ( j == 4 ) + { + if ( isSegIntersects( a->x, a->y, + bbx[a->nextCorner], bby[a->nextCorner], + shape->x[b->pt], shape->y[b->pt], + shape->x[( b->pt + 1 ) %shape->nbPoints], shape->y[( b->pt + 1 ) %shape->nbPoints] ) ) + { + j = 0; + } + } - int nbBboxPoint = j; - int nbPtPathA = 0; - int nbPtPathB = 0; + int nbBboxPoint = j; + int nbPtPathA = 0; + int nbPtPathB = 0; #ifdef _DEBUG_FULL_ - std::cout << std::endl; + std::cout << std::endl; #endif - int path_a; - int path_b; - - if (shape->status[a->pt] == -1) { // ok - path_a = -1; // a is inside so... - path_b = 1; // b is outside - } else if (shape->status[b->pt] == -1) { // ok - path_a = 1; - path_b = -1; - } else if (shape->status[a->pt] == 1 && shape->status[b->pt] == 1) { - path_a = -1; - path_b = -1; - } else if (shape->status[a->pt] == 1) { - path_a = 1; - path_b = -1; - } else if (shape->status[b->pt] == 1) { - path_a = -1; - path_b = 1; - } else { - std::cout << "OULALA C EST UN PROBLEMEM CA!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl; - path_a = 0; - path_b = 0; - } + int path_a; + int path_b; + + if ( shape->status[a->pt] == -1 ) // ok + { + path_a = -1; // a is inside so... + path_b = 1; // b is outside + } + else if ( shape->status[b->pt] == -1 ) // ok + { + path_a = 1; + path_b = -1; + } + else if ( shape->status[a->pt] == 1 && shape->status[b->pt] == 1 ) + { + path_a = -1; + path_b = -1; + } + else if ( shape->status[a->pt] == 1 ) + { + path_a = 1; + path_b = -1; + } + else if ( shape->status[b->pt] == 1 ) + { + path_a = -1; + path_b = 1; + } + else + { + std::cout << "OULALA C EST UN PROBLEMEM CA!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl; + path_a = 0; + path_b = 0; + } #ifdef _DEBUG_FULL_ - std::cout << "Path_a: " << path_a << std::endl; - std::cout << "Path_b: " << path_b << std::endl; + std::cout << "Path_a: " << path_a << std::endl; + std::cout << "Path_b: " << path_b << std::endl; #endif - nbPtPathA = shape->getPath ( (b->pt + 1) % shape->nbPoints, - a->pt, - &path_a); + nbPtPathA = shape->getPath(( b->pt + 1 ) % shape->nbPoints, + a->pt, + &path_a ); - nbPtPathB = shape->getPath ( (a->pt + 1) % shape->nbPoints, - (b->pt + 1) % shape->nbPoints, - &path_b); + nbPtPathB = shape->getPath(( a->pt + 1 ) % shape->nbPoints, + ( b->pt + 1 ) % shape->nbPoints, + &path_b ); - if (a->pt != b->pt) { - nbPtPathA++; - } + if ( a->pt != b->pt ) + { + nbPtPathA++; + } #ifdef _DEBUG_FULL_ - std::cout << "Path_a: " << path_a << std::endl; - std::cout << "Path_b: " << path_b << std::endl; + std::cout << "Path_a: " << path_a << std::endl; + std::cout << "Path_b: " << path_b << std::endl; #endif - PointSet *newShape = NULL; - Crossing *tmp; - if ( (a->pt == b->pt) && (a->way == 1)) { - tmp = a; - a = b; - b = tmp; - } - // split shape into two new shape - if ( (newShape = shape->extractPath (path_a, nbPtPathA, nbBboxPoint, bbx, bby, b, a, (b->pt + 1) % shape->nbPoints))) { - if (path_a == -1) { // new shape inside => push into shapes_final - shapes_final->push_back (newShape); - } else { // to drop or to resplit... - shapes_toProcess->push_back (newShape); - } - } - - if ( (newShape = shape->extractPath (path_b, nbPtPathB, nbBboxPoint, bbx, bby, a, b, (a->pt + 1) % shape->nbPoints))) { - if (path_b == -1) { - shapes_final->push_back (newShape); - } else { - shapes_toProcess->push_back (newShape); - } - } - - delete shape; - } else { - if (vabs (a->x - shape->x[a->pt]) < 0.00001 && vabs (a->y - shape->y[a->pt]) < 0.00001) { - shape->status[a->pt] = a->seg + 10; - } - if (vabs (a->x - shape->x[ (a->pt+1) %shape->nbPoints]) < 0.00001 && vabs (a->y - shape->y[ (a->pt+1) %shape->nbPoints]) < 0.00001) { - shape->status[a->pt] = a->seg + 10; - } - if (vabs (a->x - shape->x[b->pt]) < 0.00001 && vabs (a->y - shape->y[b->pt]) < 0.00001) { - shape->status[a->pt] = a->seg + 10; - } - if (vabs (a->x - shape->x[ (b->pt+1) %shape->nbPoints]) < 0.00001 && vabs (a->y - shape->y[ (b->pt+1) %shape->nbPoints]) < 0.00001) { - shape->status[a->pt] = a->seg + 10; - } - - shapes_toProcess->push_back (shape); - } - } else if (nbCrossingIter == 1 || crossingTabSize == 1) { // First shape dont cross the bbox => outside or bbox is inside shape - bool check = false, ok = false; - - if (crossingTabSize == 1) { - std::cout << "WARN : one crossing !!!!! " << std::endl; - bool in = true; - bool out = true; - for (i = 0;i < shape->nbPoints;i++) { + PointSet *newShape = NULL; + Crossing *tmp; + if (( a->pt == b->pt ) && ( a->way == 1 ) ) + { + tmp = a; + a = b; + b = tmp; + } + // split shape into two new shape + if (( newShape = shape->extractPath( path_a, nbPtPathA, nbBboxPoint, bbx, bby, b, a, ( b->pt + 1 ) % shape->nbPoints ) ) ) + { + if ( path_a == -1 ) // new shape inside => push into shapes_final + { + shapes_final->push_back( newShape ); + } + else // to drop or to resplit... + { + shapes_toProcess->push_back( newShape ); + } + } + + if (( newShape = shape->extractPath( path_b, nbPtPathB, nbBboxPoint, bbx, bby, a, b, ( a->pt + 1 ) % shape->nbPoints ) ) ) + { + if ( path_b == -1 ) + { + shapes_final->push_back( newShape ); + } + else + { + shapes_toProcess->push_back( newShape ); + } + } + + delete shape; + } + else + { + if ( vabs( a->x - shape->x[a->pt] ) < 0.00001 && vabs( a->y - shape->y[a->pt] ) < 0.00001 ) + { + shape->status[a->pt] = a->seg + 10; + } + if ( vabs( a->x - shape->x[( a->pt+1 ) %shape->nbPoints] ) < 0.00001 && vabs( a->y - shape->y[( a->pt+1 ) %shape->nbPoints] ) < 0.00001 ) + { + shape->status[a->pt] = a->seg + 10; + } + if ( vabs( a->x - shape->x[b->pt] ) < 0.00001 && vabs( a->y - shape->y[b->pt] ) < 0.00001 ) + { + shape->status[a->pt] = a->seg + 10; + } + if ( vabs( a->x - shape->x[( b->pt+1 ) %shape->nbPoints] ) < 0.00001 && vabs( a->y - shape->y[( b->pt+1 ) %shape->nbPoints] ) < 0.00001 ) + { + shape->status[a->pt] = a->seg + 10; + } + + shapes_toProcess->push_back( shape ); + } + } + else if ( nbCrossingIter == 1 || crossingTabSize == 1 ) // First shape dont cross the bbox => outside or bbox is inside shape + { + bool check = false, ok = false; + + if ( crossingTabSize == 1 ) + { + std::cout << "WARN : one crossing !!!!! " << std::endl; + bool in = true; + bool out = true; + for ( i = 0;i < shape->nbPoints;i++ ) + { #ifdef _DEBUG_FULL_ - std::cout << shape->x[i] << ";" << shape->y[i] << ";" << shape->status[i] << std::endl; + std::cout << shape->x[i] << ";" << shape->y[i] << ";" << shape->status[i] << std::endl; #endif - if (shape->status[i] == -1) { - out = false; - } else if (shape->status[i] == 1) { - in = false; - } - } - - if (in) { - // shape is totally inside - shapes_final->push_back (shape); - ok = true; - } else - check = true; - - } else - check = true; - - if (check && isPointInPolygon (shape->nbPoints, - shape->x, shape->y, - (bbx[0] + bbx[2]) / 2, - (bby[0] + bby[2]) / 2)) { - // bbox is inside the shape => reduce shape to bbox - delete[] shape->status; - delete[] shape->x; - delete[] shape->y; - shape->status = new int[4]; - shape->x = new double[4]; - shape->y = new double[4]; - shape->nbPoints = 4; - for (i = 0;i < 4;i++) { - shape->status[i] = 0; - shape->x[i] = bbx[i]; - shape->y[i] = bby[i]; - } - shapes_final->push_back (shape); // keep the bbox as shape - } else if (ok == false) - delete shape; - } else { - int stat = -1; - for (i = 0;i < shape->nbPoints;i++) { - if (shape->status[i] == 1) { - stat = 1; - break; - } - } - if (stat > 0) - delete shape; - else - shapes_final->push_back (shape); + if ( shape->status[i] == -1 ) + { + out = false; + } + else if ( shape->status[i] == 1 ) + { + in = false; } + } - for (i = 0;i < crossingTabSize;i++) - delete crossingTab[i]; - delete[] crossingTab; + if ( in ) + { + // shape is totally inside + shapes_final->push_back( shape ); + ok = true; + } + else + check = true; + + } + else + check = true; + + if ( check && isPointInPolygon( shape->nbPoints, + shape->x, shape->y, + ( bbx[0] + bbx[2] ) / 2, + ( bby[0] + bby[2] ) / 2 ) ) + { + // bbox is inside the shape => reduce shape to bbox + delete[] shape->status; + delete[] shape->x; + delete[] shape->y; + shape->status = new int[4]; + shape->x = new double[4]; + shape->y = new double[4]; + shape->nbPoints = 4; + for ( i = 0;i < 4;i++ ) + { + shape->status[i] = 0; + shape->x[i] = bbx[i]; + shape->y[i] = bby[i]; + } + shapes_final->push_back( shape ); // keep the bbox as shape } + else if ( ok == false ) + delete shape; + } + else + { + int stat = -1; + for ( i = 0;i < shape->nbPoints;i++ ) + { + if ( shape->status[i] == 1 ) + { + stat = 1; + break; + } + } + if ( stat > 0 ) + delete shape; + else + shapes_final->push_back( shape ); + } - delete shapes_toProcess; - delete crossings; + for ( i = 0;i < crossingTabSize;i++ ) + delete crossingTab[i]; + delete[] crossingTab; } + + delete shapes_toProcess; + delete crossings; + } //#undef _DEBUG_ //#undef _DEBUG_FULL_ - PointSet* PointSet::extractShape (int nbPtSh, int imin, int imax, int fps, int fpe, double fptx, double fpty) { + PointSet* PointSet::extractShape( int nbPtSh, int imin, int imax, int fps, int fpe, double fptx, double fpty ) + { - int i, j; + int i, j; - PointSet *newShape = new PointSet(); + PointSet *newShape = new PointSet(); - newShape->type = GEOS_POLYGON; + newShape->type = GEOS_POLYGON; - newShape->nbPoints = nbPtSh; + newShape->nbPoints = nbPtSh; - newShape->x = new double[newShape->nbPoints]; - newShape->y = new double[newShape->nbPoints]; - newShape->status = NULL; + newShape->x = new double[newShape->nbPoints]; + newShape->y = new double[newShape->nbPoints]; + newShape->status = NULL; #ifdef _DEBUG_FULL_ - std::cout << "New shape: "; + std::cout << "New shape: "; #endif - // new shape # 1 from imin to imax - for (j = 0, i = imin;i != (imax + 1) % nbPoints;i = (i + 1) % nbPoints, j++) { - newShape->x[j] = x[i]; - newShape->y[j] = y[i]; + // new shape # 1 from imin to imax + for ( j = 0, i = imin;i != ( imax + 1 ) % nbPoints;i = ( i + 1 ) % nbPoints, j++ ) + { + newShape->x[j] = x[i]; + newShape->y[j] = y[i]; #ifdef _DEBUG_FULL_ - std::cout << x[i] << ";" << y[i] << std::endl; + std::cout << x[i] << ";" << y[i] << std::endl; #endif - } - // is the cutting point a new one ? - if (fps != fpe) { - // yes => so add it - newShape->x[j] = fptx; - newShape->y[j] = fpty; + } + // is the cutting point a new one ? + if ( fps != fpe ) + { + // yes => so add it + newShape->x[j] = fptx; + newShape->y[j] = fpty; #ifdef _DEBUG_FULL_ - std::cout << fptx << ";" << fpty << std::endl; + std::cout << fptx << ";" << fpty << std::endl; #endif - } + } #ifdef _DEBUG_FULL_ - std::cout << "J = " << j << "/" << newShape->nbPoints << std::endl; - std::cout << std::endl; - std::cout << "This: " << this << std::endl; + std::cout << "J = " << j << "/" << newShape->nbPoints << std::endl; + std::cout << std::endl; + std::cout << "This: " << this << std::endl; #endif - return newShape; - } + return newShape; + } - void PointSet::splitPolygons (LinkedList *shapes_toProcess, - LinkedList *shapes_final, - double xrm, double yrm , char *uid) { + void PointSet::splitPolygons( LinkedList *shapes_toProcess, + LinkedList *shapes_final, + double xrm, double yrm , char *uid ) + { #ifdef _DEBUG_ - std::cout << "splitPolygons: " << uid << std::endl; + std::cout << "splitPolygons: " << uid << std::endl; #endif - int i, j; + int i, j; - int nbp; - double *x; - double *y; + int nbp; + double *x; + double *y; - int *pts; + int *pts; - int *cHull; - int cHullSize; + int *cHull; + int cHullSize; - double cp; - double bestcp = 0; + double cp; + double bestcp = 0; - double bestArea = 0; - double area; + double bestArea = 0; + double area; - double base; - double b, c; - double s; + double base; + double b, c; + double s; - int ihs; - int ihn; + int ihs; + int ihn; - int ips; - int ipn; + int ips; + int ipn; - int holeS = -1; // hole start and end points - int holeE = -1; + int holeS = -1; // hole start and end points + int holeE = -1; - int retainedPt = -1; - int pt = 0; + int retainedPt = -1; + int pt = 0; - double labelArea = xrm * yrm; + double labelArea = xrm * yrm; - PointSet *shape; + PointSet *shape; - while (shapes_toProcess->size() > 0) { + while ( shapes_toProcess->size() > 0 ) + { #ifdef _DEBUG_FULL_ - std::cout << "Shape popping()" << std::endl; + std::cout << "Shape popping()" << std::endl; #endif - shape = shapes_toProcess->pop_front(); + shape = shapes_toProcess->pop_front(); - x = shape->x; - y = shape->y; - nbp = shape->nbPoints; - pts = new int[nbp]; + x = shape->x; + y = shape->y; + nbp = shape->nbPoints; + pts = new int[nbp]; #ifdef _DEBUG_FULL_ - std::cout << "nbp: " << nbp << std::endl; - std::cout << " PtSet: "; + std::cout << "nbp: " << nbp << std::endl; + std::cout << " PtSet: "; #endif - for (i = 0;i < nbp;i++) { - pts[i] = i; + for ( i = 0;i < nbp;i++ ) + { + pts[i] = i; #ifdef _DEBUG_FULL_ - std::cout << x[i] << ";" << y[i] << std::endl; + std::cout << x[i] << ";" << y[i] << std::endl; #endif - } + } #ifdef _DEBUG_FULL_ - std::cout << std::endl; + std::cout << std::endl; #endif - // conpute convex hull - shape->cHullSize = convexHullId (pts, x, y, nbp, shape->cHull); + // conpute convex hull + shape->cHullSize = convexHullId( pts, x, y, nbp, shape->cHull ); - cHull = shape->cHull; - cHullSize = shape->cHullSize; + cHull = shape->cHull; + cHullSize = shape->cHullSize; #ifdef _DEBUG_FULL_ - std::cout << " CHull: "; - for (i = 0;i < cHullSize;i++) { - std::cout << cHull[i] << " "; - } - std::cout << std::endl; + std::cout << " CHull: "; + for ( i = 0;i < cHullSize;i++ ) + { + std::cout << cHull[i] << " "; + } + std::cout << std::endl; #endif - bestArea = 0; - retainedPt = -1; - - // lookup for a hole - for (ihs = 0;ihs < cHullSize;ihs++) { - // ihs->ihn => cHull'seg - ihn = (ihs + 1) % cHullSize; - - ips = cHull[ihs]; - ipn = (ips + 1) % nbp; - if (ipn != cHull[ihn]) { // next point on shape is not the next point on cHull => there is a hole here ! - bestcp = 0; - pt = -1; - // lookup for the deepest point in the hole - for (i = ips;i != cHull[ihn];i = (i + 1) % nbp) { - cp = vabs (cross_product (x[cHull[ihs]], y[cHull[ihs]], - x[cHull[ihn]], y[cHull[ihn]], - x[i], y[i])); - if (cp - bestcp > EPSILON) { - bestcp = cp; - pt = i; - } - } + bestArea = 0; + retainedPt = -1; + + // lookup for a hole + for ( ihs = 0;ihs < cHullSize;ihs++ ) + { + // ihs->ihn => cHull'seg + ihn = ( ihs + 1 ) % cHullSize; + + ips = cHull[ihs]; + ipn = ( ips + 1 ) % nbp; + if ( ipn != cHull[ihn] ) // next point on shape is not the next point on cHull => there is a hole here ! + { + bestcp = 0; + pt = -1; + // lookup for the deepest point in the hole + for ( i = ips;i != cHull[ihn];i = ( i + 1 ) % nbp ) + { + cp = vabs( cross_product( x[cHull[ihs]], y[cHull[ihs]], + x[cHull[ihn]], y[cHull[ihn]], + x[i], y[i] ) ); + if ( cp - bestcp > EPSILON ) + { + bestcp = cp; + pt = i; + } + } #ifdef _DEBUG_FULL_ - std::cout << "Deeper POint: " << pt << " between " << ips << " and " << cHull[ihn] << std::endl; + std::cout << "Deeper POint: " << pt << " between " << ips << " and " << cHull[ihn] << std::endl; #endif - if (pt != -1) { - // compute the ihs->ihn->pt triangle's area - base = dist_euc2d (x[cHull[ihs]], y[cHull[ihs]], - x[cHull[ihn]], y[cHull[ihn]]); - - b = dist_euc2d (x[cHull[ihs]], y[cHull[ihs]], - x[pt], y[pt]); - - c = dist_euc2d (x[cHull[ihn]], y[cHull[ihn]], - x[pt], y[pt]); - - s = (base + b + c) / 2; // s = half perimeter - area = s * (s - base) * (s - b) * (s - c); - if (area < 0) - area = -area; - - // retain the biggest area - if (area - bestArea > EPSILON) { - bestArea = area; - retainedPt = pt; - holeS = ihs; - holeE = ihn; - } - } - } + if ( pt != -1 ) + { + // compute the ihs->ihn->pt triangle's area + base = dist_euc2d( x[cHull[ihs]], y[cHull[ihs]], + x[cHull[ihn]], y[cHull[ihn]] ); + + b = dist_euc2d( x[cHull[ihs]], y[cHull[ihs]], + x[pt], y[pt] ); + + c = dist_euc2d( x[cHull[ihn]], y[cHull[ihn]], + x[pt], y[pt] ); + + s = ( base + b + c ) / 2; // s = half perimeter + area = s * ( s - base ) * ( s - b ) * ( s - c ); + if ( area < 0 ) + area = -area; + + // retain the biggest area + if ( area - bestArea > EPSILON ) + { + bestArea = area; + retainedPt = pt; + holeS = ihs; + holeE = ihn; } - - // we have a hole, its area, and the deppest point in hole - // we're going to find the second point to cup the shape - // holeS = hole starting point - // holeE = hole ending point - // retainedPt = deppest point in hole - // bestArea = area of triangle HoleS->holeE->retainedPoint - bestArea = sqrt (bestArea); - double cx, cy, dx, dy, ex, ey, fx, fy, seg_length, ptx, pty, fptx = 0, fpty = 0; - int ps = -1, pe = -1, fps = -1, fpe = -1; - if (retainedPt >= 0 && bestArea > labelArea) { // there is a hole so we'll cut the shape in two new shape (only if hole area is bigger than twice labelArea) + } + } + } + + // we have a hole, its area, and the deppest point in hole + // we're going to find the second point to cup the shape + // holeS = hole starting point + // holeE = hole ending point + // retainedPt = deppest point in hole + // bestArea = area of triangle HoleS->holeE->retainedPoint + bestArea = sqrt( bestArea ); + double cx, cy, dx, dy, ex, ey, fx, fy, seg_length, ptx, pty, fptx = 0, fpty = 0; + int ps = -1, pe = -1, fps = -1, fpe = -1; + if ( retainedPt >= 0 && bestArea > labelArea ) // there is a hole so we'll cut the shape in two new shape (only if hole area is bigger than twice labelArea) + { #ifdef _DEBUG_FULL_ - std::cout << "Trou: " << retainedPt << std::endl; - std::cout << "Hole: " << cHull[holeS] << " -> " << cHull[holeE] << std::endl; - std::cout << "iterate from " << (cHull[holeE] + 1) % nbp << " to " << (cHull[holeS] - 1 + nbp) % nbp << std::endl; + std::cout << "Trou: " << retainedPt << std::endl; + std::cout << "Hole: " << cHull[holeS] << " -> " << cHull[holeE] << std::endl; + std::cout << "iterate from " << ( cHull[holeE] + 1 ) % nbp << " to " << ( cHull[holeS] - 1 + nbp ) % nbp << std::endl; #endif - c = DBL_MAX; - - - // iterate on all shape points except points which are in the hole - double isValid; - int k, l; - for (i = (cHull[holeE] + 1) % nbp;i != (cHull[holeS] - 1 + nbp) % nbp;i = j) { - j = (i + 1) % nbp; // i->j is shape segment not in hole - - // compute distance between retainedPoint and segment - // whether perpendicular distance (if retaindPoint is fronting segment i->j) - // or distance between retainedPt and i or j (choose the nearest) - seg_length = dist_euc2d (x[i], y[i], x[j], y[j]); - cx = (x[i] + x[j]) / 2.0; - cy = (y[i] + y[j]) / 2.0; - dx = cy - y[i]; - dy = cx - x[i]; - - ex = cx - dx; - ey = cy + dy; - fx = cx + dx; - fy = cy - dy; + c = DBL_MAX; + + + // iterate on all shape points except points which are in the hole + double isValid; + int k, l; + for ( i = ( cHull[holeE] + 1 ) % nbp;i != ( cHull[holeS] - 1 + nbp ) % nbp;i = j ) + { + j = ( i + 1 ) % nbp; // i->j is shape segment not in hole + + // compute distance between retainedPoint and segment + // whether perpendicular distance (if retaindPoint is fronting segment i->j) + // or distance between retainedPt and i or j (choose the nearest) + seg_length = dist_euc2d( x[i], y[i], x[j], y[j] ); + cx = ( x[i] + x[j] ) / 2.0; + cy = ( y[i] + y[j] ) / 2.0; + dx = cy - y[i]; + dy = cx - x[i]; + + ex = cx - dx; + ey = cy + dy; + fx = cx + dx; + fy = cy - dy; #ifdef _DEBUG_FULL_ - std::cout << "D: " << dx << " " << dy << std::endl; - std::cout << "seg_length: " << seg_length << std::endl; + std::cout << "D: " << dx << " " << dy << std::endl; + std::cout << "seg_length: " << seg_length << std::endl; #endif - if (seg_length < EPSILON || vabs ( (b = cross_product (ex, ey, fx, fy, x[retainedPt], y[retainedPt]) / (seg_length))) > (seg_length / 2)) { // retainedPt is not fronting i->j - if ( (ex = dist_euc2d_sq (x[i], y[i], x[retainedPt], y[retainedPt])) < (ey = dist_euc2d_sq (x[j], y[j], x[retainedPt], y[retainedPt]))) { - b = ex; - ps = i; - pe = i; - } else { - b = ey; - ps = j; - pe = j; - } - } else { // point fronting i->j => compute pependicular distance => create a new point - b = cross_product (x[i], y[i], x[j], y[j], x[retainedPt], y[retainedPt]) / seg_length; - b *= b; - ps = i; - pe = j; - - if (!computeLineIntersection (x[i], y[i], x[j], y[j], x[retainedPt], y[retainedPt], x[retainedPt] - dx, y[retainedPt] + dy, &ptx, &pty)) { - std::cout << "Oups ... il devrait par tomber la..." << std::endl; - } + if ( seg_length < EPSILON || vabs(( b = cross_product( ex, ey, fx, fy, x[retainedPt], y[retainedPt] ) / ( seg_length ) ) ) > ( seg_length / 2 ) ) // retainedPt is not fronting i->j + { + if (( ex = dist_euc2d_sq( x[i], y[i], x[retainedPt], y[retainedPt] ) ) < ( ey = dist_euc2d_sq( x[j], y[j], x[retainedPt], y[retainedPt] ) ) ) + { + b = ex; + ps = i; + pe = i; + } + else + { + b = ey; + ps = j; + pe = j; + } + } + else // point fronting i->j => compute pependicular distance => create a new point + { + b = cross_product( x[i], y[i], x[j], y[j], x[retainedPt], y[retainedPt] ) / seg_length; + b *= b; + ps = i; + pe = j; + + if ( !computeLineIntersection( x[i], y[i], x[j], y[j], x[retainedPt], y[retainedPt], x[retainedPt] - dx, y[retainedPt] + dy, &ptx, &pty ) ) + { + std::cout << "Oups ... il devrait par tomber la..." << std::endl; + } #ifdef _DEBUG_FULL_ - std::cout << "intersection : " << x[i] << " " << y[i] << " " << x[j] << " " << y[j] << " " << x[retainedPt] << " " << y[retainedPt] << " " << x[retainedPt] - dx << " " << y[retainedPt] + dy << std::endl; - std::cout << " => " << ptx << ";" << pty << std::endl; - std::cout << " cxy> " << cx << ";" << cy << std::endl; - std::cout << " dxy> " << dx << ";" << dy << std::endl; + std::cout << "intersection : " << x[i] << " " << y[i] << " " << x[j] << " " << y[j] << " " << x[retainedPt] << " " << y[retainedPt] << " " << x[retainedPt] - dx << " " << y[retainedPt] + dy << std::endl; + std::cout << " => " << ptx << ";" << pty << std::endl; + std::cout << " cxy> " << cx << ";" << cy << std::endl; + std::cout << " dxy> " << dx << ";" << dy << std::endl; #endif - } - - isValid = true; - double pointX, pointY; - if (ps == pe) { - pointX = x[pe]; - pointY = y[pe]; - } else { - pointX = ptx; - pointY = pty; - } - - for (k = cHull[holeS];k != cHull[holeE];k = (k + 1) % nbp) { - l = (k + 1) % nbp; - //std::cout << "test " << k << " " << l << std::endl; - if (isSegIntersects (x[retainedPt], y[retainedPt], pointX, pointY, x[k], y[k], x[l], y[l])) { - isValid = false; - //std::cout << "Invalid point" << pe << ps << std::endl; - break; - } - } - - - if (isValid && b < c) { - //std::cout << "new point: " << ps << " " << pe << std::endl; - c = b; - fps = ps; - fpe = pe; - fptx = ptx; - fpty = pty; - } - } // for point which are not in hole + } + + isValid = true; + double pointX, pointY; + if ( ps == pe ) + { + pointX = x[pe]; + pointY = y[pe]; + } + else + { + pointX = ptx; + pointY = pty; + } + + for ( k = cHull[holeS];k != cHull[holeE];k = ( k + 1 ) % nbp ) + { + l = ( k + 1 ) % nbp; + //std::cout << "test " << k << " " << l << std::endl; + if ( isSegIntersects( x[retainedPt], y[retainedPt], pointX, pointY, x[k], y[k], x[l], y[l] ) ) + { + isValid = false; + //std::cout << "Invalid point" << pe << ps << std::endl; + break; + } + } + + + if ( isValid && b < c ) + { + //std::cout << "new point: " << ps << " " << pe << std::endl; + c = b; + fps = ps; + fpe = pe; + fptx = ptx; + fpty = pty; + } + } // for point which are not in hole #ifdef _DEBUG_FULL_ - std::cout << " cut from " << retainedPt << " to "; - if (fps == fpe) - std::cout << "point " << fps << std::endl; - else { - std::cout << "new point (" << fptx << ";" << fpty << " between " << fps << " and " << fpe << std::endl; - } + std::cout << " cut from " << retainedPt << " to "; + if ( fps == fpe ) + std::cout << "point " << fps << std::endl; + else + { + std::cout << "new point (" << fptx << ";" << fpty << " between " << fps << " and " << fpe << std::endl; + } #endif - // we will cut the shapeu in two new shapes, one from [retainedPoint] to [newPoint] and one form [newPoint] to [retainedPoint] - int imin = retainedPt; - int imax = ( ( (fps < retainedPt && fpe < retainedPt) || (fps > retainedPt && fpe > retainedPt)) ? min (fps, fpe) : max (fps, fpe)); + // we will cut the shapeu in two new shapes, one from [retainedPoint] to [newPoint] and one form [newPoint] to [retainedPoint] + int imin = retainedPt; + int imax = ((( fps < retainedPt && fpe < retainedPt ) || ( fps > retainedPt && fpe > retainedPt ) ) ? min( fps, fpe ) : max( fps, fpe ) ); - int nbPtSh1, nbPtSh2; // how many points in new shapes ? - if (imax > imin) - nbPtSh1 = imax - imin + 1 + (fpe != fps); - else - nbPtSh1 = imax + nbp - imin + 1 + (fpe != fps); + int nbPtSh1, nbPtSh2; // how many points in new shapes ? + if ( imax > imin ) + nbPtSh1 = imax - imin + 1 + ( fpe != fps ); + else + nbPtSh1 = imax + nbp - imin + 1 + ( fpe != fps ); - if ( (imax == fps ? fpe : fps) < imin) - nbPtSh2 = imin - (imax == fps ? fpe : fps) + 1 + (fpe != fps); - else - nbPtSh2 = imin + nbp - (imax == fps ? fpe : fps) + 1 + (fpe != fps); + if (( imax == fps ? fpe : fps ) < imin ) + nbPtSh2 = imin - ( imax == fps ? fpe : fps ) + 1 + ( fpe != fps ); + else + nbPtSh2 = imin + nbp - ( imax == fps ? fpe : fps ) + 1 + ( fpe != fps ); #ifdef _DEBUG_FULL_ - std::cout << "imin: " << imin << " imax:" << imax << std::endl; + std::cout << "imin: " << imin << " imax:" << imax << std::endl; #endif - if (retainedPt == -1 || fps == -1 || fpe == -1) { + if ( retainedPt == -1 || fps == -1 || fpe == -1 ) + { #ifdef _DEBUG_ - std::cout << std::endl << "Failed to split feature !!! (uid=" << uid << ")" << std::endl; + std::cout << std::endl << "Failed to split feature !!! (uid=" << uid << ")" << std::endl; #endif - if (shape->parent) - delete shape; - } - // check for useless spliting - else if (imax == imin || nbPtSh1 <= 2 || nbPtSh2 <= 2 || nbPtSh1 == nbp || nbPtSh2 == nbp) { - shapes_final->push_back (shape); - } else { + if ( shape->parent ) + delete shape; + } + // check for useless spliting + else if ( imax == imin || nbPtSh1 <= 2 || nbPtSh2 <= 2 || nbPtSh1 == nbp || nbPtSh2 == nbp ) + { + shapes_final->push_back( shape ); + } + else + { - PointSet *newShape = shape->extractShape (nbPtSh1, imin, imax, fps, fpe, fptx, fpty); + PointSet *newShape = shape->extractShape( nbPtSh1, imin, imax, fps, fpe, fptx, fpty ); - if (shape->parent) - newShape->parent = shape->parent; - else - newShape->parent = shape; + if ( shape->parent ) + newShape->parent = shape->parent; + else + newShape->parent = shape; #ifdef _DEBUG_FULL_ - int i = 0; - std::cout << "push back:" << std::endl; - for (i = 0;i < newShape->nbPoints;i++) { - std::cout << newShape->x[i] << ";" << newShape->y[i] << std::endl; - } + int i = 0; + std::cout << "push back:" << std::endl; + for ( i = 0;i < newShape->nbPoints;i++ ) + { + std::cout << newShape->x[i] << ";" << newShape->y[i] << std::endl; + } #endif - shapes_toProcess->push_back (newShape); + shapes_toProcess->push_back( newShape ); - if (imax == fps) - imax = fpe; - else - imax = fps; + if ( imax == fps ) + imax = fpe; + else + imax = fps; - newShape = shape->extractShape (nbPtSh2, imax, imin, fps, fpe, fptx, fpty); + newShape = shape->extractShape( nbPtSh2, imax, imin, fps, fpe, fptx, fpty ); - if (shape->parent) - newShape->parent = shape->parent; - else - newShape->parent = shape; + if ( shape->parent ) + newShape->parent = shape->parent; + else + newShape->parent = shape; #ifdef _DEBUG_FULL_ - std::cout << "push back:" << std::endl; - for (i = 0;i < newShape->nbPoints;i++) { - std::cout << newShape->x[i] << ";" << newShape->y[i] << std::endl; - } + std::cout << "push back:" << std::endl; + for ( i = 0;i < newShape->nbPoints;i++ ) + { + std::cout << newShape->x[i] << ";" << newShape->y[i] << std::endl; + } #endif - shapes_toProcess->push_back (newShape); + shapes_toProcess->push_back( newShape ); - if (shape->parent) - delete shape; - } - } else { + if ( shape->parent ) + delete shape; + } + } + else + { #ifdef _DEBUG_FULL_ - std::cout << "Put shape into shapes_final" << std::endl; + std::cout << "Put shape into shapes_final" << std::endl; #endif - shapes_final->push_back (shape); - } - delete[] pts; - } + shapes_final->push_back( shape ); + } + delete[] pts; } + } - PointSet * PointSet::createProblemSpecificPointSet (double bbx[4], double bby[4], bool *outside, bool *inside) { - int i; + PointSet * PointSet::createProblemSpecificPointSet( double bbx[4], double bby[4], bool *outside, bool *inside ) + { + int i; #ifdef _DEBUG_FULL_ - std::cout << "CreateProblemSpecific:" << std::endl; + std::cout << "CreateProblemSpecific:" << std::endl; #endif - PointSet *shape = new PointSet(); - shape->status = new int[nbPoints]; - shape->x = new double[nbPoints]; - shape->y = new double[nbPoints]; - shape->nbPoints = nbPoints; - shape->type = type; - - shape->xmin = xmin; - shape->xmax = xmax; - shape->ymin = ymin; - shape->ymax = ymax; - - *outside = true; - *inside = true; - - // Build PointSet from geom => (x,y) coord, status[i] -> -1 inside, 1 outside , 0 on border - - double epsilon = 0.000001; - for (i = 0;i < nbPoints;i++) { - shape->x[i] = this->x[i]; - shape->y[i] = this->y[i]; - - double cp0 = cross_product (bbx[0], bby[0], bbx[1], bby[1], - shape->x[i], shape->y[i]); - double cp1 = cross_product (bbx[1], bby[1], bbx[2], bby[2], - shape->x[i], shape->y[i]); - double cp2 = cross_product (bbx[2], bby[2], bbx[3], bby[3], - shape->x[i], shape->y[i]); - double cp3 = cross_product (bbx[3], bby[3], bbx[0], bby[0], - shape->x[i], shape->y[i]); - - if (cp0 > epsilon && cp1 > epsilon && cp2 > epsilon && cp3 > epsilon) { - shape->status[i] = -1; // point is inside the map extent - *outside = false; - } else if (vabs (cp0) < epsilon && cp1 > epsilon && cp2 > epsilon && cp3 > epsilon) { - shape->status[i] = 10; // Point is on the bottom border - *outside = false; - } else if (cp0 > epsilon && vabs (cp1) < epsilon && cp2 > epsilon && cp3 > epsilon) { - shape->status[i] = 11; // point is on the right border - *outside = false; - } else if (cp0 > epsilon && cp1 > epsilon && vabs (cp2) < epsilon && cp3 > epsilon) { - shape->status[i] = 12; // point is on the top border - *outside = false; - } else if (cp0 > epsilon && cp1 > epsilon && cp2 > epsilon && vabs (cp3) < epsilon) { - shape->status[i] = 13; // point is on the left border - *outside = false; - } else if (vabs (cp0) < epsilon && vabs (cp1) < epsilon && cp2 > epsilon && cp3 > epsilon) { - shape->status[i] = 15; // point is on the bottom right corner - *outside = false; - } else if (cp0 > epsilon && vabs (cp1) < epsilon && vabs (cp2) < epsilon && cp3 > epsilon) { - shape->status[i] = 15; // point is on the top right corner - *outside = false; - } else if (cp0 > epsilon && cp1 > epsilon && vabs (cp2) < epsilon && vabs (cp3) < epsilon) { - shape->status[i] = 15; // point is on the top left corner - *outside = false; - } else if (vabs (cp0) < epsilon && cp1 > epsilon && cp2 > epsilon && vabs (cp3) < epsilon) { - shape->status[i] = 15; // point is on the bottom left corner - *outside = false; - } else { - shape->status[i] = 1; // point is not in the map extent - *inside = false; - } + PointSet *shape = new PointSet(); + shape->status = new int[nbPoints]; + shape->x = new double[nbPoints]; + shape->y = new double[nbPoints]; + shape->nbPoints = nbPoints; + shape->type = type; + + shape->xmin = xmin; + shape->xmax = xmax; + shape->ymin = ymin; + shape->ymax = ymax; + + *outside = true; + *inside = true; + + // Build PointSet from geom => (x,y) coord, status[i] -> -1 inside, 1 outside , 0 on border + + double epsilon = 0.000001; + for ( i = 0;i < nbPoints;i++ ) + { + shape->x[i] = this->x[i]; + shape->y[i] = this->y[i]; + + double cp0 = cross_product( bbx[0], bby[0], bbx[1], bby[1], + shape->x[i], shape->y[i] ); + double cp1 = cross_product( bbx[1], bby[1], bbx[2], bby[2], + shape->x[i], shape->y[i] ); + double cp2 = cross_product( bbx[2], bby[2], bbx[3], bby[3], + shape->x[i], shape->y[i] ); + double cp3 = cross_product( bbx[3], bby[3], bbx[0], bby[0], + shape->x[i], shape->y[i] ); + + if ( cp0 > epsilon && cp1 > epsilon && cp2 > epsilon && cp3 > epsilon ) + { + shape->status[i] = -1; // point is inside the map extent + *outside = false; + } + else if ( vabs( cp0 ) < epsilon && cp1 > epsilon && cp2 > epsilon && cp3 > epsilon ) + { + shape->status[i] = 10; // Point is on the bottom border + *outside = false; + } + else if ( cp0 > epsilon && vabs( cp1 ) < epsilon && cp2 > epsilon && cp3 > epsilon ) + { + shape->status[i] = 11; // point is on the right border + *outside = false; + } + else if ( cp0 > epsilon && cp1 > epsilon && vabs( cp2 ) < epsilon && cp3 > epsilon ) + { + shape->status[i] = 12; // point is on the top border + *outside = false; + } + else if ( cp0 > epsilon && cp1 > epsilon && cp2 > epsilon && vabs( cp3 ) < epsilon ) + { + shape->status[i] = 13; // point is on the left border + *outside = false; + } + else if ( vabs( cp0 ) < epsilon && vabs( cp1 ) < epsilon && cp2 > epsilon && cp3 > epsilon ) + { + shape->status[i] = 15; // point is on the bottom right corner + *outside = false; + } + else if ( cp0 > epsilon && vabs( cp1 ) < epsilon && vabs( cp2 ) < epsilon && cp3 > epsilon ) + { + shape->status[i] = 15; // point is on the top right corner + *outside = false; + } + else if ( cp0 > epsilon && cp1 > epsilon && vabs( cp2 ) < epsilon && vabs( cp3 ) < epsilon ) + { + shape->status[i] = 15; // point is on the top left corner + *outside = false; + } + else if ( vabs( cp0 ) < epsilon && cp1 > epsilon && cp2 > epsilon && vabs( cp3 ) < epsilon ) + { + shape->status[i] = 15; // point is on the bottom left corner + *outside = false; + } + else + { + shape->status[i] = 1; // point is not in the map extent + *inside = false; + } #ifdef _DEBUG_FULL_ - std::cout << shape->x[i] << ";" << shape->y[i] << ";" << shape->status[i] << ";" << cp0 << ";" << cp1 << ";" << cp2 << ";" << cp3 << std::endl; + std::cout << shape->x[i] << ";" << shape->y[i] << ";" << shape->status[i] << ";" << cp0 << ";" << cp1 << ";" << cp2 << ";" << cp3 << std::endl; #endif - } + } - shape->holeOf = NULL; - shape->parent = NULL; + shape->holeOf = NULL; + shape->parent = NULL; - return shape; - } + return shape; + } - CHullBox * PointSet::compute_chull_bbox () { - int i; - int j; + CHullBox * PointSet::compute_chull_bbox() + { + int i; + int j; - double bbox[4]; // xmin, ymin, xmax, ymax + double bbox[4]; // xmin, ymin, xmax, ymax - double alpha; - int alpha_d; + double alpha; + int alpha_d; - double alpha_seg; + double alpha_seg; - double dref; - double d1, d2; + double dref; + double d1, d2; - double bb[16]; // {ax, ay, bx, by, cx, cy, dx, dy, ex, ey, fx, fy, gx, gy, hx, hy}} + double bb[16]; // {ax, ay, bx, by, cx, cy, dx, dy, ex, ey, fx, fy, gx, gy, hx, hy}} - double cp; - double best_cp; - double distNearestPoint; - int nearestPoint; + double cp; + double best_cp; + double distNearestPoint; + int nearestPoint; - double area; - double width; - double length; + double area; + double width; + double length; - double best_area = DBL_MAX; - double best_alpha = -1; - double best_bb[16]; - double best_length = 0; - double best_width = 0; + double best_area = DBL_MAX; + double best_alpha = -1; + double best_bb[16]; + double best_length = 0; + double best_width = 0; - bbox[0] = DBL_MAX; - bbox[1] = DBL_MAX; - bbox[2] = - DBL_MAX; - bbox[3] = - DBL_MAX; + bbox[0] = DBL_MAX; + bbox[1] = DBL_MAX; + bbox[2] = - DBL_MAX; + bbox[3] = - DBL_MAX; #ifdef _DEBUG_ - std::cout << "Compute_chull_bbox" << std::endl; + std::cout << "Compute_chull_bbox" << std::endl; #endif - for (i = 0;i < cHullSize;i++) { + for ( i = 0;i < cHullSize;i++ ) + { #ifdef _DEBUG_FULL_ - std::cout << x[cHull[i]] << ";" << y[cHull[i]] << std::endl; + std::cout << x[cHull[i]] << ";" << y[cHull[i]] << std::endl; #endif - if (x[cHull[i]] < bbox[0]) - bbox[0] = x[cHull[i]]; + if ( x[cHull[i]] < bbox[0] ) + bbox[0] = x[cHull[i]]; - if (x[cHull[i]] > bbox[2]) - bbox[2] = x[cHull[i]]; + if ( x[cHull[i]] > bbox[2] ) + bbox[2] = x[cHull[i]]; - if (y[cHull[i]] < bbox[1]) - bbox[1] = y[cHull[i]]; + if ( y[cHull[i]] < bbox[1] ) + bbox[1] = y[cHull[i]]; - if (y[cHull[i]] > bbox[3]) - bbox[3] = y[cHull[i]]; - } + if ( y[cHull[i]] > bbox[3] ) + bbox[3] = y[cHull[i]]; + } - dref = bbox[2] - bbox[0]; + dref = bbox[2] - bbox[0]; - for (alpha_d = 0; alpha_d < 90;alpha_d++) { - alpha = alpha_d * M_PI / 180.0; - d1 = cos (alpha) * dref; - d2 = sin (alpha) * dref; + for ( alpha_d = 0; alpha_d < 90;alpha_d++ ) + { + alpha = alpha_d * M_PI / 180.0; + d1 = cos( alpha ) * dref; + d2 = sin( alpha ) * dref; - bb[0] = bbox[0]; - bb[1] = bbox[3]; // ax, ay + bb[0] = bbox[0]; + bb[1] = bbox[3]; // ax, ay - bb[4] = bbox[0]; - bb[5] = bbox[1]; // cx, cy + bb[4] = bbox[0]; + bb[5] = bbox[1]; // cx, cy - bb[8] = bbox[2]; - bb[9] = bbox[1]; // ex, ey + bb[8] = bbox[2]; + bb[9] = bbox[1]; // ex, ey - bb[12] = bbox[2]; - bb[13] = bbox[3]; // gx, gy + bb[12] = bbox[2]; + bb[13] = bbox[3]; // gx, gy - bb[2] = bb[0] + d1; - bb[3] = bb[1] + d2; // bx, by - bb[6] = bb[4] - d2; - bb[7] = bb[5] + d1; // dx, dy - bb[10] = bb[8] - d1; - bb[11] = bb[9] - d2; // fx, fy - bb[14] = bb[12] + d2; - bb[15] = bb[13] - d1; // hx, hy + bb[2] = bb[0] + d1; + bb[3] = bb[1] + d2; // bx, by + bb[6] = bb[4] - d2; + bb[7] = bb[5] + d1; // dx, dy + bb[10] = bb[8] - d1; + bb[11] = bb[9] - d2; // fx, fy + bb[14] = bb[12] + d2; + bb[15] = bb[13] - d1; // hx, hy - // adjust all points - for (i = 0;i < 16;i += 4) { + // adjust all points + for ( i = 0;i < 16;i += 4 ) + { - alpha_seg = ( (i / 4 > 0 ? (i / 4) - 1 : 3)) * M_PI / 2 + alpha; + alpha_seg = (( i / 4 > 0 ? ( i / 4 ) - 1 : 3 ) ) * M_PI / 2 + alpha; - best_cp = DBL_MAX; - nearestPoint = -1; - for (j = 0;j < nbPoints;j++) { - cp = cross_product (bb[i+2], bb[i+3], bb[i], bb[i+1], x[cHull[j]], y[cHull[j]]); - if (cp < best_cp) { - best_cp = cp; - nearestPoint = cHull[j]; - } - } + best_cp = DBL_MAX; + nearestPoint = -1; + for ( j = 0;j < nbPoints;j++ ) + { + cp = cross_product( bb[i+2], bb[i+3], bb[i], bb[i+1], x[cHull[j]], y[cHull[j]] ); + if ( cp < best_cp ) + { + best_cp = cp; + nearestPoint = cHull[j]; + } + } - distNearestPoint = best_cp / dref; + distNearestPoint = best_cp / dref; - d1 = cos (alpha_seg) * distNearestPoint; - d2 = sin (alpha_seg) * distNearestPoint; + d1 = cos( alpha_seg ) * distNearestPoint; + d2 = sin( alpha_seg ) * distNearestPoint; - bb[i] += d1; // x - bb[i+1] += d2; // y - bb[i+2] += d1; // x - bb[i+3] += d2; // y - } + bb[i] += d1; // x + bb[i+1] += d2; // y + bb[i+2] += d1; // x + bb[i+3] += d2; // y + } - // compute and compare AREA - width = cross_product (bb[6], bb[7], bb[4], bb[5], bb[12], bb[13]) / dref; - length = cross_product (bb[2], bb[3], bb[0], bb[1], bb[8], bb[9]) / dref; + // compute and compare AREA + width = cross_product( bb[6], bb[7], bb[4], bb[5], bb[12], bb[13] ) / dref; + length = cross_product( bb[2], bb[3], bb[0], bb[1], bb[8], bb[9] ) / dref; - area = width * length; + area = width * length; - if (area < 0) - area *= -1; + if ( area < 0 ) + area *= -1; - if (best_area - area > EPSILON) { - best_area = area; - best_length = length; - best_width = width; - best_alpha = alpha; - memcpy (best_bb, bb, sizeof (double) *16); - } - } + if ( best_area - area > EPSILON ) + { + best_area = area; + best_length = length; + best_width = width; + best_alpha = alpha; + memcpy( best_bb, bb, sizeof( double ) *16 ); + } + } - // best bbox is defined + // best bbox is defined - CHullBox * finalBb = new CHullBox(); + CHullBox * finalBb = new CHullBox(); - for (i = 0;i < 16;i = i + 4) { - computeLineIntersection (best_bb[i], best_bb[i+1], best_bb[i+2], best_bb[i+3], - best_bb[ (i+4) %16], best_bb[ (i+5) %16], best_bb[ (i+6) %16], best_bb[ (i+7) %16], - &finalBb->x[int (i/4) ], &finalBb->y[int (i/4) ]); - } + for ( i = 0;i < 16;i = i + 4 ) + { + computeLineIntersection( best_bb[i], best_bb[i+1], best_bb[i+2], best_bb[i+3], + best_bb[( i+4 ) %16], best_bb[( i+5 ) %16], best_bb[( i+6 ) %16], best_bb[( i+7 ) %16], + &finalBb->x[int ( i/4 )], &finalBb->y[int ( i/4 )] ); + } - finalBb->alpha = best_alpha; - finalBb->width = best_width; - finalBb->length = best_length; + finalBb->alpha = best_alpha; + finalBb->width = best_width; + finalBb->length = best_length; #ifdef _DEBUG_FULL_ - std::cout << "FINAL" << std::endl; - std::cout << "Length : " << best_length << std::endl; - std::cout << "Width : " << best_width << std::endl; - std::cout << "Alpha: " << best_alpha << " " << best_alpha*180 / M_PI << std::endl; - for (i = 0;i < 4;i++) { - std::cout << finalBb->x[0] << " " << finalBb->y[0] << " "; - } - std::cout << std::endl; + std::cout << "FINAL" << std::endl; + std::cout << "Length : " << best_length << std::endl; + std::cout << "Width : " << best_width << std::endl; + std::cout << "Alpha: " << best_alpha << " " << best_alpha*180 / M_PI << std::endl; + for ( i = 0;i < 4;i++ ) + { + std::cout << finalBb->x[0] << " " << finalBb->y[0] << " "; + } + std::cout << std::endl; #endif - return finalBb; - } + return finalBb; + } #if 0 - double PointSet::getDistInside(double px, double py){ - - double dist[8]; - double rpx[8]; - double rpy[8]; - bool ok[8]; - - if (!isPointInPolygon(nbPoints, x, y, px,py)){ - double d = getDist(px,py); - //std::cout << "Outside : " << d << std::endl; - if (d < 0){ - d = -(d*d*d*d); - } - else{ - d = d*d*d*d; - } - return d; - } + double PointSet::getDistInside( double px, double py ) + { + + double dist[8]; + double rpx[8]; + double rpy[8]; + bool ok[8]; + + if ( !isPointInPolygon( nbPoints, x, y, px, py ) ) + { + double d = getDist( px, py ); + //std::cout << "Outside : " << d << std::endl; + if ( d < 0 ) + { + d = -( d * d * d * d ); + } + else + { + d = d * d * d * d; + } + return d; + } - int i; + int i; - double width = (xmax - xmin)*2; - double height = (ymax - ymin)*2; + double width = ( xmax - xmin ) * 2; + double height = ( ymax - ymin ) * 2; /* 1 0 7 @@ -1399,168 +1568,190 @@ namespace pal { 3 4 5 */ - // Compute references points - for (i=0;i<8;i++){ - dist[i] = DBL_MAX; - ok[i] = false; - rpx[i] = px; - rpy[i] = py; - } + // Compute references points + for ( i = 0;i < 8;i++ ) + { + dist[i] = DBL_MAX; + ok[i] = false; + rpx[i] = px; + rpy[i] = py; + } - rpx[0] += 0; - rpy[0] += height; - - rpx[1] -= width; - rpy[1] += height; - - rpx[2] -= width; - rpy[2] += 0; - - rpx[3] -= width; - rpy[3] -= height; - - rpx[4] += 0; - rpy[4] -= height; - - rpx[5] += width; - rpy[5] -= height; - - rpx[6] += width; - rpy[6] += 0; - - rpx[7] += width; - rpy[7] += height; - - int j,k; - for (i=0;i d){ - dist[k] = d; - ok[k] = true; - //std::cout << "new dist for " << k << ": " << dist[k] << std::endl; - } - } - } - } + rpx[0] += 0; + rpy[0] += height; - double a,b,c,d; + rpx[1] -= width; + rpy[1] += height; - - for (i=0;i<8;i++){ - if (!ok[i]){ - std::cout << "ERROR!!!!!!!!!!!!!!!!!" << std::endl; - dist[i] = 0; - } - //std::cout << "dist[" << i << "]: " << dist[i] << std::endl; - } + rpx[2] -= width; + rpy[2] += 0; - a = min (dist[0], dist[4]); - b = min (dist[1], dist[5]); - c = min (dist[2], dist[6]); - d = min (dist[3], dist[7]); - /* - std::cout << "a: " << a << std::endl; - std::cout << "b: " << b << std::endl; - std::cout << "c: " << c << std::endl; - std::cout << "d: " << d << std::endl; - */ - //a = (a+b+c+d)/4.0; + rpx[3] -= width; + rpy[3] -= height; - //a = min(a,b); - //c = min(c,d); - //return min(a,c); - + rpx[4] += 0; + rpy[4] -= height; - return (a*b*c*d); - } -#endif + rpx[5] += width; + rpy[5] -= height; - double PointSet::getDist (double px, double py, double *rx, double *ry) { - if (nbPoints == 1 || type == GEOS_POINT) { - if (rx && ry){ - *rx = x[0]; - *ry = y[0]; - } - return dist_euc2d_sq (x[0], y[0], px, py); - } + rpx[6] += width; + rpy[6] += 0; - int a,b; - int nbP = (type == GEOS_POLYGON ? nbPoints : nbPoints -1); + rpx[7] += width; + rpy[7] += height; - double best_dist = DBL_MAX; - double d; + int j, k; + for ( i = 0;i < nbPoints;i++ ) + { + j = ( i + 1 ) % nbPoints; - for (a=0;a d ) + { + dist[k] = d; + ok[k] = true; + //std::cout << "new dist for " << k << ": " << dist[k] << std::endl; + } + } + } + } - double px2, py2; - px2 = px - y[b] + y[a]; - py2 = py + x[b] - x[a]; - double ix, iy; + double a, b, c, d; - // (px,py)->(px2,py2) is a line perpendicular to a->b - // Check the line p->p2 cross the segment a->b - if (computeLineSegIntersection (px, py, px2, py2, - x[a], y[a], x[b], y[b], - &ix, &iy)){ - d = dist_euc2d_sq(px, py, ix, iy); - } - else{ - double d1 = dist_euc2d_sq (x[a], y[a], px, py); - double d2 = dist_euc2d_sq (x[b], y[b], px, py); - if (d1 < d2){ - d = d1; - ix = x[a]; - iy = y[a]; - } - else{ - d = d2; - ix = x[b]; - iy = y[b]; - } - } - - if (d < best_dist){ - best_dist = d; - if (rx && ry){ - *rx = ix; - *ry = iy; - } - } - } // end for (a in nbPoints) - return best_dist; + for ( i = 0;i < 8;i++ ) + { + if ( !ok[i] ) + { + std::cout << "ERROR!!!!!!!!!!!!!!!!!" << std::endl; + dist[i] = 0; + } + //std::cout << "dist[" << i << "]: " << dist[i] << std::endl; } + a = min( dist[0], dist[4] ); + b = min( dist[1], dist[5] ); + c = min( dist[2], dist[6] ); + d = min( dist[3], dist[7] ); + /* + std::cout << "a: " << a << std::endl; + std::cout << "b: " << b << std::endl; + std::cout << "c: " << c << std::endl; + std::cout << "d: " << d << std::endl; + */ + //a = (a+b+c+d)/4.0; + //a = min(a,b); + //c = min(c,d); + //return min(a,c); - void PointSet::getCentroid (double &px, double &py) { - double ix, iy; - double mesh = min ( (xmax - xmin) / 10, (ymax - ymin) / 10); - bool ptOk = false; - - while (!ptOk) { - double best = -DBL_MAX; - double dist; - for (ix = xmin;ix < xmax;ix = ix + mesh) { - for (iy = ymin;iy < ymax;iy = iy + mesh) { - dist = getDist (ix, iy, NULL, NULL); - if (dist > 0 && dist > best) { - ptOk = true; - best = dist; - px = ix; - py = iy; - } - } - } - mesh /= 10; + + return ( a*b*c*d ); + } +#endif + + double PointSet::getDist( double px, double py, double *rx, double *ry ) + { + if ( nbPoints == 1 || type == GEOS_POINT ) + { + if ( rx && ry ) + { + *rx = x[0]; + *ry = y[0]; + } + return dist_euc2d_sq( x[0], y[0], px, py ); + } + + int a, b; + int nbP = ( type == GEOS_POLYGON ? nbPoints : nbPoints - 1 ); + + double best_dist = DBL_MAX; + double d; + + for ( a = 0;a < nbP;a++ ) + { + b = ( a + 1 ) % nbPoints; + + double px2, py2; + px2 = px - y[b] + y[a]; + py2 = py + x[b] - x[a]; + double ix, iy; + + // (px,py)->(px2,py2) is a line perpendicular to a->b + // Check the line p->p2 cross the segment a->b + if ( computeLineSegIntersection( px, py, px2, py2, + x[a], y[a], x[b], y[b], + &ix, &iy ) ) + { + d = dist_euc2d_sq( px, py, ix, iy ); + } + else + { + double d1 = dist_euc2d_sq( x[a], y[a], px, py ); + double d2 = dist_euc2d_sq( x[b], y[b], px, py ); + if ( d1 < d2 ) + { + d = d1; + ix = x[a]; + iy = y[a]; + } + else + { + d = d2; + ix = x[b]; + iy = y[b]; + } + } + + if ( d < best_dist ) + { + best_dist = d; + if ( rx && ry ) + { + *rx = ix; + *ry = iy; + } + } + } // end for (a in nbPoints) + + return best_dist; + } + + + + void PointSet::getCentroid( double &px, double &py ) + { + double ix, iy; + double mesh = min(( xmax - xmin ) / 10, ( ymax - ymin ) / 10 ); + bool ptOk = false; + + while ( !ptOk ) + { + double best = -DBL_MAX; + double dist; + for ( ix = xmin;ix < xmax;ix = ix + mesh ) + { + for ( iy = ymin;iy < ymax;iy = iy + mesh ) + { + dist = getDist( ix, iy, NULL, NULL ); + if ( dist > 0 && dist > best ) + { + ptOk = true; + best = dist; + px = ix; + py = iy; + } } + } + mesh /= 10; } + } } // end namespace diff --git a/src/core/pal/pointset.h b/src/core/pal/pointset.h index 40f306f50911..1a081afd006d 100644 --- a/src/core/pal/pointset.h +++ b/src/core/pal/pointset.h @@ -1,242 +1,256 @@ -/* - * libpal - Automated Placement of Labels Library - * - * Copyright (C) 2008 Maxence Laurent, MIS-TIC, HEIG-VD - * University of Applied Sciences, Western Switzerland - * http://www.hes-so.ch - * - * Contact: - * maxence.laurent heig-vd ch - * or - * eric.taillard heig-vd ch - * - * This file is part of libpal. - * - * libpal is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * libpal is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with libpal. If not, see . - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifndef _POINTSET_H -#define _POINTSET_H - -#include - -#include -#include -#include - -#include "rtree.hpp" -#include "linkedlist.hpp" - -namespace pal { - - class Pal; - class Feat; - class Feature; - class Projection; - class LabelPosition; - - typedef struct _cross { - int pt; - double d; - double x; - double y; - int seg; // seg{0,1,2,3} - int nextCorner; // pt{0,1,2,3} - int way; - - } Crossing; - - class PointSet; - - typedef struct _cHullBox { - double x[4]; - double y[4]; - - double alpha; - - double width; - double length; - } CHullBox; - - - - inline bool ptrCrossingCompare (Crossing * a, Crossing * b) { - return a == b; - } - - inline bool crossingDist (void *a, void *b) { - return ( (Crossing*) a)->d > ( (Crossing*) b)->d; - } - - - class PointSet { - friend class Feature; - friend class Pal; - friend class Layer; - friend class LabelPosition; - friend class PolygonCostCalculator; - friend class Problem; - friend bool pruneLabelPositionCallback (LabelPosition *lp, void *ctx); - //friend Feat *splitButterflyPolygon (Feat *f, int pt_a, int pt_b, double cx, double cy); - friend bool obstacleCallback (PointSet *feat, void *ctx); - friend bool extractFeatCallback (Feature*, void*); - friend void extractXYCoord (Feat *f); - friend LinkedList * splitGeom (GEOSGeometry *the_geom, const char *geom_id); - friend void releaseAllInIndex (RTree *obstacles); - friend bool releaseCallback (PointSet *pset, void *ctx); - friend bool filteringCallback (PointSet*, void*); - /*protected*/ -public: - int nbPoints; - double *x; - double *y; // points order is counterclockwise - - int *status; // -1 means inside the bbox, +1 means outside and 0 is either in either out - int *cHull; - int cHullSize; - - int type; - - //PointSet *parent; - - PointSet* holeOf; - PointSet* parent; - - PointSet (double x, double y); - - PointSet (PointSet &ps); - - -//public: - double xmin; - double xmax; - double ymin; - double ymax; - - PointSet (); - PointSet (int nbPoints, double *x, double *y); - ~PointSet(); - - int getPath (int start, int stop, int *path_val); - - PointSet *extractPath (int path, int nbPtPath, int nbBboxPt, double bbx[4], double bby[4], Crossing *start, Crossing *stop, int startPt); - - PointSet* extractShape (int nbPtSh, int imin, int imax, int fps, int fpe, double fptx, double fpty); - - PointSet *createProblemSpecificPointSet (double bbx[4], double bby[4], bool *outside, bool *inside); - - CHullBox * compute_chull_bbox (); - - /* - * \brief Take each line in shape_toProcess and only keep inside bbox line parts - */ - static void reduceLine (PointSet *line, - LinkedList *shapes_final, - double bbx[4], double bby[4]); - - - /** - * \brief takes shapes from shapes_toProcess, compute intersection with bbox - * and puts new shapes into shapes_final - */ - static void reducePolygon (PointSet* shape_toProcess, - LinkedList *shapes_final, - double bbx[4], double bby[4]); - - - /* - * split a concave shape into several convex shapes - * - */ - static void splitPolygons (LinkedList *shapes_toProcess, - LinkedList *shapes_final, - double xrm, double yrm, char *uid); - - - - /** - * \brief return the minimum distance bw this and the point (px,py) - * - * compute the minimum distance bw the point (px,py) and this. - * Optionnaly, store the nearest point in (rx,ry) - * - * @param px x coordinate of the point - * @param py y coordinate of the points - * @param rx pointer to x coorinates of the nearest point (can be NULL) - * @param ry pointer to y coorinates of the nearest point (can be NULL) - */ - double getDist(double px, double py, double *rx, double *ry); - - - - //double getDistInside(double px, double py); - - void getCentroid (double &px, double &py); - - - - - /* - * Iterate on line by real step of dl on x,y points - * @param nbPoint # point in line - * @param x x coord - * @param y y coord - * @param d ?? - * @param ad distance from pt0 to each point (ad0 = pt0->pt0) - * @param dl ?? - * @param px current x coord on line - * @param py current y coord on line - */ - inline void getPoint (double *d, double *ad, double dl, - double *px, double *py) { - int i; - double dx, dy, di; - double distr; - - i = 0; - if (dl >= 0) { - while (i < nbPoints && ad[i] <= dl) i++; - i--; - } - - if (i < nbPoints - 1) { - if (dl < 0) { - dx = x[nbPoints-1] - x[0]; - dy = y[nbPoints-1] - y[0]; - di = sqrt (dx * dx + dy * dy); - } else { - dx = x[i+1] - x[i]; - dy = y[i+1] - y[i]; - di = d[i]; - } - - distr = dl - ad[i]; - *px = x[i] + dx * distr / di; - *py = y[i] + dy * distr / di; - } else { // just select last point... - *px = x[i]; - *py = y[i]; - } - } - }; - -} // namespace pal - -#endif - +/* + * libpal - Automated Placement of Labels Library + * + * Copyright (C) 2008 Maxence Laurent, MIS-TIC, HEIG-VD + * University of Applied Sciences, Western Switzerland + * http://www.hes-so.ch + * + * Contact: + * maxence.laurent heig-vd ch + * or + * eric.taillard heig-vd ch + * + * This file is part of libpal. + * + * libpal is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * libpal is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with libpal. If not, see . + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifndef _POINTSET_H +#define _POINTSET_H + +#include + +#include +#include +#include + +#include "rtree.hpp" +#include "linkedlist.hpp" + +namespace pal +{ + + class Pal; + class Feat; + class Feature; + class Projection; + class LabelPosition; + + typedef struct _cross + { + int pt; + double d; + double x; + double y; + int seg; // seg{0,1,2,3} + int nextCorner; // pt{0,1,2,3} + int way; + + } Crossing; + + class PointSet; + + typedef struct _cHullBox + { + double x[4]; + double y[4]; + + double alpha; + + double width; + double length; + } CHullBox; + + + + inline bool ptrCrossingCompare( Crossing * a, Crossing * b ) + { + return a == b; + } + + inline bool crossingDist( void *a, void *b ) + { + return (( Crossing* ) a )->d > (( Crossing* ) b )->d; + } + + + class PointSet + { + friend class Feature; + friend class Pal; + friend class Layer; + friend class LabelPosition; + friend class PolygonCostCalculator; + friend class Problem; + friend bool pruneLabelPositionCallback( LabelPosition *lp, void *ctx ); + //friend Feat *splitButterflyPolygon (Feat *f, int pt_a, int pt_b, double cx, double cy); + friend bool obstacleCallback( PointSet *feat, void *ctx ); + friend bool extractFeatCallback( Feature*, void* ); + friend void extractXYCoord( Feat *f ); + friend LinkedList * splitGeom( GEOSGeometry *the_geom, const char *geom_id ); + friend void releaseAllInIndex( RTree *obstacles ); + friend bool releaseCallback( PointSet *pset, void *ctx ); + friend bool filteringCallback( PointSet*, void* ); + /*protected*/ + public: + int nbPoints; + double *x; + double *y; // points order is counterclockwise + + int *status; // -1 means inside the bbox, +1 means outside and 0 is either in either out + int *cHull; + int cHullSize; + + int type; + + //PointSet *parent; + + PointSet* holeOf; + PointSet* parent; + + PointSet( double x, double y ); + + PointSet( PointSet &ps ); + + +//public: + double xmin; + double xmax; + double ymin; + double ymax; + + PointSet(); + PointSet( int nbPoints, double *x, double *y ); + ~PointSet(); + + int getPath( int start, int stop, int *path_val ); + + PointSet *extractPath( int path, int nbPtPath, int nbBboxPt, double bbx[4], double bby[4], Crossing *start, Crossing *stop, int startPt ); + + PointSet* extractShape( int nbPtSh, int imin, int imax, int fps, int fpe, double fptx, double fpty ); + + PointSet *createProblemSpecificPointSet( double bbx[4], double bby[4], bool *outside, bool *inside ); + + CHullBox * compute_chull_bbox(); + + /* + * \brief Take each line in shape_toProcess and only keep inside bbox line parts + */ + static void reduceLine( PointSet *line, + LinkedList *shapes_final, + double bbx[4], double bby[4] ); + + + /** + * \brief takes shapes from shapes_toProcess, compute intersection with bbox + * and puts new shapes into shapes_final + */ + static void reducePolygon( PointSet* shape_toProcess, + LinkedList *shapes_final, + double bbx[4], double bby[4] ); + + + /* + * split a concave shape into several convex shapes + * + */ + static void splitPolygons( LinkedList *shapes_toProcess, + LinkedList *shapes_final, + double xrm, double yrm, char *uid ); + + + + /** + * \brief return the minimum distance bw this and the point (px,py) + * + * compute the minimum distance bw the point (px,py) and this. + * Optionnaly, store the nearest point in (rx,ry) + * + * @param px x coordinate of the point + * @param py y coordinate of the points + * @param rx pointer to x coorinates of the nearest point (can be NULL) + * @param ry pointer to y coorinates of the nearest point (can be NULL) + */ + double getDist( double px, double py, double *rx, double *ry ); + + + + //double getDistInside(double px, double py); + + void getCentroid( double &px, double &py ); + + + + + /* + * Iterate on line by real step of dl on x,y points + * @param nbPoint # point in line + * @param x x coord + * @param y y coord + * @param d ?? + * @param ad distance from pt0 to each point (ad0 = pt0->pt0) + * @param dl ?? + * @param px current x coord on line + * @param py current y coord on line + */ + inline void getPoint( double *d, double *ad, double dl, + double *px, double *py ) + { + int i; + double dx, dy, di; + double distr; + + i = 0; + if ( dl >= 0 ) + { + while ( i < nbPoints && ad[i] <= dl ) i++; + i--; + } + + if ( i < nbPoints - 1 ) + { + if ( dl < 0 ) + { + dx = x[nbPoints-1] - x[0]; + dy = y[nbPoints-1] - y[0]; + di = sqrt( dx * dx + dy * dy ); + } + else + { + dx = x[i+1] - x[i]; + dy = y[i+1] - y[i]; + di = d[i]; + } + + distr = dl - ad[i]; + *px = x[i] + dx * distr / di; + *py = y[i] + dy * distr / di; + } + else // just select last point... + { + *px = x[i]; + *py = y[i]; + } + } + }; + +} // namespace pal + +#endif + diff --git a/src/core/pal/priorityqueue.cpp b/src/core/pal/priorityqueue.cpp index c478ecadf8d6..5b4d7d0067ff 100644 --- a/src/core/pal/priorityqueue.cpp +++ b/src/core/pal/priorityqueue.cpp @@ -36,271 +36,305 @@ #include "internalexception.h" #include "priorityqueue.h" -namespace pal { +namespace pal +{ - bool smaller (double l, double r) { - return l > r; - } + bool smaller( double l, double r ) + { + return l > r; + } - bool bigger (double l, double r) { - return l < r; - } + bool bigger( double l, double r ) + { + return l < r; + } // O (size log size) - PriorityQueue::PriorityQueue (int n, int maxId, bool min) : size (0), maxsize (n), maxId (maxId) { - heap = new int[maxsize]; - p = new double[maxsize]; - pos = new int[maxId+1]; + PriorityQueue::PriorityQueue( int n, int maxId, bool min ) : size( 0 ), maxsize( n ), maxId( maxId ) + { + heap = new int[maxsize]; + p = new double[maxsize]; + pos = new int[maxId+1]; - int i; + int i; - for (i = 0;i <= maxId;i++) - pos[i] = -1; + for ( i = 0;i <= maxId;i++ ) + pos[i] = -1; - if (min) - greater = smaller; - else - greater = bigger; - } + if ( min ) + greater = smaller; + else + greater = bigger; + } - PriorityQueue::~PriorityQueue() { - delete[] heap; - delete[] p; - delete[] pos; - } + PriorityQueue::~PriorityQueue() + { + delete[] heap; + delete[] p; + delete[] pos; + } - int PriorityQueue::getSize() { - return size; - } + int PriorityQueue::getSize() + { + return size; + } // O(log size) - int PriorityQueue::getBest() { - if (size <= 0) - throw InternalException::Empty(); - - int return_value = heap[0]; + int PriorityQueue::getBest() + { + if ( size <= 0 ) + throw InternalException::Empty(); - //std::cerr << "getBest" << std::endl; - //std::cerr << " key: " << return_value << std::endl; - //std::cerr << " Size: " << size << std::endl; + int return_value = heap[0]; - size--; + //std::cerr << "getBest" << std::endl; + //std::cerr << " key: " << return_value << std::endl; + //std::cerr << " Size: " << size << std::endl; + size--; - pos[heap[0]] = -1; - if (size > 0) { - pos[heap[size]] = 0; + pos[heap[0]] = -1; - heap[0] = heap[size]; - p[0] = p[size]; - downheap (0); - } + if ( size > 0 ) + { + pos[heap[size]] = 0; - return return_value; + heap[0] = heap[size]; + p[0] = p[size]; + downheap( 0 ); } + return return_value; + } - bool PriorityQueue::isIn (int key) { - return key <= maxId && pos[key] >= 0; - } - int PriorityQueue::getId (int key) { - return key <= maxId ? pos[key] : -1; - } + bool PriorityQueue::isIn( int key ) + { + return key <= maxId && pos[key] >= 0; + } - void PriorityQueue::insert (int key, double p) { - if (size == maxsize || key > maxId || key < 0) - throw InternalException::Full(); + int PriorityQueue::getId( int key ) + { + return key <= maxId ? pos[key] : -1; + } - //std::cerr << "insert" << std::endl; - //std::cerr << " key: " << key << std::endl; - //std::cerr << " size: " << size << std::endl; + void PriorityQueue::insert( int key, double p ) + { + if ( size == maxsize || key > maxId || key < 0 ) + throw InternalException::Full(); - heap[size] = key; - pos[key] = size; - this->p[size] = p; + //std::cerr << "insert" << std::endl; + //std::cerr << " key: " << key << std::endl; + //std::cerr << " size: " << size << std::endl; - size++; + heap[size] = key; + pos[key] = size; + this->p[size] = p; + size++; - upheap (key); - } + + upheap( key ); + } // O(size) // - void PriorityQueue::remove (int key) { - if (key < 0 || key > maxId) - return; - int i = pos[key]; + void PriorityQueue::remove( int key ) + { + if ( key < 0 || key > maxId ) + return; + int i = pos[key]; - //std::cerr << "Remove " << key << std::endl; - //std::cerr << " pos[key]: " << i << std::endl; + //std::cerr << "Remove " << key << std::endl; + //std::cerr << " pos[key]: " << i << std::endl; - if (i >= 0) { + if ( i >= 0 ) + { - //std::cerr << "size:" << size << std::endl; - //std::cerr << "heap[size]:" << heap[size] << std::endl; - //std::cerr << "pos[heap[size]]:" << pos[heap[size]] << std::endl; - //std::cerr << "pos[key]:" << pos[key] << std::endl; + //std::cerr << "size:" << size << std::endl; + //std::cerr << "heap[size]:" << heap[size] << std::endl; + //std::cerr << "pos[heap[size]]:" << pos[heap[size]] << std::endl; + //std::cerr << "pos[key]:" << pos[key] << std::endl; - size--; - pos[heap[size]] = i; - pos[key] = -1; + size--; + pos[heap[size]] = i; + pos[key] = -1; - heap[i] = heap[size]; - p[i] = p[size]; + heap[i] = heap[size]; + p[i] = p[size]; - downheap (i); - } + downheap( i ); } + } // O (size log size) - void PriorityQueue::sort() { - int i; - int pi = 2; - while (size > pi) pi *= 2; + void PriorityQueue::sort() + { + int i; + int pi = 2; + while ( size > pi ) pi *= 2; - i = pi / 2 - 2; + i = pi / 2 - 2; - for (i = size - 1;i >= 0;i--) - downheap (i); + for ( i = size - 1;i >= 0;i-- ) + downheap( i ); - } + } - void PriorityQueue::upheap (int key) { - int i; - int i2; + void PriorityQueue::upheap( int key ) + { + int i; + int i2; - int tmpT; - double tmpP; + int tmpT; + double tmpP; - if (key < 0 || key > maxId) - return; + if ( key < 0 || key > maxId ) + return; - i = pos[key]; + i = pos[key]; - if (i >= -1) { - while (i > 0) { - if (greater (p[PARENT (i) ], p[i])) { - i2 = PARENT (i); + if ( i >= -1 ) + { + while ( i > 0 ) + { + if ( greater( p[PARENT( i )], p[i] ) ) + { + i2 = PARENT( i ); - pos[heap[i]] = i2; - pos[heap[i2]] = i; + pos[heap[i]] = i2; + pos[heap[i2]] = i; - tmpT = heap[i]; - tmpP = p[i]; + tmpT = heap[i]; + tmpP = p[i]; - heap[i] = heap[i2]; - p[i] = p[i2]; + heap[i] = heap[i2]; + p[i] = p[i2]; - heap[i2] = tmpT; - p[i2] = tmpP; + heap[i2] = tmpT; + p[i2] = tmpP; - i = i2; - } else - break; - } + i = i2; } + else + break; + } } + } // O(log n) - void PriorityQueue::downheap (int id) { - int min_child; - int tmpT; - double tmpP; - - for (;;) { - if (LEFT (id) < size) { - if (RIGHT (id) < size) { - min_child = greater (p[RIGHT (id) ], p[LEFT (id) ]) ? LEFT (id) : RIGHT (id); - } else - min_child = LEFT (id); - } else // leaf - break; - - if (greater (p[id], p[min_child])) { - pos[heap[id]] = min_child; - pos[heap[min_child]] = id; - - tmpT = heap[id]; - tmpP = p[id]; - - heap[id] = heap[min_child]; - p[id] = p[min_child]; - - heap[min_child] = tmpT; - p[min_child] = tmpP; - - id = min_child; - } else - break; + void PriorityQueue::downheap( int id ) + { + int min_child; + int tmpT; + double tmpP; + + for ( ;; ) + { + if ( LEFT( id ) < size ) + { + if ( RIGHT( id ) < size ) + { + min_child = greater( p[RIGHT( id )], p[LEFT( id )] ) ? LEFT( id ) : RIGHT( id ); } - } + else + min_child = LEFT( id ); + } + else // leaf + break; - void PriorityQueue::setPriority (int key, double new_p) { + if ( greater( p[id], p[min_child] ) ) + { + pos[heap[id]] = min_child; + pos[heap[min_child]] = id; - if (key < 0 || key > maxId) - return; + tmpT = heap[id]; + tmpP = p[id]; - int i = pos[key]; + heap[id] = heap[min_child]; + p[id] = p[min_child]; - if (i < 0) { - insert (key, new_p); - return; - } + heap[min_child] = tmpT; + p[min_child] = tmpP; + + id = min_child; + } + else + break; + } + } + + void PriorityQueue::setPriority( int key, double new_p ) + { - p[i] = new_p;; + if ( key < 0 || key > maxId ) + return; - upheap (key); - downheap (pos[key]); + int i = pos[key]; + + if ( i < 0 ) + { + insert( key, new_p ); + return; } + p[i] = new_p;; - void PriorityQueue::decreaseKey (int key) { + upheap( key ); + downheap( pos[key] ); + } - if (key < 0 || key > maxId) - return; - int i = pos[key]; + void PriorityQueue::decreaseKey( int key ) + { - if (i < 0) - return; + if ( key < 0 || key > maxId ) + return; - p[i]--; + int i = pos[key]; - upheap (key); - downheap (pos[key]); - } + if ( i < 0 ) + return; + p[i]--; - void PriorityQueue::print() { - int i; + upheap( key ); + downheap( pos[key] ); + } - fprintf (stderr, "Size: %d\nMaxSize: %d\n", size, maxsize); - for (i = 0;i < size;i++) { - //printf ("key: %7d -> index: %7d -> key: %7d p: %7d\n", i, pos[i], heap[pos[i]], p[pos[i]]); - fprintf (stderr, "id: %7d -> key: %7d -> id: %7d p: %7f\n", i, heap[i], pos[heap[i]], p[i]); - } - fprintf (stderr, "\n"); + void PriorityQueue::print() + { + int i; + fprintf( stderr, "Size: %d\nMaxSize: %d\n", size, maxsize ); + + for ( i = 0;i < size;i++ ) + { + //printf ("key: %7d -> index: %7d -> key: %7d p: %7d\n", i, pos[i], heap[pos[i]], p[pos[i]]); + fprintf( stderr, "id: %7d -> key: %7d -> id: %7d p: %7f\n", i, heap[i], pos[heap[i]], p[i] ); } + fprintf( stderr, "\n" ); + } - int PriorityQueue::getSizeByPos() { - int i; - int count = 0; - for (i = 0;i < maxsize;i++) { - if (pos[i] >= 0) - count++; - } - return count; + + int PriorityQueue::getSizeByPos() + { + int i; + int count = 0; + for ( i = 0;i < maxsize;i++ ) + { + if ( pos[i] >= 0 ) + count++; } + return count; + } } // namespace diff --git a/src/core/pal/priorityqueue.h b/src/core/pal/priorityqueue.h index 33c7456e9655..e44310afb084 100644 --- a/src/core/pal/priorityqueue.h +++ b/src/core/pal/priorityqueue.h @@ -41,51 +41,53 @@ #define PARENT(x) ((x-1)/2) -namespace pal { +namespace pal +{ - class PriorityQueue { + class PriorityQueue + { private: - int size; - int maxsize; - int maxId; - int *heap; - double *p; - int *pos; + int size; + int maxsize; + int maxId; + int *heap; + double *p; + int *pos; - bool (*greater) (double l, double r); + bool ( *greater )( double l, double r ); public: - /** \brief Create a priority queue of max size n - * \@param n max size of the queuet - * \@param p external vector representing the priority - * \@param min best element has the smalest p when min is True ans has the biggest when min is false - */ - PriorityQueue (int n, int maxId, bool min); - ~PriorityQueue(); + /** \brief Create a priority queue of max size n + * \@param n max size of the queuet + * \@param p external vector representing the priority + * \@param min best element has the smalest p when min is True ans has the biggest when min is false + */ + PriorityQueue( int n, int maxId, bool min ); + ~PriorityQueue(); - void print(); + void print(); - int getSize(); - int getSizeByPos(); + int getSize(); + int getSizeByPos(); - bool isIn (int key); + bool isIn( int key ); - int getBest(); // O(log n) + int getBest(); // O(log n) - void remove (int key); - void insert (int key, double p); + void remove( int key ); + void insert( int key, double p ); - void sort(); // O(n log n) + void sort(); // O(n log n) - void downheap (int id); - void upheap (int key); + void downheap( int id ); + void upheap( int key ); - void decreaseKey (int key); - void setPriority (int key, double new_p); + void decreaseKey( int key ); + void setPriority( int key, double new_p ); - int getId (int key); - }; + int getId( int key ); + }; } // namespace diff --git a/src/core/pal/problem.cpp b/src/core/pal/problem.cpp index 69f07911ff39..c75824da464a 100644 --- a/src/core/pal/problem.cpp +++ b/src/core/pal/problem.cpp @@ -61,3000 +61,3330 @@ -namespace pal { - - inline void delete_chain (Chain *chain) { - if (chain) { - delete[] chain->feat; - delete[] chain->label; - delete chain; - } +namespace pal +{ + + inline void delete_chain( Chain *chain ) + { + if ( chain ) + { + delete[] chain->feat; + delete[] chain->label; + delete chain; } - - Problem::Problem() : nblp (0), all_nblp (0), nbft (0), displayAll (0), labelpositions (NULL), featStartId (NULL), featNbLp (NULL), inactiveCost (NULL), sol (NULL) { - bbox[0] = 0; - bbox[1] = 0; - bbox[2] = 0; - bbox[3] = 0; - featWrap = NULL; - candidates = new RTree(); - candidates_sol = new RTree(); - candidates_subsol = NULL; + } + + Problem::Problem() : nblp( 0 ), all_nblp( 0 ), nbft( 0 ), displayAll( 0 ), labelpositions( NULL ), featStartId( NULL ), featNbLp( NULL ), inactiveCost( NULL ), sol( NULL ) + { + bbox[0] = 0; + bbox[1] = 0; + bbox[2] = 0; + bbox[3] = 0; + featWrap = NULL; + candidates = new RTree(); + candidates_sol = new RTree(); + candidates_subsol = NULL; + } + + Problem::~Problem() + { + int i; + + if ( sol ) + { + if ( sol->s ) + delete[] sol->s; + delete sol; } - Problem::~Problem() { - int i; - - if (sol) { - if (sol->s) - delete[] sol->s; - delete sol; - } + if ( featWrap ) + delete[] featWrap; + if ( featStartId ) + delete[] featStartId; + if ( featNbLp ) + delete[] featNbLp; - if (featWrap) - delete[] featWrap; - if (featStartId) - delete[] featStartId; - if (featNbLp) - delete[] featNbLp; + for ( i = 0;i < nbLabelledLayers;i++ ) + delete[] labelledLayersName[i]; - for (i = 0;i < nbLabelledLayers;i++) - delete[] labelledLayersName[i]; + delete[] labelledLayersName; - delete[] labelledLayersName; + for ( i = 0;i < all_nblp;i++ ) + delete labelpositions[i]; - for (i = 0;i < all_nblp;i++) - delete labelpositions[i]; + if ( labelpositions ) + delete[] labelpositions; - if (labelpositions) - delete[] labelpositions; + if ( inactiveCost ) + delete[] inactiveCost; - if (inactiveCost) - delete[] inactiveCost; + delete candidates; + delete candidates_sol; - delete candidates; - delete candidates_sol; - - if (candidates_subsol) { - delete candidates_subsol; - } + if ( candidates_subsol ) + { + delete candidates_subsol; } - - typedef struct { - int id; - double inactiveCost; - double nbOverlap; - } Ft; - - - inline bool borderSizeDec (void *l, void *r) { - return ( (SubPart*) l)->borderSize < ( (SubPart*) r)->borderSize; - } - - inline bool borderSizeInc (void *l, void *r) { - return ( (SubPart*) l)->borderSize > ( (SubPart*) r)->borderSize; - } - - inline bool increaseImportance (void *l, void *r) { - return ( (Ft*) l)->inactiveCost < ( (Ft*) r)->inactiveCost; + } + + typedef struct + { + int id; + double inactiveCost; + double nbOverlap; + } Ft; + + + inline bool borderSizeDec( void *l, void *r ) + { + return (( SubPart* ) l )->borderSize < (( SubPart* ) r )->borderSize; + } + + inline bool borderSizeInc( void *l, void *r ) + { + return (( SubPart* ) l )->borderSize > (( SubPart* ) r )->borderSize; + } + + inline bool increaseImportance( void *l, void *r ) + { + return (( Ft* ) l )->inactiveCost < (( Ft* ) r )->inactiveCost; + } + + inline bool increaseNbOverlap( void *l, void *r ) + { + return (( Ft* ) l )->nbOverlap > (( Ft* ) r )->nbOverlap; + } + + + typedef struct + { + LabelPosition *lp; + int *nbOverlaps; + } RemoveOverlapContext; + + bool removeOverlapCallback( LabelPosition *lp, void *ctx ) + { + LabelPosition *lp2 = ( LabelPosition * ) ctx; + + if ( lp2->isInConflict( lp ) ) + { + //std::cout << " hit !" << std::endl; + lp->nbOverlap--; + lp2->nbOverlap--; } - inline bool increaseNbOverlap (void *l, void *r) { - return ( (Ft*) l)->nbOverlap > ( (Ft*) r)->nbOverlap; - } + return true; + } - typedef struct { - LabelPosition *lp; - int *nbOverlaps; - } RemoveOverlapContext; + void Problem::reduce() + { - bool removeOverlapCallback (LabelPosition *lp, void *ctx) { - LabelPosition *lp2 = (LabelPosition *) ctx; + int i; + int j; + int k; - if (lp2->isInConflict (lp)) { - //std::cout << " hit !" << std::endl; - lp->nbOverlap--; - lp2->nbOverlap--; - } + int counter = 0; - return true; - } + int lpid; + bool *ok = new bool[nblp]; + bool run = true; - void Problem::reduce() { + for ( i = 0;i < nblp;i++ ) + ok[i] = false; - int i; - int j; - int k; - int counter = 0; + double amin[2]; + double amax[2]; + LabelPosition *lp; + LabelPosition *lp2; + int c; - int lpid; - bool *ok = new bool[nblp]; - bool run = true; + while ( run ) + { + run = false; + for ( i = 0;i < nbft;i++ ) + { + // ok[i] = true; + for ( j = 0;j < featNbLp[i];j++ ) // foreach candidate + { + if ( !ok[featStartId[i] + j] ) + { + if (( lp = labelpositions[featStartId[i] + j] )->nbOverlap == 0 ) // if candidate has no overlap + { + run = true; + ok[featStartId[i] + j] = true; + // 1) remove worse candidates from candidates + // 2) update nb_overlaps + counter += featNbLp[i] - j - 1; - for (i = 0;i < nblp;i++) - ok[i] = false; + for ( k = j + 1;k < featNbLp[i];k++ ) + { + lpid = featStartId[i] + k; + ok[lpid] = true; + lp2 = labelpositions[lpid]; - double amin[2]; - double amax[2]; - LabelPosition *lp; - LabelPosition *lp2; - int c; + amin[0] = DBL_MAX; + amax[0] = -DBL_MAX; + amin[1] = DBL_MAX; + amax[1] = -DBL_MAX; + for ( c = 0;c < 4;c++ ) + { + if ( lp2->x[c] < amin[0] ) + amin[0] = lp2->x[c]; + if ( lp2->x[c] > amax[0] ) + amax[0] = lp2->x[c]; + if ( lp2->y[c] < amin[1] ) + amin[1] = lp2->y[c]; + if ( lp2->y[c] > amax[1] ) + amax[1] = lp2->y[c]; + } + nbOverlap -= lp2->nbOverlap; + candidates->Search( amin, amax, removeOverlapCallback, ( void* ) lp2 ); + lp2->removeFromIndex( candidates ); + } - while (run) { - run = false; - for (i = 0;i < nbft;i++) { - // ok[i] = true; - for (j = 0;j < featNbLp[i];j++) { // foreach candidate - if (!ok[featStartId[i] + j]) { - if ( (lp = labelpositions[featStartId[i] + j])->nbOverlap == 0) { // if candidate has no overlap - run = true; - ok[featStartId[i] + j] = true; - // 1) remove worse candidates from candidates - // 2) update nb_overlaps - counter += featNbLp[i] - j - 1; - - for (k = j + 1;k < featNbLp[i];k++) { - - lpid = featStartId[i] + k; - ok[lpid] = true; - lp2 = labelpositions[lpid]; - - amin[0] = DBL_MAX; - amax[0] = -DBL_MAX; - amin[1] = DBL_MAX; - amax[1] = -DBL_MAX; - for (c = 0;c < 4;c++) { - if (lp2->x[c] < amin[0]) - amin[0] = lp2->x[c]; - if (lp2->x[c] > amax[0]) - amax[0] = lp2->x[c]; - if (lp2->y[c] < amin[1]) - amin[1] = lp2->y[c]; - if (lp2->y[c] > amax[1]) - amax[1] = lp2->y[c]; - } - - nbOverlap -= lp2->nbOverlap; - candidates->Search (amin, amax, removeOverlapCallback, (void*) lp2); - lp2->removeFromIndex (candidates); - } - - //lp->removeFromIndex(candidates); - featNbLp[i] = j + 1; - break; - } - } - } + //lp->removeFromIndex(candidates); + featNbLp[i] = j + 1; + break; } + } } + } + } - this->nblp -= counter; + this->nblp -= counter; #ifdef _VERBOSE_ - std::cout << "problem reduce to " << nblp << " candidates which makes " << nbOverlap << " overlaps" << std::endl; -#endif - delete[] ok; + std::cout << "problem reduce to " << nblp << " candidates which makes " << nbOverlap << " overlaps" << std::endl; +#endif + delete[] ok; + } + + /** + * \brief Basic initial solution : every feature to -1 + */ + void Problem::init_sol_empty() + { + int i; + + if ( sol ) + { + if ( sol->s ) + delete[] sol->s; + delete sol; } - /** - * \brief Basic initial solution : every feature to -1 - */ - void Problem::init_sol_empty() { - int i; + sol = new Sol(); + sol->s = new int[nbft]; - if (sol) { - if (sol->s) - delete[] sol->s; - delete sol; - } + for ( i = 0;i < nbft;i++ ) + sol->s[i] = -1; - sol = new Sol(); - sol->s = new int[nbft]; + sol->cost = nbft; + } - for (i = 0;i < nbft;i++) - sol->s[i] = -1; - sol->cost = nbft; - } + typedef struct + { + PriorityQueue *list; + LabelPosition *lp; + RTree *candidates; + } FalpContext; + bool falpCallback2( LabelPosition *lp, void * ctx ) + { + LabelPosition *lp2 = (( FalpContext* ) ctx )->lp; + PriorityQueue *list = (( FalpContext* ) ctx )->list; - typedef struct { - PriorityQueue *list; - LabelPosition *lp; - RTree *candidates; - } FalpContext; - - bool falpCallback2 (LabelPosition *lp, void * ctx) { - LabelPosition *lp2 = ( (FalpContext*) ctx)->lp; - PriorityQueue *list = ( (FalpContext*) ctx)->list; - - if (lp->id != lp2->id && list->isIn (lp->id) && lp->isInConflict (lp2)) { - list->decreaseKey (lp->id); - } - return true; + if ( lp->id != lp2->id && list->isIn( lp->id ) && lp->isInConflict( lp2 ) ) + { + list->decreaseKey( lp->id ); } - - - void ignoreLabel (LabelPosition *lp, PriorityQueue *list, RTree *candidates) { - - - FalpContext *context = new FalpContext(); - context->candidates = NULL; - context->list = list; - double amin[2]; - double amax[2]; - int c; - - if (list->isIn (lp->id)) { - list->remove (lp->id); - - amin[0] = DBL_MAX; - amax[0] = -DBL_MAX; - amin[1] = DBL_MAX; - amax[1] = -DBL_MAX; - for (c = 0;c < 4;c++) { - if (lp->x[c] < amin[0]) - amin[0] = lp->x[c]; - if (lp->x[c] > amax[0]) - amax[0] = lp->x[c]; - if (lp->y[c] < amin[1]) - amin[1] = lp->y[c]; - if (lp->y[c] > amax[1]) - amax[1] = lp->y[c]; - } - context->lp = lp; - candidates->Search (amin, amax, falpCallback2, context); - } - - delete context; + return true; + } + + + void ignoreLabel( LabelPosition *lp, PriorityQueue *list, RTree *candidates ) + { + + + FalpContext *context = new FalpContext(); + context->candidates = NULL; + context->list = list; + double amin[2]; + double amax[2]; + int c; + + if ( list->isIn( lp->id ) ) + { + list->remove( lp->id ); + + amin[0] = DBL_MAX; + amax[0] = -DBL_MAX; + amin[1] = DBL_MAX; + amax[1] = -DBL_MAX; + for ( c = 0;c < 4;c++ ) + { + if ( lp->x[c] < amin[0] ) + amin[0] = lp->x[c]; + if ( lp->x[c] > amax[0] ) + amax[0] = lp->x[c]; + if ( lp->y[c] < amin[1] ) + amin[1] = lp->y[c]; + if ( lp->y[c] > amax[1] ) + amax[1] = lp->y[c]; + } + context->lp = lp; + candidates->Search( amin, amax, falpCallback2, context ); } + delete context; + } - bool falpCallback1 (LabelPosition *lp, void * ctx) { - LabelPosition *lp2 = ( (FalpContext*) ctx)->lp; - PriorityQueue *list = ( (FalpContext*) ctx)->list; - RTree *candidates = ( (FalpContext*) ctx)->candidates; - if (lp2->isInConflict (lp)) { - ignoreLabel (lp, list, candidates); - } - return true; + bool falpCallback1( LabelPosition *lp, void * ctx ) + { + LabelPosition *lp2 = (( FalpContext* ) ctx )->lp; + PriorityQueue *list = (( FalpContext* ) ctx )->list; + RTree *candidates = (( FalpContext* ) ctx )->candidates; + + if ( lp2->isInConflict( lp ) ) + { + ignoreLabel( lp, list, candidates ); } + return true; + } - /* Better initial solution - * Step one FALP (Yamamoto, Camara, Lorena 2005) - */ - void Problem::init_sol_falp() { + /* Better initial solution + * Step one FALP (Yamamoto, Camara, Lorena 2005) + */ + void Problem::init_sol_falp() + { #ifdef _DEBUG_ - std::cout << "Init solution FALP" << std::endl; + std::cout << "Init solution FALP" << std::endl; #endif - int i, j; - int label; - PriorityQueue *list; + int i, j; + int label; + PriorityQueue *list; - init_sol_empty(); + init_sol_empty(); - list = new PriorityQueue (nblp, all_nblp, true); + list = new PriorityQueue( nblp, all_nblp, true ); - double amin[2]; - double amax[2]; - int c; + double amin[2]; + double amax[2]; + int c; - FalpContext *context = new FalpContext(); - context->candidates = candidates; - context->list = list; + FalpContext *context = new FalpContext(); + context->candidates = candidates; + context->list = list; - LabelPosition *lp; + LabelPosition *lp; - for (i = 0;i < nbft;i++) - for (j = 0;j < featNbLp[i];j++) { - label = featStartId[i] + j; - list->insert (label, (double) labelpositions[label]->nbOverlap); - } + for ( i = 0;i < nbft;i++ ) + for ( j = 0;j < featNbLp[i];j++ ) + { + label = featStartId[i] + j; + list->insert( label, ( double ) labelpositions[label]->nbOverlap ); + } - while (list->getSize() > 0) { // O (log size) - label = list->getBest(); // O (log size) + while ( list->getSize() > 0 ) // O (log size) + { + label = list->getBest(); // O (log size) - lp = labelpositions[label]; + lp = labelpositions[label]; - if (lp->id != label) { - std::cout << "Error: " << lp->id << " <--> " << label << std::endl; - } + if ( lp->id != label ) + { + std::cout << "Error: " << lp->id << " <--> " << label << std::endl; + } - sol->s[lp->probFeat] = label; + sol->s[lp->probFeat] = label; #ifdef _DEBUG_FULL_ - std::cout << "sol->s[" << lp->probFeat << "] :" << label << std::endl; -#endif + std::cout << "sol->s[" << lp->probFeat << "] :" << label << std::endl; +#endif + + for ( i = featStartId[lp->probFeat];i < featStartId[lp->probFeat] + featNbLp[lp->probFeat];i++ ) + { + ignoreLabel( labelpositions[i], list, candidates ); + + } + + + amin[0] = DBL_MAX; + amax[0] = -DBL_MAX; + amin[1] = DBL_MAX; + amax[1] = -DBL_MAX; + for ( c = 0;c < 4;c++ ) + { + if ( lp->x[c] < amin[0] ) + amin[0] = lp->x[c]; + if ( lp->x[c] > amax[0] ) + amax[0] = lp->x[c]; + if ( lp->y[c] < amin[1] ) + amin[1] = lp->y[c]; + if ( lp->y[c] > amax[1] ) + amax[1] = lp->y[c]; + } + context->lp = lp; + candidates->Search( amin, amax, falpCallback1, ( void* ) context ); + candidates_sol->Insert( amin, amax, lp ); + } + + delete context; - for (i = featStartId[lp->probFeat];i < featStartId[lp->probFeat] + featNbLp[lp->probFeat];i++) { - ignoreLabel (labelpositions[i], list, candidates); - } + if ( displayAll ) + { + int nbOverlap; + int start_p; + LabelPosition* retainedLabel = NULL; + int p; + + for ( i = 0;i < nbft;i++ ) // forearch hidden feature + { + if ( sol->s[i] == -1 ) + { + nbOverlap = INT_MAX; + start_p = featStartId[i]; + for ( p = 0;p < featNbLp[i];p++ ) + { + lp = labelpositions[start_p+p]; + lp->nbOverlap = 0; amin[0] = DBL_MAX; amax[0] = -DBL_MAX; amin[1] = DBL_MAX; amax[1] = -DBL_MAX; - for (c = 0;c < 4;c++) { - if (lp->x[c] < amin[0]) - amin[0] = lp->x[c]; - if (lp->x[c] > amax[0]) - amax[0] = lp->x[c]; - if (lp->y[c] < amin[1]) - amin[1] = lp->y[c]; - if (lp->y[c] > amax[1]) - amax[1] = lp->y[c]; + for ( c = 0;c < 4;c++ ) + { + if ( lp->x[c] < amin[0] ) + amin[0] = lp->x[c]; + if ( lp->x[c] > amax[0] ) + amax[0] = lp->x[c]; + if ( lp->y[c] < amin[1] ) + amin[1] = lp->y[c]; + if ( lp->y[c] > amax[1] ) + amax[1] = lp->y[c]; } - context->lp = lp; - candidates->Search (amin, amax, falpCallback1, (void*) context); - candidates_sol->Insert (amin, amax, lp); - } - - delete context; - - - if (displayAll) { - int nbOverlap; - int start_p; - LabelPosition* retainedLabel = NULL; - int p; + candidates_sol->Search( amin, amax, countOverlapCallback, lp ); - for (i = 0;i < nbft;i++) { // forearch hidden feature - if (sol->s[i] == -1) { - nbOverlap = INT_MAX; - start_p = featStartId[i]; - for (p = 0;p < featNbLp[i];p++) { - lp = labelpositions[start_p+p]; - lp->nbOverlap = 0; - amin[0] = DBL_MAX; - amax[0] = -DBL_MAX; - amin[1] = DBL_MAX; - amax[1] = -DBL_MAX; - for (c = 0;c < 4;c++) { - if (lp->x[c] < amin[0]) - amin[0] = lp->x[c]; - if (lp->x[c] > amax[0]) - amax[0] = lp->x[c]; - if (lp->y[c] < amin[1]) - amin[1] = lp->y[c]; - if (lp->y[c] > amax[1]) - amax[1] = lp->y[c]; - } - - - candidates_sol->Search (amin, amax, countOverlapCallback, lp); - - if (lp->nbOverlap < nbOverlap) { - retainedLabel = lp; - nbOverlap = lp->nbOverlap; - } - } - sol->s[i] = retainedLabel->id; + if ( lp->nbOverlap < nbOverlap ) + { + retainedLabel = lp; + nbOverlap = lp->nbOverlap; + } + } + sol->s[i] = retainedLabel->id; - retainedLabel->insertIntoIndex (candidates_sol); + retainedLabel->insertIntoIndex( candidates_sol ); - } - } } - - delete list; + } } + delete list; + } + //#define _DEBUG_ - void Problem::popmusic() { + void Problem::popmusic() + { - if (nbft == 0) - return; + if ( nbft == 0 ) + return; - int i; - int seed; - bool *ok = new bool[nbft]; + int i; + int seed; + bool *ok = new bool[nbft]; - int r = pal->popmusic_r; + int r = pal->popmusic_r; - SearchMethod searchMethod = pal->searchMethod; + SearchMethod searchMethod = pal->searchMethod; - candidates_subsol = new RTree(); + candidates_subsol = new RTree(); - double delta = 0.0; + double delta = 0.0; - int it = 0; + int it = 0; #ifdef _VERBOSE_ - clock_t start_time = clock(); - clock_t create_part_time; - clock_t init_sol_time; - clock_t search_time; + clock_t start_time = clock(); + clock_t create_part_time; + clock_t init_sol_time; + clock_t search_time; #endif - SubPart *current = NULL; + SubPart *current = NULL; - int subPartTotalSize = 0; + int subPartTotalSize = 0; - labelPositionCost = new double[all_nblp]; - nbOlap = new int[all_nblp]; + labelPositionCost = new double[all_nblp]; + nbOlap = new int[all_nblp]; - featWrap = new int[nbft]; - memset (featWrap, -1, sizeof (int) *nbft); + featWrap = new int[nbft]; + memset( featWrap, -1, sizeof( int ) *nbft ); - SubPart ** parts = new SubPart*[nbft]; - int *isIn = new int[nbft]; + SubPart ** parts = new SubPart*[nbft]; + int *isIn = new int[nbft]; - memset (isIn, 0, sizeof (int) *nbft); + memset( isIn, 0, sizeof( int ) *nbft ); - for (i = 0;i < nbft;i++) { - parts[i] = subPart (r, i, isIn); - subPartTotalSize += parts[i]->subSize; - ok[i] = false; - } - delete[] isIn; - sort ( (void**) parts, nbft, borderSizeInc); - //sort ((void**)parts, nbft, borderSizeDec); + for ( i = 0;i < nbft;i++ ) + { + parts[i] = subPart( r, i, isIn ); + subPartTotalSize += parts[i]->subSize; + ok[i] = false; + } + delete[] isIn; + sort(( void** ) parts, nbft, borderSizeInc ); + //sort ((void**)parts, nbft, borderSizeDec); #ifdef _VERBOSE_ - create_part_time = clock(); - std::cout << " SubPart (averagesize: " << subPartTotalSize / nbft << ") creation: " << (double) (create_part_time - start_time) / (double) CLOCKS_PER_SEC << std::endl; + create_part_time = clock(); + std::cout << " SubPart (averagesize: " << subPartTotalSize / nbft << ") creation: " << ( double )( create_part_time - start_time ) / ( double ) CLOCKS_PER_SEC << std::endl; #endif - init_sol_falp(); + init_sol_falp(); #ifdef _VERBOSE_ - init_sol_time = clock(); - std::cout << " Compute initial solution: " << (double) (init_sol_time - create_part_time) / (double) CLOCKS_PER_SEC; + init_sol_time = clock(); + std::cout << " Compute initial solution: " << ( double )( init_sol_time - create_part_time ) / ( double ) CLOCKS_PER_SEC; #endif - solution_cost(); + solution_cost(); #ifdef _VERBOSE_ - std::cerr << "\t" << sol->cost << "\t" << nbActive << "\t" << (double) nbActive / (double) nbft; - std::cout << " (solution cost: " << sol->cost << ", nbDisplayed: " << nbActive << "(" << (double) nbActive / (double) nbft << "%)" << std::endl; -#endif - - - int popit = 0; - - seed = 0; - while (true) { - it++; - /* find the next seed not ok */ - for (i = (seed + 1) % nbft;ok[i] && i != seed;i = (i + 1) % nbft); - - if (i == seed && ok[seed]) { - current = NULL; // everything is OK :-) - break; - } else { - seed = i; - current = parts[seed]; - } - - // update sub part solution - candidates_subsol->RemoveAll(); - - for (i = 0;i < current->subSize;i++) { - current->sol[i] = sol->s[current->sub[i]]; - if (current->sol[i] != -1) { - labelpositions[current->sol[i]]->insertIntoIndex (candidates_subsol); - } - } - - - - switch (searchMethod) { - //case branch_and_bound : - //delta = current->branch_and_bound_search(); - // break; - - case POPMUSIC_TABU : - delta = popmusic_tabu (current); - break; - case POPMUSIC_TABU_CHAIN : - delta = popmusic_tabu_chain (current); - break; - case POPMUSIC_CHAIN : - delta = popmusic_chain (current); - break; - default: + std::cerr << "\t" << sol->cost << "\t" << nbActive << "\t" << ( double ) nbActive / ( double ) nbft; + std::cout << " (solution cost: " << sol->cost << ", nbDisplayed: " << nbActive << "(" << ( double ) nbActive / ( double ) nbft << "%)" << std::endl; +#endif + + + int popit = 0; + + seed = 0; + while ( true ) + { + it++; + /* find the next seed not ok */ + for ( i = ( seed + 1 ) % nbft;ok[i] && i != seed;i = ( i + 1 ) % nbft ); + + if ( i == seed && ok[seed] ) + { + current = NULL; // everything is OK :-) + break; + } + else + { + seed = i; + current = parts[seed]; + } + + // update sub part solution + candidates_subsol->RemoveAll(); + + for ( i = 0;i < current->subSize;i++ ) + { + current->sol[i] = sol->s[current->sub[i]]; + if ( current->sol[i] != -1 ) + { + labelpositions[current->sol[i]]->insertIntoIndex( candidates_subsol ); + } + } + + + + switch ( searchMethod ) + { + //case branch_and_bound : + //delta = current->branch_and_bound_search(); + // break; + + case POPMUSIC_TABU : + delta = popmusic_tabu( current ); + break; + case POPMUSIC_TABU_CHAIN : + delta = popmusic_tabu_chain( current ); + break; + case POPMUSIC_CHAIN : + delta = popmusic_chain( current ); + break; + default: #ifdef _VERBOSE_ - std::cerr << "Unknown search method..." << std::endl; + std::cerr << "Unknown search method..." << std::endl; #endif - return; - } + return; + } - popit++; + popit++; - if (delta > EPSILON) { - /* Update solution */ + if ( delta > EPSILON ) + { + /* Update solution */ #ifdef _DEBUG_FULL_ - std::cout << "Update solution from subpart, current cost:" << std::endl; - solution_cost (); - std::cout << "Delta > EPSILON: update solution" << std::endl; - std::cout << "after modif cost:" << std::endl; - solution_cost (); -#endif - for (i = 0;i < current->borderSize;i++) { - ok[current->sub[i]] = false; - } + std::cout << "Update solution from subpart, current cost:" << std::endl; + solution_cost(); + std::cout << "Delta > EPSILON: update solution" << std::endl; + std::cout << "after modif cost:" << std::endl; + solution_cost(); +#endif + for ( i = 0;i < current->borderSize;i++ ) + { + ok[current->sub[i]] = false; + } - for (i = current->borderSize;i < current->subSize;i++) { + for ( i = current->borderSize;i < current->subSize;i++ ) + { - if (sol->s[current->sub[i]] != -1) { - labelpositions[sol->s[current->sub[i]]]->removeFromIndex (candidates_sol); - } + if ( sol->s[current->sub[i]] != -1 ) + { + labelpositions[sol->s[current->sub[i]]]->removeFromIndex( candidates_sol ); + } - sol->s[current->sub[i]] = current->sol[i]; + sol->s[current->sub[i]] = current->sol[i]; - if (current->sol[i] != -1) { - labelpositions[current->sol[i]]->insertIntoIndex (candidates_sol); - } + if ( current->sol[i] != -1 ) + { + labelpositions[current->sol[i]]->insertIntoIndex( candidates_sol ); + } - ok[current->sub[i]] = false; - } - } else {// not improved + ok[current->sub[i]] = false; + } + } + else // not improved + { #ifdef _DEBUG_FULL_ - std::cout << "subpart not improved" << std::endl; + std::cout << "subpart not improved" << std::endl; #endif - ok[seed] = true; - } - } + ok[seed] = true; + } + } - solution_cost(); + solution_cost(); #ifdef _VERBOSE_ - search_time = clock(); - std::cout << " Improved solution: " << (double) (search_time - start_time) / (double) CLOCKS_PER_SEC << " (solution cost: " << sol->cost << ", nbDisplayed: " << nbActive << " (" << (double) nbActive / (double) nbft << ")" << std::endl; + search_time = clock(); + std::cout << " Improved solution: " << ( double )( search_time - start_time ) / ( double ) CLOCKS_PER_SEC << " (solution cost: " << sol->cost << ", nbDisplayed: " << nbActive << " (" << ( double ) nbActive / ( double ) nbft << ")" << std::endl; - std::cerr << "\t" << subPartTotalSize; - if (searchMethod == POPMUSIC_TABU) - std::cerr << "\tpop_tabu\t"; - else if (searchMethod == POPMUSIC_TABU_CHAIN) - std::cerr << "\tpop_tabu_chain\t"; - else if (searchMethod == POPMUSIC_CHAIN) - std::cerr << "\tpop_chain\t"; + std::cerr << "\t" << subPartTotalSize; + if ( searchMethod == POPMUSIC_TABU ) + std::cerr << "\tpop_tabu\t"; + else if ( searchMethod == POPMUSIC_TABU_CHAIN ) + std::cerr << "\tpop_tabu_chain\t"; + else if ( searchMethod == POPMUSIC_CHAIN ) + std::cerr << "\tpop_chain\t"; - std::cerr << r << "\t" << popit << "\t" << (create_part_time - start_time) / (double) CLOCKS_PER_SEC << "\t" << (init_sol_time - create_part_time) / (double) CLOCKS_PER_SEC << "\t" << (search_time - init_sol_time) / (double) CLOCKS_PER_SEC << "\t" << (search_time - start_time) / (double) CLOCKS_PER_SEC << "\t" << sol->cost << "\t" << nbActive << "\t" << (double) nbActive / (double) nbft; + std::cerr << r << "\t" << popit << "\t" << ( create_part_time - start_time ) / ( double ) CLOCKS_PER_SEC << "\t" << ( init_sol_time - create_part_time ) / ( double ) CLOCKS_PER_SEC << "\t" << ( search_time - init_sol_time ) / ( double ) CLOCKS_PER_SEC << "\t" << ( search_time - start_time ) / ( double ) CLOCKS_PER_SEC << "\t" << sol->cost << "\t" << nbActive << "\t" << ( double ) nbActive / ( double ) nbft; #endif - delete[] labelPositionCost; - delete[] nbOlap; - - for (i = 0;i < nbft;i++) { - delete[] parts[i]->sub; - delete[] parts[i]->sol; - delete parts[i]; - } - delete[] parts; - - delete[] ok; + delete[] labelPositionCost; + delete[] nbOlap; - return; + for ( i = 0;i < nbft;i++ ) + { + delete[] parts[i]->sub; + delete[] parts[i]->sol; + delete parts[i]; } -#undef _DEBUG_ - - typedef struct { - LinkedList *queue; - int *isIn; - LabelPosition *lp; - } SubPartContext; - - bool subPartCallback (LabelPosition *lp, void *ctx) { - int lpid = lp->id; - int *isIn = ( (SubPartContext*) ctx)->isIn; - LinkedList *queue = ( (SubPartContext*) ctx)->queue; + delete[] parts; + delete[] ok; - int id = lp->probFeat; - if (!isIn[id] && lp->isInConflict ( ( (SubPartContext*) ctx)->lp)) { - queue->push_back (id); - isIn[id] = 1; - } + return; + } +#undef _DEBUG_ - return true; + typedef struct + { + LinkedList *queue; + int *isIn; + LabelPosition *lp; + } SubPartContext; + + bool subPartCallback( LabelPosition *lp, void *ctx ) + { + int lpid = lp->id; + int *isIn = (( SubPartContext* ) ctx )->isIn; + LinkedList *queue = (( SubPartContext* ) ctx )->queue; + + + int id = lp->probFeat; + if ( !isIn[id] && lp->isInConflict((( SubPartContext* ) ctx )->lp ) ) + { + queue->push_back( id ); + isIn[id] = 1; } - /* Select a sub part, expected size of r, from seed */ - SubPart * Problem::subPart (int r, int featseed, int *isIn) { - LinkedList *queue = new LinkedList (intCompare); - LinkedList *ri = new LinkedList (intCompare); - - int *sub; - - int id; - register int featS; - register int p; - int i; - int c; - - int n = 0; - int nb = 0; - - double amin[2]; - double amax[2]; - - SubPartContext context; - context.queue = queue; - context.isIn = isIn; - - queue->push_back (featseed); - isIn[featseed] = 1; - - LabelPosition *lp; - - while (ri->size() < r && queue->size() > 0) { - id = queue->pop_front(); - ri->push_back (id); - - featS = featStartId[id]; - p = featNbLp[id]; - - for (i = featS;i < featS + p;i++) { // foreach candidat of feature 'id' - lp = labelpositions[i]; - amin[0] = DBL_MAX; - amax[0] = -DBL_MAX; - amin[1] = DBL_MAX; - amax[1] = -DBL_MAX; - for (c = 0;c < 4;c++) { - if (lp->x[c] < amin[0]) - amin[0] = lp->x[c]; - if (lp->x[c] > amax[0]) - amax[0] = lp->x[c]; - if (lp->y[c] < amin[1]) - amin[1] = lp->y[c]; - if (lp->y[c] > amax[1]) - amax[1] = lp->y[c]; - } - context.lp = lp; - candidates->Search (amin, amax, subPartCallback, (void*) &context); - } + return true; + } + + /* Select a sub part, expected size of r, from seed */ + SubPart * Problem::subPart( int r, int featseed, int *isIn ) + { + LinkedList *queue = new LinkedList ( intCompare ); + LinkedList *ri = new LinkedList ( intCompare ); + + int *sub; + + int id; + register int featS; + register int p; + int i; + int c; + + int n = 0; + int nb = 0; + + double amin[2]; + double amax[2]; + + SubPartContext context; + context.queue = queue; + context.isIn = isIn; + + queue->push_back( featseed ); + isIn[featseed] = 1; + + LabelPosition *lp; + + while ( ri->size() < r && queue->size() > 0 ) + { + id = queue->pop_front(); + ri->push_back( id ); + + featS = featStartId[id]; + p = featNbLp[id]; + + for ( i = featS;i < featS + p;i++ ) // foreach candidat of feature 'id' + { + lp = labelpositions[i]; + amin[0] = DBL_MAX; + amax[0] = -DBL_MAX; + amin[1] = DBL_MAX; + amax[1] = -DBL_MAX; + for ( c = 0;c < 4;c++ ) + { + if ( lp->x[c] < amin[0] ) + amin[0] = lp->x[c]; + if ( lp->x[c] > amax[0] ) + amax[0] = lp->x[c]; + if ( lp->y[c] < amin[1] ) + amin[1] = lp->y[c]; + if ( lp->y[c] > amax[1] ) + amax[1] = lp->y[c]; } - - nb = queue->size(); - n = ri->size(); - - sub = new int[n+nb]; - - i = 0; - - while (queue->size() > 0) { - sub[i] = queue->pop_front(); - isIn[sub[i]] = 0; - i++; - } - - while (ri->size() > 0) { - sub[i] = ri->pop_front(); - isIn[sub[i]] = 0; - i++; - } - - delete queue; - delete ri; - - SubPart *subPart = new SubPart(); - - subPart->probSize = n; - subPart->borderSize = nb; - subPart->subSize = n + nb; - subPart->sub = sub; - subPart->sol = new int [subPart->subSize]; - subPart->seed = featseed; - return subPart; + context.lp = lp; + candidates->Search( amin, amax, subPartCallback, ( void* ) &context ); + } } + nb = queue->size(); + n = ri->size(); - /** From SubPart.cpp ***/ + sub = new int[n+nb]; - double Problem::compute_feature_cost (SubPart *part, int feat_id, int label_id, int *nbOverlap) { - double cost; - *nbOverlap = 0; + i = 0; - int c; - - CountContext context; - context.inactiveCost = inactiveCost; - context.nbOv = nbOverlap; - context.cost = &cost; + while ( queue->size() > 0 ) + { + sub[i] = queue->pop_front(); + isIn[sub[i]] = 0; + i++; + } - double amin[2]; - double amax[2]; - LabelPosition *lp; + while ( ri->size() > 0 ) + { + sub[i] = ri->pop_front(); + isIn[sub[i]] = 0; + i++; + } - cost = 0.0; + delete queue; + delete ri; + + SubPart *subPart = new SubPart(); + + subPart->probSize = n; + subPart->borderSize = nb; + subPart->subSize = n + nb; + subPart->sub = sub; + subPart->sol = new int [subPart->subSize]; + subPart->seed = featseed; + return subPart; + } + + + /** From SubPart.cpp ***/ + + double Problem::compute_feature_cost( SubPart *part, int feat_id, int label_id, int *nbOverlap ) + { + double cost; + *nbOverlap = 0; + + int c; + + CountContext context; + context.inactiveCost = inactiveCost; + context.nbOv = nbOverlap; + context.cost = &cost; + + double amin[2]; + double amax[2]; + LabelPosition *lp; + + cost = 0.0; + + if ( label_id >= 0 ) // is the feature displayed ? + { + lp = labelpositions[label_id]; + + amin[0] = DBL_MAX; + amax[0] = -DBL_MAX; + amin[1] = DBL_MAX; + amax[1] = -DBL_MAX; + for ( c = 0;c < 4;c++ ) + { + if ( lp->x[c] < amin[0] ) + amin[0] = lp->x[c]; + if ( lp->x[c] > amax[0] ) + amax[0] = lp->x[c]; + if ( lp->y[c] < amin[1] ) + amin[1] = lp->y[c]; + if ( lp->y[c] > amax[1] ) + amax[1] = lp->y[c]; + } + context.lp = lp; + candidates_subsol->Search( amin, amax, countFullOverlapCallback, ( void* ) &context ); + + cost += lp->cost; + } + else + { + cost = inactiveCost[part->sub[feat_id]]; + //(*nbOverlap)++; + } - if (label_id >= 0) { // is the feature displayed ? - lp = labelpositions[label_id]; + return cost; - amin[0] = DBL_MAX; - amax[0] = -DBL_MAX; - amin[1] = DBL_MAX; - amax[1] = -DBL_MAX; - for (c = 0;c < 4;c++) { - if (lp->x[c] < amin[0]) - amin[0] = lp->x[c]; - if (lp->x[c] > amax[0]) - amax[0] = lp->x[c]; - if (lp->y[c] < amin[1]) - amin[1] = lp->y[c]; - if (lp->y[c] > amax[1]) - amax[1] = lp->y[c]; - } - context.lp = lp; - candidates_subsol->Search (amin, amax, countFullOverlapCallback, (void*) &context); + } - cost += lp->cost; - } else { - cost = inactiveCost[part->sub[feat_id]]; - //(*nbOverlap)++; - } + double Problem::compute_subsolution_cost( SubPart *part, int *s, int *nbOverlap ) + { + int i; + double cost = 0.0; + int nbO = 0; - return cost; + *nbOverlap = 0; + for ( i = 0;i < part->subSize;i++ ) + { + cost += compute_feature_cost( part, i, s[i], &nbO ); + *nbOverlap += nbO; } - double Problem::compute_subsolution_cost (SubPart *part, int *s, int *nbOverlap) { - int i; - double cost = 0.0; - int nbO = 0; + return cost; + } - *nbOverlap = 0; - for (i = 0;i < part->subSize;i++) { - cost += compute_feature_cost (part, i, s[i], &nbO); - *nbOverlap += nbO; - } - return cost; - } + typedef struct _Triple + { + int feat_id; + int label_id; + double cost; + int nbOverlap; + } Triple; + bool decreaseCost( void *tl, void *tr ) + { + return (( Triple* ) tl )->cost < (( Triple* ) tr )->cost; + } - typedef struct _Triple { - int feat_id; - int label_id; - double cost; - int nbOverlap; - } Triple; + bool increaseCost( void *tl, void *tr ) + { + return (( Triple* ) tl )->cost > (( Triple* ) tr )->cost; + } - bool decreaseCost (void *tl, void *tr) { - return ( (Triple*) tl)->cost < ( (Triple*) tr)->cost; - } - bool increaseCost (void *tl, void *tr) { - return ( (Triple*) tl)->cost > ( (Triple*) tr)->cost; - } + inline void actualizeTabuCandidateList( int m, int iteration, int nbOverlap, int *candidateListSize, + double candidateBaseFactor, double *candidateFactor, + int minCandidateListSize, double reductionFactor, + int minTabuTSize, double tabuFactor, int *tenure, int n ) + { + if ( *candidateFactor > candidateBaseFactor ) + *candidateFactor /= reductionFactor; + if ( iteration % m == 0 ) + { + *tenure = minTabuTSize + ( int )( tabuFactor * nbOverlap ); + *candidateListSize = minCandidateListSize + ( int )( *candidateFactor * nbOverlap ); - inline void actualizeTabuCandidateList (int m, int iteration, int nbOverlap, int *candidateListSize, - double candidateBaseFactor, double *candidateFactor, - int minCandidateListSize, double reductionFactor, - int minTabuTSize, double tabuFactor, int *tenure, int n) { + if ( *candidateListSize > n ) + *candidateListSize = n; + } - if (*candidateFactor > candidateBaseFactor) - *candidateFactor /= reductionFactor; + } - if (iteration % m == 0) { - *tenure = minTabuTSize + (int) (tabuFactor * nbOverlap); - *candidateListSize = minCandidateListSize + (int) (*candidateFactor * nbOverlap); - if (*candidateListSize > n) - *candidateListSize = n; - } + inline void actualizeCandidateList( int nbOverlap, int *candidateListSize, double candidateBaseFactor, + double *candidateFactor, int minCandidateListSize, double growingFactor, int n ) + { - } + candidateBaseFactor += 0; + if ( *candidateListSize < n ) + *candidateFactor = *candidateFactor * growingFactor; + *candidateListSize = minCandidateListSize + ( int )( *candidateFactor * nbOverlap ); - inline void actualizeCandidateList (int nbOverlap, int *candidateListSize, double candidateBaseFactor, - double *candidateFactor, int minCandidateListSize, double growingFactor, int n) { + if ( *candidateListSize > n ) + *candidateListSize = n; + } - candidateBaseFactor += 0; - if (*candidateListSize < n) - *candidateFactor = *candidateFactor * growingFactor; - *candidateListSize = minCandidateListSize + (int) (*candidateFactor * nbOverlap); - if (*candidateListSize > n) - *candidateListSize = n; - } + typedef struct + { + LabelPosition *lp; + Triple **candidates; + double *labelPositionCost; + int *nbOlap; + double diff_cost; + int *featWrap; + int *sol; + int borderSize; + } UpdateContext; + bool updateCandidatesCost( LabelPosition *lp, void *context ) + { + UpdateContext *ctx = ( UpdateContext* ) context; + if ( ctx->lp->isInConflict( lp ) ) + { + ctx->labelPositionCost[lp->id] += ctx->diff_cost; + if ( ctx->diff_cost > 0 ) + ctx->nbOlap[lp->id]++; + else + ctx->nbOlap[lp->id]--; - typedef struct { - LabelPosition *lp; - Triple **candidates; - double *labelPositionCost; - int *nbOlap; - double diff_cost; - int *featWrap; - int *sol; - int borderSize; - } UpdateContext; - - bool updateCandidatesCost (LabelPosition *lp, void *context) { - UpdateContext *ctx = (UpdateContext*) context; - - if (ctx->lp->isInConflict (lp)) { - ctx->labelPositionCost[lp->id] += ctx->diff_cost; - if (ctx->diff_cost > 0) - ctx->nbOlap[lp->id]++; - else - ctx->nbOlap[lp->id]--; - - int feat_id = ctx->featWrap[ctx->lp->probFeat]; - int feat_id2; - if (feat_id >= 0 && ctx->sol[feat_id] == lp->id) { // this label is in use - if ( (feat_id2 = feat_id - ctx->borderSize) >= 0) { - ctx->candidates[feat_id2]->cost += ctx->diff_cost; - ctx->candidates[feat_id2]->nbOverlap--; - } - } + int feat_id = ctx->featWrap[ctx->lp->probFeat]; + int feat_id2; + if ( feat_id >= 0 && ctx->sol[feat_id] == lp->id ) // this label is in use + { + if (( feat_id2 = feat_id - ctx->borderSize ) >= 0 ) + { + ctx->candidates[feat_id2]->cost += ctx->diff_cost; + ctx->candidates[feat_id2]->nbOverlap--; } - return true; + } } + return true; + } - double Problem::popmusic_tabu (SubPart *part) { + double Problem::popmusic_tabu( SubPart *part ) + { #ifdef _DEBUG_FULL_ - std::cout << "Subpart: Tabu Search" << std::endl; + std::cout << "Subpart: Tabu Search" << std::endl; #endif - int probSize = part->probSize; - int borderSize = part->borderSize; - int subSize = part->subSize; - int *sub = part->sub; - int *sol = part->sol; + int probSize = part->probSize; + int borderSize = part->borderSize; + int subSize = part->subSize; + int *sub = part->sub; + int *sol = part->sol; - Triple **candidateList = new Triple*[probSize]; - Triple **candidateListUnsorted = new Triple*[probSize]; + Triple **candidateList = new Triple*[probSize]; + Triple **candidateListUnsorted = new Triple*[probSize]; - int * best_sol = new int[subSize]; + int * best_sol = new int[subSize]; - double cur_cost; - double best_cost; - double initial_cost; + double cur_cost; + double best_cost; + double initial_cost; - int *tabu_list = new int[probSize]; + int *tabu_list = new int[probSize]; - int i; - int j; + int i; + int j; - int itwImp; - int it = 0; - int max_it; - int stop_it; + int itwImp; + int it = 0; + int max_it; + int stop_it; - double delta; - double delta_min; - bool authorized; + double delta; + double delta_min; + bool authorized; - int feat_id; - int feat_sub_id; - int label_id; - int p; + int feat_id; + int feat_sub_id; + int label_id; + int p; - int choosed_feat; - int choosed_label; - int candidateId; + int choosed_feat; + int choosed_label; + int candidateId; - int nbOverlap = 0; - //int nbOverlapLabel; + int nbOverlap = 0; + //int nbOverlapLabel; - int tenure = 10; // - int m = 50; // m [10;50] + int tenure = 10; // + int m = 50; // m [10;50] - int minTabuTSize = 9; // min_t [2;10] - double tabuFactor = 0.5; // p_t [0.1;0.8] + int minTabuTSize = 9; // min_t [2;10] + double tabuFactor = 0.5; // p_t [0.1;0.8] - int minCandidateListSize = 18; // min_c [2;20] + int minCandidateListSize = 18; // min_c [2;20] - double candidateBaseFactor = 0.73; // p_base [0.1;0.8] + double candidateBaseFactor = 0.73; // p_base [0.1;0.8] - double growingFactor = 15; // fa [5;20] - double reductionFactor = 1.3; // f_r [1.1;1.5] + double growingFactor = 15; // fa [5;20] + double reductionFactor = 1.3; // f_r [1.1;1.5] - int candidateListSize = minCandidateListSize; - double candidateFactor = candidateBaseFactor; + int candidateListSize = minCandidateListSize; + double candidateFactor = candidateBaseFactor; - int first_lp; + int first_lp; - //double EPSILON = 0.000001; - max_it = probSize * pal->tabuMaxIt; - itwImp = probSize * pal->tabuMinIt; - stop_it = itwImp; + //double EPSILON = 0.000001; + max_it = probSize * pal->tabuMaxIt; + itwImp = probSize * pal->tabuMinIt; + stop_it = itwImp; - max_it = probSize * pal->tabuMaxIt; + max_it = probSize * pal->tabuMaxIt; - cur_cost = 0.0; - nbOverlap = 0; + cur_cost = 0.0; + nbOverlap = 0; - int lp; - for (i = 0;i < subSize;i++) - featWrap[sub[i]] = i; + int lp; + for ( i = 0;i < subSize;i++ ) + featWrap[sub[i]] = i; - for (i = 0;i < subSize;i++) { - j = featStartId[sub[i]]; - for (lp = 0;lp < featNbLp[sub[i]];lp++) { - it = j + lp; - //std::cerr << "it = " << j << " + " << lp << std::endl; - // std::cerr << "it/nblp:" << it << "/" << all_nblp << std::endl; - labelPositionCost[it] = compute_feature_cost (part, i, it, & (nbOlap[it])); - //std::cerr << "nbOlap[" << it << "] : " << nbOlap[it] << std::endl; - } - } + for ( i = 0;i < subSize;i++ ) + { + j = featStartId[sub[i]]; + for ( lp = 0;lp < featNbLp[sub[i]];lp++ ) + { + it = j + lp; + //std::cerr << "it = " << j << " + " << lp << std::endl; + // std::cerr << "it/nblp:" << it << "/" << all_nblp << std::endl; + labelPositionCost[it] = compute_feature_cost( part, i, it, & ( nbOlap[it] ) ); + //std::cerr << "nbOlap[" << it << "] : " << nbOlap[it] << std::endl; + } + } - first_lp = (displayAll ? 0 : -1); - for (i = 0;i < probSize;i++) { + first_lp = ( displayAll ? 0 : -1 ); + for ( i = 0;i < probSize;i++ ) + { - tabu_list[i] = -1; // nothing is tabu + tabu_list[i] = -1; // nothing is tabu - candidateList[i] = new Triple(); - candidateList[i]->feat_id = i + borderSize; - candidateList[i]->label_id = sol[i+borderSize]; + candidateList[i] = new Triple(); + candidateList[i]->feat_id = i + borderSize; + candidateList[i]->label_id = sol[i+borderSize]; - candidateListUnsorted[i] = candidateList[i]; + candidateListUnsorted[i] = candidateList[i]; - if (sol[i+borderSize] >= 0) { - j = sol[i+borderSize]; - candidateList[i]->cost = labelPositionCost[j]; - candidateList[i]->nbOverlap = nbOlap[j]; - } else { - candidateList[i]->cost = inactiveCost[sub[i+borderSize]]; - candidateList[i]->nbOverlap = 1; - } + if ( sol[i+borderSize] >= 0 ) + { + j = sol[i+borderSize]; + candidateList[i]->cost = labelPositionCost[j]; + candidateList[i]->nbOverlap = nbOlap[j]; + } + else + { + candidateList[i]->cost = inactiveCost[sub[i+borderSize]]; + candidateList[i]->nbOverlap = 1; + } - } + } - for (i = 0;i < subSize;i++) { - if (sol[i] == -1) { - cur_cost += inactiveCost[sub[i]]; - } else { - nbOverlap += nbOlap[sol[i]]; - cur_cost += labelPositionCost[sol[i]]; - } - } + for ( i = 0;i < subSize;i++ ) + { + if ( sol[i] == -1 ) + { + cur_cost += inactiveCost[sub[i]]; + } + else + { + nbOverlap += nbOlap[sol[i]]; + cur_cost += labelPositionCost[sol[i]]; + } + } - sort ( (void**) candidateList, probSize, decreaseCost); + sort(( void** ) candidateList, probSize, decreaseCost ); - best_cost = cur_cost; - initial_cost = cur_cost; - memcpy (best_sol, sol, sizeof (int) * (subSize)); + best_cost = cur_cost; + initial_cost = cur_cost; + memcpy( best_sol, sol, sizeof( int ) * ( subSize ) ); - // START TABU + // START TABU - it = 0; - while (it < stop_it && best_cost >= EPSILON) { + it = 0; + while ( it < stop_it && best_cost >= EPSILON ) + { #ifdef _DEBUG_FULL_ - std::cout << " ITERATION : " << it << " stop: " << stop_it << std::endl; + std::cout << " ITERATION : " << it << " stop: " << stop_it << std::endl; #endif - actualizeTabuCandidateList (m, it, nbOverlap, &candidateListSize, candidateBaseFactor, &candidateFactor, minCandidateListSize, reductionFactor, minTabuTSize, tabuFactor, &tenure, probSize); - delta_min = DBL_MAX; - choosed_feat = -1; - choosed_label = -2; - candidateId = -1; + actualizeTabuCandidateList( m, it, nbOverlap, &candidateListSize, candidateBaseFactor, &candidateFactor, minCandidateListSize, reductionFactor, minTabuTSize, tabuFactor, &tenure, probSize ); + delta_min = DBL_MAX; + choosed_feat = -1; + choosed_label = -2; + candidateId = -1; - // foreach retained Candidate - for (i = 0;i < candidateListSize;i++) { - feat_id = candidateList[i]->feat_id; - feat_sub_id = sub[feat_id]; - label_id = candidateList[i]->label_id; + // foreach retained Candidate + for ( i = 0;i < candidateListSize;i++ ) + { + feat_id = candidateList[i]->feat_id; + feat_sub_id = sub[feat_id]; + label_id = candidateList[i]->label_id; - int oldPos = (label_id < 0 ? -1 : label_id - featStartId[feat_sub_id]); + int oldPos = ( label_id < 0 ? -1 : label_id - featStartId[feat_sub_id] ); - p = featNbLp[feat_sub_id]; + p = featNbLp[feat_sub_id]; - /* label -1 means inactive feature */ - // foreach labelposition of feature minus the one in the solution - for (j = first_lp;j < p;j++) { - if (j != oldPos) { + /* label -1 means inactive feature */ + // foreach labelposition of feature minus the one in the solution + for ( j = first_lp;j < p;j++ ) + { + if ( j != oldPos ) + { - if (sol[feat_id] < 0) { - delta = -inactiveCost[feat_sub_id]; - } else { - delta = -labelPositionCost[sol[feat_id]]; - delta -= nbOlap[sol[feat_id]] * (inactiveCost[feat_sub_id] + labelpositions[label_id]->cost); - } + if ( sol[feat_id] < 0 ) + { + delta = -inactiveCost[feat_sub_id]; + } + else + { + delta = -labelPositionCost[sol[feat_id]]; + delta -= nbOlap[sol[feat_id]] * ( inactiveCost[feat_sub_id] + labelpositions[label_id]->cost ); + } - if (j >= 0) { - delta += labelPositionCost[featStartId[feat_sub_id] + j]; - delta += nbOlap[featStartId[feat_sub_id] + j] * (inactiveCost[feat_sub_id] + labelpositions[featStartId[feat_sub_id] + j]->cost); - } else { - delta += inactiveCost[feat_sub_id]; - } + if ( j >= 0 ) + { + delta += labelPositionCost[featStartId[feat_sub_id] + j]; + delta += nbOlap[featStartId[feat_sub_id] + j] * ( inactiveCost[feat_sub_id] + labelpositions[featStartId[feat_sub_id] + j]->cost ); + } + else + { + delta += inactiveCost[feat_sub_id]; + } #ifdef _DEBUG_FULL_ - std::cout << " test moving " << oldPos << " to " << featStartId[feat_sub_id] + j << std::endl; - std::cout << " new pos makes " << nbOlap[featStartId[feat_sub_id] + j] << " overlaps" << std::endl; - std::cout << " delta is : " << delta << std::endl; + std::cout << " test moving " << oldPos << " to " << featStartId[feat_sub_id] + j << std::endl; + std::cout << " new pos makes " << nbOlap[featStartId[feat_sub_id] + j] << " overlaps" << std::endl; + std::cout << " delta is : " << delta << std::endl; #endif - // move is authorized wether the feat isn't taboo or whether the move give a new best solution - authorized = (tabu_list[feat_id - borderSize] <= it) || (cur_cost + delta < best_cost); + // move is authorized wether the feat isn't taboo or whether the move give a new best solution + authorized = ( tabu_list[feat_id - borderSize] <= it ) || ( cur_cost + delta < best_cost ); #ifdef _DEBUG_FULL_ - if (tabu_list[feat_id - borderSize] > it) { - std::cout << " Move is tabu" << std::endl; - } else { - std::cout << " Move is ok" << std::endl; - } + if ( tabu_list[feat_id - borderSize] > it ) + { + std::cout << " Move is tabu" << std::endl; + } + else + { + std::cout << " Move is ok" << std::endl; + } #endif - if (delta < delta_min && authorized) { + if ( delta < delta_min && authorized ) + { #ifdef _DEBUG_FULL_ - std::cout << " keep move" << std::endl; - std::cout << " choosed_feat: " << feat_id << std::endl; - if (j == -1) - std::cout << " choosed_label: " << j << std::endl; - else - std::cout << " choosed_label: " << featStartId[feat_sub_id] + j << std::endl; + std::cout << " keep move" << std::endl; + std::cout << " choosed_feat: " << feat_id << std::endl; + if ( j == -1 ) + std::cout << " choosed_label: " << j << std::endl; + else + std::cout << " choosed_label: " << featStartId[feat_sub_id] + j << std::endl; - std::cout << " delta: " << delta << std::endl; + std::cout << " delta: " << delta << std::endl; #endif - choosed_feat = feat_id; + choosed_feat = feat_id; - if (j == -1) - choosed_label = -1; - else - choosed_label = featStartId[feat_sub_id] + j; + if ( j == -1 ) + choosed_label = -1; + else + choosed_label = featStartId[feat_sub_id] + j; - delta_min = delta; - candidateId = i; - } + delta_min = delta; + candidateId = i; + } #ifdef _DEBUG_FULL_ - else if (!authorized) { - std::cout << " tabu" << std::endl; - } else { - std::cout << " no good enough" << std::endl; - } -#endif - } - } + else if ( !authorized ) + { + std::cout << " tabu" << std::endl; + } + else + { + std::cout << " no good enough" << std::endl; } +#endif + } + } + } - // if a modification has been retained - if (choosed_feat >= 0) { + // if a modification has been retained + if ( choosed_feat >= 0 ) + { #ifdef _DEBUG_FULL_ - std::cout << " Apply move:" << std::endl; - std::cout << " feat: " << choosed_feat << std::endl; - std::cout << " label: " << choosed_label << std::endl; - std::cout << " delta: " << delta_min << std::endl << std::endl; -#endif - // update the solution and update tabu list - int old_label = sol[choosed_feat]; - - tabu_list[choosed_feat-borderSize] = it + tenure; - sol[choosed_feat] = choosed_label; - candidateList[candidateId]->label_id = choosed_label; - - if (old_label != -1) - labelpositions[old_label]->removeFromIndex (candidates_subsol); - - /* re-compute all labelpositioncost that overlap with old an new label */ - double local_inactive = inactiveCost[sub[choosed_feat]]; - - if (choosed_label != -1) { - candidateList[candidateId]->cost = labelPositionCost[choosed_label]; - candidateList[candidateId]->nbOverlap = nbOlap[choosed_label]; - } else { - candidateList[candidateId]->cost = local_inactive; - candidateList[candidateId]->nbOverlap = 1; - } + std::cout << " Apply move:" << std::endl; + std::cout << " feat: " << choosed_feat << std::endl; + std::cout << " label: " << choosed_label << std::endl; + std::cout << " delta: " << delta_min << std::endl << std::endl; +#endif + // update the solution and update tabu list + int old_label = sol[choosed_feat]; - cur_cost += delta_min; - - double amin[2]; - double amax[2]; - int c; - LabelPosition *lp; - - UpdateContext context; - - context.candidates = candidateListUnsorted; - context.labelPositionCost = labelPositionCost; - context.nbOlap = nbOlap; - context.featWrap = featWrap; - context.sol = sol; - context.borderSize = borderSize; - - if (old_label >= 0) { - lp = labelpositions[old_label]; - - - amin[0] = DBL_MAX; - amax[0] = -DBL_MAX; - amin[1] = DBL_MAX; - amax[1] = -DBL_MAX; - for (c = 0;c < 4;c++) { - if (lp->x[c] < amin[0]) - amin[0] = lp->x[c]; - if (lp->x[c] > amax[0]) - amax[0] = lp->x[c]; - if (lp->y[c] < amin[1]) - amin[1] = lp->y[c]; - if (lp->y[c] > amax[1]) - amax[1] = lp->y[c]; - } - context.diff_cost = -local_inactive - labelpositions[old_label]->cost; - context.lp = labelpositions[old_label]; - - candidates->Search (amin, amax, updateCandidatesCost, &context); - } + tabu_list[choosed_feat-borderSize] = it + tenure; + sol[choosed_feat] = choosed_label; + candidateList[candidateId]->label_id = choosed_label; - if (choosed_label >= 0) { - lp = labelpositions[choosed_label]; + if ( old_label != -1 ) + labelpositions[old_label]->removeFromIndex( candidates_subsol ); + /* re-compute all labelpositioncost that overlap with old an new label */ + double local_inactive = inactiveCost[sub[choosed_feat]]; - amin[0] = DBL_MAX; - amax[0] = -DBL_MAX; - amin[1] = DBL_MAX; - amax[1] = -DBL_MAX; - for (c = 0;c < 4;c++) { - if (lp->x[c] < amin[0]) - amin[0] = lp->x[c]; - if (lp->x[c] > amax[0]) - amax[0] = lp->x[c]; - if (lp->y[c] < amin[1]) - amin[1] = lp->y[c]; - if (lp->y[c] > amax[1]) - amax[1] = lp->y[c]; - } + if ( choosed_label != -1 ) + { + candidateList[candidateId]->cost = labelPositionCost[choosed_label]; + candidateList[candidateId]->nbOverlap = nbOlap[choosed_label]; + } + else + { + candidateList[candidateId]->cost = local_inactive; + candidateList[candidateId]->nbOverlap = 1; + } - context.diff_cost = local_inactive + labelpositions[choosed_label]->cost; - context.lp = labelpositions[choosed_label]; + cur_cost += delta_min; + double amin[2]; + double amax[2]; + int c; + LabelPosition *lp; - candidates->Search (amin, amax, updateCandidatesCost, &context); + UpdateContext context; - lp->insertIntoIndex (candidates_subsol); - } + context.candidates = candidateListUnsorted; + context.labelPositionCost = labelPositionCost; + context.nbOlap = nbOlap; + context.featWrap = featWrap; + context.sol = sol; + context.borderSize = borderSize; - sort ( (void**) candidateList, probSize, decreaseCost); + if ( old_label >= 0 ) + { + lp = labelpositions[old_label]; + + + amin[0] = DBL_MAX; + amax[0] = -DBL_MAX; + amin[1] = DBL_MAX; + amax[1] = -DBL_MAX; + for ( c = 0;c < 4;c++ ) + { + if ( lp->x[c] < amin[0] ) + amin[0] = lp->x[c]; + if ( lp->x[c] > amax[0] ) + amax[0] = lp->x[c]; + if ( lp->y[c] < amin[1] ) + amin[1] = lp->y[c]; + if ( lp->y[c] > amax[1] ) + amax[1] = lp->y[c]; + } + context.diff_cost = -local_inactive - labelpositions[old_label]->cost; + context.lp = labelpositions[old_label]; + + candidates->Search( amin, amax, updateCandidatesCost, &context ); + } - if (best_cost - cur_cost > EPSILON) { // new best sol - best_cost = cur_cost; - memcpy (best_sol, sol, sizeof (int) * (subSize)); - stop_it = it + itwImp; - if (stop_it > max_it) - stop_it = max_it; - } - } else { - /* no feature was selected : increase candidate list size*/ - actualizeCandidateList (nbOverlap, &candidateListSize, candidateBaseFactor, - &candidateFactor, minCandidateListSize, growingFactor, probSize); - } + if ( choosed_label >= 0 ) + { + lp = labelpositions[choosed_label]; + + + amin[0] = DBL_MAX; + amax[0] = -DBL_MAX; + amin[1] = DBL_MAX; + amax[1] = -DBL_MAX; + for ( c = 0;c < 4;c++ ) + { + if ( lp->x[c] < amin[0] ) + amin[0] = lp->x[c]; + if ( lp->x[c] > amax[0] ) + amax[0] = lp->x[c]; + if ( lp->y[c] < amin[1] ) + amin[1] = lp->y[c]; + if ( lp->y[c] > amax[1] ) + amax[1] = lp->y[c]; + } + + context.diff_cost = local_inactive + labelpositions[choosed_label]->cost; + context.lp = labelpositions[choosed_label]; + + + candidates->Search( amin, amax, updateCandidatesCost, &context ); + + lp->insertIntoIndex( candidates_subsol ); + } + + sort(( void** ) candidateList, probSize, decreaseCost ); + + if ( best_cost - cur_cost > EPSILON ) // new best sol + { + best_cost = cur_cost; + memcpy( best_sol, sol, sizeof( int ) * ( subSize ) ); + stop_it = it + itwImp; + if ( stop_it > max_it ) + stop_it = max_it; + } + } + else + { + /* no feature was selected : increase candidate list size*/ + actualizeCandidateList( nbOverlap, &candidateListSize, candidateBaseFactor, + &candidateFactor, minCandidateListSize, growingFactor, probSize ); + } #ifdef _DEBUG_FULL_ - std::cout << "cost : " << cur_cost << std::endl; - int nbover; - std::cout << "computed cost: " << compute_subsolution_cost (part, sol, &nbover) << std::endl; - std::cout << "best_cost: " << best_cost << std::endl << std::endl; + std::cout << "cost : " << cur_cost << std::endl; + int nbover; + std::cout << "computed cost: " << compute_subsolution_cost( part, sol, &nbover ) << std::endl; + std::cout << "best_cost: " << best_cost << std::endl << std::endl; #endif - it++; - } + it++; + } - memcpy (sol, best_sol, sizeof (int) * (subSize)); + memcpy( sol, best_sol, sizeof( int ) * ( subSize ) ); - for (i = 0;i < subSize;i++) - featWrap[sub[i]] = -1; + for ( i = 0;i < subSize;i++ ) + featWrap[sub[i]] = -1; - for (i = 0;i < probSize;i++) - delete candidateList[i]; + for ( i = 0;i < probSize;i++ ) + delete candidateList[i]; - delete[] candidateList; - delete[] candidateListUnsorted; - delete[] best_sol; - delete[] tabu_list; + delete[] candidateList; + delete[] candidateListUnsorted; + delete[] best_sol; + delete[] tabu_list; - /* Return delta */ - return initial_cost - best_cost; - } + /* Return delta */ + return initial_cost - best_cost; + } - typedef struct { - LabelPosition *lp; - int *tmpsol; - int *featWrap; - int *feat; - int borderSize; - LinkedList *currentChain; - LinkedList *conflicts; - double *delta_tmp; - double *inactiveCost; + typedef struct + { + LabelPosition *lp; + int *tmpsol; + int *featWrap; + int *feat; + int borderSize; + LinkedList *currentChain; + LinkedList *conflicts; + double *delta_tmp; + double *inactiveCost; - } ChainContext; + } ChainContext; - bool chainCallback (LabelPosition *lp, void *context) { - ChainContext *ctx = (ChainContext*) context; + bool chainCallback( LabelPosition *lp, void *context ) + { + ChainContext *ctx = ( ChainContext* ) context; #ifdef _DEBUG_FULL_ - std::cout << "chainCallback" << std::endl; - std::cout << " lp from rtree: " << lp << std::endl; - std::cout << " lpid from rtree: " << lp->id << std::endl; - std::cout << " lpco from rtree: " << lp->cost << std::endl; - std::cout << " lp from context: " << ctx->lp << std::endl; - std::cout << " lpid from context: " << ctx->lp->id << std::endl; - std::cout << " lpco from context: " << ctx->lp->cost << std::endl; - std::cout << " delta_tmp: " << ctx->delta_tmp << std::endl; - std::cout << " *delta_tmp: " << *ctx->delta_tmp << std::endl; - std::cout << " inactiveCost: " << ctx->inactiveCost << std::endl; + std::cout << "chainCallback" << std::endl; + std::cout << " lp from rtree: " << lp << std::endl; + std::cout << " lpid from rtree: " << lp->id << std::endl; + std::cout << " lpco from rtree: " << lp->cost << std::endl; + std::cout << " lp from context: " << ctx->lp << std::endl; + std::cout << " lpid from context: " << ctx->lp->id << std::endl; + std::cout << " lpco from context: " << ctx->lp->cost << std::endl; + std::cout << " delta_tmp: " << ctx->delta_tmp << std::endl; + std::cout << " *delta_tmp: " << *ctx->delta_tmp << std::endl; + std::cout << " inactiveCost: " << ctx->inactiveCost << std::endl; #endif #ifdef _DEBUG_FULL_ - std::cout << "ejChCallBack: " << lp->id << "<->" << ctx->lp->id << std::endl; + std::cout << "ejChCallBack: " << lp->id << "<->" << ctx->lp->id << std::endl; #endif - if (lp->isInConflict (ctx->lp)) { + if ( lp->isInConflict( ctx->lp ) ) + { #ifdef _DEBUG_FULL_ - std::cout << "ejChCallBack: " << lp->id << "<->" << ctx->lp->id << std::endl; - std::cout << " Conflictual..." << std::endl; + std::cout << "ejChCallBack: " << lp->id << "<->" << ctx->lp->id << std::endl; + std::cout << " Conflictual..." << std::endl; #endif - int feat, rfeat; - bool sub = ctx->featWrap!=NULL; + int feat, rfeat; + bool sub = ctx->featWrap != NULL; - feat = lp->probFeat; - if (sub) { - rfeat = feat; - feat = ctx->featWrap[feat]; - } else - rfeat = feat; + feat = lp->probFeat; + if ( sub ) + { + rfeat = feat; + feat = ctx->featWrap[feat]; + } + else + rfeat = feat; #ifdef _DEBUG_FULL_ - std::cout << " feat: " << feat << std::endl; - std::cout << " sol: " << ctx->tmpsol[feat] << "/" << lp->id << std::endl; - std::cout << " border:" << ctx->borderSize << std::endl; -#endif - if (feat >= 0 && ctx->tmpsol[feat] == lp->id) { - if (sub && feat < ctx->borderSize) { + std::cout << " feat: " << feat << std::endl; + std::cout << " sol: " << ctx->tmpsol[feat] << "/" << lp->id << std::endl; + std::cout << " border:" << ctx->borderSize << std::endl; +#endif + if ( feat >= 0 && ctx->tmpsol[feat] == lp->id ) + { + if ( sub && feat < ctx->borderSize ) + { #ifdef _DEBUG_FULL_ - std::cout << " Cannot touch border (throw) !" << std::endl; + std::cout << " Cannot touch border (throw) !" << std::endl; #endif - throw - 2; - } - } + throw - 2; + } + } - // is there any cycles ? - Cell *cur = ctx->currentChain->getFirst(); + // is there any cycles ? + Cell *cur = ctx->currentChain->getFirst(); - while (cur) { - if (cur->item->feat == feat) { + while ( cur ) + { + if ( cur->item->feat == feat ) + { #ifdef _DEBUG_FULL_ - std::cout << "Cycle into chain (throw) !" << std::endl; + std::cout << "Cycle into chain (throw) !" << std::endl; #endif - throw - 1; - } - cur = cur->next; - } - - if (!ctx->conflicts->isIn (feat)) { - ctx->conflicts->push_back (feat); - *ctx->delta_tmp += lp->cost + ctx->inactiveCost[rfeat]; - } + throw - 1; } - return true; + cur = cur->next; + } + + if ( !ctx->conflicts->isIn( feat ) ) + { + ctx->conflicts->push_back( feat ); + *ctx->delta_tmp += lp->cost + ctx->inactiveCost[rfeat]; + } } - - inline Chain *Problem::chain (SubPart *part, int seed) { - - int i; - int j; - - int lid; - - //int probSize = part->probSize; - int borderSize = part->borderSize; - int subSize = part->subSize; - int *sub = part->sub; - int *sol = part->sol; - register int subseed; - - double delta; - double delta_min; - double delta_best = DBL_MAX; - double delta_tmp; - - int next_seed; - int retainedLabel; - Chain *retainedChain = NULL; - - int max_degree = pal->ejChainDeg; - - int seedNbLp; - - LinkedList *currentChain = new LinkedList (ptrETCompare); - LinkedList *conflicts = new LinkedList (intCompare); - - int *tmpsol = new int[subSize]; - memcpy (tmpsol, sol, sizeof (int) *subSize); - - LabelPosition *lp; - double amin[2]; - double amax[2]; - int c; - - ChainContext context; - context.featWrap = featWrap; - context.borderSize = borderSize; - context.tmpsol = tmpsol; - context.inactiveCost = inactiveCost; - context.feat = NULL; - context.currentChain = currentChain; - context.conflicts = conflicts; - context.delta_tmp = &delta_tmp; - - delta = 0; - while (seed != -1) { - subseed = sub[seed]; - seedNbLp = featNbLp[subseed]; - delta_min = DBL_MAX; + return true; + } + + inline Chain *Problem::chain( SubPart *part, int seed ) + { + + int i; + int j; + + int lid; + + //int probSize = part->probSize; + int borderSize = part->borderSize; + int subSize = part->subSize; + int *sub = part->sub; + int *sol = part->sol; + register int subseed; + + double delta; + double delta_min; + double delta_best = DBL_MAX; + double delta_tmp; + + int next_seed; + int retainedLabel; + Chain *retainedChain = NULL; + + int max_degree = pal->ejChainDeg; + + int seedNbLp; + + LinkedList *currentChain = new LinkedList ( ptrETCompare ); + LinkedList *conflicts = new LinkedList ( intCompare ); + + int *tmpsol = new int[subSize]; + memcpy( tmpsol, sol, sizeof( int ) *subSize ); + + LabelPosition *lp; + double amin[2]; + double amax[2]; + int c; + + ChainContext context; + context.featWrap = featWrap; + context.borderSize = borderSize; + context.tmpsol = tmpsol; + context.inactiveCost = inactiveCost; + context.feat = NULL; + context.currentChain = currentChain; + context.conflicts = conflicts; + context.delta_tmp = &delta_tmp; + + delta = 0; + while ( seed != -1 ) + { + subseed = sub[seed]; + seedNbLp = featNbLp[subseed]; + delta_min = DBL_MAX; #ifdef _DEBUG_FULL_ - std::cout << "New seed: " << seed << "/" << subseed << std::endl; -#endif - next_seed = -1; - retainedLabel = -2; - + std::cout << "New seed: " << seed << "/" << subseed << std::endl; +#endif + next_seed = -1; + retainedLabel = -2; + + + if ( tmpsol[seed] == -1 ) + delta -= inactiveCost[subseed]; + else + delta -= labelpositions[tmpsol[seed]]->cost; + + // TODO modify to handle displayAll param + for ( i = -1;i < seedNbLp;i++ ) + { + try + { + // Skip active label ! + if ( !( tmpsol[seed] == -1 && i == -1 ) && i + featStartId[subseed] != tmpsol[seed] ) + { + if ( i != -1 ) + { + lid = featStartId[subseed] + i; + delta_tmp = delta; + + lp = labelpositions[lid]; + + // evaluate conflicts graph in solution after moving seed's label + amin[0] = DBL_MAX; + amax[0] = -DBL_MAX; + amin[1] = DBL_MAX; + amax[1] = -DBL_MAX; + for ( c = 0;c < 4;c++ ) + { + if ( lp->x[c] < amin[0] ) + amin[0] = lp->x[c]; + if ( lp->x[c] > amax[0] ) + amax[0] = lp->x[c]; + if ( lp->y[c] < amin[1] ) + amin[1] = lp->y[c]; + if ( lp->y[c] > amax[1] ) + amax[1] = lp->y[c]; + } + context.lp = lp; - if (tmpsol[seed] == -1) - delta -= inactiveCost[subseed]; - else - delta -= labelpositions[tmpsol[seed]]->cost; - - // TODO modify to handle displayAll param - for (i = -1;i < seedNbLp;i++) { - try { - // Skip active label ! - if (! (tmpsol[seed] == -1 && i == -1) && i + featStartId[subseed] != tmpsol[seed]) { - if (i != -1) { - lid = featStartId[subseed] + i; - delta_tmp = delta; - - lp = labelpositions[lid]; - - // evaluate conflicts graph in solution after moving seed's label - amin[0] = DBL_MAX; - amax[0] = -DBL_MAX; - amin[1] = DBL_MAX; - amax[1] = -DBL_MAX; - for (c = 0;c < 4;c++) { - if (lp->x[c] < amin[0]) - amin[0] = lp->x[c]; - if (lp->x[c] > amax[0]) - amax[0] = lp->x[c]; - if (lp->y[c] < amin[1]) - amin[1] = lp->y[c]; - if (lp->y[c] > amax[1]) - amax[1] = lp->y[c]; - } - context.lp = lp; - - if (conflicts->size() != 0) - std::cerr << "Conflicts not empty !!" << std::endl; - - // search ative conflicts and count them - candidates_subsol->Search (amin, amax, chainCallback, (void*) &context); + if ( conflicts->size() != 0 ) + std::cerr << "Conflicts not empty !!" << std::endl; -#ifdef _DEBUG_FULL_ - std::cout << "Conflicts:" << conflicts->size() << std::endl; -#endif - // no conflict -> end of chain - if (conflicts->size() == 0) { - if (!retainedChain || delta + labelpositions[lid]->cost < delta_best) { - - if (retainedChain) { - delete[] retainedChain->label; - delete[] retainedChain->feat; - } else { - retainedChain = new Chain(); // HERE - } - - delta_best = delta + labelpositions[lid]->cost; - - retainedChain->degree = currentChain->size() + 1; - retainedChain->feat = new int[retainedChain->degree]; // HERE - retainedChain->label = new int[retainedChain->degree]; // HERE - Cell *current = currentChain->getFirst(); - ElemTrans* move; - j = 0; - while (current) { - move = current->item; - retainedChain->feat[j] = move->feat; - retainedChain->label[j] = move->new_label; - current = current->next; - j++; - } - retainedChain->feat[j] = seed; - retainedChain->label[j] = lid; - retainedChain->delta = delta + labelpositions[retainedChain->label[j]]->cost; - } - } - - // another feature can be ejected - else if (conflicts->size() == 1) { - if (delta_tmp < delta_min) { - delta_min = delta_tmp; - retainedLabel = lid; - next_seed = conflicts->pop_front(); - } else { - conflicts->pop_front(); - } - } else { - - // A lot of conflict : make them inactive and store chain - Chain *newChain = new Chain(); // HERE - newChain->degree = currentChain->size() + 1 + conflicts->size(); - newChain->feat = new int[newChain->degree]; // HERE - newChain->label = new int[newChain->degree]; // HERE - Cell *current = currentChain->getFirst(); - ElemTrans* move; - j = 0; - while (current) { - move = current->item; - newChain->feat[j] = move->feat; - newChain->label[j] = move->new_label; - current = current->next; - j++; - } - - newChain->feat[j] = seed; - newChain->label[j] = lid; - newChain->delta = delta + labelpositions[newChain->label[j]]->cost; - j++; - - - while (conflicts->size() > 0) { - int ftid = conflicts->pop_front(); - newChain->feat[j] = ftid; - newChain->label[j] = -1; - newChain->delta += inactiveCost[sub[ftid]]; - j++; - } - - if (newChain->delta < delta_best) { - if (retainedChain) - delete_chain (retainedChain); - - delta_best = newChain->delta; - retainedChain = newChain; - } else { - delete_chain (newChain); - } - } - } else { // Current label == -1 end of chain ... - if (!retainedChain || delta + inactiveCost[subseed] < delta_best) { - if (retainedChain) { - delete[] retainedChain->label; - delete[] retainedChain->feat; - } else - retainedChain = new Chain(); // HERE - - delta_best = delta + inactiveCost[subseed]; - - retainedChain->degree = currentChain->size() + 1; - retainedChain->feat = new int[retainedChain->degree]; // HERE - retainedChain->label = new int[retainedChain->degree]; // HERE - Cell *current = currentChain->getFirst(); - ElemTrans* move; - j = 0; - while (current) { - move = current->item; - retainedChain->feat[j] = move->feat; - retainedChain->label[j] = move->new_label; - current = current->next; - j++; - } - retainedChain->feat[j] = seed; - retainedChain->label[j] = -1; - retainedChain->delta = delta + inactiveCost[subseed]; - } - } - } - } catch (int i) { -#ifdef _DEBUG_FULL_ - std::cout << "catch int " << i << std::endl; -#else - i; -#endif - while (conflicts->size() > 0) - conflicts->pop_front(); - } - } // end foreach labelposition + // search ative conflicts and count them + candidates_subsol->Search( amin, amax, chainCallback, ( void* ) &context ); - if (next_seed == -1) { - seed = -1; - } else if (currentChain->size() > max_degree) { -#ifdef _VERBOSE_ - std::cout << "Max degree reached !! (" << max_degree << ")" << std::endl; -#endif - seed = -1; - } else { - ElemTrans *et = new ElemTrans(); - et->feat = seed; - et->old_label = tmpsol[seed]; - et->new_label = retainedLabel; - currentChain->push_back (et); - - if (et->old_label != -1) { - labelpositions[et->old_label]->removeFromIndex (candidates_subsol); +#ifdef _DEBUG_FULL_ + std::cout << "Conflicts:" << conflicts->size() << std::endl; +#endif + // no conflict -> end of chain + if ( conflicts->size() == 0 ) + { + if ( !retainedChain || delta + labelpositions[lid]->cost < delta_best ) + { + + if ( retainedChain ) + { + delete[] retainedChain->label; + delete[] retainedChain->feat; + } + else + { + retainedChain = new Chain(); // HERE + } + + delta_best = delta + labelpositions[lid]->cost; + + retainedChain->degree = currentChain->size() + 1; + retainedChain->feat = new int[retainedChain->degree]; // HERE + retainedChain->label = new int[retainedChain->degree]; // HERE + Cell *current = currentChain->getFirst(); + ElemTrans* move; + j = 0; + while ( current ) + { + move = current->item; + retainedChain->feat[j] = move->feat; + retainedChain->label[j] = move->new_label; + current = current->next; + j++; + } + retainedChain->feat[j] = seed; + retainedChain->label[j] = lid; + retainedChain->delta = delta + labelpositions[retainedChain->label[j]]->cost; } + } - if (et->new_label != -1) { - labelpositions[et->new_label]->insertIntoIndex (candidates_subsol); + // another feature can be ejected + else if ( conflicts->size() == 1 ) + { + if ( delta_tmp < delta_min ) + { + delta_min = delta_tmp; + retainedLabel = lid; + next_seed = conflicts->pop_front(); + } + else + { + conflicts->pop_front(); + } + } + else + { + + // A lot of conflict : make them inactive and store chain + Chain *newChain = new Chain(); // HERE + newChain->degree = currentChain->size() + 1 + conflicts->size(); + newChain->feat = new int[newChain->degree]; // HERE + newChain->label = new int[newChain->degree]; // HERE + Cell *current = currentChain->getFirst(); + ElemTrans* move; + j = 0; + while ( current ) + { + move = current->item; + newChain->feat[j] = move->feat; + newChain->label[j] = move->new_label; + current = current->next; + j++; } - tmpsol[seed] = retainedLabel; - delta += labelpositions[retainedLabel]->cost; - seed = next_seed; - } - } + newChain->feat[j] = seed; + newChain->label[j] = lid; + newChain->delta = delta + labelpositions[newChain->label[j]]->cost; + j++; - while (currentChain->size() > 0) { - ElemTrans* et = currentChain->pop_front(); - if (et->new_label != -1) { - labelpositions[et->new_label]->removeFromIndex (candidates_subsol); - } + while ( conflicts->size() > 0 ) + { + int ftid = conflicts->pop_front(); + newChain->feat[j] = ftid; + newChain->label[j] = -1; + newChain->delta += inactiveCost[sub[ftid]]; + j++; + } - if (et->old_label != -1) { - labelpositions[et->old_label]->insertIntoIndex (candidates_subsol); - } + if ( newChain->delta < delta_best ) + { + if ( retainedChain ) + delete_chain( retainedChain ); - delete et; + delta_best = newChain->delta; + retainedChain = newChain; + } + else + { + delete_chain( newChain ); + } + } + } + else // Current label == -1 end of chain ... + { + if ( !retainedChain || delta + inactiveCost[subseed] < delta_best ) + { + if ( retainedChain ) + { + delete[] retainedChain->label; + delete[] retainedChain->feat; + } + else + retainedChain = new Chain(); // HERE + + delta_best = delta + inactiveCost[subseed]; + + retainedChain->degree = currentChain->size() + 1; + retainedChain->feat = new int[retainedChain->degree]; // HERE + retainedChain->label = new int[retainedChain->degree]; // HERE + Cell *current = currentChain->getFirst(); + ElemTrans* move; + j = 0; + while ( current ) + { + move = current->item; + retainedChain->feat[j] = move->feat; + retainedChain->label[j] = move->new_label; + current = current->next; + j++; + } + retainedChain->feat[j] = seed; + retainedChain->label[j] = -1; + retainedChain->delta = delta + inactiveCost[subseed]; + } + } + } + } + catch ( int i ) + { +#ifdef _DEBUG_FULL_ + std::cout << "catch int " << i << std::endl; +#else + i; +#endif + while ( conflicts->size() > 0 ) + conflicts->pop_front(); + } + } // end foreach labelposition + + if ( next_seed == -1 ) + { + seed = -1; + } + else if ( currentChain->size() > max_degree ) + { +#ifdef _VERBOSE_ + std::cout << "Max degree reached !! (" << max_degree << ")" << std::endl; +#endif + seed = -1; + } + else + { + ElemTrans *et = new ElemTrans(); + et->feat = seed; + et->old_label = tmpsol[seed]; + et->new_label = retainedLabel; + currentChain->push_back( et ); + + if ( et->old_label != -1 ) + { + labelpositions[et->old_label]->removeFromIndex( candidates_subsol ); } - delete currentChain; - - delete[] tmpsol; - delete conflicts; + if ( et->new_label != -1 ) + { + labelpositions[et->new_label]->insertIntoIndex( candidates_subsol ); + } - return retainedChain; + tmpsol[seed] = retainedLabel; + delta += labelpositions[retainedLabel]->cost; + seed = next_seed; + } } + while ( currentChain->size() > 0 ) + { + ElemTrans* et = currentChain->pop_front(); - inline Chain *Problem::chain (int seed) { - - int i; - int j; + if ( et->new_label != -1 ) + { + labelpositions[et->new_label]->removeFromIndex( candidates_subsol ); + } - int lid; + if ( et->old_label != -1 ) + { + labelpositions[et->old_label]->insertIntoIndex( candidates_subsol ); + } - double delta; - double delta_min; - double delta_best = DBL_MAX; - double delta_tmp; - - int next_seed; - int retainedLabel; - Chain *retainedChain = NULL; - - int max_degree = pal->ejChainDeg; - - int seedNbLp; + delete et; + } + delete currentChain; + + delete[] tmpsol; + delete conflicts; + + + return retainedChain; + } + + + inline Chain *Problem::chain( int seed ) + { + + int i; + int j; + + int lid; + + double delta; + double delta_min; + double delta_best = DBL_MAX; + double delta_tmp; + + int next_seed; + int retainedLabel; + Chain *retainedChain = NULL; + + int max_degree = pal->ejChainDeg; + + int seedNbLp; + + LinkedList *currentChain = new LinkedList ( ptrETCompare ); + LinkedList *conflicts = new LinkedList ( intCompare ); + + int *tmpsol = new int[nbft]; + memcpy( tmpsol, sol->s, sizeof( int ) *nbft ); + + LabelPosition *lp; + double amin[2]; + double amax[2]; + int c; + + ChainContext context; + context.featWrap = NULL; + context.borderSize = 0; + context.tmpsol = tmpsol; + context.inactiveCost = inactiveCost; + context.feat = NULL; + context.currentChain = currentChain; + context.conflicts = conflicts; + context.delta_tmp = &delta_tmp; + + delta = 0; + while ( seed != -1 ) + { + seedNbLp = featNbLp[seed]; + delta_min = DBL_MAX; + + next_seed = -1; + retainedLabel = -2; + + // sol[seed] is ejected + if ( tmpsol[seed] == -1 ) + delta -= inactiveCost[seed]; + else + delta -= labelpositions[tmpsol[seed]]->cost; + + for ( i = -1;i < seedNbLp;i++ ) + { + try + { + // Skip active label ! + if ( !( tmpsol[seed] == -1 && i == -1 ) && i + featStartId[seed] != tmpsol[seed] ) + { + if ( i != -1 ) // new_label + { + lid = featStartId[seed] + i; + delta_tmp = delta; + + lp = labelpositions[lid]; + + // evaluate conflicts graph in solution after moving seed's label + amin[0] = DBL_MAX; + amax[0] = -DBL_MAX; + amin[1] = DBL_MAX; + amax[1] = -DBL_MAX; + for ( c = 0;c < 4;c++ ) + { + if ( lp->x[c] < amin[0] ) + amin[0] = lp->x[c]; + if ( lp->x[c] > amax[0] ) + amax[0] = lp->x[c]; + if ( lp->y[c] < amin[1] ) + amin[1] = lp->y[c]; + if ( lp->y[c] > amax[1] ) + amax[1] = lp->y[c]; + } + context.lp = lp; + if ( conflicts->size() != 0 ) + std::cerr << "Conflicts not empty" << std::endl; + + candidates_sol->Search( amin, amax, chainCallback, ( void* ) &context ); + + // no conflict -> end of chain + if ( conflicts->size() == 0 ) + { + if ( !retainedChain || delta + labelpositions[lid]->cost < delta_best ) + { + if ( retainedChain ) + { + delete[] retainedChain->label; + delete[] retainedChain->feat; + } + else + { + retainedChain = new Chain(); + } + + delta_best = delta + labelpositions[lid]->cost; + + retainedChain->degree = currentChain->size() + 1; + retainedChain->feat = new int[retainedChain->degree]; + retainedChain->label = new int[retainedChain->degree]; + Cell *current = currentChain->getFirst(); + ElemTrans* move; + j = 0; + while ( current ) + { + move = current->item; + retainedChain->feat[j] = move->feat; + retainedChain->label[j] = move->new_label; + current = current->next; + j++; + } + retainedChain->feat[j] = seed; + retainedChain->label[j] = lid; + retainedChain->delta = delta + labelpositions[lid]->cost; + } + } - LinkedList *currentChain = new LinkedList (ptrETCompare); - LinkedList *conflicts = new LinkedList (intCompare); + // another feature can be ejected + else if ( conflicts->size() == 1 ) + { + if ( delta_tmp < delta_min ) + { + delta_min = delta_tmp; + retainedLabel = lid; + next_seed = conflicts->pop_front(); + } + else + { + conflicts->pop_front(); + } + } + else + { + + // A lot of conflict : make them inactive and store chain + Chain *newChain = new Chain(); + newChain->degree = currentChain->size() + 1 + conflicts->size(); + newChain->feat = new int[newChain->degree]; + newChain->label = new int[newChain->degree]; + Cell *current = currentChain->getFirst(); + ElemTrans* move; + j = 0; + + while ( current ) + { + move = current->item; + newChain->feat[j] = move->feat; + newChain->label[j] = move->new_label; + current = current->next; + j++; + } - int *tmpsol = new int[nbft]; - memcpy (tmpsol, sol->s, sizeof (int) *nbft); + // add the current candidates into the chain + newChain->feat[j] = seed; + newChain->label[j] = lid; + newChain->delta = delta + labelpositions[newChain->label[j]]->cost; + j++; + + // hide all conflictual candidates + while ( conflicts->size() > 0 ) + { + int ftid = conflicts->pop_front(); + newChain->feat[j] = ftid; + newChain->label[j] = -1; + newChain->delta += inactiveCost[ftid]; + j++; + } - LabelPosition *lp; - double amin[2]; - double amax[2]; - int c; + if ( newChain->delta < delta_best ) + { + if ( retainedChain ) + delete_chain( retainedChain ); - ChainContext context; - context.featWrap = NULL; - context.borderSize = 0; - context.tmpsol = tmpsol; - context.inactiveCost = inactiveCost; - context.feat = NULL; - context.currentChain = currentChain; - context.conflicts = conflicts; - context.delta_tmp = &delta_tmp; - - delta = 0; - while (seed != -1) { - seedNbLp = featNbLp[seed]; - delta_min = DBL_MAX; - - next_seed = -1; - retainedLabel = -2; - - // sol[seed] is ejected - if (tmpsol[seed] == -1) - delta -= inactiveCost[seed]; - else - delta -= labelpositions[tmpsol[seed]]->cost; - - for (i = -1;i < seedNbLp;i++) { - try { - // Skip active label ! - if (! (tmpsol[seed] == -1 && i == -1) && i + featStartId[seed] != tmpsol[seed]) { - if (i != -1) { // new_label - lid = featStartId[seed] + i; - delta_tmp = delta; - - lp = labelpositions[lid]; - - // evaluate conflicts graph in solution after moving seed's label - amin[0] = DBL_MAX; - amax[0] = -DBL_MAX; - amin[1] = DBL_MAX; - amax[1] = -DBL_MAX; - for (c = 0;c < 4;c++) { - if (lp->x[c] < amin[0]) - amin[0] = lp->x[c]; - if (lp->x[c] > amax[0]) - amax[0] = lp->x[c]; - if (lp->y[c] < amin[1]) - amin[1] = lp->y[c]; - if (lp->y[c] > amax[1]) - amax[1] = lp->y[c]; - } - context.lp = lp; - if (conflicts->size() != 0) - std::cerr << "Conflicts not empty" << std::endl; - - candidates_sol->Search (amin, amax, chainCallback, (void*) &context); - - // no conflict -> end of chain - if (conflicts->size() == 0) { - if (!retainedChain || delta + labelpositions[lid]->cost < delta_best) { - if (retainedChain) { - delete[] retainedChain->label; - delete[] retainedChain->feat; - } else { - retainedChain = new Chain(); - } - - delta_best = delta + labelpositions[lid]->cost; - - retainedChain->degree = currentChain->size() + 1; - retainedChain->feat = new int[retainedChain->degree]; - retainedChain->label = new int[retainedChain->degree]; - Cell *current = currentChain->getFirst(); - ElemTrans* move; - j = 0; - while (current) { - move = current->item; - retainedChain->feat[j] = move->feat; - retainedChain->label[j] = move->new_label; - current = current->next; - j++; - } - retainedChain->feat[j] = seed; - retainedChain->label[j] = lid; - retainedChain->delta = delta + labelpositions[lid]->cost; - } - } - - // another feature can be ejected - else if (conflicts->size() == 1) { - if (delta_tmp < delta_min) { - delta_min = delta_tmp; - retainedLabel = lid; - next_seed = conflicts->pop_front(); - } else { - conflicts->pop_front(); - } - } else { - - // A lot of conflict : make them inactive and store chain - Chain *newChain = new Chain(); - newChain->degree = currentChain->size() + 1 + conflicts->size(); - newChain->feat = new int[newChain->degree]; - newChain->label = new int[newChain->degree]; - Cell *current = currentChain->getFirst(); - ElemTrans* move; - j = 0; - - while (current) { - move = current->item; - newChain->feat[j] = move->feat; - newChain->label[j] = move->new_label; - current = current->next; - j++; - } - - // add the current candidates into the chain - newChain->feat[j] = seed; - newChain->label[j] = lid; - newChain->delta = delta + labelpositions[newChain->label[j]]->cost; - j++; - - // hide all conflictual candidates - while (conflicts->size() > 0) { - int ftid = conflicts->pop_front(); - newChain->feat[j] = ftid; - newChain->label[j] = -1; - newChain->delta += inactiveCost[ftid]; - j++; - } - - if (newChain->delta < delta_best) { - if (retainedChain) - delete_chain (retainedChain); - - delta_best = newChain->delta; - retainedChain = newChain; - } else { - delete_chain (newChain); - } - } - - } else { // Current label == -1 end of chain ... - if (!retainedChain || delta + inactiveCost[seed] < delta_best) { - if (retainedChain) { - delete[] retainedChain->label; - delete[] retainedChain->feat; - } else - retainedChain = new Chain(); - - delta_best = delta + inactiveCost[seed]; - - retainedChain->degree = currentChain->size() + 1; - retainedChain->feat = new int[retainedChain->degree]; - retainedChain->label = new int[retainedChain->degree]; - Cell *current = currentChain->getFirst(); - ElemTrans* move; - j = 0; - while (current) { - move = current->item; - retainedChain->feat[j] = move->feat; - retainedChain->label[j] = move->new_label; - current = current->next; - j++; - } - retainedChain->feat[j] = seed; - retainedChain->label[j] = -1; - retainedChain->delta = delta + inactiveCost[seed]; - } - } - } - } catch (int i) { -#ifdef _DEBUG_FULL_ - std::cout << "catch Cycle in chain" << std::endl; -#else - i; -#endif - while (conflicts->size() > 0) - conflicts->pop_front(); + delta_best = newChain->delta; + retainedChain = newChain; } - } // end foreach labelposition - - if (next_seed == -1) { - seed = -1; - } else if (currentChain->size() > max_degree) { - std::cout << "Max degree reached !! (" << max_degree << ")" << std::endl; - seed = -1; - } else { - ElemTrans *et = new ElemTrans(); - et->feat = seed; - et->old_label = tmpsol[seed]; - et->new_label = retainedLabel; - currentChain->push_back (et); - - if (et->old_label != -1) { - labelpositions[et->old_label]->removeFromIndex (candidates_sol); + else + { + delete_chain( newChain ); } + } - if (et->new_label != -1) { - labelpositions[et->new_label]->insertIntoIndex (candidates_sol); + } + else // Current label == -1 end of chain ... + { + if ( !retainedChain || delta + inactiveCost[seed] < delta_best ) + { + if ( retainedChain ) + { + delete[] retainedChain->label; + delete[] retainedChain->feat; } - - - tmpsol[seed] = retainedLabel; - delta += labelpositions[retainedLabel]->cost; - seed = next_seed; + else + retainedChain = new Chain(); + + delta_best = delta + inactiveCost[seed]; + + retainedChain->degree = currentChain->size() + 1; + retainedChain->feat = new int[retainedChain->degree]; + retainedChain->label = new int[retainedChain->degree]; + Cell *current = currentChain->getFirst(); + ElemTrans* move; + j = 0; + while ( current ) + { + move = current->item; + retainedChain->feat[j] = move->feat; + retainedChain->label[j] = move->new_label; + current = current->next; + j++; + } + retainedChain->feat[j] = seed; + retainedChain->label[j] = -1; + retainedChain->delta = delta + inactiveCost[seed]; + } } + } + } + catch ( int i ) + { +#ifdef _DEBUG_FULL_ + std::cout << "catch Cycle in chain" << std::endl; +#else + i; +#endif + while ( conflicts->size() > 0 ) + conflicts->pop_front(); + } + } // end foreach labelposition + + if ( next_seed == -1 ) + { + seed = -1; + } + else if ( currentChain->size() > max_degree ) + { + std::cout << "Max degree reached !! (" << max_degree << ")" << std::endl; + seed = -1; + } + else + { + ElemTrans *et = new ElemTrans(); + et->feat = seed; + et->old_label = tmpsol[seed]; + et->new_label = retainedLabel; + currentChain->push_back( et ); + + if ( et->old_label != -1 ) + { + labelpositions[et->old_label]->removeFromIndex( candidates_sol ); } + if ( et->new_label != -1 ) + { + labelpositions[et->new_label]->insertIntoIndex( candidates_sol ); + } - while (currentChain->size() > 0) { - ElemTrans* et = currentChain->pop_front(); - if (et->new_label != -1) { - labelpositions[et->new_label]->removeFromIndex (candidates_sol); - } + tmpsol[seed] = retainedLabel; + delta += labelpositions[retainedLabel]->cost; + seed = next_seed; + } + } - if (et->old_label != -1) { - labelpositions[et->old_label]->insertIntoIndex (candidates_sol); - } - delete et; - } - delete currentChain; + while ( currentChain->size() > 0 ) + { + ElemTrans* et = currentChain->pop_front(); - delete[] tmpsol; - delete conflicts; + if ( et->new_label != -1 ) + { + labelpositions[et->new_label]->removeFromIndex( candidates_sol ); + } + if ( et->old_label != -1 ) + { + labelpositions[et->old_label]->insertIntoIndex( candidates_sol ); + } - return retainedChain; + delete et; } + delete currentChain; + delete[] tmpsol; + delete conflicts; - /** - * POPMUSIC, chain - */ - double Problem::popmusic_chain (SubPart *part) { - int i; - //int j; - int probSize = part->probSize; - int borderSize = part->borderSize; - int subSize = part->subSize; - int *sub = part->sub; - int *sol = part->sol; + return retainedChain; + } - int *best_sol = new int[subSize]; - for (i = 0;i < subSize;i++) { - featWrap[sub[i]] = i; - best_sol[i] = sol[i]; - } + /** + * POPMUSIC, chain + */ + double Problem::popmusic_chain( SubPart *part ) + { + int i; + //int j; - double initial_cost; - double cur_cost = 0; - double best_cost = 0; + int probSize = part->probSize; + int borderSize = part->borderSize; + int subSize = part->subSize; + int *sub = part->sub; + int *sol = part->sol; - int nbOverlap = 0; + int *best_sol = new int[subSize]; - int seed; + for ( i = 0;i < subSize;i++ ) + { + featWrap[sub[i]] = i; + best_sol[i] = sol[i]; + } - int featOv; + double initial_cost; + double cur_cost = 0; + double best_cost = 0; - int lid; - int fid; + int nbOverlap = 0; - int *tabu_list = new int[subSize]; + int seed; - Chain *current_chain = NULL; + int featOv; - //int itC; + int lid; + int fid; - int it; - int stop_it; - int maxit; - int itwimp; // iteration without improvment + int *tabu_list = new int[subSize]; - int tenure = pal->tenure; + Chain *current_chain = NULL; - for (i = 0;i < subSize;i++) { - cur_cost += compute_feature_cost (part, i, sol[i], &featOv); - nbOverlap += featOv; - } + //int itC; - initial_cost = cur_cost; - best_cost = cur_cost; + int it; + int stop_it; + int maxit; + int itwimp; // iteration without improvment - it = 0; + int tenure = pal->tenure; - maxit = probSize * pal->tabuMaxIt; + for ( i = 0;i < subSize;i++ ) + { + cur_cost += compute_feature_cost( part, i, sol[i], &featOv ); + nbOverlap += featOv; + } - itwimp = probSize * pal->tabuMinIt;; + initial_cost = cur_cost; + best_cost = cur_cost; - stop_it = itwimp; + it = 0; - // feature on border always are tabu - for (i = 0;i < borderSize;i++) - tabu_list[i] = maxit; // border always are taboo + maxit = probSize * pal->tabuMaxIt; - for (i = 0;i < probSize;i++) - tabu_list[i+borderSize] = -1; // others aren't + itwimp = probSize * pal->tabuMinIt;; - while (it < stop_it) { - seed = (it % probSize) + borderSize; + stop_it = itwimp; - if ( (current_chain = chain (part, seed))) { + // feature on border always are tabu + for ( i = 0;i < borderSize;i++ ) + tabu_list[i] = maxit; // border always are taboo - /* we accept a modification only if the seed is not tabu or - * if the nmodification will generate a new best solution */ - if (tabu_list[seed] < it || (cur_cost + current_chain->delta) - best_cost < 0.0) { + for ( i = 0;i < probSize;i++ ) + tabu_list[i+borderSize] = -1; // others aren't - for (i = 0;i < current_chain->degree;i++) { - fid = current_chain->feat[i]; - lid = current_chain->label[i]; + while ( it < stop_it ) + { + seed = ( it % probSize ) + borderSize; - if (sol[fid] >= 0) { - labelpositions[sol[fid]]->removeFromIndex (candidates_subsol); - } - sol[fid] = lid; + if (( current_chain = chain( part, seed ) ) ) + { - if (sol[fid] >= 0) { - labelpositions[lid]->insertIntoIndex (candidates_subsol); - } + /* we accept a modification only if the seed is not tabu or + * if the nmodification will generate a new best solution */ + if ( tabu_list[seed] < it || ( cur_cost + current_chain->delta ) - best_cost < 0.0 ) + { - tabu_list[fid] = it + tenure; - } + for ( i = 0;i < current_chain->degree;i++ ) + { + fid = current_chain->feat[i]; + lid = current_chain->label[i]; - cur_cost += current_chain->delta; -#ifdef _DEBUG_FULL_ - std::cout << "cur->cost: " << cur_cost << std::endl; - int kov; - std::cout << "computed cost: " << compute_subsolution_cost (part, sol, &kov) << std::endl << std::endl; -#endif - /* check if new solution is a new best solution */ - if (best_cost - cur_cost > EPSILON) { - best_cost = cur_cost; - memcpy (best_sol, sol, sizeof (int) *subSize); + if ( sol[fid] >= 0 ) + { + labelpositions[sol[fid]]->removeFromIndex( candidates_subsol ); + } + sol[fid] = lid; - stop_it = (it + itwimp > maxit ? maxit : it + itwimp); - } - } - delete_chain (current_chain); + if ( sol[fid] >= 0 ) + { + labelpositions[lid]->insertIntoIndex( candidates_subsol ); } - it++; - } - memcpy (sol, best_sol, sizeof (int) *subSize); - - /* - for (i=borderSize;idelta < 0.0){ - best_cost += chain->delta; - for (j=0;jdegree;j++){ - fid = chain->feat[j]; - lid = chain->label[j]; - sol[fid] = lid; - } - } + tabu_list[fid] = it + tenure; + } - delete_chain(chain); - } + cur_cost += current_chain->delta; +#ifdef _DEBUG_FULL_ + std::cout << "cur->cost: " << cur_cost << std::endl; + int kov; + std::cout << "computed cost: " << compute_subsolution_cost( part, sol, &kov ) << std::endl << std::endl; +#endif + /* check if new solution is a new best solution */ + if ( best_cost - cur_cost > EPSILON ) + { + best_cost = cur_cost; + memcpy( best_sol, sol, sizeof( int ) *subSize ); + + stop_it = ( it + itwimp > maxit ? maxit : it + itwimp ); + } } - */ + delete_chain( current_chain ); + } + it++; + } - for (i = 0;i < subSize;i++) - featWrap[sub[i]] = -1; + memcpy( sol, best_sol, sizeof( int ) *subSize ); + + /* + for (i=borderSize;idelta < 0.0){ + best_cost += chain->delta; + for (j=0;jdegree;j++){ + fid = chain->feat[j]; + lid = chain->label[j]; + sol[fid] = lid; + } + } + + delete_chain(chain); + } + } + */ - delete[] best_sol; - delete[] tabu_list; + for ( i = 0;i < subSize;i++ ) + featWrap[sub[i]] = -1; + delete[] best_sol; + delete[] tabu_list; - return initial_cost - best_cost; - } + return initial_cost - best_cost; + } - /** - * - * POPMUSIC, Tabu search with chain' - * - */ - double Problem::popmusic_tabu_chain (SubPart *part) { - int i; - int probSize = part->probSize; - int borderSize = part->borderSize; - int subSize = part->subSize; - int *sub = part->sub; - int *sol = part->sol; + /** + * + * POPMUSIC, Tabu search with chain' + * + */ + double Problem::popmusic_tabu_chain( SubPart *part ) + { + int i; - int *best_sol = new int[subSize]; + int probSize = part->probSize; + int borderSize = part->borderSize; + int subSize = part->subSize; + int *sub = part->sub; + int *sol = part->sol; - for (i = 0;i < subSize;i++) { - featWrap[sub[i]] = i; - } + int *best_sol = new int[subSize]; + + for ( i = 0;i < subSize;i++ ) + { + featWrap[sub[i]] = i; + } - double initial_cost; - double cur_cost = 0; - double best_cost = 0; - double bestChain; + double initial_cost; + double cur_cost = 0; + double best_cost = 0; + double bestChain; - int nbOverlap = 0; + int nbOverlap = 0; - int seed; + int seed; - int featOv; + int featOv; - int lid; - int fid; + int lid; + int fid; - int *tmpsol = new int[subSize]; + int *tmpsol = new int[subSize]; - int *tabu_list = new int[subSize]; + int *tabu_list = new int[subSize]; - Chain *retainedChain = NULL; - Chain *current_chain = NULL; + Chain *retainedChain = NULL; + Chain *current_chain = NULL; - int itC; + int itC; - int it; - int stop_it; - int maxit; - int itwimp; + int it; + int stop_it; + int maxit; + int itwimp; - int tenure = pal->tenure; + int tenure = pal->tenure; - int itBest = -1; - //int deltaIt = 0; + int itBest = -1; + //int deltaIt = 0; - Triple **candidates = new Triple*[probSize]; - Triple **candidatesUnsorted = new Triple*[probSize]; + Triple **candidates = new Triple*[probSize]; + Triple **candidatesUnsorted = new Triple*[probSize]; - LinkedList *conflicts = new LinkedList (intCompare); + LinkedList *conflicts = new LinkedList ( intCompare ); - for (i = 0;i < subSize;i++) { - cur_cost += compute_feature_cost (part, i, sol[i], &featOv); - nbOverlap += featOv; - } + for ( i = 0;i < subSize;i++ ) + { + cur_cost += compute_feature_cost( part, i, sol[i], &featOv ); + nbOverlap += featOv; + } - initial_cost = cur_cost; - best_cost = cur_cost; + initial_cost = cur_cost; + best_cost = cur_cost; - it = 0; + it = 0; - maxit = probSize * pal->tabuMaxIt; + maxit = probSize * pal->tabuMaxIt; - itwimp = probSize * pal->tabuMinIt;; + itwimp = probSize * pal->tabuMinIt;; - stop_it = itwimp; + stop_it = itwimp; - for (i = 0;i < borderSize;i++) - tabu_list[i] = maxit; + for ( i = 0;i < borderSize;i++ ) + tabu_list[i] = maxit; - for (i = 0;i < probSize;i++) { - tabu_list[i+borderSize] = -1; + for ( i = 0;i < probSize;i++ ) + { + tabu_list[i+borderSize] = -1; - candidates[i] = new Triple(); - candidates[i]->feat_id = i + borderSize; - candidatesUnsorted[i] = candidates[i]; + candidates[i] = new Triple(); + candidates[i]->feat_id = i + borderSize; + candidatesUnsorted[i] = candidates[i]; - candidates[i]->cost = (sol[i+borderSize] == -1 ? inactiveCost[i+borderSize] : labelpositions[sol[i+borderSize]]->cost); - } + candidates[i]->cost = ( sol[i+borderSize] == -1 ? inactiveCost[i+borderSize] : labelpositions[sol[i+borderSize]]->cost ); + } - sort ( (void**) candidates, probSize, decreaseCost); + sort(( void** ) candidates, probSize, decreaseCost ); - int validCandidateId = -1; + int validCandidateId = -1; - int candidateListSize; - int seedSh; - candidateListSize = int (pal->candListSize * (double) probSize + 0.5); + int candidateListSize; + int seedSh; + candidateListSize = int ( pal->candListSize * ( double ) probSize + 0.5 ); - if (candidateListSize > probSize) - candidateListSize = probSize; + if ( candidateListSize > probSize ) + candidateListSize = probSize; #ifdef _DEBUG_FULL_ - int nbOv; - std::cout << std::endl << "Initial solution cost " << cur_cost << std::endl; - std::cout << "Computed: " << compute_subsolution_cost (part, sol, &nbOv); - std::cout << "NbOverlap: " << nbOv << std::endl; + int nbOv; + std::cout << std::endl << "Initial solution cost " << cur_cost << std::endl; + std::cout << "Computed: " << compute_subsolution_cost( part, sol, &nbOv ); + std::cout << "NbOverlap: " << nbOv << std::endl; #endif - while (it < stop_it) { - retainedChain = NULL; - bestChain = DBL_MAX; - validCandidateId = -1; + while ( it < stop_it ) + { + retainedChain = NULL; + bestChain = DBL_MAX; + validCandidateId = -1; #ifdef _DEBUG_FULL_ - std::cout << std::endl << std::endl << candidateListSize << std::endl; + std::cout << std::endl << std::endl << candidateListSize << std::endl; #endif - for (itC = 0;itC < candidateListSize;itC++) { - seed = candidates[itC]->feat_id; - seedSh = seed - borderSize; + for ( itC = 0;itC < candidateListSize;itC++ ) + { + seed = candidates[itC]->feat_id; + seedSh = seed - borderSize; #ifdef _DEBUG_FULL_ - std::cout << "new candidates:" << std::endl; + std::cout << "new candidates:" << std::endl; #endif - current_chain = chain (part, seed); + current_chain = chain( part, seed ); #ifdef _DEBUG_FULL_ - std::cout << "get chain:" << current_chain << std::endl; -#endif - if (current_chain) { - // seed is not taboo or chain give us a new best solution - if (tabu_list[seed] < it || (cur_cost + current_chain->delta) - best_cost < 0.0) { - if (!retainedChain) { - retainedChain = current_chain; - bestChain = current_chain->delta; + std::cout << "get chain:" << current_chain << std::endl; +#endif + if ( current_chain ) + { + // seed is not taboo or chain give us a new best solution + if ( tabu_list[seed] < it || ( cur_cost + current_chain->delta ) - best_cost < 0.0 ) + { + if ( !retainedChain ) + { + retainedChain = current_chain; + bestChain = current_chain->delta; #ifdef _DEBUG_FULL_ - std::cout << "New chain, delta = " << current_chain->delta << std::endl; + std::cout << "New chain, delta = " << current_chain->delta << std::endl; #endif - } else if (current_chain->delta - retainedChain->delta < EPSILON) { - delete_chain (retainedChain); - retainedChain = current_chain; - bestChain = current_chain->delta; + } + else if ( current_chain->delta - retainedChain->delta < EPSILON ) + { + delete_chain( retainedChain ); + retainedChain = current_chain; + bestChain = current_chain->delta; #ifdef _DEBUG_FULL_ - std::cout << "New best chain, delta = " << current_chain->delta << std::endl; + std::cout << "New best chain, delta = " << current_chain->delta << std::endl; #endif - } else { + } + else + { #ifdef _DEBUG_FULL_ - std::cout << "chain rejected..." << std::endl; + std::cout << "chain rejected..." << std::endl; #endif - delete_chain (current_chain); - } - } else { + delete_chain( current_chain ); + } + } + else + { #ifdef _DEBUG_FULL_ - std::cout << "chain rejected, tabu and/or delta = " << current_chain->delta << std::endl; + std::cout << "chain rejected, tabu and/or delta = " << current_chain->delta << std::endl; #endif - delete_chain (current_chain); - } - } + delete_chain( current_chain ); + } + } #ifdef _DEBUG_FULL_ - else { - std::cout << "no chain !!" << std::endl; - } + else + { + std::cout << "no chain !!" << std::endl; + } #endif - } // end foreach candidates + } // end foreach candidates - if (retainedChain /*&& retainedChain->delta <= 0*/) { + if ( retainedChain /*&& retainedChain->delta <= 0*/ ) + { #ifdef _DEBUG_FULL_ - std::cout << it << " retained chain's degree: " << retainedChain->degree; - std::cout << " and delta: " << retainedChain->delta << std::endl; + std::cout << it << " retained chain's degree: " << retainedChain->degree; + std::cout << " and delta: " << retainedChain->delta << std::endl; #endif - for (i = 0;i < retainedChain->degree;i++) { - fid = retainedChain->feat[i]; - lid = retainedChain->label[i]; + for ( i = 0;i < retainedChain->degree;i++ ) + { + fid = retainedChain->feat[i]; + lid = retainedChain->label[i]; #ifdef _DEBUG_FULL_ - std::cout << fid << ": " << sol[fid] << " -> " << lid << " Costs: " << inactiveCost[fid] << ":" << (sol[fid] != -1 ? labelpositions[sol[fid]]->cost : -1) << ":" << (lid != -1 ? labelpositions[lid]->cost : -1) << std::endl; + std::cout << fid << ": " << sol[fid] << " -> " << lid << " Costs: " << inactiveCost[fid] << ":" << ( sol[fid] != -1 ? labelpositions[sol[fid]]->cost : -1 ) << ":" << ( lid != -1 ? labelpositions[lid]->cost : -1 ) << std::endl; #endif - if (sol[fid] >= 0) - labelpositions[sol[fid]]->removeFromIndex (candidates_subsol); + if ( sol[fid] >= 0 ) + labelpositions[sol[fid]]->removeFromIndex( candidates_subsol ); - sol[fid] = lid; + sol[fid] = lid; - if (lid >= 0) - labelpositions[lid]->insertIntoIndex (candidates_subsol); + if ( lid >= 0 ) + labelpositions[lid]->insertIntoIndex( candidates_subsol ); - tabu_list[fid] = it + tenure; + tabu_list[fid] = it + tenure; #ifdef _DEBUG_FULL_ - std::cout << "fid: " << fid << std::endl; - std::cout << "borderSize: " << borderSize << std::endl; - std::cout << "lid: " << lid << std::endl; - std::cout << "sub[fid]: " << sub[fid] << std::endl; - std::cout << "inactivecosr[sub[fid]]: " << inactiveCost[sub[fid]] << std::endl; - if (lid > -1) { - std::cout << "label[lid]: " << labelpositions[lid] << std::endl; - std::cout << "label[lid]->cost: " << labelpositions[lid]->cost << std::endl; - } -#endif - candidatesUnsorted[fid-borderSize]->cost = (lid == -1 ? inactiveCost[sub[fid]] : labelpositions[lid]->cost); + std::cout << "fid: " << fid << std::endl; + std::cout << "borderSize: " << borderSize << std::endl; + std::cout << "lid: " << lid << std::endl; + std::cout << "sub[fid]: " << sub[fid] << std::endl; + std::cout << "inactivecosr[sub[fid]]: " << inactiveCost[sub[fid]] << std::endl; + if ( lid > -1 ) + { + std::cout << "label[lid]: " << labelpositions[lid] << std::endl; + std::cout << "label[lid]->cost: " << labelpositions[lid]->cost << std::endl; + } +#endif + candidatesUnsorted[fid-borderSize]->cost = ( lid == -1 ? inactiveCost[sub[fid]] : labelpositions[lid]->cost ); - } + } #ifdef _DEBUG_FULL_ - std::cout << std::endl; + std::cout << std::endl; #endif - //std::cout << "old solution cost:" << cur_cost << std::endl; + //std::cout << "old solution cost:" << cur_cost << std::endl; - cur_cost += retainedChain->delta; + cur_cost += retainedChain->delta; - //std::cout << "new solution cost:" << cur_cost << std::endl; - //int nbOv; - //std::cout << "computed solution cost:" << compute_subsolution_cost (part, sol, &nbOv) << std::endl; - //std::cout << "Overlap: " << nbOv << std::endl; + //std::cout << "new solution cost:" << cur_cost << std::endl; + //int nbOv; + //std::cout << "computed solution cost:" << compute_subsolution_cost (part, sol, &nbOv) << std::endl; + //std::cout << "Overlap: " << nbOv << std::endl; - delete_chain (retainedChain); + delete_chain( retainedChain ); - if (best_cost - cur_cost > EPSILON) { + if ( best_cost - cur_cost > EPSILON ) + { #ifdef _DEBUG_FULL_ - std::cout << "new_best" << std::endl; + std::cout << "new_best" << std::endl; #endif - best_cost = cur_cost; - memcpy (best_sol, sol, sizeof (int) *subSize); + best_cost = cur_cost; + memcpy( best_sol, sol, sizeof( int ) *subSize ); - itBest = it; + itBest = it; - stop_it = (it + itwimp > maxit ? maxit : it + itwimp); - } - sort ( (void**) candidates, probSize, decreaseCost); + stop_it = ( it + itwimp > maxit ? maxit : it + itwimp ); + } + sort(( void** ) candidates, probSize, decreaseCost ); - } + } #ifdef _DEBUG_FULL_ - else { - std::cout << it << " no chain" << std::endl << std::endl; - } + else + { + std::cout << it << " no chain" << std::endl << std::endl; + } #endif - it++; - } - - memcpy (sol, best_sol, sizeof (int) *subSize); - - delete conflicts; - - for (i = 0;i < probSize;i++) - delete candidates[i]; - - delete[] candidates; - delete[] candidatesUnsorted; + it++; + } - for (i = 0;i < subSize;i++) - featWrap[sub[i]] = -1; + memcpy( sol, best_sol, sizeof( int ) *subSize ); - delete[] best_sol; - delete[] tmpsol; - delete[] tabu_list; + delete conflicts; + for ( i = 0;i < probSize;i++ ) + delete candidates[i]; - return initial_cost - best_cost; - } + delete[] candidates; + delete[] candidatesUnsorted; - bool checkCallback (LabelPosition *lp, void *ctx) { - LinkedList *list = (LinkedList*) ctx; - list->push_back (lp); + for ( i = 0;i < subSize;i++ ) + featWrap[sub[i]] = -1; - return true; - } + delete[] best_sol; + delete[] tmpsol; + delete[] tabu_list; - void Problem::check_solution() { + return initial_cost - best_cost; + } - LabelPosition *lp; - int *solution = new int[nbft]; + bool checkCallback( LabelPosition *lp, void *ctx ) + { + LinkedList *list = ( LinkedList* ) ctx; + list->push_back( lp ); - double amin[2]; - double amax[2]; + return true; + } - amin[0] = bbox[0]; - amin[1] = bbox[1]; - amax[0] = bbox[2]; - amax[1] = bbox[3]; - LinkedList *list = new LinkedList (ptrLPosCompare); + void Problem::check_solution() + { - candidates_sol->Search (amin, amax, checkCallback, (void*) list); + LabelPosition *lp; + int *solution = new int[nbft]; - std::cerr << "Check Solution" << std::endl; + double amin[2]; + double amax[2]; - int i; - int nbActive = 0; - for (i = 0;i < nbft;i++) { - solution[i] = -1; - if (sol->s[i] >= 0) - nbActive++; - } + amin[0] = bbox[0]; + amin[1] = bbox[1]; + amax[0] = bbox[2]; + amax[1] = bbox[3]; - if (list->size() != nbActive) { - std::cerr << "Error in solution !!!!" << std::endl; - } + LinkedList *list = new LinkedList ( ptrLPosCompare ); - while (list->size() > 0) { - lp = list->pop_front(); - if (solution[lp->probFeat] >= 0) { - std::cerr << "Doublon : " << lp->probFeat << " " - << solution[lp->probFeat] << "<->" - << lp->id << std::endl; - } + candidates_sol->Search( amin, amax, checkCallback, ( void* ) list ); - solution[lp->probFeat] = lp->id; - //std::cout << "lp->id:" << lp->id <<; - } + std::cerr << "Check Solution" << std::endl; - for (i = 0;i < nbft;i++) { - if (solution[i] != sol->s[i]) { - std::cerr << "Feat " << i << " : " << solution[i] << "<-->" << sol->s[i] << std::endl; - } - } + int i; + int nbActive = 0; + for ( i = 0;i < nbft;i++ ) + { + solution[i] = -1; + if ( sol->s[i] >= 0 ) + nbActive++; } - typedef struct _nokContext { - LabelPosition *lp; - bool *ok; - int *wrap; - } NokContext; - - bool nokCallback (LabelPosition *lp, void *context) { - - LabelPosition *lp2 = ( (NokContext*) context)->lp; - bool *ok = ( (NokContext*) context)->ok; - int *wrap = ( (NokContext*) context)->wrap; + if ( list->size() != nbActive ) + { + std::cerr << "Error in solution !!!!" << std::endl; + } - if (lp2->isInConflict (lp)) { - if (wrap) { - ok[wrap[lp->probFeat]] = false; - } else { - ok[lp->probFeat] = false; - } - } + while ( list->size() > 0 ) + { + lp = list->pop_front(); + if ( solution[lp->probFeat] >= 0 ) + { + std::cerr << "Doublon : " << lp->probFeat << " " + << solution[lp->probFeat] << "<->" + << lp->id << std::endl; + } + + solution[lp->probFeat] = lp->id; + //std::cout << "lp->id:" << lp->id <<; + } - return true; + for ( i = 0;i < nbft;i++ ) + { + if ( solution[i] != sol->s[i] ) + { + std::cerr << "Feat " << i << " : " << solution[i] << "<-->" << sol->s[i] << std::endl; + } + } + } + + typedef struct _nokContext + { + LabelPosition *lp; + bool *ok; + int *wrap; + } NokContext; + + bool nokCallback( LabelPosition *lp, void *context ) + { + + LabelPosition *lp2 = (( NokContext* ) context )->lp; + bool *ok = (( NokContext* ) context )->ok; + int *wrap = (( NokContext* ) context )->wrap; + + if ( lp2->isInConflict( lp ) ) + { + if ( wrap ) + { + ok[wrap[lp->probFeat]] = false; + } + else + { + ok[lp->probFeat] = false; + } } + return true; + } + #if 0 // tabu, - void Problem::chain_search() { - int i; + void Problem::chain_search() + { + int i; - int *best_sol = new int[nbft]; + int *best_sol = new int[nbft]; - double initial_cost; - double cur_cost = 0; - double best_cost = 0; + double initial_cost; + double cur_cost = 0; + double best_cost = 0; - int nbOverlap = 0; + int nbOverlap = 0; - int seed; + int seed; - int featOv; + int featOv; - int lid; - int fid; + int lid; + int fid; - int *tabu_list = new int[nbft]; + int *tabu_list = new int[nbft]; - Chain *current_chain = NULL; + Chain *current_chain = NULL; - int it; - int stop_it; - int maxit; - int itwimp; // iteration without improvment + int it; + int stop_it; + int maxit; + int itwimp; // iteration without improvment - int tenure = pal->tenure; - //tenure = 0; + int tenure = pal->tenure; + //tenure = 0; #ifdef _VERBOSE_ - clock_t start_time = clock(); - clock_t init_sol_time; - clock_t search_time; + clock_t start_time = clock(); + clock_t init_sol_time; + clock_t search_time; #endif - init_sol_falp(); + init_sol_falp(); #ifdef _VERBOSE_ - std::cout << " Compute initial solution: " << (double) ( (init_sol_time = clock()) - start_time) / (double) CLOCKS_PER_SEC; + std::cout << " Compute initial solution: " << ( double )(( init_sol_time = clock() ) - start_time ) / ( double ) CLOCKS_PER_SEC; #endif - solution_cost(); + solution_cost(); #ifdef _VERBOSE_ - std::cerr << "\t" << sol->cost << "\t" << nbActive << "\t" << (double) nbActive / (double) nbft; - std::cout << " (solution cost: " << sol->cost << ", nbDisplayed: " << nbActive << "(" << double (nbActive) / nbft << "%)" << std::endl; + std::cerr << "\t" << sol->cost << "\t" << nbActive << "\t" << ( double ) nbActive / ( double ) nbft; + std::cout << " (solution cost: " << sol->cost << ", nbDisplayed: " << nbActive << "(" << double( nbActive ) / nbft << "%)" << std::endl; #endif - cur_cost = sol->cost; + cur_cost = sol->cost; - initial_cost = cur_cost; + initial_cost = cur_cost; - best_cost = cur_cost; + best_cost = cur_cost; - memcpy (best_sol, sol->s, sizeof (int) *nbft); + memcpy( best_sol, sol->s, sizeof( int ) *nbft ); - it = 0; + it = 0; - maxit = nbft * pal->tabuMaxIt; + maxit = nbft * pal->tabuMaxIt; - itwimp = nbft * pal->tabuMinIt;; + itwimp = nbft * pal->tabuMinIt;; - stop_it = itwimp; + stop_it = itwimp; - for (i = 0;i < nbft;i++) - tabu_list[i] = -1; // others aren't + for ( i = 0;i < nbft;i++ ) + tabu_list[i] = -1; // others aren't - while (it < stop_it) { - seed = (it % nbft); + while ( it < stop_it ) + { + seed = ( it % nbft ); - if ( (current_chain = chain (seed))) { + if (( current_chain = chain( seed ) ) ) + { - /* we accept a modification only if the seed is not tabu or - * if the nmodification will generate a new best solution */ - if (tabu_list[seed] < it || (cur_cost + current_chain->delta) - best_cost < -EPSILON) { + /* we accept a modification only if the seed is not tabu or + * if the nmodification will generate a new best solution */ + if ( tabu_list[seed] < it || ( cur_cost + current_chain->delta ) - best_cost < -EPSILON ) + { - for (i = 0;i < current_chain->degree;i++) { - fid = current_chain->feat[i]; - lid = current_chain->label[i]; + for ( i = 0;i < current_chain->degree;i++ ) + { + fid = current_chain->feat[i]; + lid = current_chain->label[i]; - if (sol->s[fid] >= 0) { - labelpositions[sol->s[fid]]->removeFromIndex (candidates_sol); - } - sol->s[fid] = lid; + if ( sol->s[fid] >= 0 ) + { + labelpositions[sol->s[fid]]->removeFromIndex( candidates_sol ); + } + sol->s[fid] = lid; - if (sol->s[fid] >= 0) { - labelpositions[lid]->insertIntoIndex (candidates_sol); - } + if ( sol->s[fid] >= 0 ) + { + labelpositions[lid]->insertIntoIndex( candidates_sol ); + } - tabu_list[fid] = it + tenure; - } + tabu_list[fid] = it + tenure; + } - cur_cost += current_chain->delta; + cur_cost += current_chain->delta; #ifdef _DEBUG_ - std::cout << "cur->cost: " << cur_cost << std::endl; - solution_cost(); - std::cout << "computed cost: " << sol->cost << std::endl << std::endl; -#endif - - /* check if new solution is a new best solution */ - //std::cout << "Costs : " << cur_cost <<" <--> " << best_cost << std::endl; - if (best_cost - cur_cost > EPSILON) { - //std::cout << "New best : " << cur_cost <<" <--> " << best_cost << std::endl; - //std::cout << "New best" << std::endl; - best_cost = cur_cost; - memcpy (best_sol, sol->s, sizeof (int) *nbft); - - stop_it = (it + itwimp > maxit ? maxit : it + itwimp); - } - } - delete_chain (current_chain); - } - it++; + std::cout << "cur->cost: " << cur_cost << std::endl; + solution_cost(); + std::cout << "computed cost: " << sol->cost << std::endl << std::endl; +#endif + + /* check if new solution is a new best solution */ + //std::cout << "Costs : " << cur_cost <<" <--> " << best_cost << std::endl; + if ( best_cost - cur_cost > EPSILON ) + { + //std::cout << "New best : " << cur_cost <<" <--> " << best_cost << std::endl; + //std::cout << "New best" << std::endl; + best_cost = cur_cost; + memcpy( best_sol, sol->s, sizeof( int ) *nbft ); + + stop_it = ( it + itwimp > maxit ? maxit : it + itwimp ); + } } + delete_chain( current_chain ); + } + it++; + } - memcpy (sol->s, best_sol, sizeof (int) *nbft); + memcpy( sol->s, best_sol, sizeof( int ) *nbft ); - candidates_sol->RemoveAll(); - for (i = 0;i < nbft;i++) - if (sol->s[i] != -1) - labelpositions[sol->s[i]]->insertIntoIndex (candidates_sol); + candidates_sol->RemoveAll(); + for ( i = 0;i < nbft;i++ ) + if ( sol->s[i] != -1 ) + labelpositions[sol->s[i]]->insertIntoIndex( candidates_sol ); - std::cout << "Cost : " << cur_cost << std::endl; + std::cout << "Cost : " << cur_cost << std::endl; - solution_cost(); + solution_cost(); #ifdef _VERBOSE_ - std::cout << " Improved solution: " << (double) ( (search_time = clock()) - start_time) / (double) CLOCKS_PER_SEC << " (solution cost: " << sol->cost << ", nbDisplayed: " << nbActive << " (" << (double) nbActive / (double) nbft << "%)" << std::endl; + std::cout << " Improved solution: " << ( double )(( search_time = clock() ) - start_time ) / ( double ) CLOCKS_PER_SEC << " (solution cost: " << sol->cost << ", nbDisplayed: " << nbActive << " (" << ( double ) nbActive / ( double ) nbft << "%)" << std::endl; - std::cerr << "\tna\tchain" << "\tna\t" << it << "\tna\t" << (init_sol_time - start_time) / (double) CLOCKS_PER_SEC << "\t" << (search_time - init_sol_time) / (double) CLOCKS_PER_SEC << "\t" << (search_time - start_time) / (double) CLOCKS_PER_SEC << "\t" << sol->cost << "\t" << nbActive << "\t" << (double) nbActive / (double) nbft; + std::cerr << "\tna\tchain" << "\tna\t" << it << "\tna\t" << ( init_sol_time - start_time ) / ( double ) CLOCKS_PER_SEC << "\t" << ( search_time - init_sol_time ) / ( double ) CLOCKS_PER_SEC << "\t" << ( search_time - start_time ) / ( double ) CLOCKS_PER_SEC << "\t" << sol->cost << "\t" << nbActive << "\t" << ( double ) nbActive / ( double ) nbft; #endif - delete[] best_sol; - delete[] tabu_list; + delete[] best_sol; + delete[] tabu_list; - return; - } + return; + } #endif - void Problem::chain_search() { + void Problem::chain_search() + { - if (nbft == 0) - return; + if ( nbft == 0 ) + return; - int i; + int i; - int seed; - bool *ok = new bool[nbft]; + int seed; + bool *ok = new bool[nbft]; - int fid; - int lid; + int fid; + int lid; #ifdef _VERBOSE_ - clock_t start_time = clock(); - clock_t init_sol_time; - clock_t search_time; + clock_t start_time = clock(); + clock_t init_sol_time; + clock_t search_time; #endif - int popit = 0; + int popit = 0; - int c; - double amin[2]; - double amax[2]; + int c; + double amin[2]; + double amax[2]; - NokContext context; + NokContext context; - context.ok = ok; - context.wrap = NULL; + context.ok = ok; + context.wrap = NULL; - Chain *retainedChain; + Chain *retainedChain; - featWrap = NULL; + featWrap = NULL; - for (i = 0;i < nbft;i++) { - ok[i] = false; - } + for ( i = 0;i < nbft;i++ ) + { + ok[i] = false; + } - //initialization(); - init_sol_falp(); + //initialization(); + init_sol_falp(); - //check_solution(); + //check_solution(); #ifdef _VERBOSE_ - std::cout << " Compute initial solution: " << (double) ( (init_sol_time = clock()) - start_time) / (double) CLOCKS_PER_SEC; + std::cout << " Compute initial solution: " << ( double )(( init_sol_time = clock() ) - start_time ) / ( double ) CLOCKS_PER_SEC; #endif - solution_cost(); + solution_cost(); #ifdef _VERBOSE_ - std::cerr << "\t" << sol->cost << "\t" << nbActive << "\t" << (double) nbActive / (double) nbft; - std::cout << " (solution cost: " << sol->cost << ", nbDisplayed: " << nbActive << "(" << double (nbActive) / nbft << "%)" << std::endl; + std::cerr << "\t" << sol->cost << "\t" << nbActive << "\t" << ( double ) nbActive / ( double ) nbft; + std::cout << " (solution cost: " << sol->cost << ", nbDisplayed: " << nbActive << "(" << double( nbActive ) / nbft << "%)" << std::endl; #endif - int iter = 0; + int iter = 0; - while (true) { + while ( true ) + { - //check_solution(); + //check_solution(); - for (seed = (iter + 1) % nbft; - ok[seed] && seed != iter; - seed = (seed + 1) % nbft); + for ( seed = ( iter + 1 ) % nbft; + ok[seed] && seed != iter; + seed = ( seed + 1 ) % nbft ); - // All seeds are OK - if (seed == iter) { - break; - } + // All seeds are OK + if ( seed == iter ) + { + break; + } - iter = (iter + 1) % nbft; + iter = ( iter + 1 ) % nbft; #ifdef _DEBUG_FULL_ - std::cout << "Seed for it " << popit << " is " << seed << std::endl; + std::cout << "Seed for it " << popit << " is " << seed << std::endl; #endif - retainedChain = chain (seed); + retainedChain = chain( seed ); - if (retainedChain && retainedChain->delta < - EPSILON) { + if ( retainedChain && retainedChain->delta < - EPSILON ) + { #ifdef _DEBUG_FULL_ - std::cout << "chain's degree & delta : " << retainedChain->degree << " " << retainedChain->delta << std::endl; + std::cout << "chain's degree & delta : " << retainedChain->degree << " " << retainedChain->delta << std::endl; #endif - // apply modification - for (i = 0;i < retainedChain->degree;i++) { - fid = retainedChain->feat[i]; - lid = retainedChain->label[i]; -#ifdef _DEBUG_FULL_ - std::cout << " " << i << " :" << fid << " " << lid << std::endl; - std::cout << " sol->s[fid]: " << sol->s[fid] << " <=> " << lid << std::endl; - if (sol->s[fid] == -1 || lid == -1) - std::cout << "feat inactive :" << inactiveCost[fid] << std::endl; - if (sol->s[fid] >= 0) - std::cout << "old cost : " << labelpositions[sol->s[fid]]->cost << std::endl; - if (lid >= 0) - std::cout << "new cost : " << labelpositions[lid]->cost << std::endl; -#endif - - if (sol->s[fid] >= 0) { - LabelPosition *old = labelpositions[sol->s[fid]]; - old->removeFromIndex (candidates_sol); - - - amin[0] = DBL_MAX; - amax[0] = -DBL_MAX; - amin[1] = DBL_MAX; - amax[1] = -DBL_MAX; - for (c = 0;c < 4;c++) { - if (old->x[c] < amin[0]) - amin[0] = old->x[c]; - if (old->x[c] > amax[0]) - amax[0] = old->x[c]; - if (old->y[c] < amin[1]) - amin[1] = old->y[c]; - if (old->y[c] > amax[1]) - amax[1] = old->y[c]; - } - - context.lp = old; - candidates->Search (amin, amax, nokCallback, &context); - } - - sol->s[fid] = lid; - - if (sol->s[fid] >= 0) { - labelpositions[lid]->insertIntoIndex (candidates_sol); - } - - ok[fid] = false; - } - sol->cost += retainedChain->delta; + // apply modification + for ( i = 0;i < retainedChain->degree;i++ ) + { + fid = retainedChain->feat[i]; + lid = retainedChain->label[i]; #ifdef _DEBUG_FULL_ - std::cout << "Expected cost: " << sol->cost << std::endl; - solution_cost (); - std::cout << "chain iteration " << popit << ": " << sol->cost << ", " << retainedChain->delta << ", " << retainedChain->degree << std::endl; + std::cout << " " << i << " :" << fid << " " << lid << std::endl; + std::cout << " sol->s[fid]: " << sol->s[fid] << " <=> " << lid << std::endl; + if ( sol->s[fid] == -1 || lid == -1 ) + std::cout << "feat inactive :" << inactiveCost[fid] << std::endl; + if ( sol->s[fid] >= 0 ) + std::cout << "old cost : " << labelpositions[sol->s[fid]]->cost << std::endl; + if ( lid >= 0 ) + std::cout << "new cost : " << labelpositions[lid]->cost << std::endl; #endif - } else { - // no chain or the one is not god enough - ok[seed] = true; + + if ( sol->s[fid] >= 0 ) + { + LabelPosition *old = labelpositions[sol->s[fid]]; + old->removeFromIndex( candidates_sol ); + + + amin[0] = DBL_MAX; + amax[0] = -DBL_MAX; + amin[1] = DBL_MAX; + amax[1] = -DBL_MAX; + for ( c = 0;c < 4;c++ ) + { + if ( old->x[c] < amin[0] ) + amin[0] = old->x[c]; + if ( old->x[c] > amax[0] ) + amax[0] = old->x[c]; + if ( old->y[c] < amin[1] ) + amin[1] = old->y[c]; + if ( old->y[c] > amax[1] ) + amax[1] = old->y[c]; } - delete_chain (retainedChain); - popit++; + context.lp = old; + candidates->Search( amin, amax, nokCallback, &context ); + } + + sol->s[fid] = lid; + + if ( sol->s[fid] >= 0 ) + { + labelpositions[lid]->insertIntoIndex( candidates_sol ); + } + + ok[fid] = false; } + sol->cost += retainedChain->delta; +#ifdef _DEBUG_FULL_ + std::cout << "Expected cost: " << sol->cost << std::endl; + solution_cost(); + std::cout << "chain iteration " << popit << ": " << sol->cost << ", " << retainedChain->delta << ", " << retainedChain->degree << std::endl; +#endif + } + else + { + // no chain or the one is not god enough + ok[seed] = true; + } + + delete_chain( retainedChain ); + popit++; + } #ifdef _DEBUG_FULL_ - std::cout << "Cur_cost: " << sol->cost << std::endl; - sol->cost = 0; + std::cout << "Cur_cost: " << sol->cost << std::endl; + sol->cost = 0; #endif - solution_cost(); + solution_cost(); #ifdef _VERBOSE_ - std::cout << " Improved solution: " << (double) ( (search_time = clock()) - start_time) / (double) CLOCKS_PER_SEC << " (solution cost: " << sol->cost << ", nbDisplayed: " << nbActive << " (" << (double) nbActive / (double) nbft << "%)" << std::endl; + std::cout << " Improved solution: " << ( double )(( search_time = clock() ) - start_time ) / ( double ) CLOCKS_PER_SEC << " (solution cost: " << sol->cost << ", nbDisplayed: " << nbActive << " (" << ( double ) nbActive / ( double ) nbft << "%)" << std::endl; - std::cerr << "\tna\tchain" << "\tna\t" << popit << "\tna\t" << (init_sol_time - start_time) / (double) CLOCKS_PER_SEC << "\t" << (search_time - init_sol_time) / (double) CLOCKS_PER_SEC << "\t" << (search_time - start_time) / (double) CLOCKS_PER_SEC << "\t" << sol->cost << "\t" << nbActive << "\t" << (double) nbActive / (double) nbft; + std::cerr << "\tna\tchain" << "\tna\t" << popit << "\tna\t" << ( init_sol_time - start_time ) / ( double ) CLOCKS_PER_SEC << "\t" << ( search_time - init_sol_time ) / ( double ) CLOCKS_PER_SEC << "\t" << ( search_time - start_time ) / ( double ) CLOCKS_PER_SEC << "\t" << sol->cost << "\t" << nbActive << "\t" << ( double ) nbActive / ( double ) nbft; #endif - delete[] ok; + delete[] ok; - return; - } + return; + } #if 0 - double Problem::popmusic_chain (SubPart *part) { - int i; - - int probSize = part->probSize; - int borderSize = part->borderSize; - int subSize = part->subSize; - int *sub = part->sub; - int *sol = part->sol; - - int *best_sol = new int[subSize]; - - for (i = 0;i < subSize;i++) { - featWrap[sub[i]] = i; - best_sol[i] = sol[i]; - } + double Problem::popmusic_chain( SubPart *part ) + { + int i; + + int probSize = part->probSize; + int borderSize = part->borderSize; + int subSize = part->subSize; + int *sub = part->sub; + int *sol = part->sol; + + int *best_sol = new int[subSize]; + + for ( i = 0;i < subSize;i++ ) + { + featWrap[sub[i]] = i; + best_sol[i] = sol[i]; + } - double initial_cost; - double cur_cost = 0; + double initial_cost; + double cur_cost = 0; - int nbOverlap = 0; + int nbOverlap = 0; - int seed; + int seed; - int featOv; + int featOv; - int lid; - int fid; + int lid; + int fid; - bool *ok = new bool[subSize]; + bool *ok = new bool[subSize]; - Chain *retainedChain = NULL; + Chain *retainedChain = NULL; - int c; - double amin[2]; - double amax[2]; + int c; + double amin[2]; + double amax[2]; - NokContext context; - context.ok = ok; - context.feat = NULL; - context.wrap = featWrap; + NokContext context; + context.ok = ok; + context.feat = NULL; + context.wrap = featWrap; - //int itC; + //int itC; - int iter = 0, it = 0; + int iter = 0, it = 0; - for (i = 0;i < subSize;i++) { - cur_cost += compute_feature_cost (part, i, sol[i], &featOv); - nbOverlap += featOv; - } + for ( i = 0;i < subSize;i++ ) + { + cur_cost += compute_feature_cost( part, i, sol[i], &featOv ); + nbOverlap += featOv; + } - initial_cost = cur_cost; + initial_cost = cur_cost; #ifdef _DEBUG_FULL_ - cout << "Popmusic_chain" << std::endl; - std::cout << " initial cost" << initial_cost << std::endl; + cout << "Popmusic_chain" << std::endl; + std::cout << " initial cost" << initial_cost << std::endl; #endif - // feature on border are ok - for (i = 0;i < borderSize;i++) - ok[i] = true; // border is ok + // feature on border are ok + for ( i = 0;i < borderSize;i++ ) + ok[i] = true; // border is ok - for (i = 0;i < probSize;i++) - ok[i+borderSize] = false; // others aren't + for ( i = 0;i < probSize;i++ ) + ok[i+borderSize] = false; // others aren't - while (true) { - for (seed = (iter + 1) % probSize; - ok[seed + borderSize] && seed != iter; - seed = (seed + 1) % probSize); + while ( true ) + { + for ( seed = ( iter + 1 ) % probSize; + ok[seed + borderSize] && seed != iter; + seed = ( seed + 1 ) % probSize ); - if (seed == iter) - break; + if ( seed == iter ) + break; - iter = (iter + 1) % probSize; - seed = seed + borderSize; + iter = ( iter + 1 ) % probSize; + seed = seed + borderSize; - retainedChain = chain (part, seed); + retainedChain = chain( part, seed ); #ifdef _DEBUG_FULL_ - std::cout << " seed: " << seed << "(" << seed - borderSize << " / " << probSize << ")" << std::endl; - std::cout << " chain(seed)"; - if (retainedChain) { - std::cout << " delta: " << retainedChain->delta << std::endl; - } else - std::cout << ": undef" << std::endl; + std::cout << " seed: " << seed << "(" << seed - borderSize << " / " << probSize << ")" << std::endl; + std::cout << " chain(seed)"; + if ( retainedChain ) + { + std::cout << " delta: " << retainedChain->delta << std::endl; + } + else + std::cout << ": undef" << std::endl; +#endif + + if ( retainedChain && retainedChain->delta < -EPSILON ) + { +#ifdef _DEBUG_FULL_ + std::cout << " chain accepted " << std::endl; #endif + for ( i = 0;i < retainedChain->degree;i++ ) + { + fid = retainedChain->feat[i]; + lid = retainedChain->label[i]; - if (retainedChain && retainedChain->delta < -EPSILON) { -#ifdef _DEBUG_FULL_ - std::cout << " chain accepted " << std::endl; -#endif - for (i = 0;i < retainedChain->degree;i++) { - fid = retainedChain->feat[i]; - lid = retainedChain->label[i]; - - if (sol[fid] >= 0) { - LabelPosition *old = labelpositions[sol[fid]]; - old->removeFromIndex (candidates_subsol); - - amin[0] = DBL_MAX; - amax[0] = -DBL_MAX; - amin[1] = DBL_MAX; - amax[1] = -DBL_MAX; - for (c = 0;c < 4;c++) { - if (old->x[c] < amin[0]) - amin[0] = old->x[c]; - if (old->x[c] > amax[0]) - amax[0] = old->x[c]; - if (old->y[c] < amin[1]) - amin[1] = old->y[c]; - if (old->y[c] > amax[1]) - amax[1] = old->y[c]; - } - - context.lp = old; - candidates->Search (amin, amax, nokCallback, &context); - } - - sol[fid] = lid; - - if (sol[fid] >= 0) - labelpositions[lid]->insertIntoIndex (candidates_subsol); - - ok[fid] = false; - } + if ( sol[fid] >= 0 ) + { + LabelPosition *old = labelpositions[sol[fid]]; + old->removeFromIndex( candidates_subsol ); - cur_cost += retainedChain->delta; -#ifdef _DEBUG_FULL_ - std::cout << " cur->cost: " << cur_cost << std::endl; - int kov; - std::cout << " computed cost: " << compute_subsolution_cost (part, sol, &kov) << std::endl << std::endl; -#endif - } else { - ok[seed] = true; + amin[0] = DBL_MAX; + amax[0] = -DBL_MAX; + amin[1] = DBL_MAX; + amax[1] = -DBL_MAX; + for ( c = 0;c < 4;c++ ) + { + if ( old->x[c] < amin[0] ) + amin[0] = old->x[c]; + if ( old->x[c] > amax[0] ) + amax[0] = old->x[c]; + if ( old->y[c] < amin[1] ) + amin[1] = old->y[c]; + if ( old->y[c] > amax[1] ) + amax[1] = old->y[c]; } - delete_chain (retainedChain); - it++; + + context.lp = old; + candidates->Search( amin, amax, nokCallback, &context ); + } + + sol[fid] = lid; + + if ( sol[fid] >= 0 ) + labelpositions[lid]->insertIntoIndex( candidates_subsol ); + + ok[fid] = false; } - for (i = 0;i < subSize;i++) - featWrap[sub[i]] = -1; + cur_cost += retainedChain->delta; +#ifdef _DEBUG_FULL_ + std::cout << " cur->cost: " << cur_cost << std::endl; + int kov; + std::cout << " computed cost: " << compute_subsolution_cost( part, sol, &kov ) << std::endl << std::endl; +#endif + } + else + { + ok[seed] = true; + } + delete_chain( retainedChain ); + it++; + } + + for ( i = 0;i < subSize;i++ ) + featWrap[sub[i]] = -1; - delete[] ok; + delete[] ok; #ifdef _DEBUG_FULL_ - std::cout << "Final cost : " << cur_cost << " (" << initial_cost - cur_cost << ")" << std::endl; + std::cout << "Final cost : " << cur_cost << " (" << initial_cost - cur_cost << ")" << std::endl; #endif - return initial_cost - cur_cost; - } + return initial_cost - cur_cost; + } //#undef _DEBUG_FULL_ #endif - std::list * Problem::getSolution (bool returnInactive) { + std::list * Problem::getSolution( bool returnInactive ) + { - int i; - std::list *solList = new std::list(); + int i; + std::list *solList = new std::list(); - if (nbft == 0) - return solList; + if ( nbft == 0 ) + return solList; - for (i = 0;i < nbft;i++) - if (sol->s[i] != -1) - solList->push_back (labelpositions[sol->s[i]]->toLabel (true)); - else if (returnInactive) - solList->push_back (labelpositions[featStartId[i]]->toLabel (false)); + for ( i = 0;i < nbft;i++ ) + if ( sol->s[i] != -1 ) + solList->push_back( labelpositions[sol->s[i]]->toLabel( true ) ); + else if ( returnInactive ) + solList->push_back( labelpositions[featStartId[i]]->toLabel( false ) ); - return solList; - } + return solList; + } - PalStat * Problem::getStats() { - int i, j; + PalStat * Problem::getStats() + { + int i, j; - PalStat *stats = new PalStat(); + PalStat *stats = new PalStat(); - stats->nbObjects = nbft; - stats->nbLabelledObjects = 0; + stats->nbObjects = nbft; + stats->nbLabelledObjects = 0; - stats->nbLayers = nbLabelledLayers; - stats->layersName = new char*[stats->nbLayers]; - stats->layersNbObjects = new int[stats->nbLayers]; - stats->layersNbLabelledObjects = new int[stats->nbLayers]; + stats->nbLayers = nbLabelledLayers; + stats->layersName = new char*[stats->nbLayers]; + stats->layersNbObjects = new int[stats->nbLayers]; + stats->layersNbLabelledObjects = new int[stats->nbLayers]; - for (i = 0;i < stats->nbLayers;i++) { - stats->layersName[i] = new char[strlen (labelledLayersName[i]) + 1]; - strcpy (stats->layersName[i], labelledLayersName[i]); - stats->layersNbObjects[i] = 0; - stats->layersNbLabelledObjects[i] = 0; - } + for ( i = 0;i < stats->nbLayers;i++ ) + { + stats->layersName[i] = new char[strlen( labelledLayersName[i] ) + 1]; + strcpy( stats->layersName[i], labelledLayersName[i] ); + stats->layersNbObjects[i] = 0; + stats->layersNbLabelledObjects[i] = 0; + } - char *lyrName; - int k; - for (i = 0;i < nbft;i++) { - lyrName = labelpositions[featStartId[i]]->feature->layer->name; - k = -1; - for (j = 0;j < stats->nbLayers;j++) { - if (strcmp (lyrName, stats->layersName[j]) == 0) { - k = j; - break; - } - } - if (k != -1) { - stats->layersNbObjects[k]++; - if (sol->s[i] >= 0) { - stats->layersNbLabelledObjects[k]++; - stats->nbLabelledObjects++; - } - } else { - std::cerr << "Error unknown layers while computing stats: " << lyrName << std::endl; - } + char *lyrName; + int k; + for ( i = 0;i < nbft;i++ ) + { + lyrName = labelpositions[featStartId[i]]->feature->layer->name; + k = -1; + for ( j = 0;j < stats->nbLayers;j++ ) + { + if ( strcmp( lyrName, stats->layersName[j] ) == 0 ) + { + k = j; + break; } - - return stats; + } + if ( k != -1 ) + { + stats->layersNbObjects[k]++; + if ( sol->s[i] >= 0 ) + { + stats->layersNbLabelledObjects[k]++; + stats->nbLabelledObjects++; + } + } + else + { + std::cerr << "Error unknown layers while computing stats: " << lyrName << std::endl; + } } - void Problem::post_optimization() { -#if 0 - /* - * this->sol => s[nbFeature] s[i] = quel label pour la feat. i - * this->labelpositions => tout les candidats à la suite pour toute les feature - * labelpositions[sol->s[i]] => label choisi pour la feat. i (attention sol->s[i] peut == -1 pour indiquer que le label est pas affiché) - * - * this->featStartId => featStartId[i] indice du premier candidate dans labelposiiton pour la feat. i - * this->feat => a quel feat correspond un candidats (feat[labelId] == feature id) - * - * - * - * - * labelpositon[i]->geometry == la geometrie qui correspond au label (possible que ça soit NULL) dans ce cas c'est labelpositions[i]->feature qui doit etre utilisée (normalement c'est que pour les points) - * - * - * - * L'appel a cette méthode est fait dans pal->labeller - * - */ - Feature *feature; - LabelPosition *lp; - - int i, j; - double xrm, yrm; - - std::ofstream solution ("solution.raw"); - solution << "GeomType ; nbPoints ; label length ; label height ; down-left X ; down-left Y ; rotation (rad) ; points list" << std::endl; - for (i = 0;i < nbft;i++) { - - if (sol->s[i] >= 0) { - lp = labelpositions[sol->s[i]]; - if (lp->feature->layer->label_unit == PIXEL) { - xrm = px2meters (lp->feature->label_x, pal->dpi, scale); - yrm = px2meters (lp->feature->label_y, pal->dpi, scale); - } else { - xrm = lp->feature->label_x; - yrm = lp->feature->label_y; - } - } else { - lp = labelpositions[featStartId[i]]; - xrm = yrm = 0; - } - + return stats; + } - feature = lp->feature; - - if (sol->s[i] >= 0) { - solution << feature->type << ";" << feature->nbPoints << ";" << xrm << ";" << yrm - << ";" << lp->x[0] << ";" << lp->y[0] << ";" << lp->alpha << ";"; - } else { - solution << feature->type << ";" << feature->nbPoints << ";0;0;0;0;0;"; - } - - feature->fetchCoordinates (pal); - for (j = 0;j < feature->nbPoints;j++) { - solution << feature->x[j] << " " << feature->y[j] << " "; - } - feature->releaseCoordinates(); - solution << std::endl; + void Problem::post_optimization() + { +#if 0 + /* + * this->sol => s[nbFeature] s[i] = quel label pour la feat. i + * this->labelpositions => tout les candidats à la suite pour toute les feature + * labelpositions[sol->s[i]] => label choisi pour la feat. i (attention sol->s[i] peut == -1 pour indiquer que le label est pas affiché) + * + * this->featStartId => featStartId[i] indice du premier candidate dans labelposiiton pour la feat. i + * this->feat => a quel feat correspond un candidats (feat[labelId] == feature id) + * + * + * + * + * labelpositon[i]->geometry == la geometrie qui correspond au label (possible que ça soit NULL) dans ce cas c'est labelpositions[i]->feature qui doit etre utilisée (normalement c'est que pour les points) + * + * + * + * L'appel a cette méthode est fait dans pal->labeller + * + */ + Feature *feature; + LabelPosition *lp; + + int i, j; + double xrm, yrm; + + std::ofstream solution( "solution.raw" ); + solution << "GeomType ; nbPoints ; label length ; label height ; down-left X ; down-left Y ; rotation (rad) ; points list" << std::endl; + for ( i = 0;i < nbft;i++ ) + { + + if ( sol->s[i] >= 0 ) + { + lp = labelpositions[sol->s[i]]; + if ( lp->feature->layer->label_unit == PIXEL ) + { + xrm = px2meters( lp->feature->label_x, pal->dpi, scale ); + yrm = px2meters( lp->feature->label_y, pal->dpi, scale ); } - - solution.close(); -#endif + else + { + xrm = lp->feature->label_x; + yrm = lp->feature->label_y; + } + } + else + { + lp = labelpositions[featStartId[i]]; + xrm = yrm = 0; + } + + + feature = lp->feature; + + if ( sol->s[i] >= 0 ) + { + solution << feature->type << ";" << feature->nbPoints << ";" << xrm << ";" << yrm + << ";" << lp->x[0] << ";" << lp->y[0] << ";" << lp->alpha << ";"; + } + else + { + solution << feature->type << ";" << feature->nbPoints << ";0;0;0;0;0;"; + } + + feature->fetchCoordinates( pal ); + for ( j = 0;j < feature->nbPoints;j++ ) + { + solution << feature->x[j] << " " << feature->y[j] << " "; + } + feature->releaseCoordinates(); + solution << std::endl; } - void Problem::solution_cost() { - -#ifdef _DEBUG_FULL_ - std::cout << "Global solution evaluation" << std::endl; + solution.close(); #endif + } - sol->cost = 0.0; - nbActive = 0; - - int nbOv; - - int c; - int i; - - CountContext context; - context.inactiveCost = inactiveCost; - context.nbOv = &nbOv; - context.cost = &sol->cost; - double amin[2]; - double amax[2]; - LabelPosition *lp; - - int nbHidden = 0; + void Problem::solution_cost() + { - for (i = 0;i < nbft;i++) { - if (sol->s[i] == -1) { - sol->cost += inactiveCost[i]; - nbHidden++; - } else { - nbOv = 0; - lp = labelpositions[sol->s[i]]; - - amin[0] = DBL_MAX; - amax[0] = -DBL_MAX; - amin[1] = DBL_MAX; - amax[1] = -DBL_MAX; - for (c = 0;c < 4;c++) { - if (lp->x[c] < amin[0]) - amin[0] = lp->x[c]; - if (lp->x[c] > amax[0]) - amax[0] = lp->x[c]; - if (lp->y[c] < amin[1]) - amin[1] = lp->y[c]; - if (lp->y[c] > amax[1]) - amax[1] = lp->y[c]; - } - context.lp = lp; - candidates_sol->Search (amin, amax, countFullOverlapCallback, &context); +#ifdef _DEBUG_FULL_ + std::cout << "Global solution evaluation" << std::endl; +#endif + + sol->cost = 0.0; + nbActive = 0; + + int nbOv; + + int c; + int i; + + CountContext context; + context.inactiveCost = inactiveCost; + context.nbOv = &nbOv; + context.cost = &sol->cost; + double amin[2]; + double amax[2]; + LabelPosition *lp; + + int nbHidden = 0; + + for ( i = 0;i < nbft;i++ ) + { + if ( sol->s[i] == -1 ) + { + sol->cost += inactiveCost[i]; + nbHidden++; + } + else + { + nbOv = 0; + lp = labelpositions[sol->s[i]]; + + amin[0] = DBL_MAX; + amax[0] = -DBL_MAX; + amin[1] = DBL_MAX; + amax[1] = -DBL_MAX; + for ( c = 0;c < 4;c++ ) + { + if ( lp->x[c] < amin[0] ) + amin[0] = lp->x[c]; + if ( lp->x[c] > amax[0] ) + amax[0] = lp->x[c]; + if ( lp->y[c] < amin[1] ) + amin[1] = lp->y[c]; + if ( lp->y[c] > amax[1] ) + amax[1] = lp->y[c]; + } + context.lp = lp; + candidates_sol->Search( amin, amax, countFullOverlapCallback, &context ); - sol->cost += lp->cost; + sol->cost += lp->cost; - if (nbOv == 0) - nbActive++; - } - } + if ( nbOv == 0 ) + nbActive++; + } + } #ifdef _DEBUG_ - if (nbActive + nbHidden != nbft) { - std::cout << "Conflicts in solution: " << nbHidden / 2 << std::endl; - } - std::cout << "nbActive and free: " << nbActive << " (" << double (nbActive) / double (nbft) << " %)" << std::endl; - std::cout << "solution cost:" << sol->cost << std::endl; -#endif + if ( nbActive + nbHidden != nbft ) + { + std::cout << "Conflicts in solution: " << nbHidden / 2 << std::endl; } + std::cout << "nbActive and free: " << nbActive << " (" << double( nbActive ) / double( nbft ) << " %)" << std::endl; + std::cout << "solution cost:" << sol->cost << std::endl; +#endif + } #ifdef _EXPORT_MAP_ - void Problem::drawLabels (std::ofstream &svgmap) { - int i; - - svgmap << "" << std::endl << std::endl; - - for (i = 0;i < nbft;i++) { - if (sol->s[i] >= 0) { - LabelPosition *lp = labelpositions[sol->s[i]]; - toSVGPath (4, 3, lp->x, lp->y, pal->getDpi(), scale, convert2pt (bbox[0], scale, pal->getDpi()), convert2pt (bbox[3], scale, pal->getDpi()), "label", lp->feature->uid, svgmap); - } - } - - svgmap << "" << std::endl; + void Problem::drawLabels( std::ofstream &svgmap ) + { + int i; + + svgmap << "" << std::endl << std::endl; + + for ( i = 0;i < nbft;i++ ) + { + if ( sol->s[i] >= 0 ) + { + LabelPosition *lp = labelpositions[sol->s[i]]; + toSVGPath( 4, 3, lp->x, lp->y, pal->getDpi(), scale, convert2pt( bbox[0], scale, pal->getDpi() ), convert2pt( bbox[3], scale, pal->getDpi() ), "label", lp->feature->uid, svgmap ); + } } + + svgmap << "" << std::endl; + } #endif } // namespace diff --git a/src/core/pal/problem.h b/src/core/pal/problem.h index 80b702fb200e..1696ffaab3ce 100644 --- a/src/core/pal/problem.h +++ b/src/core/pal/problem.h @@ -38,184 +38,189 @@ #include #include "rtree.hpp" -namespace pal { +namespace pal +{ - class LabelPosition; - class Label; + class LabelPosition; + class Label; - class Sol { + class Sol + { public: - int *s; - double cost; - }; - - typedef struct _subpart { - /** - * # of features in problem - */ - int probSize; - - /** - * # of features bounding the problem - */ - int borderSize; - - /** - * total # features (prob + border) - */ - int subSize; - - /** - * wrap bw sub feat and main feat - */ - int *sub; - /** - * sub solution - */ - int *sol; - /** - * first feat in sub part - */ - int seed; - } SubPart; - - typedef struct _chain { - int degree; - double delta; - int *feat; - int *label; - } Chain; + int *s; + double cost; + }; + typedef struct _subpart + { /** - * \brief Represent a problem + * # of features in problem */ - class Problem { + int probSize; - friend class Pal; + /** + * # of features bounding the problem + */ + int borderSize; + + /** + * total # features (prob + border) + */ + int subSize; + + /** + * wrap bw sub feat and main feat + */ + int *sub; + /** + * sub solution + */ + int *sol; + /** + * first feat in sub part + */ + int seed; + } SubPart; + + typedef struct _chain + { + int degree; + double delta; + int *feat; + int *label; + } Chain; + + /** + * \brief Represent a problem + */ + class Problem + { + + friend class Pal; private: - /** - * How many layers are lebelled ? - */ - int nbLabelledLayers; + /** + * How many layers are lebelled ? + */ + int nbLabelledLayers; - /** - * Names of the labelled layers - */ - char **labelledLayersName; + /** + * Names of the labelled layers + */ + char **labelledLayersName; - /** - * # active candidates (remaining after reduce()) - */ - int nblp; - /** - * # candidates (all, including) - */ - int all_nblp; + /** + * # active candidates (remaining after reduce()) + */ + int nblp; + /** + * # candidates (all, including) + */ + int all_nblp; - /** - * # feature to label - */ - int nbft; + /** + * # feature to label + */ + int nbft; - /** - * if true, special value -1 is prohibited - */ - bool displayAll; + /** + * if true, special value -1 is prohibited + */ + bool displayAll; - /** - * Map extent (xmin, ymin, xmax, ymax) - */ - double bbox[4]; + /** + * Map extent (xmin, ymin, xmax, ymax) + */ + double bbox[4]; - /** - * map scale is 1:scale - */ - double scale; + /** + * map scale is 1:scale + */ + double scale; - double *labelPositionCost; - int *nbOlap; + double *labelPositionCost; + int *nbOlap; - LabelPosition **labelpositions; + LabelPosition **labelpositions; - RTree *candidates; // index all candidates - RTree *candidates_sol; // index active candidates - RTree *candidates_subsol; // idem for subparts + RTree *candidates; // index all candidates + RTree *candidates_sol; // index active candidates + RTree *candidates_subsol; // idem for subparts - //int *feat; // [nblp] - int *featStartId; // [nbft] - int *featNbLp; // [nbft] - double *inactiveCost; // + //int *feat; // [nblp] + int *featStartId; // [nbft] + int *featNbLp; // [nbft] + double *inactiveCost; // - Sol *sol; // [nbft] - int nbActive; + Sol *sol; // [nbft] + int nbActive; - int nbOverlap; + int nbOverlap; - int *featWrap; + int *featWrap; - Chain *chain (SubPart *part, int seed); + Chain *chain( SubPart *part, int seed ); - Chain *chain (int seed); + Chain *chain( int seed ); - Pal *pal; + Pal *pal; - void solution_cost(); - void check_solution(); + void solution_cost(); + void check_solution(); - Problem(); + Problem(); - //Problem(char *lorena_file, bool displayAll); + //Problem(char *lorena_file, bool displayAll); - ~Problem(); + ~Problem(); - void reduce(); + void reduce(); - void post_optimization(); + void post_optimization(); - /** - * \brief popmusic framework - */ - void popmusic(); + /** + * \brief popmusic framework + */ + void popmusic(); - /** - * \brief Test with very-large scale neighborhood - */ - void chain_search(); + /** + * \brief Test with very-large scale neighborhood + */ + void chain_search(); - std::list * getSolution (bool returnInactive); + std::list * getSolution( bool returnInactive ); - PalStat * getStats(); + PalStat * getStats(); - /* usefull only for postscript post-conversion*/ - //void toFile(char *label_file); + /* usefull only for postscript post-conversion*/ + //void toFile(char *label_file); - SubPart *subPart (int r, int featseed, int *isIn); + SubPart *subPart( int r, int featseed, int *isIn ); - void initialization(); + void initialization(); - double compute_feature_cost (SubPart *part, int feat_id, int label_id, int *nbOverlap); - double compute_subsolution_cost (SubPart *part, int *s, int * nbOverlap); + double compute_feature_cost( SubPart *part, int feat_id, int label_id, int *nbOverlap ); + double compute_subsolution_cost( SubPart *part, int *s, int * nbOverlap ); - double popmusic_chain (SubPart *part); + double popmusic_chain( SubPart *part ); - double popmusic_tabu (SubPart *part); - double popmusic_tabu_chain (SubPart *part); + double popmusic_tabu( SubPart *part ); + double popmusic_tabu_chain( SubPart *part ); - void init_sol_empty(); - void init_sol_falp(); + void init_sol_empty(); + void init_sol_falp(); #ifdef _EXPORT_MAP_ - void drawLabels (std::ofstream &svgmap); + void drawLabels( std::ofstream &svgmap ); #endif - }; + }; } // namespace diff --git a/src/core/pal/simplemutex.h b/src/core/pal/simplemutex.h index 1a693856de73..5f13f74df21f 100644 --- a/src/core/pal/simplemutex.h +++ b/src/core/pal/simplemutex.h @@ -56,31 +56,37 @@ #define DESTROY_MUTEX(mutex) (CloseHandle(mutex)) #endif -namespace pal { +namespace pal +{ - typedef THREAD_TYPE MUTEX_T; + typedef THREAD_TYPE MUTEX_T; - class SimpleMutex { + class SimpleMutex + { private: - MUTEX_T mutex; + MUTEX_T mutex; public: - SimpleMutex() { - CREATE_MUTEX (mutex); - } - - ~SimpleMutex() { - DESTROY_MUTEX (mutex); - } - - void lock() { - LOCK (mutex); - } - - void unlock() { - UNLOCK (mutex); - } - }; + SimpleMutex() + { + CREATE_MUTEX( mutex ); + } + + ~SimpleMutex() + { + DESTROY_MUTEX( mutex ); + } + + void lock() + { + LOCK( mutex ); + } + + void unlock() + { + UNLOCK( mutex ); + } + }; } // namespace diff --git a/src/core/pal/util.cpp b/src/core/pal/util.cpp index 7b8e6e109e78..bb16ab741761 100644 --- a/src/core/pal/util.cpp +++ b/src/core/pal/util.cpp @@ -66,498 +66,565 @@ #define M_SQRT2 1.41421356237309504880 #endif -namespace pal { - - void sort (double* heap, int* x, int* y, int N) { - unsigned int n = N, i = n / 2, parent, child; - double t; - int tx; - int ty; - for (;;) { - if (i > 0) { - i--; - t = heap[i]; - tx = x[i]; - ty = y[i]; - } else { - n--; - if (n == 0) return; - t = heap[n]; - tx = x[n]; - ty = y[n]; - heap[n] = heap[0]; - x[n] = x[0]; - y[n] = y[0]; - } - parent = i; - child = i * 2 + 1; - while (child < n) { - if (child + 1 < n && heap[child + 1] > heap[child]) { - child++; - } - if (heap[child] > t) { - heap[parent] = heap[child]; - x[parent] = x[child]; - y[parent] = y[child]; - parent = child; - child = parent * 2 + 1; - } else { - break; - } - } - heap[parent] = t; - x[parent] = tx; - y[parent] = ty; +namespace pal +{ + + void sort( double* heap, int* x, int* y, int N ) + { + unsigned int n = N, i = n / 2, parent, child; + double t; + int tx; + int ty; + for ( ;; ) + { + if ( i > 0 ) + { + i--; + t = heap[i]; + tx = x[i]; + ty = y[i]; + } + else + { + n--; + if ( n == 0 ) return; + t = heap[n]; + tx = x[n]; + ty = y[n]; + heap[n] = heap[0]; + x[n] = x[0]; + y[n] = y[0]; + } + parent = i; + child = i * 2 + 1; + while ( child < n ) + { + if ( child + 1 < n && heap[child + 1] > heap[child] ) + { + child++; } - } - - void tabcpy (int n, const int* const x, const int* const y, - const double* const prob, int *cx, int *cy, double *p) { - int i; - - for (i = 0;i < n;i++) { - cx[i] = x[i]; - cy[i] = y[i]; - p[i] = prob[i]; + if ( heap[child] > t ) + { + heap[parent] = heap[child]; + x[parent] = x[child]; + y[parent] = y[child]; + parent = child; + child = parent * 2 + 1; } + else + { + break; + } + } + heap[parent] = t; + x[parent] = tx; + y[parent] = ty; } - - - void sort (void** items, int N, bool (*greater) (void *l, void *r)) { - - if (N <= 0) - return; - - unsigned int n = (unsigned int) N, i = n / 2, parent, child; - - void *t = NULL; - - for (;;) { - if (i > 0) { - i--; - t = items[i]; - } else { - n--; - if (n == 0) return; - t = items[n]; - items[n] = items[0]; - } - parent = i; - child = i * 2 + 1; - while (child < n) { - if (child + 1 < n && greater (items[child + 1], items[child])) { - child++; - } - if (greater (items[child], t)) { - items[parent] = items[child]; - parent = child; - child = parent * 2 + 1; - } else { - break; - } - } - items[parent] = t; + } + + void tabcpy( int n, const int* const x, const int* const y, + const double* const prob, int *cx, int *cy, double *p ) + { + int i; + + for ( i = 0;i < n;i++ ) + { + cx[i] = x[i]; + cy[i] = y[i]; + p[i] = prob[i]; + } + } + + + void sort( void** items, int N, bool ( *greater )( void *l, void *r ) ) + { + + if ( N <= 0 ) + return; + + unsigned int n = ( unsigned int ) N, i = n / 2, parent, child; + + void *t = NULL; + + for ( ;; ) + { + if ( i > 0 ) + { + i--; + t = items[i]; + } + else + { + n--; + if ( n == 0 ) return; + t = items[n]; + items[n] = items[0]; + } + parent = i; + child = i * 2 + 1; + while ( child < n ) + { + if ( child + 1 < n && greater( items[child + 1], items[child] ) ) + { + child++; + } + if ( greater( items[child], t ) ) + { + items[parent] = items[child]; + parent = child; + child = parent * 2 + 1; } + else + { + break; + } + } + items[parent] = t; } + } - bool countOverlapCallback (LabelPosition *lp, void *ctx) { - LabelPosition *lp2 = (LabelPosition*) ctx; - - if (lp2->isInConflict (lp)) { - lp2->nbOverlap++; - } + bool countOverlapCallback( LabelPosition *lp, void *ctx ) + { + LabelPosition *lp2 = ( LabelPosition* ) ctx; - return true; + if ( lp2->isInConflict( lp ) ) + { + lp2->nbOverlap++; } - bool countFullOverlapCallback (LabelPosition *lp, void *ctx) { - LabelPosition *lp2 = ( (CountContext*) ctx)->lp; - double *cost = ( (CountContext*) ctx)->cost; - //int *feat = ((CountContext*)ctx)->feat; - int *nbOv = ( (CountContext*) ctx)->nbOv; - double *inactiveCost = ( (CountContext*) ctx)->inactiveCost; - if (lp2->isInConflict (lp)) { + return true; + } + + bool countFullOverlapCallback( LabelPosition *lp, void *ctx ) + { + LabelPosition *lp2 = (( CountContext* ) ctx )->lp; + double *cost = (( CountContext* ) ctx )->cost; + //int *feat = ((CountContext*)ctx)->feat; + int *nbOv = (( CountContext* ) ctx )->nbOv; + double *inactiveCost = (( CountContext* ) ctx )->inactiveCost; + if ( lp2->isInConflict( lp ) ) + { #ifdef _DEBUG_FULL_ - std::cout << "count overlap : " << lp->id << "<->" << lp2->id << std::endl; + std::cout << "count overlap : " << lp->id << "<->" << lp2->id << std::endl; #endif - (*nbOv) ++; - *cost += inactiveCost[lp->probFeat] + lp->cost; - - } + ( *nbOv ) ++; + *cost += inactiveCost[lp->probFeat] + lp->cost; - return true; } + return true; + } + //inline bool ptrGeomEq (const geos::geom::Geometry *l, const geos::geom::Geometry *r){ - inline bool ptrGeomEq (const GEOSGeometry *l, const GEOSGeometry *r) { - return l == r; - } + inline bool ptrGeomEq( const GEOSGeometry *l, const GEOSGeometry *r ) + { + return l == r; + } //LinkedList * unmulti (geos::geom::Geometry *the_geom){ - LinkedList * unmulti (GEOSGeometry *the_geom) { - - //LinkedList *queue = new LinkedList(ptrGeomEq); - //LinkedList *final_queue = new LinkedList(ptrGeomEq); - LinkedList *queue = new LinkedList (ptrGeomEq); - LinkedList *final_queue = new LinkedList (ptrGeomEq); - - //const geos::geom::Geometry *geom; - const GEOSGeometry *geom; - - queue->push_back (the_geom); - int nGeom; - int i; - - while (queue->size() > 0) { - geom = queue->pop_front(); - switch (GEOSGeomTypeId (geom)) { - //case geos::geom::GEOS_MULTIPOINT: - //case geos::geom::GEOS_MULTILINESTRING: - //case geos::geom::GEOS_MULTIPOLYGON: - case GEOS_MULTIPOINT: - case GEOS_MULTILINESTRING: - case GEOS_MULTIPOLYGON: - nGeom = GEOSGetNumGeometries (geom); - for (i = 0;i < nGeom;i++) { - queue->push_back (GEOSGetGeometryN (geom, i)); - } - break; - case GEOS_POINT: - case GEOS_LINESTRING: - case GEOS_POLYGON: - final_queue->push_back (geom); - break; - default: - throw InternalException::UnknownGeometry(); - } - } - delete queue; - - return final_queue; + LinkedList * unmulti( GEOSGeometry *the_geom ) + { + + //LinkedList *queue = new LinkedList(ptrGeomEq); + //LinkedList *final_queue = new LinkedList(ptrGeomEq); + LinkedList *queue = new LinkedList ( ptrGeomEq ); + LinkedList *final_queue = new LinkedList ( ptrGeomEq ); + + //const geos::geom::Geometry *geom; + const GEOSGeometry *geom; + + queue->push_back( the_geom ); + int nGeom; + int i; + + while ( queue->size() > 0 ) + { + geom = queue->pop_front(); + switch ( GEOSGeomTypeId( geom ) ) + { + //case geos::geom::GEOS_MULTIPOINT: + //case geos::geom::GEOS_MULTILINESTRING: + //case geos::geom::GEOS_MULTIPOLYGON: + case GEOS_MULTIPOINT: + case GEOS_MULTILINESTRING: + case GEOS_MULTIPOLYGON: + nGeom = GEOSGetNumGeometries( geom ); + for ( i = 0;i < nGeom;i++ ) + { + queue->push_back( GEOSGetGeometryN( geom, i ) ); + } + break; + case GEOS_POINT: + case GEOS_LINESTRING: + case GEOS_POLYGON: + final_queue->push_back( geom ); + break; + default: + throw InternalException::UnknownGeometry(); + } } + delete queue; + return final_queue; + } - /* - * \brief read coordinates from a GEOS geom - */ - void extractXYCoord (Feat *f) { - int i, j; - //Projection *proj = pal->proj; + /* + * \brief read coordinates from a GEOS geom + */ + void extractXYCoord( Feat *f ) + { + int i, j; - const GEOSCoordSequence *coordSeq; + //Projection *proj = pal->proj; - const GEOSGeometry *geom = f->geom; - const GEOSGeometry *r_geom; - const GEOSGeometry *interior; + const GEOSCoordSequence *coordSeq; - switch (GEOSGeomTypeId (geom)) { - case GEOS_POINT: - case GEOS_LINESTRING: - case GEOS_POLYGON: - f->type = GEOSGeomTypeId (geom); - break; - default: - std::cout << "Wrong geometry !!" << std::endl; - } + const GEOSGeometry *geom = f->geom; + const GEOSGeometry *r_geom; + const GEOSGeometry *interior; + + switch ( GEOSGeomTypeId( geom ) ) + { + case GEOS_POINT: + case GEOS_LINESTRING: + case GEOS_POLYGON: + f->type = GEOSGeomTypeId( geom ); + break; + default: + std::cout << "Wrong geometry !!" << std::endl; + } - if (f->type == GEOS_POLYGON) { - r_geom = GEOSGetExteriorRing (geom); - if (GEOSGetNumInteriorRings (geom) > 0) { - f->nbHoles = GEOSGetNumInteriorRings (geom); - f->holes = new PointSet*[f->nbHoles]; + if ( f->type == GEOS_POLYGON ) + { + r_geom = GEOSGetExteriorRing( geom ); + if ( GEOSGetNumInteriorRings( geom ) > 0 ) + { + f->nbHoles = GEOSGetNumInteriorRings( geom ); + f->holes = new PointSet*[f->nbHoles]; #ifdef _DEBUG_FULL_ - std::cout << f->nbHoles << " obstacles !" << std::endl; + std::cout << f->nbHoles << " obstacles !" << std::endl; #endif - for (i = 0;i < f->nbHoles;i++) { - f->holes[i] = new PointSet(); - f->holes[i]->holeOf = NULL; - - interior = GEOSGetInteriorRingN (geom, i); - f->holes[i]->nbPoints = GEOSGetNumCoordinates (interior); - f->holes[i]->x = new double[f->holes[i]->nbPoints]; - f->holes[i]->y = new double[f->holes[i]->nbPoints]; - - f->holes[i]->xmin = DBL_MAX; - f->holes[i]->xmax = -DBL_MAX; - f->holes[i]->ymin = DBL_MAX; - f->holes[i]->ymax = -DBL_MAX; - - coordSeq = GEOSGeom_getCoordSeq (interior); - - for (j = 0;j < f->holes[i]->nbPoints;j++) { - GEOSCoordSeq_getX (coordSeq, j, &f->holes[i]->x[j]); - GEOSCoordSeq_getY (coordSeq, j, &f->holes[i]->y[j]); - - f->holes[i]->xmax = f->holes[i]->x[j] > f->holes[i]->xmax ? f->holes[i]->x[j] : f->holes[i]->xmax; - f->holes[i]->xmin = f->holes[i]->x[j] < f->holes[i]->xmin ? f->holes[i]->x[j] : f->holes[i]->xmin; - - f->holes[i]->ymax = f->holes[i]->y[j] > f->holes[i]->ymax ? f->holes[i]->y[j] : f->holes[i]->ymax; - f->holes[i]->ymin = f->holes[i]->y[j] < f->holes[i]->ymin ? f->holes[i]->y[j] : f->holes[i]->ymin; - } - //delete coordSeq; - reorderPolygon (f->holes[i]->nbPoints, f->holes[i]->x, f->holes[i]->y); - } - } - } else { - r_geom = geom; - f->nbHoles = 0; + for ( i = 0;i < f->nbHoles;i++ ) + { + f->holes[i] = new PointSet(); + f->holes[i]->holeOf = NULL; + + interior = GEOSGetInteriorRingN( geom, i ); + f->holes[i]->nbPoints = GEOSGetNumCoordinates( interior ); + f->holes[i]->x = new double[f->holes[i]->nbPoints]; + f->holes[i]->y = new double[f->holes[i]->nbPoints]; + + f->holes[i]->xmin = DBL_MAX; + f->holes[i]->xmax = -DBL_MAX; + f->holes[i]->ymin = DBL_MAX; + f->holes[i]->ymax = -DBL_MAX; + + coordSeq = GEOSGeom_getCoordSeq( interior ); + + for ( j = 0;j < f->holes[i]->nbPoints;j++ ) + { + GEOSCoordSeq_getX( coordSeq, j, &f->holes[i]->x[j] ); + GEOSCoordSeq_getY( coordSeq, j, &f->holes[i]->y[j] ); + + f->holes[i]->xmax = f->holes[i]->x[j] > f->holes[i]->xmax ? f->holes[i]->x[j] : f->holes[i]->xmax; + f->holes[i]->xmin = f->holes[i]->x[j] < f->holes[i]->xmin ? f->holes[i]->x[j] : f->holes[i]->xmin; + + f->holes[i]->ymax = f->holes[i]->y[j] > f->holes[i]->ymax ? f->holes[i]->y[j] : f->holes[i]->ymax; + f->holes[i]->ymin = f->holes[i]->y[j] < f->holes[i]->ymin ? f->holes[i]->y[j] : f->holes[i]->ymin; + } + //delete coordSeq; + reorderPolygon( f->holes[i]->nbPoints, f->holes[i]->x, f->holes[i]->y ); } + } + } + else + { + r_geom = geom; + f->nbHoles = 0; + } - f->nbPoints = GEOSGetNumCoordinates (r_geom); - coordSeq = GEOSGeom_getCoordSeq (r_geom); + f->nbPoints = GEOSGetNumCoordinates( r_geom ); + coordSeq = GEOSGeom_getCoordSeq( r_geom ); - double xmin = DBL_MAX; - double xmax = -DBL_MAX; - double ymin = DBL_MAX; - double ymax = -DBL_MAX; + double xmin = DBL_MAX; + double xmax = -DBL_MAX; + double ymin = DBL_MAX; + double ymax = -DBL_MAX; - //std::cout << "Label: <" << label << "> nbPoints : " << nbPoints << std::endl; - f->x = new double[f->nbPoints]; - f->y = new double[f->nbPoints]; + //std::cout << "Label: <" << label << "> nbPoints : " << nbPoints << std::endl; + f->x = new double[f->nbPoints]; + f->y = new double[f->nbPoints]; - int *pts = new int [f->nbPoints]; + int *pts = new int [f->nbPoints]; #ifdef _DEBUG_FULL_ - std::cout << "ExtractXY (" << f->nbPoints << " points)" << std::endl; + std::cout << "ExtractXY (" << f->nbPoints << " points)" << std::endl; #endif - for (i = 0;i < f->nbPoints;i++) { - GEOSCoordSeq_getX (coordSeq, i, &f->x[i]); - GEOSCoordSeq_getY (coordSeq, i, &f->y[i]); + for ( i = 0;i < f->nbPoints;i++ ) + { + GEOSCoordSeq_getX( coordSeq, i, &f->x[i] ); + GEOSCoordSeq_getY( coordSeq, i, &f->y[i] ); - xmax = f->x[i] > xmax ? f->x[i] : xmax; - xmin = f->x[i] < xmin ? f->x[i] : xmin; + xmax = f->x[i] > xmax ? f->x[i] : xmax; + xmin = f->x[i] < xmin ? f->x[i] : xmin; - ymax = f->y[i] > ymax ? f->y[i] : ymax; - ymin = f->y[i] < ymin ? f->y[i] : ymin; + ymax = f->y[i] > ymax ? f->y[i] : ymax; + ymin = f->y[i] < ymin ? f->y[i] : ymin; - pts[i] = i; + pts[i] = i; #ifdef _DEBUG_FULL_ - std::cout << f->x[i] << ";" << f->y[i] << std::endl; + std::cout << f->x[i] << ";" << f->y[i] << std::endl; #endif - } - - f->minmax[0] = xmin; - f->minmax[1] = ymin; - f->minmax[2] = xmax; - f->minmax[3] = ymax; - - - // TODO make a function with that and add simplify() process - int new_nbPoints = f->nbPoints; - bool *ok = new bool[new_nbPoints]; + } - for (i = 0;i < f->nbPoints;i++) { - ok[i] = true; - j = (i + 1) % f->nbPoints; - if (i == j) - break; - if (vabs (f->x[i] - f->x[j]) < 0.0000001 && vabs (f->y[i] - f->y[j]) < 0.0000001) { - new_nbPoints--; - ok[i] = false; - } - } + f->minmax[0] = xmin; + f->minmax[1] = ymin; + f->minmax[2] = xmax; + f->minmax[3] = ymax; + + + // TODO make a function with that and add simplify() process + int new_nbPoints = f->nbPoints; + bool *ok = new bool[new_nbPoints]; + + for ( i = 0;i < f->nbPoints;i++ ) + { + ok[i] = true; + j = ( i + 1 ) % f->nbPoints; + if ( i == j ) + break; + if ( vabs( f->x[i] - f->x[j] ) < 0.0000001 && vabs( f->y[i] - f->y[j] ) < 0.0000001 ) + { + new_nbPoints--; + ok[i] = false; + } + } - if (new_nbPoints < f->nbPoints) { + if ( new_nbPoints < f->nbPoints ) + { #ifdef _DEBUG_FULL_ - std::cout << "Sans Doublon: (" << new_nbPoints << ")" << std::endl; + std::cout << "Sans Doublon: (" << new_nbPoints << ")" << std::endl; #endif - double *new_x = new double[new_nbPoints]; - double *new_y = new double[new_nbPoints]; - for (i = 0, j = 0;i < f->nbPoints;i++) { - if (ok[i]) { - new_x[j] = f->x[i]; - new_y[j] = f->y[i]; + double *new_x = new double[new_nbPoints]; + double *new_y = new double[new_nbPoints]; + for ( i = 0, j = 0;i < f->nbPoints;i++ ) + { + if ( ok[i] ) + { + new_x[j] = f->x[i]; + new_y[j] = f->y[i]; #ifdef _DEBUG_FULL_ - std::cout << new_x[j] << ";" << new_y[j] << std::endl; + std::cout << new_x[j] << ";" << new_y[j] << std::endl; #endif - j++; - } - } - delete[] f->x; - delete[] f->y; - f->x = new_x; - f->y = new_y; - f->nbPoints = new_nbPoints; + j++; } + } + delete[] f->x; + delete[] f->y; + f->x = new_x; + f->y = new_y; + f->nbPoints = new_nbPoints; + } - delete[] ok; + delete[] ok; - //delete coordSeq; - delete[] pts; - } + //delete coordSeq; + delete[] pts; + } + + LinkedList * splitGeom( GEOSGeometry *the_geom, const char *geom_id ) + { + LinkedList *fCoordQueue = new LinkedList ( ptrFeatCompare ); + LinkedList *finalQueue = new LinkedList ( ptrFeatCompare ); - LinkedList * splitGeom (GEOSGeometry *the_geom, const char *geom_id) { - LinkedList *fCoordQueue = new LinkedList (ptrFeatCompare); - LinkedList *finalQueue = new LinkedList (ptrFeatCompare); - - LinkedList *simpleGeometries = unmulti (the_geom); - - int i, j, k, l, j2, l2; - - const GEOSGeometry *geom; - - int pt_a = -1; - int pt_b = -1; - double cX, cY; - double tmpX, tmpY; - - Feat *f; - - while (simpleGeometries->size() > 0) { - geom = simpleGeometries->pop_front(); - //std::cout << " split->typeid : " << geom->getGeometryTypeId() << std::endl; - switch (GEOSGeomTypeId (geom)) { - case GEOS_MULTIPOINT: - case GEOS_MULTILINESTRING: - case GEOS_MULTIPOLYGON: - std::cerr << "MUTLI geometry should never occurs here" << std::endl; - break; - case GEOS_POINT: - case GEOS_LINESTRING: - f = new Feat(); - f->geom = geom; - f->id = geom_id; - f->type = GEOSGeomTypeId (geom); - extractXYCoord (f); - fCoordQueue->push_back (f); - break; - case GEOS_POLYGON: - f = new Feat(); - f->geom = geom; - f->id = geom_id; - f->type = GEOS_POLYGON; - extractXYCoord (f); - - // BUGFIX #8 by maxence -- 11/03/2008 - if (f->nbPoints >= 3) { + LinkedList *simpleGeometries = unmulti( the_geom ); + + int i, j, k, l, j2, l2; + + const GEOSGeometry *geom; + + int pt_a = -1; + int pt_b = -1; + double cX, cY; + double tmpX, tmpY; + + Feat *f; + + while ( simpleGeometries->size() > 0 ) + { + geom = simpleGeometries->pop_front(); + //std::cout << " split->typeid : " << geom->getGeometryTypeId() << std::endl; + switch ( GEOSGeomTypeId( geom ) ) + { + case GEOS_MULTIPOINT: + case GEOS_MULTILINESTRING: + case GEOS_MULTIPOLYGON: + std::cerr << "MUTLI geometry should never occurs here" << std::endl; + break; + case GEOS_POINT: + case GEOS_LINESTRING: + f = new Feat(); + f->geom = geom; + f->id = geom_id; + f->type = GEOSGeomTypeId( geom ); + extractXYCoord( f ); + fCoordQueue->push_back( f ); + break; + case GEOS_POLYGON: + f = new Feat(); + f->geom = geom; + f->id = geom_id; + f->type = GEOS_POLYGON; + extractXYCoord( f ); + + // BUGFIX #8 by maxence -- 11/03/2008 + if ( f->nbPoints >= 3 ) + { #ifdef _DEBUG_FULL_ - std::cout << "new polygon for " << geom_id << " (" << f->nbPoints << " pts)" << std::endl; - for (i = 0;i < f->nbPoints;i++) { - std::cout << f->x[i] << " ; " << f->y[i] << std::endl; - } + std::cout << "new polygon for " << geom_id << " (" << f->nbPoints << " pts)" << std::endl; + for ( i = 0;i < f->nbPoints;i++ ) + { + std::cout << f->x[i] << " ; " << f->y[i] << std::endl; + } #endif - if (reorderPolygon (f->nbPoints, f->x, f->y) == 0) { + if ( reorderPolygon( f->nbPoints, f->x, f->y ) == 0 ) + { #ifdef _DEBUG_FULL_ - std::cout << "reordered: " << geom_id << " (" << f->nbPoints << " pts)" << std::endl; - for (i = 0;i < f->nbPoints;i++) { - std::cout << f->x[i] << " ; " << f->y[i] << std::endl; - } + std::cout << "reordered: " << geom_id << " (" << f->nbPoints << " pts)" << std::endl; + for ( i = 0;i < f->nbPoints;i++ ) + { + std::cout << f->x[i] << " ; " << f->y[i] << std::endl; + } #endif - fCoordQueue->push_back (f); - } else { - std::cout << __FILE__ << ":" << __LINE__ << " Unable to reorder the polygon ..." << std::endl; - for (i = 0;i < f->nbHoles;i++) - delete f->holes[i]; - delete f->holes; - delete f->x; - delete f->y; - delete f; - } - } else { - std::cout << "Geometry " << geom_id << " is invalid (less than 3 real points)" << std::endl; - for (i = 0;i < f->nbHoles;i++) - delete f->holes[i]; - delete f->holes; - delete[] f->x; - delete[] f->y; - delete f; - } - break; - default: - throw InternalException::UnknownGeometry(); + fCoordQueue->push_back( f ); } - } + else + { + std::cout << __FILE__ << ":" << __LINE__ << " Unable to reorder the polygon ..." << std::endl; + for ( i = 0;i < f->nbHoles;i++ ) + delete f->holes[i]; + delete f->holes; + delete f->x; + delete f->y; + delete f; + } + } + else + { + std::cout << "Geometry " << geom_id << " is invalid (less than 3 real points)" << std::endl; + for ( i = 0;i < f->nbHoles;i++ ) + delete f->holes[i]; + delete f->holes; + delete[] f->x; + delete[] f->y; + delete f; + } + break; + default: + throw InternalException::UnknownGeometry(); + } + } - delete simpleGeometries; + delete simpleGeometries; - cX = 0.0; - cY = 0.0; + cX = 0.0; + cY = 0.0; - while (fCoordQueue->size() > 0) { - f = fCoordQueue->pop_front(); + while ( fCoordQueue->size() > 0 ) + { + f = fCoordQueue->pop_front(); - if (f->type == GEOS_POLYGON) { + if ( f->type == GEOS_POLYGON ) + { #ifdef _DEBUG_FULL_ - std::cout << "New feature coordinates:" << std::endl; - for (i = 0;i < f->nbPoints;i++) - std::cout << f->x[i] << ";" << f->y[i] << std::endl; + std::cout << "New feature coordinates:" << std::endl; + for ( i = 0;i < f->nbPoints;i++ ) + std::cout << f->x[i] << ";" << f->y[i] << std::endl; #endif - // Butterfly detector - // - // 3____0 - // \ / - // \/ <--- not allowed - // /\ - // 1/__\2 - // - // 1____0 - // \ / - // 2\/5 <--- allowed - // /\ - // 3/__\4 - // - pt_a = -1; - pt_b = -1; - for (i = 0;i < f->nbPoints - 2;i++) { - j = i + 1; - j2 = (j + 1) % f->nbPoints; - for (k = i + 2;k < f->nbPoints - (i == 0);k++) { - l = (k + 1) % f->nbPoints; - l2 = (l + 1) % f->nbPoints; - - //std::cout << " " << i << "->" << j << " " << k << "->" << l << std::endl; - if (computeSegIntersectionExt (f->x[i], f->y[i], - f->x[j], f->y[j], - f->x[j2], f->y[j2], - f->x[k], f->y[k], - f->x[l], f->y[l], - f->x[l2], f->y[l2], - &tmpX, &tmpY)) { + // Butterfly detector + // + // 3____0 + // \ / + // \/ <--- not allowed + // /\ + // 1/__\2 + // + // 1____0 + // \ / + // 2\/5 <--- allowed + // /\ + // 3/__\4 + // + pt_a = -1; + pt_b = -1; + for ( i = 0;i < f->nbPoints - 2;i++ ) + { + j = i + 1; + j2 = ( j + 1 ) % f->nbPoints; + for ( k = i + 2;k < f->nbPoints - ( i == 0 );k++ ) + { + l = ( k + 1 ) % f->nbPoints; + l2 = ( l + 1 ) % f->nbPoints; + + //std::cout << " " << i << "->" << j << " " << k << "->" << l << std::endl; + if ( computeSegIntersectionExt( f->x[i], f->y[i], + f->x[j], f->y[j], + f->x[j2], f->y[j2], + f->x[k], f->y[k], + f->x[l], f->y[l], + f->x[l2], f->y[l2], + &tmpX, &tmpY ) ) + { #ifdef _DEBUG_FULL_ - std::cout << i << "->" << j << " intersect " << k << "->" << l << std::endl; + std::cout << i << "->" << j << " intersect " << k << "->" << l << std::endl; #endif - pt_a = i; - pt_b = k; - cX = tmpX; - cY = tmpY; - i = k = f->nbPoints; - } - } - } - - if (pt_a == -1 && pt_b == -1) { - finalQueue->push_back (f); - } else { - //fCoordQueue->push_back(splitButterflyPolygon (f, (pt_a+1)%f->nbPoints, (pt_b+1)%f->nbPoints, cX, cY)); - //fCoordQueue->push_back(splitButterflyPolygon (f, (pt_b+1)%f->nbPoints, (pt_a+1)%f->nbPoints, cX, cY)); - for (i = 0;i < f->nbHoles;i++) - delete f->holes[i]; - delete f->holes; - delete[] f->x; - delete[] f->y; - delete f; - } - } else { - finalQueue->push_back (f); + pt_a = i; + pt_b = k; + cX = tmpX; + cY = tmpY; + i = k = f->nbPoints; } + } + } + if ( pt_a == -1 && pt_b == -1 ) + { + finalQueue->push_back( f ); } - delete fCoordQueue; - //delete the_geom; - return finalQueue; + else + { + //fCoordQueue->push_back(splitButterflyPolygon (f, (pt_a+1)%f->nbPoints, (pt_b+1)%f->nbPoints, cX, cY)); + //fCoordQueue->push_back(splitButterflyPolygon (f, (pt_b+1)%f->nbPoints, (pt_a+1)%f->nbPoints, cX, cY)); + for ( i = 0;i < f->nbHoles;i++ ) + delete f->holes[i]; + delete f->holes; + delete[] f->x; + delete[] f->y; + delete f; + } + } + else + { + finalQueue->push_back( f ); + } + } + delete fCoordQueue; + //delete the_geom; + return finalQueue; + } } // namespace diff --git a/src/core/pal/util.h b/src/core/pal/util.h index 7354ad54fc5c..c4f347d4f2e5 100644 --- a/src/core/pal/util.h +++ b/src/core/pal/util.h @@ -44,230 +44,253 @@ #include "rtree.hpp" #include "pointset.h" -namespace pal { +namespace pal +{ - class LabelPosition; - class Layer; - class Feature; + class LabelPosition; + class Layer; + class Feature; - inline bool ptrFeatureCompare (Feature * a, Feature * b) { - return a == b; - } + inline bool ptrFeatureCompare( Feature * a, Feature * b ) + { + return a == b; + } - /** - * \brief For translating feature from GEOS to Pal - */ - class Feat { - public: - const GEOSGeometry *geom; - const char *id; - int type; + /** + * \brief For translating feature from GEOS to Pal + */ + class Feat + { + public: + const GEOSGeometry *geom; + const char *id; + int type; - int nbPoints; - double *x; - double *y; + int nbPoints; + double *x; + double *y; - double minmax[4]; // {xmin, ymin, xmax, ymax} + double minmax[4]; // {xmin, ymin, xmax, ymax} - int nbHoles; - PointSet **holes; + int nbHoles; + PointSet **holes; - }; + }; - /** - * \brief split GEOS geom (multilinestring, multipoint, multipolygon) => (point, linestring, polygone) - */ - LinkedList * splitGeom (GEOSGeometry *the_geom, const char *geom_id); + /** + * \brief split GEOS geom (multilinestring, multipoint, multipolygon) => (point, linestring, polygone) + */ + LinkedList * splitGeom( GEOSGeometry *the_geom, const char *geom_id ); - typedef struct _feats { - Feature *feature; - PointSet *shape; - double priority; - int nblp; - LabelPosition **lPos; - } Feats; + typedef struct _feats + { + Feature *feature; + PointSet *shape; + double priority; + int nblp; + LabelPosition **lPos; + } Feats; - typedef struct _elementary_transformation { - int feat; - int old_label; - int new_label; - } ElemTrans; + typedef struct _elementary_transformation + { + int feat; + int old_label; + int new_label; + } ElemTrans; #define EPSILON 1e-9 - inline int max (int a, int b) - {return (a > b ? a : b);} + inline int max( int a, int b ) + {return( a > b ? a : b );} + + inline double max( double a, double b ) + {return( a > b ? a : b );} + + inline int min( int a, int b ) + {return( a < b ? a : b );} - inline double max (double a, double b) - {return (a > b ? a : b);} + inline double min( double a, double b ) + {return( a < b ? a : b );} - inline int min (int a, int b) - {return (a < b ? a : b);} + inline double vabs( double x ) + { return x >= 0 ? x : -x; } - inline double min (double a, double b) - {return (a < b ? a : b);} - inline double vabs (double x) - { return x >= 0 ? x : -x; } + inline double degree2meter( double delta_deg ) + { + double lat = delta_deg * 0.5; + const static double rads = ( 4.0 * atan( 1.0 ) ) / 180.0; + double a = cos( lat * rads ); + a = a * a; + double c = 2.0 * atan2( sqrt( a ), sqrt( 1.0 - a ) ); + const static double ra = 6378000; // [m] + const static double e = 0.0810820288; + double radius = ra * ( 1.0 - e * e ) / pow( 1.0 - e * e * sin( lat * rads ) * sin( lat * rads ), 1.5 ); + double meters = ( delta_deg ) / 180.0 * radius * c; // [m] - - inline double degree2meter (double delta_deg){ - double lat = delta_deg*0.5; - const static double rads = (4.0*atan(1.0))/180.0; - double a = cos(lat*rads); - a = a*a; - double c = 2.0*atan2(sqrt(a), sqrt(1.0 - a)); - const static double ra = 6378000; // [m] - const static double e = 0.0810820288; - double radius = ra*(1.0 - e*e) / pow(1.0 - e*e*sin(lat*rads)*sin(lat*rads ), 1.5 ); - double meters = (delta_deg) / 180.0 * radius * c; // [m] + return meters; + } - return meters; + inline double unit_convert( double x, Units from, Units to, int dpi, double scale, double delta_canvas_width ) + { + /* nothing to convert */ + if ( from == to ) + { + return x; } - inline double unit_convert (double x, Units from, Units to, int dpi, double scale, double delta_canvas_width) - { - /* nothing to convert */ - if (from == to){ - return x; + switch ( from ) + { + case pal::PIXEL: + switch ( to ) + { + case pal::METER: + return (( x / double( dpi ) ) * 0.0254 ) * scale; + case pal::FOOT: + return (( x / double( dpi ) )*12 ) * scale; + case pal::DEGREE: + double iw = degree2meter( delta_canvas_width ) * 39.3700787; + return ( x * delta_canvas_width * scale ) / ( iw * dpi ); } - - switch (from){ - case pal::PIXEL: - switch (to){ - case pal::METER: - return ((x / double (dpi)) * 0.0254) * scale; - case pal::FOOT: - return ((x / double (dpi))*12) * scale; - case pal::DEGREE: - double iw = degree2meter(delta_canvas_width)*39.3700787; - return (x * delta_canvas_width * scale) / (iw * dpi); - } - break; - case pal::METER: - switch (to){ - case pal::PIXEL: - return (x*dpi)/(2.54*scale); - case pal::FOOT: - return x/0.3048; - case pal::DEGREE: - double mw = degree2meter(delta_canvas_width); - return (x * delta_canvas_width) / mw; - } - break; - case pal::FOOT: - switch (to){ - case pal::PIXEL: - return (x*dpi)/(12*scale); - case pal::METER: - return x*0.3048; - case pal::DEGREE: - double iw = degree2meter(delta_canvas_width)*39.3700787; - return (x * delta_canvas_width) / iw; - } - break; - case pal::DEGREE: - switch (to){ - case pal::PIXEL: - fprintf (stderr, "Degree to pixel not yet implemented"); - break; - case pal::METER: - fprintf (stderr, "Degree to meter not yet implemented"); - break; - case pal::FOOT: - fprintf (stderr, "Degree to foot not yet implemented"); - break; - } - break; + break; + case pal::METER: + switch ( to ) + { + case pal::PIXEL: + return ( x*dpi ) / ( 2.54*scale ); + case pal::FOOT: + return x / 0.3048; + case pal::DEGREE: + double mw = degree2meter( delta_canvas_width ); + return ( x * delta_canvas_width ) / mw; } - - fprintf (stderr, "Unable to convert. Unknown units"); - return 0.0; + break; + case pal::FOOT: + switch ( to ) + { + case pal::PIXEL: + return ( x*dpi ) / ( 12*scale ); + case pal::METER: + return x*0.3048; + case pal::DEGREE: + double iw = degree2meter( delta_canvas_width ) * 39.3700787; + return ( x * delta_canvas_width ) / iw; + } + break; + case pal::DEGREE: + switch ( to ) + { + case pal::PIXEL: + fprintf( stderr, "Degree to pixel not yet implemented" ); + break; + case pal::METER: + fprintf( stderr, "Degree to meter not yet implemented" ); + break; + case pal::FOOT: + fprintf( stderr, "Degree to foot not yet implemented" ); + break; + } + break; } + fprintf( stderr, "Unable to convert. Unknown units" ); + return 0.0; + } - /* From meters to PostScript Point */ - inline void convert2pt (int *x, double scale, int dpi) { - *x = (int) ( ( (double) * x / scale) * 39.3700787402 * dpi + 0.5); - } + /* From meters to PostScript Point */ + inline void convert2pt( int *x, double scale, int dpi ) + { + *x = ( int )((( double ) * x / scale ) * 39.3700787402 * dpi + 0.5 ); + } - inline int convert2pt (double x, double scale, int dpi) { - return (int) ( (x / scale) * 39.3700787402 * dpi + 0.5); - } + inline int convert2pt( double x, double scale, int dpi ) + { + return ( int )(( x / scale ) * 39.3700787402 * dpi + 0.5 ); + } - void sort (double* heap, int* x, int* y, int N); + void sort( double* heap, int* x, int* y, int N ); - inline bool intCompare (int a, int b) { - return a == b; - } - inline bool strCompare (char * a, char * b) { - return strcmp (a, b) == 0; - } + inline bool intCompare( int a, int b ) + { + return a == b; + } - inline bool ptrLPosCompare (LabelPosition * a, LabelPosition * b) { - return a == b; - } + inline bool strCompare( char * a, char * b ) + { + return strcmp( a, b ) == 0; + } - inline bool ptrPSetCompare (PointSet * a, PointSet * b) { - return a == b; - } + inline bool ptrLPosCompare( LabelPosition * a, LabelPosition * b ) + { + return a == b; + } + inline bool ptrPSetCompare( PointSet * a, PointSet * b ) + { + return a == b; + } - inline bool ptrFeatCompare (Feat * a, Feat * b) { - return a == b; - } - inline bool ptrFeatsCompare (Feats * a, Feats * b) { - return a == b; - } + inline bool ptrFeatCompare( Feat * a, Feat * b ) + { + return a == b; + } - inline bool ptrLayerCompare (Layer * a, Layer * b) { - return a == b; - } + inline bool ptrFeatsCompare( Feats * a, Feats * b ) + { + return a == b; + } + inline bool ptrLayerCompare( Layer * a, Layer * b ) + { + return a == b; + } - inline bool ptrETCompare (ElemTrans * a, ElemTrans * b) { - return a == b; - } - /** - * \brief Sort an array of pointers - * \param items arays of pointers to sort - * \param N number of items - * \param greater function to compare two items - **/ - void sort (void** items, int N, bool (*greater) (void *l, void *r)); + inline bool ptrETCompare( ElemTrans * a, ElemTrans * b ) + { + return a == b; + } + + /** + * \brief Sort an array of pointers + * \param items arays of pointers to sort + * \param N number of items + * \param greater function to compare two items + **/ + void sort( void** items, int N, bool ( *greater )( void *l, void *r ) ); - void tabcpy (int n, const int* const x, const int* const y, - const double* const prob, int *cx, int *cy, double *p); + void tabcpy( int n, const int* const x, const int* const y, + const double* const prob, int *cx, int *cy, double *p ); - typedef struct { - LabelPosition *lp; - int *nbOv; - double *cost; - double *inactiveCost; - //int *feat; - } CountContext; + typedef struct + { + LabelPosition *lp; + int *nbOv; + double *cost; + double *inactiveCost; + //int *feat; + } CountContext; - /* - * count overlap, ctx = p_lp - */ - bool countOverlapCallback (LabelPosition *lp, void *ctx); + /* + * count overlap, ctx = p_lp + */ + bool countOverlapCallback( LabelPosition *lp, void *ctx ); - bool countFullOverlapCallback (LabelPosition *lp, void *ctx); + bool countFullOverlapCallback( LabelPosition *lp, void *ctx ); } // namespace diff --git a/src/core/qgscentralpointpositionmanager.cpp b/src/core/qgscentralpointpositionmanager.cpp index 0a2675a679fb..47d9cde12a86 100644 --- a/src/core/qgscentralpointpositionmanager.cpp +++ b/src/core/qgscentralpointpositionmanager.cpp @@ -31,7 +31,7 @@ QgsCentralPointPositionManager::~QgsCentralPointPositionManager() } -void QgsCentralPointPositionManager::addLayer(QgsVectorLayer* vl, QList& overlays) +void QgsCentralPointPositionManager::addLayer( QgsVectorLayer* vl, QList& overlays ) { mOverlays << overlays; } @@ -41,38 +41,38 @@ void QgsCentralPointPositionManager::removeLayers() mOverlays.clear(); } -void QgsCentralPointPositionManager::findObjectPositions(const QgsRenderContext& context, QGis::UnitType unitType) +void QgsCentralPointPositionManager::findObjectPositions( const QgsRenderContext& context, QGis::UnitType unitType ) { QList::iterator overlay_it = mOverlays.begin(); QgsVectorOverlay* currentOverlay = 0; QgsPoint currentPosition; - for(; overlay_it != mOverlays.end(); ++overlay_it) + for ( ; overlay_it != mOverlays.end(); ++overlay_it ) { currentOverlay = *overlay_it; - if(!currentOverlay) + if ( !currentOverlay ) { continue; } QMap* objectMap = currentOverlay->overlayObjects(); - if(!objectMap) + if ( !objectMap ) { continue; } QMap::iterator object_it = objectMap->begin(); - for(; object_it != objectMap->end(); ++object_it) + for ( ; object_it != objectMap->end(); ++object_it ) { - if(findObjectPosition(object_it.value()->geometry()->asWkb(), currentPosition) == 0) + if ( findObjectPosition( object_it.value()->geometry()->asWkb(), currentPosition ) == 0 ) { - object_it.value()->addPosition(currentPosition); + object_it.value()->addPosition( currentPosition ); } } } } -int QgsCentralPointPositionManager::findObjectPosition(const unsigned char* wkb, QgsPoint& position) const +int QgsCentralPointPositionManager::findObjectPosition( const unsigned char* wkb, QgsPoint& position ) const { QGis::WkbType type; int currentPosition = 0; //parsing position in the wkb binary @@ -80,167 +80,167 @@ int QgsCentralPointPositionManager::findObjectPosition(const unsigned char* wkb, bool hasZValue = false; currentPosition += 1; - memcpy(&type, &(wkb[currentPosition]), sizeof(int)); - currentPosition += sizeof(int); + memcpy( &type, &( wkb[currentPosition] ), sizeof( int ) ); + currentPosition += sizeof( int ); - switch (type) - { + switch ( type ) + { case QGis::WKBMultiPoint: case QGis::WKBMultiPoint25D: - currentPosition += (2 * sizeof(int) + 1); + currentPosition += ( 2 * sizeof( int ) + 1 ); case QGis::WKBPoint25D: case QGis::WKBPoint: - memcpy(¤tX, &(wkb[currentPosition]), sizeof(double)); - currentPosition += sizeof(double); - memcpy(¤tY, &(wkb[currentPosition]), sizeof(double)); - position.setX(currentX); - position.setY(currentY); + memcpy( ¤tX, &( wkb[currentPosition] ), sizeof( double ) ); + currentPosition += sizeof( double ); + memcpy( ¤tY, &( wkb[currentPosition] ), sizeof( double ) ); + position.setX( currentX ); + position.setY( currentY ); return 0; case QGis::WKBMultiLineString25D: case QGis::WKBMultiLineString: + { + int numberOfLines; + memcpy( &numberOfLines, &( wkb[currentPosition] ), sizeof( int ) ); + if ( numberOfLines < 1 ) { - int numberOfLines; - memcpy(&numberOfLines, &(wkb[currentPosition]), sizeof(int)); - if(numberOfLines < 1) - { - return 1; - } - currentPosition += (2 * sizeof(int) + 1); + return 1; } + currentPosition += ( 2 * sizeof( int ) + 1 ); + } case QGis::WKBLineString25D: case QGis::WKBLineString://get the middle point + { + if ( type == QGis::WKBLineString25D || type == QGis::WKBMultiLineString25D ) { - if(type == QGis::WKBLineString25D || type == QGis::WKBMultiLineString25D) - { - hasZValue = true; - } + hasZValue = true; + } - int numberOfPoints; - memcpy(&numberOfPoints, &(wkb[currentPosition]), sizeof(int)); - currentPosition += sizeof(int); - if(numberOfPoints < 1) - { - return 2; - } - if(numberOfPoints > 2) + int numberOfPoints; + memcpy( &numberOfPoints, &( wkb[currentPosition] ), sizeof( int ) ); + currentPosition += sizeof( int ); + if ( numberOfPoints < 1 ) + { + return 2; + } + if ( numberOfPoints > 2 ) + { + int midpoint = ( numberOfPoints - 1 ) / 2 ; + for ( int i = 0; i < midpoint; ++i ) { - int midpoint = (numberOfPoints-1)/2 ; - for(int i = 0; i < midpoint; ++i) - { - currentPosition += 2 * sizeof(double); - if(hasZValue) - { - currentPosition += sizeof(double); - } - } + currentPosition += 2 * sizeof( double ); + if ( hasZValue ) + { + currentPosition += sizeof( double ); + } } - double xPos, yPos; - memcpy(&xPos, &(wkb[currentPosition]), sizeof(double)); - currentPosition+= sizeof(double); - memcpy(&yPos, &(wkb[currentPosition]), sizeof(double)); - position.setX(xPos); - position.setY(yPos); - return 0; } + double xPos, yPos; + memcpy( &xPos, &( wkb[currentPosition] ), sizeof( double ) ); + currentPosition += sizeof( double ); + memcpy( &yPos, &( wkb[currentPosition] ), sizeof( double ) ); + position.setX( xPos ); + position.setY( yPos ); + return 0; + } case QGis::WKBMultiPolygon25D: case QGis::WKBMultiPolygon: - { - int numberOfPolygons; - memcpy(&numberOfPolygons, &(wkb[currentPosition]), sizeof(int)); - if(numberOfPolygons < 1) - { - return 3; - } - currentPosition += sizeof(int); - currentPosition += (1 + sizeof(int)); - } + { + int numberOfPolygons; + memcpy( &numberOfPolygons, &( wkb[currentPosition] ), sizeof( int ) ); + if ( numberOfPolygons < 1 ) + { + return 3; + } + currentPosition += sizeof( int ); + currentPosition += ( 1 + sizeof( int ) ); + } case QGis::WKBPolygon25D: case QGis::WKBPolygon: //calculate the centroid of the first ring + { + //2.5D or 2D type? + if ( type == QGis::WKBPolygon25D || type == QGis::WKBMultiPolygon25D ) { - //2.5D or 2D type? - if(type == QGis::WKBPolygon25D || type == QGis::WKBMultiPolygon25D) - { - hasZValue = true; - } - //number of rings - int numberOfRings; - memcpy(&numberOfRings, &(wkb[currentPosition]), sizeof(int)); - if(numberOfRings < 1) - { - return 4; - } - currentPosition+= sizeof(int); - - //number of points - int numberOfPoints; - memcpy(&numberOfPoints, &(wkb[currentPosition]), sizeof(int)); - if(numberOfPoints < 1) - { - return 5; - } - currentPosition+= sizeof(int); + hasZValue = true; + } + //number of rings + int numberOfRings; + memcpy( &numberOfRings, &( wkb[currentPosition] ), sizeof( int ) ); + if ( numberOfRings < 1 ) + { + return 4; + } + currentPosition += sizeof( int ); - double *x = new double[numberOfPoints]; - double *y = new double[numberOfPoints]; + //number of points + int numberOfPoints; + memcpy( &numberOfPoints, &( wkb[currentPosition] ), sizeof( int ) ); + if ( numberOfPoints < 1 ) + { + return 5; + } + currentPosition += sizeof( int ); - for(int i = 0; i < numberOfPoints; ++i) - { - memcpy(&(x[i]), &(wkb[currentPosition]), sizeof(double)); - currentPosition+= sizeof(double); - memcpy(&(y[i]), &(wkb[currentPosition]), sizeof(double)); - currentPosition+= sizeof(double); - if(hasZValue) - { - currentPosition += sizeof(double); - } - } - double centroidX, centroidY; - int res = calculatePolygonCentroid(x, y, numberOfPoints, centroidX, centroidY); - delete [] x; - delete [] y; + double *x = new double[numberOfPoints]; + double *y = new double[numberOfPoints]; - if( res != 0) - { - return 1; - } - else - { - position.setX(centroidX); - position.setY(centroidY); - return 0; - } + for ( int i = 0; i < numberOfPoints; ++i ) + { + memcpy( &( x[i] ), &( wkb[currentPosition] ), sizeof( double ) ); + currentPosition += sizeof( double ); + memcpy( &( y[i] ), &( wkb[currentPosition] ), sizeof( double ) ); + currentPosition += sizeof( double ); + if ( hasZValue ) + { + currentPosition += sizeof( double ); } + } + double centroidX, centroidY; + int res = calculatePolygonCentroid( x, y, numberOfPoints, centroidX, centroidY ); + delete [] x; + delete [] y; + + if ( res != 0 ) + { + return 1; + } + else + { + position.setX( centroidX ); + position.setY( centroidY ); + return 0; + } + } default: return 6; - } + } return 0; } -int QgsCentralPointPositionManager::calculatePolygonCentroid(double x[], double y[], int numberOfPoints, double& centroidX, double& centroidY) const +int QgsCentralPointPositionManager::calculatePolygonCentroid( double x[], double y[], int numberOfPoints, double& centroidX, double& centroidY ) const { register int i, j; double ai, atmp = 0, xtmp = 0, ytmp = 0; - if(numberOfPoints < 3) - { - return 1; - } + if ( numberOfPoints < 3 ) + { + return 1; + } - for(i = numberOfPoints - 1, j = 0; j < numberOfPoints; i = j, j++) - { - ai = x[i] * y[j] - x[j] * y[i]; - atmp += ai; - xtmp += (x[j] + x[i]) * ai; - ytmp += (y[j] + y[i]) * ai; - } - if(atmp == 0) - { - return 2; - } - centroidX = xtmp/(3*atmp); - centroidY = ytmp/(3*atmp); + for ( i = numberOfPoints - 1, j = 0; j < numberOfPoints; i = j, j++ ) + { + ai = x[i] * y[j] - x[j] * y[i]; + atmp += ai; + xtmp += ( x[j] + x[i] ) * ai; + ytmp += ( y[j] + y[i] ) * ai; + } + if ( atmp == 0 ) + { + return 2; + } + centroidX = xtmp / ( 3 * atmp ); + centroidY = ytmp / ( 3 * atmp ); return 0; } diff --git a/src/core/qgscentralpointpositionmanager.h b/src/core/qgscentralpointpositionmanager.h index c27a52feeafd..fe38ad98b48a 100644 --- a/src/core/qgscentralpointpositionmanager.h +++ b/src/core/qgscentralpointpositionmanager.h @@ -27,23 +27,23 @@ class QgsPoint; a feature. It does not consider conflicts in case of several overlay layers*/ class QgsCentralPointPositionManager: public QgsOverlayObjectPositionManager { - public: - QgsCentralPointPositionManager(); - ~QgsCentralPointPositionManager(); - void addLayer(QgsVectorLayer* vl, QList& overlays); - /**Removes all the overlays*/ - void removeLayers(); - void findObjectPositions(const QgsRenderContext& context, QGis::UnitType unitType); - - private: - /**Calculates the central point for points/lines/polygons. Returns 0 in case of success*/ - int findObjectPosition(const unsigned char* wkb, QgsPoint& position) const; - /**Calculates the polygon centroid with the algorithm from Graphics gems IV: Centroid of a polygon. - @return 0 in case of success*/ - int calculatePolygonCentroid(double x[], double y[], int numberOfPoints, double& centroidX, double& centroidY) const; - - /**Stores all the overlay objects to retrieve all objects when positioning*/ - QList mOverlays; + public: + QgsCentralPointPositionManager(); + ~QgsCentralPointPositionManager(); + void addLayer( QgsVectorLayer* vl, QList& overlays ); + /**Removes all the overlays*/ + void removeLayers(); + void findObjectPositions( const QgsRenderContext& context, QGis::UnitType unitType ); + + private: + /**Calculates the central point for points/lines/polygons. Returns 0 in case of success*/ + int findObjectPosition( const unsigned char* wkb, QgsPoint& position ) const; + /**Calculates the polygon centroid with the algorithm from Graphics gems IV: Centroid of a polygon. + @return 0 in case of success*/ + int calculatePolygonCentroid( double x[], double y[], int numberOfPoints, double& centroidX, double& centroidY ) const; + + /**Stores all the overlay objects to retrieve all objects when positioning*/ + QList mOverlays; }; #endif diff --git a/src/core/qgsgeometry.cpp b/src/core/qgsgeometry.cpp index 7290f9560a23..6cd5b23997f2 100644 --- a/src/core/qgsgeometry.cpp +++ b/src/core/qgsgeometry.cpp @@ -588,9 +588,9 @@ size_t QgsGeometry::wkbSize() GEOSGeometry* QgsGeometry::asGeos() { - if(mDirtyGeos) + if ( mDirtyGeos ) { - if(!exportWkbToGeos()) + if ( !exportWkbToGeos() ) { return 0; } diff --git a/src/core/qgsmaprenderer.cpp b/src/core/qgsmaprenderer.cpp index 1004e5dd8c57..cf589350eb62 100644 --- a/src/core/qgsmaprenderer.cpp +++ b/src/core/qgsmaprenderer.cpp @@ -258,13 +258,13 @@ void QgsMapRenderer::render( QPainter* painter ) bool placeOverlays = false; QgsOverlayObjectPositionManager* overlayManager = overlayManagerFromSettings(); QList allOverlayList; //list of all overlays, used to draw them after layers have been rendered - if(overlayManager) + if ( overlayManager ) { placeOverlays = true; } //add map scale to render context - mRenderContext.setRendererScale(mScale); + mRenderContext.setRendererScale( mScale ); // render all layers in the stack, starting at the base QListIterator li( mLayerSet ); @@ -355,26 +355,26 @@ void QgsMapRenderer::render( QPainter* painter ) } //create overlay objects for features within the view extent - if(ml->type() == QgsMapLayer::VectorLayer && overlayManager) + if ( ml->type() == QgsMapLayer::VectorLayer && overlayManager ) { - QgsVectorLayer* vl = dynamic_cast(ml); - if(vl) - { - QList thisLayerOverlayList; - vl->vectorOverlays(thisLayerOverlayList); + QgsVectorLayer* vl = dynamic_cast( ml ); + if ( vl ) + { + QList thisLayerOverlayList; + vl->vectorOverlays( thisLayerOverlayList ); - QList::iterator overlayIt = thisLayerOverlayList.begin(); - for(; overlayIt != thisLayerOverlayList.end(); ++overlayIt) + QList::iterator overlayIt = thisLayerOverlayList.begin(); + for ( ; overlayIt != thisLayerOverlayList.end(); ++overlayIt ) + { + if (( *overlayIt )->displayFlag() ) { - if((*overlayIt)->displayFlag()) - { - (*overlayIt)->createOverlayObjects(mRenderContext); - allOverlayList.push_back(*overlayIt); - } + ( *overlayIt )->createOverlayObjects( mRenderContext ); + allOverlayList.push_back( *overlayIt ); } - - overlayManager->addLayer(vl, thisLayerOverlayList); } + + overlayManager->addLayer( vl, thisLayerOverlayList ); + } } if ( !ml->draw( mRenderContext ) ) @@ -459,14 +459,14 @@ void QgsMapRenderer::render( QPainter* painter ) } // if (!mOverview) //find overlay positions and draw the vector overlays - if(overlayManager && allOverlayList.size() > 0) + if ( overlayManager && allOverlayList.size() > 0 ) { - overlayManager->findObjectPositions(mRenderContext, mScaleCalculator->mapUnits()); + overlayManager->findObjectPositions( mRenderContext, mScaleCalculator->mapUnits() ); //draw all the overlays QList::iterator allOverlayIt = allOverlayList.begin(); - for(; allOverlayIt != allOverlayList.end(); ++allOverlayIt) + for ( ; allOverlayIt != allOverlayList.end(); ++allOverlayIt ) { - (*allOverlayIt)->drawOverlayObjects(mRenderContext); + ( *allOverlayIt )->drawOverlayObjects( mRenderContext ); } overlayManager->removeLayers(); delete overlayManager; @@ -769,28 +769,28 @@ QStringList& QgsMapRenderer::layerSet() QgsOverlayObjectPositionManager* QgsMapRenderer::overlayManagerFromSettings() { QSettings settings; - QString overlayAlgorithmQString = settings.value( "qgis/overlayPlacementAlgorithm", "Central point").toString(); + QString overlayAlgorithmQString = settings.value( "qgis/overlayPlacementAlgorithm", "Central point" ).toString(); -QgsOverlayObjectPositionManager* result = 0; + QgsOverlayObjectPositionManager* result = 0; - if(overlayAlgorithmQString != "Central point") + if ( overlayAlgorithmQString != "Central point" ) { QgsPALObjectPositionManager* palManager = new QgsPALObjectPositionManager(); - if(overlayAlgorithmQString == "Chain") + if ( overlayAlgorithmQString == "Chain" ) { - palManager->setPlacementAlgorithm("Chain"); + palManager->setPlacementAlgorithm( "Chain" ); } - else if(overlayAlgorithmQString == "Popmusic tabu chain") + else if ( overlayAlgorithmQString == "Popmusic tabu chain" ) { - palManager->setPlacementAlgorithm("Popmusic tabu chain"); + palManager->setPlacementAlgorithm( "Popmusic tabu chain" ); } - else if(overlayAlgorithmQString == "Popmusic tabu") + else if ( overlayAlgorithmQString == "Popmusic tabu" ) { - palManager->setPlacementAlgorithm("Popmusic tabu"); + palManager->setPlacementAlgorithm( "Popmusic tabu" ); } - else if(overlayAlgorithmQString == "Popmusic chain") + else if ( overlayAlgorithmQString == "Popmusic chain" ) { - palManager->setPlacementAlgorithm("Popmusic chain"); + palManager->setPlacementAlgorithm( "Popmusic chain" ); } result = palManager; } diff --git a/src/core/qgsoverlayobject.cpp b/src/core/qgsoverlayobject.cpp index a33cffd170ee..4c29fefe768f 100644 --- a/src/core/qgsoverlayobject.cpp +++ b/src/core/qgsoverlayobject.cpp @@ -18,60 +18,60 @@ #include "qgsoverlayobject.h" #include "qgsgeometry.h" -QgsOverlayObject::QgsOverlayObject(int width, int height, double rotation, QgsGeometry* geometry): mWidth(width), mHeight(height), mRotation(rotation), mGeometry(geometry) +QgsOverlayObject::QgsOverlayObject( int width, int height, double rotation, QgsGeometry* geometry ): mWidth( width ), mHeight( height ), mRotation( rotation ), mGeometry( geometry ) { } QgsOverlayObject::~QgsOverlayObject() { - delete mGeometry; + delete mGeometry; } -QgsOverlayObject::QgsOverlayObject(const QgsOverlayObject& other): mWidth(other.width()), mHeight(other.height()), mPositions(other.positions()), mRotation(other.rotation()) +QgsOverlayObject::QgsOverlayObject( const QgsOverlayObject& other ): mWidth( other.width() ), mHeight( other.height() ), mPositions( other.positions() ), mRotation( other.rotation() ) { - mGeometry = new QgsGeometry(*(other.geometry())); + mGeometry = new QgsGeometry( *( other.geometry() ) ); } -QgsOverlayObject& QgsOverlayObject::operator=(const QgsOverlayObject& other) +QgsOverlayObject& QgsOverlayObject::operator=( const QgsOverlayObject & other ) { mWidth = other.width(); mHeight = other.height(); mPositions = other.positions(); mRotation = other.rotation(); - mGeometry = new QgsGeometry(*(other.geometry())); + mGeometry = new QgsGeometry( *( other.geometry() ) ); return *this; } GEOSGeometry* QgsOverlayObject::getGeosGeometry() { - if(!mGeometry) - { - return 0; - } + if ( !mGeometry ) + { + return 0; + } - return mGeometry->asGeos(); + return mGeometry->asGeos(); } -void QgsOverlayObject::addPosition(const QgsPoint& position) +void QgsOverlayObject::addPosition( const QgsPoint& position ) { - mPositions.push_back(position); + mPositions.push_back( position ); } -void QgsOverlayObject::setGeometry(QgsGeometry* g) +void QgsOverlayObject::setGeometry( QgsGeometry* g ) { - delete mGeometry; - mGeometry = g; + delete mGeometry; + mGeometry = g; } QgsPoint QgsOverlayObject::position() const { - if(mPositions.size() > 0) - { - return mPositions.at(0); - } - else - { - return QgsPoint(0.0, 0.0); - } + if ( mPositions.size() > 0 ) + { + return mPositions.at( 0 ); + } + else + { + return QgsPoint( 0.0, 0.0 ); + } } diff --git a/src/core/qgsoverlayobject.h b/src/core/qgsoverlayobject.h index 3c34a6f611ba..dd017c83a4e5 100644 --- a/src/core/qgsoverlayobject.h +++ b/src/core/qgsoverlayobject.h @@ -30,19 +30,19 @@ class QgsGeometry; class CORE_EXPORT QgsOverlayObject: public pal::PalGeometry { public: - QgsOverlayObject(int width = 0, int height = 0, double rotation = 0, QgsGeometry* geometry = 0); + QgsOverlayObject( int width = 0, int height = 0, double rotation = 0, QgsGeometry* geometry = 0 ); virtual ~QgsOverlayObject(); //copy constructor and assignment operator necessary because of mGeometry - QgsOverlayObject(const QgsOverlayObject& other); - QgsOverlayObject& operator=(const QgsOverlayObject& other); + QgsOverlayObject( const QgsOverlayObject& other ); + QgsOverlayObject& operator=( const QgsOverlayObject& other ); - /**Returns the feature geometry in geos format. The calling function does _not_ take - ownership of the generated object*/ - GEOSGeometry* getGeosGeometry(); - /**Feature geometry is released when object is destructed so this function is empty*/ - void releaseGeosGeometry(GEOSGeometry *the_geom) {} + /**Returns the feature geometry in geos format. The calling function does _not_ take + ownership of the generated object*/ + GEOSGeometry* getGeosGeometry(); + /**Feature geometry is released when object is destructed so this function is empty*/ + void releaseGeosGeometry( GEOSGeometry *the_geom ) {} //getters int width() const {return mWidth;} @@ -54,13 +54,13 @@ class CORE_EXPORT QgsOverlayObject: public pal::PalGeometry QList positions() const {return mPositions;} //setters - void setHeight(int height) {mHeight = height;} - void setWidth(int width) {mWidth = width;} - void setRotation(double rotation) {mRotation = rotation;} + void setHeight( int height ) {mHeight = height;} + void setWidth( int width ) {mWidth = width;} + void setRotation( double rotation ) {mRotation = rotation;} /**Set geometry. This class takes ownership of the object*/ - void setGeometry(QgsGeometry* g); + void setGeometry( QgsGeometry* g ); /**Adds a position in map coordinates*/ - void addPosition(const QgsPoint& position); + void addPosition( const QgsPoint& position ); private: diff --git a/src/core/qgsoverlayobjectpositionmanager.h b/src/core/qgsoverlayobjectpositionmanager.h index fed68718bdb1..09911bb302bc 100644 --- a/src/core/qgsoverlayobjectpositionmanager.h +++ b/src/core/qgsoverlayobjectpositionmanager.h @@ -30,15 +30,15 @@ class QgsOverlayObjectPositionManager { public: - /**Adds a layer that may contain * overlays to the position manager. The overlay objects contained in the - overlays will then be considered in label placement*/ - virtual void addLayer(QgsVectorLayer* vl, QList& overlays) = 0; - /**Removes all the layers*/ - virtual void removeLayers() = 0; - /**Calculate positions for the overlay objects - @param context Context of rendering operation (Painter, scale factor) - @param unitType meters, feet, degrees*/ - virtual void findObjectPositions(const QgsRenderContext& context, QGis::UnitType unitType) = 0; + /**Adds a layer that may contain * overlays to the position manager. The overlay objects contained in the + overlays will then be considered in label placement*/ + virtual void addLayer( QgsVectorLayer* vl, QList& overlays ) = 0; + /**Removes all the layers*/ + virtual void removeLayers() = 0; + /**Calculate positions for the overlay objects + @param context Context of rendering operation (Painter, scale factor) + @param unitType meters, feet, degrees*/ + virtual void findObjectPositions( const QgsRenderContext& context, QGis::UnitType unitType ) = 0; }; #endif diff --git a/src/core/qgspalobjectpositionmanager.cpp b/src/core/qgspalobjectpositionmanager.cpp index 32088d5e4158..c64657919bc4 100644 --- a/src/core/qgspalobjectpositionmanager.cpp +++ b/src/core/qgspalobjectpositionmanager.cpp @@ -1,10 +1,10 @@ - /*************************************************************************** - qgspalobjectpositionmanager.cpp - description - --------------------------------- - begin : October 2008 - copyright : (C) 2008 by Marco Hugentobler - email : marco dot hugentobler at karto dot baug dot ethz dot ch - ***************************************************************************/ +/*************************************************************************** + qgspalobjectpositionmanager.cpp - description + --------------------------------- + begin : October 2008 + copyright : (C) 2008 by Marco Hugentobler + email : marco dot hugentobler at karto dot baug dot ethz dot ch +***************************************************************************/ /*************************************************************************** * * @@ -24,7 +24,7 @@ #include "label.h" #include "layer.h" -QgsPALObjectPositionManager::QgsPALObjectPositionManager(): mNumberOfLayers(0) +QgsPALObjectPositionManager::QgsPALObjectPositionManager(): mNumberOfLayers( 0 ) { } @@ -34,17 +34,17 @@ QgsPALObjectPositionManager::~QgsPALObjectPositionManager() } -void QgsPALObjectPositionManager::addLayer(QgsVectorLayer* vl, QList& overlays) +void QgsPALObjectPositionManager::addLayer( QgsVectorLayer* vl, QList& overlays ) { - if(overlays.size() < 1) - { - return; - } + if ( overlays.size() < 1 ) + { + return; + } //set arrangement based on vector type pal::Arrangement labelArrangement; - switch(vl->geometryType()) - { + switch ( vl->geometryType() ) + { case QGis::Point: labelArrangement = pal::P_POINT; break; @@ -56,43 +56,43 @@ void QgsPALObjectPositionManager::addLayer(QgsVectorLayer* vl, QList::const_iterator overlayIt = overlays.begin(); - for(; overlayIt != overlays.end(); ++overlayIt) + for ( ; overlayIt != overlays.end(); ++overlayIt ) + { + if ( !( *overlayIt ) ) { - if(! (*overlayIt)) - { - continue; - } - - QMap* positionObjects = (*overlayIt)->overlayObjects(); - if(!positionObjects) - { - continue; - } - - QMap::const_iterator objectIt = positionObjects->begin(); - for(; objectIt != positionObjects->end(); ++objectIt) - { - positionLayer->registerFeature(strdup(QString::number(objectNr).toAscii().data()), objectIt.value(), objectIt.value()->width(), objectIt.value()->height()); + continue; + } + + QMap* positionObjects = ( *overlayIt )->overlayObjects(); + if ( !positionObjects ) + { + continue; + } + + QMap::const_iterator objectIt = positionObjects->begin(); + for ( ; objectIt != positionObjects->end(); ++objectIt ) + { + positionLayer->registerFeature( strdup( QString::number( objectNr ).toAscii().data() ), objectIt.value(), objectIt.value()->width(), objectIt.value()->height() ); ++objectNr; } } } -void QgsPALObjectPositionManager::findObjectPositions(const QgsRenderContext& renderContext, QGis::UnitType unitType) +void QgsPALObjectPositionManager::findObjectPositions( const QgsRenderContext& renderContext, QGis::UnitType unitType ) { //trigger label placement QgsRectangle viewExtent = renderContext.extent(); @@ -101,7 +101,7 @@ void QgsPALObjectPositionManager::findObjectPositions(const QgsRenderContext& re //set map units pal::Units mapUnits; - switch (unitType) + switch ( unitType ) { case QGis::Meters: mapUnits = pal::METER; @@ -115,74 +115,74 @@ void QgsPALObjectPositionManager::findObjectPositions(const QgsRenderContext& re mapUnits = pal::DEGREE; break; } - mPositionEngine.setMapUnit(mapUnits); - std::list* resultLabelList = mPositionEngine.labeller(renderContext.rendererScale(), bbox, &stat, true); + mPositionEngine.setMapUnit( mapUnits ); + std::list* resultLabelList = mPositionEngine.labeller( renderContext.rendererScale(), bbox, &stat, true ); delete stat; //and read the positions back to the overlay objects - if(!resultLabelList) - { - return; - } + if ( !resultLabelList ) + { + return; + } QgsOverlayObject* currentOverlayObject = 0; std::list::iterator labelIt = resultLabelList->begin(); - for(; labelIt != resultLabelList->end(); ++labelIt) - { - currentOverlayObject = dynamic_cast((*labelIt)->getGeometry()); - if(!currentOverlayObject) + for ( ; labelIt != resultLabelList->end(); ++labelIt ) + { + currentOverlayObject = dynamic_cast(( *labelIt )->getGeometry() ); + if ( !currentOverlayObject ) { continue; } - //QGIS takes the coordinates of the middle points - double x = ((*labelIt)->getX(0) + (*labelIt)->getX(1) + (*labelIt)->getX(2) + (*labelIt)->getX(3)) / 4; - double y = ((*labelIt)->getY(0) + (*labelIt)->getY(1) + (*labelIt)->getY(2) + (*labelIt)->getY(3)) / 4; - currentOverlayObject->addPosition(QgsPoint(x, y)); - } + //QGIS takes the coordinates of the middle points + double x = (( *labelIt )->getX( 0 ) + ( *labelIt )->getX( 1 ) + ( *labelIt )->getX( 2 ) + ( *labelIt )->getX( 3 ) ) / 4; + double y = (( *labelIt )->getY( 0 ) + ( *labelIt )->getY( 1 ) + ( *labelIt )->getY( 2 ) + ( *labelIt )->getY( 3 ) ) / 4; + currentOverlayObject->addPosition( QgsPoint( x, y ) ); + } } void QgsPALObjectPositionManager::removeLayers() { std::list* layerList = mPositionEngine.getLayers(); - if(!layerList) - { - return; - } + if ( !layerList ) + { + return; + } //Iterators get invalid if elements are deleted in a std::list //Therefore we have to get the layer pointers in a first step and remove them in a second QList layersToRemove; std::list::iterator layerIt = layerList->begin(); - for(; layerIt != layerList->end(); ++layerIt) - { - layersToRemove.push_back(*layerIt); - } + for ( ; layerIt != layerList->end(); ++layerIt ) + { + layersToRemove.push_back( *layerIt ); + } QList::iterator removeIt = layersToRemove.begin(); - for(; removeIt != layersToRemove.end(); ++removeIt) + for ( ; removeIt != layersToRemove.end(); ++removeIt ) { - mPositionEngine.removeLayer(*removeIt); + mPositionEngine.removeLayer( *removeIt ); } } //Chain, Popmusic tabu chain, Popmusic tabu, Popmusic chain -void QgsPALObjectPositionManager::setPlacementAlgorithm(const QString& algorithmName) +void QgsPALObjectPositionManager::setPlacementAlgorithm( const QString& algorithmName ) { - if(algorithmName == "Popmusic tabu chain") + if ( algorithmName == "Popmusic tabu chain" ) { - mPositionEngine.setSearch(pal::POPMUSIC_TABU_CHAIN); + mPositionEngine.setSearch( pal::POPMUSIC_TABU_CHAIN ); } - else if(algorithmName == "Popmusic tabu") + else if ( algorithmName == "Popmusic tabu" ) { - mPositionEngine.setSearch(pal::POPMUSIC_TABU); + mPositionEngine.setSearch( pal::POPMUSIC_TABU ); } - else if(algorithmName == "Popmusic chain") + else if ( algorithmName == "Popmusic chain" ) { - mPositionEngine.setSearch(pal::POPMUSIC_CHAIN); + mPositionEngine.setSearch( pal::POPMUSIC_CHAIN ); } else //default is "Chain" { - mPositionEngine.setSearch(pal::CHAIN); + mPositionEngine.setSearch( pal::CHAIN ); } } diff --git a/src/core/qgspalobjectpositionmanager.h b/src/core/qgspalobjectpositionmanager.h index 97d545ea8b93..4c2065257a2c 100644 --- a/src/core/qgspalobjectpositionmanager.h +++ b/src/core/qgspalobjectpositionmanager.h @@ -1,10 +1,10 @@ - /*************************************************************************** - qgspalobjectpositionmanager.h - description - --------------------------------- - begin : October 2008 - copyright : (C) 2008 by Marco Hugentobler - email : marco dot hugentobler at karto dot baug dot ethz dot ch - ***************************************************************************/ +/*************************************************************************** + qgspalobjectpositionmanager.h - description + --------------------------------- + begin : October 2008 + copyright : (C) 2008 by Marco Hugentobler + email : marco dot hugentobler at karto dot baug dot ethz dot ch +***************************************************************************/ /*************************************************************************** * * @@ -26,13 +26,13 @@ class QgsPALObjectPositionManager: public QgsOverlayObjectPositionManager public: QgsPALObjectPositionManager(); ~QgsPALObjectPositionManager(); - void addLayer(QgsVectorLayer* vl, QList& overlays); - void findObjectPositions(const QgsRenderContext& renderContext, QGis::UnitType unitType); + void addLayer( QgsVectorLayer* vl, QList& overlays ); + void findObjectPositions( const QgsRenderContext& renderContext, QGis::UnitType unitType ); void removeLayers(); /**Sets algorithm used for object placements. Possibilities are: Chain, Popmusic tabu chain, Popmusic tabu, Popmusic chain*/ - void setPlacementAlgorithm(const QString& algorithmName); + void setPlacementAlgorithm( const QString& algorithmName ); private: pal::Pal mPositionEngine; diff --git a/src/core/qgstolerance.cpp b/src/core/qgstolerance.cpp index 5b78e7599ffe..65c4e63a83f2 100644 --- a/src/core/qgstolerance.cpp +++ b/src/core/qgstolerance.cpp @@ -17,9 +17,9 @@ #include -double QgsTolerance::toleranceInMapUnits(double tolerance, double mapUnitsPerPixel, UnitType units) +double QgsTolerance::toleranceInMapUnits( double tolerance, double mapUnitsPerPixel, UnitType units ) { - if (units == MapUnits) + if ( units == MapUnits ) { return tolerance; } @@ -30,14 +30,14 @@ double QgsTolerance::vertexSearchRadius( double mapUnitsPerPixel ) { QSettings settings; double tolerance = settings.value( "/qgis/digitizing/search_radius_vertex_edit", 10 ).toDouble(); - UnitType units = (QgsTolerance::UnitType) settings.value( "/qgis/digitizing/search_radius_vertex_edit_unit", 0 ).toInt(); - return toleranceInMapUnits(tolerance, mapUnitsPerPixel, units); + UnitType units = ( QgsTolerance::UnitType ) settings.value( "/qgis/digitizing/search_radius_vertex_edit_unit", 0 ).toInt(); + return toleranceInMapUnits( tolerance, mapUnitsPerPixel, units ); } double QgsTolerance::defaultTolerance( double mapUnitsPerPixel ) { QSettings settings; double tolerance = settings.value( "/qgis/digitizing/default_snapping_tolerance", 0 ).toDouble(); - UnitType units = (QgsTolerance::UnitType) settings.value( "/qgis/digitizing/default_snapping_tolerance_unit", 0 ).toInt(); - return toleranceInMapUnits(tolerance, mapUnitsPerPixel, units); + UnitType units = ( QgsTolerance::UnitType ) settings.value( "/qgis/digitizing/default_snapping_tolerance_unit", 0 ).toInt(); + return toleranceInMapUnits( tolerance, mapUnitsPerPixel, units ); } diff --git a/src/core/qgstolerance.h b/src/core/qgstolerance.h index 13e370d5273e..6b5eff9ab17e 100644 --- a/src/core/qgstolerance.h +++ b/src/core/qgstolerance.h @@ -27,8 +27,8 @@ class CORE_EXPORT QgsTolerance public: /**Type of unit of tolerance value from settings*/ - enum UnitType - { + enum UnitType + { /**Map unit value*/ MapUnits, /**Pixels unit of tolerance*/ @@ -49,14 +49,14 @@ class CORE_EXPORT QgsTolerance */ static double defaultTolerance( double mapUnitsPerPixel ); - /** + /** * Static function to translate tolerance value into current map unit value * @param tolerace tolerance value to be translated * @param mapUnitsPerPixel number of map units per pixel * @param units type of units to be translated * @return value of tolerance in map units */ - static double toleranceInMapUnits(double tolerance, double mapUnitsPerPixel, UnitType units = MapUnits); + static double toleranceInMapUnits( double tolerance, double mapUnitsPerPixel, UnitType units = MapUnits ); }; diff --git a/src/core/qgsvectorlayer.cpp b/src/core/qgsvectorlayer.cpp index 1fb82b97e73b..611cfd30b07b 100644 --- a/src/core/qgsvectorlayer.cpp +++ b/src/core/qgsvectorlayer.cpp @@ -2510,11 +2510,11 @@ bool QgsVectorLayer::writeSymbology( QDomNode& node, QDomDocument& doc, QString& //save vector overlays (e.g. diagrams) QList::const_iterator overlay_it = mOverlays.constBegin(); - for(; overlay_it != mOverlays.constEnd(); ++overlay_it) + for ( ; overlay_it != mOverlays.constEnd(); ++overlay_it ) { - if(*overlay_it) + if ( *overlay_it ) { - (*overlay_it)->writeXML(mapLayerNode, doc); + ( *overlay_it )->writeXML( mapLayerNode, doc ); } } @@ -3606,33 +3606,33 @@ QgsVectorLayer::RangeData &QgsVectorLayer::range( int idx ) return mRanges[ fields[idx].name()]; } -void QgsVectorLayer::addOverlay(QgsVectorOverlay* overlay) +void QgsVectorLayer::addOverlay( QgsVectorOverlay* overlay ) { - mOverlays.push_back(overlay); + mOverlays.push_back( overlay ); } -void QgsVectorLayer::removeOverlay(const QString& typeName) +void QgsVectorLayer::removeOverlay( const QString& typeName ) { - for(int i = mOverlays.size() - 1; i >=0; --i) + for ( int i = mOverlays.size() - 1; i >= 0; --i ) + { + if ( mOverlays.at( i )->typeName() == typeName ) { - if(mOverlays.at(i)->typeName() == typeName) - { - mOverlays.removeAt(i); - } + mOverlays.removeAt( i ); } + } } -void QgsVectorLayer::vectorOverlays(QList& overlayList) +void QgsVectorLayer::vectorOverlays( QList& overlayList ) { - overlayList = mOverlays; + overlayList = mOverlays; } -QgsVectorOverlay* QgsVectorLayer::findOverlayByType(const QString& typeName) +QgsVectorOverlay* QgsVectorLayer::findOverlayByType( const QString& typeName ) { QList::iterator it = mOverlays.begin(); - for(; it != mOverlays.end(); ++it) + for ( ; it != mOverlays.end(); ++it ) { - if( (*it)->typeName() == typeName) + if (( *it )->typeName() == typeName ) { return *it; } diff --git a/src/core/qgsvectorlayer.h b/src/core/qgsvectorlayer.h index db831b372074..c8e40985cdf9 100644 --- a/src/core/qgsvectorlayer.h +++ b/src/core/qgsvectorlayer.h @@ -428,16 +428,16 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer RangeData &range( int idx ); /**Adds a new overlay to this class. QgsVectorLayer takes ownership of the object*/ - void addOverlay(QgsVectorOverlay* overlay); + void addOverlay( QgsVectorOverlay* overlay ); /**Removes all overlays of a given type*/ - void removeOverlay(const QString& typeName); + void removeOverlay( const QString& typeName ); /**Returns pointers to the overlays of this layer*/ - void vectorOverlays(QList& overlayList); + void vectorOverlays( QList& overlayList ); /**Returns the (first) overlay of a type, e.g. diagram or label*/ - QgsVectorOverlay* findOverlayByType(const QString& typeName); + QgsVectorOverlay* findOverlayByType( const QString& typeName ); public slots: /** Select feature by its ID, optionally emit signal selectionChanged() */ diff --git a/src/core/qgsvectoroverlay.cpp b/src/core/qgsvectoroverlay.cpp index 245c52ad642a..54298839e8be 100644 --- a/src/core/qgsvectoroverlay.cpp +++ b/src/core/qgsvectoroverlay.cpp @@ -1,10 +1,10 @@ - /*************************************************************************** - qgsvectoroverlay.cpp - description - -------------------- - begin : January 2007 - copyright : (C) 2007 by Marco Hugentobler - email : marco dot hugentobler at karto dot baug dot ethz dot ch - ***************************************************************************/ +/*************************************************************************** + qgsvectoroverlay.cpp - description + -------------------- + begin : January 2007 + copyright : (C) 2007 by Marco Hugentobler + email : marco dot hugentobler at karto dot baug dot ethz dot ch +***************************************************************************/ /*************************************************************************** * * @@ -18,7 +18,7 @@ #include "qgsvectoroverlay.h" #include "qgsoverlayobject.h" -QgsVectorOverlay::QgsVectorOverlay(QgsVectorLayer* vl): mVectorLayer(vl), mDisplayFlag(true) +QgsVectorOverlay::QgsVectorOverlay( QgsVectorLayer* vl ): mVectorLayer( vl ), mDisplayFlag( true ) { } @@ -30,10 +30,10 @@ QgsVectorOverlay::~QgsVectorOverlay() void QgsVectorOverlay::removeOverlayObjects() { - QMap::iterator it = mOverlayObjects.begin(); - for(; it != mOverlayObjects.end(); ++it) - { - delete (it.value()); - } - mOverlayObjects.clear(); + QMap::iterator it = mOverlayObjects.begin(); + for ( ; it != mOverlayObjects.end(); ++it ) + { + delete( it.value() ); + } + mOverlayObjects.clear(); } diff --git a/src/core/qgsvectoroverlay.h b/src/core/qgsvectoroverlay.h index ee323975bc3e..7b4b5ca297ca 100644 --- a/src/core/qgsvectoroverlay.h +++ b/src/core/qgsvectoroverlay.h @@ -1,10 +1,10 @@ - /*************************************************************************** - qgsvectoroverlay.h - description - ------------------ - begin : January 2007 - copyright : (C) 2007 by Marco Hugentobler - email : marco dot hugentobler at karto dot baug dot ethz dot ch - ***************************************************************************/ +/*************************************************************************** + qgsvectoroverlay.h - description + ------------------ + begin : January 2007 + copyright : (C) 2007 by Marco Hugentobler + email : marco dot hugentobler at karto dot baug dot ethz dot ch +***************************************************************************/ /*************************************************************************** * * @@ -28,60 +28,60 @@ class QgsRenderContext; /**Base class for vector layer overlays (e.g. Diagrams, labels, etc.). For each object, the position of the bounding box is stored in a QgsOberlayObject. The vector overlays are drawn on top of all layers*/ class CORE_EXPORT QgsVectorOverlay { - public: - QgsVectorOverlay(QgsVectorLayer* vl); - virtual ~QgsVectorOverlay(); + public: + QgsVectorOverlay( QgsVectorLayer* vl ); + virtual ~QgsVectorOverlay(); - /**Create the overlay objects contained in a view extent. Subclasses need to implement this method and assign width/height information to the overlay ovbjects*/ + /**Create the overlay objects contained in a view extent. Subclasses need to implement this method and assign width/height information to the overlay ovbjects*/ - virtual void createOverlayObjects(const QgsRenderContext& renderContext) = 0; + virtual void createOverlayObjects( const QgsRenderContext& renderContext ) = 0; - /**Remove the overlay objects and release their memory*/ - void removeOverlayObjects(); + /**Remove the overlay objects and release their memory*/ + void removeOverlayObjects(); - /**Draw the overlay objects*/ - virtual void drawOverlayObjects(QgsRenderContext& context) const = 0; + /**Draw the overlay objects*/ + virtual void drawOverlayObjects( QgsRenderContext& context ) const = 0; - /**Gives direct access to oberlay objects*/ - QMap* overlayObjects(){return &mOverlayObjects;} + /**Gives direct access to oberlay objects*/ + QMap* overlayObjects() {return &mOverlayObjects;} - /**Describes the overlay type (e.g. "diagram" or "label")*/ - virtual QString typeName() const = 0; + /**Describes the overlay type (e.g. "diagram" or "label")*/ + virtual QString typeName() const = 0; - /**Set attribute indices necessary to fetch*/ - void setAttributes(const QgsAttributeList& list){mAttributes = list;} + /**Set attribute indices necessary to fetch*/ + void setAttributes( const QgsAttributeList& list ) {mAttributes = list;} - bool displayFlag() const {return mDisplayFlag;} + bool displayFlag() const {return mDisplayFlag;} - /**Display yes/no*/ - void setDisplayFlag(bool flag){mDisplayFlag = flag;} + /**Display yes/no*/ + void setDisplayFlag( bool flag ) {mDisplayFlag = flag;} - /**Restore from project file*/ - virtual bool readXML(const QDomNode& overlayNode) = 0; + /**Restore from project file*/ + virtual bool readXML( const QDomNode& overlayNode ) = 0; - /**Save to project file*/ - virtual bool writeXML(QDomNode& layer_node, QDomDocument& doc) const = 0; + /**Save to project file*/ + virtual bool writeXML( QDomNode& layer_node, QDomDocument& doc ) const = 0; - protected: - /**Pointer to the vector layer for this overlay*/ - QgsVectorLayer* mVectorLayer; + protected: + /**Pointer to the vector layer for this overlay*/ + QgsVectorLayer* mVectorLayer; - /**True if overlay should be displayed*/ - bool mDisplayFlag; + /**True if overlay should be displayed*/ + bool mDisplayFlag; - /**A list with attribute indexes that are needed for overlay rendering*/ - QgsAttributeList mAttributes; + /**A list with attribute indexes that are needed for overlay rendering*/ + QgsAttributeList mAttributes; - /**Key: feature ids, value: the corresponding overlay objects. Normally, they are created for each redraw and deleted before the next redraw*/ - QMap mOverlayObjects; + /**Key: feature ids, value: the corresponding overlay objects. Normally, they are created for each redraw and deleted before the next redraw*/ + QMap mOverlayObjects; - /**Position constraints that may be set to be persistent after redraws. Key is the feature id, value the map point - where the feature should be placed*/ - QMap mPositionConstraints; + /**Position constraints that may be set to be persistent after redraws. Key is the feature id, value the map point + where the feature should be placed*/ + QMap mPositionConstraints; - private: - /**Default constructor forbidden*/ - QgsVectorOverlay(); + private: + /**Default constructor forbidden*/ + QgsVectorOverlay(); }; #endif diff --git a/src/gui/qgsmapcanvassnapper.cpp b/src/gui/qgsmapcanvassnapper.cpp index f114ceae9b78..8c7e493f3de8 100644 --- a/src/gui/qgsmapcanvassnapper.cpp +++ b/src/gui/qgsmapcanvassnapper.cpp @@ -101,7 +101,7 @@ int QgsMapCanvasSnapper::snapToCurrentLayer( const QPoint& p, QListmapUnitsPerPixel()); + snapLayer.mTolerance = QgsTolerance::vertexSearchRadius( mMapCanvas->mapUnitsPerPixel() ); } else { @@ -196,7 +196,7 @@ int QgsMapCanvasSnapper::snapToBackgroundLayers( const QPoint& p, QListtoDouble(); - snapLayer.mUnitType = (QgsTolerance::UnitType) tolUnitIt->toInt(); + snapLayer.mUnitType = ( QgsTolerance::UnitType ) tolUnitIt->toInt(); //segment or vertex if (( *snapIt ) == "to_vertex" ) @@ -248,7 +248,7 @@ int QgsMapCanvasSnapper::snapToBackgroundLayers( const QPoint& p, QListmapUnitsPerPixel()); + snapLayer.mTolerance = QgsTolerance::defaultTolerance( mMapCanvas->mapUnitsPerPixel() ); snapLayer.mUnitType = QgsTolerance::MapUnits; snapLayers.append( snapLayer ); diff --git a/src/plugins/diagram_overlay/qgsbardiagramfactory.cpp b/src/plugins/diagram_overlay/qgsbardiagramfactory.cpp index 9b474e90c75b..a92602863c9a 100644 --- a/src/plugins/diagram_overlay/qgsbardiagramfactory.cpp +++ b/src/plugins/diagram_overlay/qgsbardiagramfactory.cpp @@ -20,7 +20,7 @@ #include #include -QgsBarDiagramFactory::QgsBarDiagramFactory(): QgsWKNDiagramFactory(), mBarWidth(5) +QgsBarDiagramFactory::QgsBarDiagramFactory(): QgsWKNDiagramFactory(), mBarWidth( 5 ) { } @@ -30,31 +30,31 @@ QgsBarDiagramFactory::~QgsBarDiagramFactory() } -QImage* QgsBarDiagramFactory::createDiagram(int size, const QgsFeature& f, const QgsRenderContext& renderContext) const +QImage* QgsBarDiagramFactory::createDiagram( int size, const QgsFeature& f, const QgsRenderContext& renderContext ) const { QgsAttributeMap dataValues = f.attributeMap(); - double sizeScaleFactor = diagramSizeScaleFactor(renderContext); + double sizeScaleFactor = diagramSizeScaleFactor( renderContext ); //for barcharts, the specified height is valid for the classification attribute //the heights of the other bars are calculated with the same height/value ratio //the bar widths are fixed (20 at the moment) //int diagramWidth = barWidth * mAttributes.size(); - int h = renderContext.rasterScaleFactor() * (getMaximumHeight(size, dataValues) * sizeScaleFactor + 2 * mMaximumPenWidth); - int w = renderContext.rasterScaleFactor() * (mBarWidth * sizeScaleFactor * mCategories.size() + 2 * mMaximumPenWidth); + int h = renderContext.rasterScaleFactor() * ( getMaximumHeight( size, dataValues ) * sizeScaleFactor + 2 * mMaximumPenWidth ); + int w = renderContext.rasterScaleFactor() * ( mBarWidth * sizeScaleFactor * mCategories.size() + 2 * mMaximumPenWidth ); //consider the gaps todo: take this information from method getDiagramDimensions() QList::const_iterator c_it = mCategories.constBegin(); - for(; c_it != mCategories.constEnd(); ++c_it) - { - w += (2 * c_it->gap() * renderContext.rasterScaleFactor()); - } - - QImage* diagramImage = new QImage(QSize(w, h), QImage::Format_ARGB32_Premultiplied); - diagramImage->fill(0); //transparent background + for ( ; c_it != mCategories.constEnd(); ++c_it ) + { + w += ( 2 * c_it->gap() * renderContext.rasterScaleFactor() ); + } + + QImage* diagramImage = new QImage( QSize( w, h ), QImage::Format_ARGB32_Premultiplied ); + diagramImage->fill( 0 ); //transparent background //calculate value/pixel ratio - double sizeValueRatio = sizeValueRatioBarChart(size, dataValues); + double sizeValueRatio = sizeValueRatioBarChart( size, dataValues ); //draw the bars itself double currentValue; @@ -62,101 +62,101 @@ QImage* QgsBarDiagramFactory::createDiagram(int size, const QgsFeature& f, const QgsAttributeMap::const_iterator att_it; QList::const_iterator category_it = mCategories.constBegin(); - + int currentWidth = mMaximumPenWidth; - - QPainter p(diagramImage); - p.setRenderHint(QPainter::Antialiasing); - for(; category_it != mCategories.constEnd(); ++category_it) + QPainter p( diagramImage ); + p.setRenderHint( QPainter::Antialiasing ); + + for ( ; category_it != mCategories.constEnd(); ++category_it ) + { + att_it = dataValues.find( category_it->propertyIndex() ); + if ( att_it != dataValues.constEnd() ) { - att_it = dataValues.find(category_it->propertyIndex()); - if(att_it != dataValues.constEnd()) - { - currentWidth += category_it->gap(); //first gap - p.setPen(category_it->pen()); - currentValue = att_it->toDouble(); - currentBarHeight = (int)(currentValue * sizeValueRatio * sizeScaleFactor * renderContext.rasterScaleFactor()); - p.setBrush(category_it->brush()); - p.drawRect(QRect(currentWidth, h - currentBarHeight + mMaximumPenWidth, mBarWidth * sizeScaleFactor *renderContext.rasterScaleFactor(), currentBarHeight)); - currentWidth += category_it->gap() * renderContext.rasterScaleFactor(); //second gap - currentWidth += mBarWidth * sizeScaleFactor *renderContext.rasterScaleFactor(); //go for the next bar... - } + currentWidth += category_it->gap(); //first gap + p.setPen( category_it->pen() ); + currentValue = att_it->toDouble(); + currentBarHeight = ( int )( currentValue * sizeValueRatio * sizeScaleFactor * renderContext.rasterScaleFactor() ); + p.setBrush( category_it->brush() ); + p.drawRect( QRect( currentWidth, h - currentBarHeight + mMaximumPenWidth, mBarWidth * sizeScaleFactor *renderContext.rasterScaleFactor(), currentBarHeight ) ); + currentWidth += category_it->gap() * renderContext.rasterScaleFactor(); //second gap + currentWidth += mBarWidth * sizeScaleFactor * renderContext.rasterScaleFactor(); //go for the next bar... } + } return diagramImage; } -int QgsBarDiagramFactory::getDiagramDimensions(int size, const QgsFeature& f, const QgsRenderContext& context, int& width, int& height) const +int QgsBarDiagramFactory::getDiagramDimensions( int size, const QgsFeature& f, const QgsRenderContext& context, int& width, int& height ) const { - double sizeScaleFactor = diagramSizeScaleFactor(context); + double sizeScaleFactor = diagramSizeScaleFactor( context ); - height = context.rasterScaleFactor() * (getMaximumHeight(size, f.attributeMap()) * sizeScaleFactor + 2 * mMaximumPenWidth); - width = context.rasterScaleFactor() * (mBarWidth * sizeScaleFactor * mCategories.size() + 2 * mMaximumPenWidth); + height = context.rasterScaleFactor() * ( getMaximumHeight( size, f.attributeMap() ) * sizeScaleFactor + 2 * mMaximumPenWidth ); + width = context.rasterScaleFactor() * ( mBarWidth * sizeScaleFactor * mCategories.size() + 2 * mMaximumPenWidth ); //consider the gaps QList::const_iterator c_it = mCategories.constBegin(); - for(; c_it != mCategories.constEnd(); ++c_it) - { - width += (2 * c_it->gap()); - } + for ( ; c_it != mCategories.constEnd(); ++c_it ) + { + width += ( 2 * c_it->gap() ); + } return 0; } -int QgsBarDiagramFactory::getMaximumHeight(int size, const QgsAttributeMap& featureAttributes) const +int QgsBarDiagramFactory::getMaximumHeight( int size, const QgsAttributeMap& featureAttributes ) const { //calculate value/pixel ratio - double pixelValueRatio = sizeValueRatioBarChart(size, featureAttributes); - - //find maximum attribute value - double maximumAttValue = -std::numeric_limits::max(); - double currentValue; - - QList::const_iterator category_it = mCategories.constBegin(); - QgsAttributeMap::const_iterator it; - - for(; category_it != mCategories.constEnd(); ++category_it) - { - it = featureAttributes.find(category_it->propertyIndex()); - if(it != featureAttributes.constEnd()) - { - currentValue = it->toDouble(); - if(currentValue > maximumAttValue) - { - maximumAttValue = currentValue; - } - } - } - - //and calculate height of image based on the maximum attribute value - int height = (int)(maximumAttValue * pixelValueRatio); - return height; + double pixelValueRatio = sizeValueRatioBarChart( size, featureAttributes ); + + //find maximum attribute value + double maximumAttValue = -std::numeric_limits::max(); + double currentValue; + + QList::const_iterator category_it = mCategories.constBegin(); + QgsAttributeMap::const_iterator it; + + for ( ; category_it != mCategories.constEnd(); ++category_it ) + { + it = featureAttributes.find( category_it->propertyIndex() ); + if ( it != featureAttributes.constEnd() ) + { + currentValue = it->toDouble(); + if ( currentValue > maximumAttValue ) + { + maximumAttValue = currentValue; + } + } + } + + //and calculate height of image based on the maximum attribute value + int height = ( int )( maximumAttValue * pixelValueRatio ); + return height; } -double QgsBarDiagramFactory::sizeValueRatioBarChart(int size, const QgsAttributeMap& featureAttributes) const +double QgsBarDiagramFactory::sizeValueRatioBarChart( int size, const QgsAttributeMap& featureAttributes ) const { - //find value for scaling attribute +//find value for scaling attribute QgsAttributeList::const_iterator scaling_it = mScalingAttributes.constBegin(); double scalingValue = 0; - for(; scaling_it != mScalingAttributes.constEnd(); ++scaling_it) + for ( ; scaling_it != mScalingAttributes.constEnd(); ++scaling_it ) + { + QgsAttributeMap::const_iterator it = featureAttributes.find( *scaling_it ); + if ( it == featureAttributes.constEnd() ) { - QgsAttributeMap::const_iterator it = featureAttributes.find(*scaling_it); - if(it == featureAttributes.constEnd()) - { - continue; //error, scaling attribute not contained in feature attributes - } - scalingValue += (it->toDouble()); + continue; //error, scaling attribute not contained in feature attributes } - + scalingValue += ( it->toDouble() ); + } + //calculate value/pixel ratio - return (size / scalingValue); + return ( size / scalingValue ); } -bool QgsBarDiagramFactory::_writeXML(QDomNode& factory_node, QDomDocument& doc) const +bool QgsBarDiagramFactory::_writeXML( QDomNode& factory_node, QDomDocument& doc ) const { - QDomElement barWidthElem = doc.createElement("barWidth"); - QDomText barWidthText = doc.createTextNode(QString::number(mBarWidth)); - barWidthElem.appendChild(barWidthText); - factory_node.appendChild(barWidthElem); - return true; + QDomElement barWidthElem = doc.createElement( "barWidth" ); + QDomText barWidthText = doc.createTextNode( QString::number( mBarWidth ) ); + barWidthElem.appendChild( barWidthText ); + factory_node.appendChild( barWidthElem ); + return true; } diff --git a/src/plugins/diagram_overlay/qgsbardiagramfactory.h b/src/plugins/diagram_overlay/qgsbardiagramfactory.h index 654d5be66cd3..5ee2ced6e3d8 100644 --- a/src/plugins/diagram_overlay/qgsbardiagramfactory.h +++ b/src/plugins/diagram_overlay/qgsbardiagramfactory.h @@ -23,45 +23,45 @@ /**A class that creates bar diagrams*/ class QgsBarDiagramFactory: public QgsWKNDiagramFactory { - public: - QgsBarDiagramFactory(); - ~QgsBarDiagramFactory(); + public: + QgsBarDiagramFactory(); + ~QgsBarDiagramFactory(); - /**Creates a diagram for a feature and a given size (that is usually determined by QgsDiagramRenderer. The calling method takes ownership of the generated image*/ - QImage* createDiagram(int size, const QgsFeature& f, const QgsRenderContext& renderContext) const; + /**Creates a diagram for a feature and a given size (that is usually determined by QgsDiagramRenderer. The calling method takes ownership of the generated image*/ + QImage* createDiagram( int size, const QgsFeature& f, const QgsRenderContext& renderContext ) const; - /**Creates items to show in the legend*/ - int createLegendContent(int size, const QgsRenderContext& renderContext, QString value, QMap& items) const{return 1;} //soon + /**Creates items to show in the legend*/ + int createLegendContent( int size, const QgsRenderContext& renderContext, QString value, QMap& items ) const {return 1;} //soon - /**Gets the width and height (in pixels) of the diagram image. Considers different width, height values, the maximum width of the drawing pen and the conversion from mm size to pixels according to render context. - @param size diagram size calculated by diagram renderer (in mm) - @param f reference to the feature associated with the diagram - @param the render context (contains mm scale factor and raster scale factor) - @param width out: the width of the diagram image in pixels - @param height out: the height of the diagram image in pixels*/ - int getDiagramDimensions(int size, const QgsFeature& f, const QgsRenderContext& context, int& width, int& height) const; + /**Gets the width and height (in pixels) of the diagram image. Considers different width, height values, the maximum width of the drawing pen and the conversion from mm size to pixels according to render context. + @param size diagram size calculated by diagram renderer (in mm) + @param f reference to the feature associated with the diagram + @param the render context (contains mm scale factor and raster scale factor) + @param width out: the width of the diagram image in pixels + @param height out: the height of the diagram image in pixels*/ + int getDiagramDimensions( int size, const QgsFeature& f, const QgsRenderContext& context, int& width, int& height ) const; - /**Returns the property described by the size (e.g. diameter or height). This can be important to - know if e.g. size has to be calculated proportional to pie area*/ - QgsDiagramFactory::SizeType sizeType() const {return QgsDiagramFactory::HEIGHT;} + /**Returns the property described by the size (e.g. diameter or height). This can be important to + know if e.g. size has to be calculated proportional to pie area*/ + QgsDiagramFactory::SizeType sizeType() const {return QgsDiagramFactory::HEIGHT;} - /**Writes bar with into the project file*/ - bool _writeXML(QDomNode& factory_node, QDomDocument& doc) const; + /**Writes bar with into the project file*/ + bool _writeXML( QDomNode& factory_node, QDomDocument& doc ) const; - private: + private: - /**width of one bar (default 5 mm)*/ - int mBarWidth; - + /**width of one bar (default 5 mm)*/ + int mBarWidth; - /**Calculates the maximum height of the bar chart (based on size for the - scaling attribute)*/ - int getMaximumHeight(int size, const QgsAttributeMap& featureAttributes) const; - /**Calculates the value to size unit ratio for the bar chart (based on the size \ - of the scaling attribute) - @return the ratio or -1 in case of error*/ - double sizeValueRatioBarChart(int size, const QgsAttributeMap& featureAttributes) const; + /**Calculates the maximum height of the bar chart (based on size for the + scaling attribute)*/ + int getMaximumHeight( int size, const QgsAttributeMap& featureAttributes ) const; + + /**Calculates the value to size unit ratio for the bar chart (based on the size \ + of the scaling attribute) + @return the ratio or -1 in case of error*/ + double sizeValueRatioBarChart( int size, const QgsAttributeMap& featureAttributes ) const; }; #endif diff --git a/src/plugins/diagram_overlay/qgsdiagramcategory.cpp b/src/plugins/diagram_overlay/qgsdiagramcategory.cpp index 4f079161a400..79c829114556 100644 --- a/src/plugins/diagram_overlay/qgsdiagramcategory.cpp +++ b/src/plugins/diagram_overlay/qgsdiagramcategory.cpp @@ -17,13 +17,13 @@ #include "qgsdiagramcategory.h" -QgsDiagramCategory::QgsDiagramCategory(): mPen(Qt::NoPen), mGap(0) +QgsDiagramCategory::QgsDiagramCategory(): mPen( Qt::NoPen ), mGap( 0 ) { - + } QgsDiagramCategory::~QgsDiagramCategory() { - + } diff --git a/src/plugins/diagram_overlay/qgsdiagramcategory.h b/src/plugins/diagram_overlay/qgsdiagramcategory.h index a21f8f6b0787..3d6aac6ad8fc 100644 --- a/src/plugins/diagram_overlay/qgsdiagramcategory.h +++ b/src/plugins/diagram_overlay/qgsdiagramcategory.h @@ -21,36 +21,36 @@ #include #include -/**Describes a diagram category that -can be displayed e.g. as a pie slice +/**Describes a diagram category that +can be displayed e.g. as a pie slice or a bar pillar*/ class QgsDiagramCategory { - public: - QgsDiagramCategory(); - ~QgsDiagramCategory(); - - //getters - const QBrush& brush() const {return mBrush;} - const QPen& pen() const {return mPen;} - int propertyIndex() const {return mPropertyIndex;} - int gap() const {return mGap;} - - //setters - void setBrush(const QBrush& b) {mBrush = b;} - void setPen(const QPen& p) {mPen = p;} - void setPropertyIndex(int index){mPropertyIndex = index;} - void setGap(int g){mGap = g;} - - private: - /**Outline to draw the category*/ - QPen mPen; - /**Fill to draw the category*/ - QBrush mBrush; - /**Index of the attribute represented by the category*/ - int mPropertyIndex; - /**Gap to highlight the category (e.g. explode in pie)*/ - int mGap; + public: + QgsDiagramCategory(); + ~QgsDiagramCategory(); + + //getters + const QBrush& brush() const {return mBrush;} + const QPen& pen() const {return mPen;} + int propertyIndex() const {return mPropertyIndex;} + int gap() const {return mGap;} + + //setters + void setBrush( const QBrush& b ) {mBrush = b;} + void setPen( const QPen& p ) {mPen = p;} + void setPropertyIndex( int index ) {mPropertyIndex = index;} + void setGap( int g ) {mGap = g;} + + private: + /**Outline to draw the category*/ + QPen mPen; + /**Fill to draw the category*/ + QBrush mBrush; + /**Index of the attribute represented by the category*/ + int mPropertyIndex; + /**Gap to highlight the category (e.g. explode in pie)*/ + int mGap; }; #endif diff --git a/src/plugins/diagram_overlay/qgsdiagramdialog.cpp b/src/plugins/diagram_overlay/qgsdiagramdialog.cpp index 9eca76b6ac7c..10efa8f153b8 100644 --- a/src/plugins/diagram_overlay/qgsdiagramdialog.cpp +++ b/src/plugins/diagram_overlay/qgsdiagramdialog.cpp @@ -28,320 +28,320 @@ #include -QgsDiagramDialog::QgsDiagramDialog(QgsVectorLayer* vl): mVectorLayer(vl) +QgsDiagramDialog::QgsDiagramDialog( QgsVectorLayer* vl ): mVectorLayer( vl ) { - setupUi(this); + setupUi( this ); - mDiagramTypeComboBox->insertItem(0, tr("Pie chart")); - mDiagramTypeComboBox->insertItem(1, tr("Bar chart")); - mDiagramTypeComboBox->insertItem(2, tr("Proportional SVG symbols")); + mDiagramTypeComboBox->insertItem( 0, tr( "Pie chart" ) ); + mDiagramTypeComboBox->insertItem( 1, tr( "Bar chart" ) ); + mDiagramTypeComboBox->insertItem( 2, tr( "Proportional SVG symbols" ) ); - if(!mVectorLayer) - { - return; - } + if ( !mVectorLayer ) + { + return; + } //insert attributes into combo box QgsVectorDataProvider *provider; - if ((provider = dynamic_cast(mVectorLayer->dataProvider()))) + if (( provider = dynamic_cast( mVectorLayer->dataProvider() ) ) ) + { + const QgsFieldMap & fields = provider->fields(); + QString str; + + int comboIndex = 0; + for ( QgsFieldMap::const_iterator it = fields.begin(); it != fields.end(); ++it ) { - const QgsFieldMap & fields = provider->fields(); - QString str; - - int comboIndex = 0; - for (QgsFieldMap::const_iterator it = fields.begin(); it != fields.end(); ++it) - { - str = (*it).name(); - mClassificationComboBox->insertItem(comboIndex, str); - ++comboIndex; - } - } + str = ( *it ).name(); + mClassificationComboBox->insertItem( comboIndex, str ); + ++comboIndex; + } + } - mClassificationTypeComboBox->insertItem(0, "linearly scaling"); + mClassificationTypeComboBox->insertItem( 0, "linearly scaling" ); //if mVectorLayer already has a diagram overlay, apply its settings to this dialog - const QgsVectorOverlay* previousOverlay = mVectorLayer->findOverlayByType("diagram"); - if(previousOverlay) - { - restoreSettings(previousOverlay); - } - setGuiElementsEnabled(mDisplayDiagramsCheckBox->checkState() == Qt::Checked); + const QgsVectorOverlay* previousOverlay = mVectorLayer->findOverlayByType( "diagram" ); + if ( previousOverlay ) + { + restoreSettings( previousOverlay ); + } + setGuiElementsEnabled( mDisplayDiagramsCheckBox->checkState() == Qt::Checked ); } -QgsDiagramDialog::QgsDiagramDialog(): mVectorLayer(0) +QgsDiagramDialog::QgsDiagramDialog(): mVectorLayer( 0 ) { } - + QgsDiagramDialog::~QgsDiagramDialog() { } -void QgsDiagramDialog::on_mClassificationTypeComboBox_currentIndexChanged(const QString& newType) +void QgsDiagramDialog::on_mClassificationTypeComboBox_currentIndexChanged( const QString& newType ) { - if(newType == "linearly scaling") + if ( newType == "linearly scaling" ) + { + QWidget* currentWidget = mWidgetStackRenderers->currentWidget(); + if ( currentWidget ) { - QWidget* currentWidget = mWidgetStackRenderers->currentWidget(); - if(currentWidget) - { - mWidgetStackRenderers->removeWidget(currentWidget); - } - QWidget* newWidget = new QgsLinearlyScalingDialog(mVectorLayer); - mWidgetStackRenderers->addWidget(newWidget); - mWidgetStackRenderers->setCurrentWidget(newWidget); - on_mClassificationComboBox_currentIndexChanged(mClassificationComboBox->currentText()); + mWidgetStackRenderers->removeWidget( currentWidget ); } + QWidget* newWidget = new QgsLinearlyScalingDialog( mVectorLayer ); + mWidgetStackRenderers->addWidget( newWidget ); + mWidgetStackRenderers->setCurrentWidget( newWidget ); + on_mClassificationComboBox_currentIndexChanged( mClassificationComboBox->currentText() ); + } } -void QgsDiagramDialog::on_mClassificationComboBox_currentIndexChanged(const QString& newAttribute) +void QgsDiagramDialog::on_mClassificationComboBox_currentIndexChanged( const QString& newAttribute ) { - int attributeIndex = QgsDiagramOverlay::indexFromAttributeName(newAttribute, mVectorLayer); - if(attributeIndex == -1) - { - return; - } - QgsDiagramRendererWidget* rendererWidget = dynamic_cast(mWidgetStackRenderers->currentWidget()); - if(!rendererWidget) - { - return; - } - rendererWidget->changeClassificationField(attributeIndex); + int attributeIndex = QgsDiagramOverlay::indexFromAttributeName( newAttribute, mVectorLayer ); + if ( attributeIndex == -1 ) + { + return; + } + QgsDiagramRendererWidget* rendererWidget = dynamic_cast( mWidgetStackRenderers->currentWidget() ); + if ( !rendererWidget ) + { + return; + } + rendererWidget->changeClassificationField( attributeIndex ); } -void QgsDiagramDialog::on_mDiagramTypeComboBox_currentIndexChanged(const QString& text) +void QgsDiagramDialog::on_mDiagramTypeComboBox_currentIndexChanged( const QString& text ) { - //remove old widget - QWidget* currentWidget = mDiagramFactoryStackedWidget->currentWidget(); - mDiagramFactoryStackedWidget->removeWidget(currentWidget); - delete currentWidget; - - //and create a new one - QgsDiagramFactoryWidget* newWidget = 0; - if(text == tr("Pie chart")) - { - newWidget = new QgsWKNDiagramFactoryWidget(mVectorLayer, "Pie"); - } - else if(text == tr("Bar chart")) - { - newWidget = new QgsWKNDiagramFactoryWidget(mVectorLayer, "Bar"); - } - else if(text == (tr("Proportional SVG symbols"))) - { - newWidget = new QgsSVGDiagramFactoryWidget(); - } + //remove old widget + QWidget* currentWidget = mDiagramFactoryStackedWidget->currentWidget(); + mDiagramFactoryStackedWidget->removeWidget( currentWidget ); + delete currentWidget; + + //and create a new one + QgsDiagramFactoryWidget* newWidget = 0; + if ( text == tr( "Pie chart" ) ) + { + newWidget = new QgsWKNDiagramFactoryWidget( mVectorLayer, "Pie" ); + } + else if ( text == tr( "Bar chart" ) ) + { + newWidget = new QgsWKNDiagramFactoryWidget( mVectorLayer, "Bar" ); + } + else if ( text == ( tr( "Proportional SVG symbols" ) ) ) + { + newWidget = new QgsSVGDiagramFactoryWidget(); + } - if(newWidget) - { - mDiagramFactoryStackedWidget->addWidget(newWidget); - mDiagramFactoryStackedWidget->setCurrentWidget(newWidget); - newWidget->show(); - } + if ( newWidget ) + { + mDiagramFactoryStackedWidget->addWidget( newWidget ); + mDiagramFactoryStackedWidget->setCurrentWidget( newWidget ); + newWidget->show(); + } } -void QgsDiagramDialog::on_mDisplayDiagramsCheckBox_stateChanged(int state) +void QgsDiagramDialog::on_mDisplayDiagramsCheckBox_stateChanged( int state ) { //activate / deactivate all gui items depending on the checkbox state - if(state == Qt::Checked) + if ( state == Qt::Checked ) { - setGuiElementsEnabled(true); + setGuiElementsEnabled( true ); } else { - setGuiElementsEnabled(false); + setGuiElementsEnabled( false ); } } void QgsDiagramDialog::apply() const { - if(!mVectorLayer) - { - return; - } + if ( !mVectorLayer ) + { + return; + } - //create diagram factory - QgsDiagramFactory* diagramFactory = 0; - QWidget* factoryWidget = mDiagramFactoryStackedWidget->currentWidget(); + //create diagram factory + QgsDiagramFactory* diagramFactory = 0; + QWidget* factoryWidget = mDiagramFactoryStackedWidget->currentWidget(); - if(factoryWidget) + if ( factoryWidget ) + { + QgsDiagramFactoryWidget* diagramFactoryWidget = dynamic_cast( factoryWidget ); + if ( factoryWidget ) { - QgsDiagramFactoryWidget* diagramFactoryWidget = dynamic_cast(factoryWidget); - if(factoryWidget) - { - diagramFactory = diagramFactoryWidget->createFactory(); - } + diagramFactory = diagramFactoryWidget->createFactory(); } + } - if(!diagramFactory) - { - return; - } + if ( !diagramFactory ) + { + return; + } - //and diagram renderer + //and diagram renderer - //classAttr comes from the gui - int classAttr = QgsDiagramOverlay::indexFromAttributeName(mClassificationComboBox->currentText(), mVectorLayer); - if(classAttr == -1) - { - return; - } + //classAttr comes from the gui + int classAttr = QgsDiagramOverlay::indexFromAttributeName( mClassificationComboBox->currentText(), mVectorLayer ); + if ( classAttr == -1 ) + { + return; + } - //attList contains the category attributes - QgsAttributeList attList; - QgsWKNDiagramFactory* wknDiagramFactory = dynamic_cast(diagramFactory); - if(wknDiagramFactory) - { - attList += wknDiagramFactory->categoryAttributes(); - } + //attList contains the category attributes + QgsAttributeList attList; + QgsWKNDiagramFactory* wknDiagramFactory = dynamic_cast( diagramFactory ); + if ( wknDiagramFactory ) + { + attList += wknDiagramFactory->categoryAttributes(); + } - QgsDiagramRenderer* diagramRenderer = 0; - QgsDiagramFactory::SizeUnit diagramSizeUnit = QgsDiagramFactory::MM; //mm on output medium is default + QgsDiagramRenderer* diagramRenderer = 0; + QgsDiagramFactory::SizeUnit diagramSizeUnit = QgsDiagramFactory::MM; //mm on output medium is default - QWidget* rendererWidget = mWidgetStackRenderers->currentWidget(); - if(rendererWidget) + QWidget* rendererWidget = mWidgetStackRenderers->currentWidget(); + if ( rendererWidget ) + { + QgsDiagramRendererWidget* diagramRendererWidget = dynamic_cast( rendererWidget ); + if ( diagramRendererWidget ) { - QgsDiagramRendererWidget* diagramRendererWidget = dynamic_cast(rendererWidget); - if(diagramRendererWidget) - { - diagramRenderer = diagramRendererWidget->createRenderer(classAttr, attList); - diagramSizeUnit = diagramRendererWidget->sizeUnit(); - } + diagramRenderer = diagramRendererWidget->createRenderer( classAttr, attList ); + diagramSizeUnit = diagramRendererWidget->sizeUnit(); } + } - if(!diagramRenderer) - { - return; - } + if ( !diagramRenderer ) + { + return; + } - diagramRenderer->setFactory(diagramFactory); - QgsAttributeList scalingAttributeList; - scalingAttributeList.push_back(classAttr); - diagramFactory->setScalingAttributes(scalingAttributeList); - //also set units to the diagram factory - diagramFactory->setSizeUnit(diagramSizeUnit); + diagramRenderer->setFactory( diagramFactory ); + QgsAttributeList scalingAttributeList; + scalingAttributeList.push_back( classAttr ); + diagramFactory->setScalingAttributes( scalingAttributeList ); + //also set units to the diagram factory + diagramFactory->setSizeUnit( diagramSizeUnit ); - //the overlay needs to fetch scaling attributes and category attributes - if(!attList.contains(classAttr)) - { - attList.push_back(classAttr); - } - QgsDiagramOverlay* diagramOverlay = new QgsDiagramOverlay(mVectorLayer); - diagramOverlay->setDiagramRenderer(diagramRenderer); - diagramOverlay->setAttributes(attList); + //the overlay needs to fetch scaling attributes and category attributes + if ( !attList.contains( classAttr ) ) + { + attList.push_back( classAttr ); + } + QgsDiagramOverlay* diagramOverlay = new QgsDiagramOverlay( mVectorLayer ); + diagramOverlay->setDiagramRenderer( diagramRenderer ); + diagramOverlay->setAttributes( attList ); - //display flag - if(mDisplayDiagramsCheckBox->checkState() == Qt::Checked) - { - diagramOverlay->setDisplayFlag(true); - } - if(mDisplayDiagramsCheckBox->checkState() == Qt::Unchecked) - { - diagramOverlay->setDisplayFlag(false); - } + //display flag + if ( mDisplayDiagramsCheckBox->checkState() == Qt::Checked ) + { + diagramOverlay->setDisplayFlag( true ); + } + if ( mDisplayDiagramsCheckBox->checkState() == Qt::Unchecked ) + { + diagramOverlay->setDisplayFlag( false ); + } - //remove already existing diagram overlays - mVectorLayer-> removeOverlay("diagram"); + //remove already existing diagram overlays + mVectorLayer-> removeOverlay( "diagram" ); //finally add the new overlay to the vector layer - mVectorLayer->addOverlay(diagramOverlay); + mVectorLayer->addOverlay( diagramOverlay ); } -void QgsDiagramDialog::restoreSettings(const QgsVectorOverlay* overlay) +void QgsDiagramDialog::restoreSettings( const QgsVectorOverlay* overlay ) { - const QgsDiagramOverlay* previousDiagramOverlay = dynamic_cast(overlay); - if(overlay) + const QgsDiagramOverlay* previousDiagramOverlay = dynamic_cast( overlay ); + if ( overlay ) + { + //set check state according to QgsDiagramOverlay + if ( previousDiagramOverlay->displayFlag() ) + { + mDisplayDiagramsCheckBox->setCheckState( Qt::Checked ); + } + else + { + mDisplayDiagramsCheckBox->setCheckState( Qt::Unchecked ); + } + const QgsDiagramRenderer* previousDiagramRenderer = dynamic_cast( previousDiagramOverlay->diagramRenderer() ); + + if ( previousDiagramRenderer && previousDiagramRenderer->factory() ) { - //set check state according to QgsDiagramOverlay - if(previousDiagramOverlay->displayFlag()) - { - mDisplayDiagramsCheckBox->setCheckState(Qt::Checked); - } - else - { - mDisplayDiagramsCheckBox->setCheckState(Qt::Unchecked); - } - const QgsDiagramRenderer* previousDiagramRenderer = dynamic_cast(previousDiagramOverlay->diagramRenderer()); - - if(previousDiagramRenderer && previousDiagramRenderer->factory()) + QgsDiagramFactory* theFactory = previousDiagramRenderer->factory(); + QgsDiagramFactoryWidget* newWidget = 0; + + + QgsWKNDiagramFactory* theWKNFactory = dynamic_cast( theFactory ); + if ( theWKNFactory ) + { + QString wknType = theWKNFactory->diagramType(); + if ( wknType == ( "Pie" ) ) { - QgsDiagramFactory* theFactory = previousDiagramRenderer->factory(); - QgsDiagramFactoryWidget* newWidget = 0; - - - QgsWKNDiagramFactory* theWKNFactory = dynamic_cast(theFactory); - if(theWKNFactory) - { - QString wknType = theWKNFactory->diagramType(); - if(wknType == ("Pie")) - { - newWidget = new QgsWKNDiagramFactoryWidget(mVectorLayer, "Pie"); - mDiagramTypeComboBox->setCurrentIndex(mDiagramTypeComboBox->findText(tr("Pie chart"))); - } - else - { - newWidget = new QgsWKNDiagramFactoryWidget(mVectorLayer, "Bar"); - mDiagramTypeComboBox->setCurrentIndex(mDiagramTypeComboBox->findText(tr("Bar chart"))); - } - newWidget->setExistingFactory(theWKNFactory); - } - - QgsSVGDiagramFactory* theSVGFactory = dynamic_cast(theFactory); - if(theSVGFactory) - { - mDiagramTypeComboBox->setCurrentIndex(mDiagramTypeComboBox->findText(tr("Proportional SVG symbols"))); - newWidget = new QgsSVGDiagramFactoryWidget(); - } - - newWidget->setExistingFactory(theFactory); - //remove old widget - QWidget* currentWidget = mDiagramFactoryStackedWidget->currentWidget(); - mDiagramFactoryStackedWidget->removeWidget(currentWidget); - delete currentWidget; - - if(newWidget) + newWidget = new QgsWKNDiagramFactoryWidget( mVectorLayer, "Pie" ); + mDiagramTypeComboBox->setCurrentIndex( mDiagramTypeComboBox->findText( tr( "Pie chart" ) ) ); + } + else { - mDiagramFactoryStackedWidget->addWidget(newWidget); - mDiagramFactoryStackedWidget->setCurrentWidget(newWidget); - newWidget->show(); + newWidget = new QgsWKNDiagramFactoryWidget( mVectorLayer, "Bar" ); + mDiagramTypeComboBox->setCurrentIndex( mDiagramTypeComboBox->findText( tr( "Bar chart" ) ) ); } + newWidget->setExistingFactory( theWKNFactory ); + } - - //classification attribute - QString classFieldName; - QgsAttributeList attList = previousDiagramRenderer->classificationAttributes(); - if(attList.size() > 0) - { - classFieldName = QgsDiagramOverlay::attributeNameFromIndex(attList.first(), mVectorLayer); - mClassificationComboBox->setCurrentIndex(mClassificationComboBox->findText(classFieldName)); - - //classification type (specific for renderer subclass) - mClassificationTypeComboBox->setCurrentIndex(mClassificationTypeComboBox->findText("linearly scaling")); - } - - //apply the renderer settings to the renderer specific dialog - if(mWidgetStackRenderers->count() > 0) - { - QgsDiagramRendererWidget* rendererWidget = dynamic_cast(mWidgetStackRenderers->currentWidget()); - if(rendererWidget) - { - rendererWidget->applySettings(previousDiagramRenderer); - } - } - } + QgsSVGDiagramFactory* theSVGFactory = dynamic_cast( theFactory ); + if ( theSVGFactory ) + { + mDiagramTypeComboBox->setCurrentIndex( mDiagramTypeComboBox->findText( tr( "Proportional SVG symbols" ) ) ); + newWidget = new QgsSVGDiagramFactoryWidget(); + } + + newWidget->setExistingFactory( theFactory ); + //remove old widget + QWidget* currentWidget = mDiagramFactoryStackedWidget->currentWidget(); + mDiagramFactoryStackedWidget->removeWidget( currentWidget ); + delete currentWidget; + + if ( newWidget ) + { + mDiagramFactoryStackedWidget->addWidget( newWidget ); + mDiagramFactoryStackedWidget->setCurrentWidget( newWidget ); + newWidget->show(); + } + + + //classification attribute + QString classFieldName; + QgsAttributeList attList = previousDiagramRenderer->classificationAttributes(); + if ( attList.size() > 0 ) + { + classFieldName = QgsDiagramOverlay::attributeNameFromIndex( attList.first(), mVectorLayer ); + mClassificationComboBox->setCurrentIndex( mClassificationComboBox->findText( classFieldName ) ); + + //classification type (specific for renderer subclass) + mClassificationTypeComboBox->setCurrentIndex( mClassificationTypeComboBox->findText( "linearly scaling" ) ); + } + + //apply the renderer settings to the renderer specific dialog + if ( mWidgetStackRenderers->count() > 0 ) + { + QgsDiagramRendererWidget* rendererWidget = dynamic_cast( mWidgetStackRenderers->currentWidget() ); + if ( rendererWidget ) + { + rendererWidget->applySettings( previousDiagramRenderer ); + } + } + } } } -void QgsDiagramDialog::setGuiElementsEnabled(bool enabled) +void QgsDiagramDialog::setGuiElementsEnabled( bool enabled ) { - mDiagramTypeComboBox->setEnabled(enabled); - mTypeLabel->setEnabled(enabled); - mDiagramFactoryStackedWidget->setEnabled(enabled); - mClassificationTypeLabel->setEnabled(enabled); - mClassificationTypeComboBox->setEnabled(enabled); - mClassificationLabel->setEnabled(enabled); - mClassificationComboBox->setEnabled(enabled); - mWidgetStackRenderers->setEnabled(enabled); + mDiagramTypeComboBox->setEnabled( enabled ); + mTypeLabel->setEnabled( enabled ); + mDiagramFactoryStackedWidget->setEnabled( enabled ); + mClassificationTypeLabel->setEnabled( enabled ); + mClassificationTypeComboBox->setEnabled( enabled ); + mClassificationLabel->setEnabled( enabled ); + mClassificationComboBox->setEnabled( enabled ); + mWidgetStackRenderers->setEnabled( enabled ); } diff --git a/src/plugins/diagram_overlay/qgsdiagramdialog.h b/src/plugins/diagram_overlay/qgsdiagramdialog.h index fe4372df677d..9bb95d90a265 100644 --- a/src/plugins/diagram_overlay/qgsdiagramdialog.h +++ b/src/plugins/diagram_overlay/qgsdiagramdialog.h @@ -27,27 +27,27 @@ class QgsVectorOverlay; /**Dialog to enter options for diagram symbolisation*/ class QgsDiagramDialog: public QgsApplyDialog, private Ui::QgsDiagramDialogBase { - Q_OBJECT - public: - QgsDiagramDialog(QgsVectorLayer* vl); - ~QgsDiagramDialog(); - void apply() const; + Q_OBJECT + public: + QgsDiagramDialog( QgsVectorLayer* vl ); + ~QgsDiagramDialog(); + void apply() const; private slots: - void on_mClassificationTypeComboBox_currentIndexChanged(const QString& newType); - void on_mClassificationComboBox_currentIndexChanged(const QString& newAttribute); - void on_mDiagramTypeComboBox_currentIndexChanged(const QString& text); - void on_mDisplayDiagramsCheckBox_stateChanged(int state); - - - private: - QgsDiagramDialog(); - /**Restores the dialog settings from an already existing overlay*/ - void restoreSettings(const QgsVectorOverlay* overlay); - /**Vector layer containing the features to be symbolized with diagrams*/ - QgsVectorLayer* mVectorLayer; - /**Activate / deactivate all the input elements of this dialog*/ - void setGuiElementsEnabled(bool enabled); + void on_mClassificationTypeComboBox_currentIndexChanged( const QString& newType ); + void on_mClassificationComboBox_currentIndexChanged( const QString& newAttribute ); + void on_mDiagramTypeComboBox_currentIndexChanged( const QString& text ); + void on_mDisplayDiagramsCheckBox_stateChanged( int state ); + + + private: + QgsDiagramDialog(); + /**Restores the dialog settings from an already existing overlay*/ + void restoreSettings( const QgsVectorOverlay* overlay ); + /**Vector layer containing the features to be symbolized with diagrams*/ + QgsVectorLayer* mVectorLayer; + /**Activate / deactivate all the input elements of this dialog*/ + void setGuiElementsEnabled( bool enabled ); }; #endif diff --git a/src/plugins/diagram_overlay/qgsdiagramfactory.cpp b/src/plugins/diagram_overlay/qgsdiagramfactory.cpp index d607008753c3..fce522c74f66 100644 --- a/src/plugins/diagram_overlay/qgsdiagramfactory.cpp +++ b/src/plugins/diagram_overlay/qgsdiagramfactory.cpp @@ -18,68 +18,68 @@ #include "qgsdiagramfactory.h" #include "qgsrendercontext.h" -QgsDiagramFactory::QgsDiagramFactory(): mSizeUnit(MM) - { +QgsDiagramFactory::QgsDiagramFactory(): mSizeUnit( MM ) +{ - } +} - QgsDiagramFactory::~QgsDiagramFactory() - { +QgsDiagramFactory::~QgsDiagramFactory() +{ - } +} - QgsDiagramFactory::SizeType QgsDiagramFactory::sizeType() const - { - return QgsDiagramFactory::HEIGHT; - } +QgsDiagramFactory::SizeType QgsDiagramFactory::sizeType() const +{ + return QgsDiagramFactory::HEIGHT; +} - double QgsDiagramFactory::diagramSizeScaleFactor(const QgsRenderContext& context) const - { - if(mSizeUnit == MM) - { - return context.scaleFactor(); - } - else if(mSizeUnit == MapUnits) - { - return 1 / context.mapToPixel().mapUnitsPerPixel(); //pixel based devices - } +double QgsDiagramFactory::diagramSizeScaleFactor( const QgsRenderContext& context ) const +{ + if ( mSizeUnit == MM ) + { + return context.scaleFactor(); + } + else if ( mSizeUnit == MapUnits ) + { + return 1 / context.mapToPixel().mapUnitsPerPixel(); //pixel based devices + } - return 1.0; - } + return 1.0; +} -bool QgsDiagramFactory::writeSizeUnits(QDomElement& factoryElem, QDomDocument& doc) const +bool QgsDiagramFactory::writeSizeUnits( QDomElement& factoryElem, QDomDocument& doc ) const { - if(factoryElem.isNull()) - { - return false; - } + if ( factoryElem.isNull() ) + { + return false; + } - if(mSizeUnit == MM) - { - factoryElem.setAttribute("sizeUnits", "MM"); - } - else if(mSizeUnit == MapUnits) - { - factoryElem.setAttribute("sizeUnits", "MapUnits"); - } - return true; + if ( mSizeUnit == MM ) + { + factoryElem.setAttribute( "sizeUnits", "MM" ); + } + else if ( mSizeUnit == MapUnits ) + { + factoryElem.setAttribute( "sizeUnits", "MapUnits" ); + } + return true; } -bool QgsDiagramFactory::readSizeUnits(const QDomElement& factoryElem) +bool QgsDiagramFactory::readSizeUnits( const QDomElement& factoryElem ) { - if(factoryElem.isNull()) - { - return false; - } + if ( factoryElem.isNull() ) + { + return false; + } - QString unitString = factoryElem.attribute("sizeUnits"); - if(unitString == "MapUnits") - { - mSizeUnit = MapUnits; - } - else - { - mSizeUnit = MM; - } - return true; + QString unitString = factoryElem.attribute( "sizeUnits" ); + if ( unitString == "MapUnits" ) + { + mSizeUnit = MapUnits; + } + else + { + mSizeUnit = MM; + } + return true; } diff --git a/src/plugins/diagram_overlay/qgsdiagramfactory.h b/src/plugins/diagram_overlay/qgsdiagramfactory.h index 8e50353a340c..00f6f26a06d1 100644 --- a/src/plugins/diagram_overlay/qgsdiagramfactory.h +++ b/src/plugins/diagram_overlay/qgsdiagramfactory.h @@ -32,75 +32,75 @@ class QImage; /**Interface for classes that create diagrams*/ class QgsDiagramFactory { - public: - /**Describes if the size describes one dimensional height (e.g. bar chart), \ - a diameter (e.g. piechart) or a squareside. This may be taken into consideration \ - from a renderer for interpolation*/ - enum SizeType + public: + /**Describes if the size describes one dimensional height (e.g. bar chart), \ + a diameter (e.g. piechart) or a squareside. This may be taken into consideration \ + from a renderer for interpolation*/ + enum SizeType { HEIGHT, DIAMETER, SQUARESIDE, }; - enum SizeUnit //size in millimeters on output device or in map units on map - { - MM, - MapUnits - }; - - QgsDiagramFactory(); - virtual ~QgsDiagramFactory(); - - /**Creates the diagram image for a feature in order to be placed on the map - @param size diagram size (may be height, diameter, squaresize depending on diagram type - @param f feature that is symbolized by the diagram - @param renderContext rendering parameters*/ - virtual QImage* createDiagram(int size, const QgsFeature& f, const QgsRenderContext& renderContext) const = 0; - /**Creates the text/images for the legend items. The caller takes ownership of the generated \ - image objects. - @param size diagram size that should be represented in the legend - @param u size may be in MM on output device or in map units on map - @param renderContext rendering parameters - @param value diagram value that should be represented in the legend - @param items generated items - @return 0 in case of success*/ - virtual int createLegendContent(int size, const QgsRenderContext& renderContext, QString value, QMap& items) const = 0; - /**Gets the width and height (in pixels) of the diagram image. Considers different width, height values, the maximum width of the drawing pen and the conversion from mm size to pixels according to render context. - @param size diagram size calculated by diagram renderer - @param f reference to the feature associated with the diagram - @param the render context (contains mm scale factor and raster scale factor) - @param width out: the width of the diagram image in pixels - @param height out: the height of the diagram image in pixels*/ - virtual int getDiagramDimensions(int size, const QgsFeature& f, const QgsRenderContext& context, int& width, int& height) const = 0; - virtual bool writeXML(QDomNode& overlay_node, QDomDocument& doc) const = 0; - - /**Calculates the size multiplicator. Considers the size unit as well as the render context parameters*/ - double diagramSizeScaleFactor(const QgsRenderContext& context) const; - - /**Default is one dimensional scaling*/ - virtual QgsDiagramFactory::SizeType sizeType() const; - - void setSizeUnit(SizeUnit u){mSizeUnit = u;} - SizeUnit sizeUnit() const {return mSizeUnit;} - - //setters and getters for scaling attributes - QgsAttributeList scalingAttributes() const {return mScalingAttributes;} - void setScalingAttributes(const QgsAttributeList& att){mScalingAttributes = att;} - - /**Read settings from project file*/ - virtual bool readXML(const QDomNode& factoryNode) = 0; - - bool writeSizeUnits(QDomElement& factoryElem, QDomDocument& doc) const; - bool readSizeUnits(const QDomElement& factoryElem); - - protected: - /**Size units of diagram items*/ - SizeUnit mSizeUnit; - - /**List of scaling attribute indexes (the values are summed up to - receive the value that is used for diagram size calculation)*/ - QgsAttributeList mScalingAttributes; + enum SizeUnit //size in millimeters on output device or in map units on map + { + MM, + MapUnits + }; + + QgsDiagramFactory(); + virtual ~QgsDiagramFactory(); + + /**Creates the diagram image for a feature in order to be placed on the map + @param size diagram size (may be height, diameter, squaresize depending on diagram type + @param f feature that is symbolized by the diagram + @param renderContext rendering parameters*/ + virtual QImage* createDiagram( int size, const QgsFeature& f, const QgsRenderContext& renderContext ) const = 0; + /**Creates the text/images for the legend items. The caller takes ownership of the generated \ + image objects. + @param size diagram size that should be represented in the legend + @param u size may be in MM on output device or in map units on map + @param renderContext rendering parameters + @param value diagram value that should be represented in the legend + @param items generated items + @return 0 in case of success*/ + virtual int createLegendContent( int size, const QgsRenderContext& renderContext, QString value, QMap& items ) const = 0; + /**Gets the width and height (in pixels) of the diagram image. Considers different width, height values, the maximum width of the drawing pen and the conversion from mm size to pixels according to render context. + @param size diagram size calculated by diagram renderer + @param f reference to the feature associated with the diagram + @param the render context (contains mm scale factor and raster scale factor) + @param width out: the width of the diagram image in pixels + @param height out: the height of the diagram image in pixels*/ + virtual int getDiagramDimensions( int size, const QgsFeature& f, const QgsRenderContext& context, int& width, int& height ) const = 0; + virtual bool writeXML( QDomNode& overlay_node, QDomDocument& doc ) const = 0; + + /**Calculates the size multiplicator. Considers the size unit as well as the render context parameters*/ + double diagramSizeScaleFactor( const QgsRenderContext& context ) const; + + /**Default is one dimensional scaling*/ + virtual QgsDiagramFactory::SizeType sizeType() const; + + void setSizeUnit( SizeUnit u ) {mSizeUnit = u;} + SizeUnit sizeUnit() const {return mSizeUnit;} + + //setters and getters for scaling attributes + QgsAttributeList scalingAttributes() const {return mScalingAttributes;} + void setScalingAttributes( const QgsAttributeList& att ) {mScalingAttributes = att;} + + /**Read settings from project file*/ + virtual bool readXML( const QDomNode& factoryNode ) = 0; + + bool writeSizeUnits( QDomElement& factoryElem, QDomDocument& doc ) const; + bool readSizeUnits( const QDomElement& factoryElem ); + + protected: + /**Size units of diagram items*/ + SizeUnit mSizeUnit; + + /**List of scaling attribute indexes (the values are summed up to + receive the value that is used for diagram size calculation)*/ + QgsAttributeList mScalingAttributes; }; #endif diff --git a/src/plugins/diagram_overlay/qgsdiagramfactorywidget.h b/src/plugins/diagram_overlay/qgsdiagramfactorywidget.h index 1c1bd9542525..35021ba7d9c1 100644 --- a/src/plugins/diagram_overlay/qgsdiagramfactorywidget.h +++ b/src/plugins/diagram_overlay/qgsdiagramfactorywidget.h @@ -25,13 +25,13 @@ class QgsDiagramFactory; /**Abstract factory for dialogs that display options to create a diagram factory*/ class QgsDiagramFactoryWidget: public QWidget { - public: + public: QgsDiagramFactoryWidget(); virtual ~QgsDiagramFactoryWidget(); /**Creates a diagram factory object with the settings specified by the user*/ virtual QgsDiagramFactory* createFactory() = 0; /**Sets the GUI element to the state of an existing diagram factory*/ - virtual void setExistingFactory(const QgsDiagramFactory* f) = 0; + virtual void setExistingFactory( const QgsDiagramFactory* f ) = 0; }; #endif diff --git a/src/plugins/diagram_overlay/qgsdiagramoverlay.cpp b/src/plugins/diagram_overlay/qgsdiagramoverlay.cpp index 4d729305933f..f752743ba77b 100644 --- a/src/plugins/diagram_overlay/qgsdiagramoverlay.cpp +++ b/src/plugins/diagram_overlay/qgsdiagramoverlay.cpp @@ -33,7 +33,7 @@ #include "qgsvectordataprovider.h" #include -QgsDiagramOverlay::QgsDiagramOverlay(QgsVectorLayer* vl): QgsVectorOverlay(vl), mDiagramRenderer(0) +QgsDiagramOverlay::QgsDiagramOverlay( QgsVectorLayer* vl ): QgsVectorOverlay( vl ), mDiagramRenderer( 0 ) { } @@ -43,7 +43,7 @@ QgsDiagramOverlay::~QgsDiagramOverlay() delete mDiagramRenderer; } -void QgsDiagramOverlay::setDiagramRenderer(QgsDiagramRenderer* r) +void QgsDiagramOverlay::setDiagramRenderer( QgsDiagramRenderer* r ) { delete mDiagramRenderer; mDiagramRenderer = r; @@ -54,136 +54,136 @@ const QgsDiagramRenderer* QgsDiagramOverlay::diagramRenderer() const return mDiagramRenderer; } -void QgsDiagramOverlay::createOverlayObjects(const QgsRenderContext& renderContext) +void QgsDiagramOverlay::createOverlayObjects( const QgsRenderContext& renderContext ) { - if(!mDisplayFlag) - { - return; - } + if ( !mDisplayFlag ) + { + return; + } //memory cleanup - for(QMap::iterator it = mOverlayObjects.begin(); it != mOverlayObjects.end(); ++it) - { - delete it.value(); - } + for ( QMap::iterator it = mOverlayObjects.begin(); it != mOverlayObjects.end(); ++it ) + { + delete it.value(); + } mOverlayObjects.clear(); //go through all the features and fill the multimap (query mDiagramRenderer for the correct sizes) - if(mVectorLayer && mDiagramRenderer) + if ( mVectorLayer && mDiagramRenderer ) + { + QgsVectorDataProvider* theProvider = mVectorLayer->dataProvider(); + if ( theProvider ) { - QgsVectorDataProvider* theProvider = mVectorLayer->dataProvider(); - if(theProvider) - { - //set spatial filter on data provider - theProvider->select(mAttributes, renderContext.extent()); + //set spatial filter on data provider + theProvider->select( mAttributes, renderContext.extent() ); - QgsFeature currentFeature; - int width, height; + QgsFeature currentFeature; + int width, height; - std::list wkbBuffers; - std::list wkbSizes; + std::list wkbBuffers; + std::list wkbSizes; - std::list::iterator bufferIt; - std::list::iterator sizeIt; + std::list::iterator bufferIt; + std::list::iterator sizeIt; - int multifeaturecounter = 0; + int multifeaturecounter = 0; - while(theProvider->nextFeature(currentFeature)) + while ( theProvider->nextFeature( currentFeature ) ) { - //todo: insert more objects for multipart features - if(mDiagramRenderer->getDiagramDimensions(width, height, currentFeature, renderContext) != 0) + //todo: insert more objects for multipart features + if ( mDiagramRenderer->getDiagramDimensions( width, height, currentFeature, renderContext ) != 0 ) { - //error + //error } - mOverlayObjects.insert(currentFeature.id(), new QgsOverlayObject(height, width, 0, currentFeature.geometryAndOwnership())); + mOverlayObjects.insert( currentFeature.id(), new QgsOverlayObject( height, width, 0, currentFeature.geometryAndOwnership() ) ); } - } } + } } -void QgsDiagramOverlay::drawOverlayObjects(QgsRenderContext& context) const +void QgsDiagramOverlay::drawOverlayObjects( QgsRenderContext& context ) const { - if(!mDisplayFlag) - { - return; - } - if(mVectorLayer && mDiagramRenderer) + if ( !mDisplayFlag ) + { + return; + } + if ( mVectorLayer && mDiagramRenderer ) + { + QgsVectorDataProvider* theProvider = mVectorLayer->dataProvider(); + if ( theProvider ) { - QgsVectorDataProvider* theProvider = mVectorLayer->dataProvider(); - if(theProvider) - { - //set spatial filter on data provider - theProvider->select(mAttributes, context.extent()); + //set spatial filter on data provider + theProvider->select( mAttributes, context.extent() ); - QgsFeature currentFeature; - QImage* currentDiagramImage = 0; + QgsFeature currentFeature; + QImage* currentDiagramImage = 0; - QPainter* painter = context.painter(); + QPainter* painter = context.painter(); - while(theProvider->nextFeature(currentFeature)) + while ( theProvider->nextFeature( currentFeature ) ) + { + //request diagram from renderer + currentDiagramImage = mDiagramRenderer->renderDiagram( currentFeature, context ); + if ( !currentDiagramImage ) { - //request diagram from renderer - currentDiagramImage = mDiagramRenderer->renderDiagram(currentFeature, context); - if(!currentDiagramImage) - { - qWarning("diagram image is 0"); - continue; - } - //search for overlay object in the map - QMap::const_iterator it = mOverlayObjects.find(currentFeature.id()); - if(it != mOverlayObjects.constEnd()) + qWarning( "diagram image is 0" ); + continue; + } + //search for overlay object in the map + QMap::const_iterator it = mOverlayObjects.find( currentFeature.id() ); + if ( it != mOverlayObjects.constEnd() ) + { + if ( it.value() ) { - if(it.value()) - { - QgsPoint overlayPosition = it.value()->position(); - const QgsCoordinateTransform* ct = context.coordinateTransform(); - if(ct) - { - overlayPosition = ct->transform(overlayPosition); - } - context.mapToPixel().transform(&overlayPosition); - int shiftX = currentDiagramImage->width()/2; - int shiftY = currentDiagramImage->height()/2; - - if(painter) - { - painter->save(); - painter->scale( 1.0 / context.rasterScaleFactor(), 1.0 / context.rasterScaleFactor() ); - painter->drawImage((int)(overlayPosition.x() * context.rasterScaleFactor())-shiftX, (int)(overlayPosition.y() * context.rasterScaleFactor())-shiftY, *currentDiagramImage); - painter->restore(); - } + QgsPoint overlayPosition = it.value()->position(); + const QgsCoordinateTransform* ct = context.coordinateTransform(); + if ( ct ) + { + overlayPosition = ct->transform( overlayPosition ); + } + context.mapToPixel().transform( &overlayPosition ); + int shiftX = currentDiagramImage->width() / 2; + int shiftY = currentDiagramImage->height() / 2; + + if ( painter ) + { + painter->save(); + painter->scale( 1.0 / context.rasterScaleFactor(), 1.0 / context.rasterScaleFactor() ); + painter->drawImage(( int )( overlayPosition.x() * context.rasterScaleFactor() ) - shiftX, ( int )( overlayPosition.y() * context.rasterScaleFactor() ) - shiftY, *currentDiagramImage ); + painter->restore(); } } + } - delete currentDiagramImage; - } - } + delete currentDiagramImage; + } } + } } -int QgsDiagramOverlay::getOverlayObjectSize(int& width, int& height, double value, const QgsFeature& f, const QgsRenderContext& renderContext) const +int QgsDiagramOverlay::getOverlayObjectSize( int& width, int& height, double value, const QgsFeature& f, const QgsRenderContext& renderContext ) const { - return mDiagramRenderer->getDiagramDimensions(width, height, f, renderContext); + return mDiagramRenderer->getDiagramDimensions( width, height, f, renderContext ); } -bool QgsDiagramOverlay::readXML(const QDomNode& overlayNode) +bool QgsDiagramOverlay::readXML( const QDomNode& overlayNode ) { QDomElement overlayElem = overlayNode.toElement(); - + //set display flag - if(overlayElem.attribute("display") == "true") - { - mDisplayFlag = true; - } + if ( overlayElem.attribute( "display" ) == "true" ) + { + mDisplayFlag = true; + } else - { - mDisplayFlag = false; - } + { + mDisplayFlag = false; + } //create a renderer object QgsDiagramRenderer* theDiagramRenderer = 0; - QDomNodeList rendererList = overlayNode.toElement().elementsByTagName("renderer"); + QDomNodeList rendererList = overlayNode.toElement().elementsByTagName( "renderer" ); QDomElement rendererElem; QString wellKnownName; @@ -191,219 +191,219 @@ bool QgsDiagramOverlay::readXML(const QDomNode& overlayNode) QList classAttrList; //classificationField - QDomNodeList classificationFieldList = overlayElem.elementsByTagName("scalingAttribute"); - for(int i = 0; i < classificationFieldList.size(); ++i) + QDomNodeList classificationFieldList = overlayElem.elementsByTagName( "scalingAttribute" ); + for ( int i = 0; i < classificationFieldList.size(); ++i ) + { + bool conversionSuccess = false; + int classificationField = classificationFieldList.at( i ).toElement().text().toInt( &conversionSuccess ); + if ( conversionSuccess ) { - bool conversionSuccess = false; - int classificationField = classificationFieldList.at(i).toElement().text().toInt(&conversionSuccess); - if(conversionSuccess) - { - classAttrList.push_back(classificationFieldList.at(i).toElement().text().toInt()); - } + classAttrList.push_back( classificationFieldList.at( i ).toElement().text().toInt() ); } + } - theDiagramRenderer = new QgsDiagramRenderer(classAttrList); + theDiagramRenderer = new QgsDiagramRenderer( classAttrList ); - //in case of well-known diagrams, the category attributes also need to be fetched + //in case of well-known diagrams, the category attributes also need to be fetched QDomElement categoryElem; - QDomNodeList categoryList = overlayElem.elementsByTagName("category"); + QDomNodeList categoryList = overlayElem.elementsByTagName( "category" ); - for(int i = 0; i < categoryList.size(); ++i) - { - categoryElem = categoryList.at(i).toElement(); - attributeList.push_back(categoryElem.attribute("attribute").toInt()); - } + for ( int i = 0; i < categoryList.size(); ++i ) + { + categoryElem = categoryList.at( i ).toElement(); + attributeList.push_back( categoryElem.attribute( "attribute" ).toInt() ); + } - if(rendererList.size() < 1) - { - return false; - } - rendererElem = rendererList.at(0).toElement(); + if ( rendererList.size() < 1 ) + { + return false; + } + rendererElem = rendererList.at( 0 ).toElement(); //read settings about factory - QDomNode factoryNode = overlayElem.namedItem("factory"); - if(factoryNode.isNull()) + QDomNode factoryNode = overlayElem.namedItem( "factory" ); + if ( factoryNode.isNull() ) { - return false; + return false; } QDomElement factoryElem = factoryNode.toElement(); - QString factoryType = factoryElem.attribute("type"); + QString factoryType = factoryElem.attribute( "type" ); QgsDiagramFactory* newFactory = 0; - if(factoryType == "svg") + if ( factoryType == "svg" ) { newFactory = new QgsSVGDiagramFactory(); - } - else if(factoryType == "Pie") - { + } + else if ( factoryType == "Pie" ) + { newFactory = new QgsPieDiagramFactory(); - } - else if(factoryType == "Bar") - { - newFactory = new QgsBarDiagramFactory(); - } + } + else if ( factoryType == "Bar" ) + { + newFactory = new QgsBarDiagramFactory(); + } - if(!newFactory) - { - return false; - } + if ( !newFactory ) + { + return false; + } - if(!newFactory->readXML(factoryElem)) - { - delete newFactory; - return false; - } - newFactory->setScalingAttributes(classAttrList); - theDiagramRenderer->setFactory(newFactory); + if ( !newFactory->readXML( factoryElem ) ) + { + delete newFactory; + return false; + } + newFactory->setScalingAttributes( classAttrList ); + theDiagramRenderer->setFactory( newFactory ); //Read renderer specific settings - if(theDiagramRenderer) + if ( theDiagramRenderer ) + { + theDiagramRenderer->readXML( rendererElem ); + setDiagramRenderer( theDiagramRenderer ); + + //the overlay may need a different attribute list than the renderer + QList::const_iterator it = classAttrList.constBegin(); + for ( ; it != classAttrList.constEnd(); ++it ) { - theDiagramRenderer->readXML(rendererElem); - setDiagramRenderer(theDiagramRenderer); - - //the overlay may need a different attribute list than the renderer - QList::const_iterator it = classAttrList.constBegin(); - for(; it != classAttrList.constEnd(); ++it) - { - if(!attributeList.contains(*it)) - { - attributeList.push_back(*it); - } - } - setAttributes(attributeList); - return true; + if ( !attributeList.contains( *it ) ) + { + attributeList.push_back( *it ); + } } + setAttributes( attributeList ); + return true; + } return false; } -bool QgsDiagramOverlay::writeXML(QDomNode& layer_node, QDomDocument& doc) const +bool QgsDiagramOverlay::writeXML( QDomNode& layer_node, QDomDocument& doc ) const { - QDomElement overlayElement = doc.createElement("overlay"); - overlayElement.setAttribute("type", "diagram"); - if(mDisplayFlag) - { - overlayElement.setAttribute("display", "true"); - } + QDomElement overlayElement = doc.createElement( "overlay" ); + overlayElement.setAttribute( "type", "diagram" ); + if ( mDisplayFlag ) + { + overlayElement.setAttribute( "display", "true" ); + } else + { + overlayElement.setAttribute( "display", "false" ); + } + + layer_node.appendChild( overlayElement ); + if ( mDiagramRenderer ) + { + mDiagramRenderer->writeXML( overlayElement, doc ); + QgsDiagramFactory* f = mDiagramRenderer->factory(); + if ( f ) { - overlayElement.setAttribute("display", "false"); + f->writeXML( overlayElement, doc ); } - layer_node.appendChild(overlayElement); - if(mDiagramRenderer) + //write classification attributes + QList scalingAttributes = mDiagramRenderer->classificationAttributes(); + QList::const_iterator it = scalingAttributes.constBegin(); + for ( ; it != scalingAttributes.constEnd(); ++it ) { - mDiagramRenderer->writeXML(overlayElement, doc); - QgsDiagramFactory* f = mDiagramRenderer->factory(); - if(f) - { - f->writeXML(overlayElement, doc); - } - - //write classification attributes - QList scalingAttributes = mDiagramRenderer->classificationAttributes(); - QList::const_iterator it = scalingAttributes.constBegin(); - for(; it != scalingAttributes.constEnd(); ++it) - { - QDomElement scalingAttributeElem = doc.createElement("scalingAttribute"); - QDomText scalingAttributeText = doc.createTextNode(QString::number(*it)); - scalingAttributeElem.appendChild(scalingAttributeText); - overlayElement.appendChild(scalingAttributeElem); - } + QDomElement scalingAttributeElem = doc.createElement( "scalingAttribute" ); + QDomText scalingAttributeText = doc.createTextNode( QString::number( *it ) ); + scalingAttributeElem.appendChild( scalingAttributeText ); + overlayElement.appendChild( scalingAttributeElem ); } + } return true; } -int QgsDiagramOverlay::createLegendContent(std::list >& content) const +int QgsDiagramOverlay::createLegendContent( std::list >& content ) const { #if 0 //first make sure the list is clean std::list >::iterator it; - for(it = content.begin(); it != content.end(); ++it) - { - delete (it->second); - } + for ( it = content.begin(); it != content.end(); ++it ) + { + delete( it->second ); + } content.clear(); - - if(mDiagramRenderer) + + if ( mDiagramRenderer ) + { + //first item: name of the classification attribute + QString classificationName = QgsDiagramOverlay::attributeNameFromIndex( mDiagramRenderer->classificationField(), mVectorLayer ); + content.push_back( std::make_pair( classificationName, ( QImage* )0 ) ); + + //then a descriptive symbol (must come from diagram renderer) + QString legendSymbolText; + QImage* legendSymbolImage = mDiagramRenderer->getLegendImage( legendSymbolText ); + content.push_back( std::make_pair( legendSymbolText, legendSymbolImage ) ); + + //then color/attribute pairs + std::list colorList = mDiagramRenderer->colors(); + std::list::const_iterator color_it = colorList.begin(); + QgsAttributeList attributeList = mDiagramRenderer->attributes(); + QgsAttributeList::const_iterator att_it = attributeList.begin(); + QString attributeName; + QImage* colorImage; + QPainter p; + + for ( ; att_it != attributeList.constEnd() && color_it != colorList.end(); ++color_it, ++att_it ) { - //first item: name of the classification attribute - QString classificationName = QgsDiagramOverlay::attributeNameFromIndex(mDiagramRenderer->classificationField(), mVectorLayer); - content.push_back(std::make_pair(classificationName, (QImage*)0)); - - //then a descriptive symbol (must come from diagram renderer) - QString legendSymbolText; - QImage* legendSymbolImage = mDiagramRenderer->getLegendImage(legendSymbolText); - content.push_back(std::make_pair(legendSymbolText, legendSymbolImage)); - - //then color/attribute pairs - std::list colorList = mDiagramRenderer->colors(); - std::list::const_iterator color_it = colorList.begin(); - QgsAttributeList attributeList = mDiagramRenderer->attributes(); - QgsAttributeList::const_iterator att_it = attributeList.begin(); - QString attributeName; - QImage* colorImage; - QPainter p; - - for(; att_it != attributeList.constEnd() && color_it != colorList.end(); ++color_it, ++att_it) - { - colorImage = new QImage(15, 15, QImage::Format_ARGB32_Premultiplied); - colorImage->fill(QColor(255,255,255,0).rgba()); - p.begin(colorImage); - p.setPen(Qt::NoPen); - p.setBrush(*color_it); - p.drawRect(0, 0, 15, 15); - p.end(); - attributeName = QgsDiagramOverlay::attributeNameFromIndex(*att_it, mVectorLayer); - content.push_back(std::make_pair(attributeName, colorImage)); - } - - - - return 0; + colorImage = new QImage( 15, 15, QImage::Format_ARGB32_Premultiplied ); + colorImage->fill( QColor( 255, 255, 255, 0 ).rgba() ); + p.begin( colorImage ); + p.setPen( Qt::NoPen ); + p.setBrush( *color_it ); + p.drawRect( 0, 0, 15, 15 ); + p.end(); + attributeName = QgsDiagramOverlay::attributeNameFromIndex( *att_it, mVectorLayer ); + content.push_back( std::make_pair( attributeName, colorImage ) ); } + + + + return 0; + } else - { - return 1; - } + { + return 1; + } #endif //0 return 1; //todo: adapt to new design } -int QgsDiagramOverlay::indexFromAttributeName(const QString& name, const QgsVectorLayer* vl) +int QgsDiagramOverlay::indexFromAttributeName( const QString& name, const QgsVectorLayer* vl ) { int error = -1; - - if(!vl) - { - return error; - } + + if ( !vl ) + { + return error; + } const QgsVectorDataProvider *provider; - if ((provider = dynamic_cast(vl->dataProvider()))) - { - return provider->fieldNameIndex(name); - } + if (( provider = dynamic_cast( vl->dataProvider() ) ) ) + { + return provider->fieldNameIndex( name ); + } return error; } -QString QgsDiagramOverlay::attributeNameFromIndex(int index, const QgsVectorLayer* vl) +QString QgsDiagramOverlay::attributeNameFromIndex( int index, const QgsVectorLayer* vl ) { - if(!vl) - { - return ""; - } + if ( !vl ) + { + return ""; + } const QgsVectorDataProvider *provider; - if ((provider = dynamic_cast(vl->dataProvider()))) + if (( provider = dynamic_cast( vl->dataProvider() ) ) ) + { + const QgsFieldMap & fields = provider->fields(); + QgsFieldMap::const_iterator field_iter = fields.find( index ); + if ( field_iter != fields.constEnd() ) { - const QgsFieldMap & fields = provider->fields(); - QgsFieldMap::const_iterator field_iter = fields.find(index); - if(field_iter != fields.constEnd()) - { - return field_iter->name(); - } + return field_iter->name(); } + } return ""; } diff --git a/src/plugins/diagram_overlay/qgsdiagramoverlay.h b/src/plugins/diagram_overlay/qgsdiagramoverlay.h index bc3022847168..4a1c2f12bb0e 100644 --- a/src/plugins/diagram_overlay/qgsdiagramoverlay.h +++ b/src/plugins/diagram_overlay/qgsdiagramoverlay.h @@ -25,34 +25,34 @@ class QgsDiagramRenderer; /**An overlay class that places diagrams on a vectorlayer*/ class QgsDiagramOverlay: public QgsVectorOverlay { - public: - QgsDiagramOverlay(QgsVectorLayer* vl); - ~QgsDiagramOverlay(); - void createOverlayObjects(const QgsRenderContext& renderContext); - void drawOverlayObjects(QgsRenderContext& context) const; - - //setters and getters - QString typeName() const{return "diagram";} - void setDiagramRenderer(QgsDiagramRenderer* r); - const QgsDiagramRenderer* diagramRenderer() const; - - bool readXML(const QDomNode& overlayNode); - bool writeXML(QDomNode& layer_node, QDomDocument& doc) const; - int createLegendContent(std::list >& content) const; - - /**Helper function that returns the attribute index from an attribute name. Returns -1 in case of error*/ - static int indexFromAttributeName(const QString& name, const QgsVectorLayer* vl); - /**Helper function that returns the attribute name from an attribute index. Returns an empty string - in case of error.*/ - static QString attributeNameFromIndex(int index, const QgsVectorLayer* vl); - - -protected: - int getOverlayObjectSize(int& width, int& height, double value, const QgsFeature& f, const QgsRenderContext& renderContext) const; - - private: - /**Does the classification and manages the diagram generation*/ - QgsDiagramRenderer* mDiagramRenderer; + public: + QgsDiagramOverlay( QgsVectorLayer* vl ); + ~QgsDiagramOverlay(); + void createOverlayObjects( const QgsRenderContext& renderContext ); + void drawOverlayObjects( QgsRenderContext& context ) const; + + //setters and getters + QString typeName() const {return "diagram";} + void setDiagramRenderer( QgsDiagramRenderer* r ); + const QgsDiagramRenderer* diagramRenderer() const; + + bool readXML( const QDomNode& overlayNode ); + bool writeXML( QDomNode& layer_node, QDomDocument& doc ) const; + int createLegendContent( std::list >& content ) const; + + /**Helper function that returns the attribute index from an attribute name. Returns -1 in case of error*/ + static int indexFromAttributeName( const QString& name, const QgsVectorLayer* vl ); + /**Helper function that returns the attribute name from an attribute index. Returns an empty string + in case of error.*/ + static QString attributeNameFromIndex( int index, const QgsVectorLayer* vl ); + + + protected: + int getOverlayObjectSize( int& width, int& height, double value, const QgsFeature& f, const QgsRenderContext& renderContext ) const; + + private: + /**Does the classification and manages the diagram generation*/ + QgsDiagramRenderer* mDiagramRenderer; }; #endif diff --git a/src/plugins/diagram_overlay/qgsdiagramoverlayplugin.cpp b/src/plugins/diagram_overlay/qgsdiagramoverlayplugin.cpp index b987e130ff50..85ac92396a99 100644 --- a/src/plugins/diagram_overlay/qgsdiagramoverlayplugin.cpp +++ b/src/plugins/diagram_overlay/qgsdiagramoverlayplugin.cpp @@ -35,12 +35,12 @@ static const QString pluginName = "diagram overlay"; static const QString pluginDescription = "A plugin for placing diagrams on vector layers"; static const QString pluginVersion = "Version 0.0.1"; -QgsDiagramOverlayPlugin::QgsDiagramOverlayPlugin(QgisInterface* iface): QObject(), QgsVectorOverlayPlugin(pluginName, pluginDescription, pluginVersion), mInterface(iface) +QgsDiagramOverlayPlugin::QgsDiagramOverlayPlugin( QgisInterface* iface ): QObject(), QgsVectorOverlayPlugin( pluginName, pluginDescription, pluginVersion ), mInterface( iface ) { - if(iface && iface->mainWindow()) - { - connect(iface->mainWindow(), SIGNAL(projectRead()), this, SLOT(projectRead())); - } + if ( iface && iface->mainWindow() ) + { + connect( iface->mainWindow(), SIGNAL( projectRead() ), this, SLOT( projectRead() ) ); + } } QgsDiagramOverlayPlugin::~QgsDiagramOverlayPlugin() @@ -53,20 +53,20 @@ void QgsDiagramOverlayPlugin::projectRead() //for a test, print out the content of the project file QString projectFileName = QgsProject::instance()->fileName(); - if(projectFileName.isEmpty()) - { - return; - } + if ( projectFileName.isEmpty() ) + { + return; + } - QFile projectFile(projectFileName); + QFile projectFile( projectFileName ); QDomDocument projectDocument; - if(!projectDocument.setContent(&projectFile)) - { - return; - } + if ( !projectDocument.setContent( &projectFile ) ) + { + return; + } //iterate over all maplayers - QDomNodeList mapLayerList = projectDocument.documentElement().elementsByTagName("maplayer"); + QDomNodeList mapLayerList = projectDocument.documentElement().elementsByTagName( "maplayer" ); QDomElement mapLayerElem; QDomNodeList overlayList; QDomElement overlayElem; @@ -77,57 +77,57 @@ void QgsDiagramOverlayPlugin::projectRead() QString layerId; //iterate through all maplayer elements - for(int i = 0; i < mapLayerList.size(); ++i) + for ( int i = 0; i < mapLayerList.size(); ++i ) + { + mapLayerElem = mapLayerList.at( i ).toElement(); + overlayList = mapLayerElem.elementsByTagName( "overlay" ); + + //find out layer id + idList = mapLayerElem.elementsByTagName( "id" ); + if ( idList.size() < 1 ) + { + continue; + } + layerId = idList.at( 0 ).toElement().text(); + + //iterate through all overlay elements + for ( int j = 0; j < overlayList.size(); ++j ) { - mapLayerElem = mapLayerList.at(i).toElement(); - overlayList = mapLayerElem.elementsByTagName("overlay"); - - //find out layer id - idList = mapLayerElem.elementsByTagName("id"); - if(idList.size() < 1) - { - continue; - } - layerId = idList.at(0).toElement().text(); - - //iterate through all overlay elements - for(int j = 0; j < overlayList.size(); ++j) - { - overlayElem = overlayList.at(j).toElement(); - if(overlayElem.attribute("type") == "diagram") - { - //get a pointer to the vector layer which owns the diagram overlay (use QgsMapLayerRegistry) - currentVectorLayer = dynamic_cast(QgsMapLayerRegistry::instance()->mapLayer(layerId)); - if(!currentVectorLayer) - { - continue; - } - - //create an overlay object - newDiagramOverlay = new QgsDiagramOverlay(currentVectorLayer); - newDiagramOverlay->readXML(overlayElem); - - //add the overlay to the vector layer - currentVectorLayer->addOverlay(newDiagramOverlay); - - //notify the legend that the layer legend needs to be changed - if(mInterface) - { - mInterface->refreshLegend(currentVectorLayer); - } - } - } + overlayElem = overlayList.at( j ).toElement(); + if ( overlayElem.attribute( "type" ) == "diagram" ) + { + //get a pointer to the vector layer which owns the diagram overlay (use QgsMapLayerRegistry) + currentVectorLayer = dynamic_cast( QgsMapLayerRegistry::instance()->mapLayer( layerId ) ); + if ( !currentVectorLayer ) + { + continue; + } + + //create an overlay object + newDiagramOverlay = new QgsDiagramOverlay( currentVectorLayer ); + newDiagramOverlay->readXML( overlayElem ); + + //add the overlay to the vector layer + currentVectorLayer->addOverlay( newDiagramOverlay ); + + //notify the legend that the layer legend needs to be changed + if ( mInterface ) + { + mInterface->refreshLegend( currentVectorLayer ); + } + } } + } } -QgsApplyDialog* QgsDiagramOverlayPlugin::dialog(QgsVectorLayer* vl) const +QgsApplyDialog* QgsDiagramOverlayPlugin::dialog( QgsVectorLayer* vl ) const { - return new QgsDiagramDialog(vl); + return new QgsDiagramDialog( vl ); } -QGISEXTERN QgisPlugin* classFactory(QgisInterface* iface) +QGISEXTERN QgisPlugin* classFactory( QgisInterface* iface ) { - return new QgsDiagramOverlayPlugin(iface); + return new QgsDiagramOverlayPlugin( iface ); } QGISEXTERN QString name() @@ -150,7 +150,7 @@ QGISEXTERN int type() return QgisPlugin::VECTOR_OVERLAY; } -QGISEXTERN void unload(QgisPlugin* theQgsDiagramOverlayPluginPointer) +QGISEXTERN void unload( QgisPlugin* theQgsDiagramOverlayPluginPointer ) { delete theQgsDiagramOverlayPluginPointer; } diff --git a/src/plugins/diagram_overlay/qgsdiagramoverlayplugin.h b/src/plugins/diagram_overlay/qgsdiagramoverlayplugin.h index 3b23fc7d421f..1033554d5e4f 100644 --- a/src/plugins/diagram_overlay/qgsdiagramoverlayplugin.h +++ b/src/plugins/diagram_overlay/qgsdiagramoverlayplugin.h @@ -29,19 +29,19 @@ class QgsApplyDialog; vector layer properties dialog and is able to create and configure a diagram overlay layer*/ class QgsDiagramOverlayPlugin: public QObject, public QgsVectorOverlayPlugin { - Q_OBJECT - public: - QgsDiagramOverlayPlugin(QgisInterface* iface); - ~QgsDiagramOverlayPlugin(); - QgsApplyDialog* dialog(QgsVectorLayer*) const; - void initGui(){} - void unload(){} + Q_OBJECT + public: + QgsDiagramOverlayPlugin( QgisInterface* iface ); + ~QgsDiagramOverlayPlugin(); + QgsApplyDialog* dialog( QgsVectorLayer* ) const; + void initGui() {} + void unload() {} public slots: - void projectRead(); + void projectRead(); - private: - QgisInterface* mInterface; + private: + QgisInterface* mInterface; }; #endif diff --git a/src/plugins/diagram_overlay/qgsdiagramrenderer.cpp b/src/plugins/diagram_overlay/qgsdiagramrenderer.cpp index cf38877f9e20..f5800e8dd01d 100644 --- a/src/plugins/diagram_overlay/qgsdiagramrenderer.cpp +++ b/src/plugins/diagram_overlay/qgsdiagramrenderer.cpp @@ -4,7 +4,7 @@ #include #include -QgsDiagramRenderer::QgsDiagramRenderer(const QList& classificationAttributes): mClassificationAttributes(classificationAttributes), mScaleFactor(1.0) +QgsDiagramRenderer::QgsDiagramRenderer( const QList& classificationAttributes ): mClassificationAttributes( classificationAttributes ), mScaleFactor( 1.0 ) { } @@ -13,102 +13,102 @@ QgsDiagramRenderer::~QgsDiagramRenderer() delete mFactory; } -QgsDiagramRenderer::QgsDiagramRenderer(): mScaleFactor(1.0) +QgsDiagramRenderer::QgsDiagramRenderer(): mScaleFactor( 1.0 ) { } -QImage* QgsDiagramRenderer::renderDiagram(const QgsFeature& f, const QgsRenderContext& renderContext) const +QImage* QgsDiagramRenderer::renderDiagram( const QgsFeature& f, const QgsRenderContext& renderContext ) const { - if(!mFactory) - { - return 0; - } + if ( !mFactory ) + { + return 0; + } //only scaling according to attributes does not need any items - if(mItemInterpretation != QgsDiagramRenderer::ATTRIBUTE && mItems.size() < 1) - { - return 0; - } + if ( mItemInterpretation != QgsDiagramRenderer::ATTRIBUTE && mItems.size() < 1 ) + { + return 0; + } int size; - if(calculateDiagramSize(f, size) != 0) - { - return 0; - } + if ( calculateDiagramSize( f, size ) != 0 ) + { + return 0; + } - return mFactory->createDiagram(size, f, renderContext); + return mFactory->createDiagram( size, f, renderContext ); } -int QgsDiagramRenderer::getDiagramDimensions(int& width, int& height, const QgsFeature& f, const QgsRenderContext& renderContext) const +int QgsDiagramRenderer::getDiagramDimensions( int& width, int& height, const QgsFeature& f, const QgsRenderContext& renderContext ) const { //first find out classification value - if(!mFactory || mItems.size() < 1) - { - return 1; - } + if ( !mFactory || mItems.size() < 1 ) + { + return 1; + } int size; - if(calculateDiagramSize(f, size) != 0) - { - return 2; - } - - if(mFactory->getDiagramDimensions(size, f, renderContext, width, height) != 0) - { - return 3; - } + if ( calculateDiagramSize( f, size ) != 0 ) + { + return 2; + } + + if ( mFactory->getDiagramDimensions( size, f, renderContext, width, height ) != 0 ) + { + return 3; + } return 0; } -int QgsDiagramRenderer::classificationValue(const QgsFeature& f, QVariant& value) const +int QgsDiagramRenderer::classificationValue( const QgsFeature& f, QVariant& value ) const { //find out attribute value of the feature QgsAttributeMap featureAttributes = f.attributeMap(); - + QgsAttributeMap::const_iterator iter; - - if(value.type() == QVariant::String) //string type + + if ( value.type() == QVariant::String ) //string type + { + //we can only handle one classification field for strings + if ( mClassificationAttributes.size() > 1 ) { - //we can only handle one classification field for strings - if(mClassificationAttributes.size() > 1) - { - return 1; - } - - iter = featureAttributes.find(mClassificationAttributes.first()); - if(iter == featureAttributes.constEnd()) - { - return 2; - } - value = iter.value(); + return 1; } + + iter = featureAttributes.find( mClassificationAttributes.first() ); + if ( iter == featureAttributes.constEnd() ) + { + return 2; + } + value = iter.value(); + } else //numeric type + { + double currentValue; + double totalValue = 0; + + QList::const_iterator list_it = mClassificationAttributes.constBegin(); + for ( ; list_it != mClassificationAttributes.constEnd(); ++list_it ) { - double currentValue; - double totalValue = 0; - - QList::const_iterator list_it = mClassificationAttributes.constBegin(); - for(; list_it != mClassificationAttributes.constEnd(); ++list_it) - { - QgsAttributeMap::const_iterator iter = featureAttributes.find(*list_it); - if(iter == featureAttributes.constEnd()) - { - continue; - } - currentValue = iter.value().toDouble(); - totalValue += currentValue; - } - value = QVariant(totalValue); + QgsAttributeMap::const_iterator iter = featureAttributes.find( *list_it ); + if ( iter == featureAttributes.constEnd() ) + { + continue; + } + currentValue = iter.value().toDouble(); + totalValue += currentValue; } + value = QVariant( totalValue ); + } return 0; } -void QgsDiagramRenderer::addClassificationAttribute(int attrNr) +void QgsDiagramRenderer::addClassificationAttribute( int attrNr ) { - mClassificationAttributes.push_back(attrNr); + mClassificationAttributes.push_back( attrNr ); } -bool QgsDiagramRenderer::readXML(const QDomNode& rendererNode) +bool QgsDiagramRenderer::readXML( const QDomNode& rendererNode ) { QDomElement rendererElem = rendererNode.toElement(); @@ -116,216 +116,216 @@ bool QgsDiagramRenderer::readXML(const QDomNode& rendererNode) QList itemList; bool conversionOk; - QString interpretationName = rendererNode.toElement().attribute("item_interpretation"); - if(interpretationName == "discrete") - { - mItemInterpretation = QgsDiagramRenderer::DISCRETE; - } - else if(interpretationName == "linear") - { - mItemInterpretation = QgsDiagramRenderer::LINEAR; - } - else if(interpretationName == "attribute") - { - mItemInterpretation = QgsDiagramRenderer::ATTRIBUTE; - } - else if(interpretationName == "constant") - { - mItemInterpretation = QgsDiagramRenderer::CONSTANT; - } - - QDomNodeList itemNodeList = rendererElem.elementsByTagName("diagramitem"); - for(int i = 0; i < itemNodeList.size(); ++i) + QString interpretationName = rendererNode.toElement().attribute( "item_interpretation" ); + if ( interpretationName == "discrete" ) + { + mItemInterpretation = QgsDiagramRenderer::DISCRETE; + } + else if ( interpretationName == "linear" ) + { + mItemInterpretation = QgsDiagramRenderer::LINEAR; + } + else if ( interpretationName == "attribute" ) + { + mItemInterpretation = QgsDiagramRenderer::ATTRIBUTE; + } + else if ( interpretationName == "constant" ) + { + mItemInterpretation = QgsDiagramRenderer::CONSTANT; + } + + QDomNodeList itemNodeList = rendererElem.elementsByTagName( "diagramitem" ); + for ( int i = 0; i < itemNodeList.size(); ++i ) + { + QgsDiagramItem currentItem; + QVariant currentValue; + currentItem.size = itemNodeList.at( i ).toElement().attribute( "size" ).toInt(); + currentValue = QVariant( itemNodeList.at( i ).toElement().attribute( "value" ).toDouble( &conversionOk ) ); + if ( !conversionOk ) //string data? { - QgsDiagramItem currentItem; - QVariant currentValue; - currentItem.size = itemNodeList.at(i).toElement().attribute("size").toInt(); - currentValue = QVariant(itemNodeList.at(i).toElement().attribute("value").toDouble(&conversionOk)); - if(!conversionOk) //string data? - { - currentValue = QVariant(itemNodeList.at(i).toElement().attribute("value")); - } - currentItem.value = currentValue; - itemList.push_back(currentItem); + currentValue = QVariant( itemNodeList.at( i ).toElement().attribute( "value" ) ); } - setDiagramItems(itemList); + currentItem.value = currentValue; + itemList.push_back( currentItem ); + } + setDiagramItems( itemList ); return true; } -bool QgsDiagramRenderer::writeXML(QDomNode& overlay_node, QDomDocument& doc) const +bool QgsDiagramRenderer::writeXML( QDomNode& overlay_node, QDomDocument& doc ) const { - QDomElement rendererElement = doc.createElement("renderer"); + QDomElement rendererElement = doc.createElement( "renderer" ); //write interpolation to xml file QString interpretationName; - if(mItemInterpretation == QgsDiagramRenderer::DISCRETE) - { - interpretationName = "discrete"; - } - else if(mItemInterpretation == QgsDiagramRenderer::LINEAR) - { - interpretationName = "linear"; - } - else if(mItemInterpretation == QgsDiagramRenderer::ATTRIBUTE) - { - interpretationName = "attribute"; - } - else if(mItemInterpretation == QgsDiagramRenderer::CONSTANT) - { - interpretationName = "constant"; - } - rendererElement.setAttribute("item_interpretation", interpretationName); + if ( mItemInterpretation == QgsDiagramRenderer::DISCRETE ) + { + interpretationName = "discrete"; + } + else if ( mItemInterpretation == QgsDiagramRenderer::LINEAR ) + { + interpretationName = "linear"; + } + else if ( mItemInterpretation == QgsDiagramRenderer::ATTRIBUTE ) + { + interpretationName = "attribute"; + } + else if ( mItemInterpretation == QgsDiagramRenderer::CONSTANT ) + { + interpretationName = "constant"; + } + rendererElement.setAttribute( "item_interpretation", interpretationName ); QList::const_iterator item_it = mItems.constBegin(); - for(; item_it != mItems.constEnd(); ++item_it) - { - QDomElement itemElement = doc.createElement("diagramitem"); - itemElement.setAttribute("size", item_it->size); - itemElement.setAttribute("value", item_it->value.toString()); - rendererElement.appendChild(itemElement); - } - - overlay_node.appendChild(rendererElement); + for ( ; item_it != mItems.constEnd(); ++item_it ) + { + QDomElement itemElement = doc.createElement( "diagramitem" ); + itemElement.setAttribute( "size", item_it->size ); + itemElement.setAttribute( "value", item_it->value.toString() ); + rendererElement.appendChild( itemElement ); + } + + overlay_node.appendChild( rendererElement ); return true; } -int QgsDiagramRenderer::createLegendContent(const QgsRenderContext& renderContext, QMap items) const +int QgsDiagramRenderer::createLegendContent( const QgsRenderContext& renderContext, QMap items ) const { - if(!mFactory || mItems.size() < 1) - { - return 1; - } + if ( !mFactory || mItems.size() < 1 ) + { + return 1; + } //determine a size and value for the legend, use the middle item for this - int element = (int)(mItems.size()/2); - QString value = mItems.at(element).value.toString(); - int size = mItems.at(element).size; - - if(mFactory->createLegendContent(size, renderContext, value, items) != 0) - { - return 2; - } + int element = ( int )( mItems.size() / 2 ); + QString value = mItems.at( element ).value.toString(); + int size = mItems.at( element ).size; + + if ( mFactory->createLegendContent( size, renderContext, value, items ) != 0 ) + { + return 2; + } return 0; } -int QgsDiagramRenderer::calculateDiagramSize(const QgsFeature& f, int& size) const +int QgsDiagramRenderer::calculateDiagramSize( const QgsFeature& f, int& size ) const { //find out value for classificationAttribute QVariant value; - if(classificationValue(f, value) != 0) - { - return 1; - } - - if(mItemInterpretation == ATTRIBUTE) - { - size = (int)(value.toDouble() * mScaleFactor); - return 0; - } - - if(mItems.size() < 1) - { - return 2; - } - - if(mItemInterpretation == CONSTANT) - { - size = (int)(mItems.constBegin()->size * mScaleFactor); - return 0; - } + if ( classificationValue( f, value ) != 0 ) + { + return 1; + } + + if ( mItemInterpretation == ATTRIBUTE ) + { + size = ( int )( value.toDouble() * mScaleFactor ); + return 0; + } + + if ( mItems.size() < 1 ) + { + return 2; + } + + if ( mItemInterpretation == CONSTANT ) + { + size = ( int )( mItems.constBegin()->size * mScaleFactor ); + return 0; + } //find out size bool sizeAssigned = false; QList::const_iterator current_it = mItems.constBegin(); QList::const_iterator last_it = mItems.constEnd(); - - if(value.type() == QVariant::String) //string types are handled differently + + if ( value.type() == QVariant::String ) //string types are handled differently + { + for ( ; current_it != mItems.constEnd(); ++current_it ) { - for(; current_it != mItems.constEnd(); ++current_it) - { - if(current_it->value.toString() == value.toString()) - { - size = (int)(current_it->size * mScaleFactor); - sizeAssigned = true; - } - } - if(!sizeAssigned) - { - return 3; - } + if ( current_it->value.toString() == value.toString() ) + { + size = ( int )( current_it->size * mScaleFactor ); + sizeAssigned = true; + } } + if ( !sizeAssigned ) + { + return 3; + } + } else //numerical types + { + for ( ; current_it != mItems.constEnd(); ++current_it ) { - for(; current_it != mItems.constEnd(); ++current_it) - { - if(value.toDouble() < current_it->value.toDouble()) - { - if(last_it == mItems.constEnd()) //values below classifications receive first items size - { - size = (int)(current_it->size * mScaleFactor); - } - else - { - size = (int)(interpolateSize(value.toDouble(), last_it->value.toDouble(), current_it->value.toDouble(), last_it->size, current_it->size) * mScaleFactor); - - } - sizeAssigned = true; - break; - } - last_it = current_it; - } - - if(!sizeAssigned)//values above classification receive last items size - { - size = (int)(last_it->size * mScaleFactor); - } + if ( value.toDouble() < current_it->value.toDouble() ) + { + if ( last_it == mItems.constEnd() ) //values below classifications receive first items size + { + size = ( int )( current_it->size * mScaleFactor ); + } + else + { + size = ( int )( interpolateSize( value.toDouble(), last_it->value.toDouble(), current_it->value.toDouble(), last_it->size, current_it->size ) * mScaleFactor ); + + } + sizeAssigned = true; + break; + } + last_it = current_it; } + if ( !sizeAssigned )//values above classification receive last items size + { + size = ( int )( last_it->size * mScaleFactor ); + } + } + return 0; } -int QgsDiagramRenderer::interpolateSize(double value, double lowerValue, double upperValue, \ - int lowerSize, int upperSize) const +int QgsDiagramRenderer::interpolateSize( double value, double lowerValue, double upperValue, \ + int lowerSize, int upperSize ) const { - switch(mItemInterpretation) - { + switch ( mItemInterpretation ) + { case DISCRETE: return lowerSize; break; case LINEAR: + { + if ( value <= lowerValue ) + { + return lowerSize; + } + else if ( value >= upperValue ) + { + return upperSize; + } + + QgsDiagramFactory::SizeType t; + if ( mFactory ) { - if(value <= lowerValue) - { - return lowerSize; - } - else if(value >= upperValue) - { - return upperSize; - } - - QgsDiagramFactory::SizeType t; - if(mFactory) - { - t = mFactory->sizeType(); - } - - if(!mFactory || t == QgsDiagramFactory::HEIGHT) - { - //do one dimensional linear interpolation - return (int)(((value - lowerValue) * upperSize + (upperValue - value) * lowerSize) / (upperValue - lowerValue)); - } - else if(t == QgsDiagramFactory::DIAMETER) - { - double lowerArea = (lowerSize/2)*(lowerSize/2)*M_PI; - double upperArea = (upperSize/2)*(upperSize/2)*M_PI; - double valueArea = ((value - lowerValue) * upperArea + (upperValue - value) * lowerArea)/(upperValue - lowerValue); - return (int)(2*sqrt(valueArea/M_PI)); - } + t = mFactory->sizeType(); } + + if ( !mFactory || t == QgsDiagramFactory::HEIGHT ) + { + //do one dimensional linear interpolation + return ( int )((( value - lowerValue ) * upperSize + ( upperValue - value ) * lowerSize ) / ( upperValue - lowerValue ) ); + } + else if ( t == QgsDiagramFactory::DIAMETER ) + { + double lowerArea = ( lowerSize / 2 ) * ( lowerSize / 2 ) * M_PI; + double upperArea = ( upperSize / 2 ) * ( upperSize / 2 ) * M_PI; + double valueArea = (( value - lowerValue ) * upperArea + ( upperValue - value ) * lowerArea ) / ( upperValue - lowerValue ); + return ( int )( 2*sqrt( valueArea / M_PI ) ); + } + } default: return 1; - } + } return 0; //something went wrong if we arrive here } diff --git a/src/plugins/diagram_overlay/qgsdiagramrenderer.h b/src/plugins/diagram_overlay/qgsdiagramrenderer.h index 14c611b4f921..2ca3b61aded1 100644 --- a/src/plugins/diagram_overlay/qgsdiagramrenderer.h +++ b/src/plugins/diagram_overlay/qgsdiagramrenderer.h @@ -32,18 +32,18 @@ class QImage; //structure that describes a renderer entry class QgsDiagramItem { -public: - QVariant value; - int size; + public: + QVariant value; + int size; }; class QgsDiagramRenderer { - public: + public: - //describes how the items are interpreted for diagram size calculation - enum ItemInterpretation + //describes how the items are interpreted for diagram size calculation + enum ItemInterpretation { DISCRETE, //lower item is used if item falls between lower and upper item LINEAR, //linear interpolation between items containing the value @@ -51,64 +51,64 @@ class QgsDiagramRenderer CONSTANT //constant value is used (the size of the first item) }; - QgsDiagramRenderer(const QList& classificationAttributes); - virtual ~QgsDiagramRenderer(); - /**Returns a diagram image for a feature.*/ - virtual QImage* renderDiagram(const QgsFeature& f, const QgsRenderContext& renderContext) const; - /**Returns only the size of the diagram. - @param width the width of the diagram in pixels - @param height the height of the diagram in pixels - @param f feature that is associated with the diagram - @param context contains information about mm scale factor and dpi + QgsDiagramRenderer( const QList& classificationAttributes ); + virtual ~QgsDiagramRenderer(); + /**Returns a diagram image for a feature.*/ + virtual QImage* renderDiagram( const QgsFeature& f, const QgsRenderContext& renderContext ) const; + /**Returns only the size of the diagram. + @param width the width of the diagram in pixels + @param height the height of the diagram in pixels + @param f feature that is associated with the diagram + @param context contains information about mm scale factor and dpi + @return 0 in case of success*/ + virtual int getDiagramDimensions( int& width, int& height, const QgsFeature& f, const QgsRenderContext& renderContext ) const; + //setters and getters + QgsDiagramFactory* factory() const {return mFactory;} + /**Set a (properly configured) factory class. Takes ownership of the factory object*/ + void setFactory( QgsDiagramFactory* f ) {mFactory = f;} + void addClassificationAttribute( int attrNr ); + QList classificationAttributes() const {return mClassificationAttributes;} + /**Reads the specific renderer settings from project file*/ + virtual bool readXML( const QDomNode& rendererNode ); + /**Saves settings to project file. Returns true in case of success*/ + virtual bool writeXML( QDomNode& overlay_node, QDomDocument& doc ) const; + /**Creates pairs of strings / images for use in the legend @return 0 in case of success*/ - virtual int getDiagramDimensions(int& width, int& height, const QgsFeature& f, const QgsRenderContext& renderContext) const; - //setters and getters - QgsDiagramFactory* factory() const {return mFactory;} - /**Set a (properly configured) factory class. Takes ownership of the factory object*/ - void setFactory(QgsDiagramFactory* f){mFactory = f;} - void addClassificationAttribute(int attrNr); - QList classificationAttributes() const {return mClassificationAttributes;} - /**Reads the specific renderer settings from project file*/ - virtual bool readXML(const QDomNode& rendererNode); - /**Saves settings to project file. Returns true in case of success*/ - virtual bool writeXML(QDomNode& overlay_node, QDomDocument& doc) const; - /**Creates pairs of strings / images for use in the legend - @return 0 in case of success*/ - virtual int createLegendContent(const QgsRenderContext& renderContext, QMap items) const; - /**Sets the items for interpolation. The values of the items must be in ascending order*/ - void setDiagramItems(const QList& items) {mItems = items;} - /**Returns the interpolation items*/ - QList diagramItems() const {return mItems;} - void setItemInterpretation(ItemInterpretation i){mItemInterpretation = i;} - QgsDiagramRenderer::ItemInterpretation itemInterpretation() const {return mItemInterpretation;} - void setScaleFactor(double f){mScaleFactor = f;} + virtual int createLegendContent( const QgsRenderContext& renderContext, QMap items ) const; + /**Sets the items for interpolation. The values of the items must be in ascending order*/ + void setDiagramItems( const QList& items ) {mItems = items;} + /**Returns the interpolation items*/ + QList diagramItems() const {return mItems;} + void setItemInterpretation( ItemInterpretation i ) {mItemInterpretation = i;} + QgsDiagramRenderer::ItemInterpretation itemInterpretation() const {return mItemInterpretation;} + void setScaleFactor( double f ) {mScaleFactor = f;} - private: - QgsDiagramRenderer(); + private: + QgsDiagramRenderer(); - protected: - /**The object to generate the diagrams*/ - QgsDiagramFactory* mFactory; - /**Attributes for determining the size of the diagram. - If there are several attributes, their sum is used.*/ - QList mClassificationAttributes; - /**Value/size pairs for determination of the diagram size*/ - QList mItems; - /**Describes the type of interpolation (linear by default)*/ - ItemInterpretation mItemInterpretation; - /**Factor to multiply the sizes (e.g. used by QGIS mapserver dependent on the current scale)*/ - double mScaleFactor; + protected: + /**The object to generate the diagrams*/ + QgsDiagramFactory* mFactory; + /**Attributes for determining the size of the diagram. + If there are several attributes, their sum is used.*/ + QList mClassificationAttributes; + /**Value/size pairs for determination of the diagram size*/ + QList mItems; + /**Describes the type of interpolation (linear by default)*/ + ItemInterpretation mItemInterpretation; + /**Factor to multiply the sizes (e.g. used by QGIS mapserver dependent on the current scale)*/ + double mScaleFactor; - /**Searches the value of the classification attribute(s). Considers that there - may be several attributes in case of numeric values (sum). - @return 0 in case of success*/ - int classificationValue(const QgsFeature& f, QVariant& value) const; - /**Gets diagram size - @return 0 in case of success*/ - virtual int calculateDiagramSize(const QgsFeature& f, int& size) const; - /**Does (linear or discrete) interpolation*/ - int interpolateSize(double value, double lowerValue, double upperValue, int lowerSize, \ - int upperSize) const; + /**Searches the value of the classification attribute(s). Considers that there + may be several attributes in case of numeric values (sum). + @return 0 in case of success*/ + int classificationValue( const QgsFeature& f, QVariant& value ) const; + /**Gets diagram size + @return 0 in case of success*/ + virtual int calculateDiagramSize( const QgsFeature& f, int& size ) const; + /**Does (linear or discrete) interpolation*/ + int interpolateSize( double value, double lowerValue, double upperValue, int lowerSize, \ + int upperSize ) const; }; #endif diff --git a/src/plugins/diagram_overlay/qgsdiagramrendererwidget.cpp b/src/plugins/diagram_overlay/qgsdiagramrendererwidget.cpp index 4278356ea1f0..80eed7a4d92a 100644 --- a/src/plugins/diagram_overlay/qgsdiagramrendererwidget.cpp +++ b/src/plugins/diagram_overlay/qgsdiagramrendererwidget.cpp @@ -17,7 +17,7 @@ #include "qgsdiagramrendererwidget.h" -QgsDiagramRendererWidget::QgsDiagramRendererWidget(QgsVectorLayer* vl): QWidget(), mVectorLayer(vl) +QgsDiagramRendererWidget::QgsDiagramRendererWidget( QgsVectorLayer* vl ): QWidget(), mVectorLayer( vl ) { } diff --git a/src/plugins/diagram_overlay/qgsdiagramrendererwidget.h b/src/plugins/diagram_overlay/qgsdiagramrendererwidget.h index b84346b57df8..4a27efe303de 100644 --- a/src/plugins/diagram_overlay/qgsdiagramrendererwidget.h +++ b/src/plugins/diagram_overlay/qgsdiagramrendererwidget.h @@ -29,27 +29,27 @@ class QgsVectorLayer; given the classification attribute, the attributes involved in diagram creation and a set of colors for the attributes*/ class QgsDiagramRendererWidget: public QWidget { - public: - QgsDiagramRendererWidget(QgsVectorLayer* vl); - virtual ~QgsDiagramRendererWidget(); - /**Returns a subclass of QgsDiagramRenderer or 0 in case of error - @param type diagram type (e.g. Pie, Bar) - @param classAttr index of the classification attribute - @param attributes list of all attribute indices involved in diagram generation - @param color color series for the attributes*/ - virtual QgsDiagramRenderer* createRenderer(int classAttr, const QgsAttributeList& attributes) const = 0; - /**Applies the settings of an existing renderer*/ - virtual void applySettings(const QgsDiagramRenderer* renderer) = 0; - /**Possibility to adapt the dialog to a new field*/ - virtual void changeClassificationField(int newField){} - - virtual QgsDiagramFactory::SizeUnit sizeUnit() const {return QgsDiagramFactory::MM;} - - private: - QgsDiagramRendererWidget(); - - protected: - QgsVectorLayer* mVectorLayer; + public: + QgsDiagramRendererWidget( QgsVectorLayer* vl ); + virtual ~QgsDiagramRendererWidget(); + /**Returns a subclass of QgsDiagramRenderer or 0 in case of error + @param type diagram type (e.g. Pie, Bar) + @param classAttr index of the classification attribute + @param attributes list of all attribute indices involved in diagram generation + @param color color series for the attributes*/ + virtual QgsDiagramRenderer* createRenderer( int classAttr, const QgsAttributeList& attributes ) const = 0; + /**Applies the settings of an existing renderer*/ + virtual void applySettings( const QgsDiagramRenderer* renderer ) = 0; + /**Possibility to adapt the dialog to a new field*/ + virtual void changeClassificationField( int newField ) {} + + virtual QgsDiagramFactory::SizeUnit sizeUnit() const {return QgsDiagramFactory::MM;} + + private: + QgsDiagramRendererWidget(); + + protected: + QgsVectorLayer* mVectorLayer; }; #endif diff --git a/src/plugins/diagram_overlay/qgslinearlyscalingdialog.cpp b/src/plugins/diagram_overlay/qgslinearlyscalingdialog.cpp index 87cc9c3f3c98..69d8e8736404 100644 --- a/src/plugins/diagram_overlay/qgslinearlyscalingdialog.cpp +++ b/src/plugins/diagram_overlay/qgslinearlyscalingdialog.cpp @@ -21,12 +21,12 @@ #include "qgsbardiagramfactory.h" #include "qgspiediagramfactory.h" -QgsLinearlyScalingDialog::QgsLinearlyScalingDialog(QgsVectorLayer* vl): QgsDiagramRendererWidget(vl) +QgsLinearlyScalingDialog::QgsLinearlyScalingDialog( QgsVectorLayer* vl ): QgsDiagramRendererWidget( vl ) { - setupUi(this); - QObject::connect(mFindMaximumValueButton, SIGNAL(clicked()), this, SLOT(insertMaximumAttributeValue())); - mSizeUnitComboBox->addItem(tr("Millimeter")); - mSizeUnitComboBox->addItem(tr("Map units")); + setupUi( this ); + QObject::connect( mFindMaximumValueButton, SIGNAL( clicked() ), this, SLOT( insertMaximumAttributeValue() ) ); + mSizeUnitComboBox->addItem( tr( "Millimeter" ) ); + mSizeUnitComboBox->addItem( tr( "Map units" ) ); } QgsLinearlyScalingDialog::~QgsLinearlyScalingDialog() @@ -34,73 +34,73 @@ QgsLinearlyScalingDialog::~QgsLinearlyScalingDialog() } -QgsDiagramRenderer* QgsLinearlyScalingDialog::createRenderer(int classAttr, const QgsAttributeList& attributes) const +QgsDiagramRenderer* QgsLinearlyScalingDialog::createRenderer( int classAttr, const QgsAttributeList& attributes ) const { //create a linearly scaling renderer QList attributesList; - attributesList.push_back(classAttr); - QgsDiagramRenderer* renderer = new QgsDiagramRenderer(attributesList); - + attributesList.push_back( classAttr ); + QgsDiagramRenderer* renderer = new QgsDiagramRenderer( attributesList ); + //and items of renderer QList itemList; - QgsDiagramItem firstItem; firstItem.value = QVariant(0.0); firstItem.size = 0; - QgsDiagramItem secondItem; - secondItem.value = QVariant(mValueLineEdit->text().toDouble()); + QgsDiagramItem firstItem; firstItem.value = QVariant( 0.0 ); firstItem.size = 0; + QgsDiagramItem secondItem; + secondItem.value = QVariant( mValueLineEdit->text().toDouble() ); secondItem.size = mSizeSpinBox->value(); - itemList.push_back(firstItem); - itemList.push_back(secondItem); - renderer->setDiagramItems(itemList); - renderer->setItemInterpretation(QgsDiagramRenderer::LINEAR); + itemList.push_back( firstItem ); + itemList.push_back( secondItem ); + renderer->setDiagramItems( itemList ); + renderer->setItemInterpretation( QgsDiagramRenderer::LINEAR ); - return renderer; + return renderer; } -void QgsLinearlyScalingDialog::applySettings(const QgsDiagramRenderer* renderer) +void QgsLinearlyScalingDialog::applySettings( const QgsDiagramRenderer* renderer ) { - const QgsDiagramRenderer* linearRenderer = dynamic_cast(renderer); - if(linearRenderer) - { - QList itemList = linearRenderer->diagramItems(); - QgsDiagramItem theItem = itemList.at(1); //take the upper item - mValueLineEdit->setText(theItem.value.toString()); - mSizeSpinBox->setValue(theItem.size); + const QgsDiagramRenderer* linearRenderer = dynamic_cast( renderer ); + if ( linearRenderer ) + { + QList itemList = linearRenderer->diagramItems(); + QgsDiagramItem theItem = itemList.at( 1 ); //take the upper item + mValueLineEdit->setText( theItem.value.toString() ); + mSizeSpinBox->setValue( theItem.size ); - if(linearRenderer->factory()) + if ( linearRenderer->factory() ) + { + QgsDiagramFactory::SizeUnit sizeUnit = linearRenderer->factory()->sizeUnit(); + if ( sizeUnit == QgsDiagramFactory::MM ) + { + mSizeUnitComboBox->setCurrentIndex( mSizeUnitComboBox->findText( tr( "Millimeter" ) ) ); + } + else if ( sizeUnit == QgsDiagramFactory::MapUnits ) { - QgsDiagramFactory::SizeUnit sizeUnit = linearRenderer->factory()->sizeUnit(); - if(sizeUnit == QgsDiagramFactory::MM) - { - mSizeUnitComboBox->setCurrentIndex(mSizeUnitComboBox->findText(tr("Millimeter"))); - } - else if(sizeUnit == QgsDiagramFactory::MapUnits) - { - mSizeUnitComboBox->setCurrentIndex(mSizeUnitComboBox->findText(tr("Map units"))); - } - } + mSizeUnitComboBox->setCurrentIndex( mSizeUnitComboBox->findText( tr( "Map units" ) ) ); + } } + } } void QgsLinearlyScalingDialog::insertMaximumAttributeValue() { //find the maximum value for this attribute - if(mVectorLayer) + if ( mVectorLayer ) + { + QgsVectorDataProvider *provider = dynamic_cast( mVectorLayer->dataProvider() ); + if ( provider ) { - QgsVectorDataProvider *provider = dynamic_cast(mVectorLayer->dataProvider()); - if(provider) - { - mValueLineEdit->setText(provider->maximumValue(mClassificationField).toString()); - } + mValueLineEdit->setText( provider->maximumValue( mClassificationField ).toString() ); } + } } QgsDiagramFactory::SizeUnit QgsLinearlyScalingDialog::sizeUnit() const { - if(mSizeUnitComboBox->currentText() == tr("Map units")) - { - return QgsDiagramFactory::MapUnits; - } - else - { - return QgsDiagramFactory::MM; - } + if ( mSizeUnitComboBox->currentText() == tr( "Map units" ) ) + { + return QgsDiagramFactory::MapUnits; + } + else + { + return QgsDiagramFactory::MM; + } } diff --git a/src/plugins/diagram_overlay/qgslinearlyscalingdialog.h b/src/plugins/diagram_overlay/qgslinearlyscalingdialog.h index c46d4a878298..d20f7b9b03d5 100644 --- a/src/plugins/diagram_overlay/qgslinearlyscalingdialog.h +++ b/src/plugins/diagram_overlay/qgslinearlyscalingdialog.h @@ -26,26 +26,26 @@ class QgsVectorLayer; class QgsLinearlyScalingDialog: public QgsDiagramRendererWidget, private Ui::QgsLinearlyScalingDialogBase { - Q_OBJECT - public: - QgsLinearlyScalingDialog(QgsVectorLayer* vl); - ~QgsLinearlyScalingDialog(); - QgsDiagramRenderer* createRenderer(int classAttr, const QgsAttributeList& attributes) const; - void applySettings(const QgsDiagramRenderer* renderer); - /**Is called from QgsDiagramDialog. Inserts new maximum value into the text widget*/ - void changeClassificationField(int newField){mClassificationField = newField;} - void setWellKnownName(const QString& wkn); - - QgsDiagramFactory::SizeUnit sizeUnit() const; - - private: - QString mClassificationAttribute; - QString mWellKnownName; - int mClassificationField; + Q_OBJECT + public: + QgsLinearlyScalingDialog( QgsVectorLayer* vl ); + ~QgsLinearlyScalingDialog(); + QgsDiagramRenderer* createRenderer( int classAttr, const QgsAttributeList& attributes ) const; + void applySettings( const QgsDiagramRenderer* renderer ); + /**Is called from QgsDiagramDialog. Inserts new maximum value into the text widget*/ + void changeClassificationField( int newField ) {mClassificationField = newField;} + void setWellKnownName( const QString& wkn ); + + QgsDiagramFactory::SizeUnit sizeUnit() const; + + private: + QString mClassificationAttribute; + QString mWellKnownName; + int mClassificationField; private slots: - /**Calculates and inserts the maximum attribute value for the classification field*/ - void insertMaximumAttributeValue(); + /**Calculates and inserts the maximum attribute value for the classification field*/ + void insertMaximumAttributeValue(); }; #endif diff --git a/src/plugins/diagram_overlay/qgspiediagramfactory.cpp b/src/plugins/diagram_overlay/qgspiediagramfactory.cpp index b432d56be4ce..a038c591c732 100644 --- a/src/plugins/diagram_overlay/qgspiediagramfactory.cpp +++ b/src/plugins/diagram_overlay/qgspiediagramfactory.cpp @@ -25,22 +25,22 @@ QgsPieDiagramFactory::QgsPieDiagramFactory(): QgsWKNDiagramFactory() QgsPieDiagramFactory::~QgsPieDiagramFactory() { - + } -QImage* QgsPieDiagramFactory::createDiagram(int size, const QgsFeature& f, const QgsRenderContext& renderContext) const +QImage* QgsPieDiagramFactory::createDiagram( int size, const QgsFeature& f, const QgsRenderContext& renderContext ) const { QgsAttributeMap dataValues = f.attributeMap(); - double sizeScaleFactor = diagramSizeScaleFactor(renderContext); - + double sizeScaleFactor = diagramSizeScaleFactor( renderContext ); + //create transparent QImage - int imageSideLength = size * sizeScaleFactor * renderContext.rasterScaleFactor() + 2 * mMaximumPenWidth + 2 * mMaximumGap; - QImage* diagramImage = new QImage(QSize(imageSideLength, imageSideLength), QImage::Format_ARGB32_Premultiplied); - diagramImage->fill(qRgba(0, 0, 0, 0)); //transparent background + int imageSideLength = size * sizeScaleFactor * renderContext.rasterScaleFactor() + 2 * mMaximumPenWidth + 2 * mMaximumGap; + QImage* diagramImage = new QImage( QSize( imageSideLength, imageSideLength ), QImage::Format_ARGB32_Premultiplied ); + diagramImage->fill( qRgba( 0, 0, 0, 0 ) ); //transparent background QPainter p; - p.begin(diagramImage); - p.setRenderHint(QPainter::Antialiasing); - p.setPen(Qt::NoPen); + p.begin( diagramImage ); + p.setRenderHint( QPainter::Antialiasing ); + p.setPen( Qt::NoPen ); //calculate sum of data values double sum = 0; @@ -48,22 +48,22 @@ QImage* QgsPieDiagramFactory::createDiagram(int size, const QgsFeature& f, const QgsAttributeMap::const_iterator value_it; QList::const_iterator it = mCategories.constBegin(); - for(; it != mCategories.constEnd(); ++it) + for ( ; it != mCategories.constEnd(); ++it ) + { + value_it = dataValues.find( it->propertyIndex() ); + valueList.push_back( value_it->toDouble() ); + if ( value_it != dataValues.constEnd() ) { - value_it = dataValues.find(it->propertyIndex()); - valueList.push_back(value_it->toDouble()); - if(value_it != dataValues.constEnd()) - { - sum += value_it->toDouble(); - } + sum += value_it->toDouble(); } + } - if(sum - 0.0 < 0.000000000000001) - { - p.end(); - delete diagramImage; - return 0; - } + if ( sum - 0.0 < 0.000000000000001 ) + { + p.end(); + delete diagramImage; + return 0; + } //draw pies @@ -74,43 +74,43 @@ QImage* QgsPieDiagramFactory::createDiagram(int size, const QgsFeature& f, const QList::const_iterator category_it = mCategories.constBegin(); QList::const_iterator valueList_it = valueList.constBegin(); - - for(; category_it != mCategories.constEnd() && valueList_it != valueList.constEnd(); ++category_it, ++valueList_it) + + for ( ; category_it != mCategories.constEnd() && valueList_it != valueList.constEnd(); ++category_it, ++valueList_it ) + { + p.setPen( category_it->pen() ); + currentAngle = ( int )(( *valueList_it ) / sum * 360 * 16 ); + p.setBrush( category_it->brush() ); + + xGapOffset = 0; + yGapOffset = 0; + currentGap = category_it->gap(); + if ( currentGap != 0 ) { - p.setPen(category_it->pen()); - currentAngle = (int)((*valueList_it)/sum*360*16); - p.setBrush(category_it->brush()); - - xGapOffset = 0; - yGapOffset = 0; - currentGap = category_it->gap(); - if(currentGap != 0) - { - //qt angles are degrees*16 - gapOffsetsForPieSlice(currentGap, totalAngle + currentAngle/2, xGapOffset, yGapOffset); - } - - p.drawPie(mMaximumPenWidth * renderContext.rasterScaleFactor() + mMaximumGap + xGapOffset, mMaximumPenWidth * renderContext.rasterScaleFactor() + mMaximumGap - yGapOffset, sizeScaleFactor * renderContext.rasterScaleFactor() * size, sizeScaleFactor * renderContext.rasterScaleFactor() * size, totalAngle, currentAngle); - totalAngle += currentAngle; + //qt angles are degrees*16 + gapOffsetsForPieSlice( currentGap, totalAngle + currentAngle / 2, xGapOffset, yGapOffset ); } + + p.drawPie( mMaximumPenWidth * renderContext.rasterScaleFactor() + mMaximumGap + xGapOffset, mMaximumPenWidth * renderContext.rasterScaleFactor() + mMaximumGap - yGapOffset, sizeScaleFactor * renderContext.rasterScaleFactor() * size, sizeScaleFactor * renderContext.rasterScaleFactor() * size, totalAngle, currentAngle ); + totalAngle += currentAngle; + } p.end(); - + return diagramImage; } -int QgsPieDiagramFactory::getDiagramDimensions(int size, const QgsFeature& f, const QgsRenderContext& context, int& width, int& height) const +int QgsPieDiagramFactory::getDiagramDimensions( int size, const QgsFeature& f, const QgsRenderContext& context, int& width, int& height ) const { - double squareSide = size * diagramSizeScaleFactor(context) * context.rasterScaleFactor() + 2 * mMaximumPenWidth + 2 * mMaximumGap; - width = squareSide; - height = squareSide; - return 0; + double squareSide = size * diagramSizeScaleFactor( context ) * context.rasterScaleFactor() + 2 * mMaximumPenWidth + 2 * mMaximumGap; + width = squareSide; + height = squareSide; + return 0; } -int QgsPieDiagramFactory::gapOffsetsForPieSlice(int gap, int angle, int& xOffset, int& yOffset) const +int QgsPieDiagramFactory::gapOffsetsForPieSlice( int gap, int angle, int& xOffset, int& yOffset ) const { - double rad = angle/2880.0*M_PI; - xOffset = (int)(cos(rad) * gap); - yOffset = (int)(sin(rad) * gap); - + double rad = angle / 2880.0 * M_PI; + xOffset = ( int )( cos( rad ) * gap ); + yOffset = ( int )( sin( rad ) * gap ); + return 0; } diff --git a/src/plugins/diagram_overlay/qgspiediagramfactory.h b/src/plugins/diagram_overlay/qgspiediagramfactory.h index 47a627e06127..a462a5f3c07d 100644 --- a/src/plugins/diagram_overlay/qgspiediagramfactory.h +++ b/src/plugins/diagram_overlay/qgspiediagramfactory.h @@ -26,36 +26,36 @@ class QgsPieDiagramFactory: public QgsWKNDiagramFactory { - public: - QgsPieDiagramFactory(); - ~QgsPieDiagramFactory(); - - /**Creates a diagram for a feature and a given size. The size is usually determined by QgsDiagramRenderer. The calling method takes ownership of the generated image*/ - QImage* createDiagram(int size, const QgsFeature& f, const QgsRenderContext& renderContext) const; - - /**Creates items to show in the legend*/ - int createLegendContent(int size, const QgsRenderContext& renderContext, QString value, QMap& items) const{return 1;} //soon - - /**Gets the width and height (in pixels) of the diagram image. Considers different width, height values, the maximum width of the drawing pen and the conversion from mm size to pixels according to render context. - @param size diagram size calculated by diagram renderer (in mm) - @param f reference to the feature associated with the diagram - @param the render context (contains mm scale factor and raster scale factor) - @param width out: the width of the diagram image in pixels - @param height out: the height of the diagram image in pixels*/ - int getDiagramDimensions(int size, const QgsFeature& f, const QgsRenderContext& context, int& width, int& height) const; - - /**Returns the property described by the size (e.g. diameter or height). This can be important to - know if e.g. size has to be calculated proportional to pie area*/ - QgsDiagramFactory::SizeType sizeType() const {return QgsDiagramFactory::DIAMETER;} - - private: - /**Calculates the x- and y-offsets for pie gaps - @param gap the gap (in pixels) - @param angle azimut of pie slice (mean azimut of both pie angles), 0 - 5760 (degrees * 16) with 0 in 3 o'clock position and counterclockwise direction - @param xOffset out offset (in pixel) for x-direction - @param yOffset out offset (in pixel) for y-direction - @return 0 in case of success*/ - int gapOffsetsForPieSlice(int gap, int angle, int& xOffset, int& yOffset) const; + public: + QgsPieDiagramFactory(); + ~QgsPieDiagramFactory(); + + /**Creates a diagram for a feature and a given size. The size is usually determined by QgsDiagramRenderer. The calling method takes ownership of the generated image*/ + QImage* createDiagram( int size, const QgsFeature& f, const QgsRenderContext& renderContext ) const; + + /**Creates items to show in the legend*/ + int createLegendContent( int size, const QgsRenderContext& renderContext, QString value, QMap& items ) const {return 1;} //soon + + /**Gets the width and height (in pixels) of the diagram image. Considers different width, height values, the maximum width of the drawing pen and the conversion from mm size to pixels according to render context. + @param size diagram size calculated by diagram renderer (in mm) + @param f reference to the feature associated with the diagram + @param the render context (contains mm scale factor and raster scale factor) + @param width out: the width of the diagram image in pixels + @param height out: the height of the diagram image in pixels*/ + int getDiagramDimensions( int size, const QgsFeature& f, const QgsRenderContext& context, int& width, int& height ) const; + + /**Returns the property described by the size (e.g. diameter or height). This can be important to + know if e.g. size has to be calculated proportional to pie area*/ + QgsDiagramFactory::SizeType sizeType() const {return QgsDiagramFactory::DIAMETER;} + + private: + /**Calculates the x- and y-offsets for pie gaps + @param gap the gap (in pixels) + @param angle azimut of pie slice (mean azimut of both pie angles), 0 - 5760 (degrees * 16) with 0 in 3 o'clock position and counterclockwise direction + @param xOffset out offset (in pixel) for x-direction + @param yOffset out offset (in pixel) for y-direction + @return 0 in case of success*/ + int gapOffsetsForPieSlice( int gap, int angle, int& xOffset, int& yOffset ) const; }; -#endif +#endif diff --git a/src/plugins/diagram_overlay/qgssvgdiagramfactory.cpp b/src/plugins/diagram_overlay/qgssvgdiagramfactory.cpp index 25610021648d..67bbfa4d318c 100644 --- a/src/plugins/diagram_overlay/qgssvgdiagramfactory.cpp +++ b/src/plugins/diagram_overlay/qgssvgdiagramfactory.cpp @@ -22,15 +22,15 @@ QgsSVGDiagramFactory::QgsSVGDiagramFactory(): QgsDiagramFactory() { - + } QgsSVGDiagramFactory::~QgsSVGDiagramFactory() { - + } -QImage* QgsSVGDiagramFactory::createDiagram(int size, const QgsFeature& f, const QgsRenderContext& renderContext) const +QImage* QgsSVGDiagramFactory::createDiagram( int size, const QgsFeature& f, const QgsRenderContext& renderContext ) const { //check default size QSize defaultSize = mRenderer.defaultSize(); @@ -38,98 +38,98 @@ QImage* QgsSVGDiagramFactory::createDiagram(int size, const QgsFeature& f, const int imageWidth, imageHeight; //size parameter applies to maximum of width, height - if(defaultSize.width() >= defaultSize.height()) - { - scaleFactor = ((double)size * diagramSizeScaleFactor(renderContext) * renderContext.rasterScaleFactor()) / defaultSize.width(); - } + if ( defaultSize.width() >= defaultSize.height() ) + { + scaleFactor = (( double )size * diagramSizeScaleFactor( renderContext ) * renderContext.rasterScaleFactor() ) / defaultSize.width(); + } else - { - scaleFactor = ((double)size * diagramSizeScaleFactor(renderContext) * renderContext.rasterScaleFactor()) / defaultSize.height(); - } - - imageWidth = (int)(defaultSize.width() * scaleFactor); - imageHeight = (int)(defaultSize.height() * scaleFactor); - QImage* diagramImage = new QImage(QSize(imageWidth, imageHeight), QImage::Format_ARGB32_Premultiplied); - diagramImage->fill(qRgba(0, 0, 0, 0)); //transparent background - + { + scaleFactor = (( double )size * diagramSizeScaleFactor( renderContext ) * renderContext.rasterScaleFactor() ) / defaultSize.height(); + } + + imageWidth = ( int )( defaultSize.width() * scaleFactor ); + imageHeight = ( int )( defaultSize.height() * scaleFactor ); + QImage* diagramImage = new QImage( QSize( imageWidth, imageHeight ), QImage::Format_ARGB32_Premultiplied ); + diagramImage->fill( qRgba( 0, 0, 0, 0 ) ); //transparent background + QPainter p; - p.begin(diagramImage); - p.setRenderHint(QPainter::Antialiasing); + p.begin( diagramImage ); + p.setRenderHint( QPainter::Antialiasing ); //p.scale(scaleFactor, scaleFactor); //render image - mRenderer.render(&p); + mRenderer.render( &p ); p.end(); return diagramImage; } -int QgsSVGDiagramFactory::getDiagramDimensions(int size, const QgsFeature& f, const QgsRenderContext& context, int& width, int& height) const +int QgsSVGDiagramFactory::getDiagramDimensions( int size, const QgsFeature& f, const QgsRenderContext& context, int& width, int& height ) const { double scaleFactor; QSize defaultSize = mRenderer.defaultSize(); //size parameter applies to maximum of width, height - if(defaultSize.width() >= defaultSize.height()) - { - scaleFactor = ((double)size * diagramSizeScaleFactor(context) * context.rasterScaleFactor()) / defaultSize.width(); - } + if ( defaultSize.width() >= defaultSize.height() ) + { + scaleFactor = (( double )size * diagramSizeScaleFactor( context ) * context.rasterScaleFactor() ) / defaultSize.width(); + } else - { - scaleFactor = ((double)size * diagramSizeScaleFactor(context) * context.rasterScaleFactor()) / defaultSize.height(); - } - width = (int)(defaultSize.width() * scaleFactor); - height = (int)(defaultSize.height() * scaleFactor); - return 0; + { + scaleFactor = (( double )size * diagramSizeScaleFactor( context ) * context.rasterScaleFactor() ) / defaultSize.height(); + } + width = ( int )( defaultSize.width() * scaleFactor ); + height = ( int )( defaultSize.height() * scaleFactor ); + return 0; } -bool QgsSVGDiagramFactory::setSVGData(const QByteArray& data, const QString& filePath) +bool QgsSVGDiagramFactory::setSVGData( const QByteArray& data, const QString& filePath ) { mSvgFilePath = filePath; - return mRenderer.load(data); + return mRenderer.load( data ); } -bool QgsSVGDiagramFactory::writeXML(QDomNode& overlay_node, QDomDocument& doc) const +bool QgsSVGDiagramFactory::writeXML( QDomNode& overlay_node, QDomDocument& doc ) const { - QDomElement factoryElem = doc.createElement("factory"); - factoryElem.setAttribute("type", "svg"); - //add size units as an attribute to the factory element - writeSizeUnits(factoryElem, doc); - - QDomElement svgPathElem = doc.createElement("svgPath"); - QDomText svgPathText = doc.createTextNode(mSvgFilePath); - svgPathElem.appendChild(svgPathText); - factoryElem.appendChild(svgPathElem); - overlay_node.appendChild(factoryElem); - - return true; + QDomElement factoryElem = doc.createElement( "factory" ); + factoryElem.setAttribute( "type", "svg" ); + //add size units as an attribute to the factory element + writeSizeUnits( factoryElem, doc ); + + QDomElement svgPathElem = doc.createElement( "svgPath" ); + QDomText svgPathText = doc.createTextNode( mSvgFilePath ); + svgPathElem.appendChild( svgPathText ); + factoryElem.appendChild( svgPathElem ); + overlay_node.appendChild( factoryElem ); + + return true; } -bool QgsSVGDiagramFactory::readXML(const QDomNode& factoryNode) +bool QgsSVGDiagramFactory::readXML( const QDomNode& factoryNode ) { - QDomElement factoryElem = factoryNode.toElement(); - if(factoryElem.isNull()) - { - return false; - } - - //size units - readSizeUnits(factoryElem); - - //get element - QDomElement svgPathElem = factoryElem.namedItem("svgPath").toElement(); - if(svgPathElem.isNull()) - { - return false; - } - - QString svgFilePath = svgPathElem.text(); - if(!mRenderer.load(svgFilePath)) - { - return false; - } - mSvgFilePath = svgFilePath; - - return true; + QDomElement factoryElem = factoryNode.toElement(); + if ( factoryElem.isNull() ) + { + return false; + } + + //size units + readSizeUnits( factoryElem ); + + //get element + QDomElement svgPathElem = factoryElem.namedItem( "svgPath" ).toElement(); + if ( svgPathElem.isNull() ) + { + return false; + } + + QString svgFilePath = svgPathElem.text(); + if ( !mRenderer.load( svgFilePath ) ) + { + return false; + } + mSvgFilePath = svgFilePath; + + return true; } diff --git a/src/plugins/diagram_overlay/qgssvgdiagramfactory.h b/src/plugins/diagram_overlay/qgssvgdiagramfactory.h index 8e691b9e8f9b..426966bdba55 100644 --- a/src/plugins/diagram_overlay/qgssvgdiagramfactory.h +++ b/src/plugins/diagram_overlay/qgssvgdiagramfactory.h @@ -23,48 +23,48 @@ class QgsSVGDiagramFactory: public QgsDiagramFactory { - public: - QgsSVGDiagramFactory(); - ~QgsSVGDiagramFactory(); + public: + QgsSVGDiagramFactory(); + ~QgsSVGDiagramFactory(); - /**Creates the diagram image for a feature in order to be placed on the map - @param size diagram size (may be height, diameter, squaresize depending on diagram type - @param f feature that is symbolized by the diagram - @param renderContext rendering parameters*/ - QImage* createDiagram(int size, const QgsFeature& f, const QgsRenderContext& renderContext) const; - /**Creates the text/images for the legend items. The caller takes ownership of the generated \ - image objects. - @param size diagram size that should be represented in the legend - @param renderContext rendering parameters - @param value diagram value that should be represented in the legend - @param items generated items - @return 0 in case of success*/ - int createLegendContent(int size, const QgsRenderContext& renderContext, QString value, QMap& items) const {return 1;} //later... - - /**Gets the width and height (in pixels) of the diagram image. Considers different width, height values, the maximum width of the drawing pen and the conversion from mm size to pixels according to render context. - @param size diagram size calculated by diagram renderer - @param f reference to the feature associated with the diagram - @param the render context (contains mm scale factor and raster scale factor) - @param width out: the width of the diagram image in pixels - @param height out: the height of the diagram image in pixels*/ - int getDiagramDimensions(int size, const QgsFeature& f, const QgsRenderContext& context, int& width, int& height) const; + /**Creates the diagram image for a feature in order to be placed on the map + @param size diagram size (may be height, diameter, squaresize depending on diagram type + @param f feature that is symbolized by the diagram + @param renderContext rendering parameters*/ + QImage* createDiagram( int size, const QgsFeature& f, const QgsRenderContext& renderContext ) const; + /**Creates the text/images for the legend items. The caller takes ownership of the generated \ + image objects. + @param size diagram size that should be represented in the legend + @param renderContext rendering parameters + @param value diagram value that should be represented in the legend + @param items generated items + @return 0 in case of success*/ + int createLegendContent( int size, const QgsRenderContext& renderContext, QString value, QMap& items ) const {return 1;} //later... - bool writeXML(QDomNode& overlay_node, QDomDocument& doc) const; + /**Gets the width and height (in pixels) of the diagram image. Considers different width, height values, the maximum width of the drawing pen and the conversion from mm size to pixels according to render context. + @param size diagram size calculated by diagram renderer + @param f reference to the feature associated with the diagram + @param the render context (contains mm scale factor and raster scale factor) + @param width out: the width of the diagram image in pixels + @param height out: the height of the diagram image in pixels*/ + int getDiagramDimensions( int size, const QgsFeature& f, const QgsRenderContext& context, int& width, int& height ) const; - /**Sets the SVG data to be rendered. - @return true in case of success*/ - bool setSVGData(const QByteArray& data, const QString& filePath = ""); + bool writeXML( QDomNode& overlay_node, QDomDocument& doc ) const; - QString svgFilePath() const {return mSvgFilePath;} + /**Sets the SVG data to be rendered. + @return true in case of success*/ + bool setSVGData( const QByteArray& data, const QString& filePath = "" ); - /**Read settings from project file*/ - bool readXML(const QDomNode& factoryNode); + QString svgFilePath() const {return mSvgFilePath;} - private: - mutable QSvgRenderer mRenderer; + /**Read settings from project file*/ + bool readXML( const QDomNode& factoryNode ); - /**Path to the current svg file. Mainly for the purpose of inserting the path into a newly created dialog*/ - QString mSvgFilePath; + private: + mutable QSvgRenderer mRenderer; + + /**Path to the current svg file. Mainly for the purpose of inserting the path into a newly created dialog*/ + QString mSvgFilePath; }; #endif diff --git a/src/plugins/diagram_overlay/qgssvgdiagramfactorywidget.cpp b/src/plugins/diagram_overlay/qgssvgdiagramfactorywidget.cpp index 66e77af4c1b4..7ec316f10b3b 100644 --- a/src/plugins/diagram_overlay/qgssvgdiagramfactorywidget.cpp +++ b/src/plugins/diagram_overlay/qgssvgdiagramfactorywidget.cpp @@ -26,10 +26,10 @@ QgsSVGDiagramFactoryWidget::QgsSVGDiagramFactoryWidget(): QgsDiagramFactoryWidget() { - setupUi(this); + setupUi( this ); - //add preview icons - addStandardDirectoriesToPreview(); + //add preview icons + addStandardDirectoriesToPreview(); } QgsSVGDiagramFactoryWidget::~QgsSVGDiagramFactoryWidget() @@ -39,43 +39,43 @@ QgsSVGDiagramFactoryWidget::~QgsSVGDiagramFactoryWidget() QgsDiagramFactory* QgsSVGDiagramFactoryWidget::createFactory() { - QString filePath = mPictureLineEdit->text(); - if(filePath.isEmpty()) - { - return 0; - } + QString filePath = mPictureLineEdit->text(); + if ( filePath.isEmpty() ) + { + return 0; + } - QFile svgFile(filePath); - if(!svgFile.exists()) - { - return 0; - } + QFile svgFile( filePath ); + if ( !svgFile.exists() ) + { + return 0; + } - //open file and read binary array - if(!svgFile.open(QIODevice::ReadOnly)) - { - return 0; - } + //open file and read binary array + if ( !svgFile.open( QIODevice::ReadOnly ) ) + { + return 0; + } - QByteArray svgData = svgFile.readAll(); + QByteArray svgData = svgFile.readAll(); - QgsSVGDiagramFactory* factory = new QgsSVGDiagramFactory(); - if(!factory->setSVGData(svgData, filePath)) - { - delete factory; return 0; - } + QgsSVGDiagramFactory* factory = new QgsSVGDiagramFactory(); + if ( !factory->setSVGData( svgData, filePath ) ) + { + delete factory; return 0; + } - return factory; + return factory; } -void QgsSVGDiagramFactoryWidget::setExistingFactory(const QgsDiagramFactory* f) +void QgsSVGDiagramFactoryWidget::setExistingFactory( const QgsDiagramFactory* f ) { - mPreviewListWidget->setLayoutDirection(Qt::LeftToRight); - const QgsSVGDiagramFactory* svgFactory = dynamic_cast(f); - if(svgFactory) - { - mPictureLineEdit->setText(svgFactory->svgFilePath()); - } + mPreviewListWidget->setLayoutDirection( Qt::LeftToRight ); + const QgsSVGDiagramFactory* svgFactory = dynamic_cast( f ); + if ( svgFactory ) + { + mPictureLineEdit->setText( svgFactory->svgFilePath() ); + } } void QgsSVGDiagramFactoryWidget::on_mPictureBrowseButton_clicked() @@ -105,11 +105,11 @@ void QgsSVGDiagramFactoryWidget::on_mPictureBrowseButton_clicked() } //check if it is a valid svg file - if(!testSvgFile(filePath)) - { - QMessageBox::critical( 0, "Invalid file", "Error, the selected file is not a valid svg file" ); + if ( !testSvgFile( filePath ) ) + { + QMessageBox::critical( 0, "Invalid file", "Error, the selected file is not a valid svg file" ); return; - } + } mPictureLineEdit->blockSignals( true ); mPictureLineEdit->setText( filePath ); @@ -118,96 +118,96 @@ void QgsSVGDiagramFactoryWidget::on_mPictureBrowseButton_clicked() void QgsSVGDiagramFactoryWidget::on_mPreviewListWidget_currentItemChanged( QListWidgetItem* current, QListWidgetItem* previous ) { - if(!current) + if ( !current ) { return; } - QString absoluteFilePath = current->data(Qt::UserRole).toString(); - mPictureLineEdit->setText(absoluteFilePath); + QString absoluteFilePath = current->data( Qt::UserRole ).toString(); + mPictureLineEdit->setText( absoluteFilePath ); } void QgsSVGDiagramFactoryWidget::on_mAddDirectoryButton_clicked() { //let user select a directory - QString directory = QFileDialog::getExistingDirectory(0, tr("Select new preview directory")); - if(directory.isNull()) + QString directory = QFileDialog::getExistingDirectory( 0, tr( "Select new preview directory" ) ); + if ( directory.isNull() ) { return; //dialog canceled by user } //add entry to mSearchDirectoriesComboBox - mSearchDirectoriesComboBox->addItem(directory); + mSearchDirectoriesComboBox->addItem( directory ); //and add icons to the preview - addDirectoryToPreview(directory); + addDirectoryToPreview( directory ); } void QgsSVGDiagramFactoryWidget::on_mRemoveDirectoryButton_clicked() { QString directoryToRemove = mSearchDirectoriesComboBox->currentText(); - mSearchDirectoriesComboBox->removeItem(mSearchDirectoriesComboBox->currentIndex()); + mSearchDirectoriesComboBox->removeItem( mSearchDirectoriesComboBox->currentIndex() ); //remove entries from back to front (to have the indices of existing items constant) - for(int i = (mPreviewListWidget->count() - 1); i >=0; --i) + for ( int i = ( mPreviewListWidget->count() - 1 ); i >= 0; --i ) { - QListWidgetItem* currentItem = mPreviewListWidget->item(i); - if(currentItem && currentItem->data(Qt::UserRole).toString().startsWith(directoryToRemove)) + QListWidgetItem* currentItem = mPreviewListWidget->item( i ); + if ( currentItem && currentItem->data( Qt::UserRole ).toString().startsWith( directoryToRemove ) ) { - delete(mPreviewListWidget->takeItem(i)); + delete( mPreviewListWidget->takeItem( i ) ); } } } -int QgsSVGDiagramFactoryWidget::addDirectoryToPreview(const QString& path) +int QgsSVGDiagramFactoryWidget::addDirectoryToPreview( const QString& path ) { //go through all files of a directory - QDir directory(path); - if(!directory.exists() || !directory.isReadable()) + QDir directory( path ); + if ( !directory.exists() || !directory.isReadable() ) { return 1; //error } - QFileInfoList fileList = directory.entryInfoList(QDir::Files); + QFileInfoList fileList = directory.entryInfoList( QDir::Files ); QFileInfoList::const_iterator fileIt = fileList.constBegin(); - QProgressDialog progress("Adding Icons...", "Abort", 0, fileList.size() - 1, this); + QProgressDialog progress( "Adding Icons...", "Abort", 0, fileList.size() - 1, this ); //cancel button does not seem to work properly with modal dialog //progress.setWindowModality(Qt::WindowModal); int counter = 0; - for(; fileIt != fileList.constEnd(); ++fileIt) + for ( ; fileIt != fileList.constEnd(); ++fileIt ) { - progress.setLabelText(tr("Creating icon for file ") + fileIt->fileName()); - progress.setValue(counter); + progress.setLabelText( tr( "Creating icon for file " ) + fileIt->fileName() ); + progress.setValue( counter ); QCoreApplication::processEvents(); - if(progress.wasCanceled()) + if ( progress.wasCanceled() ) { break; } QString filePath = fileIt->absoluteFilePath(); //test if file is svg or pixel format - bool fileIsSvg = testSvgFile(filePath); + bool fileIsSvg = testSvgFile( filePath ); //exclude files that are not svg or image - if(!fileIsSvg) + if ( !fileIsSvg ) { ++counter; continue; } - QListWidgetItem * listItem = new QListWidgetItem(mPreviewListWidget); + QListWidgetItem * listItem = new QListWidgetItem( mPreviewListWidget ); - if(fileIsSvg) + if ( fileIsSvg ) { - QIcon icon(filePath); - listItem->setIcon(icon); + QIcon icon( filePath ); + listItem->setIcon( icon ); } listItem->setText( "" ); //store the absolute icon file path as user data - listItem->setData( Qt::UserRole, fileIt->absoluteFilePath()); + listItem->setData( Qt::UserRole, fileIt->absoluteFilePath() ); ++counter; } @@ -217,27 +217,27 @@ int QgsSVGDiagramFactoryWidget::addDirectoryToPreview(const QString& path) void QgsSVGDiagramFactoryWidget::addStandardDirectoriesToPreview() { //list all directories in $prefix/share/qgis/svg - QDir svgDirectory(QgsApplication::svgPath()); - if(!svgDirectory.exists() || !svgDirectory.isReadable()) + QDir svgDirectory( QgsApplication::svgPath() ); + if ( !svgDirectory.exists() || !svgDirectory.isReadable() ) { - return; //error + return; //error } - QFileInfoList directoryList = svgDirectory.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot); + QFileInfoList directoryList = svgDirectory.entryInfoList( QDir::Dirs | QDir::NoDotAndDotDot ); QFileInfoList::const_iterator dirIt = directoryList.constBegin(); - for(; dirIt != directoryList.constEnd(); ++dirIt) + for ( ; dirIt != directoryList.constEnd(); ++dirIt ) { - if(addDirectoryToPreview(dirIt->absoluteFilePath()) == 0) + if ( addDirectoryToPreview( dirIt->absoluteFilePath() ) == 0 ) { - mSearchDirectoriesComboBox->addItem(dirIt->absoluteFilePath()); + mSearchDirectoriesComboBox->addItem( dirIt->absoluteFilePath() ); } } } -bool QgsSVGDiagramFactoryWidget::testSvgFile(const QString& filename) const +bool QgsSVGDiagramFactoryWidget::testSvgFile( const QString& filename ) const { - QSvgRenderer svgRenderer(filename); - if(svgRenderer.isValid()) + QSvgRenderer svgRenderer( filename ); + if ( svgRenderer.isValid() ) { return true; } diff --git a/src/plugins/diagram_overlay/qgssvgdiagramfactorywidget.h b/src/plugins/diagram_overlay/qgssvgdiagramfactorywidget.h index 24d25df49a19..e12ef67e1d2f 100644 --- a/src/plugins/diagram_overlay/qgssvgdiagramfactorywidget.h +++ b/src/plugins/diagram_overlay/qgssvgdiagramfactorywidget.h @@ -27,27 +27,27 @@ class QgsSVGDiagramFactoryWidget: public QgsDiagramFactoryWidget, private Ui::Qg { Q_OBJECT - public: + public: QgsSVGDiagramFactoryWidget(); ~QgsSVGDiagramFactoryWidget(); QgsDiagramFactory* createFactory(); - void setExistingFactory(const QgsDiagramFactory* f); + void setExistingFactory( const QgsDiagramFactory* f ); - public slots: + public slots: void on_mPictureBrowseButton_clicked(); void on_mPreviewListWidget_currentItemChanged( QListWidgetItem* current, QListWidgetItem* previous ); void on_mAddDirectoryButton_clicked(); void on_mRemoveDirectoryButton_clicked(); - private: + private: /**Add the icons of a directory to the preview. Returns 0 in case of success*/ - int addDirectoryToPreview(const QString& path); + int addDirectoryToPreview( const QString& path ); /**Add the icons of the standard directories to the preview*/ void addStandardDirectoriesToPreview(); /**Tests if a file is valid svg*/ - bool testSvgFile(const QString& filename) const; + bool testSvgFile( const QString& filename ) const; }; #endif diff --git a/src/plugins/diagram_overlay/qgswkndiagramfactory.cpp b/src/plugins/diagram_overlay/qgswkndiagramfactory.cpp index 72a3add0ccf0..25c670eae263 100644 --- a/src/plugins/diagram_overlay/qgswkndiagramfactory.cpp +++ b/src/plugins/diagram_overlay/qgswkndiagramfactory.cpp @@ -26,175 +26,175 @@ #include #include -QgsWKNDiagramFactory::QgsWKNDiagramFactory(): QgsDiagramFactory(), mMaximumPenWidth(0),mMaximumGap(0) +QgsWKNDiagramFactory::QgsWKNDiagramFactory(): QgsDiagramFactory(), mMaximumPenWidth( 0 ), mMaximumGap( 0 ) { - + } QgsWKNDiagramFactory::~QgsWKNDiagramFactory() { - + } -void QgsWKNDiagramFactory::supportedWellKnownNames(std::list& names) +void QgsWKNDiagramFactory::supportedWellKnownNames( std::list& names ) { names.clear(); - names.push_back("Pie"); - names.push_back("Bar"); + names.push_back( "Pie" ); + names.push_back( "Bar" ); } -bool QgsWKNDiagramFactory::writeXML(QDomNode& overlay_node, QDomDocument& doc) const +bool QgsWKNDiagramFactory::writeXML( QDomNode& overlay_node, QDomDocument& doc ) const { QDomElement overlayElement = overlay_node.toElement(); - QDomElement factoryElement = doc.createElement("factory"); - factoryElement.setAttribute("type", diagramType()); - //add size units as an attribute to the factory element - writeSizeUnits(factoryElement, doc); - overlay_node.appendChild(factoryElement); + QDomElement factoryElement = doc.createElement( "factory" ); + factoryElement.setAttribute( "type", diagramType() ); + //add size units as an attribute to the factory element + writeSizeUnits( factoryElement, doc ); + overlay_node.appendChild( factoryElement ); //well known name - QDomElement wellKnownNameElem = doc.createElement("wellknownname"); - QDomText wknText = doc.createTextNode(mDiagramType); - wellKnownNameElem.appendChild(wknText); - factoryElement.appendChild(wellKnownNameElem); + QDomElement wellKnownNameElem = doc.createElement( "wellknownname" ); + QDomText wknText = doc.createTextNode( mDiagramType ); + wellKnownNameElem.appendChild( wknText ); + factoryElement.appendChild( wellKnownNameElem ); //classification fields QList::const_iterator scaling_it = mScalingAttributes.constBegin(); - for(; scaling_it != mScalingAttributes.constEnd(); ++scaling_it) - { - QDomElement classificationFieldElem = doc.createElement("classificationfield"); - QDomText classFieldText = doc.createTextNode(QString::number(*scaling_it)); - classificationFieldElem.appendChild(classFieldText); - factoryElement.appendChild(classificationFieldElem); - } + for ( ; scaling_it != mScalingAttributes.constEnd(); ++scaling_it ) + { + QDomElement classificationFieldElem = doc.createElement( "classificationfield" ); + QDomText classFieldText = doc.createTextNode( QString::number( *scaling_it ) ); + classificationFieldElem.appendChild( classFieldText ); + factoryElement.appendChild( classificationFieldElem ); + } //diagram categories QList::const_iterator c_it = mCategories.constBegin(); - for(; c_it != mCategories.constEnd(); ++c_it) - { - QDomElement currentCategoryElem = doc.createElement("category"); - currentCategoryElem.setAttribute("gap", QString::number(c_it->gap())); - currentCategoryElem.setAttribute("attribute", QString::number(c_it->propertyIndex())) ; - - //brush - QDomElement currentBrushElem = doc.createElement("brush"); - currentBrushElem.setAttribute("red", QString::number(c_it->brush().color().red())); - currentBrushElem.setAttribute("green", QString::number(c_it->brush().color().green())); - currentBrushElem.setAttribute("blue", QString::number(c_it->brush().color().blue())); - currentBrushElem.setAttribute("style", QgsSymbologyUtils::brushStyle2QString(c_it->brush().style())); - - //pen - QDomElement currentPenElem = doc.createElement("pen"); - currentPenElem.setAttribute("red", QString::number(c_it->pen().color().red())); - currentPenElem.setAttribute("green", QString::number(c_it->pen().color().green())); - currentPenElem.setAttribute("blue", QString::number(c_it->pen().color().blue())); - currentPenElem.setAttribute("width", QString::number(c_it->pen().width())); - currentPenElem.setAttribute("style", QgsSymbologyUtils::penStyle2QString(c_it->pen().style())); - - currentCategoryElem.appendChild(currentBrushElem); - currentCategoryElem.appendChild(currentPenElem); - - factoryElement.appendChild(currentCategoryElem); - } + for ( ; c_it != mCategories.constEnd(); ++c_it ) + { + QDomElement currentCategoryElem = doc.createElement( "category" ); + currentCategoryElem.setAttribute( "gap", QString::number( c_it->gap() ) ); + currentCategoryElem.setAttribute( "attribute", QString::number( c_it->propertyIndex() ) ) ; + + //brush + QDomElement currentBrushElem = doc.createElement( "brush" ); + currentBrushElem.setAttribute( "red", QString::number( c_it->brush().color().red() ) ); + currentBrushElem.setAttribute( "green", QString::number( c_it->brush().color().green() ) ); + currentBrushElem.setAttribute( "blue", QString::number( c_it->brush().color().blue() ) ); + currentBrushElem.setAttribute( "style", QgsSymbologyUtils::brushStyle2QString( c_it->brush().style() ) ); + + //pen + QDomElement currentPenElem = doc.createElement( "pen" ); + currentPenElem.setAttribute( "red", QString::number( c_it->pen().color().red() ) ); + currentPenElem.setAttribute( "green", QString::number( c_it->pen().color().green() ) ); + currentPenElem.setAttribute( "blue", QString::number( c_it->pen().color().blue() ) ); + currentPenElem.setAttribute( "width", QString::number( c_it->pen().width() ) ); + currentPenElem.setAttribute( "style", QgsSymbologyUtils::penStyle2QString( c_it->pen().style() ) ); + + currentCategoryElem.appendChild( currentBrushElem ); + currentCategoryElem.appendChild( currentPenElem ); + + factoryElement.appendChild( currentCategoryElem ); + } //write subclass specific information - _writeXML(factoryElement, doc); + _writeXML( factoryElement, doc ); return true; } -void QgsWKNDiagramFactory::addCategory(QgsDiagramCategory c) +void QgsWKNDiagramFactory::addCategory( QgsDiagramCategory c ) { - mCategories.push_back(c); - + mCategories.push_back( c ); + //update the maximum pen width if necessary (for proper diagram scaling) int currentPenWidth = c.pen().width(); int currentGap = c.gap(); - if(mMaximumPenWidth < currentPenWidth) - { - mMaximumPenWidth = currentPenWidth; - } - - if(currentGap > mMaximumGap) - { - mMaximumGap = currentGap; - } + if ( mMaximumPenWidth < currentPenWidth ) + { + mMaximumPenWidth = currentPenWidth; + } + + if ( currentGap > mMaximumGap ) + { + mMaximumGap = currentGap; + } } QgsAttributeList QgsWKNDiagramFactory::categoryAttributes() const { - QgsAttributeList categoryAttList; - QList::const_iterator it = mCategories.constBegin(); - for(; it != mCategories.constEnd(); ++it) - { - categoryAttList.push_back(it->propertyIndex()); - } - return categoryAttList; + QgsAttributeList categoryAttList; + QList::const_iterator it = mCategories.constBegin(); + for ( ; it != mCategories.constEnd(); ++it ) + { + categoryAttList.push_back( it->propertyIndex() ); + } + return categoryAttList; } -bool QgsWKNDiagramFactory::readXML(const QDomNode& factoryNode) +bool QgsWKNDiagramFactory::readXML( const QDomNode& factoryNode ) { - QDomElement factoryElem = factoryNode.toElement(); - if(factoryElem.isNull()) - { - return false; - } - - //size units - readSizeUnits(factoryElem); - - //wellknownname - QDomNodeList wknNodeList = factoryElem.elementsByTagName("wellknownname"); - if(wknNodeList.size() < 1) - { - return false; - } - mDiagramType = wknNodeList.at(0).toElement().text(); + QDomElement factoryElem = factoryNode.toElement(); + if ( factoryElem.isNull() ) + { + return false; + } + + //size units + readSizeUnits( factoryElem ); + + //wellknownname + QDomNodeList wknNodeList = factoryElem.elementsByTagName( "wellknownname" ); + if ( wknNodeList.size() < 1 ) + { + return false; + } + mDiagramType = wknNodeList.at( 0 ).toElement().text(); //categories mCategories.clear(); int red, green, blue; QDomElement categoryElem, penElem, brushElem; - QDomNodeList categoryList = factoryElem.elementsByTagName("category"); + QDomNodeList categoryList = factoryElem.elementsByTagName( "category" ); //todo: mMaximumGap, mMaximumPenWidth - for(int i = 0; i < categoryList.size(); ++i) + for ( int i = 0; i < categoryList.size(); ++i ) + { + categoryElem = categoryList.at( i ).toElement(); + + QgsDiagramCategory newCategory; + newCategory.setPropertyIndex( categoryElem.attribute( "attribute" ).toInt() ); + newCategory.setGap( categoryElem.attribute( "gap" ).toInt() ); + + //pen element + penElem = categoryElem.namedItem( "pen" ).toElement(); + if ( !penElem.isNull() ) + { + QPen currentPen; + red = penElem.attribute( "red" ).toInt(); + green = penElem.attribute( "green" ).toInt(); + blue = penElem.attribute( "blue" ).toInt(); + currentPen.setColor( QColor( red, green, blue ) ); + currentPen.setStyle( QgsSymbologyUtils::qString2PenStyle( penElem.attribute( "style" ) ) ); + newCategory.setPen( currentPen ); + } + + //brush element + brushElem = categoryElem.namedItem( "brush" ).toElement(); + if ( !brushElem.isNull() ) { - categoryElem = categoryList.at(i).toElement(); - - QgsDiagramCategory newCategory; - newCategory.setPropertyIndex(categoryElem.attribute("attribute").toInt()); - newCategory.setGap(categoryElem.attribute("gap").toInt()); - - //pen element - penElem = categoryElem.namedItem("pen").toElement(); - if(!penElem.isNull()) - { - QPen currentPen; - red = penElem.attribute("red").toInt(); - green = penElem.attribute("green").toInt(); - blue = penElem.attribute("blue").toInt(); - currentPen.setColor(QColor(red, green, blue)); - currentPen.setStyle(QgsSymbologyUtils::qString2PenStyle(penElem.attribute("style"))); - newCategory.setPen(currentPen); - } - - //brush element - brushElem = categoryElem.namedItem("brush").toElement(); - if(!brushElem.isNull()) - { - QBrush currentBrush; - red = brushElem.attribute("red").toInt(); - green = brushElem.attribute("green").toInt(); - blue = brushElem.attribute("blue").toInt(); - currentBrush.setColor(QColor(red, green, blue)); - currentBrush.setStyle(QgsSymbologyUtils::qString2BrushStyle(brushElem.attribute("style"))); - newCategory.setBrush(currentBrush); - } - mCategories.push_back(newCategory); + QBrush currentBrush; + red = brushElem.attribute( "red" ).toInt(); + green = brushElem.attribute( "green" ).toInt(); + blue = brushElem.attribute( "blue" ).toInt(); + currentBrush.setColor( QColor( red, green, blue ) ); + currentBrush.setStyle( QgsSymbologyUtils::qString2BrushStyle( brushElem.attribute( "style" ) ) ); + newCategory.setBrush( currentBrush ); } + mCategories.push_back( newCategory ); + } return true; } diff --git a/src/plugins/diagram_overlay/qgswkndiagramfactory.h b/src/plugins/diagram_overlay/qgswkndiagramfactory.h index b51dd6c8ef7f..9c6e3c6fbfc5 100644 --- a/src/plugins/diagram_overlay/qgswkndiagramfactory.h +++ b/src/plugins/diagram_overlay/qgswkndiagramfactory.h @@ -35,45 +35,45 @@ class QgsFeature; (pie, bar)*/ class QgsWKNDiagramFactory: public QgsDiagramFactory { - public: - QgsWKNDiagramFactory(); - virtual ~QgsWKNDiagramFactory(); + public: + QgsWKNDiagramFactory(); + virtual ~QgsWKNDiagramFactory(); - /**Writes the wkn diagram information into a tag*/ - bool writeXML(QDomNode& overlay_node, QDomDocument& doc) const; - /**Possibility for wkn subclasses to write specific information into the XML document*/ - virtual bool _writeXML(QDomNode& factory_node, QDomDocument& doc) const {return true;} - /**Returns the property described by the size (e.g. diameter or height). This can be important to - know if e.g. size has to be calculated proportional to pie area*/ - virtual QgsDiagramFactory::SizeType sizeType() const = 0; + /**Writes the wkn diagram information into a tag*/ + bool writeXML( QDomNode& overlay_node, QDomDocument& doc ) const; + /**Possibility for wkn subclasses to write specific information into the XML document*/ + virtual bool _writeXML( QDomNode& factory_node, QDomDocument& doc ) const {return true;} + /**Returns the property described by the size (e.g. diameter or height). This can be important to + know if e.g. size has to be calculated proportional to pie area*/ + virtual QgsDiagramFactory::SizeType sizeType() const = 0; - //setters and getters for diagram type - QString diagramType() const {return mDiagramType;} - void setDiagramType(const QString& name){mDiagramType = name;} - - QList categories() const {return mCategories;} - /**Adds a new category (attribute together with symbolisation)*/ - void addCategory(QgsDiagramCategory c); + //setters and getters for diagram type + QString diagramType() const {return mDiagramType;} + void setDiagramType( const QString& name ) {mDiagramType = name;} - /**Returns the attribute indexes represented in the bars/pie slices*/ - QgsAttributeList categoryAttributes() const; - - /**Returns the supported well known names in a list*/ - static void supportedWellKnownNames(std::list& names); + QList categories() const {return mCategories;} + /**Adds a new category (attribute together with symbolisation)*/ + void addCategory( QgsDiagramCategory c ); - /**Read wkn settings from project file*/ - bool readXML(const QDomNode& factoryNode); + /**Returns the attribute indexes represented in the bars/pie slices*/ + QgsAttributeList categoryAttributes() const; - protected: + /**Returns the supported well known names in a list*/ + static void supportedWellKnownNames( std::list& names ); - /**Well known diagram name (e.g. pie, bar, line)*/ - QString mDiagramType; - /**List of attributes that are represented as slices, pillars, etc.*/ - QList mCategories; - /**Maximum line width. Needs to be considered for the size of the generated image*/ - int mMaximumPenWidth; - /**Maximum Gap. Needs to be considered for the size of the generated image*/ - int mMaximumGap; + /**Read wkn settings from project file*/ + bool readXML( const QDomNode& factoryNode ); + + protected: + + /**Well known diagram name (e.g. pie, bar, line)*/ + QString mDiagramType; + /**List of attributes that are represented as slices, pillars, etc.*/ + QList mCategories; + /**Maximum line width. Needs to be considered for the size of the generated image*/ + int mMaximumPenWidth; + /**Maximum Gap. Needs to be considered for the size of the generated image*/ + int mMaximumGap; }; #endif diff --git a/src/plugins/diagram_overlay/qgswkndiagramfactorywidget.cpp b/src/plugins/diagram_overlay/qgswkndiagramfactorywidget.cpp index cade4101b109..f42cff4ac073 100644 --- a/src/plugins/diagram_overlay/qgswkndiagramfactorywidget.cpp +++ b/src/plugins/diagram_overlay/qgswkndiagramfactorywidget.cpp @@ -23,36 +23,36 @@ #include "qgspiediagramfactory.h" #include -QgsWKNDiagramFactoryWidget::QgsWKNDiagramFactoryWidget(QgsVectorLayer* vl, const QString& wellKnownName): QgsDiagramFactoryWidget(), mVectorLayer(vl), mDiagramTypeName(wellKnownName) +QgsWKNDiagramFactoryWidget::QgsWKNDiagramFactoryWidget( QgsVectorLayer* vl, const QString& wellKnownName ): QgsDiagramFactoryWidget(), mVectorLayer( vl ), mDiagramTypeName( wellKnownName ) { - setupUi(this); - - QStringList headerLabels; - headerLabels << "Attribute"; - headerLabels << "Color"; - mAttributesTreeWidget->setHeaderLabels(headerLabels); - QObject::connect(mAddPushButton, SIGNAL(clicked()), this, SLOT(addAttribute())); - QObject::connect(mRemovePushButton, SIGNAL(clicked()), this, SLOT(removeAttribute())); - QObject::connect(mAttributesTreeWidget, SIGNAL(itemDoubleClicked( QTreeWidgetItem*, int)), this, SLOT(handleItemDoubleClick(QTreeWidgetItem*, int))); - - //insert attributes into combo box - QgsVectorDataProvider *provider; - if ((provider = dynamic_cast(mVectorLayer->dataProvider()))) + setupUi( this ); + + QStringList headerLabels; + headerLabels << "Attribute"; + headerLabels << "Color"; + mAttributesTreeWidget->setHeaderLabels( headerLabels ); + QObject::connect( mAddPushButton, SIGNAL( clicked() ), this, SLOT( addAttribute() ) ); + QObject::connect( mRemovePushButton, SIGNAL( clicked() ), this, SLOT( removeAttribute() ) ); + QObject::connect( mAttributesTreeWidget, SIGNAL( itemDoubleClicked( QTreeWidgetItem*, int ) ), this, SLOT( handleItemDoubleClick( QTreeWidgetItem*, int ) ) ); + + //insert attributes into combo box + QgsVectorDataProvider *provider; + if (( provider = dynamic_cast( mVectorLayer->dataProvider() ) ) ) + { + const QgsFieldMap & fields = provider->fields(); + QString str; + + int comboIndex = 0; + for ( QgsFieldMap::const_iterator it = fields.begin(); it != fields.end(); ++it ) { - const QgsFieldMap & fields = provider->fields(); - QString str; - - int comboIndex = 0; - for (QgsFieldMap::const_iterator it = fields.begin(); it != fields.end(); ++it) - { - str = (*it).name(); - mAttributesComboBox->insertItem(comboIndex, str); - ++comboIndex; - } + str = ( *it ).name(); + mAttributesComboBox->insertItem( comboIndex, str ); + ++comboIndex; } + } } -QgsWKNDiagramFactoryWidget::QgsWKNDiagramFactoryWidget(): mVectorLayer(0) +QgsWKNDiagramFactoryWidget::QgsWKNDiagramFactoryWidget(): mVectorLayer( 0 ) { } @@ -63,100 +63,100 @@ QgsWKNDiagramFactoryWidget::~QgsWKNDiagramFactoryWidget() QgsDiagramFactory* QgsWKNDiagramFactoryWidget::createFactory() { - QgsWKNDiagramFactory* f = 0;//new QgsWKNDiagramFactory(); - if(mDiagramTypeName == "Bar") - { - f = new QgsBarDiagramFactory(); - } - else if(mDiagramTypeName == "Pie") - { - f = new QgsPieDiagramFactory(); - } + QgsWKNDiagramFactory* f = 0;//new QgsWKNDiagramFactory(); + if ( mDiagramTypeName == "Bar" ) + { + f = new QgsBarDiagramFactory(); + } + else if ( mDiagramTypeName == "Pie" ) + { + f = new QgsPieDiagramFactory(); + } else - { - return 0; //unknown diagram type - } - f->setDiagramType(mDiagramTypeName); + { + return 0; //unknown diagram type + } + f->setDiagramType( mDiagramTypeName ); int topLevelItemCount = mAttributesTreeWidget->topLevelItemCount(); QTreeWidgetItem* currentItem = 0; int currentAttribute = -1; - for(int i = 0; i < topLevelItemCount; ++i) + for ( int i = 0; i < topLevelItemCount; ++i ) + { + currentItem = mAttributesTreeWidget->topLevelItem( i ); + currentAttribute = QgsDiagramOverlay::indexFromAttributeName( currentItem->text( 0 ), mVectorLayer ); + if ( currentAttribute != -1 ) { - currentItem = mAttributesTreeWidget->topLevelItem(i); - currentAttribute = QgsDiagramOverlay::indexFromAttributeName(currentItem->text(0), mVectorLayer); - if(currentAttribute != -1) - { - QgsDiagramCategory newCategory; - newCategory.setPropertyIndex(currentAttribute); - newCategory.setBrush(QBrush(currentItem->background(1).color())); - f->addCategory(newCategory); - } + QgsDiagramCategory newCategory; + newCategory.setPropertyIndex( currentAttribute ); + newCategory.setBrush( QBrush( currentItem->background( 1 ).color() ) ); + f->addCategory( newCategory ); } + } - return f; + return f; } -void QgsWKNDiagramFactoryWidget::setExistingFactory(const QgsDiagramFactory* f) +void QgsWKNDiagramFactoryWidget::setExistingFactory( const QgsDiagramFactory* f ) { - const QgsWKNDiagramFactory* existingWKNFactory = dynamic_cast(f); - if(existingWKNFactory) + const QgsWKNDiagramFactory* existingWKNFactory = dynamic_cast( f ); + if ( existingWKNFactory ) + { + //insert attribute names and colors into mAttributesTreeWidget + mAttributesTreeWidget->clear(); + //insert attribute names and colors into mAttributesTreeWidget + QList categoryList = existingWKNFactory->categories(); + QList::const_iterator c_it = categoryList.constBegin(); + + for ( ; c_it != categoryList.constEnd(); ++c_it ) { - //insert attribute names and colors into mAttributesTreeWidget - mAttributesTreeWidget->clear(); - //insert attribute names and colors into mAttributesTreeWidget - QList categoryList = existingWKNFactory->categories(); - QList::const_iterator c_it = categoryList.constBegin(); - - for(; c_it != categoryList.constEnd(); ++c_it) - { - QTreeWidgetItem* newItem = new QTreeWidgetItem(mAttributesTreeWidget); - newItem->setText(0, QgsDiagramOverlay::attributeNameFromIndex(c_it->propertyIndex(), mVectorLayer)); - newItem->setBackground(1, c_it->brush()); - mAttributesTreeWidget->addTopLevelItem(newItem); - } + QTreeWidgetItem* newItem = new QTreeWidgetItem( mAttributesTreeWidget ); + newItem->setText( 0, QgsDiagramOverlay::attributeNameFromIndex( c_it->propertyIndex(), mVectorLayer ) ); + newItem->setBackground( 1, c_it->brush() ); + mAttributesTreeWidget->addTopLevelItem( newItem ); } + } } void QgsWKNDiagramFactoryWidget::addAttribute() { - QTreeWidgetItem* newItem = new QTreeWidgetItem(mAttributesTreeWidget); + QTreeWidgetItem* newItem = new QTreeWidgetItem( mAttributesTreeWidget ); //text QString currentText = mAttributesComboBox->currentText(); - newItem->setText(0, currentText); + newItem->setText( 0, currentText ); //and icon - int red = 1 + (int) (255.0 * rand() / (RAND_MAX + 1.0)); - int green = 1 + (int) (255.0 * rand() / (RAND_MAX + 1.0)); - int blue = 1 + (int) (255.0 * rand() / (RAND_MAX + 1.0)); - QColor randomColor(red, green, blue); - newItem->setBackground(1, QBrush(randomColor)); - - if(!currentText.isNull() && !currentText.isEmpty()) - { - mAttributesTreeWidget->addTopLevelItem(newItem); - } + int red = 1 + ( int )( 255.0 * rand() / ( RAND_MAX + 1.0 ) ); + int green = 1 + ( int )( 255.0 * rand() / ( RAND_MAX + 1.0 ) ); + int blue = 1 + ( int )( 255.0 * rand() / ( RAND_MAX + 1.0 ) ); + QColor randomColor( red, green, blue ); + newItem->setBackground( 1, QBrush( randomColor ) ); + + if ( !currentText.isNull() && !currentText.isEmpty() ) + { + mAttributesTreeWidget->addTopLevelItem( newItem ); + } } void QgsWKNDiagramFactoryWidget::removeAttribute() { QTreeWidgetItem* currentItem = mAttributesTreeWidget->currentItem(); - if(currentItem) - { - delete currentItem; - } + if ( currentItem ) + { + delete currentItem; + } } -void QgsWKNDiagramFactoryWidget::handleItemDoubleClick(QTreeWidgetItem * item, int column) +void QgsWKNDiagramFactoryWidget::handleItemDoubleClick( QTreeWidgetItem * item, int column ) { - if(column == 1) //change color + if ( column == 1 ) //change color + { + QColor newColor = QColorDialog::getColor(); + if ( newColor.isValid() ) { - QColor newColor = QColorDialog::getColor(); - if(newColor.isValid()) - { - item->setBackground(1, QBrush(newColor)); - } + item->setBackground( 1, QBrush( newColor ) ); } + } } diff --git a/src/plugins/diagram_overlay/qgswkndiagramfactorywidget.h b/src/plugins/diagram_overlay/qgswkndiagramfactorywidget.h index 0effbba6efbc..31b1897cafe1 100644 --- a/src/plugins/diagram_overlay/qgswkndiagramfactorywidget.h +++ b/src/plugins/diagram_overlay/qgswkndiagramfactorywidget.h @@ -28,28 +28,28 @@ class QgsVectorLayer; class QgsWKNDiagramFactoryWidget: public QgsDiagramFactoryWidget, private Ui::QgsWKNDiagramFactoryWidgetBase { Q_OBJECT - public: + public: /**Creates a */ - QgsWKNDiagramFactoryWidget(QgsVectorLayer* vl, const QString& wellKnownName); + QgsWKNDiagramFactoryWidget( QgsVectorLayer* vl, const QString& wellKnownName ); ~QgsWKNDiagramFactoryWidget(); QgsDiagramFactory* createFactory(); - void setExistingFactory(const QgsDiagramFactory* f); + void setExistingFactory( const QgsDiagramFactory* f ); - private: + private: QgsWKNDiagramFactoryWidget(); QgsVectorLayer* mVectorLayer; QString mDiagramTypeName; - private slots: - /**Adds name of the attribute combo box into the tree widget*/ - void addAttribute(); - /**Removes the current attribute from the tree widget*/ - void removeAttribute(); - /**Calls the color dialog if column == 1*/ - void handleItemDoubleClick(QTreeWidgetItem * item, int column); + private slots: + /**Adds name of the attribute combo box into the tree widget*/ + void addAttribute(); + /**Removes the current attribute from the tree widget*/ + void removeAttribute(); + /**Calls the color dialog if column == 1*/ + void handleItemDoubleClick( QTreeWidgetItem * item, int column ); }; #endif diff --git a/src/plugins/interpolation/qgstininterpolator.cpp b/src/plugins/interpolation/qgstininterpolator.cpp index 0d88a4f6d603..96b7212c8953 100644 --- a/src/plugins/interpolation/qgstininterpolator.cpp +++ b/src/plugins/interpolation/qgstininterpolator.cpp @@ -65,18 +65,18 @@ void QgsTINInterpolator::initialize() DualEdgeTriangulation* theDualEdgeTriangulation = new DualEdgeTriangulation( mCachedBaseData.size(), 0 ); mTriangulation = theDualEdgeTriangulation; - //do some randomisation on the base data to have better results with regular structures - vertexData vertex1, vertex2; + //do some randomisation on the base data to have better results with regular structures + vertexData vertex1, vertex2; - for(int i = 0; i <= mCachedBaseData.size() / 2; ++i) + for ( int i = 0; i <= mCachedBaseData.size() / 2; ++i ) { - vertex1 = mCachedBaseData[i]; - Point3D* thePoint1 = new Point3D( vertex1.x, vertex1.y, vertex1.z ); - mTriangulation->addPoint( thePoint1 ); - vertex2 = mCachedBaseData[mCachedBaseData.size() - 1 - i]; - Point3D* thePoint2 = new Point3D( vertex2.x, vertex2.y, vertex2.z ); - mTriangulation->addPoint( thePoint2 ); - } + vertex1 = mCachedBaseData[i]; + Point3D* thePoint1 = new Point3D( vertex1.x, vertex1.y, vertex1.z ); + mTriangulation->addPoint( thePoint1 ); + vertex2 = mCachedBaseData[mCachedBaseData.size() - 1 - i]; + Point3D* thePoint2 = new Point3D( vertex2.x, vertex2.y, vertex2.z ); + mTriangulation->addPoint( thePoint2 ); + } #if 0 //add all the vertices to the triangulation diff --git a/src/plugins/qgsapplydialog.h b/src/plugins/qgsapplydialog.h index b40d3c98669a..fcc3b7e27e04 100644 --- a/src/plugins/qgsapplydialog.h +++ b/src/plugins/qgsapplydialog.h @@ -23,8 +23,8 @@ class QgsApplyDialog: public QDialog { public: - QgsApplyDialog(): QDialog(){} - ~QgsApplyDialog(){} + QgsApplyDialog(): QDialog() {} + ~QgsApplyDialog() {} virtual void apply() const = 0; }; diff --git a/src/plugins/qgsvectoroverlayplugin.cpp b/src/plugins/qgsvectoroverlayplugin.cpp index 8d1c8b69c3fc..d3f5a12faa99 100644 --- a/src/plugins/qgsvectoroverlayplugin.cpp +++ b/src/plugins/qgsvectoroverlayplugin.cpp @@ -1 +1 @@ - + diff --git a/src/plugins/qgsvectoroverlayplugin.h b/src/plugins/qgsvectoroverlayplugin.h index 3a9fcc4c5959..4a27cbe88092 100644 --- a/src/plugins/qgsvectoroverlayplugin.h +++ b/src/plugins/qgsvectoroverlayplugin.h @@ -1,10 +1,10 @@ - /*************************************************************************** - qgsvectoroverlayplugin.h - description - ------------------------ - begin : January 2007 - copyright : (C) 2007 by Marco Hugentobler - email : marco dot hugentobler at karto dot baug dot ethz dot ch - ***************************************************************************/ +/*************************************************************************** + qgsvectoroverlayplugin.h - description + ------------------------ + begin : January 2007 + copyright : (C) 2007 by Marco Hugentobler + email : marco dot hugentobler at karto dot baug dot ethz dot ch +***************************************************************************/ /*************************************************************************** * * @@ -27,13 +27,13 @@ class QWidget; /**Interface class for vector overlay plugins*/ class QgsVectorOverlayPlugin: public QgisPlugin { - public: - QgsVectorOverlayPlugin(const QString& name, const QString& description, const QString& version): QgisPlugin(name, description, version, QgisPlugin::VECTOR_OVERLAY){} + public: + QgsVectorOverlayPlugin( const QString& name, const QString& description, const QString& version ): QgisPlugin( name, description, version, QgisPlugin::VECTOR_OVERLAY ) {} - virtual ~QgsVectorOverlayPlugin(){} + virtual ~QgsVectorOverlayPlugin() {} - /**Returns a dialog which can be embedded into the vector layer properties*/ - virtual QgsApplyDialog* dialog(QgsVectorLayer* vl) const = 0; + /**Returns a dialog which can be embedded into the vector layer properties*/ + virtual QgsApplyDialog* dialog( QgsVectorLayer* vl ) const = 0; }; #endif