Solvespace

Форк
0
/
importmesh.cpp 
256 строк · 7.2 Кб
1
//-----------------------------------------------------------------------------
2
// Triangle mesh file reader. Reads an STL file triangle mesh and creates
3
// a SovleSpace SMesh from it. Supports only Linking, not import.
4
//
5
// Copyright 2020 Paul Kahler.
6
//-----------------------------------------------------------------------------
7
#include "solvespace.h"
8
#include "sketch.h"
9
#include <vector>
10

11
#define MIN_POINT_DISTANCE 0.001
12

13
// we will check for duplicate vertices and keep all their normals
14
class vertex {
15
public:
16
    Vector p;
17
    std::vector<Vector> normal;
18
};
19

20
static bool isEdgeVertex(vertex &v) {
21
    unsigned int i,j;
22
    bool result = false;
23
    for(i=0;i<v.normal.size();i++) {
24
        for(j=i;j<v.normal.size();j++) {
25
            if(v.normal[i].Dot(v.normal[j]) < 0.9) {
26
                result = true;
27
            }
28
        }
29
    }
30
    return result;
31
}
32
// This function has poor performance, used inside a loop it is O(n**2)
33
static void addUnique(std::vector<vertex> &lv, Vector &p, Vector &n) {
34
    unsigned int i;
35
    for(i=0; i<lv.size(); i++) {
36
        if(lv[i].p.Equals(p, MIN_POINT_DISTANCE)) {
37
            break;
38
        }
39
    }
40
    if(i==lv.size()) {
41
        vertex v;
42
        v.p = p;
43
        lv.push_back(v);
44
    }
45
    // we could improve a little by only storing unique normals
46
    lv[i].normal.push_back(n);
47
};
48

49
// Make a new point - type doesn't matter since we will make a copy later
50
static hEntity newPoint(EntityList *el, int *id, Vector p) {
51
    Entity en = {};
52
    en.type = Entity::Type::POINT_N_COPY;
53
    en.extraPoints = 0;
54
    en.timesApplied = 0;
55
    en.group.v = 462;
56
    en.actPoint = p;
57
    en.construction = false;
58
    en.style.v = Style::DATUM;
59
    en.actVisible = true;
60
    en.forceHidden = false;
61

62
    en.h.v = *id + en.group.v*65536; 
63
    *id = *id+1;   
64
    el->Add(&en);
65
    return en.h;
66
}
67

68
// check if a vertex is unique and add it via newPoint if it is.
69
static void addVertex(EntityList *el, Vector v) {
70
    if(el->n < 15000) {
71
        int id = el->n;
72
        newPoint(el, &id, v);
73
    }
74
}
75

76
static hEntity newNormal(EntityList *el, int *id, Quaternion normal, hEntity p) {
77
    // normals have parameters, but we don't need them to make a NORMAL_N_COPY from this
78
    Entity en = {};
79
    en.type = Entity::Type::NORMAL_N_COPY;
80
    en.extraPoints = 0;
81
    en.timesApplied = 0;
82
    en.group.v = 472;
83
    en.actNormal = normal;
84
    en.construction = false;
85
    en.style.v = Style::NORMALS;
86
    // to be visible we need to add a point.
87
//    en.point[0] = newPoint(el, id, Vector::From(0,0,0));
88
    en.point[0] = p;
89
    en.actVisible = true;
90
    en.forceHidden = false;
91

92
    *id = *id+1;
93
    en.h.v = *id + en.group.v*65536;    
94
    el->Add(&en);
95
    return en.h;
96
}
97

98
static hEntity newLine(EntityList *el, int *id, hEntity p0, hEntity p1) {
99
    Entity en = {};
100
    en.type = Entity::Type::LINE_SEGMENT;
101
    en.point[0] = p0;
102
    en.point[1] = p1;
103
    en.extraPoints = 0;
104
    en.timesApplied = 0;
105
    en.group.v = 493;
106
    en.construction = true;
107
    en.style.v = Style::CONSTRUCTION;
108
    en.actVisible = true;
109
    en.forceHidden = false;
110

111
    en.h.v = *id + en.group.v*65536;
112
    *id = *id + 1;
113
    el->Add(&en);
114
    return en.h;
115
}
116

117
namespace SolveSpace {
118

119
bool LinkStl(const Platform::Path &filename, EntityList *el, SMesh *m, SShell *sh) {
120
    dbp("\nLink STL triangle mesh.");
121
    el->Clear();
122
    std::string data;
123
    if(!ReadFile(filename, &data)) {
124
        Error("Couldn't read from '%s'", filename.raw.c_str());
125
        return false;
126
    }
127
    
128
    std::stringstream f(data);
129

130
    char str[80] = {};
131
    f.read(str, 80);
132
    
133
    if(0==memcmp("solid", str, 5)) {
134
    // just returning false will trigger the warning that linked file is not present
135
    // best solution is to add an importer for text STL.
136
        Message(_("Text-formated STL files are not currently supported"));
137
        return false;
138
    }
139
    
140
    uint32_t n;
141
    uint32_t color;
142
    
143
    f.read((char*)&n, 4);
144
    dbp("%d triangles", n);
145
    
146
    float x,y,z;
147
    float xn,yn,zn;
148
    
149
    std::vector<vertex> verts = {};
150
    
151
    for(uint32_t i = 0; i<n; i++) {
152
        STriangle tr = {};
153

154
        // read the triangle normal
155
        f.read((char*)&xn, 4);
156
        f.read((char*)&yn, 4);
157
        f.read((char*)&zn, 4);
158
        tr.an = Vector::From(xn,yn,zn);
159
        tr.bn = tr.an;
160
        tr.cn = tr.an;
161

162
        f.read((char*)&x, 4);
163
        f.read((char*)&y, 4);
164
        f.read((char*)&z, 4);
165
        tr.a.x = x;
166
        tr.a.y = y;
167
        tr.a.z = z;
168

169
        f.read((char*)&x, 4);
170
        f.read((char*)&y, 4);
171
        f.read((char*)&z, 4);
172
        tr.b.x = x;
173
        tr.b.y = y;
174
        tr.b.z = z;
175

176
        f.read((char*)&x, 4);
177
        f.read((char*)&y, 4);
178
        f.read((char*)&z, 4);
179
        tr.c.x = x;
180
        tr.c.y = y;
181
        tr.c.z = z;
182

183
        f.read((char*)&color,2);
184
        if(color & 0x8000) {
185
            tr.meta.color.red = (color >> 7) & 0xf8;
186
            tr.meta.color.green = (color >> 2) & 0xf8;
187
            tr.meta.color.blue = (color << 3);
188
            tr.meta.color.alpha = 255;
189
        } else {
190
            tr.meta.color.red = 90;
191
            tr.meta.color.green = 120;
192
            tr.meta.color.blue = 140;
193
            tr.meta.color.alpha = 255;        
194
        }
195

196
        m->AddTriangle(&tr);
197
        Vector normal = tr.Normal().WithMagnitude(1.0);
198
        addUnique(verts, tr.a, normal);
199
        addUnique(verts, tr.b, normal);
200
        addUnique(verts, tr.c, normal);
201
    }
202
    dbp("%d vertices", verts.size());
203

204
    int id = 1;
205

206
    //add the STL origin and normals
207
    hEntity origin = newPoint(el, &id, Vector::From(0.0, 0.0, 0.0));    
208
    newNormal(el, &id, Quaternion::From(Vector::From(1,0,0),Vector::From(0,1,0)), origin);
209
    newNormal(el, &id, Quaternion::From(Vector::From(0,1,0),Vector::From(0,0,1)), origin);
210
    newNormal(el, &id, Quaternion::From(Vector::From(0,0,1),Vector::From(1,0,0)), origin);
211

212
    BBox box = {};
213
    box.minp = verts[0].p;
214
    box.maxp = verts[0].p;
215

216
    // determine the bounding box for all vertexes
217
    for(unsigned int i=1; i<verts.size(); i++) {
218
        box.Include(verts[i].p);
219
    }
220

221
    hEntity p[8];
222
    p[0] = newPoint(el, &id, Vector::From(box.minp.x, box.minp.y, box.minp.z));
223
    p[1] = newPoint(el, &id, Vector::From(box.maxp.x, box.minp.y, box.minp.z));
224
    p[2] = newPoint(el, &id, Vector::From(box.minp.x, box.maxp.y, box.minp.z));
225
    p[3] = newPoint(el, &id, Vector::From(box.maxp.x, box.maxp.y, box.minp.z));
226
    p[4] = newPoint(el, &id, Vector::From(box.minp.x, box.minp.y, box.maxp.z));
227
    p[5] = newPoint(el, &id, Vector::From(box.maxp.x, box.minp.y, box.maxp.z));
228
    p[6] = newPoint(el, &id, Vector::From(box.minp.x, box.maxp.y, box.maxp.z));
229
    p[7] = newPoint(el, &id, Vector::From(box.maxp.x, box.maxp.y, box.maxp.z));
230

231
    newLine(el, &id, p[0], p[1]);
232
    newLine(el, &id, p[0], p[2]);
233
    newLine(el, &id, p[3], p[1]);
234
    newLine(el, &id, p[3], p[2]);
235

236
    newLine(el, &id, p[4], p[5]);
237
    newLine(el, &id, p[4], p[6]);
238
    newLine(el, &id, p[7], p[5]);
239
    newLine(el, &id, p[7], p[6]);
240

241
    newLine(el, &id, p[0], p[4]);
242
    newLine(el, &id, p[1], p[5]);
243
    newLine(el, &id, p[2], p[6]);
244
    newLine(el, &id, p[3], p[7]);
245
    
246
    for(unsigned int i=0; i<verts.size(); i++) {
247
        // create point entities for edge vertexes
248
        if(isEdgeVertex(verts[i])) {
249
           addVertex(el, verts[i].p);
250
        }
251
    }
252

253
    return true;
254
}
255

256
}
257

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

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

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

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