The Douglas-purk algorithm is used to compress a large number of redundant graphic data points to extract necessary data points.
The algorithm implements the following extraction process:
1) connect a straight line to the first and last points of the curve, calculate the distance between all points on the curve and the straight line, and find the maximum distance value dmax. Use dmax to compare it with the preset threshold D:
2) If dmax <D, all the center points on the curve are taken away; then the straight line segment is used as the approximate curve, and the curve is processed completely.
If dmax is greater than or equal to D, the coordinate points corresponding to dmax are retained, and the curve is divided into two parts. This method is used repeatedly for the two parts, that is, repeating 1), 2) step until all dmax values are less than D, that is, the extraction of the curve is completed.
Obviously, the extraction accuracy of this algorithm is also related to the threshold. The larger the threshold, the greater the degree of simplification, the more points are reduced. On the contrary, the lower the degree of simplification, the more points are retained, the shape tends to the original curve.
Bool simplifycurve (curvevertexes & prevpts, curvevertexes & nextpts, double tolerance)
{
// Exception
If (! Prevpts. Size () | Tolerance <0 .)
{
Return false;
}
Nextpts. Clear ();
// Initialization
Int ptsize = prevpts. Size ();
Simpstack stack (ptsize );
// Loop until two vertex meet...
While (stack. m_curOrder> = 0)
{
// Get Top Elemelt;
Int lOrder = stack. m_lOrders [stack. m_curOrder];
Int rOrder = stack. m_rOrders [stack. m_curOrder];
Stack. m_curOrder --;
//
CGeoPoint <double> lPt = prevPts [lOrder];
CGeoPoint <double> rPt = prevPts [rOrder];
// Max proj distance and which point
Double maxProjDist = 0.0;
Int whichPt = 0;
// Not in the same X or Y direction
If (rPt. m_x-lPt. m_x )! = 0 | (rPt. m_y-lPt. m_y )! = 0)
{
// Get Max Distance;
Int I = lOrder + 1;
For (; I <rorder; I ++)
{
Double factor = 0 .;
Cgeopoint <double> result;
Double projdist = cvectop <double>: point2line (prevpts [lorder], prevpts [rorder], prevpts [I], factor, result );
If (projdist> maxprojdist)
{
Maxprojdist = projdist;
WhichPt = I;
}
}
}
Else
{
If (rOrder-lOrder> 1)
{
Stack. m_curOrder ++;
Stack. m_lOrders [stack. m_curOrder] = lOrder;
Stack. m_rOrders [stack. m_curOrder] = rOrder-1;
}
}
// Based on this point to split this point array
If (maxProjDist> tolerance) // The value is greater than the given value, followed by two points
{
Stack. m_isRetain [whichPt] = true;
If (rOrder-lOrder> 1)
{
Stack. m_curOrder ++;
Stack. m_lOrders [stack. m_curOrder] = lOrder;
Stack. m_rOrders [stack. m_curOrder] = whichPt;
Stack. m_curOrder ++;
Stack. m_lOrders [stack. m_curOrder] = whichPt;
Stack. m_rOrders [stack. m_curOrder] = rOrder;
}
}
Else // if the value is less than the given value, the intermediate point is left behind.
{
Stack. m_isRetain [lOrder] = true;
Stack. m_isRetain [rOrder] = true;
}
}
Int I = 0;
For (; I <ptsize; I ++)
{
If (! Stack. m_isretain [I])
{
Continue;
}
Nextpts. push_back (prevpts [I]);
}
Return true;
}