Solvespace

Форк
0
/
lib.cpp 
258 строк · 9.2 Кб
1
//-----------------------------------------------------------------------------
2
// A library wrapper around SolveSpace, to permit someone to use its constraint
3
// solver without coupling their program too much to SolveSpace's internals.
4
//
5
// Copyright 2008-2013 Jonathan Westhues.
6
//-----------------------------------------------------------------------------
7
#include "solvespace.h"
8
#define EXPORT_DLL
9
#include <slvs.h>
10

11
Sketch SolveSpace::SK = {};
12
static System SYS;
13

14
void SolveSpace::Platform::FatalError(const std::string &message) {
15
    fprintf(stderr, "%s", message.c_str());
16
    abort();
17
}
18

19
void Group::GenerateEquations(IdList<Equation,hEquation> *) {
20
    // Nothing to do for now.
21
}
22

23
extern "C" {
24

25
void Slvs_QuaternionU(double qw, double qx, double qy, double qz,
26
                         double *x, double *y, double *z)
27
{
28
    Quaternion q = Quaternion::From(qw, qx, qy, qz);
29
    Vector v = q.RotationU();
30
    *x = v.x;
31
    *y = v.y;
32
    *z = v.z;
33
}
34

35
void Slvs_QuaternionV(double qw, double qx, double qy, double qz,
36
                         double *x, double *y, double *z)
37
{
38
    Quaternion q = Quaternion::From(qw, qx, qy, qz);
39
    Vector v = q.RotationV();
40
    *x = v.x;
41
    *y = v.y;
42
    *z = v.z;
43
}
44

45
void Slvs_QuaternionN(double qw, double qx, double qy, double qz,
46
                         double *x, double *y, double *z)
47
{
48
    Quaternion q = Quaternion::From(qw, qx, qy, qz);
49
    Vector v = q.RotationN();
50
    *x = v.x;
51
    *y = v.y;
52
    *z = v.z;
53
}
54

55
void Slvs_MakeQuaternion(double ux, double uy, double uz,
56
                         double vx, double vy, double vz,
57
                         double *qw, double *qx, double *qy, double *qz)
58
{
59
    Vector u = Vector::From(ux, uy, uz),
60
           v = Vector::From(vx, vy, vz);
61
    Quaternion q = Quaternion::From(u, v);
62
    *qw = q.w;
63
    *qx = q.vx;
64
    *qy = q.vy;
65
    *qz = q.vz;
66
}
67

68
void Slvs_Solve(Slvs_System *ssys, Slvs_hGroup shg)
69
{
70
    int i;
71
    for(i = 0; i < ssys->params; i++) {
72
        Slvs_Param *sp = &(ssys->param[i]);
73
        Param p = {};
74

75
        p.h.v = sp->h;
76
        p.val = sp->val;
77
        SK.param.Add(&p);
78
        if(sp->group == shg) {
79
            SYS.param.Add(&p);
80
        }
81
    }
82

83
    for(i = 0; i < ssys->entities; i++) {
84
        Slvs_Entity *se = &(ssys->entity[i]);
85
        EntityBase e = {};
86

87
        switch(se->type) {
88
case SLVS_E_POINT_IN_3D:        e.type = Entity::Type::POINT_IN_3D; break;
89
case SLVS_E_POINT_IN_2D:        e.type = Entity::Type::POINT_IN_2D; break;
90
case SLVS_E_NORMAL_IN_3D:       e.type = Entity::Type::NORMAL_IN_3D; break;
91
case SLVS_E_NORMAL_IN_2D:       e.type = Entity::Type::NORMAL_IN_2D; break;
92
case SLVS_E_DISTANCE:           e.type = Entity::Type::DISTANCE; break;
93
case SLVS_E_WORKPLANE:          e.type = Entity::Type::WORKPLANE; break;
94
case SLVS_E_LINE_SEGMENT:       e.type = Entity::Type::LINE_SEGMENT; break;
95
case SLVS_E_CUBIC:              e.type = Entity::Type::CUBIC; break;
96
case SLVS_E_CIRCLE:             e.type = Entity::Type::CIRCLE; break;
97
case SLVS_E_ARC_OF_CIRCLE:      e.type = Entity::Type::ARC_OF_CIRCLE; break;
98

99
default: dbp("bad entity type %d", se->type); return;
100
        }
101
        e.h.v           = se->h;
102
        e.group.v       = se->group;
103
        e.workplane.v   = se->wrkpl;
104
        e.point[0].v    = se->point[0];
105
        e.point[1].v    = se->point[1];
106
        e.point[2].v    = se->point[2];
107
        e.point[3].v    = se->point[3];
108
        e.normal.v      = se->normal;
109
        e.distance.v    = se->distance;
110
        e.param[0].v    = se->param[0];
111
        e.param[1].v    = se->param[1];
112
        e.param[2].v    = se->param[2];
113
        e.param[3].v    = se->param[3];
114

115
        SK.entity.Add(&e);
116
    }
117
    IdList<Param, hParam> params = {};
118
    for(i = 0; i < ssys->constraints; i++) {
119
        Slvs_Constraint *sc = &(ssys->constraint[i]);
120
        ConstraintBase c = {};
121

122
        Constraint::Type t;
123
        switch(sc->type) {
124
case SLVS_C_POINTS_COINCIDENT:  t = Constraint::Type::POINTS_COINCIDENT; break;
125
case SLVS_C_PT_PT_DISTANCE:     t = Constraint::Type::PT_PT_DISTANCE; break;
126
case SLVS_C_PT_PLANE_DISTANCE:  t = Constraint::Type::PT_PLANE_DISTANCE; break;
127
case SLVS_C_PT_LINE_DISTANCE:   t = Constraint::Type::PT_LINE_DISTANCE; break;
128
case SLVS_C_PT_FACE_DISTANCE:   t = Constraint::Type::PT_FACE_DISTANCE; break;
129
case SLVS_C_PT_IN_PLANE:        t = Constraint::Type::PT_IN_PLANE; break;
130
case SLVS_C_PT_ON_LINE:         t = Constraint::Type::PT_ON_LINE; break;
131
case SLVS_C_PT_ON_FACE:         t = Constraint::Type::PT_ON_FACE; break;
132
case SLVS_C_EQUAL_LENGTH_LINES: t = Constraint::Type::EQUAL_LENGTH_LINES; break;
133
case SLVS_C_LENGTH_RATIO:       t = Constraint::Type::LENGTH_RATIO; break;
134
case SLVS_C_ARC_ARC_LEN_RATIO:  t = Constraint::Type::ARC_ARC_LEN_RATIO; break;
135
case SLVS_C_ARC_LINE_LEN_RATIO: t = Constraint::Type::ARC_LINE_LEN_RATIO; break;
136
case SLVS_C_EQ_LEN_PT_LINE_D:   t = Constraint::Type::EQ_LEN_PT_LINE_D; break;
137
case SLVS_C_EQ_PT_LN_DISTANCES: t = Constraint::Type::EQ_PT_LN_DISTANCES; break;
138
case SLVS_C_EQUAL_ANGLE:        t = Constraint::Type::EQUAL_ANGLE; break;
139
case SLVS_C_EQUAL_LINE_ARC_LEN: t = Constraint::Type::EQUAL_LINE_ARC_LEN; break;
140
case SLVS_C_LENGTH_DIFFERENCE:  t = Constraint::Type::LENGTH_DIFFERENCE; break;
141
case SLVS_C_ARC_ARC_DIFFERENCE: t = Constraint::Type::ARC_ARC_DIFFERENCE; break;
142
case SLVS_C_ARC_LINE_DIFFERENCE:t = Constraint::Type::ARC_LINE_DIFFERENCE; break;
143
case SLVS_C_SYMMETRIC:          t = Constraint::Type::SYMMETRIC; break;
144
case SLVS_C_SYMMETRIC_HORIZ:    t = Constraint::Type::SYMMETRIC_HORIZ; break;
145
case SLVS_C_SYMMETRIC_VERT:     t = Constraint::Type::SYMMETRIC_VERT; break;
146
case SLVS_C_SYMMETRIC_LINE:     t = Constraint::Type::SYMMETRIC_LINE; break;
147
case SLVS_C_AT_MIDPOINT:        t = Constraint::Type::AT_MIDPOINT; break;
148
case SLVS_C_HORIZONTAL:         t = Constraint::Type::HORIZONTAL; break;
149
case SLVS_C_VERTICAL:           t = Constraint::Type::VERTICAL; break;
150
case SLVS_C_DIAMETER:           t = Constraint::Type::DIAMETER; break;
151
case SLVS_C_PT_ON_CIRCLE:       t = Constraint::Type::PT_ON_CIRCLE; break;
152
case SLVS_C_SAME_ORIENTATION:   t = Constraint::Type::SAME_ORIENTATION; break;
153
case SLVS_C_ANGLE:              t = Constraint::Type::ANGLE; break;
154
case SLVS_C_PARALLEL:           t = Constraint::Type::PARALLEL; break;
155
case SLVS_C_PERPENDICULAR:      t = Constraint::Type::PERPENDICULAR; break;
156
case SLVS_C_ARC_LINE_TANGENT:   t = Constraint::Type::ARC_LINE_TANGENT; break;
157
case SLVS_C_CUBIC_LINE_TANGENT: t = Constraint::Type::CUBIC_LINE_TANGENT; break;
158
case SLVS_C_EQUAL_RADIUS:       t = Constraint::Type::EQUAL_RADIUS; break;
159
case SLVS_C_PROJ_PT_DISTANCE:   t = Constraint::Type::PROJ_PT_DISTANCE; break;
160
case SLVS_C_WHERE_DRAGGED:      t = Constraint::Type::WHERE_DRAGGED; break;
161
case SLVS_C_CURVE_CURVE_TANGENT:t = Constraint::Type::CURVE_CURVE_TANGENT; break;
162

163
default: dbp("bad constraint type %d", sc->type); return;
164
        }
165

166
        c.type = t;
167

168
        c.h.v           = sc->h;
169
        c.group.v       = sc->group;
170
        c.workplane.v   = sc->wrkpl;
171
        c.valA          = sc->valA;
172
        c.ptA.v         = sc->ptA;
173
        c.ptB.v         = sc->ptB;
174
        c.entityA.v     = sc->entityA;
175
        c.entityB.v     = sc->entityB;
176
        c.entityC.v     = sc->entityC;
177
        c.entityD.v     = sc->entityD;
178
        c.other         = (sc->other) ? true : false;
179
        c.other2        = (sc->other2) ? true : false;
180

181
        c.Generate(&params);
182
        if(!params.IsEmpty()) {
183
            for(Param &p : params) {
184
                p.h = SK.param.AddAndAssignId(&p);
185
                c.valP = p.h;
186
                SYS.param.Add(&p);
187
            }
188
            params.Clear();
189
            c.ModifyToSatisfy();
190
        }
191

192
        SK.constraint.Add(&c);
193
    }
194

195
    for(i = 0; i < (int)arraylen(ssys->dragged); i++) {
196
        if(ssys->dragged[i]) {
197
            hParam hp = { ssys->dragged[i] };
198
            SYS.dragged.Add(&hp);
199
        }
200
    }
201

202
    Group g = {};
203
    g.h.v = shg;
204

205
    List<hConstraint> bad = {};
206

207
    // Now we're finally ready to solve!
208
    bool andFindBad = ssys->calculateFaileds ? true : false;
209
    SolveResult how = SYS.Solve(&g, NULL, &(ssys->dof), &bad, andFindBad, /*andFindFree=*/false);
210

211
    switch(how) {
212
        case SolveResult::OKAY:
213
            ssys->result = SLVS_RESULT_OKAY;
214
            break;
215

216
        case SolveResult::DIDNT_CONVERGE:
217
            ssys->result = SLVS_RESULT_DIDNT_CONVERGE;
218
            break;
219

220
        case SolveResult::REDUNDANT_DIDNT_CONVERGE:
221
        case SolveResult::REDUNDANT_OKAY:
222
            ssys->result = SLVS_RESULT_INCONSISTENT;
223
            break;
224

225
        case SolveResult::TOO_MANY_UNKNOWNS:
226
            ssys->result = SLVS_RESULT_TOO_MANY_UNKNOWNS;
227
            break;
228
    }
229

230
    // Write the new parameter values back to our caller.
231
    for(i = 0; i < ssys->params; i++) {
232
        Slvs_Param *sp = &(ssys->param[i]);
233
        hParam hp = { sp->h };
234
        sp->val = SK.GetParam(hp)->val;
235
    }
236

237
    if(ssys->failed) {
238
        // Copy over any the list of problematic constraints.
239
        for(i = 0; i < ssys->faileds && i < bad.n; i++) {
240
            ssys->failed[i] = bad[i].v;
241
        }
242
        ssys->faileds = bad.n;
243
    }
244

245
    bad.Clear();
246
    SYS.param.Clear();
247
    SYS.entity.Clear();
248
    SYS.eq.Clear();
249
    SYS.dragged.Clear();
250

251
    SK.param.Clear();
252
    SK.entity.Clear();
253
    SK.constraint.Clear();
254

255
    FreeAllTemporary();
256
}
257

258
} /* extern "C" */
259

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.