Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
lpe-embrodery-stitch-ordering.h
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Sub-path Ordering functions for embroidery stitch LPE
4 *
5 * Copyright (C) 2016 Michael Soegtrop
6 *
7 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
8 */
9
10#ifndef INKSCAPE_LPE_EMBRODERY_STITCH_ORDERING_H
11#define INKSCAPE_LPE_EMBRODERY_STITCH_ORDERING_H
12
13#include "live_effects/effect.h"
14
15namespace Inkscape {
16namespace LivePathEffect {
17namespace LPEEmbroderyStitchOrdering {
18
19// Structure keeping information on the ordering and reversing of sub paths
20// Used for simple ordering functions like zig-zag
21
23 int index;
24 bool reverse;
25 bool used;
26 bool connect;
27 Geom::Point begOrig; // begin point in original orientation
28 Geom::Point endOrig; // end point in original orientation
29
31 {
32 return begOrig;
33 }
35 {
36 return endOrig;
37 }
39 {
40 return reverse ? endOrig : begOrig;
41 }
43 {
44 return reverse ? begOrig : endOrig;
45 }
46};
47
48// Structure for a path end-point in OrderingInfoEx.
49// This keeps information about the two nearest neighbor points.
50
51struct OrderingInfoEx;
52
54 OrderingPoint(const Geom::Point &pointIn, OrderingInfoEx *infoexIn, bool beginIn) :
55 point(pointIn),
56 infoex(infoexIn),
57 begin(beginIn)
58 {
59 nearest[0] = nearest[1] = nullptr;
60 }
61
62 // Check if both nearest values are valid
63 bool IsNearestValid() const
64 {
65 return nearest[0] && nearest[1];
66 }
67 // Check if at least one nearest values are valid
68 bool HasNearest() const
69 {
70 return nearest[0] || nearest[1];
71 }
72 // Find 2 nearest points to given point
73 void FindNearest2(const std::vector<OrderingInfoEx *> &infos);
74 // Check if "this" is among the nearest of its nearest
75 void EnforceMutual();
76 // Check if the subpath indices of this and other are the same, otherwise zero both nearest
77 void EnforceSymmetric(const OrderingPoint &other);
78 // Dump point information
79 void Dump();
80
83 bool begin;
85};
86
87// Structure keeping information on the ordering and reversing of sub paths
88// Used for advanced ordering functions with block creation and Traveling Salesman Problem Optimization
89// A OrderingInfoEx may contain several original sub-paths in case sub-paths are directly connected.
90// Directly connected sub-paths happen e.g. after a slice boolean operation.
91
92struct OrderingGroup;
93
95 OrderingInfoEx(const OrderingInfo &infoIn, int idxIn) :
96 beg(infoIn.begOrig, this, true),
97 end(infoIn.endOrig, this, false),
98 idx(idxIn),
99 grouped(false)
100 {
101 origIndices.push_back(infoIn.index);
102 }
103
104 // If this element can be grouped (has neighbours) but is not yet grouped, create a new group
105 void MakeGroup(std::vector<OrderingInfoEx *> &infos, std::vector<OrderingGroup *> *groups);
106 // Add this and all connected elements to the group
107 void AddToGroup(std::vector<OrderingInfoEx *> &infos, OrderingGroup *group);
108
109 int idx;
110 bool grouped; // true if this element has been grouped
111 OrderingPoint beg; // begin point in original orientation
112 OrderingPoint end; // end point in original orientation
113 std::vector<int> origIndices; // Indices of the original OrderInfos (more than 1 if directly connected
114};
115
116// Neighbor information for OrderingGroupPoint - a distance and a OrderingGroupPoint
117
118struct OrderingGroupPoint;
119
122
123 // Distance from owner of this neighbor info
125 // Neighbor point (which in turn contains a pointer to the neighbor group
127
128 // Comparison function for sorting by distance
129 static bool Compare(const OrderingGroupNeighbor &a, const OrderingGroupNeighbor &b);
130};
131
132// An end point in an OrderingGroup, with nearest neighbor information
133
135
137 OrderingGroupPoint(const Geom::Point &pointIn, OrderingGroup *groupIn, int indexIn, bool beginIn, bool frontIn) :
138 point(pointIn),
139 group(groupIn),
140 indexInGroup(indexIn),
141 connection(nullptr),
143 begin(beginIn),
144 front(frontIn),
145 used(false)
146 {
147 }
148
149 // Find the nearest unused neighbor point
151 // Return the other end in the group of the point
153 // Return the alternate point (if one exists), 0 otherwise
155 // Sets the rev flags in the group assuming that the group starts with this point
156 void SetRevInGroup();
157 // Mark an end point as used and also mark the two other alternating points as used
158 // Returns the used point
159 void UsePoint();
160 // Mark an end point as unused and possibly also mark the two other alternating points as unused
161 // Returns the used point
162 void UnusePoint();
163 // Return the other end in the connection
165
166 // The coordinates of the point
168 // The group to which the point belongs
170 // The end-point index within the group
172 // The connection, which connects this point
174 // The end point index in the connection
176 // True if this is a begin point (rather than an end point)
177 bool begin;
178 // True if this is a front point (rather than a back point)
179 bool front;
180 // True if the point is used/connected to another point
181 bool used;
182 // The nearest neighbors, to which this group end point may connect
183 std::vector<OrderingGroupNeighbor> nearest;
184};
185
186// A connection between two points/groups
189 index(indexIn)
190 {
191 assert(fromIn->connection == 0);
192 assert(toIn->connection == 0);
193 points[0] = nullptr;
194 points[1] = nullptr;
195 Connect(0, fromIn);
196 Connect(1, toIn);
197 }
198
199 // Connect one of the connection endpoints to the given point
201 {
202 assert(point);
203 points[index] = point;
204 point->connection = this;
205 point->indexInConnection = index;
206 }
207
208 // Get length of connection
210 {
211 return Geom::distance(points[0]->point, points[1]->point);
212 }
213
215 // index of connection in the connections vector (just for debugging)
216 int index;
217};
218
219// A group of OrderingInfoEx, which build a block in path interconnect length optimization.
220// A block can have two sets of endpoints.
221// If a block has 2 sets of endpoints, one can swap between the two sets.
222
224 OrderingGroup(int indexIn) :
225 nEndPoints(0),
226 revItemList(false),
227 revItems(false),
228 index(indexIn)
229 {
230 for (auto & endpoint : endpoints) {
231 endpoint = nullptr;
232 }
233 }
234
236 {
237 for (int i = 0; i < nEndPoints; i++) {
238 delete endpoints[i];
239 }
240 }
241
242 // Set the endpoints of a group from the items
243 void SetEndpoints();
244 // Add all points from another group as neighbors
245 void AddNeighbors(OrderingGroup *nghb);
246 // Mark an end point as used and also mark the two other alternating points as used
247 // Returns the used point
249 // Mark an end point as unused and possibly also mark the two other alternating points as unused
250 // Returns the used point
251 void UnusePoint(int index);
252
253 // Items on the group
254 std::vector<OrderingInfoEx *> items;
255 // End points of the group
257 // Number of endpoints used (either 2 or 4)
259 // Index of the group (just for debugging purposes)
260 int index;
261 // If true, the items in the group shall be output from back to front.
263 // If false, the individual items are output alternatingly normal-reversed
264 // If true, the individual items are output alternatingly reversed-normal
266};
267
268// A segment is either a OrderingGroup or a series of groups and connections.
269// Usually a segment has just 2 end points.
270// If a segment is just one ordering group, it has the same number of end points as the ordering group
271// A main difference between a segment and a group is that the segment does not own the end points.
272
275 nEndPoints(0),
276 endbit(0),
277 swapbit(0)
278 {}
279
280 // Add an end point
281 void AddPoint(OrderingGroupPoint *point);
282 // Get begin point (taking swap and end bit into account
283 OrderingGroupPoint *GetBeginPoint(unsigned int iSwap, unsigned int iEnd);
284 // Get end point (taking swap and end bit into account
285 OrderingGroupPoint *GetEndPoint(unsigned int iSwap, unsigned int iEnd);
286
287 // End points of the group
289 // Number of endpoints used (either 2 or 4)
291 // bit index in the end counter
293 // bit index in the swap counter
295};
296
297
298// Sub-path reordering: do nothing - keep original order
299void OrderingOriginal(std::vector<OrderingInfo> &infos);
300
301// Sub-path reordering: reverse every other sub path
302void OrderingZigZag(std::vector<OrderingInfo> &infos, bool revfirst);
303
304// Sub-path reordering: continue with the neartest start or end point of yet unused sub paths
305void OrderingClosest(std::vector<OrderingInfo> &infos, bool revfirst);
306
307// Global optimization of path length
308void OrderingAdvanced(std::vector<OrderingInfo> &infos, int nDims);
309
310} //LPEEmbroderyStitchOrdering
311} //namespace LivePathEffect
312} //namespace Inkscape
313
314#endif
Two-dimensional point that doubles as a vector.
Definition point.h:66
double Coord
Floating point type used to store coordinates.
Definition coord.h:76
Angle distance(Angle const &a, Angle const &b)
Definition angle.h:163
void OrderingClosest(std::vector< OrderingInfo > &infos, bool revfirst)
void OrderingZigZag(std::vector< OrderingInfo > &infos, bool revfirst)
void OrderingAdvanced(std::vector< OrderingInfo > &infos, int nDims)
Helper class to stream background task notifications as a series of messages.
OrderingGroupConnection(OrderingGroupPoint *fromIn, OrderingGroupPoint *toIn, int indexIn)
static bool Compare(const OrderingGroupNeighbor &a, const OrderingGroupNeighbor &b)
OrderingGroupPoint(const Geom::Point &pointIn, OrderingGroup *groupIn, int indexIn, bool beginIn, bool frontIn)
void MakeGroup(std::vector< OrderingInfoEx * > &infos, std::vector< OrderingGroup * > *groups)
void AddToGroup(std::vector< OrderingInfoEx * > &infos, OrderingGroup *group)
OrderingPoint(const Geom::Point &pointIn, OrderingInfoEx *infoexIn, bool beginIn)
OrderingGroupPoint * GetBeginPoint(unsigned int iSwap, unsigned int iEnd)
OrderingGroupPoint * GetEndPoint(unsigned int iSwap, unsigned int iEnd)