Esempio n. 1
0
/*! For the oCCW (positive) polygon orientation a positive dOff will 
    inflate the polygon. For the oCW (negative) polygon orientation 
    a positive dOff will shrink the polygon.
 */
void Polygon2D::Offset(
   qreal dOff //!< Offset value.
)
{
   VecVertex vecNew;
   vecNew.reserve(GetCount());

   // Move each point
   for(unsigned int i=0; i<GetCount(); i++) {
      Line2D lnA = GetLine(i==0 ? GetCount()-1 : i-1);
      Line2D lnB = GetLine(i);

      // Offset both lines
      lnA.Offset(-dOff);
      lnB.Offset(-dOff);
      // Intersection gives the new point;
      Point2D ptI;
      unsigned int uStatus = lnA.GetIntersection(lnB, ptI);
      if(uStatus & Line2D::intExist) {
         vecNew.push_back(ptI);
      }
      // lnA and lnB are parallel
      else {
         vecNew.push_back(lnA.GetB());
      }
   }
   Clear();
   m_vecV = vecNew;
}
Esempio n. 2
0
/*! First all intersections are calculated. Then duplicates are removed.
    If only points on the line are required, all points that are outside
    the lnX[A,B] are removed. If bParallel is true, parallel segmets are
    checked for overlap and overlap points are included in the solution.
    
    \retval VecVertex container of intersection points. 
 */
QVector<Point2D> Polygon2D::GetIntersection(
   const Line2D& lnX, //!< line that intersects the polygon
   bool bOnLineOnly,  //!< if true, only points between A and B inclusive are counted.
   bool bParallel     //!< check parallel lines for overlap
) const
{
   // results are stored here
   QVector<Point2D> vecInt;

   // for each segment
   for(unsigned int i=0; i<GetCount(); i++) {
      Line2D ln = GetLine(i);
      Q_ASSERT(ln.IsValid());
      Point2D ptInt;
      // Check overlaps, if they are wanted
      if(bParallel && ln.IsParallel(lnX)) {
         Line2D lnO = ln.GetOverlap(lnX);
         if(lnO.IsValid()) {
            vecInt.push_back(lnO.GetA());
            vecInt.push_back(lnO.GetB());
         }
      }

      // check intersections
      if(ln.GetIntersection(lnX, ptInt) & Line2D::intFirst){
         vecInt.push_back(ptInt);
      }
   }

   // Sort the points in the vector. Same point may appear several
   // times.
   Point2DSortLineLess pred(lnX);
   std::sort(vecInt.begin(),vecInt.end(),pred);
   // remove duplicates, if any
   QVector<Point2D>::iterator f = std::unique(vecInt.begin(),vecInt.end());
   vecInt.erase(f,vecInt.end());

   // remove all points that are not inside the line
   if(bOnLineOnly) {
      QVector<Point2D>::iterator i=vecInt.begin();
      while(i!=vecInt.end()) {
         if(!(lnX.GetPosition(*i) & Line2D::posInsideEnd))
            i = vecInt.erase(i);
         else
            i++;
      }
   }

   return vecInt;
}
Esempio n. 3
0
bool Polygon2D::AnyIntersection(
	const Polygon2D& pg, 
	bool bBorder,
	qreal dTol			 //!< Tolerance settings.
) const
{
   for(unsigned int i=0; i<GetCount(); i++) {
      Line2D lnA = GetLine(i);
      for(unsigned int j=0; j<pg.GetCount(); j++) {
         Line2D lnB = pg.GetLine(j);

         // Check the intersection
         Point2D X;
         int iFlag = lnA.GetIntersection(lnB, X, dTol);
         if(iFlag == Line2D::intBoth) {
            // if border is part of the polygon, then there is no doubt
            // the intersection exists (it may only touch)
            if(bBorder)
               return true;
            // if the border is not part of the polygon, then we must
            // check if lines only touches
            else {
               if(lnA.GetPosition(X, dTol) & Line2D::posEnd ||
                  lnB.GetPosition(X, dTol) & Line2D::posEnd) {
                  // they only touch, this is not intersection
                  ; // do nothing
               }
               else {
                  return true;
               }
            }
         }
      }
   }
   return false;
}
Esempio n. 4
0
int Polygon2D::Split(
   const Line2D& lineSplit, //!< The spliting line. 
   Polygon2D& plgPos,       //!< Resulting positive polygon object.
   Polygon2D& plgNeg) const //!< Resulting negative polygon object.
{
   Q_ASSERT(m_vecV.size()>=3);

   int iCounter = 0;
   const int iSize = m_vecV.size();

   plgPos.Clear(); // make sure that the polygon on positive side is empty.
   plgNeg.Clear(); // the same is true for the negative side.
   plgPos.SetDegree(m_uDegree); // They should have the same degree.
   plgNeg.SetDegree(m_uDegree);

   Point2D t;
   for (int i=0; i<iSize; i++ )  {
      const Point2D& A = m_vecV[i];                      // start point
      const Point2D& B = m_vecV[(i==iSize-1 ? 0 : i+1)]; // end point of current line
      Line2D line (A,B);                                 // current line
      Point2D intPt;                                     // intersection point

      // Intersect the current line with the lineSplit. 
      // Test the returned flag!
      int flag = line.GetIntersection (lineSplit, intPt);

      // Intersection exist and it lies inside the first line (line).
      if (flag & Line2D::intFirst) {
         // The intersection is truly inside the line, not on the edges A or B
         if (intPt!=A && intPt!=B) {
            plgPos.Append(intPt);        // This means that the intesection point
            plgNeg.Append(intPt);        // is a part of both polygons.
            iCounter++;
            continue;
         }
      }

      // Check the end point of the line
      // The end point (B) could be exactly on the split line
      flag = lineSplit.GetPosition(B);

      // Yes it is
      if(flag & Line2D::posOnLine) {
         plgPos.Append(B);        // This means that the intesection point
         plgNeg.Append(B);        // is a part of both polygons.
         iCounter++;
      }
      // is it on the positive side
      else if(flag & Line2D::posPositive) {
         plgPos.Append(B);
      }
      // then it is on the negative side
      else { 
         plgNeg.Append(B);
      }
   } // for (i .. )

   if ( plgPos.GetCount() < 3 ) {
      plgPos.Clear();
   }
   if ( plgNeg.GetCount() < 3 ) {
      plgNeg.Clear();
   }
   return iCounter;
}