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