Solvespace

Форк
0
/
request.cpp 
247 строк · 8.8 Кб
1
//-----------------------------------------------------------------------------
2
// Implementation of our Request class; a request is a user-created thing
3
// that will generate an entity (line, curve) when the sketch is generated,
4
// in the same way that other entities are generated automatically, like
5
// by an extrude or a step and repeat.
6
//
7
// Copyright 2008-2013 Jonathan Westhues.
8
//-----------------------------------------------------------------------------
9
#include "solvespace.h"
10

11
const hRequest Request::HREQUEST_REFERENCE_XY = { 1 };
12
const hRequest Request::HREQUEST_REFERENCE_YZ = { 2 };
13
const hRequest Request::HREQUEST_REFERENCE_ZX = { 3 };
14

15
struct EntReqMapping {
16
    Request::Type  reqType;
17
    Entity::Type   entType;
18
    int            points;
19
    bool           useExtraPoints;
20
    bool           hasNormal;
21
    bool           hasDistance;
22
};
23
static const EntReqMapping EntReqMap[] = {
24
// request type                   entity type                 pts   xtra?   norml   dist
25
{ Request::Type::WORKPLANE,       Entity::Type::WORKPLANE,      1,  false,  true,   false },
26
{ Request::Type::DATUM_POINT,     (Entity::Type)0,              1,  false,  false,  false },
27
{ Request::Type::LINE_SEGMENT,    Entity::Type::LINE_SEGMENT,   2,  false,  false,  false },
28
{ Request::Type::CUBIC,           Entity::Type::CUBIC,          4,  true,   false,  false },
29
{ Request::Type::CUBIC_PERIODIC,  Entity::Type::CUBIC_PERIODIC, 3,  true,   false,  false },
30
{ Request::Type::CIRCLE,          Entity::Type::CIRCLE,         1,  false,  true,   true  },
31
{ Request::Type::ARC_OF_CIRCLE,   Entity::Type::ARC_OF_CIRCLE,  3,  false,  true,   false },
32
{ Request::Type::TTF_TEXT,        Entity::Type::TTF_TEXT,       4,  false,  true,   false },
33
{ Request::Type::IMAGE,           Entity::Type::IMAGE,          4,  false,  true,   false },
34
};
35

36
static void CopyEntityInfo(const EntReqMapping *te, int extraPoints,
37
                           Entity::Type *ent, Request::Type *req,
38
                           int *pts, bool *hasNormal, bool *hasDistance)
39
{
40
    int points = te->points;
41
    if(te->useExtraPoints) points += extraPoints;
42

43
    if(ent)         *ent         = te->entType;
44
    if(req)         *req         = te->reqType;
45
    if(pts)         *pts         = points;
46
    if(hasNormal)   *hasNormal   = te->hasNormal;
47
    if(hasDistance) *hasDistance = te->hasDistance;
48
}
49

50
bool EntReqTable::GetRequestInfo(Request::Type req, int extraPoints,
51
                                 Entity::Type *ent, int *pts, bool *hasNormal, bool *hasDistance)
52
{
53
    for(const EntReqMapping &te : EntReqMap) {
54
        if(req == te.reqType) {
55
            CopyEntityInfo(&te, extraPoints, ent, NULL, pts, hasNormal, hasDistance);
56
            return true;
57
        }
58
    }
59
    return false;
60
}
61

62
bool EntReqTable::GetEntityInfo(Entity::Type ent, int extraPoints,
63
                                Request::Type *req, int *pts, bool *hasNormal, bool *hasDistance)
64
{
65
    for(const EntReqMapping &te : EntReqMap) {
66
        if(ent == te.entType) {
67
            CopyEntityInfo(&te, extraPoints, NULL, req, pts, hasNormal, hasDistance);
68
            return true;
69
        }
70
    }
71
    return false;
72
}
73

74
Request::Type EntReqTable::GetRequestForEntity(Entity::Type ent) {
75
    Request::Type req;
76
    ssassert(GetEntityInfo(ent, 0, &req, NULL, NULL, NULL),
77
             "No entity for request");
78
    return req;
79
}
80

81
void Request::Generate(IdList<Entity,hEntity> *entity,
82
                       IdList<Param,hParam> *param)
83
{
84
    int points = 0;
85
    Entity::Type et = (Entity::Type)0;
86
    bool hasNormal = false;
87
    bool hasDistance = false;
88
    int i;
89

90
    // Request-specific generation.
91
    switch(type) {
92
        case Type::TTF_TEXT: {
93
            // `extraPoints` is storing kerning boolean
94
            double actualAspectRatio = SS.fonts.AspectRatio(font, str, extraPoints);
95
            if(EXACT(actualAspectRatio != 0.0)) {
96
                // We could load the font, so use the actual value.
97
                aspectRatio = actualAspectRatio;
98
            }
99
            if(EXACT(aspectRatio == 0.0)) {
100
                // We couldn't load the font and we don't have anything saved,
101
                // so just use 1:1, which is valid for the missing font symbol anyhow.
102
                aspectRatio = 1.0;
103
            }
104
            break;
105
        }
106

107
        case Type::IMAGE: {
108
            auto image = SS.images.find(file);
109
            if(image != SS.images.end()) {
110
                std::shared_ptr<Pixmap> pixmap = (*image).second;
111
                if(pixmap != NULL) {
112
                    aspectRatio = (double)pixmap->width / (double)pixmap->height;
113
                }
114
            }
115
            if(EXACT(aspectRatio == 0.0)) {
116
                aspectRatio = 1.0;
117
            }
118
            break;
119
        }
120

121
        default: // most requests don't do anything else
122
            break;
123
    }
124

125
    Entity e = {};
126
    EntReqTable::GetRequestInfo(type, extraPoints, &et, &points, &hasNormal, &hasDistance);
127

128
    // Generate the entity that's specific to this request.
129
    e.type = et;
130
    e.extraPoints = extraPoints;
131
    e.group = group;
132
    e.style = style;
133
    e.workplane = workplane;
134
    e.construction = construction;
135
    e.str = str;
136
    e.font = font;
137
    e.file = file;
138
    e.aspectRatio = aspectRatio;
139
    e.h = h.entity(0);
140

141
    // And generate entities for the points
142
    for(i = 0; i < points; i++) {
143
        Entity p = {};
144
        p.workplane = workplane;
145
        // points start from entity 1, except for datum point case
146
        p.h = h.entity(i+((et != (Entity::Type)0) ? 1 : 0));
147
        p.group = group;
148
        p.style = style;
149
        p.construction = e.construction;
150
        if(workplane == Entity::FREE_IN_3D) {
151
            p.type = Entity::Type::POINT_IN_3D;
152
            // params for x y z
153
            p.param[0] = AddParam(param, h.param(16 + 3*i + 0));
154
            p.param[1] = AddParam(param, h.param(16 + 3*i + 1));
155
            p.param[2] = AddParam(param, h.param(16 + 3*i + 2));
156
        } else {
157
            p.type = Entity::Type::POINT_IN_2D;
158
            // params for u v
159
            p.param[0] = AddParam(param, h.param(16 + 3*i + 0));
160
            p.param[1] = AddParam(param, h.param(16 + 3*i + 1));
161
        }
162
        entity->Add(&p);
163
        e.point[i] = p.h;
164
    }
165
    if(hasNormal) {
166
        Entity n = {};
167
        n.workplane = workplane;
168
        n.h = h.entity(32);
169
        n.group = group;
170
        n.style = style;
171
        n.construction = e.construction;
172
        if(workplane == Entity::FREE_IN_3D) {
173
            n.type = Entity::Type::NORMAL_IN_3D;
174
            n.param[0] = AddParam(param, h.param(32+0));
175
            n.param[1] = AddParam(param, h.param(32+1));
176
            n.param[2] = AddParam(param, h.param(32+2));
177
            n.param[3] = AddParam(param, h.param(32+3));
178
        } else {
179
            n.type = Entity::Type::NORMAL_IN_2D;
180
            // and this is just a copy of the workplane quaternion,
181
            // so no params required
182
        }
183
        ssassert(points >= 1, "Positioning a normal requires a point");
184
        // The point determines where the normal gets displayed on-screen;
185
        // it's entirely cosmetic.
186
        n.point[0] = e.point[0];
187
        entity->Add(&n);
188
        e.normal = n.h;
189
    }
190
    if(hasDistance) {
191
        Entity d = {};
192
        d.workplane = workplane;
193
        d.h = h.entity(64);
194
        d.group = group;
195
        d.style = style;
196
        d.type = Entity::Type::DISTANCE;
197
        d.param[0] = AddParam(param, h.param(64));
198
        entity->Add(&d);
199
        e.distance = d.h;
200
    }
201

202
    if(et != (Entity::Type)0) entity->Add(&e);
203
}
204

205
std::string Request::DescriptionString() const {
206
    const char *s = "";
207
    if(h == Request::HREQUEST_REFERENCE_XY) {
208
        s = "#XY";
209
    } else if(h == Request::HREQUEST_REFERENCE_YZ) {
210
        s = "#YZ";
211
    } else if(h == Request::HREQUEST_REFERENCE_ZX) {
212
        s = "#ZX";
213
    } else {
214
        switch(type) {
215
            case Type::WORKPLANE:       s = "workplane";      break;
216
            case Type::DATUM_POINT:     s = "datum-point";    break;
217
            case Type::LINE_SEGMENT:    s = "line-segment";   break;
218
            case Type::CUBIC:           s = "cubic-bezier";   break;
219
            case Type::CUBIC_PERIODIC:  s = "periodic-cubic"; break;
220
            case Type::CIRCLE:          s = "circle";         break;
221
            case Type::ARC_OF_CIRCLE:   s = "arc-of-circle";  break;
222
            case Type::TTF_TEXT:        s = "ttf-text";       break;
223
            case Type::IMAGE:           s = "image";          break;
224
        }
225
    }
226
    ssassert(s != NULL, "Unexpected request type");
227
    return ssprintf("r%03x-%s", h.v, s);
228
}
229

230
int Request::IndexOfPoint(hEntity he) const {
231
    if(type == Type::DATUM_POINT) {
232
        return (he == h.entity(0)) ? 0 : -1;
233
    }
234
    for(int i = 0; i < MAX_POINTS_IN_ENTITY; i++) {
235
        if(he == h.entity(i + 1)) {
236
            return i;
237
        }
238
    }
239
    return -1;
240
}
241

242
hParam Request::AddParam(IdList<Param,hParam> *param, hParam hp) {
243
    Param pa = {};
244
    pa.h = hp;
245
    param->Add(&pa);
246
    return hp;
247
}
248

249

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

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

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

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