Esempio n. 1
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. 2
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. 3
0
/*! Distances from the line and vertices are considered. In the case of
    line, perpendicuar distance is used in the case of vertex, radial
    distance is used.  
    \retval qreal minimal distance to the polygon border.
 */
qreal Polygon2D::GetDistance(
   const Point2D& pt //!< distance to this point is calculated.
) const
{
   qreal dD = std::numeric_limits<qreal>::max();
   
   for(unsigned int i=0; i<GetCount(); i++) {
      dD = GetMin(dD, pt.GetDistance(GetVertex(i)));
      Line2D ln = GetLine(i);
      Point2D ptN = ln.GetNearestPoint(pt);
      if(ln.GetPosition(ptN) & Line2D::posInside) 
         dD = GetMin(dD, ptN.GetDistance(pt));
   }
   return dD;
}
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;
}