bool QgsCircularString::insertVertex( QgsVertexId position, const QgsPointV2 &vertex ) { if ( position.vertex > mX.size() || position.vertex < 1 ) { return false; } mX.insert( position.vertex, vertex.x() ); mY.insert( position.vertex, vertex.y() ); if ( is3D() ) { mZ.insert( position.vertex, vertex.z() ); } if ( isMeasure() ) { mM.insert( position.vertex, vertex.m() ); } bool vertexNrEven = ( position.vertex % 2 == 0 ); if ( vertexNrEven ) { insertVertexBetween( position.vertex - 2, position.vertex - 1, position.vertex ); } else { insertVertexBetween( position.vertex, position.vertex + 1, position.vertex - 1 ); } clearCache(); //set bounding box invalid return true; }
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 QgsMapToolIdentify::closestVertexAttributes( const QgsAbstractGeometry& geometry, QgsVertexId vId, QgsMapLayer *layer, QMap< QString, QString >& derivedAttributes ) { QString str = QLocale::system().toString( vId.vertex + 1 ); derivedAttributes.insert( tr( "Closest vertex number" ), str ); QgsPointV2 closestPoint = geometry.vertexAt( vId ); QgsPoint closestPointMapCoords = mCanvas->mapSettings().layerToMapCoordinates( layer, QgsPoint( closestPoint.x(), closestPoint.y() ) ); derivedAttributes.insert( "Closest vertex X", formatXCoordinate( closestPointMapCoords ) ); derivedAttributes.insert( "Closest vertex Y", formatYCoordinate( closestPointMapCoords ) ); if ( closestPoint.is3D() ) { str = QLocale::system().toString( closestPoint.z(), 'g', 10 ); derivedAttributes.insert( "Closest vertex Z", str ); } if ( closestPoint.isMeasure() ) { str = QLocale::system().toString( closestPoint.m(), 'g', 10 ); derivedAttributes.insert( "Closest vertex M", str ); } if ( vId.type == QgsVertexId::CurveVertex ) { double radius, centerX, centerY; QgsVertexId vIdBefore = vId; --vIdBefore.vertex; QgsVertexId vIdAfter = vId; ++vIdAfter.vertex; QgsGeometryUtils::circleCenterRadius( geometry.vertexAt( vIdBefore ), geometry.vertexAt( vId ), geometry.vertexAt( vIdAfter ), radius, centerX, centerY ); derivedAttributes.insert( "Closest vertex radius", QLocale::system().toString( radius ) ); } }
void QgsCircularString::insertVertexBetween( int after, int before, int pointOnCircle ) { double xAfter = mX.at( after ); double yAfter = mY.at( after ); double xBefore = mX.at( before ); double yBefore = mY.at( before ); double xOnCircle = mX.at( pointOnCircle ); double yOnCircle = mY.at( pointOnCircle ); double radius, centerX, centerY; QgsGeometryUtils::circleCenterRadius( QgsPointV2( xAfter, yAfter ), QgsPointV2( xBefore, yBefore ), QgsPointV2( xOnCircle, yOnCircle ), radius, centerX, centerY ); double x = ( xAfter + xBefore ) / 2.0; double y = ( yAfter + yBefore ) / 2.0; QgsPointV2 newVertex = QgsGeometryUtils::pointOnLineWithDistance( QgsPointV2( centerX, centerY ), QgsPointV2( x, y ), radius ); mX.insert( before, newVertex.x() ); mY.insert( before, newVertex.y() ); if ( is3D() ) { mZ.insert( before, ( mZ[after] + mZ[before] ) / 2.0 ); } if ( isMeasure() ) { mM.insert( before, ( mM[after] + mM[before] ) / 2.0 ); } clearCache(); }
void QgsMapToolCapture::canvasMapMoveEvent( QgsMapMouseEvent * e ) { bool snapped = e->isSnapped(); QgsPoint point = e->mapPoint(); if ( !snapped ) { delete mSnappingMarker; mSnappingMarker = 0; } else { if ( !mSnappingMarker ) { mSnappingMarker = new QgsVertexMarker( mCanvas ); mSnappingMarker->setIconType( QgsVertexMarker::ICON_CROSS ); mSnappingMarker->setColor( Qt::magenta ); mSnappingMarker->setPenWidth( 3 ); } mSnappingMarker->setCenter( point ); } if ( !mTempRubberBand && mCaptureCurve.numPoints() > 0 ) { mTempRubberBand = createRubberBand( mCaptureMode == CapturePolygon ? QGis::Polygon : QGis::Line, true ); QgsPointV2 pt = mCaptureCurve.endPoint(); mTempRubberBand->addPoint( QgsPoint( pt.x(), pt.y() ) ); mTempRubberBand->addPoint( point ); } if ( mCaptureMode != CapturePoint && mTempRubberBand && mCapturing ) { mTempRubberBand->movePoint( point ); } } // mouseMoveEvent
bool QgsLineStringV2::insertVertex( const QgsVertexId& position, const QgsPointV2& vertex ) { if ( position.vertex < 0 || position.vertex > mX.size() ) { return false; } if ( mWkbType == QgsWKBTypes::Unknown || mX.isEmpty() ) { setZMTypeFromSubGeometry( &vertex, QgsWKBTypes::LineString ); } mX.insert( position.vertex, vertex.x() ); mY.insert( position.vertex, vertex.y() ); if ( is3D() ) { mZ.insert( position.vertex, vertex.z() ); } if ( isMeasure() ) { mM.insert( position.vertex, vertex.m() ); } mBoundingBox = QgsRectangle(); //set bounding box invalid return true; }
QgsRectangle QgsAbstractGeometry::calculateBoundingBox() const { double xmin = std::numeric_limits<double>::max(); double ymin = std::numeric_limits<double>::max(); double xmax = -std::numeric_limits<double>::max(); double ymax = -std::numeric_limits<double>::max(); QgsVertexId id; QgsPointV2 vertex; double x, y; while ( nextVertex( id, vertex ) ) { x = vertex.x(); y = vertex.y(); if ( x < xmin ) xmin = x; if ( x > xmax ) xmax = x; if ( y < ymin ) ymin = y; if ( y > ymax ) ymax = y; } return QgsRectangle( xmin, ymin, xmax, ymax ); }
double QgsLineStringV2::closestSegment( const QgsPointV2& pt, QgsPointV2& segmentPt, QgsVertexId& vertexAfter, bool* leftOf, double epsilon ) const { double sqrDist = std::numeric_limits<double>::max(); double testDist = 0; double segmentPtX, segmentPtY; int size = mCoords.size(); for ( int i = 1; i < size; ++i ) { const QPointF& prev = mCoords.at( i - 1 ); const QPointF& currentPt = mCoords.at( i ); testDist = QgsGeometryUtils::sqrDistToLine( pt.x(), pt.y(), prev.x(), prev.y(), currentPt.x(), currentPt.y(), segmentPtX, segmentPtY, epsilon ); if ( testDist < sqrDist ) { sqrDist = testDist; segmentPt.setX( segmentPtX ); segmentPt.setY( segmentPtY ); if ( leftOf ) { *leftOf = ( QgsGeometryUtils::leftOfLine( segmentPtX, segmentPtY, prev.x(), prev.y(), pt.x(), pt.y() ) < 0 ); } vertexAfter.part = 0; vertexAfter.ring = 0; vertexAfter.vertex = i; } } return sqrDist; }
void QgsSelectedFeature::moveSelectedVertexes( QgsVector v ) { int nUpdates = 0; Q_FOREACH ( QgsVertexEntry *entry, mVertexMap ) { if ( entry->isSelected() ) nUpdates++; } if ( nUpdates == 0 ) return; mVlayer->beginEditCommand( QObject::tr( "Moved vertices" ) ); int topologicalEditing = QgsProject::instance()->readNumEntry( "Digitizing", "/TopologicalEditing", 0 ); beginGeometryChange(); QMultiMap<double, QgsSnappingResult> currentResultList; for ( int i = mVertexMap.size() - 1; i > -1 && nUpdates > 0; i-- ) { QgsVertexEntry *entry = mVertexMap.value( i, nullptr ); if ( !entry || !entry->isSelected() ) continue; if ( topologicalEditing ) { // snap from current vertex currentResultList.clear(); mVlayer->snapWithContext( entry->pointV1(), ZERO_TOLERANCE, currentResultList, QgsSnapper::SnapToVertex ); } // only last update should trigger the geometry update // as vertex selection gets lost on the update if ( --nUpdates == 0 ) endGeometryChange(); QgsPointV2 p = entry->point(); p.setX( p.x() + v.x() ); p.setY( p.y() + v.y() ); mVlayer->moveVertex( p, mFeatureId, i ); if ( topologicalEditing ) { QMultiMap<double, QgsSnappingResult>::iterator resultIt = currentResultList.begin(); for ( ; resultIt != currentResultList.end(); ++resultIt ) { // move all other if ( mFeatureId != resultIt.value().snappedAtGeometry ) mVlayer->moveVertex( p, resultIt.value().snappedAtGeometry, resultIt.value().snappedVertexNr ); } } } if ( nUpdates > 0 ) endGeometryChange(); mVlayer->endEditCommand(); }
bool QgsSnapIndex::SegmentSnapItem::getProjection( const QgsPointV2 &p, QgsPointV2 &pProj ) { const QgsPointV2& s1 = idxFrom->point(); const QgsPointV2& s2 = idxTo->point(); double nx = s2.y() - s1.y(); double ny = -( s2.x() - s1.x() ); double t = ( p.x() * ny - p.y() * nx - s1.x() * ny + s1.y() * nx ) / (( s2.x() - s1.x() ) * ny - ( s2.y() - s1.y() ) * nx ); if ( t < 0. || t > 1. ) { return false; } pProj = QgsPointV2( s1.x() + ( s2.x() - s1.x() ) * t, s1.y() + ( s2.y() - s1.y() ) * t ); return true; }
void QgsLineStringV2::addVertex( const QgsPointV2& pt ) { if ( mWkbType == QgsWKBTypes::Unknown ) { setZMTypeFromSubGeometry( &pt, QgsWKBTypes::LineString ); } mCoords.append( QPointF( pt.x(), pt.y() ) ); if ( is3D() ) { mZ.append( pt.z() ); } if ( isMeasure() ) { mM.append( pt.m() ); } }
bool QgsLineStringV2::insertVertex( const QgsVertexId& position, const QgsPointV2& vertex ) { if ( position.vertex < 0 || position.vertex > mCoords.size() ) { return false; } mCoords.insert( position.vertex, QPointF( vertex.x(), vertex.y() ) ); if ( is3D() ) { mZ.insert( position.vertex, vertex.z() ); } if ( isMeasure() ) { mM.insert( position.vertex, vertex.m() ); } return true; }
bool QgsNodeEditorModel::setData( const QModelIndex& index, const QVariant& value, int role ) { if ( !index.isValid() || role != Qt::EditRole ) { return false; } if ( index.row() >= mSelectedFeature->vertexMap().count() ) { return false; } double x = ( index.column() == 0 ? value.toDouble() : mSelectedFeature->vertexMap().at( index.row() )->point().x() ); double y = ( index.column() == 1 ? value.toDouble() : mSelectedFeature->vertexMap().at( index.row() )->point().y() ); if ( index.column() == mRCol ) // radius modified { if ( index.row() == 0 || index.row() >= mSelectedFeature->vertexMap().count() - 1 ) return false; double r = value.toDouble(); double x1 = mSelectedFeature->vertexMap().at( index.row() - 1 )->point().x(); double y1 = mSelectedFeature->vertexMap().at( index.row() - 1 )->point().y(); double x2 = x; double y2 = y; double x3 = mSelectedFeature->vertexMap().at( index.row() + 1 )->point().x(); double y3 = mSelectedFeature->vertexMap().at( index.row() + 1 )->point().y(); QgsPointV2 result; if ( QgsGeometryUtils::segmentMidPoint( QgsPointV2( x1, y1 ), QgsPointV2( x3, y3 ), result, r, QgsPointV2( x2, y2 ) ) ) { x = result.x(); y = result.y(); } } double z = ( index.column() == mZCol ? value.toDouble() : mSelectedFeature->vertexMap().at( index.row() )->point().z() ); double m = ( index.column() == mMCol ? value.toDouble() : mSelectedFeature->vertexMap().at( index.row() )->point().m() ); QgsPointV2 p( QgsWkbTypes::PointZM, x, y, z, m ); mLayer->beginEditCommand( QObject::tr( "Moved vertices" ) ); mLayer->moveVertex( p, mSelectedFeature->featureId(), index.row() ); mLayer->endEditCommand(); mLayer->triggerRepaint(); return false; }
bool QgsLineStringV2::insertVertex( const QgsVertexId& position, const QgsPointV2& vertex ) { if ( position.vertex < 0 || position.vertex >= mCoords.size() ) { return false; } mCoords.insert( position.vertex, QPointF( vertex.x(), vertex.y() ) ); if ( is3D() ) { mZ.insert( position.vertex, vertex.z() ); } if ( isMeasure() ) { mM.insert( position.vertex, vertex.m() ); } mBoundingBox = QgsRectangle(); //set bounding box invalid so it needs to be recalculated next time return true; }
void QgsLineStringV2::addVertex( const QgsPointV2& pt ) { if ( mWkbType == QgsWKBTypes::Unknown ) { setZMTypeFromSubGeometry( &pt, QgsWKBTypes::LineString ); } mCoords.append( QPointF( pt.x(), pt.y() ) ); if ( is3D() ) { mZ.append( pt.z() ); } if ( isMeasure() ) { mM.append( pt.m() ); } mBoundingBox = QgsRectangle(); //set bounding box invalid so it needs to be recalculated next time }
int QgsMapToolCapture::addCurve( QgsCurveV2* c ) { if ( !c ) { return 1; } if ( !mRubberBand ) { mRubberBand = createRubberBand( mCaptureMode == CapturePolygon ? QGis::Polygon : QGis::Line ); } QgsLineStringV2* lineString = c->curveToLine(); QList<QgsPointV2> linePoints; lineString->points( linePoints ); delete lineString; QList<QgsPointV2>::const_iterator ptIt = linePoints.constBegin(); for ( ; ptIt != linePoints.constEnd(); ++ptIt ) { mRubberBand->addPoint( QgsPoint( ptIt->x(), ptIt->y() ) ); } if ( !mTempRubberBand ) { mTempRubberBand = createRubberBand( mCaptureMode == CapturePolygon ? QGis::Polygon : QGis::Line, true ); } else { mTempRubberBand->reset(); } QgsPointV2 endPt = c->endPoint(); mTempRubberBand->addPoint( QgsPoint( endPt.x(), endPt.y() ) ); //add last point of c //transform back to layer CRS in case map CRS and layer CRS are different QgsVectorLayer* vlayer = qobject_cast<QgsVectorLayer *>( mCanvas->currentLayer() ); const QgsCoordinateTransform* ct = mCanvas->mapSettings().layerTransform( vlayer ); if ( ct ) { c->transform( *ct, QgsCoordinateTransform::ReverseTransform ); } mCaptureCurve.addCurve( c ); return 0; }
bool QgsCurve::isClosed() const { if ( numPoints() == 0 ) return false; //don't consider M-coordinates when testing closedness QgsPointV2 start = startPoint(); QgsPointV2 end = endPoint(); return ( qgsDoubleNear( start.x(), end.x(), 1E-8 ) && qgsDoubleNear( start.y(), end.y(), 1E-8 ) && qgsDoubleNear( start.z(), end.z(), 1E-8 ) ); }
void QgsLineStringV2::addVertex( const QgsPointV2& pt ) { if ( mWkbType == QgsWKBTypes::Unknown || mX.isEmpty() ) { setZMTypeFromSubGeometry( &pt, QgsWKBTypes::LineString ); } mX.append( pt.x() ); mY.append( pt.y() ); if ( is3D() ) { mZ.append( pt.z() ); } if ( isMeasure() ) { mM.append( pt.m() ); } mBoundingBox = QgsRectangle(); //set bounding box invalid }
void TestQgsGeometryUtils::testSegmentMidPoint() { QFETCH( double, pt1x ); QFETCH( double, pt1y ); QFETCH( double, pt2x ); QFETCH( double, pt2y ); QFETCH( double, radius ); QFETCH( bool, left ); QFETCH( double, expectedX ); QFETCH( double, expectedY ); QgsPointV2 midPoint; bool ok = QgsGeometryUtils::segmentMidPoint( QgsPointV2( pt1x, pt1y ), QgsPointV2( pt2x, pt2y ), midPoint, radius, left ); QVERIFY( ok ); QVERIFY( qgsDoubleNear( midPoint.x(), expectedX ) ); QVERIFY( qgsDoubleNear( midPoint.y(), expectedY ) ); }
double QgsGeometryUtils::circleTangentDirection( const QgsPointV2& tangentPoint, const QgsPointV2& cp1, const QgsPointV2& cp2, const QgsPointV2& cp3 ) { //calculate circle midpoint double mX, mY, radius; circleCenterRadius( cp1, cp2, cp3, radius, mX, mY ); double p1Angle = QgsGeometryUtils::ccwAngle( cp1.y() - mY, cp1.x() - mX ); double p2Angle = QgsGeometryUtils::ccwAngle( cp2.y() - mY, cp2.x() - mX ); double p3Angle = QgsGeometryUtils::ccwAngle( cp3.y() - mY, cp3.x() - mX ); if ( circleClockwise( p1Angle, p2Angle, p3Angle ) ) { return lineAngle( tangentPoint.x(), tangentPoint.y(), mX, mY ); } else { return lineAngle( mX, mY, tangentPoint.x(), tangentPoint.y() ); } }
double QgsLineString::closestSegment( const QgsPointV2& pt, QgsPointV2& segmentPt, QgsVertexId& vertexAfter, bool* leftOf, double epsilon ) const { double sqrDist = std::numeric_limits<double>::max(); double testDist = 0; double segmentPtX, segmentPtY; int size = mX.size(); if ( size == 0 || size == 1 ) { vertexAfter = QgsVertexId( 0, 0, 0 ); return -1; } for ( int i = 1; i < size; ++i ) { double prevX = mX.at( i - 1 ); double prevY = mY.at( i - 1 ); double currentX = mX.at( i ); double currentY = mY.at( i ); testDist = QgsGeometryUtils::sqrDistToLine( pt.x(), pt.y(), prevX, prevY, currentX, currentY, segmentPtX, segmentPtY, epsilon ); if ( testDist < sqrDist ) { sqrDist = testDist; segmentPt.setX( segmentPtX ); segmentPt.setY( segmentPtY ); if ( leftOf ) { *leftOf = ( QgsGeometryUtils::leftOfLine( pt.x(), pt.y(), prevX, prevY, currentX, currentY ) < 0 ); } vertexAfter.part = 0; vertexAfter.ring = 0; vertexAfter.vertex = i; } } return sqrDist; }
/** * Calculate the area of a triangle in 3d space */ static double triarea3d( const QgsPointV2 &P1, const QgsPointV2 &P2, const QgsPointV2 &P3 ) { //LWDEBUG( 2, "Entered triarea3d" ); double ax, bx, ay, by, az, bz, cx, cy, cz, area; ax = P1.x() - P2.x(); bx = P3.x() - P2.x(); ay = P1.y() - P2.y(); by = P3.y() - P2.y(); az = P1.z() - P2.z(); bz = P3.z() - P2.z(); cx = ay * bz - az * by; cy = az * bx - ax * bz; cz = ax * by - ay * bx; area = qAbs( 0.5 * ( sqrt( cx * cx + cy * cy + cz * cz ) ) ); return area; }
void QgsGeometrySegmentLengthCheck::collectErrors( QList<QgsGeometryCheckError*>& errors, QStringList &/*messages*/, QAtomicInt* progressCounter , const QgsFeatureIds &ids ) const { const QgsFeatureIds& featureIds = ids.isEmpty() ? mFeaturePool->getFeatureIds() : ids; Q_FOREACH ( QgsFeatureId featureid, featureIds ) { if ( progressCounter ) progressCounter->fetchAndAddRelaxed( 1 ); QgsFeature feature; if ( !mFeaturePool->get( featureid, feature ) ) { continue; } QgsGeometry featureGeom = feature.geometry(); QgsAbstractGeometry* geom = featureGeom.geometry(); for ( int iPart = 0, nParts = geom->partCount(); iPart < nParts; ++iPart ) { for ( int iRing = 0, nRings = geom->ringCount( iPart ); iRing < nRings; ++iRing ) { int nVerts = QgsGeometryCheckerUtils::polyLineSize( geom, iPart, iRing ); if ( nVerts < 2 ) { continue; } for ( int iVert = 0, jVert = nVerts - 1; iVert < nVerts; jVert = iVert++ ) { QgsPointV2 pi = geom->vertexAt( QgsVertexId( iPart, iRing, iVert ) ); QgsPointV2 pj = geom->vertexAt( QgsVertexId( iPart, iRing, jVert ) ); double dist = qSqrt( QgsGeometryUtils::sqrDistance2D( pi, pj ) ); if ( dist < mMinLength ) { errors.append( new QgsGeometryCheckError( this, featureid, QgsPointV2( 0.5 * ( pi.x() + pj.x() ), 0.5 * ( pi.y() + pj.y() ) ), QgsVertexId( iPart, iRing, iVert ), dist, QgsGeometryCheckError::ValueLength ) ); } } } } } }
void QgsGeometryRubberBand::paint( QPainter* painter ) { if ( !mGeometry || !painter ) { return; } painter->save(); painter->translate( -pos() ); if ( mGeometryType == QGis::Polygon ) { painter->setBrush( mBrush ); } else { painter->setBrush( Qt::NoBrush ); } painter->setPen( mPen ); QgsAbstractGeometryV2* paintGeom = mGeometry->clone(); paintGeom->transform( mMapCanvas->getCoordinateTransform()->transform() ); paintGeom->draw( *painter ); //draw vertices QgsVertexId vertexId; QgsPointV2 vertex; while ( paintGeom->nextVertex( vertexId, vertex ) ) { drawVertex( painter, vertex.x(), vertex.y() ); } delete paintGeom; painter->restore(); }
void QgsMapToolIdentify::closestVertexAttributes( const QgsAbstractGeometryV2& geometry, QgsVertexId vId, QgsMapLayer *layer, QMap< QString, QString >& derivedAttributes ) { QString str = QLocale::system().toString( vId.vertex + 1 ); derivedAttributes.insert( tr( "Closest vertex number" ), str ); QgsPointV2 closestPoint = geometry.vertexAt( vId ); QgsPoint closestPointMapCoords = mCanvas->mapSettings().layerToMapCoordinates( layer, QgsPoint( closestPoint.x(), closestPoint.y() ) ); str = QLocale::system().toString( closestPointMapCoords.x(), 'g', 10 ); derivedAttributes.insert( "Closest vertex X", str ); str = QLocale::system().toString( closestPointMapCoords.y(), 'g', 10 ); derivedAttributes.insert( "Closest vertex Y", str ); if ( closestPoint.is3D() ) { str = QLocale::system().toString( closestPoint.z(), 'g', 10 ); derivedAttributes.insert( "Closest vertex Z", str ); } if ( closestPoint.isMeasure() ) { str = QLocale::system().toString( closestPoint.m(), 'g', 10 ); derivedAttributes.insert( "Closest vertex M", str ); } }
QgsPointV2 QgsGeometryUtils::pointOnLineWithDistance( const QgsPointV2& startPoint, const QgsPointV2& directionPoint, double distance ) { double dx = directionPoint.x() - startPoint.x(); double dy = directionPoint.y() - startPoint.y(); double length = sqrt( dx * dx + dy * dy ); if ( qgsDoubleNear( length, 0.0 ) ) { return startPoint; } double scaleFactor = distance / length; return QgsPointV2( startPoint.x() + dx * scaleFactor, startPoint.y() + dy * scaleFactor ); }
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(); }
bool QgsGeometryUtils::lineIntersection( const QgsPointV2& p1, const QgsVector& v, const QgsPointV2& q1, const QgsVector& w, QgsPointV2& inter ) { double d = v.y() * w.x() - v.x() * w.y(); if ( d == 0 ) return false; double dx = q1.x() - p1.x(); double dy = q1.y() - p1.y(); double k = ( dy * w.x() - dx * w.y() ) / d; inter = QgsPointV2( p1.x() + v.x() * k, p1.y() + v.y() * k ); return true; }
double QgsCircularString::closestPointOnArc( double x1, double y1, double x2, double y2, double x3, double y3, const QgsPointV2 &pt, QgsPointV2 &segmentPt, QgsVertexId &vertexAfter, bool *leftOf, double epsilon ) { double radius, centerX, centerY; QgsPointV2 pt1( x1, y1 ); QgsPointV2 pt2( x2, y2 ); QgsPointV2 pt3( x3, y3 ); QgsGeometryUtils::circleCenterRadius( pt1, pt2, pt3, radius, centerX, centerY ); double angle = QgsGeometryUtils::ccwAngle( pt.y() - centerY, pt.x() - centerX ); double angle1 = QgsGeometryUtils::ccwAngle( pt1.y() - centerY, pt1.x() - centerX ); double angle2 = QgsGeometryUtils::ccwAngle( pt2.y() - centerY, pt2.x() - centerX ); double angle3 = QgsGeometryUtils::ccwAngle( pt3.y() - centerY, pt3.x() - centerX ); bool clockwise = QgsGeometryUtils::circleClockwise( angle1, angle2, angle3 ); if ( QgsGeometryUtils::angleOnCircle( angle, angle1, angle2, angle3 ) ) { //get point on line center -> pt with distance radius segmentPt = QgsGeometryUtils::pointOnLineWithDistance( QgsPointV2( centerX, centerY ), pt, radius ); //vertexAfter vertexAfter.vertex = QgsGeometryUtils::circleAngleBetween( angle, angle1, angle2, clockwise ) ? 1 : 2; } else { double distPtPt1 = QgsGeometryUtils::sqrDistance2D( pt, pt1 ); double distPtPt3 = QgsGeometryUtils::sqrDistance2D( pt, pt3 ); segmentPt = ( distPtPt1 <= distPtPt3 ) ? pt1 : pt3; vertexAfter.vertex = ( distPtPt1 <= distPtPt3 ) ? 1 : 2; } double sqrDistance = QgsGeometryUtils::sqrDistance2D( segmentPt, pt ); //prevent rounding errors if the point is directly on the segment if ( qgsDoubleNear( sqrDistance, 0.0, epsilon ) ) { segmentPt.setX( pt.x() ); segmentPt.setY( pt.y() ); sqrDistance = 0.0; } if ( leftOf ) { *leftOf = clockwise ? sqrDistance > radius : sqrDistance < radius; } return sqrDistance; }
QgsTriangle::QgsTriangle( const QgsPointV2 &p1, const QgsPointV2 &p2, const QgsPointV2 &p3 ) { mWkbType = QgsWkbTypes::Triangle; if ( !validateGeom( p1, p2, p3 ) ) { return; } QVector< double > x; x << p1.x() << p2.x() << p3.x(); QVector< double > y; y << p1.y() << p2.y() << p3.y(); QgsLineString *ext = new QgsLineString( x, y ); setExteriorRing( ext ); }