QgsGeometry* QgsGeometryAnalyzer::locateBetweenMeasures( double fromMeasure, double toMeasure, const QgsGeometry* lineGeom ) { if ( !lineGeom ) { return nullptr; } QgsMultiPolyline resultGeom; //need to go with WKB and z coordinate until QgsGeometry supports M values QgsConstWkbPtr wkbPtr( lineGeom->asWkb(), lineGeom->wkbSize() ); wkbPtr.readHeader(); QGis::WkbType wkbType = lineGeom->wkbType(); if ( wkbType != QGis::WKBLineString25D && wkbType != QGis::WKBMultiLineString25D ) { return nullptr; } if ( wkbType == QGis::WKBLineString25D ) { locateBetweenWkbString( wkbPtr, resultGeom, fromMeasure, toMeasure ); } else if ( wkbType == QGis::WKBMultiLineString25D ) { int nLines; wkbPtr >> nLines; for ( int i = 0; i < nLines; ++i ) { wkbPtr.readHeader(); wkbPtr = locateBetweenWkbString( wkbPtr, resultGeom, fromMeasure, toMeasure ); } }
int QgsGml::createMultiPolygonFromFragments() { mCurrentWKBSize = 0; mCurrentWKBSize += 1 + 2 * sizeof( int ); mCurrentWKBSize += totalWKBFragmentSize(); mCurrentWKBSize += mCurrentWKBFragments.size() * ( 1 + 2 * sizeof( int ) ); //fragments are just the rings mCurrentWKB = QgsWkbPtr( new unsigned char[mCurrentWKBSize], mCurrentWKBSize ); QgsWkbPtr wkbPtr( mCurrentWKB ); wkbPtr << ( char ) mEndian << QGis::WKBMultiPolygon << mCurrentWKBFragments.size(); //have outer and inner iterators QList< QList<QgsWkbPtr> >::const_iterator outerWkbIt = mCurrentWKBFragments.constBegin(); for ( ; outerWkbIt != mCurrentWKBFragments.constEnd(); ++outerWkbIt ) { //new polygon wkbPtr << ( char ) mEndian << QGis::WKBPolygon << outerWkbIt->size(); QList<QgsWkbPtr>::const_iterator innerWkbIt = outerWkbIt->constBegin(); for ( ; innerWkbIt != outerWkbIt->constEnd(); ++innerWkbIt ) { memcpy( wkbPtr, *innerWkbIt, innerWkbIt->size() ); wkbPtr += innerWkbIt->size(); delete[] *innerWkbIt; } } mCurrentWKBFragments.clear(); *mWkbType = QGis::WKBMultiPolygon; return 0; }
QgsGeometry QgsGeometryAnalyzer::locateBetweenMeasures( double fromMeasure, double toMeasure, const QgsGeometry& lineGeom ) { if ( lineGeom.isEmpty() ) { return QgsGeometry(); } QgsMultiPolyline resultGeom; //need to go with WKB and z coordinate until QgsGeometry supports M values QByteArray wkb( lineGeom.exportToWkb() ); QgsConstWkbPtr wkbPtr( wkb ); wkbPtr.readHeader(); QgsWkbTypes::Type wkbType = lineGeom.wkbType(); if ( wkbType != QgsWkbTypes::LineString25D && wkbType != QgsWkbTypes::MultiLineString25D ) { return QgsGeometry(); } if ( wkbType == QgsWkbTypes::LineString25D ) { locateBetweenWkbString( wkbPtr, resultGeom, fromMeasure, toMeasure ); } else if ( wkbType == QgsWkbTypes::MultiLineString25D ) { int nLines; wkbPtr >> nLines; for ( int i = 0; i < nLines; ++i ) { wkbPtr.readHeader(); wkbPtr = locateBetweenWkbString( wkbPtr, resultGeom, fromMeasure, toMeasure ); } }
QByteArray QgsCurvePolygon::asWkb() const { int binarySize = sizeof( char ) + sizeof( quint32 ) + sizeof( quint32 ); QVector<QByteArray> wkbForRings; wkbForRings.reserve( 1 + mInteriorRings.size() ); if ( mExteriorRing ) { QByteArray wkb( mExteriorRing->asWkb() ); binarySize += wkb.length(); wkbForRings << wkb; } for ( const QgsCurve *curve : mInteriorRings ) { QByteArray wkb( curve->asWkb() ); binarySize += wkb.length(); wkbForRings << wkb; } QByteArray wkbArray; wkbArray.resize( binarySize ); QgsWkbPtr wkbPtr( wkbArray ); wkbPtr << static_cast<char>( QgsApplication::endian() ); wkbPtr << static_cast<quint32>( wkbType() ); wkbPtr << static_cast<quint32>( wkbForRings.count() ); for ( const QByteArray &wkb : qgis::as_const( wkbForRings ) ) { wkbPtr << wkb; } return wkbArray; }
bool QgsGeometryCollectionV2::fromWkb( const unsigned char * wkb ) { if ( !wkb ) { return false; } QgsConstWkbPtr wkbPtr( wkb + 1 ); //type wkbPtr >> mWkbType; int nGeometries = 0; wkbPtr >> nGeometries; QList<QgsAbstractGeometryV2*> geometryList; for ( int i = 0; i < nGeometries; ++i ) { QgsAbstractGeometryV2* geom = QgsGeometryFactory::geomFromWkb( wkbPtr ); if ( geom ) { geometryList.append( geom ); wkbPtr += geom->wkbSize(); } } mGeometries.resize( geometryList.size() ); for ( int i = 0; i < geometryList.size(); ++i ) { mGeometries[i] = geometryList.at( i ); } return true; }
const unsigned char* QgsClipper::clippedLineWKB( const unsigned char* wkb, const QgsRectangle& clipExtent, QPolygonF& line ) { QgsConstWkbPtr wkbPtr( wkb + 1 ); unsigned int wkbType, nPoints; wkbPtr >> wkbType >> nPoints; bool hasZValue = QgsWKBTypes::hasZ( static_cast< QgsWKBTypes::Type >( wkbType ) ); bool hasMValue = QgsWKBTypes::hasM( static_cast< QgsWKBTypes::Type >( wkbType ) ); double p0x, p0y, p1x = 0.0, p1y = 0.0; //original coordinates double p1x_c, p1y_c; //clipped end coordinates double lastClipX = 0.0, lastClipY = 0.0; //last successfully clipped coords line.clear(); line.reserve( nPoints + 1 ); for ( unsigned int i = 0; i < nPoints; ++i ) { if ( i == 0 ) { wkbPtr >> p1x >> p1y; if ( hasZValue ) wkbPtr += sizeof( double ); if ( hasMValue ) wkbPtr += sizeof( double ); continue; } else {
const unsigned char* QgsDistanceArea::measureLine( const unsigned char* feature, double* area, bool hasZptr ) { QgsConstWkbPtr wkbPtr( feature + 1 + sizeof( int ) ); int nPoints; wkbPtr >> nPoints; QList<QgsPoint> points; double x, y; QgsDebugMsg( "This feature WKB has " + QString::number( nPoints ) + " points" ); // Extract the points from the WKB format into the vector for ( int i = 0; i < nPoints; ++i ) { wkbPtr >> x >> y; if ( hasZptr ) { // totally ignore Z value wkbPtr += sizeof( double ); } points.append( QgsPoint( x, y ) ); } *area = measureLine( points ); return wkbPtr; }
bool QgsPolygonV2::fromWkb( const unsigned char* wkb ) { clear(); if ( !wkb ) { return false; } QgsConstWkbPtr wkbPtr( wkb ); QgsWKBTypes::Type type = wkbPtr.readHeader(); if ( QgsWKBTypes::flatType( type ) != QgsWKBTypes::Polygon ) { return false; } mWkbType = type; QgsWKBTypes::Type ringType; switch ( mWkbType ) { case QgsWKBTypes::PolygonZ: ringType = QgsWKBTypes::LineStringZ; break; case QgsWKBTypes::PolygonM: ringType = QgsWKBTypes::LineStringM; break; case QgsWKBTypes::PolygonZM: ringType = QgsWKBTypes::LineStringZM; break; case QgsWKBTypes::Polygon25D: ringType = QgsWKBTypes::LineString25D; break; default: ringType = QgsWKBTypes::LineString; break; } int nRings; wkbPtr >> nRings; for ( int i = 0; i < nRings; ++i ) { QgsLineStringV2* line = new QgsLineStringV2(); line->fromWkbPoints( ringType, wkbPtr ); /*if ( !line->isRing() ) { delete line; continue; }*/ if ( !mExteriorRing ) { mExteriorRing = line; } else { mInteriorRings.append( line ); } } return true; }
double QgsDistanceArea::measurePerimeter( const QgsGeometry* geometry ) { if ( !geometry ) return 0.0; const unsigned char* wkb = geometry->asWkb(); if ( !wkb ) return 0.0; QgsConstWkbPtr wkbPtr( wkb + 1 ); QGis::WkbType wkbType; wkbPtr >> wkbType; double res = 0.0, resTotal = 0.0; int count, i; // measure distance or area based on what is the type of geometry bool hasZptr = false; switch ( wkbType ) { case QGis::WKBLineString25D: case QGis::WKBLineString: case QGis::WKBMultiLineString25D: case QGis::WKBMultiLineString: return 0.0; case QGis::WKBPolygon25D: hasZptr = true; //intentional fall-through case QGis::WKBPolygon: measurePolygon( wkb, 0, &res, hasZptr ); QgsDebugMsg( "returning " + QString::number( res ) ); return res; case QGis::WKBMultiPolygon25D: hasZptr = true; //intentional fall-through case QGis::WKBMultiPolygon: wkbPtr >> count; for ( i = 0; i < count; i++ ) { wkbPtr = measurePolygon( wkbPtr, 0, &res, hasZptr ); if ( !wkbPtr ) { QgsDebugMsg( "measurePolygon returned 0" ); break; } resTotal += res; } QgsDebugMsg( "returning " + QString::number( resTotal ) ); return resTotal; default: QgsDebugMsg( QString( "measure: unexpected geometry type: %1" ).arg( wkbType ) ); return 0; } }
const unsigned char* QgsSymbolV2::_getLineString( QPolygonF& pts, QgsRenderContext& context, const unsigned char* wkb, bool clipToExtent ) { QgsConstWkbPtr wkbPtr( wkb + 1 ); unsigned int wkbType, nPoints; wkbPtr >> wkbType >> nPoints; bool hasZValue = QgsWKBTypes::hasZ( static_cast< QgsWKBTypes::Type >( wkbType ) ); bool hasMValue = QgsWKBTypes::hasM( static_cast< QgsWKBTypes::Type >( wkbType ) ); double x = 0.0; double y = 0.0; const QgsCoordinateTransform* ct = context.coordinateTransform(); const QgsMapToPixel& mtp = context.mapToPixel(); //apply clipping for large lines to achieve a better rendering performance if ( clipToExtent && nPoints > 1 ) { const QgsRectangle& e = context.extent(); double cw = e.width() / 10; double ch = e.height() / 10; QgsRectangle clipRect( e.xMinimum() - cw, e.yMinimum() - ch, e.xMaximum() + cw, e.yMaximum() + ch ); wkbPtr = QgsConstWkbPtr( QgsClipper::clippedLineWKB( wkb, clipRect, pts ) ); } else { pts.resize( nPoints ); QPointF* ptr = pts.data(); for ( unsigned int i = 0; i < nPoints; ++i, ++ptr ) { wkbPtr >> x >> y; if ( hasZValue ) wkbPtr += sizeof( double ); if ( hasMValue ) wkbPtr += sizeof( double ); *ptr = QPointF( x, y ); } } //transform the QPolygonF to screen coordinates if ( ct ) { ct->transformPolygon( pts ); } QPointF* ptr = pts.data(); for ( int i = 0; i < pts.size(); ++i, ++ptr ) { mtp.transformInPlace( ptr->rx(), ptr->ry() ); } return wkbPtr; }
QgsGeometry *QgsGPXFeatureIterator::readWaypointGeometry( const QgsWaypoint &wpt ) { int size = 1 + sizeof( int ) + 2 * sizeof( double ); unsigned char *geo = new unsigned char[size]; QgsWkbPtr wkbPtr( geo, size ); wkbPtr << ( char ) QgsApplication::endian() << QgsWkbTypes::Point << wpt.lon << wpt.lat; QgsGeometry *g = new QgsGeometry(); g->fromWkb( geo, size ); return g; }
bool QgsLineStringV2::fromWkb( const unsigned char* wkb ) { if ( !wkb ) { return false; } QgsConstWkbPtr wkbPtr( wkb ); QgsWKBTypes::Type type = wkbPtr.readHeader(); if ( QgsWKBTypes::flatType( type ) != QgsWKBTypes::LineString ) { return false; } mWkbType = type; importVerticesFromWkb( wkbPtr ); return true; }
QgsGeometry *QgsGPXFeatureIterator::readTrackGeometry( const QgsTrack &trk ) { // TODO: support multi line string for segments if ( trk.segments.isEmpty() ) return nullptr; // A track consists of several segments. Add all those segments into one. int totalPoints = 0; for ( int i = 0; i < trk.segments.size(); i ++ ) { totalPoints += trk.segments[i].points.size(); } if ( totalPoints == 0 ) return nullptr; //QgsDebugMsg( "GPX feature track total points: " + QString::number( totalPoints ) ); // some wkb voodoo int size = 1 + 2 * sizeof( int ) + 2 * sizeof( double ) * totalPoints; unsigned char *geo = new unsigned char[size]; if ( !geo ) { QgsDebugMsg( "Track too large!" ); return nullptr; } QgsWkbPtr wkbPtr( geo, size ); wkbPtr << ( char ) QgsApplication::endian() << QgsWkbTypes::LineString << totalPoints; for ( int k = 0; k < trk.segments.size(); k++ ) { int nPoints = trk.segments[k].points.size(); for ( int i = 0; i < nPoints; ++i ) { wkbPtr << trk.segments[k].points[i].lon << trk.segments[k].points[i].lat; } } //create QgsGeometry and use it for intersection test //if geometry is to be fetched, it is attached to the feature, otherwise we delete it QgsGeometry *g = new QgsGeometry(); g->fromWkb( geo, size ); return g; }
const unsigned char* QgsFeatureRendererV2::_getPoint( QPointF& pt, QgsRenderContext& context, const unsigned char* wkb ) { QgsConstWkbPtr wkbPtr( wkb + 1 ); unsigned int wkbType; wkbPtr >> wkbType >> pt.rx() >> pt.ry(); if ( static_cast< QgsWKBTypes::Type >( wkbType ) == QgsWKBTypes::Point25D || static_cast< QgsWKBTypes::Type >( wkbType ) == QgsWKBTypes::PointZ ) wkbPtr += sizeof( double ); if ( context.coordinateTransform() ) { double z = 0; // dummy variable for coordiante transform context.coordinateTransform()->transformInPlace( pt.rx(), pt.ry(), z ); } context.mapToPixel().transformInPlace( pt.rx(), pt.ry() ); return wkbPtr; }
QgsGeometry *QgsGPXFeatureIterator::readRouteGeometry( const QgsRoute &rte ) { // some wkb voodoo int size = 1 + 2 * sizeof( int ) + 2 * sizeof( double ) * rte.points.size(); unsigned char *geo = new unsigned char[size]; QgsWkbPtr wkbPtr( geo, size ); wkbPtr << ( char ) QgsApplication::endian() << QgsWkbTypes::LineString << rte.points.size(); for ( int i = 0; i < rte.points.size(); ++i ) { wkbPtr << rte.points[i].lon << rte.points[i].lat; } //create QgsGeometry and use it for intersection test //if geometry is to be fetched, it is attached to the feature, otherwise we delete it QgsGeometry *g = new QgsGeometry(); g->fromWkb( geo, size ); return g; }
int QgsGml::createPolygonFromFragments() { mCurrentWKBSize = 1 + 2 * sizeof( int ) + totalWKBFragmentSize(); mCurrentWKB = QgsWkbPtr( new unsigned char[mCurrentWKBSize], mCurrentWKBSize ); QgsWkbPtr wkbPtr( mCurrentWKB ); wkbPtr << mEndian << QGis::WKBPolygon << mCurrentWKBFragments.constBegin()->size(); QList<QgsWkbPtr>::const_iterator wkbIt = mCurrentWKBFragments.constBegin()->constBegin(); for ( ; wkbIt != mCurrentWKBFragments.constBegin()->constEnd(); ++wkbIt ) { memcpy( wkbPtr, *wkbIt, wkbIt->size() ); wkbPtr += wkbIt->size(); delete[] *wkbIt; } mCurrentWKBFragments.clear(); *mWkbType = QGis::WKBPolygon; return 0; }
int QgsGml::createMultiLineFromFragments() { mCurrentWKBSize = 1 + 2 * sizeof( int ) + totalWKBFragmentSize(); mCurrentWKB = QgsWkbPtr( new unsigned char[mCurrentWKBSize], mCurrentWKBSize ); QgsWkbPtr wkbPtr( mCurrentWKB, mCurrentWKBSize ); wkbPtr << mEndian << QGis::WKBMultiLineString << mCurrentWKBFragments.constBegin()->size(); //copy (and delete) all the wkb fragments QList<QgsWkbPtr>::const_iterator wkbIt = mCurrentWKBFragments.constBegin()->constBegin(); for ( ; wkbIt != mCurrentWKBFragments.constBegin()->constEnd(); ++wkbIt ) { memcpy( wkbPtr, *wkbIt, wkbIt->size() ); wkbPtr += wkbIt->size(); delete[] *wkbIt; } mCurrentWKBFragments.clear(); *mWkbType = QGis::WKBMultiLineString; return 0; }
void QgsFeatureRendererV2::renderFeatureWithSymbol( QgsFeature& feature, QgsSymbolV2* symbol, QgsRenderContext& context, int layer, bool selected, bool drawVertexMarker ) { QgsSymbolV2::SymbolType symbolType = symbol->type(); const QgsGeometry* geom = feature.constGeometry(); if ( !geom || !geom->geometry() ) { return; } const QgsGeometry* segmentizedGeometry = geom; bool deleteSegmentizedGeometry = false; context.setGeometry( geom->geometry() ); //convert curve types to normal point/line/polygon ones switch ( QgsWKBTypes::flatType( geom->geometry()->wkbType() ) ) { case QgsWKBTypes::CurvePolygon: case QgsWKBTypes::CircularString: case QgsWKBTypes::CompoundCurve: case QgsWKBTypes::MultiSurface: case QgsWKBTypes::MultiCurve: { QgsAbstractGeometryV2* g = geom->geometry()->segmentize(); if ( !g ) { return; } segmentizedGeometry = new QgsGeometry( g ); deleteSegmentizedGeometry = true; break; } default: break; } switch ( QgsWKBTypes::flatType( segmentizedGeometry->geometry()->wkbType() ) ) { case QgsWKBTypes::Point: { if ( symbolType != QgsSymbolV2::Marker ) { QgsDebugMsg( "point can be drawn only with marker symbol!" ); break; } QPointF pt; _getPoint( pt, context, segmentizedGeometry->asWkb() ); (( QgsMarkerSymbolV2* )symbol )->renderPoint( pt, &feature, context, layer, selected ); if ( context.testFlag( QgsRenderContext::DrawSymbolBounds ) ) { //draw debugging rect context.painter()->setPen( Qt::red ); context.painter()->setBrush( QColor( 255, 0, 0, 100 ) ); context.painter()->drawRect((( QgsMarkerSymbolV2* )symbol )->bounds( pt, context ) ); } } break; case QgsWKBTypes::LineString: { if ( symbolType != QgsSymbolV2::Line ) { QgsDebugMsg( "linestring can be drawn only with line symbol!" ); break; } QPolygonF pts; _getLineString( pts, context, segmentizedGeometry->asWkb(), symbol->clipFeaturesToExtent() ); (( QgsLineSymbolV2* )symbol )->renderPolyline( pts, &feature, context, layer, selected ); } break; case QgsWKBTypes::Polygon: { if ( symbolType != QgsSymbolV2::Fill ) { QgsDebugMsg( "polygon can be drawn only with fill symbol!" ); break; } QPolygonF pts; QList<QPolygonF> holes; _getPolygon( pts, holes, context, segmentizedGeometry->asWkb(), symbol->clipFeaturesToExtent() ); (( QgsFillSymbolV2* )symbol )->renderPolygon( pts, ( holes.count() ? &holes : NULL ), &feature, context, layer, selected ); } break; case QgsWKBTypes::MultiPoint: { if ( symbolType != QgsSymbolV2::Marker ) { QgsDebugMsg( "multi-point can be drawn only with marker symbol!" ); break; } QgsConstWkbPtr wkbPtr( segmentizedGeometry->asWkb() + 1 + sizeof( int ) ); unsigned int num; wkbPtr >> num; const unsigned char* ptr = wkbPtr; QPointF pt; for ( unsigned int i = 0; i < num; ++i ) { ptr = QgsConstWkbPtr( _getPoint( pt, context, ptr ) ); (( QgsMarkerSymbolV2* )symbol )->renderPoint( pt, &feature, context, layer, selected ); } } break; case QgsWKBTypes::MultiCurve: case QgsWKBTypes::MultiLineString: { if ( symbolType != QgsSymbolV2::Line ) { QgsDebugMsg( "multi-linestring can be drawn only with line symbol!" ); break; } QgsConstWkbPtr wkbPtr( segmentizedGeometry->asWkb() + 1 + sizeof( int ) ); unsigned int num; wkbPtr >> num; const unsigned char* ptr = wkbPtr; QPolygonF pts; const QgsGeometryCollectionV2* geomCollection = dynamic_cast<const QgsGeometryCollectionV2*>( geom->geometry() ); for ( unsigned int i = 0; i < num; ++i ) { if ( geomCollection ) { context.setGeometry( geomCollection->geometryN( i ) ); } ptr = QgsConstWkbPtr( _getLineString( pts, context, ptr, symbol->clipFeaturesToExtent() ) ); (( QgsLineSymbolV2* )symbol )->renderPolyline( pts, &feature, context, layer, selected ); } } break; case QgsWKBTypes::MultiSurface: case QgsWKBTypes::MultiPolygon: { if ( symbolType != QgsSymbolV2::Fill ) { QgsDebugMsg( "multi-polygon can be drawn only with fill symbol!" ); break; } QgsConstWkbPtr wkbPtr( segmentizedGeometry->asWkb() + 1 + sizeof( int ) ); unsigned int num; wkbPtr >> num; const unsigned char* ptr = wkbPtr; QPolygonF pts; QList<QPolygonF> holes; const QgsGeometryCollectionV2* geomCollection = dynamic_cast<const QgsGeometryCollectionV2*>( geom->geometry() ); for ( unsigned int i = 0; i < num; ++i ) { if ( geomCollection ) { context.setGeometry( geomCollection->geometryN( i ) ); } ptr = _getPolygon( pts, holes, context, ptr, symbol->clipFeaturesToExtent() ); (( QgsFillSymbolV2* )symbol )->renderPolygon( pts, ( holes.count() ? &holes : NULL ), &feature, context, layer, selected ); } break; } default: QgsDebugMsg( QString( "feature %1: unsupported wkb type 0x%2 for rendering" ).arg( feature.id() ).arg( geom->wkbType(), 0, 16 ) ); } if ( drawVertexMarker ) { const QgsCoordinateTransform* ct = context.coordinateTransform(); const QgsMapToPixel& mtp = context.mapToPixel(); QgsPointV2 vertexPoint; QgsVertexId vertexId; double x, y, z; QPointF mapPoint; while ( geom->geometry()->nextVertex( vertexId, vertexPoint ) ) { //transform x = vertexPoint.x(); y = vertexPoint.y(); z = vertexPoint.z(); if ( ct ) { ct->transformInPlace( x, y, z ); } mapPoint.setX( x ); mapPoint.setY( y ); mtp.transformInPlace( mapPoint.rx(), mapPoint.ry() ); renderVertexMarker( mapPoint, context ); } } if ( deleteSegmentizedGeometry ) { delete segmentizedGeometry; } }
const unsigned char* QgsSymbolV2::_getPolygon( QPolygonF& pts, QList<QPolygonF>& holes, QgsRenderContext& context, const unsigned char* wkb, bool clipToExtent ) { QgsConstWkbPtr wkbPtr( wkb + 1 ); unsigned int wkbType, numRings; wkbPtr >> wkbType >> numRings; if ( numRings == 0 ) // sanity check for zero rings in polygon return wkbPtr; bool hasZValue = QgsWKBTypes::hasZ( static_cast< QgsWKBTypes::Type >( wkbType ) ); bool hasMValue = QgsWKBTypes::hasM( static_cast< QgsWKBTypes::Type >( wkbType ) ); double x, y; holes.clear(); const QgsCoordinateTransform* ct = context.coordinateTransform(); const QgsMapToPixel& mtp = context.mapToPixel(); const QgsRectangle& e = context.extent(); double cw = e.width() / 10; double ch = e.height() / 10; QgsRectangle clipRect( e.xMinimum() - cw, e.yMinimum() - ch, e.xMaximum() + cw, e.yMaximum() + ch ); for ( unsigned int idx = 0; idx < numRings; idx++ ) { unsigned int nPoints; wkbPtr >> nPoints; QPolygonF poly( nPoints ); // Extract the points from the WKB and store in a pair of vectors. QPointF* ptr = poly.data(); for ( unsigned int jdx = 0; jdx < nPoints; ++jdx, ++ptr ) { wkbPtr >> x >> y; if ( hasZValue ) wkbPtr += sizeof( double ); if ( hasMValue ) wkbPtr += sizeof( double ); *ptr = QPointF( x, y ); } if ( nPoints < 1 ) continue; //clip close to view extent, if needed QRectF ptsRect = poly.boundingRect(); if ( clipToExtent && !context.extent().contains( ptsRect ) ) QgsClipper::trimPolygon( poly, clipRect ); //transform the QPolygonF to screen coordinates if ( ct ) { ct->transformPolygon( poly ); } ptr = poly.data(); for ( int i = 0; i < poly.size(); ++i, ++ptr ) { mtp.transformInPlace( ptr->rx(), ptr->ry() ); } if ( idx == 0 ) pts = poly; else holes.append( poly ); } return wkbPtr; }
const unsigned char *QgsDistanceArea::measurePolygon( const unsigned char* feature, double* area, double* perimeter, bool hasZptr ) const { if ( !feature ) { QgsDebugMsg( "no feature to measure" ); return nullptr; } QgsConstWkbPtr wkbPtr( feature + 1 + sizeof( int ) ); // get number of rings in the polygon int numRings; wkbPtr >> numRings; if ( numRings == 0 ) { QgsDebugMsg( "no rings to measure" ); return nullptr; } // Set pointer to the first ring QList<QgsPoint> points; QgsPoint pnt; double x, y; if ( area ) *area = 0; if ( perimeter ) *perimeter = 0; try { for ( int idx = 0; idx < numRings; idx++ ) { int nPoints; wkbPtr >> nPoints; // Extract the points from the WKB and store in a pair of // vectors. for ( int jdx = 0; jdx < nPoints; jdx++ ) { wkbPtr >> x >> y; if ( hasZptr ) { // totally ignore Z value wkbPtr += sizeof( double ); } pnt = QgsPoint( x, y ); if ( mEllipsoidalMode && ( mEllipsoid != GEO_NONE ) ) { pnt = mCoordTransform->transform( pnt ); } points.append( pnt ); } if ( points.size() > 2 ) { if ( area ) { double areaTmp = computePolygonArea( points ); if ( idx == 0 ) { // exterior ring *area += areaTmp; } else { *area -= areaTmp; // interior rings } } if ( perimeter ) { if ( idx == 0 ) { // exterior ring *perimeter += computeDistance( points ); } } } points.clear(); } } catch ( QgsCsException &cse ) { Q_UNUSED( cse ); QgsMessageLog::logMessage( QObject::tr( "Caught a coordinate system exception while trying to transform a point. Unable to calculate polygon area or perimeter." ) ); } return wkbPtr; }
void QgsPointDisplacementRenderer::drawGroup( const DisplacementGroup& group, QgsRenderContext& context ) { const QgsFeature& feature = group.begin().value().first; bool selected = mSelectedFeatures.contains( feature.id() ); // maybe we should highlight individual features instead of the whole group? //get list of labels and symbols QStringList labelAttributeList; QList< QgsMarkerSymbolV2* > symbolList; QgsFeatureList featureList; QgsMultiPointV2* groupMultiPoint = new QgsMultiPointV2(); for ( DisplacementGroup::const_iterator attIt = group.constBegin(); attIt != group.constEnd(); ++attIt ) { labelAttributeList << ( mDrawLabels ? getLabel( attIt.value().first ) : QString() ); symbolList << dynamic_cast<QgsMarkerSymbolV2*>( attIt.value().second ); featureList << attIt.value().first; groupMultiPoint->addGeometry( attIt.value().first.constGeometry()->geometry()->clone() ); } //calculate centroid of all points, this will be center of group QgsGeometry groupGeom( groupMultiPoint ); QgsGeometry* centroid = groupGeom.centroid(); QPointF pt; QgsConstWkbPtr wkbPtr( centroid->asWkb(), centroid->wkbSize() ); _getPoint( pt, context, wkbPtr ); delete centroid; //calculate max diagonal size from all symbols in group double diagonal = 0; Q_FOREACH ( QgsMarkerSymbolV2* symbol, symbolList ) { if ( symbol ) { diagonal = qMax( diagonal, QgsSymbolLayerV2Utils::convertToPainterUnits( context, M_SQRT2 * symbol->size(), symbol->sizeUnit(), symbol->sizeMapUnitScale() ) ); } } QgsSymbolV2RenderContext symbolContext( context, QgsSymbolV2::MM, 1.0, selected ); QList<QPointF> symbolPositions; QList<QPointF> labelPositions; double circleRadius = -1.0; calculateSymbolAndLabelPositions( symbolContext, pt, symbolList.size(), diagonal, symbolPositions, labelPositions, circleRadius ); //draw Circle if ( circleRadius > 0 ) drawCircle( circleRadius, symbolContext, pt, symbolList.size() ); //draw mid point if ( labelAttributeList.size() > 1 ) { if ( mCenterSymbol ) { mCenterSymbol->renderPoint( pt, &feature, context, -1, selected ); } else { context.painter()->drawRect( QRectF( pt.x() - symbolContext.outputLineWidth( 1 ), pt.y() - symbolContext.outputLineWidth( 1 ), symbolContext.outputLineWidth( 2 ), symbolContext.outputLineWidth( 2 ) ) ); } } //draw symbols on the circle drawSymbols( featureList, context, symbolList, symbolPositions, selected ); //and also the labels drawLabels( pt, symbolContext, labelPositions, labelAttributeList ); }
void QgsGml::endElement( const XML_Char* el ) { QString elementName( QString::fromUtf8( el ) ); ParseMode theParseMode( mParseModeStack.isEmpty() ? none : mParseModeStack.top() ); QStringList splitName = elementName.split( NS_SEPARATOR ); QString localName = splitName.last(); QString ns = splitName.size() > 1 ? splitName.first() : ""; if (( theParseMode == coordinate && elementName == GML_NAMESPACE + NS_SEPARATOR + "coordinates" ) || ( theParseMode == posList && ( elementName == GML_NAMESPACE + NS_SEPARATOR + "pos" || elementName == GML_NAMESPACE + NS_SEPARATOR + "posList" ) ) ) { mParseModeStack.pop(); } else if ( theParseMode == attribute && localName == mAttributeName ) //add a thematic attribute to the feature { mParseModeStack.pop(); setAttribute( mAttributeName, mStringCash ); } else if ( theParseMode == geometry && localName == mGeometryAttribute ) { mParseModeStack.pop(); } else if ( theParseMode == boundingBox && elementName == GML_NAMESPACE + NS_SEPARATOR + "boundedBy" ) { //create bounding box from mStringCash if ( createBBoxFromCoordinateString( mCurrentExtent, mStringCash ) != 0 ) { QgsDebugMsg( "creation of bounding box failed" ); } mParseModeStack.pop(); } else if ( theParseMode == feature && localName == mTypeName ) { Q_ASSERT( mCurrentFeature ); if ( mCurrentWKBSize > 0 ) { QgsGeometry *g = new QgsGeometry(); g->fromWkb( mCurrentWKB, mCurrentWKBSize ); mCurrentFeature->setGeometry( g ); mCurrentWKB = QgsWkbPtr( nullptr, 0 ); } else if ( !mCurrentExtent.isEmpty() ) { mCurrentFeature->setGeometry( QgsGeometry::fromRect( mCurrentExtent ) ); } else { mCurrentFeature->setGeometry( nullptr ); } mCurrentFeature->setValid( true ); mFeatures.insert( mCurrentFeature->id(), mCurrentFeature ); if ( !mCurrentFeatureId.isEmpty() ) { mIdMap.insert( mCurrentFeature->id(), mCurrentFeatureId ); } mCurrentFeature = nullptr; ++mFeatureCount; mParseModeStack.pop(); } else if ( elementName == GML_NAMESPACE + NS_SEPARATOR + "Point" ) { QList<QgsPoint> pointList; if ( pointsFromString( pointList, mStringCash ) != 0 ) { //error } if ( pointList.isEmpty() ) return; // error if ( theParseMode == QgsGml::geometry ) { //directly add WKB point to the feature if ( getPointWKB( mCurrentWKB, *( pointList.constBegin() ) ) != 0 ) { //error } if ( *mWkbType != QGis::WKBMultiPoint ) //keep multitype in case of geometry type mix { *mWkbType = QGis::WKBPoint; } } else //multipoint, add WKB as fragment { QgsWkbPtr wkbPtr( nullptr, 0 ); if ( getPointWKB( wkbPtr, *( pointList.constBegin() ) ) != 0 ) { //error } if ( !mCurrentWKBFragments.isEmpty() ) { mCurrentWKBFragments.last().push_back( wkbPtr ); } else { QgsDebugMsg( "No wkb fragments" ); delete [] wkbPtr; } } } else if ( elementName == GML_NAMESPACE + NS_SEPARATOR + "LineString" ) { //add WKB point to the feature QList<QgsPoint> pointList; if ( pointsFromString( pointList, mStringCash ) != 0 ) { //error } if ( theParseMode == QgsGml::geometry ) { if ( getLineWKB( mCurrentWKB, pointList ) != 0 ) { //error } if ( *mWkbType != QGis::WKBMultiLineString )//keep multitype in case of geometry type mix { *mWkbType = QGis::WKBLineString; } } else //multiline, add WKB as fragment { QgsWkbPtr wkbPtr( nullptr, 0 ); if ( getLineWKB( wkbPtr, pointList ) != 0 ) { //error } if ( !mCurrentWKBFragments.isEmpty() ) { mCurrentWKBFragments.last().push_back( wkbPtr ); } else { QgsDebugMsg( "no wkb fragments" ); delete [] wkbPtr; } } } else if (( theParseMode == geometry || theParseMode == multiPolygon ) && elementName == GML_NAMESPACE + NS_SEPARATOR + "LinearRing" ) { QList<QgsPoint> pointList; if ( pointsFromString( pointList, mStringCash ) != 0 ) { //error } QgsWkbPtr wkbPtr( nullptr, 0 ); if ( getRingWKB( wkbPtr, pointList ) != 0 ) { //error } if ( !mCurrentWKBFragments.isEmpty() ) { mCurrentWKBFragments.last().push_back( wkbPtr ); } else { delete[] wkbPtr; QgsDebugMsg( "no wkb fragments" ); } } else if (( theParseMode == geometry || theParseMode == multiPolygon ) && elementName == GML_NAMESPACE + NS_SEPARATOR + "Polygon" ) { if ( *mWkbType != QGis::WKBMultiPolygon )//keep multitype in case of geometry type mix { *mWkbType = QGis::WKBPolygon; } if ( theParseMode == geometry ) { createPolygonFromFragments(); } } else if ( theParseMode == multiPoint && elementName == GML_NAMESPACE + NS_SEPARATOR + "MultiPoint" ) { *mWkbType = QGis::WKBMultiPoint; mParseModeStack.pop(); createMultiPointFromFragments(); } else if ( theParseMode == multiLine && elementName == GML_NAMESPACE + NS_SEPARATOR + "MultiLineString" ) { *mWkbType = QGis::WKBMultiLineString; mParseModeStack.pop(); createMultiLineFromFragments(); } else if ( theParseMode == multiPolygon && elementName == GML_NAMESPACE + NS_SEPARATOR + "MultiPolygon" ) { *mWkbType = QGis::WKBMultiPolygon; mParseModeStack.pop(); createMultiPolygonFromFragments(); } }