//----------------------------------------------------------------------------- // Triangle mesh file reader. Reads an STL file triangle mesh and creates // a SovleSpace SMesh from it. Supports only Linking, not import. // // Copyright 2020 Paul Kahler. //----------------------------------------------------------------------------- #include "solvespace.h" #include "sketch.h" #include #include #define MIN_POINT_DISTANCE 0.001 namespace SolveSpace { // we will check for duplicate vertices and keep all their normals class vertex { public: Vector p; std::vector normal; }; static bool isEdgeVertex(vertex &v) { unsigned int i,j; bool result = false; for(i=0;i &lv, Vector &p, Vector &n) { unsigned int i; for(i=0; iAdd(&en); return en.h; } // check if a vertex is unique and add it via newPoint if it is. static void addVertex(EntityList *el, Vector v) { if(el->n < 15000) { int id = el->n; newPoint(el, &id, v); } } static hEntity newNormal(EntityList *el, int *id, Quaternion normal, hEntity p) { // normals have parameters, but we don't need them to make a NORMAL_N_COPY from this Entity en = {}; en.type = Entity::Type::NORMAL_N_COPY; en.extraPoints = 0; en.timesApplied = 0; en.group.v = 472; en.actNormal = normal; en.construction = false; en.style.v = Style::NORMALS; // to be visible we need to add a point. // en.point[0] = newPoint(el, id, Vector::From(0,0,0)); en.point[0] = p; en.actVisible = true; en.forceHidden = false; *id = *id+1; en.h.v = *id + en.group.v*65536; el->Add(&en); return en.h; } static hEntity newLine(EntityList *el, int *id, hEntity p0, hEntity p1) { Entity en = {}; en.type = Entity::Type::LINE_SEGMENT; en.point[0] = p0; en.point[1] = p1; en.extraPoints = 0; en.timesApplied = 0; en.group.v = 493; en.construction = true; en.style.v = Style::CONSTRUCTION; en.actVisible = true; en.forceHidden = false; en.h.v = *id + en.group.v*65536; *id = *id + 1; el->Add(&en); return en.h; } bool LinkStl(const Platform::Path &filename, EntityList *el, SMesh *m, SShell *sh) { dbp("\nLink STL triangle mesh."); el->Clear(); std::string data; if(!ReadFile(filename, &data)) { Error("Couldn't read from '%s'", filename.raw.c_str()); return false; } std::stringstream f(data); char str[80] = {}; f.read(str, 80); if(0==memcmp("solid", str, 5)) { // just returning false will trigger the warning that linked file is not present // best solution is to add an importer for text STL. Message(_("Text-formated STL files are not currently supported")); return false; } uint32_t n; uint32_t color; f.read((char*)&n, 4); dbp("%d triangles", n); float x,y,z; float xn,yn,zn; std::vector verts = {}; for(uint32_t i = 0; i> 7) & 0xf8; tr.meta.color.green = (color >> 2) & 0xf8; tr.meta.color.blue = (color << 3); tr.meta.color.alpha = 255; } else { tr.meta.color.red = 90; tr.meta.color.green = 120; tr.meta.color.blue = 140; tr.meta.color.alpha = 255; } m->AddTriangle(&tr); Vector normal = tr.Normal().WithMagnitude(1.0); addUnique(verts, tr.a, normal); addUnique(verts, tr.b, normal); addUnique(verts, tr.c, normal); } dbp("%d vertices", verts.size()); int id = 1; //add the STL origin and normals hEntity origin = newPoint(el, &id, Vector::From(0.0, 0.0, 0.0)); newNormal(el, &id, Quaternion::From(Vector::From(1,0,0),Vector::From(0,1,0)), origin); newNormal(el, &id, Quaternion::From(Vector::From(0,1,0),Vector::From(0,0,1)), origin); newNormal(el, &id, Quaternion::From(Vector::From(0,0,1),Vector::From(1,0,0)), origin); BBox box = {}; box.minp = verts[0].p; box.maxp = verts[0].p; // determine the bounding box for all vertexes for(unsigned int i=1; i