道格拉斯-普克 Douglas-Peuker抽稀算法

道格拉斯-普克抽稀算法,是用来对大量冗余的图形数据点进行压缩以提取必要的数据点。
该算法实现抽稀的过程是:
1)对曲线的首末点虚连一条直线,求曲线上所有点与直线的距离,并找出最大距离值dmax,用dmax与事先给定的阈值D相比: 
2)若dmax<D,则将这条曲线上的中间点全部舍去;则该直线段作为曲线的近似,该段曲线处理完毕。 
  若dmax≥D,保留dmax对应的坐标点,并以该点为界,把曲线分为两部分,对这两部分重复使用该方法,即重复1),2)步,直到所有dmax均<D,即完成对曲线的抽稀。 

显然,本算法的抽稀精度也与阈值相关,阈值越大,简化程度越大,点减少的越多,反之,化简程度越低,点保留的越多,形状也越趋于原曲线。 

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 with ...
 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) //大于给定值接着二分
  { 
   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 //小于给定值舍去中间点,留下首末点
  {
            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;
}

 

你可能感兴趣的:(道格拉斯-普克 Douglas-Peuker抽稀算法)