From 2afd6103d97b88f8cfd52109de3e7cf06c95b2aa Mon Sep 17 00:00:00 2001 From: phkahler <14852918+phkahler@users.noreply.github.com> Date: Thu, 1 Oct 2020 00:05:33 -0400 Subject: [PATCH] Add STL linking with bounding box and edge verticies. Experimental. --- src/CMakeLists.txt | 1 + src/file.cpp | 4 +- src/importmesh.cpp | 222 +++++++++++++++++++++++++++++++++++++++++++ src/platform/gui.cpp | 1 + src/solvespace.h | 1 + 5 files changed, 228 insertions(+), 1 deletion(-) create mode 100644 src/importmesh.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5ac7b41..ec39939 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -176,6 +176,7 @@ set(solvespace_core_SOURCES groupmesh.cpp importdxf.cpp importidf.cpp + importmesh.cpp mesh.cpp modify.cpp mouse.cpp diff --git a/src/file.cpp b/src/file.cpp index 4e3b50d..c898972 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -710,7 +710,9 @@ bool SolveSpaceUI::LoadEntitiesFromFile(const Platform::Path &filename, EntityLi SMesh *m, SShell *sh) { if(strcmp(filename.Extension().c_str(), "emn")==0) { - return LinkIDF(filename, le, m, sh); + return LinkIDF(filename, le, m, sh); + } else if(strcmp(filename.Extension().c_str(), "stl")==0) { + return LinkStl(filename, le, m, sh); } else { return LoadEntitiesFromSlvs(filename, le, m, sh); } diff --git a/src/importmesh.cpp b/src/importmesh.cpp new file mode 100644 index 0000000..2115175 --- /dev/null +++ b/src/importmesh.cpp @@ -0,0 +1,222 @@ +//----------------------------------------------------------------------------- +// 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 + +#define MIN_POINT_DISTANCE 0.001 + +// we will check for duplicate verticies 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+2; + newPoint(el, id, v); + } +} + +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; + el->Add(&en); + return en.h; +} + +namespace SolveSpace { + +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); + + uint32_t n; + uint32_t color; + + f.read((char*)&n, 4); + dbp("%d triangles", n); + + float x,y,z; + float xn,yn,zn; + + //add the STL origin as an entity + addVertex(el, Vector::From(0.0, 0.0, 0.0)); + + 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); + } + SK.GetGroup(SS.GW.activeGroup)->forceToMesh = true; + dbp("%d verticies", verts.size()); + + BBox box = {}; + box.minp = verts[0].p; + box.maxp = verts[0].p; + + // determine the bounding box for all vertexes + for(unsigned int i=1; in+2; + p[0] = newPoint(el, id++, Vector::From(box.minp.x, box.minp.y, box.minp.z)); + p[1] = newPoint(el, id++, Vector::From(box.maxp.x, box.minp.y, box.minp.z)); + p[2] = newPoint(el, id++, Vector::From(box.minp.x, box.maxp.y, box.minp.z)); + p[3] = newPoint(el, id++, Vector::From(box.maxp.x, box.maxp.y, box.minp.z)); + p[4] = newPoint(el, id++, Vector::From(box.minp.x, box.minp.y, box.maxp.z)); + p[5] = newPoint(el, id++, Vector::From(box.maxp.x, box.minp.y, box.maxp.z)); + p[6] = newPoint(el, id++, Vector::From(box.minp.x, box.maxp.y, box.maxp.z)); + p[7] = newPoint(el, id++, Vector::From(box.maxp.x, box.maxp.y, box.maxp.z)); + + newLine(el, id++, p[0], p[1]); + newLine(el, id++, p[0], p[2]); + newLine(el, id++, p[3], p[1]); + newLine(el, id++, p[3], p[2]); + + newLine(el, id++, p[4], p[5]); + newLine(el, id++, p[4], p[6]); + newLine(el, id++, p[7], p[5]); + newLine(el, id++, p[7], p[6]); + + newLine(el, id++, p[0], p[4]); + newLine(el, id++, p[1], p[5]); + newLine(el, id++, p[2], p[6]); + newLine(el, id++, p[3], p[7]); + + for(unsigned int i=0; i SolveSpaceModelFileFilters = { std::vector SolveSpaceLinkFileFilters = { { CN_("file-type", "SolveSpace models"), { "slvs" } }, { CN_("file-type", "IDF circuit board"), { "emn" } }, + { CN_("file-type", "STL triangle mesh"), { "stl" } }, }; std::vector RasterFileFilters = { diff --git a/src/solvespace.h b/src/solvespace.h index e64a1ab..d4caab2 100644 --- a/src/solvespace.h +++ b/src/solvespace.h @@ -812,6 +812,7 @@ public: void ImportDxf(const Platform::Path &file); void ImportDwg(const Platform::Path &file); bool LinkIDF(const Platform::Path &filename, EntityList *le, SMesh *m, SShell *sh); +bool LinkStl(const Platform::Path &filename, EntityList *le, SMesh *m, SShell *sh); extern SolveSpaceUI SS; extern Sketch SK;