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,
|
||||
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
|
||||
handles (Slvs_hParam, Slvs_hEntity, Slvs_hConstraint). These handles are
|
||||
32-bit integer values starting from 1. Each object has a unique handle
|
||||
within its type (but it's acceptable, for example to have a constraint
|
||||
with an Slvs_hConstraint of 7, and also to have an entity with an
|
||||
Slvs_hEntity of 7). The use of handles instead of pointers helps to
|
||||
avoid memory corruption.
|
||||
32-bit integer values starting from 1. The zero handle is reserved. Each
|
||||
object has a unique handle within its type (but it's acceptable, for
|
||||
example to have a constraint with an Slvs_hConstraint of 7, and also to
|
||||
have an entity with an Slvs_hEntity of 7). The use of handles instead
|
||||
of pointers helps to avoid memory corruption.
|
||||
|
||||
Entities and constraints are assigned into groups. A group is a set of
|
||||
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,
|
||||
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
|
||||
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
|
||||
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
|
||||
later sketch, we may constrain our entities against existing geometry from
|
||||
earlier sketches. The constraints will move the entities in our current
|
||||
sketch, but will not change the geometry from the earlier sketches.
|
||||
|
||||
To use the solver, we first define a set of parameters, entities,
|
||||
and constraints. We provide an initial guess for each parameter; this
|
||||
will improve convergence, and also determine which solution gets chosen
|
||||
when (finitely many) multiple solutions exist. Typically, these initial
|
||||
guesses are provided by the initial configuration in which the user drew
|
||||
the entities before constraining them.
|
||||
To use the solver, we first define a set of parameters, entities, and
|
||||
constraints. We provide an initial guess for each parameter; this is
|
||||
necessary to achieve convergence, and also determines which solution
|
||||
gets chosen when (finitely many) multiple solutions exist. Typically,
|
||||
these initial guesses are provided by the initial configuration in which
|
||||
the user drew the entities before constraining them.
|
||||
|
||||
We then run the solver for a given group. The entities within that group
|
||||
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:
|
||||
|
||||
* 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
|
||||
example, if a line with nonzero length is constrained both
|
||||
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
|
||||
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
|
||||
|
||||
A point in 3d. Defined by three parameters:
|
||||
|
@ -236,6 +243,8 @@ SLVS_E_ARC_OF_CIRCLE
|
|||
distance(center, beginning) = distance(center, end)
|
||||
|
||||
|
||||
TYPES OF CONSTRAINTS
|
||||
====================
|
||||
|
||||
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
|
||||
|
@ -401,3 +410,11 @@ SLVS_C_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
|
||||
// workplane. Then in our group to be solved, we create a line segment, which
|
||||
// we dimension to be horizontal and 2.0 units long.
|
||||
// An example of a constraint in 2d. In our first group, we create a workplane
|
||||
// along the reference frame's xy plane. In a second group, we create some
|
||||
// entities in that group and dimension them.
|
||||
//-----------------------------------------------------------------------------
|
||||
void Example2d(void)
|
||||
{
|
||||
|
@ -124,6 +124,38 @@ void Example2d(void)
|
|||
sys.entity[sys.entities++] = Slvs_MakeLineSegment(400, g,
|
||||
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.
|
||||
sys.constraint[sys.constraints++] = Slvs_MakeConstraint(
|
||||
1, g,
|
||||
|
@ -163,6 +195,21 @@ void Example2d(void)
|
|||
18.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
|
||||
// the problem.
|
||||
sys.calculateFaileds = 1;
|
||||
|
@ -171,10 +218,19 @@ void Example2d(void)
|
|||
Slvs_Solve(&sys, g);
|
||||
|
||||
if(sys.result == SLVS_RESULT_OKAY) {
|
||||
printf("okay; now at (%.3f %.3f)\n"
|
||||
" (%.3f %.3f)\n",
|
||||
printf("solved okay\n");
|
||||
printf("line from (%.3f %.3f) to (%.3f %.3f)\n",
|
||||
sys.param[7].val, sys.param[8].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);
|
||||
} else {
|
||||
int i;
|
||||
|
|
|
@ -58,6 +58,17 @@ void Slvs_MakeQuaternion(double ux, double uy, double uz,
|
|||
void Slvs_Solve(Slvs_System *ssys, Slvs_hGroup shg)
|
||||
{
|
||||
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();
|
||||
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
|
||||
#define __SLVS_H
|
||||
|
@ -31,6 +44,10 @@ typedef struct {
|
|||
|
||||
#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
|
||||
|
@ -142,7 +159,10 @@ typedef struct {
|
|||
// its size in faileds.
|
||||
//
|
||||
// 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;
|
||||
int faileds;
|
||||
|
||||
|
|
Loading…
Reference in New Issue