"Irinuki" Pen pressure detection on vector layer

I want Krita to implement pen pressure detection in vector layers.

I want to use pen pressure detection in Krita’s vector layer to create “Irinuki”(“入り抜き”).

The main purpose of this feature request is to draw line art for comic(MANGA漫画).
By drawing line art with pressure sensitivity in a vector layer instead of a paint layer, you can move the line nodes and later correct the line art drawn with pen pressure sensitivity in a vector layer.Post-correction of line art drawn with pressure sensitivity is not possible in pixel layer.

However, the current vector layer standard used by Krita is SVG-standard, which is a SVG-standard that does not have information about the line-width, thickness or strength per node for lines, etc.
Therefore, in order to realize this feature request, it is necessary to develop a vector layer in Krita that is not SVG-standard-compliant but is unique to Krita.

examples about this feature request
similar features in other software

CLIP STUDIO PAINT EX

2 Likes

Hi. I agree this would be very useful, perhaps doubly so for animation. However, this is a massive task. I looked at CSP and its vector features are very advanced, it can produce a lot of brush effects in vector, which goes well beyond just supporting pen pressure.

Perhaps just getting basic lines with pressure-sensitive size or opacity would be a good starting point, but there will be undoubtedly many additional feature requests from users on top of that. Also, I believe this topic has been brought up before, although I don’t have any links at hand.

If you want to work on this difficult task on your own, then I don’t think you should open a feature request. Just open a regular development topic and share your updates there.

1 Like

@YRH
I appreciate you.
It would be difficult for only me to develop this feature request by only myself, but I have researched technologies that seem to be related. This research may be wrong, but I am posting it in the hope that it will contribute to Krita even a little.

Google Gemini

Okay, here’s the English translation of the previous explanation of Centripetal Catmull-Rom splines in C++:
Centripetal Catmull-Rom Spline in C++

The Centripetal Catmull-Rom spline, unlike standard or tensioned Catmull-Rom splines, adjusts the progression of the parameter t based on the distances between control points. This helps prevent self-intersections and loops in areas where control points turn sharply, resulting in more natural and smoother curves.

Concept of Centripetal Catmull-Rom Splines

In standard Catmull-Rom splines, the parameter t increases linearly between control points. However, if the distances between control points vary significantly, this can lead to unnatural curve shapes.

In Centripetal Catmull-Rom splines, the parameter interval αi​ between each control point is calculated proportionally to the ω-th power of the Euclidean distance between the control points. A common value for ω is 0.5 (square root).

αi​=∥Pi+1​−Pi​∥ω

Then, the parameter value ti​ corresponding to each control point Pi​ is calculated cumulatively:

t0​=0
ti​=ti−1​+αi−1​ (for i=1,…,n−1)

Finally, the parameter t is normalized to the range [0,1]:

t^i​=tn−1​ti​​

When calculating a point C(u) on the curve (0≤u≤1), we first identify the parameter interval [t^i​,t^i+1​] to which the given u belongs. Then, we calculate a local parameter t′ (0≤t′≤1) within that interval:

t′=t^i+1​−t^i​u−t^i​​

This t′ is then used in a similar interpolation formula as the standard Catmull-Rom spline. However, the interpolation weights are adjusted based on the parameter intervals.

Formula for Centripetal Catmull-Rom Splines

The point C(u) on the curve within the interval [Pi​,Pi+1​] is calculated using the parameters t^i​ and t^i+1​.

First, the tangent vector di​ at each control point is calculated. In Centripetal Catmull-Rom splines, the tangent vector is computed considering the parameter intervals:

di​=2t^i+1​−t^i−1​​(Pi+1​−Pi−1​)

Special handling is needed for the first and last points. For example, the tangent at the first point can be proportional to P1​−P0​, and the tangent at the last point proportional to Pn−1​−Pn−2​.

Then, using the local parameter t′ within the interval [t^i​,t^i+1​], Hermite interpolation is performed:

C(t′)=(2t′3−3t′2+1)Pi​+(−2t′3+3t′2)Pi+1​+(t′3−2t′2+t′)di​(t^i+1​−t^i​)+(t′3−t′2)di+1​(t^i+1​−t^i​)

Where di​ and di+1​ are the tangent vectors at Pi​ and Pi+1​, respectively.

C++ Code Example (for ω=0.5)
C++

#include
#include
#include
#include // std::numeric_limits

struct Point {
double x;
double y;
};

// Function to calculate the distance between two points
double distance(const Point& p1, const Point& p2) {
return std::sqrt(std::pow(p1.x - p2.x, 2) + std::pow(p1.y - p2.y, 2));
}

// Function to calculate a point on the Centripetal Catmull-Rom spline
Point calculateCentripetalCatmullRomPoint(double u, const std::vector& p, const std::vector& t) {
int n = p.size();
if (n < 4) {
std::cerr << “Error: At least 4 control points are required for Centripetal Catmull-Rom spline.” << std::endl;
return {std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN()};
}

// Determine which segment u belongs to
int segment = -1;
for (int i = 0; i < n - 1; ++i) {
    if (u >= t[i] && u <= t[i + 1]) {
        segment = i;
        break;
    }
}
if (segment == -1) {
    return p[n - 1]; // Return the last point if u is 1, etc.
}

double localT = (u - t[segment]) / (t[segment + 1] - t[segment]);

// Select the four control points for interpolation
int i = segment + 1;
Point p0 = (i > 1) ? p[i - 2] : p[0];
Point p1 = p[i - 1];
Point p2 = p[i];
Point p3 = (i < n - 1) ? p[i + 1] : p[n - 1];

double t2 = localT * localT;
double t3 = localT * t2;

Point result;
result.x = 0.5 * (
    (2 * p1.x) +
    (-p0.x + p2.x) * localT +
    (2 * p0.x - 5 * p1.x + 4 * p2.x - p3.x) * t2 +
    (-p0.x + 3 * p1.x - 3 * p2.x + p3.x) * t3
);
result.y = 0.5 * (
    (2 * p1.y) +
    (-p0.y + p2.y) * localT +
    (2 * p0.y - 5 * p1.y + 4 * p2.y - p3.y) * t2 +
    (-p0.y + 3 * p1.y - 3 * p2.y + p3.y) * t3
);

return result;

}

int main() {
// Coordinates of the control points (at least 4 are required)
std::vector controlPoints = {
{100, 100},
{200, 300},
{300, 150},
{400, 250},
{500, 100}
};
int n = controlPoints.size();

// Calculate the parameter t
std::vector<double> t(n);
t[0] = 0.0;
for (int i = 0; i < n - 1; ++i) {
    t[i + 1] = t[i] + std::pow(distance(controlPoints[i], controlPoints[i + 1]), 0.5);
}
// Normalize the parameter t to the range [0, 1]
for (int i = 0; i < n; ++i) {
    t[i] /= t[n - 1];
}

// Number of points to generate on the curve
int numPoints = 100;
std::vector<Point> centripetalCatmullRomPoints;

// Calculate points on the curve by varying the parameter u from 0 to 1
for (int i = 0; i <= numPoints; ++i) {
    double u = static_cast<double>(i) / numPoints;
    Point point = calculateCentripetalCatmullRomPoint(u, controlPoints, t);
    centripetalCatmullRomPoints.push_back(point);
}

// Display the calculated points of the Centripetal Catmull-Rom spline
std::cout << "Centripetal Catmull-Rom spline points:" << std::endl;
for (const auto& point : centripetalCatmullRomPoints) {
    std::cout << "(" << point.x << ", " << point.y << ")" << std::endl;
}

return 0;

}

Explanation of the Code

distance Function: Calculates the Euclidean distance between two points.

calculateCentripetalCatmullRomPoint Function:
    u: The parameter ranging from 0 to 1.
    p: The vector of control points.
    t: The vector of normalized parameter values corresponding to each control point.
    Handles the error case where fewer than 4 control points are provided.
    Determines the parameter interval [ti​,ti+1​] that the given u falls into.
    Calculates the local parameter localT within that interval.
    Selects the four control points Pi−1​,Pi​,Pi+1​,Pi+2​ needed for the interpolation (using repetition for endpoints).
    Calculates the point on the curve using the standard Catmull-Rom spline formula, but with the parameterization adjusted for the distances between control points.

main Function:
    Control Point Definition: Sets the coordinates of the control points in the controlPoints vector.
    Parameter t Calculation:
        Sets the first parameter t[0] to 0.
        Calculates the parameter values for each control point by accumulating the square roots of the distances between consecutive control points.
        Normalizes these parameter values to the range [0,1] by dividing by the last parameter value.
    Number of Points (numPoints): Specifies how many points to generate on the curve for a smooth appearance.
    Loop: Iterates through values of the parameter u from 0 to 1, calling calculateCentripetalCatmullRomPoint to get the corresponding point on the spline, and stores these points in the centripetalCatmullRomPoints vector.
    Result Display: Prints the calculated coordinates of the Centripetal Catmull-Rom spline points.

Key Points

Parameter Calculation: The core of the Centripetal Catmull-Rom spline is the calculation of the parameter t based on the distances between control points.
Endpoint Handling: The calculateCentripetalCatmullRomPoint function handles the endpoints by repeating the first and last control points when selecting the four points for interpolation.
Value of ω: This example uses ω=0.5. Other values (like 0.0 for uniform or 1.0 for chordal) can be used, but 0.5 often yields good results.

Centripetal Catmull-Rom splines are useful for generating smooth and natural curves, especially when dealing with control points that have sharp turns. They are effective in preventing self-intersections that can occur with standard Catmull-Rom splines in such cases. Feel free to experiment with different control point configurations and observe the resulting curves.

1 Like

I’ve already added my vote, its looks promising this feature request. Btw i saw you are searching info if people added related to this feature request. I saw a blog entry from Wolthera talking about this if i am wrong, its related to vector layers.

I remember that someone posted a similar feature request related to add Vector layers or editable strokes in vector bitmap for Krita, similar behavior just like they do for Clip studio Paint or the new one in Ibispaint (Which i am gonna add and research more later for this thread)

I put this info just in case you need.

2 Likes

@THE_CULT_OF_BERSERK
I appreciate your advice.

@halla
To summarize the contents of this feature request

Vector G-pen
Vector mapping pen
Vector school pen
Vector kabura pen (Vector turnip pen)

About vector strokes
Per node line-width
Per node outline-width
Per node outline-of-outline-width
Per node transparency
Per node line-color
Per node outline-color
Per node outline-of-outline-color
Vector strokes join

Centripetal Catmull-Rom splines

Vector 3-point perspective assistant tool
Vector 2-point perspective assistant tool

Is there anything else I have overlooked?

Who will develop this feature request?

Can I contact the Krita core development team, such as Halla Rempt?

Can I contact them on Krita Artists?

Do I need an IRC?

Either way, you’ll probably need some advice from the Krita core development team.

CLIP STUDIO PAINT EX(CSP)
Vector G-pen
Vector strokes join

Krita
Raster(not Vector) 2-point perspective assistant tool