[QGIS Commit] r11176 - in branches/symbology-ng-branch/src:
core/pal plugins/labeling
svn_qgis at osgeo.org
svn_qgis at osgeo.org
Sat Jul 25 07:21:45 EDT 2009
Author: wonder
Date: 2009-07-25 07:21:44 -0400 (Sat, 25 Jul 2009)
New Revision: 11176
Modified:
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/geomfunction.cpp
branches/symbology-ng-branch/src/core/pal/geomfunction.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.h
branches/symbology-ng-branch/src/plugins/labeling/labelinggui.cpp
branches/symbology-ng-branch/src/plugins/labeling/labelingguibase.ui
branches/symbology-ng-branch/src/plugins/labeling/pallabeling.cpp
branches/symbology-ng-branch/src/plugins/labeling/pallabeling.h
Log:
Multipart labels, advanced label info, added basic support for curved labels (some code taken from Mapnik: placement_finder.cpp)
Modified: branches/symbology-ng-branch/src/core/pal/feature.cpp
===================================================================
--- branches/symbology-ng-branch/src/core/pal/feature.cpp 2009-07-24 19:31:31 UTC (rev 11175)
+++ branches/symbology-ng-branch/src/core/pal/feature.cpp 2009-07-25 11:21:44 UTC (rev 11176)
@@ -70,6 +70,7 @@
label_x = -1;
label_y = -1;
+ labelInfo = NULL;
xmin = feat->minmax[0];
xmax = feat->minmax[2];
@@ -532,6 +533,242 @@
}
+ StraightLabelPosition* Feature::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)
+ {
+ index--;
+ distance += path_distances[index];
+ }
+
+ if (index <= 1 && distance < 0) // We've gone off the start, fail out
+ {
+ std::cerr << "err1" << std::endl;
+ return NULL;
+ }
+
+ // Same thing, checking if we go off the end
+ while (index < path_positions->nbPoints && distance > path_distances[index])
+ {
+ distance -= path_distances[index];
+ index += 1;
+ }
+ if (index >= path_positions->nbPoints)
+ {
+ std::cerr << "err2" << std::endl;
+ return NULL;
+ }
+
+ // Keep track of the initial index,distance incase we need to re-call get_placement_offset
+ int initial_index = index;
+ double initial_distance = distance;
+
+ double string_height = labelInfo->label_height;
+ double old_x = path_positions->x[index-1];
+ double old_y = path_positions->y[index-1];
+
+ double new_x = path_positions->x[index];
+ double new_y = path_positions->y[index];
+
+ double dx = new_x - old_x;
+ double dy = new_y - old_y;
+
+ double segment_length = path_distances[index];
+ if (segment_length == 0)
+ {
+ // Not allowed to place across on 0 length segments or discontinuities
+ std::cerr << "err3" << std::endl;
+ return NULL;
+ }
+
+ StraightLabelPosition* slp = NULL;
+ StraightLabelPosition* slp_tmp = NULL;
+ // current_placement = placement_result()
+ double xBase = old_x + dx*distance/segment_length;
+ double yBase = old_y + dy*distance/segment_length;
+ double angle = atan2(-dy, dx);
+
+ bool orientation_forced = (orientation != 0); // Whether the orientation was set by the caller
+ if (!orientation_forced)
+ orientation = (angle > 0.55*M_PI || angle < -0.45*M_PI ? -1 : 1);
+
+ int upside_down_char_count = 0; // Count of characters that are placed upside down.
+
+ for (int i = 0; i < 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]);
+
+ // Coordinates this character will start at
+ if (segment_length == 0)
+ {
+ // Not allowed to place across on 0 length segments or discontinuities
+ std::cerr << "err4" << std::endl;
+ return NULL;
+ }
+
+ double start_x = old_x + dx*distance/segment_length;
+ double start_y = old_y + dy*distance/segment_length;
+ // Coordinates this character ends at, calculated below
+ double end_x = 0;
+ double end_y = 0;
+
+ std::cerr << "segment len " << segment_length << " distance " << distance << std::endl;
+ if (segment_length - distance >= ci.width)
+ {
+ // if the distance remaining in this segment is enough, we just go further along the segment
+ distance += ci.width;
+ end_x = old_x + dx*distance/segment_length;
+ end_y = old_y + dy*distance/segment_length;
+ }
+ else
+ {
+ // If there isn't enough distance left on this segment
+ // then we need to search until we find the line segment that ends further than ci.width away
+ do
+ {
+ old_x = new_x;
+ old_y = new_y;
+ index++;
+ if (index >= path_positions->nbPoints) // Bail out if we run off the end of the shape
+ {
+ std::cerr << "err5" << std::endl;
+ return NULL;
+ }
+ new_x = path_positions->x[index];
+ new_y = path_positions->y[index];
+ dx = new_x - old_x;
+ dy = new_y - old_y;
+ segment_length = path_distances[index];
+
+ std::cerr << "-> " << sqrt(pow(start_x - new_x,2) + pow(start_y - new_y,2)) << " vs " << ci.width << std::endl;
+
+ } while (sqrt(pow(start_x - new_x,2) + pow(start_y - new_y,2)) < ci.width); // Distance from start_ to new_
+
+ // Calculate the position to place the end of the character on
+ findLineCircleIntersection( start_x, start_y, ci.width, old_x, old_y, new_x, new_y, end_x, end_y);
+
+ // Need to calculate distance on the new segment
+ distance = sqrt(pow(old_x - end_x,2) + pow(old_y - end_y,2));
+ }
+
+ // Calculate angle from the start of the character to the end based on start_/end_ position
+ angle = atan2(start_y-end_y, end_x-start_x);
+ //angle = atan2(end_y-start_y, end_x-start_x);
+
+ // Test last_character_angle vs angle
+ // since our rendering angle has changed then check against our
+ // max allowable angle change.
+ double angle_delta = last_character_angle - angle;
+ // 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))
+ {
+ std::cerr << "err6" << std::endl;
+ return NULL;
+ }
+
+ double render_angle = angle;
+
+ double render_x = start_x;
+ double render_y = start_y;
+
+ // Center the text on the line
+ //render_x -= ((string_height/2.0) - 1.0)*math.cos(render_angle+math.pi/2)
+ //render_y += ((string_height/2.0) - 1.0)*math.sin(render_angle+math.pi/2)
+
+ if (orientation < 0)
+ {
+ // rotate in place
+ render_x += ci.width*cos(render_angle); //- (string_height-2)*sin(render_angle);
+ render_y -= ci.width*sin(render_angle); //+ (string_height-2)*cos(render_angle);
+ render_angle += M_PI;
+ }
+
+ std::cerr << "adding part: " << render_x << " " << render_y << std::endl;
+ StraightLabelPosition* tmp = new StraightLabelPosition(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 );
+ if (slp == NULL)
+ slp = tmp;
+ else
+ slp_tmp->setNextPart(tmp);
+ slp_tmp = tmp;
+
+ //current_placement.add_node(ci.character,render_x, -render_y, render_angle);
+ //current_placement.add_node(ci.character,render_x - current_placement.starting_x, render_y - current_placement.starting_y, render_angle)
+
+ // Normalise to 0 <= angle < 2PI
+ while (render_angle >= 2*M_PI) render_angle -= 2*M_PI;
+ while (render_angle < 0) render_angle += 2*M_PI;
+
+ if (render_angle > M_PI/2 && render_angle < 1.5*M_PI)
+ upside_down_char_count++;
+ }
+ // END FOR
+
+ // If we placed too many characters upside down
+ if (upside_down_char_count >= labelInfo->char_num/2.0)
+ {
+ // if we auto-detected the orientation then retry with the opposite orientation
+ if (!orientation_forced)
+ {
+ orientation = -orientation;
+ slp = curvedPlacementAtOffset(path_positions, path_distances, orientation, initial_index, initial_distance);
+ }
+ else
+ {
+ // Otherwise we have failed to find a placement
+ std::cerr << "err7" << std::endl;
+ return NULL;
+ }
+ }
+
+ return slp;
+ }
+
+ int Feature::setPositionForLineCurved( LabelPosition ***lPos, PointSet* mapShape )
+ {
+ // label info must be present
+ if (labelInfo == NULL || labelInfo->char_num == 0)
+ return 0;
+
+ // distance calculation
+ double* path_distances = new double[mapShape->nbPoints];
+ double old_x, old_y, new_x, new_y;
+ for (int i = 0; i < mapShape->nbPoints; i++)
+ {
+ if (i == 0)
+ path_distances[i] = 0;
+ else
+ path_distances[i] = sqrt( pow(old_x - mapShape->x[i], 2) + pow(old_y - mapShape->y[i],2) );
+ old_x = mapShape->x[i];
+ old_y = mapShape->y[i];
+ }
+
+ // TODO: generate more labels
+
+ // generate curved label
+ StraightLabelPosition* slp = curvedPlacementAtOffset(mapShape, path_distances, 0, 1, 0.0);
+
+ if (!slp)
+ return 0;
+
+ // TODO: evaluate cost
+
+ int nbp = 1;
+ ( *lPos ) = new LabelPosition*[nbp];
+ (*lPos)[0] = slp;
+
+ return nbp;
+ }
+
+
+
+
/*
* seg 2
* pt3 ____________pt2
@@ -843,7 +1080,10 @@
releaseCoordinates();
break;
case GEOS_LINESTRING:
- nbp = setPositionForLine( scale, lPos, mapShape, delta );
+ if ( layer->getArrangement() == P_CURVED )
+ nbp = setPositionForLineCurved( lPos, mapShape );
+ else
+ nbp = setPositionForLine( scale, lPos, mapShape, delta );
break;
case GEOS_POLYGON:
Modified: branches/symbology-ng-branch/src/core/pal/feature.h
===================================================================
--- branches/symbology-ng-branch/src/core/pal/feature.h 2009-07-24 19:31:31 UTC (rev 11175)
+++ branches/symbology-ng-branch/src/core/pal/feature.h 2009-07-25 11:21:44 UTC (rev 11176)
@@ -48,7 +48,33 @@
namespace pal
{
+ /** optional additional info about label (for curved labels) */
+ class LabelInfo
+ {
+ public:
+ typedef struct
+ {
+ ushort chr;
+ double width;
+ } CharacterInfo;
+ LabelInfo(int num, double height)
+ {
+ max_char_angle_delta = 20;
+ label_height = height;
+ char_num = num;
+ char_info = new CharacterInfo[num];
+ }
+ ~LabelInfo() { delete [] char_info; }
+
+ double max_char_angle_delta;
+ double label_height;
+ int char_num;
+ CharacterInfo* char_info;
+ };
+
+ class StraightLabelPosition;
+
/**
* \brief Main class to handle feature
*/
@@ -59,6 +85,7 @@
//int id; /* feature no id into layer */
double label_x;
double label_y;
+ LabelInfo* labelInfo; // optional
int nbSelfObs;
PointSet **selfObs;
@@ -105,7 +132,15 @@
*/
int setPositionForLine( double scale, LabelPosition ***lPos, PointSet *mapShape, double delta_width );
+ StraightLabelPosition* curvedPlacementAtOffset( PointSet* path_positions, double* path_distances,
+ int orientation, int index, double distance );
+
/**
+ * Generate curved candidates for line features
+ */
+ int setPositionForLineCurved( LabelPosition ***lPos, PointSet* mapShape );
+
+ /**
* \brief generate candidates for point feature
* Generate candidates for point features
* \param scale map scale is 1:scale
@@ -116,7 +151,6 @@
int setPositionForPolygon( double scale, LabelPosition ***lPos, PointSet *mapShape, double delta_width );
-
/**
* \brief Feature against problem bbox
* \param bbox[0] problem x min
@@ -244,6 +278,9 @@
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/geomfunction.cpp
===================================================================
--- branches/symbology-ng-branch/src/core/pal/geomfunction.cpp 2009-07-24 19:31:31 UTC (rev 11175)
+++ branches/symbology-ng-branch/src/core/pal/geomfunction.cpp 2009-07-25 11:21:44 UTC (rev 11176)
@@ -626,5 +626,39 @@
#endif
+ void findLineCircleIntersection(double cx, double cy, double radius,
+ double x1, double y1, double x2, double y2,
+ double& xRes, double& yRes)
+ {
+ double dx = x2 - x1;
+ double dy = y2 - y1;
+ double A = dx * dx + dy * dy;
+ double B = 2 * (dx * (x1 - cx) + dy * (y1 - cy));
+ double C = (x1 - cx) * (x1 - cx) + (y1 - cy) * (y1 - cy) - radius * radius;
+
+ double det = B * B - 4 * A * C;
+ if (A <= 0.0000001 || det < 0)
+ // Should never happen, No real solutions.
+ return;
+
+ if (det == 0)
+ {
+ // Could potentially happen.... One solution.
+ double t = -B / (2 * A);
+ xRes = x1 + t * dx;
+ yRes = y1 + t * dy;
+ }
+ else
+ {
+ // Two solutions.
+ // Always use the 1st one
+ // We only really have one solution here, as we know the line segment will start in the circle and end outside
+ double t = (-B + sqrt(det)) / (2 * A);
+ xRes = x1 + t * dx;
+ yRes = y1 + t * dy;
+ }
+ }
+
+
} // end namespace
Modified: branches/symbology-ng-branch/src/core/pal/geomfunction.h
===================================================================
--- branches/symbology-ng-branch/src/core/pal/geomfunction.h 2009-07-24 19:31:31 UTC (rev 11175)
+++ branches/symbology-ng-branch/src/core/pal/geomfunction.h 2009-07-25 11:21:44 UTC (rev 11176)
@@ -81,6 +81,9 @@
+ void findLineCircleIntersection(double cx, double cy, double radius,
+ double x1, double y1, double x2, double y2,
+ double& xRes, double& yRes);
int convexHull( int *id, const double* const x, const double* const y, int n );
Modified: branches/symbology-ng-branch/src/core/pal/labelposition.cpp
===================================================================
--- branches/symbology-ng-branch/src/core/pal/labelposition.cpp 2009-07-24 19:31:31 UTC (rev 11175)
+++ branches/symbology-ng-branch/src/core/pal/labelposition.cpp 2009-07-25 11:21:44 UTC (rev 11176)
@@ -61,7 +61,7 @@
}
StraightLabelPosition::StraightLabelPosition( int id, double x1, double y1, double w, double h, double alpha, double cost, Feature *feature )
- : LabelPosition( id, cost, feature ), alpha( alpha ), w( w ), h( h )
+ : LabelPosition( id, cost, feature ), alpha( alpha ), w( w ), h( h ), nextPart(NULL), partId(-1)
{
// alpha take his value bw 0 and 2*pi rad
@@ -134,7 +134,10 @@
return true;
}
- return false;
+ if (nextPart)
+ return nextPart->isIn(bbox);
+ else
+ return false;
}
@@ -191,7 +194,18 @@
}
if ( d1 == -1 || d2 == -1 ) // disjoint
- return false;
+ {
+ if ( ls->getNextPart() )
+ {
+ if ( isInConflict(ls->getNextPart()) )
+ return true;
+ }
+
+ if (nextPart)
+ return nextPart->isInConflict( lp );
+ else
+ return false;
+ }
}
return true;
}
@@ -237,10 +251,18 @@
void StraightLabelPosition::getBoundingBox(double amin[2], double amax[2]) const
{
- amin[0] = DBL_MAX;
- amax[0] = -DBL_MAX;
- amin[1] = DBL_MAX;
- amax[1] = -DBL_MAX;
+ if (nextPart)
+ {
+ //std::cout << "using next part" <<
+ nextPart->getBoundingBox(amin, amax);
+ }
+ else
+ {
+ amin[0] = DBL_MAX;
+ amax[0] = -DBL_MAX;
+ amin[1] = DBL_MAX;
+ amax[1] = -DBL_MAX;
+ }
for ( int c = 0;c < 4;c++ )
{
if ( x[c] < amin[0] )
@@ -341,8 +363,10 @@
{
LabelPosition *lp2 = ( LabelPosition* ) ctx;
+ //std::cerr << "checking " << lp2->getFeature()->getUID() << " x " << lp->getFeature()->getUID() << std::endl;
if ( lp2->isInConflict( lp ) )
{
+ //std::cerr << "conflict!" << std::endl;
lp2->nbOverlap++;
}
@@ -433,6 +457,9 @@
dist_min = dist;
}
+ if (nextPart && dist_min > 0)
+ return min( dist_min, nextPart->getDistanceToPoint(xp, yp) );
+
return dist_min;
}
@@ -460,6 +487,10 @@
}
}
}
+
+ if (nextPart)
+ return nextPart->isBorderCrossingLine( feat );
+
return false;
}
@@ -490,6 +521,8 @@
if ( isPointInPolygon( npol, xp, yp, px, py ) )
count += 4; // virtually 4 points
+ // TODO: count with nextFeature
+
return count;
}
Modified: branches/symbology-ng-branch/src/core/pal/labelposition.h
===================================================================
--- branches/symbology-ng-branch/src/core/pal/labelposition.h 2009-07-24 19:31:31 UTC (rev 11175)
+++ branches/symbology-ng-branch/src/core/pal/labelposition.h 2009-07-25 11:21:44 UTC (rev 11176)
@@ -78,6 +78,8 @@
// virtual functions
+ virtual ~LabelPosition() {}
+
/**
* \brief is the labelposition in the bounding-box ?
*
@@ -124,7 +126,7 @@
int getProblemFeatureId() const { return probFeat; }
/** set problem feature ID and assigned label candidate ID.
* called from pal.cpp during extraction */
- void setProblemIds( int probFid, int lpId ) { probFeat = probFid; id = lpId; }
+ virtual void setProblemIds( int probFid, int lpId ) { probFeat = probFid; id = lpId; }
/** return pointer to layer's name. used for stats */
char* getLayerName() const;
@@ -212,6 +214,8 @@
double alpha, double cost,
Feature *feature );
+ ~StraightLabelPosition() { delete nextPart; }
+
// virtual functions
virtual bool isIn( double *bbox );
@@ -252,12 +256,24 @@
void print();
+ StraightLabelPosition* getNextPart() const { return nextPart; }
+ void setNextPart(StraightLabelPosition* next) { nextPart = next; }
+
+ // -1 if not multi-part
+ int getPartId() const { return partId; }
+ void setPartId(int id) { partId = id; }
+
+ void setProblemIds( int probFid, int lpId ) {
+ LabelPosition::setProblemIds(probFid, lpId);
+ if (nextPart) nextPart->setProblemIds(probFid, lpId); }
+
protected:
double x[4], y[4];
double alpha;
double w;
double h;
-
+ StraightLabelPosition* nextPart;
+ int partId;
};
} // end namespac
Modified: branches/symbology-ng-branch/src/core/pal/layer.cpp
===================================================================
--- branches/symbology-ng-branch/src/core/pal/layer.cpp 2009-07-24 19:31:31 UTC (rev 11175)
+++ branches/symbology-ng-branch/src/core/pal/layer.cpp 2009-07-25 11:21:44 UTC (rev 11176)
@@ -550,6 +550,39 @@
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 )
Modified: branches/symbology-ng-branch/src/core/pal/layer.h
===================================================================
--- branches/symbology-ng-branch/src/core/pal/layer.h 2009-07-24 19:31:31 UTC (rev 11175)
+++ branches/symbology-ng-branch/src/core/pal/layer.h 2009-07-25 11:21:44 UTC (rev 11176)
@@ -53,6 +53,7 @@
class Feature;
class Pal;
class SimpleMutex;
+ class LabelInfo;
class Feat;
@@ -343,6 +344,10 @@
*/
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.h
===================================================================
--- branches/symbology-ng-branch/src/core/pal/pal.h 2009-07-24 19:31:31 UTC (rev 11175)
+++ branches/symbology-ng-branch/src/core/pal/pal.h 2009-07-25 11:21:44 UTC (rev 11176)
@@ -100,6 +100,7 @@
P_POINT = 0, /**< arranges candidates around a point (centroid for polygon)*/
P_POINT_OVER, /** arranges candidates over a point (centroid for polygon)*/
P_LINE, /**< Only for lines and polygons, arranges candidates over the line or the polygon perimeter */
+ P_CURVED, /** Only for lines, labels along the line */
P_HORIZ, /**< Only for polygon, arranges candidates horizontaly */
P_FREE /**< Only for polygon, arranges candidates with respect of polygon orientation */
};
Modified: branches/symbology-ng-branch/src/plugins/labeling/labelinggui.cpp
===================================================================
--- branches/symbology-ng-branch/src/plugins/labeling/labelinggui.cpp 2009-07-24 19:31:31 UTC (rev 11175)
+++ branches/symbology-ng-branch/src/plugins/labeling/labelinggui.cpp 2009-07-25 11:21:44 UTC (rev 11176)
@@ -93,6 +93,9 @@
else
radOrientationLine->setChecked(true);
break;
+ case LayerSettings::Curved:
+ radLineCurved->setChecked(true);
+ break;
case LayerSettings::Horizontal:
radPolygonHorizontal->setChecked(true);
radLineHorizontal->setChecked(true);
@@ -142,7 +145,7 @@
// setup connection to changes in the placement
QRadioButton* placementRadios[] = {
radAroundPoint, radOverPoint, // point
- radLineParallel, radLineHorizontal, // line
+ radLineParallel, radLineCurved, radLineHorizontal, // line
radAroundCentroid, radPolygonHorizontal, radPolygonFree, radPolygonPerimeter // polygon
};
for (int i = 0; i < sizeof(placementRadios)/sizeof(QRadioButton*); i++)
@@ -197,6 +200,10 @@
if (radOrientationMap->isChecked())
lyr.placementFlags |= LayerSettings::MapOrientation;
}
+ else if ( stackedPlacement->currentWidget() == pageLine && radLineCurved->isChecked() )
+ {
+ lyr.placement = LayerSettings::Curved;
+ }
else if ( (stackedPlacement->currentWidget() == pageLine && radLineHorizontal->isChecked())
|| (stackedPlacement->currentWidget() == pagePolygon && radPolygonHorizontal->isChecked()) )
{
Modified: branches/symbology-ng-branch/src/plugins/labeling/labelingguibase.ui
===================================================================
--- branches/symbology-ng-branch/src/plugins/labeling/labelingguibase.ui 2009-07-24 19:31:31 UTC (rev 11175)
+++ branches/symbology-ng-branch/src/plugins/labeling/labelingguibase.ui 2009-07-25 11:21:44 UTC (rev 11176)
@@ -77,7 +77,7 @@
<item>
<widget class="QStackedWidget" name="stackedPlacement">
<property name="currentIndex">
- <number>0</number>
+ <number>1</number>
</property>
<widget class="QWidget" name="pagePoint">
<layout class="QVBoxLayout" name="verticalLayout_2">
@@ -113,6 +113,13 @@
</widget>
</item>
<item>
+ <widget class="QRadioButton" name="radLineCurved">
+ <property name="text">
+ <string>curved</string>
+ </property>
+ </widget>
+ </item>
+ <item>
<widget class="QRadioButton" name="radLineHorizontal">
<property name="text">
<string>horizontal</string>
Modified: branches/symbology-ng-branch/src/plugins/labeling/pallabeling.cpp
===================================================================
--- branches/symbology-ng-branch/src/plugins/labeling/pallabeling.cpp 2009-07-24 19:31:31 UTC (rev 11175)
+++ branches/symbology-ng-branch/src/plugins/labeling/pallabeling.cpp 2009-07-25 11:21:44 UTC (rev 11176)
@@ -33,7 +33,7 @@
class MyLabel : public PalGeometry
{
public:
- MyLabel(int id, QString text, GEOSGeometry* g): mG(g), mText(text), mId(id)
+ MyLabel(int id, QString text, GEOSGeometry* g): mG(g), mText(text), mId(id), mInfo(NULL)
{
mStrId = QByteArray::number(id);
}
@@ -41,6 +41,7 @@
~MyLabel()
{
if (mG) GEOSGeom_destroy(mG);
+ delete mInfo;
}
// getGeosGeometry + releaseGeosGeometry is called twice: once when adding, second time when labeling
@@ -57,11 +58,30 @@
const char* strId() { return mStrId.data(); }
QString text() { return mText; }
+ pal::LabelInfo* info(QFontMetrics* fm, const QgsMapToPixel* xform)
+ {
+ if (mInfo) return mInfo;
+
+ // create label info!
+ QgsPoint ptZero = xform->toMapCoordinates( 0,0 );
+ QgsPoint ptSize = xform->toMapCoordinates( 0,-fm->height() );
+
+ mInfo = new pal::LabelInfo( mText.count(), ptSize.y()-ptZero.y() );
+ for (int i = 0; i < mText.count(); i++)
+ {
+ mInfo->char_info[i].chr = mText[i].unicode();
+ ptSize = xform->toMapCoordinates( fm->width( mText[i] ), 0 );
+ mInfo->char_info[i].width = ptSize.x()-ptZero.x();
+ }
+ return mInfo;
+ }
+
protected:
GEOSGeometry* mG;
QString mText;
QByteArray mStrId;
int mId;
+ LabelInfo* mInfo;
};
// -------------
@@ -133,6 +153,9 @@
if (!palLayer->registerFeature(lbl->strId(), lbl, labelX, labelY))
return;
+ // TODO: only for placement which needs character info
+ palLayer->setFeatureLabelInfo( lbl->strId(), 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);
@@ -243,6 +266,7 @@
case LayerSettings::AroundPoint: arrangement = P_POINT; break;
case LayerSettings::OverPoint: arrangement = P_POINT_OVER; break;
case LayerSettings::Line: arrangement = P_LINE; break;
+ case LayerSettings::Curved: arrangement = P_CURVED; break;
case LayerSettings::Horizontal: arrangement = P_HORIZ; break;
case LayerSettings::Free: arrangement = P_FREE; break;
}
@@ -350,19 +374,7 @@
{
pal::StraightLabelPosition* lp = (pal::StraightLabelPosition*) problem->getFeatureCandidate(i, j);
- QgsPoint outPt = xform->transform(lp->getX(), lp->getY());
- QgsPoint outPt2 = xform->transform(lp->getX()+lp->getWidth(), lp->getY()+lp->getHeight());
-
- painter->save();
- painter->translate( QPointF(outPt.x(), outPt.y()) );
- painter->rotate(-lp->getAlpha() * 180 / M_PI );
- QRectF rect(0,0, outPt2.x()-outPt.x(), outPt2.y()-outPt.y());
- painter->drawRect(rect);
- painter->restore();
-
- // save the rect
- rect.moveTo(outPt.x(),outPt.y());
- mCandidates.append( LabelCandidate(rect, lp->getCost() * 1000) );
+ drawLabelCandidateRect(lp, painter, xform);
}
}
}
@@ -379,26 +391,7 @@
{
StraightLabelPosition* label = (StraightLabelPosition*) *it;
- QgsPoint outPt = xform->transform(label->getX(), label->getY());
-
- // TODO: optimize access :)
- const LayerSettings& lyr = layer(label->getLayerName());
-
- QString text = ((MyLabel*)label->getFeature()->getUserGeometry())->text();
-
- // shift by one as we have 2px border
- painter->save();
- painter->translate( QPointF(outPt.x()+1, outPt.y()-1-lyr.fontBaseline) );
- painter->rotate(-label->getAlpha() * 180 / M_PI );
- painter->setFont( lyr.textFont );
-
- if (lyr.bufferSize != 0)
- drawLabelBuffer(painter, text, lyr.bufferSize, lyr.bufferColor);
-
- painter->setPen( lyr.textColor );
- painter->drawText(0,0, text);
- painter->restore();
-
+ drawLabel( label, painter, xform );
}
std::cout << "LABELING draw: " << t.elapsed() << "ms" << std::endl;
@@ -443,6 +436,58 @@
return mSearch;
}
+void PalLabeling::drawLabelCandidateRect( pal::StraightLabelPosition* lp, QPainter* painter, const QgsMapToPixel* xform )
+{
+ QgsPoint outPt = xform->transform(lp->getX(), lp->getY());
+ QgsPoint outPt2 = xform->transform(lp->getX()+lp->getWidth(), lp->getY()+lp->getHeight());
+
+ painter->save();
+ painter->translate( QPointF(outPt.x(), outPt.y()) );
+ painter->rotate(-lp->getAlpha() * 180 / M_PI );
+ QRectF rect(0,0, outPt2.x()-outPt.x(), outPt2.y()-outPt.y());
+ painter->drawRect(rect);
+ painter->restore();
+
+ // save the rect
+ rect.moveTo(outPt.x(),outPt.y());
+ mCandidates.append( LabelCandidate(rect, lp->getCost() * 1000) );
+
+ // show all parts of the multipart label
+ if (lp->getNextPart())
+ drawLabelCandidateRect(lp->getNextPart(), painter, xform);
+}
+
+
+void PalLabeling::drawLabel( pal::StraightLabelPosition* label, QPainter* painter, const QgsMapToPixel* xform)
+{
+ QgsPoint outPt = xform->transform(label->getX(), label->getY());
+
+ // TODO: optimize access :)
+ const LayerSettings& lyr = layer(label->getLayerName());
+
+ QString text = ((MyLabel*)label->getFeature()->getUserGeometry())->text();
+
+ // shift by one as we have 2px border
+ painter->save();
+ painter->translate( QPointF(outPt.x()+1, outPt.y()-1-lyr.fontBaseline) );
+ painter->rotate(-label->getAlpha() * 180 / M_PI );
+ painter->setFont( lyr.textFont );
+
+ if (lyr.bufferSize != 0)
+ drawLabelBuffer(painter, text, lyr.bufferSize, lyr.bufferColor);
+
+ painter->setPen( lyr.textColor );
+ if (label->getPartId() == -1)
+ painter->drawText(0,0, text);
+ else
+ painter->drawText(0,0, QString( text[label->getPartId()] ) );
+ painter->restore();
+
+ if (label->getNextPart())
+ drawLabel( label->getNextPart(), painter, xform );
+}
+
+
void PalLabeling::drawLabelBuffer(QPainter* p, QString text, int size, QColor color)
{
p->save();
Modified: branches/symbology-ng-branch/src/plugins/labeling/pallabeling.h
===================================================================
--- branches/symbology-ng-branch/src/plugins/labeling/pallabeling.h 2009-07-24 19:31:31 UTC (rev 11175)
+++ branches/symbology-ng-branch/src/plugins/labeling/pallabeling.h 2009-07-25 11:21:44 UTC (rev 11176)
@@ -16,6 +16,7 @@
{
class Pal;
class Layer;
+ class StraightLabelPosition;
}
class QgsMapToPixel;
@@ -36,6 +37,7 @@
AroundPoint, // Point / Polygon
OverPoint, // Point / Polygon
Line, // Line / Polygon
+ Curved, // Line
Horizontal, // Polygon
Free // Polygon
};
@@ -120,6 +122,8 @@
static void registerFeatureHook(QgsFeature& f, void* layerContext);
+ void drawLabelCandidateRect( pal::StraightLabelPosition* lp, QPainter* painter, const QgsMapToPixel* xform );
+ void drawLabel( pal::StraightLabelPosition* label, QPainter* painter, const QgsMapToPixel* xform);
static void drawLabelBuffer(QPainter* p, QString text, int size, QColor color);
protected:
More information about the QGIS-commit
mailing list