Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_temporary_paint_constraint.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2026 Ayanami Kaine <personal@ayanamikaine.com>
3 * SPDX-License-Identifier: GPL-2.0-or-later
4 */
5
7
8#include <cmath>
9
10#include <QtGlobal>
11
12#include <kis_algebra_2d.h>
13
14namespace {
15constexpr qreal minLineLengthSquared = 1e-6;
16constexpr qreal snapAngleStepRadians = 3.14159265358979323846 / 12.0;
17
18QPointF snappedEndpoint(const QPointF &anchor, const QPointF &point)
19{
20 const QPointF delta = point - anchor;
21 const qreal length = KisAlgebra2D::norm(delta);
22 if (qFuzzyIsNull(length)) {
23 return point;
24 }
25
26 const qreal angle = std::atan2(delta.y(), delta.x());
27 const qreal snappedAngle = std::round(angle / snapAngleStepRadians) * snapAngleStepRadians;
28 return anchor + QPointF(length * std::cos(snappedAngle), length * std::sin(snappedAngle));
29}
30}
31
36
41
42void KisTemporaryPaintConstraint::beginLine(const QPointF &anchor)
43{
44 m_anchor = anchor;
45 m_secondPoint = anchor;
46 m_hasLine = true;
47 m_locked = false;
48 m_angleSnapped = false;
49}
50
51void KisTemporaryPaintConstraint::updateLine(const QPointF &secondPoint, bool snapToAngle)
52{
53 if (m_locked) {
54 return;
55 }
56
57 if (!m_hasLine) {
58 beginLine(secondPoint);
59 return;
60 }
61
62 if (snapToAngle) {
63 m_secondPoint = snappedEndpoint(m_anchor, secondPoint);
64 m_angleSnapped = true;
65 } else if (!m_angleSnapped) {
66 m_secondPoint = secondPoint;
67 }
68}
69
71{
72 return m_hasLine;
73}
74
76{
77 m_locked = locked && hasValidLine();
78}
79
81{
82 return m_locked;
83}
84
86{
87 return m_hasLine && KisAlgebra2D::normSquared(m_secondPoint - m_anchor) > minLineLengthSquared;
88}
89
91{
92 return m_anchor;
93}
94
99
101 const QPointF &strokeBegin,
102 bool checkForInitialMovement,
103 qreal moveThresholdPt) const
104{
105 if (!m_locked || !hasValidLine()) {
106 return point;
107 }
108
109 if (checkForInitialMovement && KisAlgebra2D::norm(point - strokeBegin) < moveThresholdPt) {
110 return strokeBegin;
111 }
112
113 const QPointF delta = m_secondPoint - m_anchor;
114 const qreal squareLength = KisAlgebra2D::normSquared(delta);
115 if (qFuzzyIsNull(squareLength)) {
116 return point;
117 }
118
119 const qreal t = KisAlgebra2D::dotProduct(point - m_anchor, delta) / squareLength;
120 return m_anchor + delta * t;
121}
qreal length(const QPointF &vec)
Definition Ellipse.cc:82
void updateLine(const QPointF &secondPoint, bool snapToAngle=false)
QPointF adjustPosition(const QPointF &point, const QPointF &strokeBegin, bool checkForInitialMovement, qreal moveThresholdPt) const
void setInteractionMode(InteractionMode mode)
static bool qFuzzyIsNull(half h)
qreal normSquared(const T &a)
qreal norm(const T &a)
PointTypeTraits< T >::value_type dotProduct(const T &a, const T &b)