void QgsMapToolAddCircularString::activate() { if ( mParentTool ) { mParentTool->deleteTempRubberBand(); if ( mPoints.isEmpty() ) { // if the parent tool has a curve, use its last point as the first point in this curve const QgsCompoundCurveV2* compoundCurve = mParentTool->captureCurve(); if ( compoundCurve && compoundCurve->nCurves() > 0 ) { const QgsCurveV2* curve = compoundCurve->curveAt( compoundCurve->nCurves() - 1 ); if ( curve ) { //mParentTool->captureCurve() is in layer coordinates, but we need map coordinates QgsPointV2 endPointLayerCoord = curve->endPoint(); QgsPoint mapPoint = toMapCoordinates( mCanvas->currentLayer(), QgsPoint( endPointLayerCoord.x(), endPointLayerCoord.y() ) ); mPoints.append( QgsPointV2( mapPoint ) ); if ( !mTempRubberBand ) { mTempRubberBand = createGeometryRubberBand(( mode() == CapturePolygon ) ? Qgis::Polygon : Qgis::Line, true ); mTempRubberBand->show(); } QgsCircularStringV2* c = new QgsCircularStringV2(); QgsPointSequenceV2 rubberBandPoints = mPoints; rubberBandPoints.append( QgsPointV2( mapPoint ) ); c->setPoints( rubberBandPoints ); mTempRubberBand->setGeometry( c ); } } } } QgsMapToolCapture::activate(); }
void QgsCircularStringV2::addToPainterPath( QPainterPath& path ) const { int nPoints = numPoints(); if ( nPoints < 1 ) { return; } if ( path.isEmpty() || path.currentPosition() != QPointF( mX[0], mY[0] ) ) { path.moveTo( QPointF( mX[0], mY[0] ) ); } for ( int i = 0; i < ( nPoints - 2 ) ; i += 2 ) { QgsPointSequenceV2 pt; segmentize( QgsPointV2( mX[i], mY[i] ), QgsPointV2( mX[i + 1], mY[i + 1] ), QgsPointV2( mX[i + 2], mY[i + 2] ), pt ); for ( int j = 1; j < pt.size(); ++j ) { path.lineTo( pt.at( j ).x(), pt.at( j ).y() ); } //arcTo( path, QPointF( mX[i], mY[i] ), QPointF( mX[i + 1], mY[i + 1] ), QPointF( mX[i + 2], mY[i + 2] ) ); } //if number of points is even, connect to last point with straight line (even though the circular string is not valid) if ( nPoints % 2 == 0 ) { path.lineTo( mX[ nPoints - 1 ], mY[ nPoints - 1 ] ); } }
QgsRectangle QgsCircularStringV2::segmentBoundingBox( const QgsPointV2& pt1, const QgsPointV2& pt2, const QgsPointV2& pt3 ) { double centerX, centerY, radius; QgsGeometryUtils::circleCenterRadius( pt1, pt2, pt3, radius, centerX, centerY ); double p1Angle = QgsGeometryUtils::ccwAngle( pt1.y() - centerY, pt1.x() - centerX ); if ( p1Angle > 360 ) { p1Angle -= 360; } double p2Angle = QgsGeometryUtils::ccwAngle( pt2.y() - centerY, pt2.x() - centerX ); if ( p2Angle > 360 ) { p2Angle -= 360; } double p3Angle = QgsGeometryUtils::ccwAngle( pt3.y() - centerY, pt3.x() - centerX ); if ( p3Angle > 360 ) { p3Angle -= 360; } //start point, end point and compass points in between can be on bounding box QgsRectangle bbox( pt1.x(), pt1.y(), pt1.x(), pt1.y() ); bbox.combineExtentWith( pt3.x(), pt3.y() ); QgsPointSequenceV2 compassPoints = compassPointsOnSegment( p1Angle, p2Angle, p3Angle, centerX, centerY, radius ); QgsPointSequenceV2::const_iterator cpIt = compassPoints.constBegin(); for ( ; cpIt != compassPoints.constEnd(); ++cpIt ) { bbox.combineExtentWith( cpIt->x(), cpIt->y() ); } return bbox; }
void QgsCircularStringV2::points( QgsPointSequenceV2 &pts ) const { pts.clear(); int nPts = numPoints(); for ( int i = 0; i < nPts; ++i ) { pts.push_back( pointN( i ) ); } }
int QgsVectorLayerEditUtils::addRing( const QList<QgsPoint>& ring, const QgsFeatureIds& targetFeatureIds, QgsFeatureId* modifiedFeatureId ) { QgsLineStringV2* ringLine = new QgsLineStringV2(); QgsPointSequenceV2 ringPoints; QList<QgsPoint>::const_iterator ringIt = ring.constBegin(); for ( ; ringIt != ring.constEnd(); ++ringIt ) { ringPoints.append( QgsPointV2( ringIt->x(), ringIt->y() ) ); } ringLine->setPoints( ringPoints ); return addRing( ringLine, targetFeatureIds, modifiedFeatureId ); }
QgsLineStringV2* QgsGeometryFactory::linestringFromPolyline( const QgsPolyline& polyline ) { QgsLineStringV2* line = new QgsLineStringV2(); QgsPointSequenceV2 points; QgsPolyline::const_iterator it = polyline.constBegin(); for ( ; it != polyline.constEnd(); ++it ) { points.append( QgsPointV2( it->x(), it->y() ) ); } line->setPoints( points ); return line; }
void QgsMapToolCircularStringCurvePoint::cadCanvasReleaseEvent( QgsMapMouseEvent* e ) { QgsPointV2 mapPoint( e->mapPoint() ); if ( e->button() == Qt::LeftButton ) { mPoints.append( mapPoint ); if ( !mCenterPointRubberBand && mShowCenterPointRubberBand ) { createCenterPointRubberBand(); } if ( !mPoints.isEmpty() ) { if ( !mTempRubberBand ) { mTempRubberBand = createGeometryRubberBand(( mode() == CapturePolygon ) ? QgsWkbTypes::PolygonGeometry : QgsWkbTypes::LineGeometry, true ); mTempRubberBand->show(); } QgsCircularStringV2* c = new QgsCircularStringV2(); QgsPointSequenceV2 rubberBandPoints = mPoints.mid( mPoints.size() - 1 - ( mPoints.size() + 1 ) % 2 ); rubberBandPoints.append( mapPoint ); c->setPoints( rubberBandPoints ); mTempRubberBand->setGeometry( c ); } if ( mPoints.size() > 1 && mPoints.size() % 2 ) { if ( !mRubberBand ) { mRubberBand = createGeometryRubberBand(( mode() == CapturePolygon ) ? QgsWkbTypes::PolygonGeometry : QgsWkbTypes::LineGeometry ); mRubberBand->show(); } QgsCircularStringV2* c = new QgsCircularStringV2(); QgsPointSequenceV2 rubberBandPoints = mPoints; rubberBandPoints.append( mapPoint ); c->setPoints( rubberBandPoints ); mRubberBand->setGeometry( c ); removeCenterPointRubberBand(); } } else if ( e->button() == Qt::RightButton ) { deactivate(); if ( mParentTool ) { mParentTool->canvasReleaseEvent( e ); } } }
void QgsCircularStringV2::setPoints( const QgsPointSequenceV2 &points ) { clearCache(); if ( points.size() < 1 ) { mWkbType = QgsWKBTypes::Unknown; mX.clear(); mY.clear(); mZ.clear(); mM.clear(); return; } //get wkb type from first point const QgsPointV2& firstPt = points.at( 0 ); bool hasZ = firstPt.is3D(); bool hasM = firstPt.isMeasure(); setZMTypeFromSubGeometry( &firstPt, QgsWKBTypes::CircularString ); mX.resize( points.size() ); mY.resize( points.size() ); if ( hasZ ) { mZ.resize( points.size() ); } else { mZ.clear(); } if ( hasM ) { mM.resize( points.size() ); } else { mM.clear(); } for ( int i = 0; i < points.size(); ++i ) { mX[i] = points[i].x(); mY[i] = points[i].y(); if ( hasZ ) { mZ[i] = points[i].z(); } if ( hasM ) { mM[i] = points[i].m(); } } }
void QgsMapToolAddCircularString::updateCenterPointRubberBand( const QgsPointV2& pt ) { if ( !mShowCenterPointRubberBand || !mCenterPointRubberBand || mPoints.size() < 2 ) { return; } if (( mPoints.size() ) % 2 != 0 ) { return; } //create circular string QgsCircularStringV2* cs = new QgsCircularStringV2(); QgsPointSequenceV2 csPoints; csPoints.append( mPoints.at( mPoints.size() - 2 ) ); csPoints.append( mPoints.at( mPoints.size() - 1 ) ); csPoints.append( pt ); cs->setPoints( csPoints ); QgsPointV2 center; double radius; QgsGeometryUtils::circleCenterRadius( csPoints.at( 0 ), csPoints.at( 1 ), csPoints.at( 2 ), radius, center.rx(), center.ry() ); QgsLineStringV2* segment1 = new QgsLineStringV2(); segment1->addVertex( center ); segment1->addVertex( csPoints.at( 0 ) ); QgsLineStringV2* segment2 = new QgsLineStringV2(); segment2->addVertex( csPoints.at( 2 ) ); segment2->addVertex( center ); QgsCompoundCurveV2* cc = new QgsCompoundCurveV2(); cc->addCurve( segment1 ); cc->addCurve( cs ); cc->addCurve( segment2 ); QgsCurvePolygonV2* cp = new QgsCurvePolygonV2(); cp->setExteriorRing( cc ); mCenterPointRubberBand->setGeometry( cp ); mCenterPointRubberBand->show(); }
void QgsCircularStringV2::segmentize( const QgsPointV2& p1, const QgsPointV2& p2, const QgsPointV2& p3, QgsPointSequenceV2 &points, double tolerance, SegmentationToleranceType toleranceType ) const { //adapted code from postgis double radius = 0; double centerX = 0; double centerY = 0; QgsGeometryUtils::circleCenterRadius( p1, p2, p3, radius, centerX, centerY ); int segSide = segmentSide( p1, p3, p2 ); if ( p1 != p3 && ( radius < 0 || qgsDoubleNear( segSide, 0.0 ) ) ) //points are colinear { points.append( p1 ); points.append( p2 ); points.append( p3 ); return; } bool clockwise = false; if ( segSide == -1 ) { clockwise = true; } double increment = tolerance; //one segment per degree if ( toleranceType == QgsAbstractGeometryV2::MaximumDifference ) { double halfAngle = acos( -tolerance / radius + 1 ); increment = 2 * halfAngle; } //angles of pt1, pt2, pt3 double a1 = atan2( p1.y() - centerY, p1.x() - centerX ); double a2 = atan2( p2.y() - centerY, p2.x() - centerX ); double a3 = atan2( p3.y() - centerY, p3.x() - centerX ); if ( clockwise ) { increment *= -1; /* Adjust a3 down so we can decrement from a1 to a3 cleanly */ if ( a3 >= a1 ) a3 -= 2.0 * M_PI; if ( a2 > a1 ) a2 -= 2.0 * M_PI; } else { /* Adjust a3 up so we can increment from a1 to a3 cleanly */ if ( a3 <= a1 ) a3 += 2.0 * M_PI; if ( a2 < a1 ) a2 += 2.0 * M_PI; } bool hasZ = is3D(); bool hasM = isMeasure(); double x, y; double z = 0; double m = 0; points.append( p1 ); if ( p2 != p3 && p1 != p2 ) //draw straight line segment if two points have the same position { QgsWKBTypes::Type pointWkbType = QgsWKBTypes::Point; if ( hasZ ) pointWkbType = QgsWKBTypes::addZ( pointWkbType ); if ( hasM ) pointWkbType = QgsWKBTypes::addM( pointWkbType ); //make sure the curve point p2 is part of the segmentized vertices. But only if p1 != p3 bool addP2 = true; if ( qgsDoubleNear( p1.x(), p3.x() ) && qgsDoubleNear( p1.y(), p3.y() ) ) { addP2 = false; } for ( double angle = a1 + increment; clockwise ? angle > a3 : angle < a3; angle += increment ) { if (( addP2 && clockwise && angle < a2 ) || ( addP2 && !clockwise && angle > a2 ) ) { points.append( p2 ); addP2 = false; } x = centerX + radius * cos( angle ); y = centerY + radius * sin( angle ); if ( !hasZ && !hasM ) { points.append( QgsPointV2( x, y ) ); continue; } if ( hasZ ) { z = interpolateArc( angle, a1, a2, a3, p1.z(), p2.z(), p3.z() ); } if ( hasM ) { m = interpolateArc( angle, a1, a2, a3, p1.m(), p2.m(), p3.m() ); } points.append( QgsPointV2( pointWkbType, x, y, z, m ) ); } } points.append( p3 ); }
QgsPointSequenceV2 QgsCircularStringV2::compassPointsOnSegment( double p1Angle, double p2Angle, double p3Angle, double centerX, double centerY, double radius ) { QgsPointSequenceV2 pointList; QgsPointV2 nPoint( centerX, centerY + radius ); QgsPointV2 ePoint( centerX + radius, centerY ); QgsPointV2 sPoint( centerX, centerY - radius ); QgsPointV2 wPoint( centerX - radius, centerY ); if ( p3Angle >= p1Angle ) { if ( p2Angle > p1Angle && p2Angle < p3Angle ) { if ( p1Angle <= 90 && p3Angle >= 90 ) { pointList.append( nPoint ); } if ( p1Angle <= 180 && p3Angle >= 180 ) { pointList.append( wPoint ); } if ( p1Angle <= 270 && p3Angle >= 270 ) { pointList.append( sPoint ); } } else { pointList.append( ePoint ); if ( p1Angle >= 90 || p3Angle <= 90 ) { pointList.append( nPoint ); } if ( p1Angle >= 180 || p3Angle <= 180 ) { pointList.append( wPoint ); } if ( p1Angle >= 270 || p3Angle <= 270 ) { pointList.append( sPoint ); } } } else { if ( p2Angle < p1Angle && p2Angle > p3Angle ) { if ( p1Angle >= 270 && p3Angle <= 270 ) { pointList.append( sPoint ); } if ( p1Angle >= 180 && p3Angle <= 180 ) { pointList.append( wPoint ); } if ( p1Angle >= 90 && p3Angle <= 90 ) { pointList.append( nPoint ); } } else { pointList.append( ePoint ); if ( p1Angle <= 270 || p3Angle >= 270 ) { pointList.append( sPoint ); } if ( p1Angle <= 180 || p3Angle >= 180 ) { pointList.append( wPoint ); } if ( p1Angle <= 90 || p3Angle >= 90 ) { pointList.append( nPoint ); } } } return pointList; }
bool QgsEllipseSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor, const QString& layerName, QgsSymbolV2RenderContext &context, QPointF shift ) const { //width double symbolWidth = mSymbolWidth; if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_WIDTH ) ) //1. priority: data defined setting on symbol layer le { context.setOriginalValueVariable( mSymbolWidth ); symbolWidth = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_WIDTH, context, mSymbolWidth ).toDouble(); } else if ( context.renderHints() & QgsSymbolV2::DataDefinedSizeScale ) //2. priority: is data defined size on symbol level { symbolWidth = mSize; } if ( mSymbolWidthUnit == QgsSymbolV2::MM ) { symbolWidth *= mmMapUnitScaleFactor; } //height double symbolHeight = mSymbolHeight; if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_HEIGHT ) ) //1. priority: data defined setting on symbol layer level { context.setOriginalValueVariable( mSymbolHeight ); symbolHeight = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_HEIGHT, context, mSymbolHeight ).toDouble(); } else if ( context.renderHints() & QgsSymbolV2::DataDefinedSizeScale ) //2. priority: is data defined size on symbol level { symbolHeight = mSize; } if ( mSymbolHeightUnit == QgsSymbolV2::MM ) { symbolHeight *= mmMapUnitScaleFactor; } //outline width double outlineWidth = mOutlineWidth; if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_OUTLINE_WIDTH ) ) { context.setOriginalValueVariable( mOutlineWidth ); outlineWidth = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_OUTLINE_WIDTH, context, mOutlineWidth ).toDouble(); } if ( mOutlineWidthUnit == QgsSymbolV2::MM ) { outlineWidth *= outlineWidth; } //fill color bool ok; QColor fc = mColor; if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_FILL_COLOR ) ) { context.setOriginalValueVariable( QgsSymbolLayerV2Utils::encodeColor( mColor ) ); QString colorString = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_FILL_COLOR, context, QVariant(), &ok ).toString(); if ( ok ) fc = QgsSymbolLayerV2Utils::decodeColor( colorString ); } //outline color QColor oc = mOutlineColor; if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_OUTLINE_COLOR ) ) { context.setOriginalValueVariable( QgsSymbolLayerV2Utils::encodeColor( mOutlineColor ) ); QString colorString = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_OUTLINE_COLOR, context, QVariant(), &ok ).toString(); if ( ok ) oc = QgsSymbolLayerV2Utils::decodeColor( colorString ); } //symbol name QString symbolName = mSymbolName; if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_SYMBOL_NAME ) ) { context.setOriginalValueVariable( mSymbolName ); symbolName = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_SYMBOL_NAME, context, mSymbolName ).toString(); } //offset double offsetX = 0; double offsetY = 0; markerOffset( context, offsetX, offsetY ); QPointF off( offsetX, offsetY ); //priority for rotation: 1. data defined symbol level, 2. symbol layer rotation (mAngle) double rotation = 0.0; if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_ROTATION ) ) { context.setOriginalValueVariable( mAngle ); rotation = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_ROTATION, context, mAngle ).toDouble() + mLineAngle; } else if ( !qgsDoubleNear( mAngle + mLineAngle, 0.0 ) ) { rotation = mAngle + mLineAngle; } rotation = -rotation; //rotation in Qt is counterclockwise if ( rotation ) off = _rotatedOffset( off, rotation ); QTransform t; t.translate( shift.x() + offsetX, shift.y() + offsetY ); if ( !qgsDoubleNear( rotation, 0.0 ) ) t.rotate( rotation ); double halfWidth = symbolWidth / 2.0; double halfHeight = symbolHeight / 2.0; if ( symbolName == "circle" ) { if ( qgsDoubleNear( halfWidth, halfHeight ) ) { QgsPointV2 pt( t.map( QPointF( 0, 0 ) ) ); e.writeFilledCircle( layerName, oc, pt, halfWidth ); } else { QgsPointSequenceV2 line; double stepsize = 2 * M_PI / 40; for ( int i = 0; i < 39; ++i ) { double angle = stepsize * i; double x = halfWidth * cos( angle ); double y = halfHeight * sin( angle ); line << QgsPointV2( t.map( QPointF( x, y ) ) ); } //close ellipse with first point line << line.at( 0 ); if ( mBrush.style() != Qt::NoBrush ) e.writePolygon( QgsRingSequenceV2() << line, layerName, "SOLID", fc ); if ( mPen.style() != Qt::NoPen ) e.writePolyline( line, layerName, "CONTINUOUS", oc, outlineWidth ); } } else if ( symbolName == "rectangle" ) { QgsPointSequenceV2 p; p << QgsPointV2( t.map( QPointF( -halfWidth, -halfHeight ) ) ) << QgsPointV2( t.map( QPointF( halfWidth, -halfHeight ) ) ) << QgsPointV2( t.map( QPointF( halfWidth, halfHeight ) ) ) << QgsPointV2( t.map( QPointF( -halfWidth, halfHeight ) ) ); p << p[0]; if ( mBrush.style() != Qt::NoBrush ) e.writePolygon( QgsRingSequenceV2() << p, layerName, "SOLID", fc ); if ( mPen.style() != Qt::NoPen ) e.writePolyline( p, layerName, "CONTINUOUS", oc, outlineWidth ); return true; } else if ( symbolName == "cross" && mPen.style() != Qt::NoPen ) { e.writePolyline( QgsPointSequenceV2() << QgsPointV2( t.map( QPointF( -halfWidth, 0 ) ) ) << QgsPointV2( t.map( QPointF( halfWidth, 0 ) ) ), layerName, "CONTINUOUS", oc, outlineWidth ); e.writePolyline( QgsPointSequenceV2() << QgsPointV2( t.map( QPointF( 0, halfHeight ) ) ) << QgsPointV2( t.map( QPointF( 0, -halfHeight ) ) ), layerName, "CONTINUOUS", oc, outlineWidth ); return true; } else if ( symbolName == "triangle" ) { QgsPointSequenceV2 p; p << QgsPointV2( t.map( QPointF( -halfWidth, -halfHeight ) ) ) << QgsPointV2( t.map( QPointF( halfWidth, -halfHeight ) ) ) << QgsPointV2( t.map( QPointF( 0, halfHeight ) ) ); p << p[0]; if ( mBrush.style() != Qt::NoBrush ) e.writePolygon( QgsRingSequenceV2() << p, layerName, "SOLID", fc ); if ( mPen.style() != Qt::NoPen ) e.writePolyline( p, layerName, "CONTINUOUS", oc, outlineWidth ); return true; } return false; //soon... }