208 lines
8.2 KiB
C
208 lines
8.2 KiB
C
//-----------------------------------------------------------------------------
|
|
// Some sample code for slvs.lib. We draw some geometric entities, provide
|
|
// initial guesses for their positions, and then constrain them. The solver
|
|
// calculates their new positions, in order to satisfy the constraints.
|
|
//
|
|
// This code is provide for evaluation purposes only. To purchase a license,
|
|
// please visit:
|
|
//
|
|
// http://solvespace.com/
|
|
//
|
|
// Copyright 2009, Jonathan Westhues
|
|
//-----------------------------------------------------------------------------
|
|
#include <windows.h>
|
|
#include <stdio.h>
|
|
|
|
#include "slvs.h"
|
|
|
|
Slvs_System sys;
|
|
|
|
void *CheckMalloc(size_t n)
|
|
{
|
|
void *r = malloc(n);
|
|
if(!r) {
|
|
printf("out of memory!\n");
|
|
exit(-1);
|
|
}
|
|
return r;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// An example of a constraint in 3d. We create
|
|
//-----------------------------------------------------------------------------
|
|
void Example3d(void)
|
|
{
|
|
// This will contain a single group, which will arbitrarily number 1.
|
|
int g = 1;
|
|
|
|
// A point, initially at (x y z) = (10 10 10)
|
|
sys.param[sys.params++] = Slvs_MakeParam(1, g, 10.0);
|
|
sys.param[sys.params++] = Slvs_MakeParam(2, g, 10.0);
|
|
sys.param[sys.params++] = Slvs_MakeParam(3, g, 10.0);
|
|
sys.entity[sys.entities++] = Slvs_MakePoint3d(101, g, 1, 2, 3);
|
|
// and a second point at (20 20 20)
|
|
sys.param[sys.params++] = Slvs_MakeParam(4, g, 20.0);
|
|
sys.param[sys.params++] = Slvs_MakeParam(5, g, 20.0);
|
|
sys.param[sys.params++] = Slvs_MakeParam(6, g, 20.0);
|
|
sys.entity[sys.entities++] = Slvs_MakePoint3d(102, g, 4, 5, 6);
|
|
// and a line segment connecting them.
|
|
sys.entity[sys.entities++] = Slvs_MakeLineSegment(200, g,
|
|
SLVS_FREE_IN_3D, 101, 102);
|
|
|
|
// The distance between the points should be 30.0 units.
|
|
sys.constraint[sys.constraints++] = Slvs_MakeConstraint(
|
|
1, g,
|
|
SLVS_C_PT_PT_DISTANCE,
|
|
SLVS_FREE_IN_3D,
|
|
30.0,
|
|
101, 102, 0, 0);
|
|
|
|
// Let's tell the solver to keep the second point as close to constant
|
|
// as possible, instead moving the first point.
|
|
sys.dragged[0] = 4;
|
|
sys.dragged[1] = 5;
|
|
sys.dragged[2] = 6;
|
|
|
|
// Now that we have written our system, we solve.
|
|
Slvs_Solve(&sys, g);
|
|
|
|
if(sys.result == SLVS_RESULT_OKAY) {
|
|
printf("okay; now at (%.3f %.3f %.3f)\n"
|
|
" (%.3f %.3f %.3f)\n",
|
|
sys.param[0].val, sys.param[1].val, sys.param[2].val,
|
|
sys.param[3].val, sys.param[4].val, sys.param[5].val);
|
|
printf("%d DOF\n", sys.dof);
|
|
} else {
|
|
printf("solve failed");
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// 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.
|
|
//-----------------------------------------------------------------------------
|
|
void Example2d(void)
|
|
{
|
|
int g;
|
|
double qw, qx, qy, qz;
|
|
|
|
g = 1;
|
|
// First, we create our workplane. Its origin corresponds to the origin
|
|
// of our base frame (x y z) = (0 0 0)
|
|
sys.param[sys.params++] = Slvs_MakeParam(1, g, 0.0);
|
|
sys.param[sys.params++] = Slvs_MakeParam(2, g, 0.0);
|
|
sys.param[sys.params++] = Slvs_MakeParam(3, g, 0.0);
|
|
sys.entity[sys.entities++] = Slvs_MakePoint3d(101, g, 1, 2, 3);
|
|
// and it is parallel to the xy plane, so it has basis vectors (1 0 0)
|
|
// and (0 1 0).
|
|
Slvs_MakeQuaternion(1, 0, 0,
|
|
0, 1, 0, &qw, &qx, &qy, &qz);
|
|
sys.param[sys.params++] = Slvs_MakeParam(4, g, qw);
|
|
sys.param[sys.params++] = Slvs_MakeParam(5, g, qx);
|
|
sys.param[sys.params++] = Slvs_MakeParam(6, g, qy);
|
|
sys.param[sys.params++] = Slvs_MakeParam(7, g, qz);
|
|
sys.entity[sys.entities++] = Slvs_MakeNormal3d(102, g, 3, 4, 5, 6);
|
|
|
|
sys.entity[sys.entities++] = Slvs_MakeWorkplane(200, g, 101, 102);
|
|
|
|
// Now create a second group. We'll solve group 2, while leaving group 1
|
|
// constant; so the workplane that we've created will be locked down,
|
|
// and the solver can't move it.
|
|
g = 2;
|
|
// These points are represented by their coordinates (u v) within the
|
|
// workplane, so they need only two parameters each.
|
|
sys.param[sys.params++] = Slvs_MakeParam(11, g, 10.0);
|
|
sys.param[sys.params++] = Slvs_MakeParam(12, g, 20.0);
|
|
sys.entity[sys.entities++] = Slvs_MakePoint2d(301, g, 200, 11, 12);
|
|
|
|
sys.param[sys.params++] = Slvs_MakeParam(13, g, 20.0);
|
|
sys.param[sys.params++] = Slvs_MakeParam(14, g, 10.0);
|
|
sys.entity[sys.entities++] = Slvs_MakePoint2d(302, g, 200, 13, 14);
|
|
|
|
// And we create a line segment with those endpoints.
|
|
sys.entity[sys.entities++] = Slvs_MakeLineSegment(400, g,
|
|
200, 301, 302);
|
|
|
|
// The length of our line segment is 30.0 units.
|
|
sys.constraint[sys.constraints++] = Slvs_MakeConstraint(
|
|
1, g,
|
|
SLVS_C_PT_PT_DISTANCE,
|
|
200,
|
|
30.0,
|
|
301, 302, 0, 0);
|
|
|
|
// And the distance from our line segment to the origin is 10.0 units.
|
|
sys.constraint[sys.constraints++] = Slvs_MakeConstraint(
|
|
2, g,
|
|
SLVS_C_PT_LINE_DISTANCE,
|
|
200,
|
|
10.0,
|
|
101, 0, 400, 0);
|
|
// And the line segment is vertical.
|
|
sys.constraint[sys.constraints++] = Slvs_MakeConstraint(
|
|
3, g,
|
|
SLVS_C_VERTICAL,
|
|
200,
|
|
0.0,
|
|
0, 0, 400, 0);
|
|
// And the distance from one endpoint to the origin is 15.0 units.
|
|
sys.constraint[sys.constraints++] = Slvs_MakeConstraint(
|
|
4, g,
|
|
SLVS_C_PT_PT_DISTANCE,
|
|
200,
|
|
15.0,
|
|
301, 101, 0, 0);
|
|
/*
|
|
// And same for the other endpoint; so if you add this constraint then
|
|
// the sketch is overconstrained and will signal an error.
|
|
sys.constraint[sys.constraints++] = Slvs_MakeConstraint(
|
|
5, g,
|
|
SLVS_C_PT_PT_DISTANCE,
|
|
200,
|
|
18.0,
|
|
302, 101, 0, 0); */
|
|
|
|
// If the solver fails, then ask it to report which constraints caused
|
|
// the problem.
|
|
sys.calculateFaileds = 1;
|
|
|
|
// And solve.
|
|
Slvs_Solve(&sys, g);
|
|
|
|
if(sys.result == SLVS_RESULT_OKAY) {
|
|
printf("okay; now at (%.3f %.3f)\n"
|
|
" (%.3f %.3f)\n",
|
|
sys.param[7].val, sys.param[8].val,
|
|
sys.param[9].val, sys.param[10].val);
|
|
printf("%d DOF\n", sys.dof);
|
|
} else {
|
|
int i;
|
|
printf("solve failed: problematic constraints are:");
|
|
for(i = 0; i < sys.faileds; i++) {
|
|
printf(" %d", sys.failed[i]);
|
|
}
|
|
printf("\n");
|
|
if(sys.result == SLVS_RESULT_INCONSISTENT) {
|
|
printf("system inconsistent\n");
|
|
} else {
|
|
printf("system nonconvergent\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
int main(void)
|
|
{
|
|
memset(&sys, 0, sizeof(sys));
|
|
sys.param = CheckMalloc(50*sizeof(sys.param[0]));
|
|
sys.entity = CheckMalloc(50*sizeof(sys.entity[0]));
|
|
sys.constraint = CheckMalloc(50*sizeof(sys.constraint[0]));
|
|
|
|
sys.failed = CheckMalloc(50*sizeof(sys.failed[0]));
|
|
sys.faileds = 50;
|
|
|
|
// Example3d();
|
|
Example2d();
|
|
}
|
|
|