Skip to content

Commit

Permalink
[UPDATE] support polygon features for simplification.
Browse files Browse the repository at this point in the history
git-svn-id: http://svn.osgeo.org/qgis/trunk@10793 c8812cc2-4d05-0410-92ff-de0c093fc19c
  • Loading branch information
wonder committed May 14, 2009
1 parent 6b96976 commit 797afab
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 37 deletions.
109 changes: 78 additions & 31 deletions src/app/qgsmaptoolsimplify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "qgstolerance.h"

#include <QMouseEvent>
#include <QMessageBox>

#include <math.h>

Expand Down Expand Up @@ -81,15 +82,29 @@ void QgsMapToolSimplify::toleranceChanged(int tolerance)

// create a copy of selected feature and do the simplification
QgsFeature f = mSelectedFeature;
QgsSimplifyFeature::simplifyLine(f, mTolerance);
if ( mSelectedFeature.geometry()->type() == QGis::Line )
{
QgsSimplifyFeature::simplifyLine(f, mTolerance);
}
else
{
QgsSimplifyFeature::simplifyPolygon(f, mTolerance);
}
mRubberBand->setToGeometry(f.geometry(), false);
}


void QgsMapToolSimplify::storeSimplified()
{
QgsVectorLayer * vlayer = currentVectorLayer();
QgsSimplifyFeature::simplifyLine(mSelectedFeature, mTolerance);
if ( mSelectedFeature.geometry()->type() == QGis::Line )
{
QgsSimplifyFeature::simplifyLine(mSelectedFeature, mTolerance);
}
else
{
QgsSimplifyFeature::simplifyPolygon(mSelectedFeature, mTolerance);
}

vlayer->changeGeometry( mSelectedFeature.id(), mSelectedFeature.geometry() );

Expand All @@ -99,7 +114,7 @@ void QgsMapToolSimplify::storeSimplified()
int QgsMapToolSimplify::calculateDivider(double num)
{
double tmp = num;
int i = 1;
long i = 1;
while (tmp < 1)
{
tmp = tmp*10;
Expand All @@ -108,7 +123,7 @@ int QgsMapToolSimplify::calculateDivider(double num)
return i;
}

void QgsMapToolSimplify::calculateSliderBoudaries()
bool QgsMapToolSimplify::calculateSliderBoudaries()
{
double minTolerance, maxTolerance;

Expand All @@ -117,9 +132,9 @@ void QgsMapToolSimplify::calculateSliderBoudaries()
bool isLine = mSelectedFeature.geometry()->type() == QGis::Line;
QVector<QgsPoint> pts = getPointList(mSelectedFeature);
int size = pts.size();
if (size == 0 || (isLine && size < 2) || (!isLine && size < 3) )
if (size == 0 || (isLine && size < 2) || (!isLine && size < 4) )
{
return;
return false;
}

// calculate min
Expand All @@ -128,30 +143,61 @@ void QgsMapToolSimplify::calculateSliderBoudaries()
if (QgsSimplifyFeature::simplifyPoints(pts, tol).size() < size)
{
found = true;
minTolerance = tol/2;
minTolerance = tol/ 2;
} else {
tol = tol * 2;
}
}

found = false;
int requiredCnt = (isLine ? 2 : 3);
int requiredCnt = (isLine ? 2 : 4); //4 for polygon is correct because first and last points are the same
bool bottomFound = false;
double highTol, lowTol;// two boundaries to be used when no directly correct solution is found
// calculate max
while (!found)
{
if (QgsSimplifyFeature::simplifyPoints(pts, tol).size() < requiredCnt + 1)

int foundVertexes = QgsSimplifyFeature::simplifyPoints(pts, tol).size();
if (foundVertexes < requiredCnt + 1)
{
//TODO: fix for polygon
found = true;
maxTolerance = tol;
if (foundVertexes == requiredCnt)
{
found = true;
maxTolerance = tol;
}
else
{
bottomFound = true;
highTol = tol;
tol = (highTol + lowTol) /2;
if (highTol/lowTol < 1.00000001)
{
found = true;
maxTolerance = lowTol;
}
}
} else {
tol = tol * 2;
if (bottomFound)
{
lowTol = tol;
tol = (highTol + lowTol) /2;
if (highTol/lowTol < 1.00000001)
{
found = true;
maxTolerance = lowTol;
}
}
else
{
lowTol = tol;
tol = tol * 2;
}
}
}
toleranceDivider = calculateDivider(minTolerance);
// set min and max
mSimplifyDialog->setRange( int(minTolerance * toleranceDivider),
int(maxTolerance * toleranceDivider) );
return true;
}


Expand Down Expand Up @@ -181,7 +227,11 @@ void QgsMapToolSimplify::canvasPressEvent( QMouseEvent * e )
mSelectedFeature = f;
}
}

if (mSelectedFeature.geometry()->isMultipart())
{
QMessageBox::critical( 0, tr( "Unsupported operation" ), tr( "Multipart features are not supported for simplification." ) );
return;
}
// delete previous rubberband (if any)
removeRubberBand();

Expand All @@ -193,10 +243,11 @@ void QgsMapToolSimplify::canvasPressEvent( QMouseEvent * e )
mRubberBand->setWidth(2);
mRubberBand->show();
//calculate boudaries for slidebar
calculateSliderBoudaries();

// show dialog as a non-modal window
mSimplifyDialog->show();
if (calculateSliderBoudaries())
{
// show dialog as a non-modal window
mSimplifyDialog->show();
}
}
}

Expand Down Expand Up @@ -234,13 +285,10 @@ QVector<QgsPoint> QgsMapToolSimplify::getPointList(QgsFeature& f)
}
return line->asPolygon()[0];
}

}





bool QgsSimplifyFeature::simplifyLine(QgsFeature& lineFeature, double tolerance)
{
QgsGeometry* line = lineFeature.geometry();
Expand All @@ -254,23 +302,22 @@ bool QgsSimplifyFeature::simplifyLine(QgsFeature& lineFeature, double tolerance
return TRUE;
}


//TODO: change to correct structure after
bool QgsSimplifyFeature::simplifyPartOfLine(QgsFeature& lineFeature, int fromVertexNr, int toVertexNr, double tolerance)
bool QgsSimplifyFeature::simplifyPolygon(QgsFeature& polygonFeature, double tolerance)
{
QgsGeometry* line = lineFeature.geometry();
if (line->type() != QGis::Line)
QgsGeometry* polygon = polygonFeature.geometry();
if (polygon->type() != QGis::Polygon)
{
return FALSE;
}

QVector<QgsPoint> resultPoints = simplifyPoints(line->asPolyline(), tolerance);
lineFeature.setGeometry( QgsGeometry::fromPolyline( resultPoints ) );
QVector<QgsPoint> resultPoints = simplifyPoints(polygon->asPolygon()[0], tolerance);
//resultPoints.push_back(resultPoints[0]);
QVector<QgsPolyline> poly;
poly.append(resultPoints);
polygonFeature.setGeometry( QgsGeometry::fromPolygon( poly ) );
return TRUE;
}



QVector<QgsPoint> QgsSimplifyFeature::simplifyPoints (const QVector<QgsPoint>& pts, double tolerance)
{
// Douglas-Peucker simplification algorithm
Expand Down
30 changes: 24 additions & 6 deletions src/app/qgsmaptoolsimplify.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
* (at your option) any later version. *
* *
***************************************************************************/
/* $Id$ */

#ifndef QGSMAPTOOLSIMPLIFY_H
#define QGSMAPTOOLSIMPLIFY_H
Expand All @@ -30,21 +31,28 @@ class QgsSimplifyDialog : public QDialog, private Ui::SimplifyLineDialog
Q_OBJECT

public:

QgsSimplifyDialog( QWidget* parent = NULL );

/** Setting range of slide bar */
void setRange(int minValue, int maxValue);

signals:
/** Signal when slidebar is moved */
void toleranceChanged( int tol );

/** Signal to accept changes */
void storeSimplified();

private slots:
/** Internal signal when value is changed */
void valueChanged( int value );
/** Internal signal to store simplified feature */
void simplify();
};


/**Map tool to add vertices to line/polygon features*/
/** Map tool to simplify line/polygon features */
class QgsMapToolSimplify: public QgsMapToolEdit
{
Q_OBJECT
Expand All @@ -62,27 +70,36 @@ public slots:
void removeRubberBand();

private:

/** Divider calculation, because slider can go only by whole numbers */
int calculateDivider(double num);

void calculateSliderBoudaries();
/** Function to calculate tolerance boudaries for simplifying */
bool calculateSliderBoudaries();

/** Function to get list of vertexes from feature */
QVector<QgsPoint> getPointList(QgsFeature& f);

// data

/** Dialog with slider to set correct tolerance value */
QgsSimplifyDialog* mSimplifyDialog;

/** Rubber band to draw current state of simplification */
QgsRubberBand* mRubberBand;

/** Feature with which we are working */
QgsFeature mSelectedFeature;

/** tolerance divider is value which tells with which delete value from sidebar */
int toleranceDivider;

/** real value of tolerance */
double mTolerance;

private slots:
/** slot to change display when slidebar is moved */
void toleranceChanged(int tolerance);

/** slot to store feture after simplification */
void storeSimplified();

};
Expand All @@ -92,6 +109,7 @@ private slots:
*/
class QgsSimplifyFeature
{
/** structure for one entry in stack for simplification algorithm */
struct StackEntry {
int anchor;
int floater;
Expand All @@ -100,8 +118,8 @@ class QgsSimplifyFeature
public:
/** simplify line feature with specified tolerance. Returns TRUE on success */
static bool simplifyLine(QgsFeature &lineFeature, double tolerance);
/** simplify a part of line feature specified by range of vertices with given tolerance. Returns TRUE on success */
static bool simplifyPartOfLine(QgsFeature &lineFeature, int fromVertexNr, int toVertexNr, double tolerance);
/** simplify polygon feature with specified tolerance. Returns TRUE on success */
static bool simplifyPolygon(QgsFeature &polygonFeature, double tolerance);
/** simplify a line given by a vector of points and tolerance. Returns simplified vector of points */
static QVector<QgsPoint> simplifyPoints (const QVector<QgsPoint>& pts, double tolerance);

Expand Down

0 comments on commit 797afab

Please sign in to comment.