27static const double SOFT_CONSTRAINT_TOLERANCE_PIXEL = 15;
 
   28static const double SOFT_CONSTRAINT_TOLERANCE_DEGREES = 10;
 
   46  res.
softLockX = std::numeric_limits<double>::quiet_NaN();
 
   47  res.
softLockY = std::numeric_limits<double>::quiet_NaN();
 
   65  int numberOfHardLock = 0;
 
   92      const double dx = edgePt1.
x() - edgePt0.
x();
 
   95        point.
setY( edgePt0.
y() );
 
   99        const double dy = edgePt1.
y() - edgePt0.
y();
 
  100        point.
setY( edgePt0.
y() + ( dy * ( point.
x() - edgePt0.
x() ) ) / dx );
 
  112      if ( std::abs( point.
x() - vertex.
x() ) / ctx.
mapUnitsPerPixel < SOFT_CONSTRAINT_TOLERANCE_PIXEL )
 
  114        point.
setX( vertex.
x() );
 
  135      const double dy = edgePt1.
y() - edgePt0.
y();
 
  138        point.
setX( edgePt0.
x() );
 
  142        const double dx = edgePt1.
x() - edgePt0.
x();
 
  143        point.
setX( edgePt0.
x() + ( dx * ( point.
y() - edgePt0.
y() ) ) / dy );
 
  155      if ( std::abs( point.
y() - vertex.
y() ) / ctx.
mapUnitsPerPixel < SOFT_CONSTRAINT_TOLERANCE_PIXEL )
 
  157        point.
setY( vertex.
y() );
 
  170    double softAngle = std::atan2( point.
y() - previousPt.
y(),
 
  171                                   point.
x() - previousPt.
x() );
 
  172    double deltaAngle = 0;
 
  176      deltaAngle = std::atan2( previousPt.
y() - penultimatePt.
y(),
 
  177                               previousPt.
x() - penultimatePt.
x() );
 
  178      softAngle -= deltaAngle;
 
  180    const int quo = std::round( softAngle / commonAngle );
 
  181    if ( std::fabs( softAngle - quo * commonAngle ) * 180.0 * M_1_PI <= SOFT_CONSTRAINT_TOLERANCE_DEGREES )
 
  184      softAngle = quo * commonAngle;
 
  187      const double dist = std::fabs( std::cos( softAngle + deltaAngle ) * ( previousPt.
y() - point.
y() )
 
  188                                     - std::sin( softAngle + deltaAngle ) * ( previousPt.
x() - point.
x() ) );
 
  199  bool angleLocked = 
false, angleRelative = 
false;
 
  200  double angleValueDeg = 0;
 
  219    double angleValue = angleValueDeg * M_PI / 180;
 
  220    if ( angleRelative && ctx.
cadPoints().count() >= 3 )
 
  223      angleValue += std::atan2( previousPt.
y() - penultimatePt.
y(),
 
  224                                previousPt.
x() - penultimatePt.
x() );
 
  227    const double cosa = std::cos( angleValue );
 
  228    const double sina = std::sin( angleValue );
 
  229    const double v = ( point.
x() - previousPt.
x() ) * cosa + ( point.
y() - previousPt.
y() ) * sina;
 
  247        point.
setY( previousPt.
y() + x * sina / cosa );
 
  263        point.
setX( previousPt.
x() + y * cosa / sina );
 
  268      point.
setX( previousPt.
x() + cosa * v );
 
  269      point.
setY( previousPt.
y() + sina * v );
 
  277      const double x1 = previousPt.
x();
 
  278      const double y1 = previousPt.
y();
 
  279      const double x2 = previousPt.
x() + cosa;
 
  280      const double y2 = previousPt.
y() + sina;
 
  282      const double x3 = edgePt0.
x();
 
  283      const double y3 = edgePt0.
y();
 
  284      const double x4 = edgePt1.
x();
 
  285      const double y4 = edgePt1.
y();
 
  287      const double d = ( x1 - x2 ) * ( y3 - y4 ) - ( y1 - y2 ) * ( x3 - x4 );
 
  291      if ( std::fabs( d ) > 0.01 )
 
  293        point.
setX( ( ( x3 - x4 ) * ( x1 * y2 - y1 * x2 ) - ( x1 - x2 ) * ( x3 * y4 - y3 * x4 ) ) / d );
 
  294        point.
setY( ( ( y3 - y4 ) * ( x1 * y2 - y1 * x2 ) - ( y1 - y2 ) * ( x3 * y4 - y3 * x4 ) ) / d );
 
  309      auto checkLineExtension = [&]( 
QgsPoint vertex )
 
  311        if ( vertex.isEmpty() )
 
  347          else if ( angleLocked )
 
  349            const double angleValue = angleValueDeg * M_PI / 180;
 
  350            const double cosa = std::cos( angleValue );
 
  351            const double sina = std::sin( angleValue );
 
  363            double angleValue = std::atan2( extensionPoint.
y() - vertex.y(),
 
  364                                            extensionPoint.
x() - vertex.x() );
 
  366            const double cosa = std::cos( angleValue );
 
  367            const double sina = std::sin( angleValue );
 
  368            const double v = ( point.
x() - extensionPoint.
x() ) * cosa + ( point.
y() - extensionPoint.
y() ) * sina;
 
  370            point.
setX( extensionPoint.
x() + cosa * v );
 
  371            point.
setY( extensionPoint.
y() + sina * v );
 
  407        const QgsPointXY verticalPt1( point.
x(), point.
y() + 1 );
 
  412          res.
valid &= intersect;
 
  414        else if ( !intersect )
 
  416          res.
softLockX = std::numeric_limits<double>::quiet_NaN();
 
  417          res.
softLockY = std::numeric_limits<double>::quiet_NaN(); 
 
  424        const QgsPointXY horizontalPt1( point.
x() + 1, point.
y() );
 
  429          res.
valid &= intersect;
 
  431        else if ( !intersect )
 
  433          res.
softLockY = std::numeric_limits<double>::quiet_NaN();
 
  466      const double dist = std::sqrt( point.
sqrDist( previousPt ) );
 
  476        point.
set( previousPt.
x() + ( point.
x() - previousPt.
x() ) * vP,
 
  477                   previousPt.
y() + ( point.
y() - previousPt.
y() ) * vP );
 
  490  QgsDebugMsgLevel( QStringLiteral( 
"point:             %1 %2" ).arg( point.
x() ).arg( point.
y() ), 4 );
 
  491  QgsDebugMsgLevel( QStringLiteral( 
"previous point:    %1 %2" ).arg( previousPt.
x() ).arg( previousPt.
y() ), 4 );
 
  492  QgsDebugMsgLevel( QStringLiteral( 
"penultimate point: %1 %2" ).arg( penultimatePt.
x() ).arg( penultimatePt.
y() ), 4 );
 
  503  QgsDebugMsg( QStringLiteral( 
"Constraints (locked / relative / value" ) );
 
@ AfterVertex
Lock to next vertex.
 
@ NoVertex
Don't lock to vertex.
 
@ BeforeVertex
Lock to previous vertex.
 
bool locked
Whether the constraint is active, i.e. should be considered.
 
double value
Numeric value of the constraint (coordinate/distance in map units or angle in degrees)
 
bool relative
Whether the value is relative to previous value.
 
Defines constraints for the QgsCadUtils::alignMapPoint() method.
 
QgsCadUtils::AlignMapPointConstraint xyVertexConstraint
 
QgsCadUtils::AlignMapPointConstraint yConstraint
Constraint for Y coordinate.
 
QgsCadUtils::AlignMapPointConstraint xConstraint
Constraint for X coordinate.
 
double mapUnitsPerPixel
Map units/pixel ratio from map canvas.
 
QgsPoint cadPoint(int index) const
Returns the recent CAD point at the specified index (in map coordinates).
 
QgsCadUtils::AlignMapPointConstraint distanceConstraint
Constraint for distance.
 
QgsSnappingUtils * snappingUtils
Snapping utils that will be used to snap point to map. Must not be nullptr.
 
QgsCadUtils::AlignMapPointConstraint commonAngleConstraint
Constraint for soft lock to a common angle.
 
QQueue< QgsPointLocator::Match > lockedSnapVertices() const
Returns the queue of point locator matches that contain the locked vertices.
 
QgsCadUtils::AlignMapPointConstraint lineExtensionConstraint
 
QList< QgsPoint > cadPoints() const
Returns the list of recent CAD points in map coordinates.
 
void dump() const
Dumps the context's properties, for debugging.
 
QgsCadUtils::AlignMapPointConstraint angleConstraint
Constraint for angle.
 
Structure returned from alignMapPoint() method.
 
Qgis::LineExtensionSide softLockLineExtension
 
QgsPointXY finalMapPoint
map point aligned according to the constraints
 
bool valid
Whether the combination of constraints is actually valid.
 
QgsPointLocator::Match snapMatch
Snapped point - only valid if actually used for something.
 
QgsPointLocator::Match edgeMatch
Snapped segment - only valid if actually used for something.
 
double softLockCommonAngle
Angle (in degrees) to which we have soft-locked ourselves (if not set it is -1)
 
static QgsCadUtils::AlignMapPointOutput alignMapPoint(const QgsPointXY &originalMapPoint, const QgsCadUtils::AlignMapPointContext &ctx)
Applies X/Y/angle/distance constraints from the given context to a map point.
 
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
 
static bool lineIntersection(const QgsPoint &p1, QgsVector v1, const QgsPoint &p2, QgsVector v2, QgsPoint &intersection) SIP_HOLDGIL
Computes the intersection between two lines.
 
static bool lineCircleIntersection(const QgsPointXY ¢er, double radius, const QgsPointXY &linePoint1, const QgsPointXY &linePoint2, QgsPointXY &intersection) SIP_HOLDGIL
Compute the intersection of a line and a circle.
 
static double distToInfiniteLine(const QgsPoint &point, const QgsPoint &linePoint1, const QgsPoint &linePoint2, double epsilon=1e-7)
Returns the distance between a point and an infinite line.
 
A geometry is the spatial representation of a feature.
 
QgsPoint vertexAt(int atVertex) const
Returns coordinates of a vertex.
 
A class to represent a 2D point.
 
bool isEmpty() const SIP_HOLDGIL
Returns true if the geometry is empty.
 
void set(double x, double y) SIP_HOLDGIL
Sets the x and y value of the point.
 
double sqrDist(double x, double y) const SIP_HOLDGIL
Returns the squared distance between this point a specified x, y coordinate.
 
void setX(double x) SIP_HOLDGIL
Sets the x value of the point.
 
void setY(double y) SIP_HOLDGIL
Sets the y value of the point.
 
Point geometry type, with support for z-dimension and m-values.
 
QgsPointLocator::Match snapToMap(QPoint point, QgsPointLocator::MatchFilter *filter=nullptr, bool relaxed=false)
Snap to map according to the current configuration.
 
QgsFeature getFeature(QgsFeatureId fid) const
Queries the layer for the feature with the given id.
 
A class to represent a vector.
 
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
 
#define QgsDebugMsgLevel(str, level)
 
Interface that allows rejection of some matches in intersection queries (e.g.
 
virtual bool acceptMatch(const QgsPointLocator::Match &match)=0
 
QgsFeatureId featureId() const
The id of the feature to which the snapped geometry belongs.
 
QgsVectorLayer * layer() const
The vector layer where the snap occurred.
 
QgsPointXY point() const
for vertex / edge match coords depending on what class returns it (geom.cache: layer coords,...
 
bool hasEdge() const
Returns true if the Match is an edge.
 
void edgePoints(QgsPointXY &pt1, QgsPointXY &pt2) const
Only for a valid edge match - obtain endpoints of the edge.
 
int vertexIndex() const
for vertex / edge match (first vertex of the edge)