Skip to content
Permalink
Browse files

Options for curved labels: above/on/below line, distance from line (a…

…s with parallel labels)

git-svn-id: http://svn.osgeo.org/qgis/branches/symbology-ng-branch@11419 c8812cc2-4d05-0410-92ff-de0c093fc19c
  • Loading branch information
wonder
wonder committed Aug 17, 2009
1 parent 7186af4 commit 56a6ef2813acaeef8f00025a4f26bf9648b2f849
Showing with 86 additions and 19 deletions.
  1. +29 −3 src/core/pal/feature.cpp
  2. +34 −0 src/core/pal/labelposition.cpp
  3. +5 −0 src/core/pal/labelposition.h
  4. +18 −16 src/plugins/labeling/labelinggui.cpp
@@ -840,6 +840,13 @@ void FeaturePart::removeDuplicatePoints()
return slp;
}

static LabelPosition* _createCurvedCandidate(LabelPosition* lp, double angle, double dist)
{
LabelPosition* newLp = new LabelPosition(*lp);
newLp->offsetPosition( dist*cos(angle+M_PI/2), dist*sin(angle+M_PI/2) );
return newLp;
}

int FeaturePart::setPositionForLineCurved( LabelPosition ***lPos, PointSet* mapShape )
{
// label info must be present
@@ -865,10 +872,13 @@ void FeaturePart::removeDuplicatePoints()
if (total_distance == 0)
return 0;

int nbp = 0;
LinkedList<LabelPosition*> *positions = new LinkedList<LabelPosition*> ( ptrLPosCompare );
double delta = max( f->labelInfo->label_height, total_distance/10.0 );

unsigned long flags = f->layer->getArrangementFlags();
if ( flags == 0 )
flags = FLAG_ON_LINE; // default flag

// generate curved labels
std::cerr << "------" << std::endl;
for (int i = 0; i*delta < total_distance; i++)
@@ -880,6 +890,7 @@ void FeaturePart::removeDuplicatePoints()
// evaluate cost
double angle_diff = 0, angle_last, diff;
LabelPosition* tmp = slp;
double sin_avg=0, cos_avg=0;
while (tmp)
{
if (tmp != slp) // not first?
@@ -890,9 +901,12 @@ void FeaturePart::removeDuplicatePoints()
angle_diff += diff;
}

sin_avg += sin(tmp->getAlpha());
cos_avg += cos(tmp->getAlpha());
angle_last = tmp->getAlpha();
tmp = tmp->getNextPart();
}

double angle_diff_avg = angle_diff / (f->labelInfo->char_num-1); // <0, pi> but pi/8 is much already
double cost = angle_diff_avg / 100; // <0, 0.031 > but usually <0, 0.003 >
if (cost < 0.0001) cost = 0.0001;
@@ -904,12 +918,24 @@ void FeaturePart::removeDuplicatePoints()
//std::cerr << "cost " << angle_diff << " vs " << costCenter << std::endl;
slp->setCost(cost);

positions->push_back(slp);
nbp++;

// average angle is calculated with respect to periodicity of angles
double angle_avg = atan2( sin_avg / f->labelInfo->char_num, cos_avg / f->labelInfo->char_num);
// displacement
if (flags & FLAG_ABOVE_LINE)
positions->push_back( _createCurvedCandidate(slp, angle_avg, f->distlabel) );
if (flags & FLAG_ON_LINE)
positions->push_back( _createCurvedCandidate(slp, angle_avg, -f->labelInfo->label_height/2) );
if (flags & FLAG_BELOW_LINE)
positions->push_back( _createCurvedCandidate(slp, angle_avg, -f->labelInfo->label_height - f->distlabel) );

// delete original candidate
delete slp;
}
}


int nbp = positions->size();
( *lPos ) = new LabelPosition*[nbp];
for (int i = 0; i < nbp; i++)
{
@@ -118,6 +118,27 @@ namespace pal
}
}

LabelPosition::LabelPosition( const LabelPosition& other )
{
id = other.id;
cost = other.cost;
feature = other.feature;
probFeat = other.probFeat;
nbOverlap = other.nbOverlap;

memcpy(x, other.x, sizeof(double)*4);
memcpy(y, other.y, sizeof(double)*4);
alpha = other.alpha;
w = other.w;
h = other.h;

if (other.nextPart)
nextPart = new LabelPosition(*other.nextPart);
else
nextPart = NULL;
partId = other.partId;
}

bool LabelPosition::isIn( double *bbox )
{
int i;
@@ -216,6 +237,19 @@ namespace pal
return false; // no conflict found
}

void LabelPosition::offsetPosition( double xOffset, double yOffset )
{
for (int i=0; i < 4; i++)
{
x[i] += xOffset;
y[i] += yOffset;
}

if (nextPart)
nextPart->offsetPosition(xOffset, yOffset);
}


int LabelPosition::getId() const
{
return id;
@@ -95,6 +95,9 @@ namespace pal
double alpha, double cost,
FeaturePart *feature );

/** copy constructor */
LabelPosition( const LabelPosition& other );

~LabelPosition() { delete nextPart; }


@@ -125,6 +128,8 @@ namespace pal
/** returns number of intersections with polygon (testing border and center) */
int getNumPointsInPolygon( int npol, double *xp, double *yp );

/** shift the label by specified offset */
void offsetPosition( double xOffset, double yOffset );


/** \brief return id
@@ -84,15 +84,6 @@ LabelingGui::LabelingGui( PalLabeling* lbl, QgsVectorLayer* layer, QWidget* pare
case LayerSettings::Line:
radLineParallel->setChecked(true);
radPolygonPerimeter->setChecked(true);

spinDistLine->setValue(lyr.dist);
chkLineAbove->setChecked( lyr.placementFlags & LayerSettings::AboveLine );
chkLineBelow->setChecked( lyr.placementFlags & LayerSettings::BelowLine );
chkLineOn->setChecked( lyr.placementFlags & LayerSettings::OnLine );
if ( lyr.placementFlags & LayerSettings::MapOrientation )
radOrientationMap->setChecked(true);
else
radOrientationLine->setChecked(true);
break;
case LayerSettings::Curved:
radLineCurved->setChecked(true);
@@ -108,6 +99,18 @@ LabelingGui::LabelingGui( PalLabeling* lbl, QgsVectorLayer* layer, QWidget* pare
Q_ASSERT(0 && "NOOO!");
}

if (lyr.placement == LayerSettings::Line || lyr.placement == LayerSettings::Curved)
{
spinDistLine->setValue(lyr.dist);
chkLineAbove->setChecked( lyr.placementFlags & LayerSettings::AboveLine );
chkLineBelow->setChecked( lyr.placementFlags & LayerSettings::BelowLine );
chkLineOn->setChecked( lyr.placementFlags & LayerSettings::OnLine );
if ( lyr.placementFlags & LayerSettings::MapOrientation )
radOrientationMap->setChecked(true);
else
radOrientationLine->setChecked(true);
}

cboFieldName->setCurrentIndex( cboFieldName->findText(lyr.fieldName) );
chkEnableLabeling->setChecked( lyr.enabled );
sliderPriority->setValue( lyr.priority );
@@ -173,9 +176,11 @@ LayerSettings LabelingGui::layerSettings()
lyr.placement = LayerSettings::OverPoint;
}
else if ( (stackedPlacement->currentWidget() == pageLine && radLineParallel->isChecked())
|| (stackedPlacement->currentWidget() == pagePolygon && radPolygonPerimeter->isChecked()) )
|| (stackedPlacement->currentWidget() == pagePolygon && radPolygonPerimeter->isChecked())
|| (stackedPlacement->currentWidget() == pageLine && radLineCurved->isChecked()) )
{
lyr.placement = LayerSettings::Line;
bool curved = (stackedPlacement->currentWidget() == pageLine && radLineCurved->isChecked());
lyr.placement = (curved ? LayerSettings::Curved : LayerSettings::Line);
lyr.dist = spinDistLine->value();
if (chkLineAbove->isChecked())
lyr.placementFlags |= LayerSettings::AboveLine;
@@ -187,10 +192,6 @@ LayerSettings LabelingGui::layerSettings()
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()) )
{
@@ -314,7 +315,8 @@ void LabelingGui::updateOptions()
stackedOptions->setCurrentWidget(pageOptionsPoint);
}
else if ( (stackedPlacement->currentWidget() == pageLine && radLineParallel->isChecked())
|| (stackedPlacement->currentWidget() == pagePolygon && radPolygonPerimeter->isChecked()) )
|| (stackedPlacement->currentWidget() == pagePolygon && radPolygonPerimeter->isChecked())
|| (stackedPlacement->currentWidget() == pageLine && radLineCurved->isChecked()) )
{
stackedOptions->setCurrentWidget(pageOptionsLine);
}

0 comments on commit 56a6ef2

Please sign in to comment.
You can’t perform that action at this time.