//----------------------------------------------------------------------------- // Data structures and prototypes for slvs.lib, a geometric constraint solver. // // See the comments in this file, the accompanying sample code (example.c) // that uses this library, and the accompanying documentation (DOC.txt). // // This code is provide for evaluation purposes only. To purchase a license, // please visit: // // http://solvespace.com/ // // Copyright 2009 Useful Subset, LLC //----------------------------------------------------------------------------- #ifndef __SLVS_H #define __SLVS_H #ifdef __cplusplus extern "C" { #endif typedef DWORD Slvs_hParam; typedef DWORD Slvs_hEntity; typedef DWORD Slvs_hConstraint; typedef DWORD Slvs_hGroup; // To obtain the 3d (not projected into a workplane) of a constraint or // an entity, specify this instead of the workplane. #define SLVS_FREE_IN_3D 0 typedef struct { Slvs_hParam h; Slvs_hGroup group; double val; } Slvs_Param; #define SLVS_E_POINT_IN_3D 50000 #define SLVS_E_POINT_IN_2D 50001 #define SLVS_E_NORMAL_IN_3D 60000 #define SLVS_E_NORMAL_IN_2D 60001 #define SLVS_E_DISTANCE 70000 // The special point, normal, and distance types used for parametric step // and repeat, extrude, and assembly are currently not exposed. Please // contact us if you are interested in using these. #define SLVS_E_WORKPLANE 80000 #define SLVS_E_LINE_SEGMENT 80001 #define SLVS_E_CUBIC 80002 #define SLVS_E_CIRCLE 80003 #define SLVS_E_ARC_OF_CIRCLE 80004 typedef struct { Slvs_hEntity h; Slvs_hGroup group; int type; Slvs_hEntity wrkpl; Slvs_hEntity point[4]; Slvs_hEntity normal; Slvs_hEntity distance; Slvs_hParam param[4]; } Slvs_Entity; #define SLVS_C_POINTS_COINCIDENT 100000 #define SLVS_C_PT_PT_DISTANCE 100001 #define SLVS_C_PT_PLANE_DISTANCE 100002 #define SLVS_C_PT_LINE_DISTANCE 100003 #define SLVS_C_PT_FACE_DISTANCE 100004 #define SLVS_C_PT_IN_PLANE 100005 #define SLVS_C_PT_ON_LINE 100006 #define SLVS_C_PT_ON_FACE 100007 #define SLVS_C_EQUAL_LENGTH_LINES 100008 #define SLVS_C_LENGTH_RATIO 100009 #define SLVS_C_EQ_LEN_PT_LINE_D 100010 #define SLVS_C_EQ_PT_LN_DISTANCES 100011 #define SLVS_C_EQUAL_ANGLE 100012 #define SLVS_C_EQUAL_LINE_ARC_LEN 100013 #define SLVS_C_SYMMETRIC 100014 #define SLVS_C_SYMMETRIC_HORIZ 100015 #define SLVS_C_SYMMETRIC_VERT 100016 #define SLVS_C_SYMMETRIC_LINE 100017 #define SLVS_C_AT_MIDPOINT 100018 #define SLVS_C_HORIZONTAL 100019 #define SLVS_C_VERTICAL 100020 #define SLVS_C_DIAMETER 100021 #define SLVS_C_PT_ON_CIRCLE 100022 #define SLVS_C_SAME_ORIENTATION 100023 #define SLVS_C_ANGLE 100024 #define SLVS_C_PARALLEL 100025 #define SLVS_C_PERPENDICULAR 100026 #define SLVS_C_ARC_LINE_TANGENT 100027 #define SLVS_C_CUBIC_LINE_TANGENT 100028 #define SLVS_C_EQUAL_RADIUS 100029 typedef struct { 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; Slvs_hEntity entityC; Slvs_hEntity entityD; int other; } Slvs_Constraint; typedef struct { //// INPUT VARIABLES // // Here, we specify the parameters and their initial values, the entities, // and the constraints. For example, param[] points to the array of // parameters, which has length params, so that the last valid element // is param[params-1]. // // param[] is actually an in/out variable; if the solver is successful, // then the new values (that satisfy the constraints) are written to it. // Slvs_Param *param; int params; Slvs_Entity *entity; int entities; Slvs_Constraint *constraint; int constraints; // If a parameter corresponds to a point (distance, normal, etc.) being // dragged, then specify it here. This will cause the solver to favor // that parameter, and attempt to change it as little as possible even // if that require it to change other parameters more. // // Unused members of this array should be set to zero. Slvs_hParam dragged[4]; // If the solver fails, then it can determine which constraints are // causing the problem. But this is a relatively slow process (for // a system with n constraints, about n times as long as just solving). // If calculateFaileds is set, then the solver will do so, otherwise // not. int calculateFaileds; //// OUTPUT VARIABLES // // If the solver fails, then it can report which constraints are causing // the problem. The caller should allocate the array failed[], and pass // its size in faileds. // // The solver will set faileds equal to the number of problematic // constraints, and write their Slvs_hConstraints into failed[]. To // ensure that there is sufficient space for any possible set of // failing constraints, faileds should be greater than or equal to // constraints. Slvs_hConstraint *failed; int faileds; // The solver indicates the number of unconstrained degrees of freedom. int dof; // The solver indicates whether the solution succeeded. #define SLVS_RESULT_OKAY 0 #define SLVS_RESULT_INCONSISTENT 1 #define SLVS_RESULT_DIDNT_CONVERGE 2 #define SLVS_RESULT_TOO_MANY_UNKNOWNS 3 int result; } Slvs_System; void Slvs_Solve(Slvs_System *sys, Slvs_hGroup hg); // Our base coordinate system has basis vectors // (1, 0, 0) (0, 1, 0) (0, 0, 1) // A unit quaternion defines a rotation to a new coordinate system with // basis vectors // U V N // which these functions compute from the quaternion. void Slvs_QuaternionU(double qw, double qx, double qy, double qz, double *x, double *y, double *z); void Slvs_QuaternionV(double qw, double qx, double qy, double qz, double *x, double *y, double *z); void Slvs_QuaternionN(double qw, double qx, double qy, double qz, double *x, double *y, double *z); // Similarly, compute a unit quaternion in terms of two basis vectors. void Slvs_MakeQuaternion(double ux, double uy, double uz, double vx, double vy, double vz, double *qw, double *qx, double *qy, double *qz); //------------------------------------- // These are just convenience functions, to save you the trouble of filling // out the structures by hand. The code is included in the header file to // let the compiler inline them if possible. static Slvs_Param Slvs_MakeParam(Slvs_hParam h, Slvs_hGroup group, double val) { Slvs_Param r; r.h = h; r.group = group; r.val = val; return r; } static Slvs_Entity Slvs_MakePoint2d(Slvs_hEntity h, Slvs_hGroup group, Slvs_hEntity wrkpl, Slvs_hParam u, Slvs_hParam v) { Slvs_Entity r; memset(&r, 0, sizeof(r)); r.h = h; r.group = group; r.type = SLVS_E_POINT_IN_2D; r.wrkpl = wrkpl; r.param[0] = u; r.param[1] = v; return r; } static Slvs_Entity Slvs_MakePoint3d(Slvs_hEntity h, Slvs_hGroup group, Slvs_hParam x, Slvs_hParam y, Slvs_hParam z) { Slvs_Entity r; memset(&r, 0, sizeof(r)); r.h = h; r.group = group; r.type = SLVS_E_POINT_IN_3D; r.wrkpl = SLVS_FREE_IN_3D; r.param[0] = x; r.param[1] = y; r.param[2] = z; return r; } static Slvs_Entity Slvs_MakeNormal3d(Slvs_hEntity h, Slvs_hGroup group, Slvs_hParam qw, Slvs_hParam qx, Slvs_hParam qy, Slvs_hParam qz) { Slvs_Entity r; memset(&r, 0, sizeof(r)); r.h = h; r.group = group; r.type = SLVS_E_NORMAL_IN_3D; r.wrkpl = SLVS_FREE_IN_3D; r.param[0] = qw; r.param[1] = qx; r.param[2] = qy; r.param[3] = qz; return r; } static Slvs_Entity Slvs_MakeNormal2d(Slvs_hEntity h, Slvs_hGroup group, Slvs_hEntity wrkpl) { Slvs_Entity r; memset(&r, 0, sizeof(r)); r.h = h; r.group = group; r.type = SLVS_E_NORMAL_IN_2D; r.wrkpl = wrkpl; return r; } static Slvs_Entity Slvs_MakeDistance(Slvs_hEntity h, Slvs_hGroup group, Slvs_hEntity wrkpl, Slvs_hParam d) { Slvs_Entity r; memset(&r, 0, sizeof(r)); r.h = h; r.group = group; r.type = SLVS_E_DISTANCE; r.wrkpl = wrkpl; r.param[0] = d; return r; } static Slvs_Entity Slvs_MakeLineSegment(Slvs_hEntity h, Slvs_hGroup group, Slvs_hEntity wrkpl, Slvs_hEntity ptA, Slvs_hEntity ptB) { Slvs_Entity r; memset(&r, 0, sizeof(r)); r.h = h; r.group = group; r.type = SLVS_E_LINE_SEGMENT; r.wrkpl = wrkpl; r.point[0] = ptA; r.point[1] = ptB; return r; } static Slvs_Entity Slvs_MakeCubic(Slvs_hEntity h, Slvs_hGroup group, Slvs_hEntity wrkpl, Slvs_hEntity pt0, Slvs_hEntity pt1, Slvs_hEntity pt2, Slvs_hEntity pt3) { Slvs_Entity r; memset(&r, 0, sizeof(r)); r.h = h; r.group = group; r.type = SLVS_E_CUBIC; r.wrkpl = wrkpl; r.point[0] = pt0; r.point[1] = pt1; r.point[2] = pt2; r.point[3] = pt3; return r; } static Slvs_Entity Slvs_MakeArcOfCircle(Slvs_hEntity h, Slvs_hGroup group, Slvs_hEntity wrkpl, Slvs_hEntity normal, Slvs_hEntity center, Slvs_hEntity start, Slvs_hEntity end) { Slvs_Entity r; memset(&r, 0, sizeof(r)); r.h = h; r.group = group; r.type = SLVS_E_ARC_OF_CIRCLE; r.wrkpl = wrkpl; r.normal = normal; r.point[0] = center; r.point[1] = start; r.point[2] = end; return r; } static Slvs_Entity Slvs_MakeCircle(Slvs_hEntity h, Slvs_hGroup group, Slvs_hEntity wrkpl, Slvs_hEntity center, Slvs_hEntity normal, Slvs_hEntity radius) { Slvs_Entity r; memset(&r, 0, sizeof(r)); r.h = h; r.group = group; r.type = SLVS_E_CIRCLE; r.wrkpl = wrkpl; r.point[0] = center; r.normal = normal; r.distance = radius; return r; } static Slvs_Entity Slvs_MakeWorkplane(Slvs_hEntity h, Slvs_hGroup group, Slvs_hEntity origin, Slvs_hEntity normal) { Slvs_Entity r; memset(&r, 0, sizeof(r)); r.h = h; r.group = group; r.type = SLVS_E_WORKPLANE; r.wrkpl = SLVS_FREE_IN_3D; r.point[0] = origin; r.normal = normal; return r; } static Slvs_Constraint 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) { Slvs_Constraint r; memset(&r, 0, sizeof(r)); r.h = h; r.group = group; r.type = type; r.wrkpl = wrkpl; r.valA = valA; r.ptA = ptA; r.ptB = ptB; r.entityA = entityA; r.entityB = entityB; return r; } #ifdef __cplusplus } #endif #endif