/*! 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; }
/*! 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; }
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; }
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; }