Polish a few little things in the constraint solver library stuff.
[git-p4: depot-paths = "//depot/solvespace/": change = 1947]solver
parent
9efa922795
commit
f8dbc89189
|
@ -1,4 +1,7 @@
|
||||||
|
|
||||||
|
INTRODUCTION
|
||||||
|
============
|
||||||
|
|
||||||
A sketch in SolveSpace consists of three basic elements: parameters,
|
A sketch in SolveSpace consists of three basic elements: parameters,
|
||||||
entities, and constraints.
|
entities, and constraints.
|
||||||
|
|
||||||
|
@ -19,11 +22,11 @@ distance constraint will set the distance between two point entities.
|
||||||
|
|
||||||
Paramters, entities, and constraints are typically referenced by their
|
Paramters, entities, and constraints are typically referenced by their
|
||||||
handles (Slvs_hParam, Slvs_hEntity, Slvs_hConstraint). These handles are
|
handles (Slvs_hParam, Slvs_hEntity, Slvs_hConstraint). These handles are
|
||||||
32-bit integer values starting from 1. Each object has a unique handle
|
32-bit integer values starting from 1. The zero handle is reserved. Each
|
||||||
within its type (but it's acceptable, for example to have a constraint
|
object has a unique handle within its type (but it's acceptable, for
|
||||||
with an Slvs_hConstraint of 7, and also to have an entity with an
|
example to have a constraint with an Slvs_hConstraint of 7, and also to
|
||||||
Slvs_hEntity of 7). The use of handles instead of pointers helps to
|
have an entity with an Slvs_hEntity of 7). The use of handles instead
|
||||||
avoid memory corruption.
|
of pointers helps to avoid memory corruption.
|
||||||
|
|
||||||
Entities and constraints are assigned into groups. A group is a set of
|
Entities and constraints are assigned into groups. A group is a set of
|
||||||
entities and constraints that is solved simultaneously. In a parametric
|
entities and constraints that is solved simultaneously. In a parametric
|
||||||
|
@ -31,23 +34,23 @@ CAD system, a single group would typically correspond to a single sketch.
|
||||||
Constraints within a group may refer to entities outside that group,
|
Constraints within a group may refer to entities outside that group,
|
||||||
but only the entities within that group will be modified by the solver.
|
but only the entities within that group will be modified by the solver.
|
||||||
|
|
||||||
(Consider point A in group 1, and point B in group 2. We have a constraint
|
Consider point A in group 1, and point B in group 2. We have a constraint
|
||||||
in group 2 that makes the points coincident. When we solve group 2, the
|
in group 2 that makes the points coincident. When we solve group 2, the
|
||||||
solver is allowed to move point B to place it on top of point A. It is
|
solver is allowed to move point B to place it on top of point A. It is
|
||||||
not allowed to move point A to put it on top of point B, because point
|
not allowed to move point A to put it on top of point B, because point
|
||||||
A is outside the group being solved.)
|
A is outside the group being solved.
|
||||||
|
|
||||||
This corresponds to the typical structure of a parametric CAD system. In a
|
This corresponds to the typical structure of a parametric CAD system. In a
|
||||||
later sketch, we may constrain our entities against existing geometry from
|
later sketch, we may constrain our entities against existing geometry from
|
||||||
earlier sketches. The constraints will move the entities in our current
|
earlier sketches. The constraints will move the entities in our current
|
||||||
sketch, but will not change the geometry from the earlier sketches.
|
sketch, but will not change the geometry from the earlier sketches.
|
||||||
|
|
||||||
To use the solver, we first define a set of parameters, entities,
|
To use the solver, we first define a set of parameters, entities, and
|
||||||
and constraints. We provide an initial guess for each parameter; this
|
constraints. We provide an initial guess for each parameter; this is
|
||||||
will improve convergence, and also determine which solution gets chosen
|
necessary to achieve convergence, and also determines which solution
|
||||||
when (finitely many) multiple solutions exist. Typically, these initial
|
gets chosen when (finitely many) multiple solutions exist. Typically,
|
||||||
guesses are provided by the initial configuration in which the user drew
|
these initial guesses are provided by the initial configuration in which
|
||||||
the entities before constraining them.
|
the user drew the entities before constraining them.
|
||||||
|
|
||||||
We then run the solver for a given group. The entities within that group
|
We then run the solver for a given group. The entities within that group
|
||||||
are modified in an attempt to satisfy the constraints.
|
are modified in an attempt to satisfy the constraints.
|
||||||
|
@ -55,18 +58,22 @@ are modified in an attempt to satisfy the constraints.
|
||||||
After running the solver, there are three possible outcomes:
|
After running the solver, there are three possible outcomes:
|
||||||
|
|
||||||
* All constraints were satisfied to within our numerical
|
* All constraints were satisfied to within our numerical
|
||||||
tolerance (i.e., success).
|
tolerance (i.e., success). The result is equal to SLVS_RESULT_OKAY,
|
||||||
|
and the parameters in param[] have been updated.
|
||||||
|
|
||||||
* The solver can prove that two constraints are inconsistent (for
|
* The solver can prove that two constraints are inconsistent (for
|
||||||
example, if a line with nonzero length is constrained both
|
example, if a line with nonzero length is constrained both
|
||||||
horizontal and vertical). In that case, a list of inconsistent
|
horizontal and vertical). In that case, a list of inconsistent
|
||||||
constraints is generated.
|
constraints is generated in failed[].
|
||||||
|
|
||||||
* The solver cannot prove that two constraints are inconsistent, but
|
* The solver cannot prove that two constraints are inconsistent, but
|
||||||
it cannot find a solution. In that case, the list of unsatisfied
|
it cannot find a solution. In that case, the list of unsatisfied
|
||||||
constraints is generated.
|
constraints is generated in failed[].
|
||||||
|
|
||||||
|
|
||||||
|
TYPES OF ENTITIES
|
||||||
|
=================
|
||||||
|
|
||||||
SLVS_E_POINT_IN_3D
|
SLVS_E_POINT_IN_3D
|
||||||
|
|
||||||
A point in 3d. Defined by three parameters:
|
A point in 3d. Defined by three parameters:
|
||||||
|
@ -236,6 +243,8 @@ SLVS_E_ARC_OF_CIRCLE
|
||||||
distance(center, beginning) = distance(center, end)
|
distance(center, beginning) = distance(center, end)
|
||||||
|
|
||||||
|
|
||||||
|
TYPES OF CONSTRAINTS
|
||||||
|
====================
|
||||||
|
|
||||||
Many constraints can apply either in 3d, or in a workplane. This is
|
Many constraints can apply either in 3d, or in a workplane. This is
|
||||||
determined by the wrkpl member of the constraint. If that member is set
|
determined by the wrkpl member of the constraint. If that member is set
|
||||||
|
@ -401,3 +410,11 @@ SLVS_C_EQUAL_RADIUS
|
||||||
The circles or arcs entityA and entityB have equal radius.
|
The circles or arcs entityA and entityB have equal radius.
|
||||||
|
|
||||||
|
|
||||||
|
USING THE SOLVER
|
||||||
|
================
|
||||||
|
|
||||||
|
See the enclosed sample code, example.c.
|
||||||
|
|
||||||
|
|
||||||
|
Copyright 2009, Jonathan Westhues.
|
||||||
|
|
||||||
|
|
|
@ -78,9 +78,9 @@ void Example3d(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// An example of a constraint in 2d. In an earlier group, we have created a
|
// An example of a constraint in 2d. In our first group, we create a workplane
|
||||||
// workplane. Then in our group to be solved, we create a line segment, which
|
// along the reference frame's xy plane. In a second group, we create some
|
||||||
// we dimension to be horizontal and 2.0 units long.
|
// entities in that group and dimension them.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void Example2d(void)
|
void Example2d(void)
|
||||||
{
|
{
|
||||||
|
@ -124,6 +124,38 @@ void Example2d(void)
|
||||||
sys.entity[sys.entities++] = Slvs_MakeLineSegment(400, g,
|
sys.entity[sys.entities++] = Slvs_MakeLineSegment(400, g,
|
||||||
200, 301, 302);
|
200, 301, 302);
|
||||||
|
|
||||||
|
// Now three more points.
|
||||||
|
sys.param[sys.params++] = Slvs_MakeParam(15, g, 100.0);
|
||||||
|
sys.param[sys.params++] = Slvs_MakeParam(16, g, 120.0);
|
||||||
|
sys.entity[sys.entities++] = Slvs_MakePoint2d(303, g, 200, 15, 16);
|
||||||
|
|
||||||
|
sys.param[sys.params++] = Slvs_MakeParam(17, g, 120.0);
|
||||||
|
sys.param[sys.params++] = Slvs_MakeParam(18, g, 110.0);
|
||||||
|
sys.entity[sys.entities++] = Slvs_MakePoint2d(304, g, 200, 17, 18);
|
||||||
|
|
||||||
|
sys.param[sys.params++] = Slvs_MakeParam(19, g, 115.0);
|
||||||
|
sys.param[sys.params++] = Slvs_MakeParam(20, g, 115.0);
|
||||||
|
sys.entity[sys.entities++] = Slvs_MakePoint2d(305, g, 200, 19, 20);
|
||||||
|
|
||||||
|
// And arc, centered at point 303, starting at point 304, ending at
|
||||||
|
// point 305.
|
||||||
|
sys.entity[sys.entities++] = Slvs_MakeArcOfCircle(401, g, 200,
|
||||||
|
303, 304, 305);
|
||||||
|
|
||||||
|
// Now one more point, and a distance
|
||||||
|
sys.param[sys.params++] = Slvs_MakeParam(21, g, 200.0);
|
||||||
|
sys.param[sys.params++] = Slvs_MakeParam(22, g, 200.0);
|
||||||
|
sys.entity[sys.entities++] = Slvs_MakePoint2d(306, g, 200, 21, 22);
|
||||||
|
|
||||||
|
sys.param[sys.params++] = Slvs_MakeParam(23, g, 30.0);
|
||||||
|
sys.entity[sys.entities++] = Slvs_MakeDistance(307, g, 200, 23);
|
||||||
|
|
||||||
|
// And a complete circle, centered at point 306 with radius equal to
|
||||||
|
// distance 307. The normal is 102, the same as our workplane.
|
||||||
|
sys.entity[sys.entities++] = Slvs_MakeCircle(402, g, 200,
|
||||||
|
306, 102, 307);
|
||||||
|
|
||||||
|
|
||||||
// The length of our line segment is 30.0 units.
|
// The length of our line segment is 30.0 units.
|
||||||
sys.constraint[sys.constraints++] = Slvs_MakeConstraint(
|
sys.constraint[sys.constraints++] = Slvs_MakeConstraint(
|
||||||
1, g,
|
1, g,
|
||||||
|
@ -163,6 +195,21 @@ void Example2d(void)
|
||||||
18.0,
|
18.0,
|
||||||
302, 101, 0, 0); */
|
302, 101, 0, 0); */
|
||||||
|
|
||||||
|
// The arc and the circle have equal radius.
|
||||||
|
sys.constraint[sys.constraints++] = Slvs_MakeConstraint(
|
||||||
|
6, g,
|
||||||
|
SLVS_C_EQUAL_RADIUS,
|
||||||
|
200,
|
||||||
|
0.0,
|
||||||
|
0, 0, 401, 402);
|
||||||
|
// The arc has radius 17.0 units.
|
||||||
|
sys.constraint[sys.constraints++] = Slvs_MakeConstraint(
|
||||||
|
7, g,
|
||||||
|
SLVS_C_DIAMETER,
|
||||||
|
200,
|
||||||
|
17.0*2,
|
||||||
|
0, 0, 401, 0);
|
||||||
|
|
||||||
// If the solver fails, then ask it to report which constraints caused
|
// If the solver fails, then ask it to report which constraints caused
|
||||||
// the problem.
|
// the problem.
|
||||||
sys.calculateFaileds = 1;
|
sys.calculateFaileds = 1;
|
||||||
|
@ -171,10 +218,19 @@ void Example2d(void)
|
||||||
Slvs_Solve(&sys, g);
|
Slvs_Solve(&sys, g);
|
||||||
|
|
||||||
if(sys.result == SLVS_RESULT_OKAY) {
|
if(sys.result == SLVS_RESULT_OKAY) {
|
||||||
printf("okay; now at (%.3f %.3f)\n"
|
printf("solved okay\n");
|
||||||
" (%.3f %.3f)\n",
|
printf("line from (%.3f %.3f) to (%.3f %.3f)\n",
|
||||||
sys.param[7].val, sys.param[8].val,
|
sys.param[7].val, sys.param[8].val,
|
||||||
sys.param[9].val, sys.param[10].val);
|
sys.param[9].val, sys.param[10].val);
|
||||||
|
|
||||||
|
printf("arc center (%.3f %.3f) start (%.3f %.3f) finish (%.3f %.3f)\n",
|
||||||
|
sys.param[11].val, sys.param[12].val,
|
||||||
|
sys.param[13].val, sys.param[14].val,
|
||||||
|
sys.param[15].val, sys.param[16].val);
|
||||||
|
|
||||||
|
printf("circle center (%.3f %.3f) radius %.3f\n",
|
||||||
|
sys.param[17].val, sys.param[18].val,
|
||||||
|
sys.param[19].val);
|
||||||
printf("%d DOF\n", sys.dof);
|
printf("%d DOF\n", sys.dof);
|
||||||
} else {
|
} else {
|
||||||
int i;
|
int i;
|
||||||
|
|
|
@ -58,6 +58,17 @@ void Slvs_MakeQuaternion(double ux, double uy, double uz,
|
||||||
void Slvs_Solve(Slvs_System *ssys, Slvs_hGroup shg)
|
void Slvs_Solve(Slvs_System *ssys, Slvs_hGroup shg)
|
||||||
{
|
{
|
||||||
if(!IsInit) {
|
if(!IsInit) {
|
||||||
|
#if 1
|
||||||
|
dbp("SolveSpace library initialized (evaluation version only).");
|
||||||
|
dbp("Built " __DATE__ " " __TIME__
|
||||||
|
". Copyright 2009 Jonathan Westhues.");
|
||||||
|
HWND h = GetForegroundWindow();
|
||||||
|
MessageBox(h,
|
||||||
|
"This is an evaluation copy of SolveSpace. To purchase a license, please "
|
||||||
|
"contact info@solvespace.com.\r\n\r\n"
|
||||||
|
"Copyright 2009 Jonathan Westhues.",
|
||||||
|
"SolveSpace", MB_OK);
|
||||||
|
#endif
|
||||||
InitHeaps();
|
InitHeaps();
|
||||||
IsInit = 1;
|
IsInit = 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,16 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// 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, Jonathan Westhues
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
#ifndef __SLVS_H
|
#ifndef __SLVS_H
|
||||||
#define __SLVS_H
|
#define __SLVS_H
|
||||||
|
@ -31,6 +44,10 @@ typedef struct {
|
||||||
|
|
||||||
#define SLVS_E_DISTANCE 70000
|
#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_WORKPLANE 80000
|
||||||
#define SLVS_E_LINE_SEGMENT 80001
|
#define SLVS_E_LINE_SEGMENT 80001
|
||||||
#define SLVS_E_CUBIC 80002
|
#define SLVS_E_CUBIC 80002
|
||||||
|
@ -142,7 +159,10 @@ typedef struct {
|
||||||
// its size in faileds.
|
// its size in faileds.
|
||||||
//
|
//
|
||||||
// The solver will set faileds equal to the number of problematic
|
// The solver will set faileds equal to the number of problematic
|
||||||
// constraints, and write their Slvs_hConstraints on
|
// 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;
|
Slvs_hConstraint *failed;
|
||||||
int faileds;
|
int faileds;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue