Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
lpe-spiro.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
2#define INKSCAPE_LPE_SPIRO_C
3
4/*
5 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
6 */
7
8#include "lpe-spiro.h"
9
11#include "helper/geom-curves.h"
12#include "live_effects/spiro.h"
13
14namespace Inkscape {
15namespace LivePathEffect {
16
18 Effect(lpeobject)
19{
20}
21
22LPESpiro::~LPESpiro() = default;
23
28
30{
31 using Geom::X;
32 using Geom::Y;
33
34 // Make copy of old path as it is changed during processing
35 Geom::PathVector const original_pathv = curve;
36 guint len = curve.curveCount() + 2;
37
38 curve.clear();
39 Spiro::spiro_cp *path = g_new (Spiro::spiro_cp, len);
40 int ip = 0;
41
42 for(const auto & path_it : original_pathv) {
43 if (path_it.empty())
44 continue;
45
46 // start of path
47 {
48 Geom::Point p = path_it.initialPoint();
49 path[ip].x = p[X];
50 path[ip].y = p[Y];
51 path[ip].ty = '{' ; // for closed paths, this is overwritten
52 ip++;
53 }
54
55 // midpoints
56 Geom::Path::const_iterator curve_it1 = path_it.begin(); // incoming curve
57 Geom::Path::const_iterator curve_it2 = ++(path_it.begin()); // outgoing curve
58 Geom::Path::const_iterator curve_endit = path_it.end_default(); // this determines when the loop has to stop
59
60 while ( curve_it2 != curve_endit )
61 {
62 /* This deals with the node between curve_it1 and curve_it2.
63 * Loop to end_default (so without last segment), loop ends when curve_it2 hits the end
64 * and then curve_it1 points to end or closing segment */
65 Geom::Point p = curve_it1->finalPoint();
66 path[ip].x = p[X];
67 path[ip].y = p[Y];
68
69 // Determine type of spiro node this is, determined by the tangents (angles) of the curves
70 // TODO: see if this can be simplified by using /helpers/geom-nodetype.cpp:get_nodetype
71 bool this_is_line = is_straight_curve(*curve_it1);
72 bool next_is_line = is_straight_curve(*curve_it2);
73
74 Geom::NodeType nodetype = Geom::get_nodetype(*curve_it1, *curve_it2);
75
76 if ( nodetype == Geom::NODE_SMOOTH || nodetype == Geom::NODE_SYMM )
77 {
78 if (this_is_line && !next_is_line) {
79 path[ip].ty = ']';
80 } else if (next_is_line && !this_is_line) {
81 path[ip].ty = '[';
82 } else {
83 path[ip].ty = 'c';
84 }
85 } else {
86 path[ip].ty = 'v';
87 }
88
89 ++curve_it1;
90 ++curve_it2;
91 ip++;
92 }
93
94 // add last point to the spiropath
95 Geom::Point p = curve_it1->finalPoint();
96 path[ip].x = p[X];
97 path[ip].y = p[Y];
98 if (path_it.closed()) {
99 // curve_it1 points to the (visually) closing segment. determine the match between first and this last segment (the closing node)
100 Geom::NodeType nodetype = Geom::get_nodetype(*curve_it1, path_it.front());
101 switch (nodetype) {
102 case Geom::NODE_NONE: // can't happen! but if it does, it means the path isn't closed :-)
103 path[ip].ty = '}';
104 ip++;
105 break;
106 case Geom::NODE_CUSP:
107 path[0].ty = path[ip].ty = 'v';
108 break;
110 case Geom::NODE_SYMM:
111 path[0].ty = path[ip].ty = 'c';
112 break;
113 }
114 } else {
115 // set type to path closer
116 path[ip].ty = '}';
117 ip++;
118 }
119
120 // run subpath through spiro
121 int sp_len = ip;
122 curve = Spiro::spiro_run(path, sp_len);
123 ip = 0;
124 }
125
126 g_free(path);
127}
128
129} // namespace LivePathEffect
130} // namespace Inkscape
131
132/*
133 Local Variables:
134 mode:c++
135 c-file-style:"stroustrup"
136 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
137 indent-tabs-mode:nil
138 fill-column:99
139 End:
140*/
141// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
Sequence of subpaths.
Definition pathvector.h:122
Two-dimensional point that doubles as a vector.
Definition point.h:66
void doEffect(Geom::PathVector &curve) override
Definition lpe-spiro.cpp:24
LPESpiro(LivePathEffectObject *lpeobject)
Definition lpe-spiro.cpp:17
Specific curve type functions for Inkscape, not provided by lib2geom.
bool is_straight_curve(Geom::BezierCurve const &c)
Definition geom-curves.h:22
Specific nodetype geometry functions for Inkscape, not provided my lib2geom.
@ Y
Definition coord.h:48
@ X
Definition coord.h:48
NodeType
What kind of node is this? This is the value for the node->type field.
@ NODE_NONE
Discontinuous node, usually either start or endpoint of a path.
@ NODE_CUSP
This node continuously joins two segments, but the unit tangent is discontinuous.
@ NODE_SYMM
This node is symmetric.
@ NODE_SMOOTH
This node continuously joins two segments, with continuous unit tangent.
NodeType get_nodetype(Curve const &c_incoming, Curve const &c_outgoing)
void sp_spiro_do_effect(Geom::PathVector &curve)
Definition lpe-spiro.cpp:29
Helper class to stream background task notifications as a series of messages.
Geom::Path spiro_run(const spiro_cp *src, int src_len)
Definition spiro.cpp:23
auto len
Definition safe-printf.h:21
C implementation of third-order polynomial spirals.
double y
Definition spiro.h:22
double x
Definition spiro.h:21
Definition curve.h:24