Allow combining extrude, lathe, translate and rotate group as assemblies.

This significantly improves performance e.g. in case of a sketch
containing a multitude of wooden panels, as the meshes can be
merely transformed instead of being joined.
pull/97/head
EvilSpirit 2016-05-03 13:44:10 +06:00 committed by whitequark
parent 5462fc6b3c
commit 6658b1fa2b
10 changed files with 2142 additions and 10 deletions

View File

@ -4,6 +4,10 @@ Changelog
3.0 3.0
--- ---
New sketch features:
* Extrude, lathe, translate and rotate groups can now use the "assembly"
boolean operation, to increase performance.
New export/import features: New export/import features:
* Three.js: allow configuring projection for exported model, and initially * Three.js: allow configuring projection for exported model, and initially
use the current viewport projection. use the current viewport projection.

View File

@ -103,7 +103,7 @@ void SMesh::RemapFaces(Group *g, int remap) {
} }
template<class T> template<class T>
void Group::GenerateForStepAndRepeat(T *steps, T *outs) { void Group::GenerateForStepAndRepeat(T *steps, T *outs, Group::CombineAs forWhat) {
T workA, workB; T workA, workB;
workA = {}; workA = {};
workB = {}; workB = {};
@ -141,6 +141,8 @@ void Group::GenerateForStepAndRepeat(T *steps, T *outs) {
// And tack this transformed copy on to the return. // And tack this transformed copy on to the return.
if(soFar->IsEmpty()) { if(soFar->IsEmpty()) {
scratch->MakeFromCopyOf(&transd); scratch->MakeFromCopyOf(&transd);
} else if (forWhat == CombineAs::ASSEMBLE) {
scratch->MakeFromAssemblyOf(soFar, &transd);
} else { } else {
scratch->MakeFromUnionOf(soFar, &transd); scratch->MakeFromUnionOf(soFar, &transd);
} }
@ -202,8 +204,8 @@ void Group::GenerateShellAndMesh() {
srcg = SK.GetGroup(opA); srcg = SK.GetGroup(opA);
if(!srcg->suppress) { if(!srcg->suppress) {
GenerateForStepAndRepeat<SShell>(&(srcg->thisShell), &thisShell); GenerateForStepAndRepeat<SShell>(&(srcg->thisShell), &thisShell, srcg->meshCombine);
GenerateForStepAndRepeat<SMesh> (&(srcg->thisMesh), &thisMesh); GenerateForStepAndRepeat<SMesh> (&(srcg->thisMesh), &thisMesh, srcg->meshCombine);
} }
} else if(type == Type::EXTRUDE && haveSrc) { } else if(type == Type::EXTRUDE && haveSrc) {
Group *src = SK.GetGroup(opA); Group *src = SK.GetGroup(opA);

View File

@ -268,7 +268,7 @@ public:
bool IsMeshGroup(); bool IsMeshGroup();
void GenerateShellAndMesh(); void GenerateShellAndMesh();
template<class T> void GenerateForStepAndRepeat(T *steps, T *outs); template<class T> void GenerateForStepAndRepeat(T *steps, T *outs, Group::CombineAs forWhat);
template<class T> void GenerateForBoolean(T *a, T *b, T *o, Group::CombineAs how); template<class T> void GenerateForBoolean(T *a, T *b, T *o, Group::CombineAs how);
void GenerateDisplayItems(); void GenerateDisplayItems();

View File

@ -352,12 +352,11 @@ void TextWindow::ShowGroupInfo() {
bool un = (g->meshCombine == Group::CombineAs::UNION); bool un = (g->meshCombine == Group::CombineAs::UNION);
bool diff = (g->meshCombine == Group::CombineAs::DIFFERENCE); bool diff = (g->meshCombine == Group::CombineAs::DIFFERENCE);
bool asy = (g->meshCombine == Group::CombineAs::ASSEMBLE); bool asy = (g->meshCombine == Group::CombineAs::ASSEMBLE);
bool asa = (g->type == Group::Type::LINKED);
Printf(false, " %Ftsolid model as"); Printf(false, " %Ftsolid model as");
Printf(false, "%Ba %f%D%Lc%Fd%s union%E " Printf(false, "%Ba %f%D%Lc%Fd%s union%E "
"%f%D%Lc%Fd%s difference%E " "%f%D%Lc%Fd%s difference%E "
"%f%D%Lc%Fd%s%s%E ", "%f%D%Lc%Fd%s assemble%E ",
&TextWindow::ScreenChangeGroupOption, &TextWindow::ScreenChangeGroupOption,
Group::CombineAs::UNION, Group::CombineAs::UNION,
un ? RADIO_TRUE : RADIO_FALSE, un ? RADIO_TRUE : RADIO_FALSE,
@ -366,8 +365,7 @@ void TextWindow::ShowGroupInfo() {
diff ? RADIO_TRUE : RADIO_FALSE, diff ? RADIO_TRUE : RADIO_FALSE,
&TextWindow::ScreenChangeGroupOption, &TextWindow::ScreenChangeGroupOption,
Group::CombineAs::ASSEMBLE, Group::CombineAs::ASSEMBLE,
asa ? (asy ? RADIO_TRUE : RADIO_FALSE) : " ", (asy ? RADIO_TRUE : RADIO_FALSE));
asa ? " assemble" : "");
if(g->type == Group::Type::EXTRUDE || if(g->type == Group::Type::EXTRUDE ||
g->type == Group::Type::LATHE) g->type == Group::Type::LATHE)

View File

@ -52,7 +52,9 @@ set(testsuite_SOURCES
request/cubic_periodic/test.cpp request/cubic_periodic/test.cpp
request/datum_point/test.cpp request/datum_point/test.cpp
request/line_segment/test.cpp request/line_segment/test.cpp
request/ttf_text/test.cpp) request/ttf_text/test.cpp
group/translate_asy/test.cpp
)
add_executable(solvespace_testsuite add_executable(solvespace_testsuite
${testsuite_SOURCES}) ${testsuite_SOURCES})

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,22 @@
#include "harness.h"
TEST_CASE(normal_roundtrip) {
CHECK_LOAD("normal.slvs");
CHECK_RENDER_ISO("normal.png");
CHECK_SAVE("normal.slvs");
}
TEST_CASE(normal_inters) {
CHECK_LOAD("normal.slvs");
Group *g = SK.GetGroup(SS.GW.activeGroup);
SMesh *m = &g->displayMesh;
SEdgeList el = {};
bool inters, leaks;
SKdNode::From(m)->MakeCertainEdgesInto(&el,
EdgeKind::SELF_INTER, /*coplanarIsInter=*/false, &inters, &leaks);
// The assembly is supposed to interfere.
CHECK_TRUE(inters);
}

View File

@ -260,6 +260,18 @@ bool Test::Helper::CheckRender(const char *file, int line, const char *reference
} }
} }
bool Test::Helper::CheckRenderXY(const char *file, int line, const char *fixture) {
SS.GW.projRight = Vector::From(1, 0, 0);
SS.GW.projUp = Vector::From(0, 1, 0);
return CheckRender(file, line, fixture);
}
bool Test::Helper::CheckRenderIso(const char *file, int line, const char *fixture) {
SS.GW.projRight = Vector::From(0.707, 0.000, -0.707);
SS.GW.projUp = Vector::From(-0.408, 0.816, -0.408);
return CheckRender(file, line, fixture);
}
// Avoid global constructors; using a global static vector instead of a local one // Avoid global constructors; using a global static vector instead of a local one
// breaks MinGW for some obscure reason. // breaks MinGW for some obscure reason.
static std::vector<Test::Case> *testCasesPtr; static std::vector<Test::Case> *testCasesPtr;

View File

@ -25,6 +25,8 @@ public:
bool CheckLoad(const char *file, int line, const char *fixture); bool CheckLoad(const char *file, int line, const char *fixture);
bool CheckSave(const char *file, int line, const char *reference); bool CheckSave(const char *file, int line, const char *reference);
bool CheckRender(const char *file, int line, const char *fixture); bool CheckRender(const char *file, int line, const char *fixture);
bool CheckRenderXY(const char *file, int line, const char *fixture);
bool CheckRenderIso(const char *file, int line, const char *fixture);
}; };
class Case { class Case {
@ -54,4 +56,6 @@ using namespace SolveSpace;
#define CHECK_SAVE(fixture) \ #define CHECK_SAVE(fixture) \
do { if(!helper->CheckSave(__FILE__, __LINE__, fixture)) return; } while(0) do { if(!helper->CheckSave(__FILE__, __LINE__, fixture)) return; } while(0)
#define CHECK_RENDER(reference) \ #define CHECK_RENDER(reference) \
do { if(!helper->CheckRender(__FILE__, __LINE__, reference)) return; } while(0) do { if(!helper->CheckRenderXY(__FILE__, __LINE__, reference)) return; } while(0)
#define CHECK_RENDER_ISO(reference) \
do { if(!helper->CheckRenderIso(__FILE__, __LINE__, reference)) return; } while(0)