void SparseMatrix::rowToPolynomial( const RowIndex row, const std::vector<PolyRing::Monoid::ConstMonoPtr>& colMonomials, Poly& poly ) { poly.setToZero(); poly.reserve(entryCountInRow(row)); const auto end = rowEnd(row); for (auto it = rowBegin(row); it != end; ++it) { MATHICGB_ASSERT(it.index() < colMonomials.size()); if (it.scalar() != 0) poly.append(it.scalar(), *colMonomials[it.index()]); } MATHICGB_ASSERT(poly.termsAreInDescendingOrder()); }
void LineCombiner::add( QPointF p1, QPointF p2 ) { bool ok; qDebug() << "add" << p1 << p2; // find closest points within the threshold distance of p1 and p2 IndexPt * ip1 = _findClosestPt( p1 ); IndexPt * ip2 = _findClosestPt( p2 ); // normalize the cases if ( ! ip1 ) { std::swap( ip1, ip2 ); std::swap( p1, p2 ); } if ( ip1 ) { CARTA_ASSERT( ip1-> poly ); } if ( ip2 ) { CARTA_ASSERT( ip2-> poly ); } // case1: this line segment is not near anything else if ( ip1 == nullptr && ip2 == nullptr ) { qDebug() << "case null null"; // we insert a new polyline and update spacial index // make a new polyline from p1 and p2 Poly * poly = new Poly; poly->append( p1 ); poly->append( p2 ); // insert beginning of this polyline into grid findCell( p1 )-> pts.append( IndexPt( poly, false ) ); // insert end of this polyine into grid findCell( p2 )-> pts.append( IndexPt( poly, true ) ); IndexPt ipt1( poly, true ); CARTA_ASSERT( findCell( ipt1.pt() )->pts.contains( ipt1 ) ); return; } // catch a super-special case.... both points point to the same polyline, same end... // we'll treat this as if only one of the points pointed to a polyline) if( ip2 && ip1->poly == ip2->poly && ip1->flipped == ip2->flipped) { qDebug() << "super special"; ip2 = nullptr; } // only one point has a match (ip1, ip2 is null) if ( ip1 != nullptr && ip2 == nullptr ) { qDebug() << "case poly null"; // make a copy of what ip1 points to, because it'll be destroyed IndexPt ip1copy = * ip1; // remove ip1 from it's corresponding cell (after this ip1 will point to // a destroyed memory!) ok = findCell( ip1-> pt() )-> pts.removeOne( * ip1 ); CARTA_ASSERT( ok ); // re-point ip1 to the copy ip1 = & ip1copy; // we extend the polyline that ip1 points to with p2 if ( ip1-> flipped ) { ip1-> poly-> append( p2 ); } else { ip1-> poly-> prepend( p2 ); } // and add a new index point (for p2) to the respective cell findCell( p2 )-> pts.append( * ip1 ); return; } // both points have a match, and it's the same polyline, but different ends... if ( ip1-> poly == ip2-> poly ) { qDebug() << "case poly poly same"; CARTA_ASSERT( ip1->flipped == ! ip2->flipped ); // we need to remove both points from their cells Poly * poly = ip1->poly; ok = findCell( ip1->pt() )->pts.removeOne( * ip1 ); CARTA_ASSERT( ok ); ok = findCell( ip2->pt() )->pts.removeOne( * ip2 ); CARTA_ASSERT( ok ); // make it a closed polyline poly->append( poly->first() ); QPolygonF polygon = poly2polygon( poly ); m_polygons.push_back( polygon ); delete poly; return; } // last case is: both points have a match to 2 different polylines qDebug() << "case poly poly diff"; // we need to merge these two polylines together IndexPt ip1c = * ip1; IndexPt ip2c = * ip2; // remove first polyline from the spatial index ok = findCell( ip1c.poly->front() )-> pts.removeAll( { ip1c.poly, false } ); CARTA_ASSERT( ok ); ok = findCell( ip1c.poly->back() )-> pts.removeAll( { ip1c.poly, true } ); CARTA_ASSERT( ok ); // remove second polyline from the spatial index ok = findCell( ip2c.poly->front() )-> pts.removeAll( { ip2c.poly, false } ); CARTA_ASSERT( ok ); ok = findCell( ip2c.poly->back() )-> pts.removeAll( { ip2c.poly, true } ); CARTA_ASSERT( ok ); Q_UNUSED(ok); // we need to handle 4 cases for merging... in any case, we'll be re-using poly1 and // appending/prepending to it all elements from poly2 // case1: append poly2 to the end of poly1, in forward order if ( ip1c.flipped && ! ip2c.flipped ) { qDebug() << "subcase1 - append forward"; for ( auto & pt : * ip2c.poly ) { ip1c.poly->append( pt ); } } else if ( ip1c.flipped && ip2c.flipped ) { qDebug() << "subcase2 - append reverse"; QLinkedListIterator < QPointF > i( * ip2c.poly ); i.toBack(); while ( i.hasPrevious() ) { ip1c.poly-> append( i.previous() ); } } else if ( ! ip1c.flipped && ! ip2c.flipped ) { qDebug() << "subase3 - prepend forward"; for ( auto & pt : * ip2c.poly ) { ip1c.poly->prepend( pt ); } } else { qDebug() << "subase4 - prepend reverse"; QLinkedListIterator < QPointF > i( * ip2c.poly ); i.toBack(); while ( i.hasPrevious() ) { ip1c.poly-> prepend( i.previous() ); } } // get rid of poly2 delete ip2c.poly; // re-insert the endpoints of poly1 into spatial index ip1c = IndexPt( ip1c.poly, false ); ip2c = IndexPt( ip1c.poly, true ); findCell( ip1c.poly->first() )->pts.append( ip1c ); findCell( ip1c.poly->last() )->pts.append( ip2c ); } // add