1 /*-----------------------------------------------------------------------------
2 * Data structures and prototypes for slvs.lib, a geometric constraint solver.
3 *
4 * See the comments in this file, the accompanying sample code that uses
5 * this library, and the accompanying documentation (DOC.txt).
6 *
7 * Copyright 2009-2013 Jonathan Westhues.
8 *---------------------------------------------------------------------------*/
9
10 #ifndef __SLVS_H
11 #define __SLVS_H
12
13 #ifdef WIN32
14 # ifdef EXPORT_DLL
15 # define DLL __declspec( dllexport )
16 # else
17 # define DLL __declspec( dllimport )
18 # endif
19 #else
20 # define DLL
21 #endif
22
23 #ifdef __cplusplus
24 extern "C" {
25 #endif
26
27 #ifdef _MSC_VER
28 typedef unsigned __int32 uint32_t;
29 #else
30 #include <stdint.h>
31 #endif
32
33 typedef uint32_t Slvs_hParam;
34 typedef uint32_t Slvs_hEntity;
35 typedef uint32_t Slvs_hConstraint;
36 typedef uint32_t Slvs_hGroup;
37
38 /* To obtain the 3d (not projected into a workplane) of a constraint or
39 * an entity, specify this instead of the workplane. */
40 #define SLVS_FREE_IN_3D 0
41
42
43 typedef struct {
44 Slvs_hParam h;
45 Slvs_hGroup group;
46 double val;
47 } Slvs_Param;
48
49
50 #define SLVS_E_POINT_IN_3D 50000
51 #define SLVS_E_POINT_IN_2D 50001
52
53 #define SLVS_E_NORMAL_IN_3D 60000
54 #define SLVS_E_NORMAL_IN_2D 60001
55
56 #define SLVS_E_DISTANCE 70000
57
58 /* The special point, normal, and distance types used for parametric step
59 * and repeat, extrude, and assembly are currently not exposed. Please
60 * contact us if you are interested in using these. */
61
62 #define SLVS_E_WORKPLANE 80000
63 #define SLVS_E_LINE_SEGMENT 80001
64 #define SLVS_E_CUBIC 80002
65 #define SLVS_E_CIRCLE 80003
66 #define SLVS_E_ARC_OF_CIRCLE 80004
67
68 typedef struct {
69 Slvs_hEntity h;
70 Slvs_hGroup group;
71
72 int type;
73
74 Slvs_hEntity wrkpl;
75 Slvs_hEntity point[4];
76 Slvs_hEntity normal;
77 Slvs_hEntity distance;
78
79 Slvs_hParam param[4];
80 } Slvs_Entity;
81
82 #define SLVS_C_POINTS_COINCIDENT 100000
83 #define SLVS_C_PT_PT_DISTANCE 100001
84 #define SLVS_C_PT_PLANE_DISTANCE 100002
85 #define SLVS_C_PT_LINE_DISTANCE 100003
86 #define SLVS_C_PT_FACE_DISTANCE 100004
87 #define SLVS_C_PT_IN_PLANE 100005
88 #define SLVS_C_PT_ON_LINE 100006
89 #define SLVS_C_PT_ON_FACE 100007
90 #define SLVS_C_EQUAL_LENGTH_LINES 100008
91 #define SLVS_C_LENGTH_RATIO 100009
92 #define SLVS_C_EQ_LEN_PT_LINE_D 100010
93 #define SLVS_C_EQ_PT_LN_DISTANCES 100011
94 #define SLVS_C_EQUAL_ANGLE 100012
95 #define SLVS_C_EQUAL_LINE_ARC_LEN 100013
96 #define SLVS_C_SYMMETRIC 100014
97 #define SLVS_C_SYMMETRIC_HORIZ 100015
98 #define SLVS_C_SYMMETRIC_VERT 100016
99 #define SLVS_C_SYMMETRIC_LINE 100017
100 #define SLVS_C_AT_MIDPOINT 100018
101 #define SLVS_C_HORIZONTAL 100019
102 #define SLVS_C_VERTICAL 100020
103 #define SLVS_C_DIAMETER 100021
104 #define SLVS_C_PT_ON_CIRCLE 100022
105 #define SLVS_C_SAME_ORIENTATION 100023
106 #define SLVS_C_ANGLE 100024
107 #define SLVS_C_PARALLEL 100025
108 #define SLVS_C_PERPENDICULAR 100026
109 #define SLVS_C_ARC_LINE_TANGENT 100027
110 #define SLVS_C_CUBIC_LINE_TANGENT 100028
111 #define SLVS_C_EQUAL_RADIUS 100029
112 #define SLVS_C_PROJ_PT_DISTANCE 100030
113 #define SLVS_C_WHERE_DRAGGED 100031
114 #define SLVS_C_CURVE_CURVE_TANGENT 100032
115 #define SLVS_C_LENGTH_DIFFERENCE 100033
116
117 typedef struct {
118 Slvs_hConstraint h;
119 Slvs_hGroup group;
120
121 int type;
122
123 Slvs_hEntity wrkpl;
124
125 double valA;
126 Slvs_hEntity ptA;
127 Slvs_hEntity ptB;
128 Slvs_hEntity entityA;
129 Slvs_hEntity entityB;
130 Slvs_hEntity entityC;
131 Slvs_hEntity entityD;
132
133 int other;
134 int other2;
135 } Slvs_Constraint;
136
137
138 typedef struct {
139 /*** INPUT VARIABLES
140 *
141 * Here, we specify the parameters and their initial values, the entities,
142 * and the constraints. For example, param[] points to the array of
143 * parameters, which has length params, so that the last valid element
144 * is param[params-1].
145 *
146 * param[] is actually an in/out variable; if the solver is successful,
147 * then the new values (that satisfy the constraints) are written to it. */
148 Slvs_Param *param;
149 int params;
150 Slvs_Entity *entity;
151 int entities;
152 Slvs_Constraint *constraint;
153 int constraints;
154
155 /* If a parameter corresponds to a point (distance, normal, etc.) being
156 * dragged, then specify it here. This will cause the solver to favor
157 * that parameter, and attempt to change it as little as possible even
158 * if that requires it to change other parameters more.
159 *
160 * Unused members of this array should be set to zero. */
161 Slvs_hParam dragged[4];
162
163 /* If the solver fails, then it can determine which constraints are
164 * causing the problem. But this is a relatively slow process (for
165 * a system with n constraints, about n times as long as just solving).
166 * If calculateFaileds is true, then the solver will do so, otherwise
167 * not. */
168 int calculateFaileds;
169
170 /*** OUTPUT VARIABLES
171 *
172 * If the solver fails, then it can report which constraints are causing
173 * the problem. The caller should allocate the array failed[], and pass
174 * its size in faileds.
175 *
176 * The solver will set faileds equal to the number of problematic
177 * constraints, and write their Slvs_hConstraints into failed[]. To
178 * ensure that there is sufficient space for any possible set of
179 * failing constraints, faileds should be greater than or equal to
180 * constraints. */
181 Slvs_hConstraint *failed;
182 int faileds;
183
184 /* The solver indicates the number of unconstrained degrees of freedom. */
185 int dof;
186
187 /* The solver indicates whether the solution succeeded. */
188 #define SLVS_RESULT_OKAY 0
189 #define SLVS_RESULT_INCONSISTENT 1
190 #define SLVS_RESULT_DIDNT_CONVERGE 2
191 #define SLVS_RESULT_TOO_MANY_UNKNOWNS 3
192 int result;
193 } Slvs_System;
194
195 DLL void Slvs_Solve(Slvs_System *sys, Slvs_hGroup hg);
196
197
198 /* Our base coordinate system has basis vectors
199 * (1, 0, 0) (0, 1, 0) (0, 0, 1)
200 * A unit quaternion defines a rotation to a new coordinate system with
201 * basis vectors
202 * U V N
203 * which these functions compute from the quaternion. */
204 DLL void Slvs_QuaternionU(double qw, double qx, double qy, double qz,
205 double *x, double *y, double *z);
206 DLL void Slvs_QuaternionV(double qw, double qx, double qy, double qz,
207 double *x, double *y, double *z);
208 DLL void Slvs_QuaternionN(double qw, double qx, double qy, double qz,
209 double *x, double *y, double *z);
210
211 /* Similarly, compute a unit quaternion in terms of two basis vectors. */
212 DLL void Slvs_MakeQuaternion(double ux, double uy, double uz,
213 double vx, double vy, double vz,
214 double *qw, double *qx, double *qy, double *qz);
215
216
217 /*-------------------------------------
218 * These are just convenience functions, to save you the trouble of filling
219 * out the structures by hand. The code is included in the header file to
220 * let the compiler inline them if possible. */
221
Slvs_MakeParam(Slvs_hParam h,Slvs_hGroup group,double val)222 static inline Slvs_Param Slvs_MakeParam(Slvs_hParam h, Slvs_hGroup group, double val)
223 {
224 Slvs_Param r;
225 r.h = h;
226 r.group = group;
227 r.val = val;
228 return r;
229 }
Slvs_MakePoint2d(Slvs_hEntity h,Slvs_hGroup group,Slvs_hEntity wrkpl,Slvs_hParam u,Slvs_hParam v)230 static inline Slvs_Entity Slvs_MakePoint2d(Slvs_hEntity h, Slvs_hGroup group,
231 Slvs_hEntity wrkpl,
232 Slvs_hParam u, Slvs_hParam v)
233 {
234 Slvs_Entity r;
235 memset(&r, 0, sizeof(r));
236 r.h = h;
237 r.group = group;
238 r.type = SLVS_E_POINT_IN_2D;
239 r.wrkpl = wrkpl;
240 r.param[0] = u;
241 r.param[1] = v;
242 return r;
243 }
Slvs_MakePoint3d(Slvs_hEntity h,Slvs_hGroup group,Slvs_hParam x,Slvs_hParam y,Slvs_hParam z)244 static inline Slvs_Entity Slvs_MakePoint3d(Slvs_hEntity h, Slvs_hGroup group,
245 Slvs_hParam x, Slvs_hParam y, Slvs_hParam z)
246 {
247 Slvs_Entity r;
248 memset(&r, 0, sizeof(r));
249 r.h = h;
250 r.group = group;
251 r.type = SLVS_E_POINT_IN_3D;
252 r.wrkpl = SLVS_FREE_IN_3D;
253 r.param[0] = x;
254 r.param[1] = y;
255 r.param[2] = z;
256 return r;
257 }
Slvs_MakeNormal3d(Slvs_hEntity h,Slvs_hGroup group,Slvs_hParam qw,Slvs_hParam qx,Slvs_hParam qy,Slvs_hParam qz)258 static inline Slvs_Entity Slvs_MakeNormal3d(Slvs_hEntity h, Slvs_hGroup group,
259 Slvs_hParam qw, Slvs_hParam qx,
260 Slvs_hParam qy, Slvs_hParam qz)
261 {
262 Slvs_Entity r;
263 memset(&r, 0, sizeof(r));
264 r.h = h;
265 r.group = group;
266 r.type = SLVS_E_NORMAL_IN_3D;
267 r.wrkpl = SLVS_FREE_IN_3D;
268 r.param[0] = qw;
269 r.param[1] = qx;
270 r.param[2] = qy;
271 r.param[3] = qz;
272 return r;
273 }
Slvs_MakeNormal2d(Slvs_hEntity h,Slvs_hGroup group,Slvs_hEntity wrkpl)274 static inline Slvs_Entity Slvs_MakeNormal2d(Slvs_hEntity h, Slvs_hGroup group,
275 Slvs_hEntity wrkpl)
276 {
277 Slvs_Entity r;
278 memset(&r, 0, sizeof(r));
279 r.h = h;
280 r.group = group;
281 r.type = SLVS_E_NORMAL_IN_2D;
282 r.wrkpl = wrkpl;
283 return r;
284 }
Slvs_MakeDistance(Slvs_hEntity h,Slvs_hGroup group,Slvs_hEntity wrkpl,Slvs_hParam d)285 static inline Slvs_Entity Slvs_MakeDistance(Slvs_hEntity h, Slvs_hGroup group,
286 Slvs_hEntity wrkpl, Slvs_hParam d)
287 {
288 Slvs_Entity r;
289 memset(&r, 0, sizeof(r));
290 r.h = h;
291 r.group = group;
292 r.type = SLVS_E_DISTANCE;
293 r.wrkpl = wrkpl;
294 r.param[0] = d;
295 return r;
296 }
Slvs_MakeLineSegment(Slvs_hEntity h,Slvs_hGroup group,Slvs_hEntity wrkpl,Slvs_hEntity ptA,Slvs_hEntity ptB)297 static inline Slvs_Entity Slvs_MakeLineSegment(Slvs_hEntity h, Slvs_hGroup group,
298 Slvs_hEntity wrkpl,
299 Slvs_hEntity ptA, Slvs_hEntity ptB)
300 {
301 Slvs_Entity r;
302 memset(&r, 0, sizeof(r));
303 r.h = h;
304 r.group = group;
305 r.type = SLVS_E_LINE_SEGMENT;
306 r.wrkpl = wrkpl;
307 r.point[0] = ptA;
308 r.point[1] = ptB;
309 return r;
310 }
Slvs_MakeCubic(Slvs_hEntity h,Slvs_hGroup group,Slvs_hEntity wrkpl,Slvs_hEntity pt0,Slvs_hEntity pt1,Slvs_hEntity pt2,Slvs_hEntity pt3)311 static inline Slvs_Entity Slvs_MakeCubic(Slvs_hEntity h, Slvs_hGroup group,
312 Slvs_hEntity wrkpl,
313 Slvs_hEntity pt0, Slvs_hEntity pt1,
314 Slvs_hEntity pt2, Slvs_hEntity pt3)
315 {
316 Slvs_Entity r;
317 memset(&r, 0, sizeof(r));
318 r.h = h;
319 r.group = group;
320 r.type = SLVS_E_CUBIC;
321 r.wrkpl = wrkpl;
322 r.point[0] = pt0;
323 r.point[1] = pt1;
324 r.point[2] = pt2;
325 r.point[3] = pt3;
326 return r;
327 }
Slvs_MakeArcOfCircle(Slvs_hEntity h,Slvs_hGroup group,Slvs_hEntity wrkpl,Slvs_hEntity normal,Slvs_hEntity center,Slvs_hEntity start,Slvs_hEntity end)328 static inline Slvs_Entity Slvs_MakeArcOfCircle(Slvs_hEntity h, Slvs_hGroup group,
329 Slvs_hEntity wrkpl,
330 Slvs_hEntity normal,
331 Slvs_hEntity center,
332 Slvs_hEntity start, Slvs_hEntity end)
333 {
334 Slvs_Entity r;
335 memset(&r, 0, sizeof(r));
336 r.h = h;
337 r.group = group;
338 r.type = SLVS_E_ARC_OF_CIRCLE;
339 r.wrkpl = wrkpl;
340 r.normal = normal;
341 r.point[0] = center;
342 r.point[1] = start;
343 r.point[2] = end;
344 return r;
345 }
Slvs_MakeCircle(Slvs_hEntity h,Slvs_hGroup group,Slvs_hEntity wrkpl,Slvs_hEntity center,Slvs_hEntity normal,Slvs_hEntity radius)346 static inline Slvs_Entity Slvs_MakeCircle(Slvs_hEntity h, Slvs_hGroup group,
347 Slvs_hEntity wrkpl,
348 Slvs_hEntity center,
349 Slvs_hEntity normal, Slvs_hEntity radius)
350 {
351 Slvs_Entity r;
352 memset(&r, 0, sizeof(r));
353 r.h = h;
354 r.group = group;
355 r.type = SLVS_E_CIRCLE;
356 r.wrkpl = wrkpl;
357 r.point[0] = center;
358 r.normal = normal;
359 r.distance = radius;
360 return r;
361 }
Slvs_MakeWorkplane(Slvs_hEntity h,Slvs_hGroup group,Slvs_hEntity origin,Slvs_hEntity normal)362 static inline Slvs_Entity Slvs_MakeWorkplane(Slvs_hEntity h, Slvs_hGroup group,
363 Slvs_hEntity origin, Slvs_hEntity normal)
364 {
365 Slvs_Entity r;
366 memset(&r, 0, sizeof(r));
367 r.h = h;
368 r.group = group;
369 r.type = SLVS_E_WORKPLANE;
370 r.wrkpl = SLVS_FREE_IN_3D;
371 r.point[0] = origin;
372 r.normal = normal;
373 return r;
374 }
375
Slvs_MakeConstraint(Slvs_hConstraint h,Slvs_hGroup group,int type,Slvs_hEntity wrkpl,double valA,Slvs_hEntity ptA,Slvs_hEntity ptB,Slvs_hEntity entityA,Slvs_hEntity entityB)376 static inline Slvs_Constraint Slvs_MakeConstraint(Slvs_hConstraint h,
377 Slvs_hGroup group,
378 int type,
379 Slvs_hEntity wrkpl,
380 double valA,
381 Slvs_hEntity ptA,
382 Slvs_hEntity ptB,
383 Slvs_hEntity entityA,
384 Slvs_hEntity entityB)
385 {
386 Slvs_Constraint r;
387 memset(&r, 0, sizeof(r));
388 r.h = h;
389 r.group = group;
390 r.type = type;
391 r.wrkpl = wrkpl;
392 r.valA = valA;
393 r.ptA = ptA;
394 r.ptB = ptB;
395 r.entityA = entityA;
396 r.entityB = entityB;
397 return r;
398 }
399
400 #ifdef __cplusplus
401 }
402 #endif
403
404 #endif
405