2009-04-22 06:15:01 +00:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Data structures and prototypes for slvs.lib, a geometric constraint solver.
|
|
|
|
//
|
2011-03-13 08:04:09 +00:00
|
|
|
// See the comments in this file, the accompanying sample code that uses
|
|
|
|
// this library, and the accompanying documentation (DOC.txt).
|
2009-04-22 06:15:01 +00:00
|
|
|
//
|
2013-07-28 22:08:34 +00:00
|
|
|
// Copyright 2009-2013 Jonathan Westhues.
|
2009-04-22 06:15:01 +00:00
|
|
|
//-----------------------------------------------------------------------------
|
2009-04-20 07:32:07 +00:00
|
|
|
|
|
|
|
#ifndef __SLVS_H
|
|
|
|
#define __SLVS_H
|
|
|
|
|
2010-07-10 18:53:30 +00:00
|
|
|
#ifdef EXPORT_DLL
|
|
|
|
#define DLL __declspec( dllexport )
|
|
|
|
#else
|
|
|
|
#define DLL __declspec( dllimport )
|
|
|
|
#endif
|
|
|
|
|
2009-04-20 07:32:07 +00:00
|
|
|
#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;
|
|
|
|
|
|
|
|
|
2010-05-07 02:13:57 +00:00
|
|
|
#define SLVS_E_POINT_IN_3D 50000
|
|
|
|
#define SLVS_E_POINT_IN_2D 50001
|
2009-04-20 07:32:07 +00:00
|
|
|
|
2010-05-07 02:13:57 +00:00
|
|
|
#define SLVS_E_NORMAL_IN_3D 60000
|
|
|
|
#define SLVS_E_NORMAL_IN_2D 60001
|
2009-04-20 07:32:07 +00:00
|
|
|
|
2010-05-07 02:13:57 +00:00
|
|
|
#define SLVS_E_DISTANCE 70000
|
2009-04-20 07:32:07 +00:00
|
|
|
|
2009-04-22 06:15:01 +00:00
|
|
|
// 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.
|
|
|
|
|
2010-05-07 02:13:57 +00:00
|
|
|
#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
|
2009-04-20 07:32:07 +00:00
|
|
|
|
|
|
|
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
|
2010-01-27 18:15:06 +00:00
|
|
|
#define SLVS_C_PROJ_PT_DISTANCE 100030
|
2010-05-07 02:13:57 +00:00
|
|
|
#define SLVS_C_WHERE_DRAGGED 100031
|
2010-05-10 04:14:06 +00:00
|
|
|
#define SLVS_C_CURVE_CURVE_TANGENT 100032
|
2009-04-20 07:32:07 +00:00
|
|
|
|
|
|
|
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;
|
2010-05-07 02:13:57 +00:00
|
|
|
|
2009-04-20 07:32:07 +00:00
|
|
|
int other;
|
2010-05-10 04:14:06 +00:00
|
|
|
int other2;
|
2009-04-20 07:32:07 +00:00
|
|
|
} 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
|
2010-05-07 02:13:57 +00:00
|
|
|
// if that requires it to change other parameters more.
|
2009-04-20 07:32:07 +00:00
|
|
|
//
|
|
|
|
// Unused members of this array should be set to zero.
|
|
|
|
Slvs_hParam dragged[4];
|
|
|
|
|
2009-04-21 07:56:17 +00:00
|
|
|
// 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).
|
2010-05-07 02:13:57 +00:00
|
|
|
// If calculateFaileds is true, then the solver will do so, otherwise
|
2009-04-21 07:56:17 +00:00
|
|
|
// not.
|
|
|
|
int calculateFaileds;
|
|
|
|
|
|
|
|
//// OUTPUT VARIABLES
|
2009-04-20 07:32:07 +00:00
|
|
|
//
|
|
|
|
// 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
|
2009-04-22 06:15:01 +00:00
|
|
|
// 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.
|
2009-04-20 07:32:07 +00:00
|
|
|
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;
|
|
|
|
|
2010-07-10 18:53:30 +00:00
|
|
|
DLL void Slvs_Solve(Slvs_System *sys, Slvs_hGroup hg);
|
2009-04-20 07:32:07 +00:00
|
|
|
|
|
|
|
|
|
|
|
// 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.
|
2010-07-10 18:53:30 +00:00
|
|
|
DLL void Slvs_QuaternionU(double qw, double qx, double qy, double qz,
|
|
|
|
double *x, double *y, double *z);
|
|
|
|
DLL void Slvs_QuaternionV(double qw, double qx, double qy, double qz,
|
|
|
|
double *x, double *y, double *z);
|
|
|
|
DLL void Slvs_QuaternionN(double qw, double qx, double qy, double qz,
|
|
|
|
double *x, double *y, double *z);
|
2009-04-20 07:32:07 +00:00
|
|
|
|
|
|
|
// Similarly, compute a unit quaternion in terms of two basis vectors.
|
2010-07-10 18:53:30 +00:00
|
|
|
DLL void Slvs_MakeQuaternion(double ux, double uy, double uz,
|
|
|
|
double vx, double vy, double vz,
|
|
|
|
double *qw, double *qx, double *qy, double *qz);
|
2009-04-20 07:32:07 +00:00
|
|
|
|
|
|
|
|
|
|
|
//-------------------------------------
|
|
|
|
// 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,
|
2010-01-23 06:40:10 +00:00
|
|
|
Slvs_hEntity normal,
|
2009-04-20 07:32:07 +00:00
|
|
|
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;
|
2010-01-23 06:40:10 +00:00
|
|
|
r.normal = normal;
|
2009-04-20 07:32:07 +00:00
|
|
|
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
|