[QGIS Commit] r11207 - in branches/symbology-ng-branch/src: core core/pal plugins/labeling

svn_qgis at osgeo.org svn_qgis at osgeo.org
Wed Jul 29 20:32:21 EDT 2009


Author: wonder
Date: 2009-07-29 20:32:20 -0400 (Wed, 29 Jul 2009)
New Revision: 11207

Modified:
   branches/symbology-ng-branch/src/core/pal/costcalculator.cpp
   branches/symbology-ng-branch/src/core/pal/feature.cpp
   branches/symbology-ng-branch/src/core/pal/feature.h
   branches/symbology-ng-branch/src/core/pal/internalexception.h
   branches/symbology-ng-branch/src/core/pal/labelposition.cpp
   branches/symbology-ng-branch/src/core/pal/labelposition.h
   branches/symbology-ng-branch/src/core/pal/layer.cpp
   branches/symbology-ng-branch/src/core/pal/layer.h
   branches/symbology-ng-branch/src/core/pal/pal.cpp
   branches/symbology-ng-branch/src/core/pal/pal.h
   branches/symbology-ng-branch/src/core/pal/palexception.h
   branches/symbology-ng-branch/src/core/pal/pointset.cpp
   branches/symbology-ng-branch/src/core/pal/pointset.h
   branches/symbology-ng-branch/src/core/pal/problem.cpp
   branches/symbology-ng-branch/src/core/pal/util.cpp
   branches/symbology-ng-branch/src/core/pal/util.h
   branches/symbology-ng-branch/src/core/qgspalobjectpositionmanager.cpp
   branches/symbology-ng-branch/src/plugins/labeling/pallabeling.cpp
Log:
Much needed refactoring and code cleanups in PAL.

Removed temporary "Feat" class used for conversion of geometries from GEOS.
Renamed "Feature" class to FeaturePart as it only represents on feature part.
Added Feature class which contains common properties among feature parts.
Greatly simplified registration of features in Layer.
Simplified Layer interface.


Modified: branches/symbology-ng-branch/src/core/pal/costcalculator.cpp
===================================================================
--- branches/symbology-ng-branch/src/core/pal/costcalculator.cpp	2009-07-29 21:04:58 UTC (rev 11206)
+++ branches/symbology-ng-branch/src/core/pal/costcalculator.cpp	2009-07-30 00:32:20 UTC (rev 11207)
@@ -129,7 +129,6 @@
     // center
     //cost = feat->getDistInside((this->x[0] + this->x[2])/2.0, (this->y[0] + this->y[2])/2.0 );
 
-    lp->feature->fetchCoordinates();
     pCost->update( lp->feature );
 
     PointSet *extent = new PointSet( 4, bbx, bby );
@@ -144,7 +143,6 @@
 
     lp->setCost( pCost->getCost() );
 
-    lp->feature->releaseCoordinates();
     delete pCost;
   }
 

Modified: branches/symbology-ng-branch/src/core/pal/feature.cpp
===================================================================
--- branches/symbology-ng-branch/src/core/pal/feature.cpp	2009-07-29 21:04:58 UTC (rev 11206)
+++ branches/symbology-ng-branch/src/core/pal/feature.cpp	2009-07-30 00:32:20 UTC (rev 11207)
@@ -60,103 +60,198 @@
 
 namespace pal
 {
+  Feature::Feature(Layer* l, const char* geom_id, PalGeometry* userG, double lx, double ly)
+    : layer(l), userGeom(userG), label_x(lx), label_y(ly), distlabel(0), labelInfo(NULL)
+  {
+    uid = new char[strlen( geom_id ) +1];
+    strcpy( uid, geom_id );
+  }
 
-  Feature::Feature( Feat *feat, Layer *layer, int part, int nPart, PalGeometry *userGeom ) :
-      layer( layer ), nPart( nPart ), part( part ), userGeom( userGeom )
+  Feature::~Feature()
   {
+    delete[] uid;
+  }
 
-    this->uid = new char[strlen( feat->id ) +1];
-    strcpy( this->uid, feat->id );
+  ////////////
 
-    label_x = -1;
-    label_y = -1;
-    labelInfo = NULL;
+  FeaturePart::FeaturePart( Feature *feat, const GEOSGeometry* geom )
+   : f(feat), nbHoles(0), holes(NULL)
+  {
+    extractCoords(geom);
 
-    xmin = feat->minmax[0];
-    xmax = feat->minmax[2];
-    ymin = feat->minmax[1];
-    ymax = feat->minmax[3];
+    holeOf = NULL;
+    for ( int i = 0;i < nbHoles;i++ )
+    {
+      holes[i]->holeOf = this;
+    }
+  }
 
-    nbPoints = feat->nbPoints;
-    x = feat->x;
-    y = feat->y;
 
+  FeaturePart::~FeaturePart()
+  {
+    // X and Y are deleted in PointSet
 
-    int i;
+    if (holes)
+    {
+      for ( int i = 0; i < nbHoles;i++ )
+        delete holes[i];
+      delete [] holes;
+      holes = NULL;
+    }
+  }
 
 
-    nbSelfObs = feat->nbHoles;
-    selfObs = feat->holes;
+/*
+ * \brief read coordinates from a GEOS geom
+ */
+void FeaturePart::extractCoords( const GEOSGeometry* geom )
+{
+  int i, j;
 
-    holeOf = NULL;
-    for ( i = 0;i < nbSelfObs;i++ )
+  const GEOSCoordSequence *coordSeq;
+
+  type = GEOSGeomTypeId( geom );
+
+  if ( type == GEOS_POLYGON )
+  {
+    if ( GEOSGetNumInteriorRings( geom ) > 0 )
     {
-      selfObs[i]->holeOf = this;
-    }
+      // set nbHoles, holes member variables
+      nbHoles = GEOSGetNumInteriorRings( geom );
+      holes = new PointSet*[nbHoles];
 
+      for ( i = 0;i < nbHoles;i++ )
+      {
+        holes[i] = new PointSet();
+        holes[i]->holeOf = NULL;
 
-    this->type = feat->type;
+        const GEOSGeometry* interior =  GEOSGetInteriorRingN( geom, i );
+        holes[i]->nbPoints = GEOSGetNumCoordinates( interior );
+        holes[i]->x = new double[holes[i]->nbPoints];
+        holes[i]->y = new double[holes[i]->nbPoints];
 
-#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;
+        holes[i]->xmin = holes[i]->ymin = DBL_MAX;
+        holes[i]->xmax = holes[i]->ymax = -DBL_MAX;
+
+        coordSeq = GEOSGeom_getCoordSeq( interior );
+
+        for ( j = 0;j < holes[i]->nbPoints;j++ )
+        {
+          GEOSCoordSeq_getX( coordSeq, j, &holes[i]->x[j] );
+          GEOSCoordSeq_getY( coordSeq, j, &holes[i]->y[j] );
+
+          holes[i]->xmax = holes[i]->x[j] > holes[i]->xmax ? holes[i]->x[j] : holes[i]->xmax;
+          holes[i]->xmin = holes[i]->x[j] < holes[i]->xmin ? holes[i]->x[j] : holes[i]->xmin;
+
+          holes[i]->ymax = holes[i]->y[j] > holes[i]->ymax ? holes[i]->y[j] : holes[i]->ymax;
+          holes[i]->ymin = holes[i]->y[j] < holes[i]->ymin ? holes[i]->y[j] : holes[i]->ymin;
+        }
+
+        reorderPolygon( holes[i]->nbPoints, holes[i]->x, holes[i]->y );
+      }
     }
-#endif
 
-    distlabel = 0;
-    currentAccess = 0;
+    // use exterior ring for the extraction of coordinates that follows
+    geom = GEOSGetExteriorRing( geom );
+  }
+  else
+  {
+    nbHoles = 0;
+    holes = NULL;
+  }
 
-    accessMutex = new SimpleMutex();
+  // find out number of points
+  nbPoints = GEOSGetNumCoordinates( geom );
+  coordSeq = GEOSGeom_getCoordSeq( geom );
+
+  // initialize bounding box
+  xmin = ymin = DBL_MAX;
+  xmax = ymax = -DBL_MAX;
+
+  // initialize coordinate arrays
+  x = new double[nbPoints];
+  y = new double[nbPoints];
+
+  for ( i = 0;i < nbPoints;i++ )
+  {
+    GEOSCoordSeq_getX( coordSeq, i, &x[i] );
+    GEOSCoordSeq_getY( coordSeq, i, &y[i] );
+
+    xmax = x[i] > xmax ? x[i] : xmax;
+    xmin = x[i] < xmin ? x[i] : xmin;
+
+    ymax = y[i] > ymax ? y[i] : ymax;
+    ymin = y[i] < ymin ? y[i] : ymin;
   }
+}
 
+void FeaturePart::removeDuplicatePoints()
+{
+  // TODO add simplify() process
+  int new_nbPoints = nbPoints;
+  bool *ok = new bool[new_nbPoints];
+  int i,j;
 
-  Feature::~Feature()
+  for ( i = 0;i < nbPoints;i++ )
   {
-    if ( x || y )
+    ok[i] = true;
+    j = ( i + 1 ) % nbPoints;
+    if ( i == j )
+      break;
+    if ( vabs( x[i] - x[j] ) < 0.0000001 && vabs( y[i] - y[j] ) < 0.0000001 )
     {
-      std::cout << "Warning: coordinates not released: " << layer->name << "/" << uid << std::endl;
+      new_nbPoints--;
+      ok[i] = false;
     }
+  }
 
-    if ( uid )
+  if ( new_nbPoints < nbPoints )
+  {
+    double *new_x = new double[new_nbPoints];
+    double *new_y = new double[new_nbPoints];
+    for ( i = 0, j = 0;i < nbPoints;i++ )
     {
-      delete[] uid;
-    }
-
-    if ( nbSelfObs )
-    {
-      int i;
-      for ( i = 0;i < nbSelfObs;i++ )
+      if ( ok[i] )
       {
-        if ( selfObs[i]->x || selfObs[i]->y )
-        {
-          std::cout << "Warning: hole coordinates not released" << std::endl;
-        }
-        delete selfObs[i];
+        new_x[j] = x[i];
+        new_y[j] = y[i];
+        j++;
       }
-      delete[] selfObs;
     }
-
-    delete accessMutex;
+    delete[] x;
+    delete[] y;
+    // interchange the point arrays
+    x = new_x;
+    y = new_y;
+    nbPoints = new_nbPoints;
   }
 
-  Layer *Feature::getLayer()
+  delete[] ok;
+}
+
+
+
+
+  Layer *FeaturePart::getLayer()
   {
-    return layer;
+    return f->layer;
   }
 
 
-  const char * Feature::getUID()
+  const char * FeaturePart::getUID()
   {
-    return uid;
+    return f->uid;
   }
 
-  int Feature::setPositionOverPoint( double x, double y, double scale, LabelPosition ***lPos, double delta_width )
+  int FeaturePart::setPositionOverPoint( double x, double y, double scale, LabelPosition ***lPos, double delta_width )
   {
     int nbp = 3;
     *lPos = new LabelPosition *[nbp];
 
+    // get from feature
+    double label_x = f->label_x;
+    double label_y = f->label_y;
+
     double lx = x - label_x / 2;
     double ly = y - label_y / 2;
     double cost = 0.0001;
@@ -174,30 +269,31 @@
     return nbp;
   }
 
-  int Feature::setPositionForPoint( double x, double y, double scale, LabelPosition ***lPos, double delta_width )
+  int FeaturePart::setPositionForPoint( double x, double y, double scale, LabelPosition ***lPos, double delta_width )
   {
 
 #ifdef _DEBUG_
     std::cout << "SetPosition (point) : " << layer->name << "/" << uid << std::endl;
 #endif
 
-    int dpi = layer->pal->dpi;
+    int dpi = f->layer->pal->dpi;
 
 
     double xrm;
     double yrm;
+    double distlabel = f->distlabel;
 
-    xrm = unit_convert( label_x,
-                        layer->label_unit,
-                        layer->pal->map_unit,
+    xrm = unit_convert( f->label_x,
+                        f->layer->label_unit,
+                        f->layer->pal->map_unit,
                         dpi, scale, delta_width );
 
-    yrm = unit_convert( label_y,
-                        layer->label_unit,
-                        layer->pal->map_unit,
+    yrm = unit_convert( f->label_y,
+                        f->layer->label_unit,
+                        f->layer->pal->map_unit,
                         dpi, scale, delta_width );
 
-    int nbp = layer->pal->point_p;
+    int nbp = f->layer->pal->point_p;
 
     //std::cout << "Nbp : " << nbp << std::endl;
 
@@ -338,23 +434,24 @@
   }
 
 // 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 FeaturePart::setPositionForLine( double scale, LabelPosition ***lPos, PointSet *mapShape, double delta_width )
   {
 #ifdef _DEBUG_
     std::cout << "SetPosition (line) : " << layer->name << "/" << uid << std::endl;
 #endif
     int i;
-    int dpi = layer->pal->dpi;
+    int dpi = f->layer->pal->dpi;
     double xrm, yrm;
+    double distlabel = f->distlabel;
 
-    xrm = unit_convert( label_x,
-                        layer->label_unit,
-                        layer->pal->map_unit,
+    xrm = unit_convert( f->label_x,
+                        f->layer->label_unit,
+                        f->layer->pal->map_unit,
                         dpi, scale, delta_width );
 
-    yrm = unit_convert( label_y,
-                        layer->label_unit,
-                        layer->pal->map_unit,
+    yrm = unit_convert( f->label_y,
+                        f->layer->label_unit,
+                        f->layer->pal->map_unit,
                         dpi, scale, delta_width );
 
 
@@ -373,7 +470,7 @@
     double alpha;
     double cost;
 
-    unsigned long flags = layer->getArrangementFlags();
+    unsigned long flags = f->layer->getArrangementFlags();
     if ( flags == 0 )
       flags = FLAG_ON_LINE; // default flag
     bool reversed = false;
@@ -482,7 +579,7 @@
 #ifdef _DEBUG_FULL_
       std::cout << "  Create new label" << std::endl;
 #endif
-      if ( layer->arrangement == P_LINE )
+      if ( f->layer->arrangement == P_LINE )
       {
         std::cout << alpha*180/M_PI << std::endl;
         if ( flags & FLAG_MAP_ORIENTATION )
@@ -495,7 +592,7 @@
         if ( flags & FLAG_ON_LINE )
           positions->push_back( new LabelPosition( i, bx - yrm*cos( beta ) / 2, by - yrm*sin( beta ) / 2, xrm, yrm, alpha, cost, this ) ); // Line
       }
-      else if (layer->arrangement == P_HORIZ)
+      else if (f->layer->arrangement == P_HORIZ)
       {
         positions->push_back( new LabelPosition(i, bx - xrm/2, by - yrm/2, xrm, yrm, 0, cost, this) ); // Line
         //positions->push_back( new LabelPosition(i, bx -yrm/2, by - yrm*sin(beta)/2, xrm, yrm, alpha, cost, this, line)); // Line
@@ -533,7 +630,7 @@
   }
 
 
-  LabelPosition* Feature::curvedPlacementAtOffset( PointSet* path_positions, double* path_distances, int orientation, int index, double distance )
+  LabelPosition* FeaturePart::curvedPlacementAtOffset( PointSet* path_positions, double* path_distances, int orientation, int index, double distance )
   {
     // Check that the given distance is on the given index and find the correct index and distance if not
     while (distance < 0 && index > 1)
@@ -564,7 +661,7 @@
     int initial_index = index;
     double initial_distance = distance;
 
-    double string_height = labelInfo->label_height;
+    double string_height = f->labelInfo->label_height;
     double old_x = path_positions->x[index-1];
     double old_y = path_positions->y[index-1];
 
@@ -595,12 +692,12 @@
 
     int upside_down_char_count = 0; // Count of characters that are placed upside down.
 
-    for (int i = 0; i < labelInfo->char_num; i++)
+    for (int i = 0; i < f->labelInfo->char_num; i++)
     {
       double last_character_angle = angle;
 
       // grab the next character according to the orientation
-      LabelInfo::CharacterInfo& ci = (orientation > 0 ? labelInfo->char_info[i] : labelInfo->char_info[labelInfo->char_num-i-1]);
+      LabelInfo::CharacterInfo& ci = (orientation > 0 ? f->labelInfo->char_info[i] : f->labelInfo->char_info[f->labelInfo->char_num-i-1]);
 
       // Coordinates this character will start at
       if (segment_length == 0)
@@ -666,7 +763,7 @@
       // normalise between -180 and 180
       while (angle_delta > M_PI) angle_delta -= 2*M_PI;
       while (angle_delta < -M_PI) angle_delta += 2*M_PI;
-      if (labelInfo->max_char_angle_delta > 0 && fabs(angle_delta) > labelInfo->max_char_angle_delta*(M_PI/180))
+      if (f->labelInfo->max_char_angle_delta > 0 && fabs(angle_delta) > f->labelInfo->max_char_angle_delta*(M_PI/180))
       {
         std::cerr << "err6" << std::endl;
         return NULL;
@@ -691,7 +788,7 @@
 
       //std::cerr << "adding part: " << render_x << "  " << render_y << std::endl;
       LabelPosition* tmp = new LabelPosition(0, render_x /*- xBase*/, render_y /*- yBase*/, ci.width, string_height, -render_angle, 0.0001, this);
-      tmp->setPartId( orientation > 0 ? i : labelInfo->char_num-i-1 );
+      tmp->setPartId( orientation > 0 ? i : f->labelInfo->char_num-i-1 );
       if (slp == NULL)
         slp = tmp;
       else
@@ -711,7 +808,7 @@
     // END FOR
 
     // If we placed too many characters upside down
-    if (upside_down_char_count >= labelInfo->char_num/2.0)
+    if (upside_down_char_count >= f->labelInfo->char_num/2.0)
     {
       // if we auto-detected the orientation then retry with the opposite orientation
       if (!orientation_forced)
@@ -730,10 +827,10 @@
     return slp;
   }
 
-  int Feature::setPositionForLineCurved( LabelPosition ***lPos, PointSet* mapShape )
+  int FeaturePart::setPositionForLineCurved( LabelPosition ***lPos, PointSet* mapShape )
   {
     // label info must be present
-    if (labelInfo == NULL || labelInfo->char_num == 0)
+    if (f->labelInfo == NULL || f->labelInfo->char_num == 0)
       return 0;
 
     // distance calculation
@@ -757,7 +854,7 @@
 
     int nbp = 0;
     LinkedList<LabelPosition*> *positions = new LinkedList<LabelPosition*> ( ptrLPosCompare );
-    double delta = max( labelInfo->label_height, total_distance/10.0 );
+    double delta = max( f->labelInfo->label_height, total_distance/10.0 );
 
     // generate curved labels
     std::cerr << "------" << std::endl;
@@ -818,7 +915,7 @@
    *
    */
 
-  int Feature::setPositionForPolygon( double scale, LabelPosition ***lPos, PointSet *mapShape, double delta_width )
+  int FeaturePart::setPositionForPolygon( double scale, LabelPosition ***lPos, PointSet *mapShape, double delta_width )
   {
 
 #ifdef _DEBUG_
@@ -831,15 +928,15 @@
     double xrm;
     double yrm;
 
-    xrm = unit_convert( label_x,
-                        layer->label_unit,
-                        layer->pal->map_unit,
-                        layer->pal->dpi, scale, delta_width );
+    xrm = unit_convert( f->label_x,
+                        f->layer->label_unit,
+                        f->layer->pal->map_unit,
+                        f->layer->pal->dpi, scale, delta_width );
 
-    yrm = unit_convert( label_y,
-                        layer->label_unit,
-                        layer->pal->map_unit,
-                        layer->pal->dpi, scale, delta_width );
+    yrm = unit_convert( f->label_y,
+                        f->layer->label_unit,
+                        f->layer->pal->map_unit,
+                        f->layer->pal->dpi, scale, delta_width );
 
     //print();
 
@@ -855,7 +952,7 @@
 
     shapes_toProcess->push_back( mapShape );
 
-    splitPolygons( shapes_toProcess, shapes_final, xrm, yrm, uid );
+    splitPolygons( shapes_toProcess, shapes_final, xrm, yrm, f->uid );
 
 
     delete shapes_toProcess;
@@ -910,7 +1007,7 @@
             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;
+            std::cout << "   LabelSizeUn: " << f->label_x << "   " << f->label_y << std::endl;
             continue;
           }
 
@@ -923,7 +1020,7 @@
 #endif
 
           bool enoughPlace = false;
-          if ( layer->getArrangement() == P_FREE )
+          if ( f->layer->getArrangement() == P_FREE )
           {
             enoughPlace = true;
             px = ( box->x[0] + box->x[2] ) / 2 - xrm;
@@ -952,7 +1049,7 @@
 
           } // arrangement== FREE ?
 
-          if ( layer->getArrangement() == P_HORIZ || enoughPlace )
+          if ( f->layer->getArrangement() == P_HORIZ || enoughPlace )
           {
             alpha = 0.0; // HORIZ
           }
@@ -1054,22 +1151,22 @@
     return nbp;
   }
 
-  void Feature::print()
+  void FeaturePart::print()
   {
     int i, j;
-    std::cout << "Geometry id : " << uid << std::endl;
+    std::cout << "Geometry id : " << f->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 << "Obstacle: " << nbHoles << std::endl;
+      for ( i = 0;i < nbHoles;i++ )
       {
         std::cout << "  obs " << i << std::endl;
-        for ( j = 0;j < selfObs[i]->nbPoints;j++ )
+        for ( j = 0;j < holes[i]->nbPoints;j++ )
         {
-          std::cout << selfObs[i]->x[j] << ";" << selfObs[i]->y[j] << std::endl;
+          std::cout << holes[i]->x[j] << ";" << holes[i]->y[j] << std::endl;
         }
       }
     }
@@ -1077,7 +1174,7 @@
     std::cout << std::endl;
   }
 
-  int Feature::setPosition( double scale, LabelPosition ***lPos,
+  int FeaturePart::setPosition( double scale, LabelPosition ***lPos,
                             double bbox_min[2], double bbox_max[2],
                             PointSet *mapShape, RTree<LabelPosition*, double, 2, double> *candidates
 #ifdef _EXPORT_MAP_
@@ -1103,34 +1200,26 @@
     switch ( type )
     {
       case GEOS_POINT:
-        fetchCoordinates();
-        if ( layer->getArrangement() == P_POINT_OVER )
+        if ( f->layer->getArrangement() == P_POINT_OVER )
           nbp = setPositionOverPoint( x[0], y[0], scale, lPos, delta );
         else
           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 );
-#endif
-        releaseCoordinates();
         break;
       case GEOS_LINESTRING:
-        if ( layer->getArrangement() == P_CURVED )
+        if ( f->layer->getArrangement() == P_CURVED )
           nbp = setPositionForLineCurved( lPos, mapShape );
         else
           nbp = setPositionForLine( scale, lPos, mapShape, delta );
         break;
 
       case GEOS_POLYGON:
-        switch ( layer->getArrangement() )
+        switch ( f->layer->getArrangement() )
         {
           case P_POINT:
           case P_POINT_OVER:
             double cx, cy;
             mapShape->getCentroid( cx, cy );
-            if ( layer->getArrangement() == P_POINT_OVER )
+            if ( f->layer->getArrangement() == P_POINT_OVER )
               nbp = setPositionOverPoint( cx, cy, scale, lPos, delta );
             else
               nbp = setPositionForPoint( cx, cy, scale, lPos, delta );
@@ -1171,88 +1260,5 @@
   }
 
 
-  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<Feat*> *feats = splitGeom( the_geom, this->uid, false );
-      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++ )
-      {
-        selfObs[i]->deleteCoords();
-      }
-    }
-  }
-
-
-
-  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

Modified: branches/symbology-ng-branch/src/core/pal/feature.h
===================================================================
--- branches/symbology-ng-branch/src/core/pal/feature.h	2009-07-29 21:04:58 UTC (rev 11206)
+++ branches/symbology-ng-branch/src/core/pal/feature.h	2009-07-30 00:32:20 UTC (rev 11207)
@@ -74,39 +74,73 @@
   };
 
   class LabelPosition;
+  class FeaturePart;
 
-  /**
-   * \brief Main class to handle feature
-   */
-  class Feature : public PointSet
+  class Feature
   {
+    friend class FeaturePart;
 
+    public:
+      Feature(Layer* l, const char* id, PalGeometry* userG, double lx, double ly);
+      ~Feature();
+
+      void setLabelInfo(LabelInfo* info) { labelInfo = info; }
+      void setDistLabel(double dist) { distlabel = dist; }
+
     protected:
-      //int id;   /* feature no id into layer */
       double label_x;
       double label_y;
       LabelInfo* labelInfo; // optional
 
-      int nbSelfObs;
-      PointSet **selfObs;
-
       char *uid;
       Layer *layer;
 
       double distlabel;
 
-      GEOSGeometry *the_geom;
-      int currentAccess;
+      PalGeometry *userGeom;
 
-      int nPart;
-      int part;
+      // array of parts - possibly not necessary
+      //int nPart;
+      //FeaturePart** parts;
+  };
 
-      PalGeometry *userGeom;
+  /**
+   * \brief Main class to handle feature
+   */
+  class FeaturePart : public PointSet
+  {
 
-      SimpleMutex *accessMutex;
+    protected:
+      Feature* f;
 
+      int nbHoles;
+      PointSet **holes;
+
+      GEOSGeometry *the_geom;
+
+      /** \brief read coordinates from a GEOS geom */
+      void extractCoords( const GEOSGeometry* geom );
+
+      /** find duplicate (or nearly duplicate points) and remove them.
+       * Probably to avoid numerical errors in geometry algorithms.
+       */
+      void removeDuplicatePoints();
+
 public:
+
       /**
+        * \brief create a new generic feature
+        *
+        * \param feat a pointer for a Feat which contains the spatial entites
+        */
+      FeaturePart( Feature *feat, const GEOSGeometry* geom );
+
+      /**
+       * \brief Delete the feature
+       */
+      virtual ~FeaturePart();
+
+      /**
        * \brief generate candidates for point feature
        * Generate candidates for point features
        * \param x x coordinates of the point
@@ -163,29 +197,6 @@
 
 
       /**
-        * \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)
-      * \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
        */
@@ -235,52 +246,19 @@
        */
       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);
+      PalGeometry* getUserGeometry() { return f->userGeom; }
 
+      void setLabelSize(double lx, double ly) { f->label_x = lx; f->label_y = ly; }
+      double getLabelWidth() const { return f->label_x; }
+      double getLabelHeight() const { return f->label_y; }
+      void setLabelDistance(double dist) { f->distlabel = dist; }
+      double getLabelDistance() const { return f->distlabel; }
+      void setLabelInfo(LabelInfo* info) { f->labelInfo = info; }
 
-      void deleteCoord();
+      int getNumSelfObstacles() const { return nbHoles; }
+      PointSet* getSelfObstacle(int i) { return holes[i]; }
 
-      void fetchCoordinates();
-      void releaseCoordinates();
-
-
-
-      PalGeometry* getUserGeometry() { return userGeom; }
-
-      void setLabelSize(double x, double y) { label_x = x; label_y = y; }
-      double getLabelWidth() const { return label_x; }
-      double getLabelHeight() const { return label_y; }
-
-      int getNumParts() const { return nPart; }
-
-      void setLabelDistance(double dist) { distlabel = dist; }
-      double getLabelDistance() const { return distlabel; }
-
-      int getNumSelfObstacles() const { return nbSelfObs; }
-      PointSet* getSelfObstacle(int i) { return selfObs[i]; }
-
-      void setLabelInfo(LabelInfo* info) { labelInfo = info; }
-
-
   };
 
 } // end namespace pal

Modified: branches/symbology-ng-branch/src/core/pal/internalexception.h
===================================================================
--- branches/symbology-ng-branch/src/core/pal/internalexception.h	2009-07-29 21:04:58 UTC (rev 11206)
+++ branches/symbology-ng-branch/src/core/pal/internalexception.h	2009-07-30 00:32:20 UTC (rev 11207)
@@ -31,8 +31,8 @@
 #include <config.h>
 #endif
 
-#ifndef _EXCEPTION_H
-#define _EXCEPTION_H
+#ifndef INTERNAL_EXCEPTION_H
+#define INTERNAL_EXCEPTION_H
 
 #include <exception>
 

Modified: branches/symbology-ng-branch/src/core/pal/labelposition.cpp
===================================================================
--- branches/symbology-ng-branch/src/core/pal/labelposition.cpp	2009-07-29 21:04:58 UTC (rev 11206)
+++ branches/symbology-ng-branch/src/core/pal/labelposition.cpp	2009-07-30 00:32:20 UTC (rev 11207)
@@ -55,7 +55,7 @@
 
 namespace pal
 {
-  LabelPosition::LabelPosition( int id, double x1, double y1, double w, double h, double alpha, double cost, Feature *feature )
+  LabelPosition::LabelPosition( int id, double x1, double y1, double w, double h, double alpha, double cost, FeaturePart *feature )
     : id( id ), cost( cost ), feature( feature ), nbOverlap( 0 ), alpha( alpha ), w( w ), h( h ), nextPart(NULL), partId(-1)
   {
 
@@ -236,7 +236,7 @@
     }
   }
 
-  Feature * LabelPosition::getFeature()
+  FeaturePart * LabelPosition::getFeaturePart()
   {
     return feature;
   }
@@ -294,22 +294,8 @@
       return true;
     }
 
-    // if the feature is not a hole we have to fetch corrdinates
-    // otherwise holes coordinates are still in memory (feature->selfObs)
-    if ( feat->getHoleOf() == NULL )
-    {
-      (( Feature* ) feat )->fetchCoordinates();
-    }
-
     pCost->update( feat );
 
-
-    if ( feat->getHoleOf() == NULL )
-    {
-      (( Feature* ) feat )->releaseCoordinates();
-    }
-
-
     return true;
   }
 

Modified: branches/symbology-ng-branch/src/core/pal/labelposition.h
===================================================================
--- branches/symbology-ng-branch/src/core/pal/labelposition.h	2009-07-29 21:04:58 UTC (rev 11206)
+++ branches/symbology-ng-branch/src/core/pal/labelposition.h	2009-07-30 00:32:20 UTC (rev 11207)
@@ -42,7 +42,7 @@
 namespace pal
 {
 
-  class Feature;
+  class FeaturePart;
   class Pal;
   class Label;
 
@@ -59,7 +59,7 @@
 
       int id;
       double cost;
-      Feature *feature;
+      FeaturePart *feature;
 
       // bug # 1 (maxence 10/23/2008)
       int probFeat;
@@ -90,7 +90,7 @@
       LabelPosition( int id, double x1, double y1,
                      double w, double h,
                      double alpha, double cost,
-                     Feature *feature );
+                     FeaturePart *feature );
 
       ~LabelPosition() { delete nextPart; }
 
@@ -133,7 +133,7 @@
       /** \brief return the feature corresponding to this labelposition
        * \return the feature
        */
-      Feature * getFeature();
+      FeaturePart * getFeaturePart();
 
       double getNumOverlaps() const { return nbOverlap; }
       void resetNumOverlaps() { nbOverlap = 0; } // called from problem.cpp, pal.cpp

Modified: branches/symbology-ng-branch/src/core/pal/layer.cpp
===================================================================
--- branches/symbology-ng-branch/src/core/pal/layer.cpp	2009-07-29 21:04:58 UTC (rev 11206)
+++ branches/symbology-ng-branch/src/core/pal/layer.cpp	2009-07-30 00:32:20 UTC (rev 11207)
@@ -44,6 +44,7 @@
 #include <pal/pal.h>
 #include <pal/layer.h>
 #include <pal/palexception.h>
+#include <pal/internalexception.h>
 
 #include "linkedlist.hpp"
 #include "hashtable.hpp"
@@ -69,12 +70,9 @@
 
     modMutex = new SimpleMutex();
 
-    //rtreeFile = new char[strlen(lyrName)+7];
-    //sprintf (rtreeFile, "%s.rtree", lyrName);
+    rtree = new RTree<FeaturePart*, double, 2, double>();
+    hashtable = new HashTable<Feature*> ( 5281 );
 
-    rtree = new RTree<Feature*, double, 2, double>();
-    hashtable = new HashTable<Cell<Feature*>*> ( 5281 );
-
     if ( defaultPriority < 0.0001 )
       this->defaultPriority = 0.0001;
     else if ( defaultPriority > 1.0 )
@@ -82,6 +80,7 @@
     else
       this->defaultPriority = defaultPriority;
 
+    featureParts = new LinkedList<FeaturePart*> ( ptrFeaturePartCompare );
     features = new LinkedList<Feature*> ( ptrFeatureCompare );
   }
 
@@ -89,6 +88,16 @@
   {
     modMutex->lock();
 
+    if ( featureParts )
+    {
+      while ( featureParts->size() )
+      {
+        delete featureParts->pop_front();
+      }
+      delete featureParts;
+    }
+
+    // features in the hashtable
     if ( features )
     {
       while ( features->size() )
@@ -107,12 +116,11 @@
     delete modMutex;
   }
 
-  /*
-  Feature *Layer::getFeature(int i){
-     if (i<0 || i >=int(features->size()))
-        return NULL;
-     return features->at(i);
-  }*/
+  Feature* Layer::getFeature( const char* geom_id )
+  {
+    Feature** fptr = hashtable->find(geom_id);
+    return (fptr ? *fptr : NULL);
+  }
 
 
   bool Layer::isScaleValid( double scale )
@@ -122,27 +130,11 @@
   }
 
 
-// PUBLIC method !
   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 );
-    }
-  }
-
-// TODO see rename()
   const char *Layer::getName()
   {
     return name;
@@ -225,364 +217,96 @@
       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();
 
-#ifdef _DEBUG_
-  // std::cout << "splitButterFly " << f->nbPoints << " " << pt_a << " " << pt_b <<  std::endl;
-#endif
 
-  new_feat->geom = f->geom;
+bool Layer::registerFeature( const char *geom_id, PalGeometry *userGeom, double label_x, double label_y )
+{
+  if ( !geom_id || label_x < 0 || label_y < 0 )
+    return false;
 
-  new_feat->id = f->id;
-  new_feat->type = geos::geom::GEOS_POLYGON;
+  modMutex->lock();
 
-  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;
-#endif
-
-  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->x[0] = cx;
-  new_feat->y[0] = cy;
-
-#ifdef _DEBUG_FULL_
-  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++ )
+  if ( hashtable->find( geom_id ) )
   {
-    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[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;
-#endif
+    modMutex->unlock();
+    throw new PalException::FeatureExists();
+    return false;
   }
 
-  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;
-  }
+  // Split MULTI GEOM and Collection in simple geometries
+  GEOSGeometry *the_geom = userGeom->getGeosGeometry();
 
-#ifdef _DEBUG_FULL_
-  std::cout << " go to reorder ..." << std::endl;
-#endif
-  reorderPolygon( new_feat->nbPoints, new_feat->x, new_feat->y );
+  Feature* f = new Feature( this, geom_id, userGeom, label_x, label_y );
 
-#ifdef _DEBUG_FULL_
-  std::cout << "split ok ..." << std::endl;
-#endif
+  bool first_feat = true;
 
-
-  return new_feat;
-}
-#endif
-
-bool Layer::registerFeature( const char *geom_id, PalGeometry *userGeom, double label_x, double label_y )
-{
-  int j;
-  int part = 0;
-
-  if ( geom_id && label_x >= 0 && label_y >= 0 )
+  // break the (possibly multi-part) geometry into simple geometries
+  LinkedList <const GEOSGeometry*> *simpleGeometries = unmulti( the_geom );
+  
+  while ( simpleGeometries->size() > 0 )
   {
-    modMutex->lock();
-    j = features->size();
+    const GEOSGeometry* geom = simpleGeometries->pop_front();
 
-    if ( hashtable->find( geom_id ) )
+    // ignore invalid geometries (e.g. polygons with self-intersecting rings)
+    if (GEOSisValid( geom ) != 1) // 0=invalid, 1=valid, 2=exception
     {
-      modMutex->unlock();
-      throw new PalException::FeatureExists();
-      return false;
+      std::cerr << "ignoring invalid feature " << geom_id << std::endl;
+      continue;
     }
 
-    /* Split MULTI GEOM and Collection in simple geometries*/
-    GEOSGeometry *the_geom = userGeom->getGeosGeometry();
+    int type = GEOSGeomTypeId( geom );
 
-    // also check whether the geometry is valid
-    LinkedList<Feat*> *finalQueue = splitGeom( the_geom, geom_id, true );
+    if (type != GEOS_POINT && type != GEOS_LINESTRING && type != GEOS_POLYGON)
+      throw InternalException::UnknownGeometry();
 
-    int nGeom = finalQueue->size();
+    FeaturePart* fpart = new FeaturePart(f, geom);
 
-    bool first_feat = true;
-
-    while ( finalQueue->size() > 0 )
+    // ignore invalid geometries
+    if ( (type == GEOS_LINESTRING && fpart->nbPoints < 2) ||
+         (type == GEOS_POLYGON && fpart->nbPoints < 3) )
     {
-      Feat *f = finalQueue->pop_front();
-#ifdef _DEBUG_FULL_
-      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:
-
-          // ignore invalid geometries
-          if ( (f->type == GEOS_LINESTRING && f->nbPoints < 2) ||
-               (f->type == GEOS_POLYGON && f->nbPoints < 3) )
-            continue;
-#ifdef _DEBUG_FULL_
-          std::cout << "Create Feat" << std::endl;
-#endif
-          ft = new Feature( f, this, part, nGeom, userGeom );
-          ft->deleteCoord();
-#ifdef _DEBUG_FULL_
-          std::cout << "Feature created" << std::endl;
-#endif
-          break;
-        default:
-#ifdef _VERBOSE_
-          std::cerr << "Wrong geometry type, should never occurs !!" << std::endl;
-#endif
-          exit( -1 );
-      }
-
-      double bmin[2];
-      double bmax[2];
-      ft->getBoundingBox(bmin, bmax);
-
-      ft->setLabelSize(label_x, label_y);
-
-      features->push_back( ft );
-
-      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;
-#endif
-
-      rtree->Insert( bmin, bmax, ft );
-
-#ifdef _DEBUG_FULL_
-      std::cout << "feature inserted :-)" << std::endl;
-#endif
-
-      delete f;
-#ifdef _DEBUG_FULL_
-      std::cout << "f deleted..." << std::endl;
-#endif
-      part++;
+      delete fpart;
+      continue;
     }
-    delete finalQueue;
 
-    userGeom->releaseGeosGeometry( the_geom );
-  }
-  modMutex->unlock();
-
-  return (part > 0); // true if we've added something
-}
-
-
-Cell<Feature*>* Layer::getFeatureIt( const char * geom_id )
-{
-  Cell<Feature*>** it = hashtable->find( geom_id );
-
-  if ( it )
-    return *it;
-  else
-    return NULL;
-}
-
-void Layer::setFeatureDistlabel( const char * geom_id, double distlabel )
-{
-  int i;
-
-  if ( distlabel < 0 )
-  {
-    std::cerr << "setFeatureDistlabel :  invalid size : " << distlabel << std::endl;
-    throw new PalException::ValueNotInRange();
-    return;
-  }
-
-  modMutex->lock();
-  Cell<Feature*>* it = getFeatureIt( geom_id );
-
-  if ( it )
-  {
-    // log
-    Feature *feat = it->item;
-    int nb = feat->getNumParts();
-
-    for ( i = 0;i < nb;i++ )
+    // polygons: reorder coordinates
+    if ( type == GEOS_POLYGON && reorderPolygon( fpart->nbPoints, fpart->x, fpart->y ) != 0 )
     {
-      feat = it->item;
-      feat->setLabelDistance(distlabel);
-      it = it->next;
+      delete fpart;
+      continue;
     }
-  }
-  else
-  {
-    std::cerr << "setFeatureDistlabel " << geom_id << " not found" << std::endl;
-    modMutex->unlock();
-    throw new PalException::UnknownFeature();
-  }
-  modMutex->unlock();
-}
 
+    // feature part is ready!
 
-double Layer::getFeatureDistlabel( const char *geom_id )
-{
-  modMutex->lock();
-  Cell<Feature*>* it = getFeatureIt( geom_id );
+    double bmin[2];
+    double bmax[2];
+    fpart->getBoundingBox(bmin, bmax);
 
-  int ret = -1;
-  if ( it )
-    ret = it->item->getLabelDistance();
-  else
-  {
-    modMutex->unlock();
-    throw new PalException::UnknownFeature();
-  }
+    // add to list of layer's feature parts
+    featureParts->push_back( fpart );
 
-  modMutex->unlock();
-  return ret;
-}
+    // add to r-tree for fast spatial access
+    rtree->Insert( bmin, bmax, fpart );
 
-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;
+    first_feat = false;
   }
+  delete simpleGeometries;
 
-  modMutex->lock();
-  Cell<Feature*>* it = getFeatureIt( geom_id );
+  userGeom->releaseGeosGeometry( the_geom );
 
-  if ( it )
-  {
-    Feature *feat = it->item;
-    int nb = feat->getNumParts();
-
-    for ( i = 0;i < nb;i++ )
-    {
-      feat = it->item;
-      feat->setLabelSize(label_x, 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<Feature*>* it = getFeatureIt( geom_id );
-
-  double ret = -1;
-
-  if ( it )
-    ret = it->item->getLabelHeight();
-  else
+  // add feature to layer if we have added something
+  if (!first_feat)
   {
-    modMutex->unlock();
-    throw new PalException::UnknownFeature();
+    features->push_back( f );
+    hashtable->insertItem( geom_id, f );
   }
 
-  modMutex->unlock();
-
-  return ret;
+  return !first_feat; // true if we've added something
 }
 
-double Layer::getFeatureLabelWidth( const char *geom_id )
-{
-  modMutex->lock();
-  Cell<Feature*>* it = getFeatureIt( geom_id );
-  double ret = -1;
 
-  if ( it )
-    ret = it->item->getLabelWidth();
-  else
-  {
-    modMutex->unlock();
-    throw new PalException::UnknownFeature();
-  }
-  modMutex->unlock();
-  return ret;
-}
-
-
-void Layer::setFeatureLabelInfo( const char *geom_id, LabelInfo* labelInfo )
-{
-  if ( !labelInfo )
-  {
-    throw new PalException::ValueNotInRange();
-    return;
-  }
-
-  modMutex->lock();
-  Cell<Feature*>* it = getFeatureIt( geom_id );
-
-  if ( it )
-  {
-    Feature *feat = it->item;
-    int nb = feat->getNumParts();
-
-    for ( int i = 0;i < nb;i++ )
-    {
-      feat = it->item;
-      feat->setLabelInfo(labelInfo);
-      it = it->next;
-    }
-  }
-  else
-  {
-    modMutex->unlock();
-    throw new PalException::UnknownFeature();
-  }
-  modMutex->unlock();
-}
-
-
 void Layer::setLabelUnit( Units label_unit )
 {
   if ( label_unit == PIXEL || label_unit == METER )
@@ -596,81 +320,5 @@
 
 
 
-/*
-void Layer::setFeatureGeom (const char * geom_id, const char *the_geomHex){
-
-
-   Cell<Feature*>* it = getFeatureIt (geom_id);
-
-   if (it){
-      double bmin[2];
-      double bmax[2];
-
-      int oldnPart = it->item->nPart;
-      int nPart;
-
-      //geos::io::WKBReader wkbReader =  geos::io::WKBReader();
-
-      geos::io::WKBReader * wkbReader = new geos::io::WKBReader();
-
-      std::string str = the_geomHex;
-      std::istream *is = new std::istringstream (str);
-      geos::geom::Geometry *initial_geom = wkbReader->readHEX(*is);
-      delete is;
-
-
-      LinkedList<Feat*> *finalFeats = splitGeom (initial_geom, geom_id);
-
-      nPart = finalFeats->size();
-
-      bool pushback = nPart > oldnPart;
-
-      Feature *feat;
-      Feat *ft;
-
-      if (!pushback){
-         int k = 0
-         while (finalFeats->size() > 0){
-            feat = it->item;
-
-            ft = finalFeats->pop_front();
-
-            bmin[0] = feat->xmin;
-            bmin[1] = feat->ymin;
-
-            bmax[0] = feat->xmax;
-            bmax[1] = feat->ymax;
-
-            rtree->Remove (bmin, bmax, feat);
-
-            feat->setXYCoord (ft->geom);
-            feat->nPart = nPart;
-
-            bmin[0] = feat->xmin;
-            bmin[1] = feat->ymin;
-
-            bmax[0] = feat->xmax;
-            bmax[1] = feat->ymax;
-
-            rtree->Insert (bmin, bmax, feat);
-
-            it = it->next;
-            k++;
-         }
-
-         for (;k<oldnPart;it++){
-
-         }
-      }
-      else{
-        // 1) Backup old value (xPx, etc)
-        // 2) remove old Features from old_id
-        // 3) append new feauter through addFeature method
-      }
-   }
-}
-*/
-
-
 } // end namespace
 

Modified: branches/symbology-ng-branch/src/core/pal/layer.h
===================================================================
--- branches/symbology-ng-branch/src/core/pal/layer.h	2009-07-29 21:04:58 UTC (rev 11206)
+++ branches/symbology-ng-branch/src/core/pal/layer.h	2009-07-30 00:32:20 UTC (rev 11207)
@@ -42,7 +42,6 @@
 
 namespace pal
 {
-//#include <pal/LinkedList.hpp>
 
   template <class Type> class LinkedList;
   template <class Type> class Cell;
@@ -51,12 +50,11 @@
   template<class DATATYPE, class ELEMTYPE, int NUMDIMS, class ELEMTYPEREAL, int TMAXNODES, int TMINNODES> class RTree;
 
   class Feature;
+  class FeaturePart;
   class Pal;
   class SimpleMutex;
   class LabelInfo;
 
-  class Feat;
-
   /**
    * \brief A layer of spacial entites
    *
@@ -67,18 +65,21 @@
   class Layer
   {
       friend class Pal;
-      friend class Feature;
+      friend class FeaturePart;
 
       friend class Problem;
 
       friend class LabelPosition;
-      friend bool extractFeatCallback( Feature *ft_ptr, void *ctx );
+      friend bool extractFeatCallback( FeaturePart *ft_ptr, 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 );
 
     protected:
       char *name; /* unique */
 
+      /** list of feature parts */
+      LinkedList<FeaturePart*> *featureParts;
 
+      /** list of features - for deletion */
       LinkedList<Feature*> *features;
 
       Pal *pal;
@@ -100,8 +101,8 @@
       unsigned long arrangementFlags;
 
       // indexes (spatial and id)
-      RTree<Feature*, double, 2, double, 8, 4> *rtree;
-      HashTable<Cell<Feature*>*> *hashtable;
+      RTree<FeaturePart*, double, 2, double, 8, 4> *rtree;
+      HashTable<Feature*> *hashtable;
 
       SimpleMutex *modMutex;
 
@@ -128,13 +129,6 @@
       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<Feature*> *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
        */
@@ -153,12 +147,6 @@
 
 
       /**
-       * \brief rename the layer
-       * @param name the new name
-       */
-      void rename( char *name );
-
-      /**
        *  \brief get arrangement policy
        */
       Arrangement getArrangement();
@@ -286,68 +274,9 @@
        */
       bool registerFeature( const char *geom_id, PalGeometry *userGeom, double label_x = -1, double label_y = -1 );
 
-      // TODO implement
-      //void unregisterFeature (const char *geom_id);
+      /** return pointer to feature or NULL if doesn't exist */
+      Feature* getFeature( 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, double 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
-       */
-      double getFeatureDistlabel( const char *geom_id );
-
-      /**
-       * add more detailed information about layer (character widths and more)
-       */
-      void setFeatureLabelInfo( const char *geom_id, LabelInfo* labelInfo );
   };
 
 } // end namespace pal

Modified: branches/symbology-ng-branch/src/core/pal/pal.cpp
===================================================================
--- branches/symbology-ng-branch/src/core/pal/pal.cpp	2009-07-29 21:04:58 UTC (rev 11206)
+++ branches/symbology-ng-branch/src/core/pal/pal.cpp	2009-07-30 00:32:20 UTC (rev 11207)
@@ -216,7 +216,7 @@
    *
    * Extract a specific shape from indexes
    */
-  bool extractFeatCallback( Feature *ft_ptr, void *ctx )
+  bool extractFeatCallback( FeaturePart *ft_ptr, void *ctx )
   {
 
     double min[2];
@@ -239,8 +239,6 @@
     {
       ft_ptr->getBoundingBox(min, max);
       context->obstacles->Insert( min, max, ft_ptr );
-
-      ft_ptr->fetchCoordinates();
     }
 
 
@@ -285,10 +283,7 @@
           LinkedList<PointSet*> *shapes = new LinkedList<PointSet*> ( ptrPSetCompare );
           bool outside, inside;
 
-          // Fetch coordinates
-          ft_ptr->fetchCoordinates();
           PointSet *shape = ft_ptr->createProblemSpecificPointSet( bbx, bby, &outside, &inside );
-          ft_ptr->releaseCoordinates();
 
 
           if ( inside )
@@ -387,39 +382,7 @@
 
 
 
-  bool releaseCallback( PointSet *pset, void *ctx )
-  {
-    if ( pset->getHoleOf() == NULL )
-    {
-      (( Feature* ) pset )->releaseCoordinates();
-    }
-    return true;
-  }
 
-
-  void releaseAllInIndex( RTree<PointSet*, double, 2, double> *obstacles )
-  {
-    /*
-    RTree<PointSet*, double, 2, double>::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;
-
-    obstacles->Search( amin, amax, releaseCallback, NULL );
-  }
-
-
   typedef struct _filterContext
   {
     RTree<LabelPosition*, double, 2, double> *cdtsIndex;
@@ -434,15 +397,6 @@
     double scale = (( FilterContext* ) ctx )->scale;
     Pal* pal = (( FilterContext* )ctx )->pal;
 
-    if ( pset->getHoleOf() == NULL )
-    {
-      (( Feature* ) pset )->fetchCoordinates();
-    }
-    else
-    {
-      (( Feature* ) pset->getHoleOf() )->fetchCoordinates();
-    }
-
     double amin[2], amax[2];
     pset->getBoundingBox(amin, amax);
 
@@ -453,15 +407,6 @@
     pruneContext.pal = pal;
     cdtsIndex->Search( amin, amax, LabelPosition::pruneCallback, ( void* ) &pruneContext );
 
-    if ( pset->getHoleOf() == NULL )
-    {
-      (( Feature* ) pset )->releaseCoordinates();
-    }
-    else
-    {
-      (( Feature* ) pset->getHoleOf() )->releaseCoordinates();
-    }
-
     return true;
   }
 
@@ -615,7 +560,6 @@
 #endif
       delete fFeats;
       delete prob;
-      releaseAllInIndex( obstacles );
       delete obstacles;
       return NULL;
     }
@@ -739,7 +683,6 @@
     delete fFeats;
 
     //delete candidates;
-    releaseAllInIndex( obstacles );
     delete obstacles;
 
 

Modified: branches/symbology-ng-branch/src/core/pal/pal.h
===================================================================
--- branches/symbology-ng-branch/src/core/pal/pal.h	2009-07-29 21:04:58 UTC (rev 11206)
+++ branches/symbology-ng-branch/src/core/pal/pal.h	2009-07-30 00:32:20 UTC (rev 11207)
@@ -128,7 +128,7 @@
   class Pal
   {
       friend class Problem;
-      friend class Feature;
+      friend class FeaturePart;
       friend class Layer;
     private:
       std::list<Layer*> * layers;

Modified: branches/symbology-ng-branch/src/core/pal/palexception.h
===================================================================
--- branches/symbology-ng-branch/src/core/pal/palexception.h	2009-07-29 21:04:58 UTC (rev 11206)
+++ branches/symbology-ng-branch/src/core/pal/palexception.h	2009-07-30 00:32:20 UTC (rev 11207)
@@ -31,8 +31,8 @@
 #include <config.h>
 #endif
 
-#ifndef _EXCEPTION_H
-#define _EXCEPTION_H
+#ifndef PAL_EXCEPTION_H
+#define PAL_EXCEPTION_H
 
 #include <exception>
 

Modified: branches/symbology-ng-branch/src/core/pal/pointset.cpp
===================================================================
--- branches/symbology-ng-branch/src/core/pal/pointset.cpp	2009-07-29 21:04:58 UTC (rev 11206)
+++ branches/symbology-ng-branch/src/core/pal/pointset.cpp	2009-07-30 00:32:20 UTC (rev 11207)
@@ -1747,14 +1747,6 @@
     py = cy / (3*A);
   }
 
-  void PointSet::deleteCoords()
-  {
-    delete[] x;
-    delete[] y;
-    x = NULL;
-    y = NULL;
-  }
-
 } // end namespace
 
 #endif

Modified: branches/symbology-ng-branch/src/core/pal/pointset.h
===================================================================
--- branches/symbology-ng-branch/src/core/pal/pointset.h	2009-07-29 21:04:58 UTC (rev 11206)
+++ branches/symbology-ng-branch/src/core/pal/pointset.h	2009-07-30 00:32:20 UTC (rev 11207)
@@ -47,7 +47,6 @@
 {
 
   class Pal;
-  class Feat;
   class Feature;
   class Projection;
   class LabelPosition;
@@ -92,11 +91,11 @@
 
   class PointSet
   {
-      friend class Feature;
+      friend class FeaturePart;
       friend class LabelPosition;
       friend class CostCalculator;
       friend class PolygonCostCalculator;
-      friend void extractXYCoord( Feat *f );
+      friend class Layer;
 
     protected:
       int nbPoints;
@@ -109,8 +108,6 @@
 
       int type;
 
-      //PointSet *parent;
-
       PointSet* holeOf;
       PointSet* parent;
 
@@ -126,7 +123,7 @@
 public:
       PointSet();
       PointSet( int nbPoints, double *x, double *y );
-      ~PointSet();
+      virtual ~PointSet();
 
       int getPath( int start, int stop, int *path_val );
 
@@ -185,9 +182,6 @@
       void getCentroid( double &px, double &py );
 
 
-      /** delete x and y coordinate arrays */
-      void deleteCoords();
-
       int getGeosType() const { return type; }
 
       void getBoundingBox(double min[2], double max[2]) const

Modified: branches/symbology-ng-branch/src/core/pal/problem.cpp
===================================================================
--- branches/symbology-ng-branch/src/core/pal/problem.cpp	2009-07-29 21:04:58 UTC (rev 11206)
+++ branches/symbology-ng-branch/src/core/pal/problem.cpp	2009-07-30 00:32:20 UTC (rev 11207)
@@ -3098,12 +3098,10 @@
         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;
     }
 

Modified: branches/symbology-ng-branch/src/core/pal/util.cpp
===================================================================
--- branches/symbology-ng-branch/src/core/pal/util.cpp	2009-07-29 21:04:58 UTC (rev 11206)
+++ branches/symbology-ng-branch/src/core/pal/util.cpp	2009-07-30 00:32:20 UTC (rev 11207)
@@ -240,282 +240,6 @@
   }
 
 
-
-  /*
-   * \brief read coordinates from a GEOS geom
-   */
-  void extractXYCoord( Feat *f )
-  {
-    int i, j;
-
-    //Projection *proj = pal->proj;
-
-    const GEOSCoordSequence *coordSeq;
-
-    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];
-#ifdef _DEBUG_FULL_
-        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;
-    }
-
-
-    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;
-
-    //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];
-
-
-#ifdef _DEBUG_FULL_
-    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] );
-
-      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;
-
-      pts[i] = i;
-
-#ifdef _DEBUG_FULL_
-      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;
-      }
-    }
-
-    if ( new_nbPoints < f->nbPoints )
-    {
-#ifdef _DEBUG_FULL_
-      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];
-#ifdef _DEBUG_FULL_
-          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;
-    }
-
-    delete[] ok;
-
-
-    //delete coordSeq;
-    delete[] pts;
-  }
-
-
-
-  LinkedList<Feat*> * splitGeom( GEOSGeometry *the_geom, const char *geom_id, bool check_valid )
-  {
-    LinkedList <Feat*> *fCoordQueue = new LinkedList<Feat*> ( ptrFeatCompare );
-
-    LinkedList <const GEOSGeometry*> *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();
-
-      // ignore invalid geometries (e.g. polygons with self-intersecting rings)
-      if (check_valid && GEOSisValid( geom ) != 1) // 0=invalid, 1=valid, 2=exception
-      {
-        std::cerr << "ignoring invalid feature " << geom_id << std::endl;
-        continue;
-      }
-
-      //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;
-            }
-#endif
-            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;
-              }
-#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();
-      }
-    }
-
-    delete simpleGeometries;
-
-    return fCoordQueue;
-  }
-
 } // namespace
 
 

Modified: branches/symbology-ng-branch/src/core/pal/util.h
===================================================================
--- branches/symbology-ng-branch/src/core/pal/util.h	2009-07-29 21:04:58 UTC (rev 11206)
+++ branches/symbology-ng-branch/src/core/pal/util.h	2009-07-30 00:32:20 UTC (rev 11207)
@@ -49,45 +49,17 @@
 
   class LabelPosition;
   class Layer;
-  class Feature;
+  class FeaturePart;
 
-  inline bool ptrFeatureCompare( Feature * a, Feature * b )
-  {
-    return a == b;
-  }
+  LinkedList<const GEOSGeometry*> * unmulti( GEOSGeometry *the_geom );
 
-
   /**
-   * \brief For translating feature from GEOS to Pal
+   * \brief For usage in problem solving algorithm
    */
-  class Feat
-  {
-    public:
-      const GEOSGeometry *geom;
-      const char *id;
-      int type;
-
-      int nbPoints;
-      double *x;
-      double *y;
-
-      double minmax[4]; // {xmin, ymin, xmax, ymax}
-
-      int nbHoles;
-      PointSet **holes;
-
-  };
-
-
-  /**
-   * \brief split GEOS geom (multilinestring, multipoint, multipolygon) => (point, linestring, polygone)
-   */
-  LinkedList<Feat*> * splitGeom( GEOSGeometry *the_geom, const char *geom_id, bool check_valid );
-
   class Feats
   {
   public:
-    Feature *feature;
+    FeaturePart *feature;
     PointSet *shape;
     double priority;
     int nblp;
@@ -265,11 +237,14 @@
     return a == b;
   }
 
-
-  inline bool ptrFeatCompare( Feat * a, Feat * b )
+  inline bool ptrFeatureCompare( Feature * a, Feature * b )
   {
     return a == b;
   }
+  inline bool ptrFeaturePartCompare( FeaturePart * a, FeaturePart * b )
+  {
+    return a == b;
+  }
 
   inline bool ptrFeatsCompare( Feats * a, Feats * b )
   {

Modified: branches/symbology-ng-branch/src/core/qgspalobjectpositionmanager.cpp
===================================================================
--- branches/symbology-ng-branch/src/core/qgspalobjectpositionmanager.cpp	2009-07-29 21:04:58 UTC (rev 11206)
+++ branches/symbology-ng-branch/src/core/qgspalobjectpositionmanager.cpp	2009-07-30 00:32:20 UTC (rev 11207)
@@ -148,7 +148,7 @@
   std::list<pal::LabelPosition*>::iterator labelIt = resultLabelList->begin();
   for ( ; labelIt != resultLabelList->end(); ++labelIt )
   {
-    referredGeometry = dynamic_cast<QgsPALGeometry*>(( *labelIt )->getFeature()->getUserGeometry() );
+    referredGeometry = dynamic_cast<QgsPALGeometry*>(( *labelIt )->getFeaturePart()->getUserGeometry() );
     if ( !referredGeometry )
     {
       continue;

Modified: branches/symbology-ng-branch/src/plugins/labeling/pallabeling.cpp
===================================================================
--- branches/symbology-ng-branch/src/plugins/labeling/pallabeling.cpp	2009-07-29 21:04:58 UTC (rev 11206)
+++ branches/symbology-ng-branch/src/plugins/labeling/pallabeling.cpp	2009-07-30 00:32:20 UTC (rev 11207)
@@ -154,11 +154,12 @@
     return;
 
   // TODO: only for placement which needs character info
-  palLayer->setFeatureLabelInfo( lbl->strId(), lbl->info( fontMetrics, xform ) );
+  pal::Feature* feat = palLayer->getFeature( lbl->strId() );
+  feat->setLabelInfo( lbl->info( fontMetrics, xform ) );
 
   // TODO: allow layer-wide feature dist in PAL...?
   if (dist != 0)
-    palLayer->setFeatureDistlabel(lbl->strId(), fabs(ptOne.x()-ptZero.x())* dist);
+    feat->setDistLabel(fabs(ptOne.x()-ptZero.x())* dist);
 }
 
 
@@ -470,7 +471,7 @@
   // TODO: optimize access :)
   const LayerSettings& lyr = layer(label->getLayerName());
 
-  QString text = ((MyLabel*)label->getFeature()->getUserGeometry())->text();
+  QString text = ((MyLabel*)label->getFeaturePart()->getUserGeometry())->text();
   QString txt = ( label->getPartId() == -1 ? text : QString( text[label->getPartId()] ) );
 
   QgsDebugMsg("drawLabel " + QString::number(drawBuffer) + " " + txt);



More information about the QGIS-commit mailing list