From 41b5c3da59db9f293a31b59c987d48f9689579ca Mon Sep 17 00:00:00 2001 From: Isaac Garzon Date: Tue, 8 Apr 2025 19:28:17 +0300 Subject: [PATCH 1/3] general: rework the way files are included for better maintainability Before this change, every header file was included in `solvespace.h`, inside the `SolveSpace` namespace. This meant that no header file could itself include a header file, unless it was included from `solvespace.h` as well, as otherwise standard library symbols would be injected into the `SolveSpace` namespace and used from there, causing compilation and linking issues. It also meant that no header file could be included on its own, because its dependencies were only satisfied by the inclusion order in `solvespace.h`, which means that the only way to include anything was to just include `solvespace.h`. Change it so that the headers files are properly included at the top of `solvespace.h`, outside the `SolveSpace` namespace. As a consequence of this change, each header file needs its dependencies to be explicitly satisfied, so do that. This also required shuffling the order of a few definitions in some files, as well as extracting some small definitions into their own files, so they could be depended upon without causing a circular inclusion. While at it, remove the `using namespace SolveSpace` declaration from `solvespace.h` in order to avoid polluting the global scope, and add the needed namespace declaration in every place that required it. --- bench/harness.cpp | 7 ++ src/CMakeLists.txt | 5 +- src/bsp.cpp | 22 +++-- src/clipboard.cpp | 3 + src/confscreen.cpp | 3 + src/constraint.cpp | 4 + src/constrainteq.cpp | 3 + src/defs.h | 15 +++ src/describescreen.cpp | 3 + src/draw.cpp | 4 + src/drawconstraint.cpp | 4 + src/drawentity.cpp | 4 + src/dsc.h | 29 ++++-- src/entity.cpp | 4 + src/export.cpp | 4 + src/exportstep.cpp | 3 + src/exportvector.cpp | 3 + src/expr.cpp | 11 ++- src/expr.h | 20 +++- src/file.cpp | 4 + src/generate.cpp | 9 +- src/graphicswin.cpp | 4 + src/group.cpp | 4 + src/groupmesh.cpp | 3 + src/importidf.cpp | 6 +- src/importmesh.cpp | 8 +- src/mesh.cpp | 12 ++- src/modify.cpp | 4 + src/mouse.cpp | 4 + src/param.h | 48 ++++++++++ src/platform/entrycli.cpp | 6 ++ src/platform/gui.h | 7 ++ src/platform/platform.cpp | 13 ++- src/platform/platform.h | 6 +- src/platform/platformbase.cpp | 7 +- src/polygon.cpp | 7 +- src/polygon.h | 14 ++- src/polyline.cpp | 4 + src/render/gl3shader.h | 5 + src/render/render.h | 23 +++++ src/request.cpp | 3 + src/sketch.h | 100 +++++++++----------- src/slvs/jslib.cpp | 5 +- src/slvs/lib.cpp | 125 ++++++++++++------------ src/solvespace.cpp | 10 +- src/solvespace.h | 172 +++------------------------------- src/srf/boolean.cpp | 5 +- src/srf/curve.cpp | 5 +- src/srf/merge.cpp | 5 +- src/srf/ratpoly.cpp | 5 +- src/srf/raycast.cpp | 3 + src/srf/shell.cpp | 6 +- src/srf/surface.cpp | 6 +- src/srf/surface.h | 11 ++- src/srf/surfinter.cpp | 3 + src/srf/triangulate.cpp | 6 +- src/style.cpp | 4 + src/system.cpp | 3 + src/textscreens.cpp | 3 + src/textwin.cpp | 1 + src/toolbar.cpp | 4 + src/ttf.cpp | 4 + src/ttf.h | 18 ++++ src/ui.h | 21 +++++ src/undoredo.cpp | 3 + src/util.cpp | 31 +++--- src/util.h | 105 +++++++++++++++++++++ src/view.cpp | 3 + test/debugtool.cpp | 8 +- test/harness.cpp | 1 + 70 files changed, 678 insertions(+), 350 deletions(-) create mode 100644 src/defs.h create mode 100644 src/param.h create mode 100644 src/util.h diff --git a/bench/harness.cpp b/bench/harness.cpp index 4180558ad..66d53088b 100644 --- a/bench/harness.cpp +++ b/bench/harness.cpp @@ -3,8 +3,15 @@ // // Copyright 2016 whitequark //----------------------------------------------------------------------------- +#include +#include +#include +#include + #include "solvespace.h" +using namespace SolveSpace; + static bool RunBenchmark(std::function setupFn, std::function benchFn, std::function teardownFn, diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 383c6c252..352aa55b4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -63,6 +63,9 @@ endif() # Solver add_library(slvs-solver INTERFACE) target_sources(slvs-solver INTERFACE + dsc.h + expr.h + param.h platform/platform.h solvespace.h @@ -100,8 +103,6 @@ if(ENABLE_GUI OR ENABLE_CLI) solvespace.cpp) add_library(solvespace-core STATIC - dsc.h - expr.h polygon.h sketch.h ui.h diff --git a/src/bsp.cpp b/src/bsp.cpp index bac5ff303..50a3bb2ed 100644 --- a/src/bsp.cpp +++ b/src/bsp.cpp @@ -8,8 +8,10 @@ //----------------------------------------------------------------------------- #include "solvespace.h" -SBsp2 *SBsp2::Alloc() { return (SBsp2 *)AllocTemporary(sizeof(SBsp2)); } -SBsp3 *SBsp3::Alloc() { return (SBsp3 *)AllocTemporary(sizeof(SBsp3)); } +namespace SolveSpace { + +SBsp2 *SBsp2::Alloc() { return (SBsp2 *)Platform::AllocTemporary(sizeof(SBsp2)); } +SBsp3 *SBsp3::Alloc() { return (SBsp3 *)Platform::AllocTemporary(sizeof(SBsp3)); } SBsp3 *SBsp3::FromMesh(const SMesh *m) { SMesh mc = {}; @@ -150,35 +152,35 @@ class BspUtil { Vector *vneg; static BspUtil *Alloc() { - return (BspUtil *)AllocTemporary(sizeof(BspUtil)); + return (BspUtil *)Platform::AllocTemporary(sizeof(BspUtil)); } void AllocOn() { - on = (Vector *)AllocTemporary(sizeof(Vector) * 2); + on = (Vector *)Platform::AllocTemporary(sizeof(Vector) * 2); } void AllocTriangle() { - btri = (STriangle *)AllocTemporary(sizeof(STriangle)); + btri = (STriangle *)Platform::AllocTemporary(sizeof(STriangle)); } void AllocTriangles() { - btri = (STriangle *)AllocTemporary(sizeof(STriangle) * 2); + btri = (STriangle *)Platform::AllocTemporary(sizeof(STriangle) * 2); ctri = &btri[1]; } void AllocQuad() { - vpos = (Vector *)AllocTemporary(sizeof(Vector) * 4); + vpos = (Vector *)Platform::AllocTemporary(sizeof(Vector) * 4); } void AllocClassify(size_t size) { // Allocate a one big piece is faster than a small ones. - isPos = (bool *)AllocTemporary(sizeof(bool) * size * 3); + isPos = (bool *)Platform::AllocTemporary(sizeof(bool) * size * 3); isNeg = &isPos[size]; isOn = &isNeg[size]; } void AllocVertices(size_t size) { - vpos = (Vector *)AllocTemporary(sizeof(Vector) * size * 2); + vpos = (Vector *)Platform::AllocTemporary(sizeof(Vector) * size * 2); vneg = &vpos[size]; } @@ -727,3 +729,5 @@ void SBsp2::InsertTriangle(STriangle *tr, SMesh *m, SBsp3 *bsp3) { return; } + +} // namespace SolveSpace diff --git a/src/clipboard.cpp b/src/clipboard.cpp index 95fd7a7ad..8eea1a8ce 100644 --- a/src/clipboard.cpp +++ b/src/clipboard.cpp @@ -6,6 +6,8 @@ //----------------------------------------------------------------------------- #include "solvespace.h" +namespace SolveSpace { + void SolveSpaceUI::Clipboard::Clear() { c.Clear(); r.Clear(); @@ -522,3 +524,4 @@ void TextWindow::ShowPasteTransformed() { Printf(true, "(or %Fl%Ll%fcancel operation%E)", &ScreenHome); } +} // namespace SolveSpace diff --git a/src/confscreen.cpp b/src/confscreen.cpp index 329465463..7cd86fdd8 100644 --- a/src/confscreen.cpp +++ b/src/confscreen.cpp @@ -9,6 +9,8 @@ #include #endif +namespace SolveSpace { + void TextWindow::ScreenChangeColor(int link, uint32_t v) { SS.TW.ShowEditControlWithColorPicker(13, SS.modelColor[v]); @@ -587,3 +589,4 @@ bool TextWindow::EditControlDoneForConfiguration(const std::string &s) { return true; } +} // namespace SolveSpace diff --git a/src/constraint.cpp b/src/constraint.cpp index 8e0acb99d..3075d31bb 100644 --- a/src/constraint.cpp +++ b/src/constraint.cpp @@ -6,6 +6,8 @@ //----------------------------------------------------------------------------- #include "solvespace.h" +namespace SolveSpace { + std::string Constraint::DescriptionString() const { std::string s; switch(type) { @@ -988,3 +990,5 @@ void Constraint::MenuConstrain(Command id) { } #endif /* ! LIBRARY */ + +} // namespace SolveSpace diff --git a/src/constrainteq.cpp b/src/constrainteq.cpp index 233be8f0c..644e48043 100644 --- a/src/constrainteq.cpp +++ b/src/constrainteq.cpp @@ -7,6 +7,8 @@ //----------------------------------------------------------------------------- #include "solvespace.h" +namespace SolveSpace { + const hConstraint ConstraintBase::NO_CONSTRAINT = { 0 }; bool ConstraintBase::HasLabel() const { @@ -1057,3 +1059,4 @@ void ConstraintBase::GenerateEquations(IdList *l, ssassert(false, "Unexpected constraint ID"); } +} // namespace SolveSpace diff --git a/src/defs.h b/src/defs.h new file mode 100644 index 000000000..94105f951 --- /dev/null +++ b/src/defs.h @@ -0,0 +1,15 @@ +#ifndef SOLVESPACE_DEFS_H +#define SOLVESPACE_DEFS_H + +namespace SolveSpace { + +static constexpr double ANGLE_COS_EPS = 1e-6; +static constexpr double LENGTH_EPS = 1e-6; +static constexpr double VERY_POSITIVE = 1e10; +static constexpr double VERY_NEGATIVE = -1e10; + +static constexpr double PI = 3.1415926535897931; + +} // namespace SolveSpace + +#endif // !SOLVESPACE_DEFS_H diff --git a/src/describescreen.cpp b/src/describescreen.cpp index 06590349a..02a308af8 100644 --- a/src/describescreen.cpp +++ b/src/describescreen.cpp @@ -6,6 +6,8 @@ //----------------------------------------------------------------------------- #include "solvespace.h" +namespace SolveSpace { + void TextWindow::ScreenUnselectAll(int link, uint32_t v) { GraphicsWindow::MenuEdit(Command::UNSELECT_ALL); } @@ -584,3 +586,4 @@ void TextWindow::GoToScreen(Screen screen) { shown.screen = screen; } +} // namespace SolveSpace diff --git a/src/draw.cpp b/src/draw.cpp index acc986e1a..e31b3d8cb 100644 --- a/src/draw.cpp +++ b/src/draw.cpp @@ -7,6 +7,8 @@ //----------------------------------------------------------------------------- #include "solvespace.h" +namespace SolveSpace { + bool GraphicsWindow::Selection::Equals(Selection *b) { if(entity != b->entity) return false; if(constraint != b->constraint) return false; @@ -952,3 +954,5 @@ void GraphicsWindow::Invalidate(bool clearPersistent) { window->Invalidate(); } } + +} // namespace SolveSpace diff --git a/src/drawconstraint.cpp b/src/drawconstraint.cpp index e84c0ce48..bf7d38937 100644 --- a/src/drawconstraint.cpp +++ b/src/drawconstraint.cpp @@ -8,6 +8,8 @@ //----------------------------------------------------------------------------- #include "solvespace.h" +namespace SolveSpace { + std::string Constraint::Label() const { std::string result; if(type == Type::ANGLE) { @@ -1378,3 +1380,5 @@ bool Constraint::HasLabel() const { bool Constraint::ShouldDrawExploded() const { return SK.GetGroup(group)->ShouldDrawExploded(); } + +} // namespace SolveSpace diff --git a/src/drawentity.cpp b/src/drawentity.cpp index 7ac03386d..bf856a14e 100644 --- a/src/drawentity.cpp +++ b/src/drawentity.cpp @@ -7,6 +7,8 @@ //----------------------------------------------------------------------------- #include "solvespace.h" +namespace SolveSpace { + std::string Entity::DescriptionString() const { if(h.isFromRequest()) { Request *r = SK.GetRequest(h.request()); @@ -861,3 +863,5 @@ void Entity::Draw(DrawAs how, Canvas *canvas) { } ssassert(false, "Unexpected entity type"); } + +} // namespace SolveSpace diff --git a/src/dsc.h b/src/dsc.h index d2049ab17..8ddfd5e6e 100644 --- a/src/dsc.h +++ b/src/dsc.h @@ -7,9 +7,18 @@ #ifndef SOLVESPACE_DSC_H #define SOLVESPACE_DSC_H +#include +#include +#include +#include #include #include +#include "defs.h" +#include "util.h" + +namespace SolveSpace { + /// Trait indicating which types are handle types and should get the associated operators. /// Specialize for each handle type and inherit from std::true_type. template @@ -157,9 +166,9 @@ inline double Vector::Element(int i) const { inline bool Vector::Equals(Vector v, double tol) const { // Quick axis-aligned tests before going further const Vector dv = this->Minus(v); - if (fabs(dv.x) > tol) return false; - if (fabs(dv.y) > tol) return false; - if (fabs(dv.z) > tol) return false; + if (std::abs(dv.x) > tol) return false; + if (std::abs(dv.y) > tol) return false; + if (std::abs(dv.z) > tol) return false; return dv.MagSquared() < tol*tol; } @@ -201,13 +210,13 @@ inline Vector Vector::ScaledBy(const double v) const { } inline void Vector::MakeMaxMin(Vector *maxv, Vector *minv) const { - maxv->x = max(maxv->x, x); - maxv->y = max(maxv->y, y); - maxv->z = max(maxv->z, z); + maxv->x = std::max(maxv->x, x); + maxv->y = std::max(maxv->y, y); + maxv->z = std::max(maxv->z, z); - minv->x = min(minv->x, x); - minv->y = min(minv->y, y); - minv->z = min(minv->z, z); + minv->x = std::min(minv->x, x); + minv->y = std::min(minv->y, y); + minv->z = std::min(minv->z, z); } struct VectorHash { @@ -753,4 +762,6 @@ class BBox { bool Contains(const Point2d &p, double r = 0.0) const; }; +} // namespace SolveSpace + #endif diff --git a/src/entity.cpp b/src/entity.cpp index dd42cba65..7b7b7a081 100644 --- a/src/entity.cpp +++ b/src/entity.cpp @@ -7,6 +7,8 @@ //----------------------------------------------------------------------------- #include "solvespace.h" +namespace SolveSpace { + const hEntity EntityBase::FREE_IN_3D = { 0 }; const hEntity EntityBase::NO_ENTITY = { 0 }; @@ -991,3 +993,5 @@ void EntityBase::GenerateEquations(IdList *l) const { break; } } + +} // namespace SolveSpace diff --git a/src/export.cpp b/src/export.cpp index cfa53fcd2..5e6ad0738 100644 --- a/src/export.cpp +++ b/src/export.cpp @@ -9,6 +9,8 @@ #include "solvespace.h" #include "config.h" +namespace SolveSpace { + void SolveSpaceUI::ExportSectionTo(const Platform::Path &filename) { Vector gn = (SS.GW.projRight).Cross(SS.GW.projUp); gn = gn.WithMagnitude(1); @@ -1266,3 +1268,5 @@ void SolveSpaceUI::ExportAsPngTo(const Platform::Path &filename) { // The rest of the work is done in the next redraw. GW.Invalidate(); } + +} // namespace SolveSpace diff --git a/src/exportstep.cpp b/src/exportstep.cpp index 62bf8099e..6bfd974f9 100644 --- a/src/exportstep.cpp +++ b/src/exportstep.cpp @@ -5,6 +5,8 @@ //----------------------------------------------------------------------------- #include "solvespace.h" +namespace SolveSpace { + #define FP "%.5f" // Floating Point coordinate precision. Since LENGTH_EPS = 1e-6 output 5 decimal places thus rounding out errors e.g. 0.999999mm #define CARTESIAN_POINT_FORMAT "#%d=CARTESIAN_POINT('',(" FP "," FP "," FP "));\n" const double PRECISION = 2*LENGTH_EPS; @@ -716,3 +718,4 @@ void StepFileWriter::WriteWireframe() { curves.Clear(); } +} // namespace SolveSpace diff --git a/src/exportvector.cpp b/src/exportvector.cpp index e9dad60f0..175399730 100644 --- a/src/exportvector.cpp +++ b/src/exportvector.cpp @@ -6,6 +6,8 @@ #include #include "solvespace.h" +namespace SolveSpace { + //----------------------------------------------------------------------------- // Routines for DXF export //----------------------------------------------------------------------------- @@ -1355,3 +1357,4 @@ void Step2dFileWriter::FinishAndCloseFile() { fclose(f); } +} // namespace SolveSpace diff --git a/src/expr.cpp b/src/expr.cpp index 35eb36e80..6b077fa58 100644 --- a/src/expr.cpp +++ b/src/expr.cpp @@ -6,9 +6,14 @@ // // Copyright 2008-2013 Jonathan Westhues. //----------------------------------------------------------------------------- -#include #include "solvespace.h" +namespace SolveSpace { + +static inline Expr *AllocExpr() { + return (Expr *)Platform::AllocTemporary(sizeof(Expr)); +} + ExprVector ExprVector::From(Expr *x, Expr *y, Expr *z) { ExprVector r = { x, y, z}; return r; @@ -671,7 +676,7 @@ ExprParser::Token ExprParser::Token::From(TokenType type, Expr *expr) { ExprParser::Token ExprParser::Token::From(TokenType type, Expr::Op op) { Token t; t.type = type; - t.expr = Expr::AllocExpr(); + t.expr = AllocExpr(); t.expr->op = op; return t; } @@ -954,3 +959,5 @@ Expr *Expr::From(const std::string &input, bool popUpError) { } return e; } + +} // namespace SolveSpace diff --git a/src/expr.h b/src/expr.h index 8a05cb841..eb0191722 100644 --- a/src/expr.h +++ b/src/expr.h @@ -7,6 +7,16 @@ #ifndef SOLVESPACE_EXPR_H #define SOLVESPACE_EXPR_H +#include +#include +#include +#include + +#include "dsc.h" +#include "param.h" + +namespace SolveSpace { + using SubstitutionMap = std::unordered_map>; class Expr { @@ -50,9 +60,6 @@ class Expr { Expr() = default; Expr(double val) : op(Op::CONSTANT) { v = val; } - static inline Expr *AllocExpr() - { return (Expr *)AllocTemporary(sizeof(Expr)); } - static Expr *From(hParam p); static Expr *From(double v); @@ -96,8 +103,8 @@ class Expr { // Make a copy, with the parameters (usually referenced by hParam) // resolved to pointers to the actual value. This speeds things up // considerably. - Expr *DeepCopyWithParamsAsPointers(IdList *firstTry, - IdList *thenTry, + Expr *DeepCopyWithParamsAsPointers(ParamList *firstTry, + ParamList *thenTry, bool foldConstants = false) const; static Expr *Parse(const std::string &input, std::string *error); @@ -141,4 +148,7 @@ class ExprQuaternion { Expr *Magnitude() const; }; + +} // namespace SolveSpace + #endif diff --git a/src/file.cpp b/src/file.cpp index 8bc6e97a3..86da16b87 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -5,6 +5,8 @@ //----------------------------------------------------------------------------- #include "solvespace.h" +namespace SolveSpace { + #define VERSION_STRING "\261\262\263" "SolveSpaceREVa" static int StrStartsWith(const char *str, const char *start) { @@ -1024,3 +1026,5 @@ bool SolveSpaceUI::ReloadLinkedImage(const Platform::Path &saveFile, SS.images[*filename] = pixmap; return true; } + +} // namespace SolveSpace diff --git a/src/generate.cpp b/src/generate.cpp index a0cae68bb..4d38a5204 100644 --- a/src/generate.cpp +++ b/src/generate.cpp @@ -8,6 +8,8 @@ //----------------------------------------------------------------------------- #include "solvespace.h" +namespace SolveSpace { + void SolveSpaceUI::MarkGroupDirtyByEntity(hEntity he) { Entity *e = SK.GetEntity(he); MarkGroupDirty(e->group); @@ -371,7 +373,7 @@ void SolveSpaceUI::GenerateAll(Generate type, bool andFindFree, bool genForBBox) } } - FreeAllTemporary(); + Platform::FreeAllTemporary(); allConsistent = true; SS.GW.persistentDirty = true; SS.centerOfMass.dirty = true; @@ -564,7 +566,7 @@ void SolveSpaceUI::SolveGroup(hGroup hg, bool andFindFree) { g->dofCheckOk = true; } g->solved.how = how; - FreeAllTemporary(); + Platform::FreeAllTemporary(); } SolveResult SolveSpaceUI::TestRankForGroup(hGroup hg, int *rank) { @@ -574,7 +576,7 @@ SolveResult SolveSpaceUI::TestRankForGroup(hGroup hg, int *rank) { if(g->suppressDofCalculation || g->allowRedundant) return SolveResult::OKAY; WriteEqSystemForGroup(hg); SolveResult result = sys.SolveRank(g, rank); - FreeAllTemporary(); + Platform::FreeAllTemporary(); return result; } @@ -589,3 +591,4 @@ bool SolveSpaceUI::ActiveGroupsOkay() { return true; } +} // namespace SolveSpace diff --git a/src/graphicswin.cpp b/src/graphicswin.cpp index b284cf454..98ceb739a 100644 --- a/src/graphicswin.cpp +++ b/src/graphicswin.cpp @@ -6,6 +6,8 @@ //----------------------------------------------------------------------------- #include "solvespace.h" +namespace SolveSpace { + typedef void MenuHandler(Command id); using MenuKind = Platform::MenuItem::Indicator; struct MenuEntry { @@ -1475,3 +1477,5 @@ bool GraphicsWindow::SuggestLineConstraint(hRequest request, Constraint::Type *t } return false; } + +} // namespace SolveSpace diff --git a/src/group.cpp b/src/group.cpp index b0564c7f0..4e41ffc30 100644 --- a/src/group.cpp +++ b/src/group.cpp @@ -8,6 +8,8 @@ //----------------------------------------------------------------------------- #include "solvespace.h" +namespace SolveSpace { + const hParam Param::NO_PARAM = { 0 }; #define NO_PARAM (Param::NO_PARAM) @@ -1215,3 +1217,5 @@ void Group::CopyEntity(EntityList *el, bool Group::ShouldDrawExploded() const { return SS.explode && h == SS.GW.activeGroup && type == Type::DRAWING_WORKPLANE && !SS.exportMode; } + +} // namespace SolveSpace diff --git a/src/groupmesh.cpp b/src/groupmesh.cpp index b539702eb..785817b3f 100644 --- a/src/groupmesh.cpp +++ b/src/groupmesh.cpp @@ -7,6 +7,8 @@ //----------------------------------------------------------------------------- #include "solvespace.h" +namespace SolveSpace { + void Group::AssembleLoops(bool *allClosed, bool *allCoplanar, bool *allNonZeroLen) @@ -798,3 +800,4 @@ void Group::DrawContourAreaLabels(Canvas *canvas) { } } +} // namespace SolveSpace diff --git a/src/importidf.cpp b/src/importidf.cpp index 239fd7426..12f0963e2 100644 --- a/src/importidf.cpp +++ b/src/importidf.cpp @@ -8,6 +8,8 @@ #include "solvespace.h" #include "sketch.h" +namespace SolveSpace { + // Split a string into substrings separated by spaces. // Allow quotes to enclose spaces within a string static std::vector splitString(const std::string line) { @@ -300,8 +302,6 @@ static void MakeBeziersForArcs(SBezierList *sbl, Vector center, Vector pa, Vecto } } -namespace SolveSpace { - // Here we read the important section of an IDF file. SolveSpace Entities are directly created by // the functions above, which is only OK because of the way linking works. For example points do // not have handles for solver parameters (coordinates), they only have their actPoint values @@ -533,4 +533,4 @@ bool LinkIDF(const Platform::Path &filename, EntityList *el, SMesh *m, SShell *s return true; } -} +} // namespace SolveSpace diff --git a/src/importmesh.cpp b/src/importmesh.cpp index f06a8f1b9..fc1a4ff81 100644 --- a/src/importmesh.cpp +++ b/src/importmesh.cpp @@ -6,10 +6,13 @@ //----------------------------------------------------------------------------- #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: @@ -114,8 +117,6 @@ static hEntity newLine(EntityList *el, int *id, hEntity p0, hEntity p1) { return en.h; } -namespace SolveSpace { - bool LinkStl(const Platform::Path &filename, EntityList *el, SMesh *m, SShell *sh) { dbp("\nLink STL triangle mesh."); el->Clear(); @@ -253,4 +254,5 @@ bool LinkStl(const Platform::Path &filename, EntityList *el, SMesh *m, SShell *s return true; } -} +} // namespace SolveSpace + diff --git a/src/mesh.cpp b/src/mesh.cpp index 1280a11a4..d0e866df9 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -8,6 +8,8 @@ #include +namespace SolveSpace { + void SMesh::Clear() { l.Clear(); } @@ -371,13 +373,13 @@ Vector SMesh::GetCenterOfMass() const { } STriangleLl *STriangleLl::Alloc() - { return (STriangleLl *)AllocTemporary(sizeof(STriangleLl)); } + { return (STriangleLl *)Platform::AllocTemporary(sizeof(STriangleLl)); } SKdNode *SKdNode::Alloc() - { return (SKdNode *)AllocTemporary(sizeof(SKdNode)); } + { return (SKdNode *)Platform::AllocTemporary(sizeof(SKdNode)); } SKdNode *SKdNode::From(SMesh *m) { int i; - STriangle *tra = (STriangle *)AllocTemporary((m->l.n) * sizeof(*tra)); + STriangle *tra = (STriangle *)Platform::AllocTemporary((m->l.n) * sizeof(*tra)); for(i = 0; i < m->l.n; i++) { tra[i] = m->l[i]; @@ -663,7 +665,7 @@ void SKdNode::SnapToMesh(SMesh *m) { SnapToVertex(v, &extra); for(k = 0; k < extra.l.n; k++) { - STriangle *tra = (STriangle *)AllocTemporary(sizeof(*tra)); + STriangle *tra = (STriangle *)Platform::AllocTemporary(sizeof(*tra)); *tra = extra.l[k]; AddTriangle(tra); } @@ -1215,3 +1217,5 @@ double SMesh::CalculateSurfaceArea(const std::vector &faces) const { } return area; } + +} // namespace SolveSpace diff --git a/src/modify.cpp b/src/modify.cpp index 2e51519ce..60079df8c 100644 --- a/src/modify.cpp +++ b/src/modify.cpp @@ -7,6 +7,8 @@ //----------------------------------------------------------------------------- #include "solvespace.h" +namespace SolveSpace { + //----------------------------------------------------------------------------- // Replace constraints on oldpt with the same constraints on newpt. // Useful when splitting, tangent arcing, or removing bezier points. @@ -745,3 +747,5 @@ void GraphicsWindow::SplitLinesOrCurves() { // All done, clean up and regenerate. ClearSelection(); } + +} // namespace SolveSpace diff --git a/src/mouse.cpp b/src/mouse.cpp index 96726ad1d..7ff0e5292 100644 --- a/src/mouse.cpp +++ b/src/mouse.cpp @@ -5,6 +5,8 @@ //----------------------------------------------------------------------------- #include "solvespace.h" +namespace SolveSpace { + void GraphicsWindow::UpdateDraggedPoint(hEntity hp, double mx, double my) { Entity *p = SK.GetEntity(hp); Vector pos = p->PointGetNum(); @@ -1572,3 +1574,5 @@ void GraphicsWindow::SixDofEvent(Platform::SixDofEvent event) { havePainted = false; Invalidate(); } + +} // namespace SolveSpace diff --git a/src/param.h b/src/param.h new file mode 100644 index 000000000..69b811cbd --- /dev/null +++ b/src/param.h @@ -0,0 +1,48 @@ +#ifndef SOLVESPACE_PARAM_H +#define SOLVESPACE_PARAM_H + +#include +#include + +#include "dsc.h" + +namespace SolveSpace { + +class hRequest; + +class hParam { +public: + // bits 15: 0 -- param index + // 31:16 -- request index + uint32_t v; + + inline hRequest request() const; +}; + +template<> +struct IsHandleOracle : std::true_type {}; + +class Param { +public: + int tag; + hParam h; + + double val; + bool known; + bool free; + + // Used only in the solver + Param *substd; + + static const hParam NO_PARAM; + + void Clear() {} +}; + +using ParamList = IdList; + +using ParamSet = std::unordered_set>; + +} // namespace SolveSpace + +#endif // !SOLVESPACE_PARAM_H diff --git a/src/platform/entrycli.cpp b/src/platform/entrycli.cpp index 70b6919b0..6284e12a7 100644 --- a/src/platform/entrycli.cpp +++ b/src/platform/entrycli.cpp @@ -3,9 +3,15 @@ // // Copyright 2016 whitequark //----------------------------------------------------------------------------- + +#include +#include + #include "solvespace.h" #include "config.h" +using namespace SolveSpace; + static void ShowUsage(const std::string &cmd) { fprintf(stderr, "Usage: %s [filename...]", cmd.c_str()); //-----------------------------------------------------------------------------> 80 col */ diff --git a/src/platform/gui.h b/src/platform/gui.h index 4f3d1316b..46dcc182c 100644 --- a/src/platform/gui.h +++ b/src/platform/gui.h @@ -7,6 +7,13 @@ #ifndef SOLVESPACE_GUI_H #define SOLVESPACE_GUI_H +#include +#include +#include +#include + +#include "platform.h" + namespace SolveSpace { class RgbaColor; diff --git a/src/platform/platform.cpp b/src/platform/platform.cpp index 45ac5b2d8..a57ff5ec3 100644 --- a/src/platform/platform.cpp +++ b/src/platform/platform.cpp @@ -9,8 +9,13 @@ # include # include #endif -#include "solvespace.h" -#include "config.h" + +#include +#include +#include + +#include + #if defined(WIN32) // Conversely, include Microsoft headers after solvespace.h to avoid clashes. # include @@ -20,6 +25,10 @@ # include #endif +#include "platform.h" +#include "util.h" +#include "config.h" + namespace SolveSpace { namespace Platform { diff --git a/src/platform/platform.h b/src/platform/platform.h index 1ad5e1758..771a4cf0b 100644 --- a/src/platform/platform.h +++ b/src/platform/platform.h @@ -7,6 +7,9 @@ #ifndef SOLVESPACE_PLATFORM_H #define SOLVESPACE_PLATFORM_H +#include +#include + namespace SolveSpace { namespace Platform { @@ -74,9 +77,6 @@ const void *LoadResource(const std::string &name, size_t *size); // Startup and command-line argument handling. std::vector InitCli(int argc, char **argv); -// Debug print function. -void DebugPrint(const char *fmt, ...); - // Temporary arena functions. void *AllocTemporary(size_t size); void FreeAllTemporary(); diff --git a/src/platform/platformbase.cpp b/src/platform/platformbase.cpp index 0268a170b..6e3bb8aa0 100644 --- a/src/platform/platformbase.cpp +++ b/src/platform/platformbase.cpp @@ -1,10 +1,15 @@ -#include "solvespace.h" +#include +#include + #include #if defined(WIN32) # include #endif // defined(WIN32) +#include "util.h" +#include "platform.h" + namespace SolveSpace { namespace Platform { diff --git a/src/polygon.cpp b/src/polygon.cpp index f325fd9b4..211f6a690 100644 --- a/src/polygon.cpp +++ b/src/polygon.cpp @@ -5,6 +5,8 @@ //----------------------------------------------------------------------------- #include "solvespace.h" +namespace SolveSpace { + Vector STriangle::Normal() const { Vector ab = b.Minus(a), bc = c.Minus(b); return ab.Cross(bc); @@ -353,12 +355,12 @@ void SEdgeList::CullExtraneousEdges(bool both) { // that would naively be O(n). //----------------------------------------------------------------------------- SKdNodeEdges *SKdNodeEdges::Alloc() { - SKdNodeEdges *ne = (SKdNodeEdges *)AllocTemporary(sizeof(SKdNodeEdges)); + SKdNodeEdges *ne = (SKdNodeEdges *)Platform::AllocTemporary(sizeof(SKdNodeEdges)); *ne = {}; return ne; } SEdgeLl *SEdgeLl::Alloc() { - SEdgeLl *sell = (SEdgeLl *)AllocTemporary(sizeof(SEdgeLl)); + SEdgeLl *sell = (SEdgeLl *)Platform::AllocTemporary(sizeof(SEdgeLl)); *sell = {}; return sell; } @@ -919,3 +921,4 @@ void SContour::OffsetInto(SContour *dest, double r) const { } } +} // namespace SolveSpace diff --git a/src/polygon.h b/src/polygon.h index cf0f32283..4668421b2 100644 --- a/src/polygon.h +++ b/src/polygon.h @@ -8,10 +8,21 @@ #ifndef SOLVESPACE_POLYGON_H #define SOLVESPACE_POLYGON_H +#include +#include +#include +#include + +#include "dsc.h" + +namespace SolveSpace { + +class Group; class SPointList; class SPolygon; class SContour; class SMesh; +class SSurface; class SBsp3; class SOutlineList; @@ -416,5 +427,6 @@ class PolylineBuilder { void GenerateOutlines(SOutlineList *sol); }; -#endif +} // namespace SolveSpace +#endif diff --git a/src/polyline.cpp b/src/polyline.cpp index 64aef4e98..0b7e2e955 100644 --- a/src/polyline.cpp +++ b/src/polyline.cpp @@ -6,6 +6,8 @@ //----------------------------------------------------------------------------- #include "solvespace.h" +namespace SolveSpace { + bool PolylineBuilder::Vertex::GetNext(uint32_t kind, Vertex **next, Edge **nextEdge) { auto it = std::find_if(edges.begin(), edges.end(), [&](const Edge *e) { return e->tag == 0 && e->kind == kind; @@ -241,3 +243,5 @@ void PolylineBuilder::GenerateOutlines(SOutlineList *sol) { Generate(startFunc, nextFunc, aloneFunc); } + +} // namespace SolveSpace diff --git a/src/render/gl3shader.h b/src/render/gl3shader.h index e13929dd4..19f73128b 100644 --- a/src/render/gl3shader.h +++ b/src/render/gl3shader.h @@ -20,6 +20,11 @@ # include #endif +#include +#include + +#include "sketch.h" + #if !defined(HAVE_GLES) // glDepthRange is in GL1+ but not GLES2, glDepthRangef is in GL4.1+ and GLES2. // Consistency! diff --git a/src/render/render.h b/src/render/render.h index 9601a5e7d..6a4ef62a8 100644 --- a/src/render/render.h +++ b/src/render/render.h @@ -7,10 +7,28 @@ #ifndef SOLVESPACE_RENDER_H #define SOLVESPACE_RENDER_H +#include +#include +#include +#include +#include +#include + +#include "dsc.h" +#include "resource.h" +#include "srf/surface.h" + +typedef struct _cairo cairo_t; +typedef struct _cairo_surface cairo_surface_t; + +namespace SolveSpace { + //----------------------------------------------------------------------------- // Interfaces common for all renderers //----------------------------------------------------------------------------- +class Pixmap; + enum class StipplePattern : uint32_t; // A mapping from 3d sketch coordinates to 2d screen coordinates, using @@ -265,6 +283,9 @@ class ObjectPicker : public Canvas { bool Pick(const std::function &drawFn); }; +template +using handle_map = std::map; + // A canvas that renders onto a 2d surface, performing z-index sorting, occlusion testing, etc, // on the CPU. class SurfaceRenderer : public ViewportCanvas { @@ -382,4 +403,6 @@ class CairoPixmapRenderer final : public CairoRenderer { std::shared_ptr CreateRenderer(); +} // namespace SolveSpace + #endif diff --git a/src/request.cpp b/src/request.cpp index 19676982f..cb5e3f3bb 100644 --- a/src/request.cpp +++ b/src/request.cpp @@ -8,6 +8,8 @@ //----------------------------------------------------------------------------- #include "solvespace.h" +namespace SolveSpace { + const hRequest Request::HREQUEST_REFERENCE_XY = { 1 }; const hRequest Request::HREQUEST_REFERENCE_YZ = { 2 }; const hRequest Request::HREQUEST_REFERENCE_ZX = { 3 }; @@ -245,3 +247,4 @@ hParam Request::AddParam(ParamList *param, hParam hp) { return hp; } +} // namespace SolveSpace diff --git a/src/sketch.h b/src/sketch.h index 554743452..324d56644 100644 --- a/src/sketch.h +++ b/src/sketch.h @@ -8,18 +8,29 @@ #ifndef SOLVESPACE_SKETCH_H #define SOLVESPACE_SKETCH_H -class hGroup; -class hRequest; -class hEntity; -class hParam; -class hStyle; +#include +#include +#include +#include +#include + +#include "dsc.h" +#include "param.h" +#include "polygon.h" +#include "platform/platform.h" +#include "platform/gui.h" +#include "srf/surface.h" +#include "render/render.h" + +namespace SolveSpace { + class hConstraint; -class hEquation; -class Entity; -class Param; -class Equation; -class Style; +class Expr; +class ExprVector; +class ExprQuaternion; + +enum class SolveResult : uint32_t; enum class PolyError : uint32_t { GOOD = 0, @@ -50,6 +61,17 @@ enum class Command : uint32_t; // All of the hWhatever handles are a 32-bit ID, that is used to represent // some data structure in the sketch. +class hEquation { +public: + uint32_t v; + + inline bool isFromConstraint() const; + inline hConstraint constraint() const; +}; + +template<> +struct IsHandleOracle : std::true_type {}; + class hGroup { public: // bits 15: 0 -- group index @@ -92,17 +114,15 @@ class hEntity { template<> struct IsHandleOracle : std::true_type {}; -class hParam { +class Equation { public: - // bits 15: 0 -- param index - // 31:16 -- request index - uint32_t v; + int tag; + hEquation h; - inline hRequest request() const; -}; + Expr *e; -template<> -struct IsHandleOracle : std::true_type {}; + void Clear() {} +}; class hStyle { public: @@ -112,6 +132,9 @@ class hStyle { template<> struct IsHandleOracle : std::true_type {}; +class Entity; +using EntityList = IdList; + struct EntityId { uint32_t v; // entity ID, starting from 0 }; @@ -578,7 +601,7 @@ class Entity : public EntityBase { bool IsStylable() const; bool IsVisible() const; bool CanBeDragged() const; - + enum class DrawAs { DEFAULT, OVERLAY, HIDDEN, HOVERED, SELECTED }; void Draw(DrawAs how, Canvas *canvas); void GetReferencePoints(std::vector *refs); @@ -615,21 +638,6 @@ class EntReqTable { static Request::Type GetRequestForEntity(EntityBase::Type ent); }; -class Param { -public: - int tag; - hParam h; - - double val; - bool known; - bool free; - - static const hParam NO_PARAM; - - void Clear() {} -}; - - class hConstraint { public: uint32_t v; @@ -813,28 +821,6 @@ class Constraint : public ConstraintBase { Entity *p2); }; -class hEquation { -public: - uint32_t v; - - inline bool isFromConstraint() const; - inline hConstraint constraint() const; -}; - -template<> -struct IsHandleOracle : std::true_type {}; - -class Equation { -public: - int tag; - hEquation h; - - Expr *e; - - void Clear() {} -}; - - class Style { public: int tag; @@ -1011,4 +997,6 @@ class ClipboardRequest { hRequest newReq; }; +} // namespace SolveSpace + #endif diff --git a/src/slvs/jslib.cpp b/src/slvs/jslib.cpp index 7e48c6c3b..82074ffc5 100644 --- a/src/slvs/jslib.cpp +++ b/src/slvs/jslib.cpp @@ -1,7 +1,10 @@ -#include "solvespace.h" #include "slvs.h" #include +#include "solvespace.h" + +using namespace SolveSpace; + struct JsSolveResult { int result; int dof; diff --git a/src/slvs/lib.cpp b/src/slvs/lib.cpp index 304ceb9cd..0468548bb 100644 --- a/src/slvs/lib.cpp +++ b/src/slvs/lib.cpp @@ -9,11 +9,11 @@ #include #include -Sketch SolveSpace::SK = {}; -static System SYS; -static ParamSet dragged; +namespace SolveSpace { -void SolveSpace::Platform::FatalError(const std::string &message) { +Sketch SK = {}; + +void Platform::FatalError(const std::string &message) { fprintf(stderr, "%s", message.c_str()); abort(); } @@ -22,6 +22,13 @@ void Group::GenerateEquations(IdList *) { // Nothing to do for now. } +} // namespace SolveSpace + +using namespace SolveSpace; + +static System SYS; +static ParamSet dragged; + extern "C" { static ConstraintBase::Type Slvs_CTypeToConstraintBaseType(int type) { @@ -64,7 +71,7 @@ case SLVS_C_EQUAL_RADIUS: return ConstraintBase::Type::EQUAL_RADIUS; case SLVS_C_PROJ_PT_DISTANCE: return ConstraintBase::Type::PROJ_PT_DISTANCE; case SLVS_C_WHERE_DRAGGED: return ConstraintBase::Type::WHERE_DRAGGED; case SLVS_C_CURVE_CURVE_TANGENT: return ConstraintBase::Type::CURVE_CURVE_TANGENT; -default: SolveSpace::Platform::FatalError("bad constraint type " + std::to_string(type)); +default: Platform::FatalError("bad constraint type " + std::to_string(type)); } } @@ -80,7 +87,7 @@ case SLVS_E_LINE_SEGMENT: return EntityBase::Type::LINE_SEGMENT; case SLVS_E_CUBIC: return EntityBase::Type::CUBIC; case SLVS_E_CIRCLE: return EntityBase::Type::CIRCLE; case SLVS_E_ARC_OF_CIRCLE: return EntityBase::Type::ARC_OF_CIRCLE; -default: SolveSpace::Platform::FatalError("bad entity type " + std::to_string(type)); +default: Platform::FatalError("bad entity type " + std::to_string(type)); } } @@ -264,7 +271,7 @@ Slvs_Entity Slvs_AddPoint3D(uint32_t grouph, double x, double y, double z) { Slvs_Entity Slvs_AddNormal2D(uint32_t grouph, Slvs_Entity workplane) { if(!Slvs_IsWorkplane(workplane)) { - SolveSpace::Platform::FatalError("workplane argument is not a workplane"); + Platform::FatalError("workplane argument is not a workplane"); } EntityBase e = {}; e.type = EntityBase::Type::NORMAL_IN_2D; @@ -309,7 +316,7 @@ Slvs_Entity Slvs_AddNormal3D(uint32_t grouph, double qw, double qx, double qy, d Slvs_Entity Slvs_AddDistance(uint32_t grouph, double value, Slvs_Entity workplane) { if(!Slvs_IsWorkplane(workplane)) { - SolveSpace::Platform::FatalError("workplane argument is not a workplane"); + Platform::FatalError("workplane argument is not a workplane"); } Slvs_hParam valueph = Slvs_AddParam(value); EntityBase e = {}; @@ -330,11 +337,11 @@ Slvs_Entity Slvs_AddDistance(uint32_t grouph, double value, Slvs_Entity workplan Slvs_Entity Slvs_AddLine2D(uint32_t grouph, Slvs_Entity ptA, Slvs_Entity ptB, Slvs_Entity workplane) { if(!Slvs_IsWorkplane(workplane)) { - SolveSpace::Platform::FatalError("workplane argument is not a workplane"); + Platform::FatalError("workplane argument is not a workplane"); } else if(!Slvs_IsPoint2D(ptA)) { - SolveSpace::Platform::FatalError("ptA argument is not a 2d point"); + Platform::FatalError("ptA argument is not a 2d point"); } else if(!Slvs_IsPoint2D(ptB)) { - SolveSpace::Platform::FatalError("ptB argument is not a 2d point"); + Platform::FatalError("ptB argument is not a 2d point"); } EntityBase e = {}; e.type = EntityBase::Type::LINE_SEGMENT; @@ -356,9 +363,9 @@ Slvs_Entity Slvs_AddLine2D(uint32_t grouph, Slvs_Entity ptA, Slvs_Entity ptB, Sl Slvs_Entity Slvs_AddLine3D(uint32_t grouph, Slvs_Entity ptA, Slvs_Entity ptB) { if(!Slvs_IsPoint3D(ptA)) { - SolveSpace::Platform::FatalError("ptA argument is not a 3d point"); + Platform::FatalError("ptA argument is not a 3d point"); } else if(!Slvs_IsPoint3D(ptB)) { - SolveSpace::Platform::FatalError("ptB argument is not a 3d point"); + Platform::FatalError("ptB argument is not a 3d point"); } EntityBase e = {}; e.type = EntityBase::Type::LINE_SEGMENT; @@ -380,15 +387,15 @@ Slvs_Entity Slvs_AddLine3D(uint32_t grouph, Slvs_Entity ptA, Slvs_Entity ptB) { Slvs_Entity Slvs_AddCubic(uint32_t grouph, Slvs_Entity ptA, Slvs_Entity ptB, Slvs_Entity ptC, Slvs_Entity ptD, Slvs_Entity workplane) { if(!Slvs_IsWorkplane(workplane)) { - SolveSpace::Platform::FatalError("workplane argument is not a workplane"); + Platform::FatalError("workplane argument is not a workplane"); } else if(!Slvs_IsPoint2D(ptA)) { - SolveSpace::Platform::FatalError("ptA argument is not a 2d point"); + Platform::FatalError("ptA argument is not a 2d point"); } else if(!Slvs_IsPoint2D(ptB)) { - SolveSpace::Platform::FatalError("ptB argument is not a 2d point"); + Platform::FatalError("ptB argument is not a 2d point"); } else if(!Slvs_IsPoint2D(ptC)) { - SolveSpace::Platform::FatalError("ptC argument is not a 2d point"); + Platform::FatalError("ptC argument is not a 2d point"); } else if(!Slvs_IsPoint2D(ptD)) { - SolveSpace::Platform::FatalError("ptD argument is not a 2d point"); + Platform::FatalError("ptD argument is not a 2d point"); } EntityBase e = {}; e.type = EntityBase::Type::CUBIC; @@ -416,15 +423,15 @@ Slvs_Entity Slvs_AddCubic(uint32_t grouph, Slvs_Entity ptA, Slvs_Entity ptB, Slv Slvs_Entity Slvs_AddArc(uint32_t grouph, Slvs_Entity normal, Slvs_Entity center, Slvs_Entity start, Slvs_Entity end, Slvs_Entity workplane) { if(!Slvs_IsWorkplane(workplane)) { - SolveSpace::Platform::FatalError("workplane argument is not a workplane"); + Platform::FatalError("workplane argument is not a workplane"); } else if(!Slvs_IsNormal3D(normal)) { - SolveSpace::Platform::FatalError("normal argument is not a 3d normal"); + Platform::FatalError("normal argument is not a 3d normal"); } else if(!Slvs_IsPoint2D(center)) { - SolveSpace::Platform::FatalError("center argument is not a 2d point"); + Platform::FatalError("center argument is not a 2d point"); } else if(!Slvs_IsPoint2D(start)) { - SolveSpace::Platform::FatalError("start argument is not a 2d point"); + Platform::FatalError("start argument is not a 2d point"); } else if(!Slvs_IsPoint2D(end)) { - SolveSpace::Platform::FatalError("end argument is not a 2d point"); + Platform::FatalError("end argument is not a 2d point"); } EntityBase e = {}; e.type = EntityBase::Type::ARC_OF_CIRCLE; @@ -451,13 +458,13 @@ Slvs_Entity Slvs_AddArc(uint32_t grouph, Slvs_Entity normal, Slvs_Entity center, Slvs_Entity Slvs_AddCircle(uint32_t grouph, Slvs_Entity normal, Slvs_Entity center, Slvs_Entity radius, Slvs_Entity workplane) { if(!Slvs_IsWorkplane(workplane)) { - SolveSpace::Platform::FatalError("workplane argument is not a workplane"); + Platform::FatalError("workplane argument is not a workplane"); } else if(!Slvs_IsNormal3D(normal)) { - SolveSpace::Platform::FatalError("normal argument is not a 3d normal"); + Platform::FatalError("normal argument is not a 3d normal"); } else if(!Slvs_IsPoint2D(center)) { - SolveSpace::Platform::FatalError("center argument is not a 2d point"); + Platform::FatalError("center argument is not a 2d point"); } else if(!Slvs_IsDistance(radius)) { - SolveSpace::Platform::FatalError("radius argument is not a distance"); + Platform::FatalError("radius argument is not a distance"); } EntityBase e = {}; e.type = EntityBase::Type::CIRCLE; @@ -555,7 +562,7 @@ Slvs_Constraint Slvs_Coincident(uint32_t grouph, Slvs_Entity entityA, Slvs_Entit } else if(Slvs_IsPoint(entityA) && (Slvs_IsCircle(entityB) || Slvs_IsArc(entityB))) { return Slvs_AddConstraint(grouph, SLVS_C_PT_ON_CIRCLE, workplane, 0., entityA, SLVS_E_NONE, entityB); } - SolveSpace::Platform::FatalError("Invalid arguments for coincident constraint"); + Platform::FatalError("Invalid arguments for coincident constraint"); } Slvs_Constraint Slvs_Distance(uint32_t grouph, Slvs_Entity entityA, Slvs_Entity entityB, double value, Slvs_Entity workplane) { @@ -566,7 +573,7 @@ Slvs_Constraint Slvs_Distance(uint32_t grouph, Slvs_Entity entityA, Slvs_Entity } else if(Slvs_IsPoint(entityA) && Slvs_IsLine(entityB)) { return Slvs_AddConstraint(grouph, SLVS_C_PT_LINE_DISTANCE, workplane, value, entityA, SLVS_E_NONE, entityB); } - SolveSpace::Platform::FatalError("Invalid arguments for distance constraint"); + Platform::FatalError("Invalid arguments for distance constraint"); } Slvs_Constraint Slvs_Equal(uint32_t grouph, Slvs_Entity entityA, Slvs_Entity entityB, Slvs_Entity workplane = SLVS_E_FREE_IN_3D) { @@ -577,28 +584,28 @@ Slvs_Constraint Slvs_Equal(uint32_t grouph, Slvs_Entity entityA, Slvs_Entity ent } else if((Slvs_IsArc(entityA) || Slvs_IsCircle(entityA)) && (Slvs_IsArc(entityB) || Slvs_IsCircle(entityB))) { return Slvs_AddConstraint(grouph, SLVS_C_EQUAL_RADIUS, workplane, 0., SLVS_E_NONE, SLVS_E_NONE, entityA, entityB); } - SolveSpace::Platform::FatalError("Invalid arguments for equal constraint"); + Platform::FatalError("Invalid arguments for equal constraint"); } Slvs_Constraint Slvs_EqualAngle(uint32_t grouph, Slvs_Entity entityA, Slvs_Entity entityB, Slvs_Entity entityC, Slvs_Entity entityD, Slvs_Entity workplane = SLVS_E_FREE_IN_3D) { if(Slvs_IsLine2D(entityA) && Slvs_IsLine2D(entityB) && Slvs_IsLine2D(entityC) && Slvs_IsLine2D(entityD) && (Slvs_IsWorkplane(workplane) || Slvs_IsFreeIn3D(workplane))) { return Slvs_AddConstraint(grouph, SLVS_C_EQUAL_ANGLE, workplane, 0., SLVS_E_NONE, SLVS_E_NONE, entityA, entityB, entityC, entityD); } - SolveSpace::Platform::FatalError("Invalid arguments for equal angle constraint"); + Platform::FatalError("Invalid arguments for equal angle constraint"); } Slvs_Constraint Slvs_EqualPointToLine(uint32_t grouph, Slvs_Entity entityA, Slvs_Entity entityB, Slvs_Entity entityC, Slvs_Entity entityD, Slvs_Entity workplane = SLVS_E_FREE_IN_3D) { if(Slvs_IsPoint2D(entityA) && Slvs_IsLine2D(entityB) && Slvs_IsPoint2D(entityC) && Slvs_IsLine2D(entityD) && (Slvs_IsWorkplane(workplane) || Slvs_IsFreeIn3D(workplane))) { return Slvs_AddConstraint(grouph, SLVS_C_EQ_PT_LN_DISTANCES, workplane, 0., entityA, entityB, entityC, entityD); } - SolveSpace::Platform::FatalError("Invalid arguments for equal point to line constraint"); + Platform::FatalError("Invalid arguments for equal point to line constraint"); } Slvs_Constraint Slvs_Ratio(uint32_t grouph, Slvs_Entity entityA, Slvs_Entity entityB, double value, Slvs_Entity workplane = SLVS_E_FREE_IN_3D) { if(Slvs_IsLine2D(entityA) && Slvs_IsLine2D(entityB) && (Slvs_IsWorkplane(workplane) || Slvs_IsFreeIn3D(workplane))) { return Slvs_AddConstraint(grouph, SLVS_C_LENGTH_RATIO, workplane, value, SLVS_E_NONE, SLVS_E_NONE, entityA, entityB); } - SolveSpace::Platform::FatalError("Invalid arguments for ratio constraint"); + Platform::FatalError("Invalid arguments for ratio constraint"); } Slvs_Constraint Slvs_Symmetric(uint32_t grouph, Slvs_Entity entityA, Slvs_Entity entityB, Slvs_Entity entityC = SLVS_E_NONE, Slvs_Entity workplane = SLVS_E_FREE_IN_3D) { @@ -608,99 +615,99 @@ Slvs_Constraint Slvs_Symmetric(uint32_t grouph, Slvs_Entity entityA, Slvs_Entity return Slvs_AddConstraint(grouph, SLVS_C_SYMMETRIC, entityC, 0., entityA, entityB, entityC); } else if(Slvs_IsPoint2D(entityA) && Slvs_IsPoint2D(entityB) && Slvs_IsLine(entityC)) { if(Slvs_IsFreeIn3D(workplane)) { - SolveSpace::Platform::FatalError("3d workplane given for a 2d constraint"); + Platform::FatalError("3d workplane given for a 2d constraint"); } return Slvs_AddConstraint(grouph, SLVS_C_SYMMETRIC_LINE, workplane, 0., entityA, entityB, entityC); } - SolveSpace::Platform::FatalError("Invalid arguments for symmetric constraint"); + Platform::FatalError("Invalid arguments for symmetric constraint"); } Slvs_Constraint Slvs_SymmetricH(uint32_t grouph, Slvs_Entity ptA, Slvs_Entity ptB, Slvs_Entity workplane) { if(Slvs_IsFreeIn3D(workplane)) { - SolveSpace::Platform::FatalError("3d workplane given for a 2d constraint"); + Platform::FatalError("3d workplane given for a 2d constraint"); } else if(Slvs_IsPoint2D(ptA) && Slvs_IsPoint2D(ptB)) { return Slvs_AddConstraint(grouph, SLVS_C_SYMMETRIC_HORIZ, workplane, 0., ptA, ptB); } - SolveSpace::Platform::FatalError("Invalid arguments for symmetric horizontal constraint"); + Platform::FatalError("Invalid arguments for symmetric horizontal constraint"); } Slvs_Constraint Slvs_SymmetricV(uint32_t grouph, Slvs_Entity ptA, Slvs_Entity ptB, Slvs_Entity workplane) { if(Slvs_IsFreeIn3D(workplane)) { - SolveSpace::Platform::FatalError("3d workplane given for a 2d constraint"); + Platform::FatalError("3d workplane given for a 2d constraint"); } else if(Slvs_IsPoint2D(ptA) && Slvs_IsPoint2D(ptB)) { return Slvs_AddConstraint(grouph, SLVS_C_SYMMETRIC_VERT, workplane, 0., ptA, ptB); } - SolveSpace::Platform::FatalError("Invalid arguments for symmetric vertical constraint"); + Platform::FatalError("Invalid arguments for symmetric vertical constraint"); } Slvs_Constraint Slvs_Midpoint(uint32_t grouph, Slvs_Entity ptA, Slvs_Entity ptB, Slvs_Entity workplane = SLVS_E_FREE_IN_3D) { if(Slvs_IsPoint(ptA) && Slvs_IsLine(ptB) && (Slvs_IsWorkplane(workplane) || Slvs_IsFreeIn3D(workplane))) { return Slvs_AddConstraint(grouph, SLVS_C_AT_MIDPOINT, workplane, 0., ptA, SLVS_E_NONE, ptB); } - SolveSpace::Platform::FatalError("Invalid arguments for midpoint constraint"); + Platform::FatalError("Invalid arguments for midpoint constraint"); } Slvs_Constraint Slvs_Horizontal(uint32_t grouph, Slvs_Entity entityA, Slvs_Entity workplane, Slvs_Entity entityB = SLVS_E_NONE) { if(Slvs_IsFreeIn3D(workplane)) { - SolveSpace::Platform::FatalError("Horizontal constraint is not supported in 3D"); + Platform::FatalError("Horizontal constraint is not supported in 3D"); } else if(Slvs_IsLine2D(entityA)) { return Slvs_AddConstraint(grouph, SLVS_C_HORIZONTAL, workplane, 0., SLVS_E_NONE, SLVS_E_NONE, entityA); } else if(Slvs_IsPoint2D(entityA) && Slvs_IsPoint2D(entityB)) { return Slvs_AddConstraint(grouph, SLVS_C_HORIZONTAL, workplane, 0., entityA, entityB); } - SolveSpace::Platform::FatalError("Invalid arguments for horizontal constraint"); + Platform::FatalError("Invalid arguments for horizontal constraint"); } Slvs_Constraint Slvs_Vertical(uint32_t grouph, Slvs_Entity entityA, Slvs_Entity workplane, Slvs_Entity entityB = SLVS_E_NONE) { if(Slvs_IsFreeIn3D(workplane)) { - SolveSpace::Platform::FatalError("Vertical constraint is not supported in 3D"); + Platform::FatalError("Vertical constraint is not supported in 3D"); } else if(Slvs_IsLine2D(entityA)) { return Slvs_AddConstraint(grouph, SLVS_C_VERTICAL, workplane, 0., SLVS_E_NONE, SLVS_E_NONE, entityA); } else if(Slvs_IsPoint2D(entityA) && Slvs_IsPoint2D(entityB)) { return Slvs_AddConstraint(grouph, SLVS_C_VERTICAL, workplane, 0., entityA, entityB); } - SolveSpace::Platform::FatalError("Invalid arguments for horizontal constraint"); + Platform::FatalError("Invalid arguments for horizontal constraint"); } Slvs_Constraint Slvs_Diameter(uint32_t grouph, Slvs_Entity entityA, double value) { if(Slvs_IsArc(entityA) || Slvs_IsCircle(entityA)) { return Slvs_AddConstraint(grouph, SLVS_C_DIAMETER, SLVS_E_FREE_IN_3D, value, SLVS_E_NONE, SLVS_E_NONE, entityA); } - SolveSpace::Platform::FatalError("Invalid arguments for diameter constraint"); + Platform::FatalError("Invalid arguments for diameter constraint"); } Slvs_Constraint Slvs_SameOrientation(uint32_t grouph, Slvs_Entity entityA, Slvs_Entity entityB) { if(Slvs_IsNormal3D(entityA) && Slvs_IsNormal3D(entityB)) { return Slvs_AddConstraint(grouph, SLVS_C_SAME_ORIENTATION, SLVS_E_FREE_IN_3D, 0., SLVS_E_NONE, SLVS_E_NONE, entityA, entityB); } - SolveSpace::Platform::FatalError("Invalid arguments for same orientation constraint"); + Platform::FatalError("Invalid arguments for same orientation constraint"); } Slvs_Constraint Slvs_Angle(uint32_t grouph, Slvs_Entity entityA, Slvs_Entity entityB, double value, Slvs_Entity workplane = SLVS_E_FREE_IN_3D, int inverse = 0) { if(Slvs_IsLine2D(entityA) && Slvs_IsLine2D(entityB) && (Slvs_IsWorkplane(workplane) || Slvs_IsFreeIn3D(workplane))) { return Slvs_AddConstraint(grouph, SLVS_C_ANGLE, workplane, value, SLVS_E_NONE, SLVS_E_NONE, entityA, entityB, SLVS_E_NONE, SLVS_E_NONE, inverse); } - SolveSpace::Platform::FatalError("Invalid arguments for angle constraint"); + Platform::FatalError("Invalid arguments for angle constraint"); } Slvs_Constraint Slvs_Perpendicular(uint32_t grouph, Slvs_Entity entityA, Slvs_Entity entityB, Slvs_Entity workplane = SLVS_E_FREE_IN_3D, int inverse = 0) { if(Slvs_IsLine2D(entityA) && Slvs_IsLine2D(entityB) && (Slvs_IsWorkplane(workplane) || Slvs_IsFreeIn3D(workplane))) { return Slvs_AddConstraint(grouph, SLVS_C_PERPENDICULAR, workplane, 0., SLVS_E_NONE, SLVS_E_NONE, entityA, entityB, SLVS_E_NONE, SLVS_E_NONE, inverse); } - SolveSpace::Platform::FatalError("Invalid arguments for perpendicular constraint"); + Platform::FatalError("Invalid arguments for perpendicular constraint"); } Slvs_Constraint Slvs_Parallel(uint32_t grouph, Slvs_Entity entityA, Slvs_Entity entityB, Slvs_Entity workplane = SLVS_E_FREE_IN_3D) { if(Slvs_IsLine2D(entityA) && Slvs_IsLine2D(entityB) && (Slvs_IsWorkplane(workplane) || Slvs_IsFreeIn3D(workplane))) { return Slvs_AddConstraint(grouph, SLVS_C_PARALLEL, workplane, 0., SLVS_E_NONE, SLVS_E_NONE, entityA, entityB); } - SolveSpace::Platform::FatalError("Invalid arguments for parallel constraint"); + Platform::FatalError("Invalid arguments for parallel constraint"); } Slvs_Constraint Slvs_Tangent(uint32_t grouph, Slvs_Entity entityA, Slvs_Entity entityB, Slvs_Entity workplane = SLVS_E_FREE_IN_3D) { if(Slvs_IsArc(entityA) && Slvs_IsLine2D(entityB)) { if(Slvs_IsFreeIn3D(workplane)) { - SolveSpace::Platform::FatalError("3d workplane given for a 2d constraint"); + Platform::FatalError("3d workplane given for a 2d constraint"); } Vector a1 = SK.entity.FindById(hEntity { entityA.point[1] })->PointGetNum(), a2 = SK.entity.FindById(hEntity { entityA.point[2] })->PointGetNum(); @@ -712,7 +719,7 @@ Slvs_Constraint Slvs_Tangent(uint32_t grouph, Slvs_Entity entityA, Slvs_Entity e } else if(l0.Equals(a2) || l1.Equals(a2)) { other = 1; } else { - SolveSpace::Platform::FatalError("The tangent arc and line segment must share an " + Platform::FatalError("The tangent arc and line segment must share an " "endpoint. Constrain them with Constrain -> " "On Point before constraining tangent."); } @@ -728,14 +735,14 @@ Slvs_Constraint Slvs_Tangent(uint32_t grouph, Slvs_Entity entityA, Slvs_Entity e } else if(l0.Equals(af) || l1.Equals(af)) { other = 1; } else { - SolveSpace::Platform::FatalError("The tangent cubic and line segment must share an " + Platform::FatalError("The tangent cubic and line segment must share an " "endpoint. Constrain them with Constrain -> " "On Point before constraining tangent."); } return Slvs_AddConstraint(grouph, SLVS_C_CUBIC_LINE_TANGENT, workplane, 0., SLVS_E_NONE, SLVS_E_NONE, entityA, entityB, SLVS_E_NONE, SLVS_E_NONE, other); } else if((Slvs_IsArc(entityA) || Slvs_IsCubic(entityA)) && (Slvs_IsArc(entityB) || Slvs_IsCubic(entityB))) { if(Slvs_IsFreeIn3D(workplane)) { - SolveSpace::Platform::FatalError("3d workplane given for a 2d constraint"); + Platform::FatalError("3d workplane given for a 2d constraint"); } EntityBase* skEntityA = SK.entity.FindById(hEntity { entityA.h }); EntityBase* skEntityB = SK.entity.FindById(hEntity { entityB.h }); @@ -756,34 +763,34 @@ Slvs_Constraint Slvs_Tangent(uint32_t grouph, Slvs_Entity entityA, Slvs_Entity e other = 1; other2 = 1; } else { - SolveSpace::Platform::FatalError("The curves must share an endpoint. Constrain them " + Platform::FatalError("The curves must share an endpoint. Constrain them " "with Constrain -> On Point before constraining " "tangent."); } return Slvs_AddConstraint(grouph, SLVS_C_CURVE_CURVE_TANGENT, workplane, 0., SLVS_E_NONE, SLVS_E_NONE, entityA, entityB, SLVS_E_NONE, SLVS_E_NONE, other, other2); } - SolveSpace::Platform::FatalError("Invalid arguments for tangent constraint"); + Platform::FatalError("Invalid arguments for tangent constraint"); } Slvs_Constraint Slvs_DistanceProj(uint32_t grouph, Slvs_Entity ptA, Slvs_Entity ptB, double value) { if(Slvs_IsPoint(ptA) && Slvs_IsPoint(ptB)) { return Slvs_AddConstraint(grouph, SLVS_C_PROJ_PT_DISTANCE, SLVS_E_FREE_IN_3D, value, ptA, ptB); } - SolveSpace::Platform::FatalError("Invalid arguments for projected distance constraint"); + Platform::FatalError("Invalid arguments for projected distance constraint"); } Slvs_Constraint Slvs_LengthDiff(uint32_t grouph, Slvs_Entity entityA, Slvs_Entity entityB, double value, Slvs_Entity workplane = SLVS_E_FREE_IN_3D) { if(Slvs_IsLine(entityA) && Slvs_IsLine(entityB) && (Slvs_IsWorkplane(workplane) || Slvs_IsFreeIn3D(workplane))) { return Slvs_AddConstraint(grouph, SLVS_C_LENGTH_DIFFERENCE, workplane, value, SLVS_E_NONE, SLVS_E_NONE, entityA, entityB); } - SolveSpace::Platform::FatalError("Invalid arguments for length difference constraint"); + Platform::FatalError("Invalid arguments for length difference constraint"); } Slvs_Constraint Slvs_Dragged(uint32_t grouph, Slvs_Entity ptA, Slvs_Entity workplane = SLVS_E_FREE_IN_3D) { if(Slvs_IsPoint(ptA) && (Slvs_IsWorkplane(workplane) || Slvs_IsFreeIn3D(workplane))) { return Slvs_AddConstraint(grouph, SLVS_C_WHERE_DRAGGED, workplane, 0., ptA); } - SolveSpace::Platform::FatalError("Invalid arguments for dragged constraint"); + Platform::FatalError("Invalid arguments for dragged constraint"); } void Slvs_QuaternionU(double qw, double qx, double qy, double qz, @@ -1110,7 +1117,7 @@ void Slvs_Solve(Slvs_System *ssys, uint32_t shg) SK.entity.Clear(); SK.constraint.Clear(); - FreeAllTemporary(); + Platform::FreeAllTemporary(); } } /* extern "C" */ diff --git a/src/solvespace.cpp b/src/solvespace.cpp index f4f606c99..2fdf7b6a3 100644 --- a/src/solvespace.cpp +++ b/src/solvespace.cpp @@ -7,8 +7,10 @@ #include "solvespace.h" #include "config.h" -SolveSpaceUI SolveSpace::SS = {}; -Sketch SolveSpace::SK = {}; +namespace SolveSpace { + +SolveSpaceUI SS = {}; +Sketch SK = {}; void SolveSpaceUI::Init() { #if !defined(HEADLESS) @@ -638,7 +640,7 @@ bool SolveSpaceUI::OkayToStartNewFile() { using Platform::MessageDialog; dialog->SetType(MessageDialog::Type::QUESTION); dialog->SetTitle(C_("title", "Modified File")); - if(!SolveSpace::SS.saveFile.IsEmpty()) { + if(!SS.saveFile.IsEmpty()) { dialog->SetMessage(ssprintf(C_("dialog", "Do you want to save the changes you made to " "the sketch ā€œ%sā€?"), saveFile.raw.c_str())); } else { @@ -1230,3 +1232,5 @@ Group *Sketch::GetRunningMeshGroupFor(hGroup h) { } return NULL; } + +} // namespace SolveSpace diff --git a/src/solvespace.h b/src/solvespace.h index f1230b1c5..572c48d71 100644 --- a/src/solvespace.h +++ b/src/solvespace.h @@ -7,82 +7,25 @@ #ifndef SOLVESPACE_H #define SOLVESPACE_H -#include "resource.h" -#include "platform/platform.h" -#include "platform/gui.h" - -#include -#include -#include -#include -#include -#include +#include #include #include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include -#include -#include -#include #define EIGEN_NO_DEBUG #undef Success #include -// We declare these in advance instead of simply using FT_Library -// (defined as typedef FT_LibraryRec_* FT_Library) because including -// freetype.h invokes indescribable horrors and we would like to avoid -// doing that every time we include solvespace.h. -struct FT_LibraryRec_; -struct FT_FaceRec_; - -typedef struct _cairo cairo_t; -typedef struct _cairo_surface cairo_surface_t; - -// The few floating-point equality comparisons in SolveSpace have been -// carefully considered, so we disable the -Wfloat-equal warning for them -#ifdef __clang__ -# define EXACT(expr) \ - (_Pragma("clang diagnostic push") \ - _Pragma("clang diagnostic ignored \"-Wfloat-equal\"") \ - (expr) \ - _Pragma("clang diagnostic pop")) -#else -# define EXACT(expr) (expr) -#endif - -// Debugging functions -#if defined(__GNUC__) -#define ssassert(condition, message) \ - do { \ - if(__builtin_expect((condition), true) == false) { \ - SolveSpace::AssertFailure(__FILE__, __LINE__, __func__, #condition, message); \ - __builtin_unreachable(); \ - } \ - } while(0) -#else -#define ssassert(condition, message) \ - do { \ - if((condition) == false) { \ - SolveSpace::AssertFailure(__FILE__, __LINE__, __func__, #condition, message); \ - abort(); \ - } \ - } while(0) -#endif +#include "dsc.h" +#include "polygon.h" +#include "srf/surface.h" +#include "render/render.h" +#include "expr.h" +#include "sketch.h" +#include "ttf.h" +#include "ui.h" -#define dbp SolveSpace::Platform::DebugPrint -#define DBPTRI(tri) \ - dbp("tri: (%.3f %.3f %.3f) (%.3f %.3f %.3f) (%.3f %.3f %.3f)", \ - CO((tri).a), CO((tri).b), CO((tri).c)) +#include "platform/platform.h" namespace SolveSpace { @@ -91,55 +34,6 @@ using std::max; using std::swap; using std::fabs; -[[noreturn]] -void AssertFailure(const char *file, unsigned line, const char *function, - const char *condition, const char *message); - -#if defined(__GNUC__) -__attribute__((__format__ (__printf__, 1, 2))) -#endif -std::string ssprintf(const char *fmt, ...); - -inline bool IsReasonable(double x) { - return std::isnan(x) || x > 1e11 || x < -1e11; -} - -inline int WRAP(int v, int n) { - // Clamp it to the range [0, n) - while(v >= n) v -= n; - while(v < 0) v += n; - return v; -} -inline double WRAP_NOT_0(double v, double n) { - // Clamp it to the range (0, n] - while(v > n) v -= n; - while(v <= 0) v += n; - return v; -} -inline double WRAP_SYMMETRIC(double v, double n) { - // Clamp it to the range (-n/2, n/2] - while(v > n/2) v -= n; - while(v <= -n/2) v += n; - return v; -} - -#define CO(v) (v).x, (v).y, (v).z - -static constexpr double ANGLE_COS_EPS = 1e-6; -static constexpr double LENGTH_EPS = 1e-6; -static constexpr double VERY_POSITIVE = 1e10; -static constexpr double VERY_NEGATIVE = -1e10; - - -using Platform::AllocTemporary; -using Platform::FreeAllTemporary; - -class Expr; -class ExprVector; -class ExprQuaternion; -class RgbaColor; -enum class Command : uint32_t; - enum class Unit : uint32_t { MM = 0, INCHES, @@ -147,22 +41,7 @@ enum class Unit : uint32_t { FEET_INCHES }; -template -using handle_map = std::map; - -class Group; -class SSurface; -#include "dsc.h" -#include "polygon.h" -#include "srf/surface.h" -#include "render/render.h" - -class Entity; -class hEntity; -class Param; -class hParam; -typedef IdList EntityList; -typedef IdList ParamList; +class Pixmap; enum class SolveResult : uint32_t { OKAY = 0, @@ -172,13 +51,6 @@ enum class SolveResult : uint32_t { TOO_MANY_UNKNOWNS = 20 }; -using ParamSet = std::unordered_set>; - -#include "sketch.h" -#include "ui.h" -#include "expr.h" - - // Utility functions that are provided in the platform-independent code. class utf8_iterator { const char *p, *n; @@ -206,20 +78,6 @@ class ReadUTF8 { utf8_iterator end() const { return utf8_iterator(&str[0] + str.length()); } }; - -#define arraylen(x) (sizeof((x))/sizeof((x)[0])) -#define PI (3.1415926535897931) -void MakeMatrix(double *mat, double a11, double a12, double a13, double a14, - double a21, double a22, double a23, double a24, - double a31, double a32, double a33, double a34, - double a41, double a42, double a43, double a44); -void MultMatrix(double *mata, double *matb, double *matr); - -int64_t GetMilliseconds(); -void Message(const char *fmt, ...); -void MessageAndRun(std::function onDismiss, const char *fmt, ...); -void Error(const char *fmt, ...); - class System { public: enum { MAX_UNKNOWNS = 2048 }; @@ -298,8 +156,6 @@ class System { void Clear(); }; -#include "ttf.h" - class StepFileWriter { public: bool HasCartesianPointAnAlias(int number, Vector v, int vertex, @@ -888,10 +744,6 @@ bool LinkStl(const Platform::Path &filename, EntityList *le, SMesh *m, SShell *s extern SolveSpaceUI SS; extern Sketch SK; -} - -#ifndef __OBJC__ -using namespace SolveSpace; -#endif +} // namespace SolveSpace #endif diff --git a/src/srf/boolean.cpp b/src/srf/boolean.cpp index 7b8c00c56..4778b185e 100644 --- a/src/srf/boolean.cpp +++ b/src/srf/boolean.cpp @@ -6,6 +6,8 @@ //----------------------------------------------------------------------------- #include "solvespace.h" +namespace SolveSpace { + static int I; void SShell::MakeFromUnionOf(SShell *a, SShell *b) { @@ -866,7 +868,7 @@ void SSurface::MakeClassifyingBsp(SShell *shell, SShell *useCurvesFrom) { } SBspUv *SBspUv::Alloc() { - return (SBspUv *)AllocTemporary(sizeof(SBspUv)); + return (SBspUv *)Platform::AllocTemporary(sizeof(SBspUv)); } SBspUv *SBspUv::From(SEdgeList *el, SSurface *srf) { @@ -1044,3 +1046,4 @@ double SBspUv::MinimumDistanceToEdge(Point2d p, SSurface *srf) const { return min(d, min(dn, dp)); } +} // namespace SolveSpace diff --git a/src/srf/curve.cpp b/src/srf/curve.cpp index c1f71bf38..ef3e19a04 100644 --- a/src/srf/curve.cpp +++ b/src/srf/curve.cpp @@ -4,7 +4,9 @@ // // Copyright 2008-2013 Jonathan Westhues. //----------------------------------------------------------------------------- -#include "../solvespace.h" +#include "solvespace.h" + +namespace SolveSpace { SBezier SBezier::From(Vector4 p0, Vector4 p1) { SBezier ret = {}; @@ -881,3 +883,4 @@ STrimBy STrimBy::EntireCurve(SShell *shell, hSCurve hsc, bool backwards) { return stb; } +} // namespace SolveSpace diff --git a/src/srf/merge.cpp b/src/srf/merge.cpp index 42ae55906..03ef339d8 100644 --- a/src/srf/merge.cpp +++ b/src/srf/merge.cpp @@ -4,7 +4,9 @@ // // Copyright 2008-2013 Jonathan Westhues. //----------------------------------------------------------------------------- -#include "../solvespace.h" +#include "solvespace.h" + +namespace SolveSpace { void SShell::MergeCoincidentSurfaces() { surface.ClearTags(); @@ -125,3 +127,4 @@ void SShell::MergeCoincidentSurfaces() { surface.RemoveTagged(); } +} // namespace SolveSpace diff --git a/src/srf/ratpoly.cpp b/src/srf/ratpoly.cpp index 46180a55e..20b8d198b 100644 --- a/src/srf/ratpoly.cpp +++ b/src/srf/ratpoly.cpp @@ -5,7 +5,9 @@ // // Copyright 2008-2013 Jonathan Westhues. //----------------------------------------------------------------------------- -#include "../solvespace.h" +#include "solvespace.h" + +namespace SolveSpace { // Converge it to better than LENGTH_EPS; we want two points, each // independently projected into uv and back, to end up equal with the @@ -699,3 +701,4 @@ void SSurface::PointOnCurve(const SBezier *curve, double *up, double *vp) dbp("didn't converge (surface and curve intersecting)"); } +} // namespace SolveSpace diff --git a/src/srf/raycast.cpp b/src/srf/raycast.cpp index acbcd8fdc..4c2f43500 100644 --- a/src/srf/raycast.cpp +++ b/src/srf/raycast.cpp @@ -9,6 +9,8 @@ //----------------------------------------------------------------------------- #include "solvespace.h" +namespace SolveSpace { + // Dot product tolerance for perpendicular; this is on the direction cosine, // so it's about 0.001 degrees. const double SShell::DOTP_TOL = 1e-5; @@ -611,3 +613,4 @@ bool SShell::ClassifyEdge(Class *indir, Class *outdir, return true; } +} // namespace SolveSpace diff --git a/src/srf/shell.cpp b/src/srf/shell.cpp index ca3b75ee9..9d7fa4752 100644 --- a/src/srf/shell.cpp +++ b/src/srf/shell.cpp @@ -4,7 +4,9 @@ // // Copyright 2008-2013 Jonathan Westhues. //----------------------------------------------------------------------------- -#include "../solvespace.h" +#include "solvespace.h" + +namespace SolveSpace { typedef struct { hSCurve hc; @@ -612,3 +614,5 @@ void SShell::Clear() { } curve.Clear(); } + +} // namespace SolveSpace diff --git a/src/srf/surface.cpp b/src/srf/surface.cpp index 18edabf61..8ddd084d1 100644 --- a/src/srf/surface.cpp +++ b/src/srf/surface.cpp @@ -4,7 +4,9 @@ // // Copyright 2008-2013 Jonathan Westhues. //----------------------------------------------------------------------------- -#include "../solvespace.h" +#include "solvespace.h" + +namespace SolveSpace { SSurface SSurface::FromExtrusionOf(SBezier *sb, Vector t0, Vector t1) { SSurface ret = {}; @@ -489,4 +491,4 @@ void SSurface::Clear() { trim.Clear(); } - +} // namespace SolveSpace diff --git a/src/srf/surface.h b/src/srf/surface.h index b1a7cd90d..2ef85ed11 100644 --- a/src/srf/surface.h +++ b/src/srf/surface.h @@ -10,6 +10,14 @@ #ifndef SOLVESPACE_SURFACE_H #define SOLVESPACE_SURFACE_H +#include + +#include "dsc.h" +#include "polygon.h" + +namespace SolveSpace { + +class Group; class SBezierList; class SSurface; class SCurvePt; @@ -435,5 +443,6 @@ class SShell { void Clear(); }; -#endif +} // namespace SolveSpace +#endif diff --git a/src/srf/surfinter.cpp b/src/srf/surfinter.cpp index 5b6464dc2..c13c7d2f9 100644 --- a/src/srf/surfinter.cpp +++ b/src/srf/surfinter.cpp @@ -7,6 +7,8 @@ //----------------------------------------------------------------------------- #include "solvespace.h" +namespace SolveSpace { + extern int FLAG; void SSurface::AddExactIntersectionCurve(SBezier *sb, SSurface *srfB, @@ -591,3 +593,4 @@ void SShell::MakeCoincidentEdgesInto(SSurface *proto, bool sameNormal, } } +} // namespace SolveSpace diff --git a/src/srf/triangulate.cpp b/src/srf/triangulate.cpp index 464bce624..81a2a4534 100644 --- a/src/srf/triangulate.cpp +++ b/src/srf/triangulate.cpp @@ -6,7 +6,9 @@ // // Copyright 2008-2013 Jonathan Westhues. //----------------------------------------------------------------------------- -#include "../solvespace.h" +#include "solvespace.h" + +namespace SolveSpace { void SPolygon::UvTriangulateInto(SMesh *m, SSurface *srf) { if(l.n <= 0) return; @@ -732,3 +734,5 @@ void SPolygon::TriangulateInto(SMesh *m) const { p.Clear(); pm.Clear(); } + +} // namespace SolveSpace diff --git a/src/style.cpp b/src/style.cpp index 4349eb36e..950b04e9c 100644 --- a/src/style.cpp +++ b/src/style.cpp @@ -7,6 +7,8 @@ //----------------------------------------------------------------------------- #include "solvespace.h" +namespace SolveSpace { + const Style::Default Style::Defaults[] = { { { ACTIVE_GRP }, "ActiveGrp", RGBf(1.0, 1.0, 1.0), 1.5, 4, true, StipplePattern::CONTINUOUS }, { { CONSTRUCTION }, "Construction", RGBf(0.1, 0.7, 0.1), 1.5, 0, false, StipplePattern::CONTINUOUS }, @@ -942,3 +944,5 @@ void TextWindow::ShowStyleInfo() { void TextWindow::ScreenAssignSelectionToStyle(int link, uint32_t v) { Style::AssignSelectionToStyle(v); } + +} // namespace SolveSpace diff --git a/src/system.cpp b/src/system.cpp index eb15d1b44..89d315938 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -11,6 +11,8 @@ #include #include +namespace SolveSpace { + // The solver will converge all unknowns to within this tolerance. This must // always be much less than LENGTH_EPS, and in practice should be much less. const double System::CONVERGE_TOLERANCE = (LENGTH_EPS/(1e2)); @@ -609,3 +611,4 @@ void System::MarkParamsFree(bool find) { } } +} // namespace SolveSpace diff --git a/src/textscreens.cpp b/src/textscreens.cpp index ec75b01ec..41dcb1b7d 100644 --- a/src/textscreens.cpp +++ b/src/textscreens.cpp @@ -6,6 +6,8 @@ //----------------------------------------------------------------------------- #include "solvespace.h" +namespace SolveSpace { + //----------------------------------------------------------------------------- // A navigation bar that always appears at the top of the window, with a // link to bring us back home. @@ -979,3 +981,4 @@ void TextWindow::EditControlDone(std::string s) { } } +} // namespace SolveSpace diff --git a/src/textwin.cpp b/src/textwin.cpp index 8d37c8216..537c2d13e 100644 --- a/src/textwin.cpp +++ b/src/textwin.cpp @@ -4,6 +4,7 @@ // Copyright 2008-2013 Jonathan Westhues. //----------------------------------------------------------------------------- #include +#include #include "solvespace.h" namespace SolveSpace { diff --git a/src/toolbar.cpp b/src/toolbar.cpp index 74764883a..372b9098c 100644 --- a/src/toolbar.cpp +++ b/src/toolbar.cpp @@ -7,6 +7,8 @@ //----------------------------------------------------------------------------- #include "solvespace.h" +namespace SolveSpace { + struct ToolIcon { std::string name; Command command; @@ -246,3 +248,5 @@ bool GraphicsWindow::ToolbarDrawOrHitTest(int mx, int my, UiCanvas *canvas, return withinToolbar; } + +} // namespace SolveSpace diff --git a/src/ttf.cpp b/src/ttf.cpp index 10ba0d888..2aa928b72 100644 --- a/src/ttf.cpp +++ b/src/ttf.cpp @@ -41,6 +41,8 @@ extern "C" const char *ft_error_string(int err) { #include "solvespace.h" +namespace SolveSpace { + //----------------------------------------------------------------------------- // Get the list of available font filenames, and load the name for each of // them. Only that, though, not the glyphs too. @@ -443,3 +445,5 @@ double TtfFont::AspectRatio(const std::string &str, bool kerning) { return dx; } + +} // namespace SolveSpace diff --git a/src/ttf.h b/src/ttf.h index 1dc7205d3..560158d86 100644 --- a/src/ttf.h +++ b/src/ttf.h @@ -9,6 +9,22 @@ #ifndef SOLVESPACE_TTF_H #define SOLVESPACE_TTF_H +#include + +#include "dsc.h" +#include "platform/platform.h" + +// We declare these in advance instead of simply using FT_Library +// (defined as typedef FT_LibraryRec_* FT_Library) because including +// freetype.h invokes indescribable horrors and we would like to avoid +// doing that every time we include solvespace.h. +struct FT_LibraryRec_; +struct FT_FaceRec_; + +namespace SolveSpace { + +class SBezierList; + class TtfFont { public: Platform::Path fontFile; // or resource path/name as res:// @@ -47,4 +63,6 @@ class TtfFontList { double AspectRatio(const std::string &font, const std::string &str, bool kerning); }; +} // namespace SolveSpace + #endif diff --git a/src/ui.h b/src/ui.h index eef546ece..3bb789a12 100644 --- a/src/ui.h +++ b/src/ui.h @@ -8,6 +8,26 @@ #ifndef SOLVESPACE_UI_H #define SOLVESPACE_UI_H +#include +#include +#include +#include +#include + +#include "dsc.h" +#include "platform/gui.h" +#include "sketch.h" + +namespace SolveSpace { + +class Camera; +class Lighting; +class Canvas; +class UiCanvas; +class BatchCanvas; +class ViewportCanvas; +class Pixmap; + class Locale { public: std::string language; @@ -864,5 +884,6 @@ class GraphicsWindow { void SixDofEvent(Platform::SixDofEvent event); }; +} // namespace SolveSpace #endif diff --git a/src/undoredo.cpp b/src/undoredo.cpp index 8ea8a0679..17d1a376b 100644 --- a/src/undoredo.cpp +++ b/src/undoredo.cpp @@ -7,6 +7,8 @@ //----------------------------------------------------------------------------- #include "solvespace.h" +namespace SolveSpace { + void SolveSpaceUI::UndoRemember() { unsaved = true; PushFromCurrentOnto(&undo); @@ -152,3 +154,4 @@ void SolveSpaceUI::UndoClearState(UndoState *ut) { *ut = {}; } +} // namespace SolveSpace diff --git a/src/util.cpp b/src/util.cpp index f14417cc9..d1ea15a30 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -4,18 +4,25 @@ // // Copyright 2008-2013 Jonathan Westhues. //----------------------------------------------------------------------------- +#include +#include +#include +#include + #include "solvespace.h" -void SolveSpace::AssertFailure(const char *file, unsigned line, const char *function, +namespace SolveSpace { + +void AssertFailure(const char *file, unsigned line, const char *function, const char *condition, const char *message) { std::string formattedMsg; formattedMsg += ssprintf("File %s, line %u, function %s:\n", file, line, function); formattedMsg += ssprintf("Assertion failed: %s.\n", condition); formattedMsg += ssprintf("Message: %s.\n", message); - SolveSpace::Platform::FatalError(formattedMsg); + Platform::FatalError(formattedMsg); } -std::string SolveSpace::ssprintf(const char *fmt, ...) +std::string ssprintf(const char *fmt, ...) { va_list va; @@ -57,13 +64,13 @@ char32_t utf8_iterator::operator*() return result; } -int64_t SolveSpace::GetMilliseconds() +int64_t GetMilliseconds() { auto timestamp = std::chrono::steady_clock::now().time_since_epoch(); return std::chrono::duration_cast(timestamp).count(); } -void SolveSpace::MakeMatrix(double *mat, +void MakeMatrix(double *mat, double a11, double a12, double a13, double a14, double a21, double a22, double a23, double a24, double a31, double a32, double a33, double a34, @@ -87,7 +94,7 @@ void SolveSpace::MakeMatrix(double *mat, mat[15] = a44; } -void SolveSpace::MultMatrix(double *mata, double *matb, double *matr) { +void MultMatrix(double *mata, double *matb, double *matr) { for(int i = 0; i < 4; i++) { for(int j = 0; j < 4; j++) { double s = 0.0; @@ -178,21 +185,21 @@ static void MessageBox(const char *fmt, va_list va, bool error, dialog->ShowModal(); #endif } -void SolveSpace::Error(const char *fmt, ...) +void Error(const char *fmt, ...) { va_list f; va_start(f, fmt); MessageBox(fmt, f, /*error=*/true); va_end(f); } -void SolveSpace::Message(const char *fmt, ...) +void Message(const char *fmt, ...) { va_list f; va_start(f, fmt); MessageBox(fmt, f, /*error=*/false); va_end(f); } -void SolveSpace::MessageAndRun(std::function onDismiss, const char *fmt, ...) +void MessageAndRun(std::function onDismiss, const char *fmt, ...) { va_list f; va_start(f, fmt); @@ -1025,7 +1032,7 @@ bool BBox::Contains(const Point2d &p, double r) const { p.y <= (maxp.y + r); } -const std::vector& SolveSpace::StipplePatternDashes(StipplePattern pattern) { +const std::vector& StipplePatternDashes(StipplePattern pattern) { static bool initialized; static std::vector dashes[(size_t)StipplePattern::LAST + 1]; if(!initialized) { @@ -1054,7 +1061,7 @@ const std::vector& SolveSpace::StipplePatternDashes(StipplePattern patte return dashes[(size_t)pattern]; } -double SolveSpace::StipplePatternLength(StipplePattern pattern) { +double StipplePatternLength(StipplePattern pattern) { static bool initialized; static double lengths[(size_t)StipplePattern::LAST + 1]; if(!initialized) { @@ -1070,3 +1077,5 @@ double SolveSpace::StipplePatternLength(StipplePattern pattern) { return lengths[(size_t)pattern]; } + +} // namespace SolveSpace diff --git a/src/util.h b/src/util.h new file mode 100644 index 000000000..585b5decd --- /dev/null +++ b/src/util.h @@ -0,0 +1,105 @@ +#ifndef SOLVESPACE_UTIL_H +#define SOLVESPACE_UTIL_H + +#include +#include +#include +#include +#include +#include + +// The few floating-point equality comparisons in SolveSpace have been +// carefully considered, so we disable the -Wfloat-equal warning for them +#ifdef __clang__ +# define EXACT(expr) \ + (_Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Wfloat-equal\"") \ + (expr) \ + _Pragma("clang diagnostic pop")) +#else +# define EXACT(expr) (expr) +#endif + +// Debugging functions +#if defined(__GNUC__) +#define ssassert(condition, message) \ + do { \ + if(__builtin_expect((condition), true) == false) { \ + SolveSpace::AssertFailure(__FILE__, __LINE__, __func__, #condition, message); \ + __builtin_unreachable(); \ + } \ + } while(0) +#else +#define ssassert(condition, message) \ + do { \ + if((condition) == false) { \ + SolveSpace::AssertFailure(__FILE__, __LINE__, __func__, #condition, message); \ + std::abort(); \ + } \ + } while(0) +#endif + +#define CO(v) (v).x, (v).y, (v).z + +#define dbp SolveSpace::Platform::DebugPrint + +namespace SolveSpace { + +namespace Platform { + +// Debug print function. +void DebugPrint(const char *fmt, ...); + +} // namespace Platform + +[[noreturn]] +void AssertFailure(const char *file, unsigned line, const char *function, + const char *condition, const char *message); + +#if defined(__GNUC__) +__attribute__((__format__ (__printf__, 1, 2))) +#endif +std::string ssprintf(const char *fmt, ...); + +inline bool IsReasonable(double x) { + return std::isnan(x) || x > 1e11 || x < -1e11; +} + +inline int WRAP(int v, int n) { + // Clamp it to the range [0, n) + while(v >= n) v -= n; + while(v < 0) v += n; + return v; +} +inline double WRAP_NOT_0(double v, double n) { + // Clamp it to the range (0, n] + while(v > n) v -= n; + while(v <= 0) v += n; + return v; +} +inline double WRAP_SYMMETRIC(double v, double n) { + // Clamp it to the range (-n/2, n/2] + while(v > n/2) v -= n; + while(v <= -n/2) v += n; + return v; +} + +template +inline constexpr size_t arraylen(const T (&)[N]) { + return N; +} + +void MakeMatrix(double *mat, double a11, double a12, double a13, double a14, + double a21, double a22, double a23, double a24, + double a31, double a32, double a33, double a34, + double a41, double a42, double a43, double a44); +void MultMatrix(double *mata, double *matb, double *matr); + +int64_t GetMilliseconds(); +void Message(const char *fmt, ...); +void MessageAndRun(std::function onDismiss, const char *fmt, ...); +void Error(const char *fmt, ...); + +} // namespace SolveSpace + +#endif // !SOLVESPACE_UTIL_H diff --git a/src/view.cpp b/src/view.cpp index 5f6de3299..62602531a 100644 --- a/src/view.cpp +++ b/src/view.cpp @@ -6,6 +6,8 @@ //----------------------------------------------------------------------------- #include "solvespace.h" +namespace SolveSpace { + void TextWindow::ShowEditView() { Printf(true, "%Ft3D VIEW PARAMETERS%E"); @@ -169,3 +171,4 @@ bool TextWindow::EditControlDoneForView(const std::string &s) { return true; } +} // namespace SolveSpace diff --git a/test/debugtool.cpp b/test/debugtool.cpp index aa66c1fee..aea6b8475 100644 --- a/test/debugtool.cpp +++ b/test/debugtool.cpp @@ -3,7 +3,11 @@ // // Copyright 2017 whitequark //----------------------------------------------------------------------------- -#include "solvespace.h" + +#include "expr.h" +#include "platform/platform.h" + +using namespace SolveSpace; int main(int argc, char **argv) { std::vector args = Platform::InitCli(argc, argv); @@ -16,7 +20,7 @@ int main(int argc, char **argv) { } else { fprintf(stderr, "%g\n", e->Eval()); } - FreeAllTemporary(); + Platform::FreeAllTemporary(); } else { fprintf(stderr, "Usage: %s \n", args[0].c_str()); //-----------------------------------------------------------------------------> 80 col */ diff --git a/test/harness.cpp b/test/harness.cpp index ef14799df..303324da9 100644 --- a/test/harness.cpp +++ b/test/harness.cpp @@ -3,6 +3,7 @@ // // Copyright 2016 whitequark //----------------------------------------------------------------------------- +#include #include #include #include From f39a7fbf80298ccfd32ebf242ca30e4e70e6050c Mon Sep 17 00:00:00 2001 From: Isaac Garzon Date: Thu, 1 May 2025 13:23:23 +0300 Subject: [PATCH 2/3] handle: extract handle-related code from dsc.h This makes it easier to avoid including dsc.h when it's not needed. --- src/CMakeLists.txt | 1 + src/dsc.h | 37 ------------------------------------ src/handle.h | 47 ++++++++++++++++++++++++++++++++++++++++++++++ src/param.h | 8 ++++++-- src/srf/surface.h | 1 + 5 files changed, 55 insertions(+), 39 deletions(-) create mode 100644 src/handle.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 352aa55b4..88b2f0a70 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -65,6 +65,7 @@ add_library(slvs-solver INTERFACE) target_sources(slvs-solver INTERFACE dsc.h expr.h + handle.h param.h platform/platform.h solvespace.h diff --git a/src/dsc.h b/src/dsc.h index 8ddfd5e6e..1a535c6b5 100644 --- a/src/dsc.h +++ b/src/dsc.h @@ -11,7 +11,6 @@ #include #include #include -#include #include #include "defs.h" @@ -19,42 +18,6 @@ namespace SolveSpace { -/// Trait indicating which types are handle types and should get the associated operators. -/// Specialize for each handle type and inherit from std::true_type. -template -struct IsHandleOracle : std::false_type {}; - -// Equality-compare any two instances of a handle type. -template -static inline typename std::enable_if::value, bool>::type -operator==(T const &lhs, T const &rhs) { - return lhs.v == rhs.v; -} - -// Inequality-compare any two instances of a handle type. -template -static inline typename std::enable_if::value, bool>::type -operator!=(T const &lhs, T const &rhs) { - return !(lhs == rhs); -} - -// Less-than-compare any two instances of a handle type. -template -static inline typename std::enable_if::value, bool>::type -operator<(T const &lhs, T const &rhs) { - return lhs.v < rhs.v; -} - -template -struct HandleHasher { - static_assert(IsHandleOracle::value, "Not a valid handle type"); - - inline size_t operator()(const T &h) const { - using Hasher = std::hash; - return Hasher{}(h.v); - } -}; - class Vector; class Vector4; class Point2d; diff --git a/src/handle.h b/src/handle.h new file mode 100644 index 000000000..e247e6083 --- /dev/null +++ b/src/handle.h @@ -0,0 +1,47 @@ +#ifndef SOVLESPACE_HANDLE_H +#define SOVLESPACE_HANDLE_H + +#include +#include + +namespace SolveSpace { + +/// Trait indicating which types are handle types and should get the associated operators. +/// Specialize for each handle type and inherit from std::true_type. +template +struct IsHandleOracle : std::false_type {}; + +// Equality-compare any two instances of a handle type. +template +static inline typename std::enable_if::value, bool>::type +operator==(T const &lhs, T const &rhs) { + return lhs.v == rhs.v; +} + +// Inequality-compare any two instances of a handle type. +template +static inline typename std::enable_if::value, bool>::type +operator!=(T const &lhs, T const &rhs) { + return !(lhs == rhs); +} + +// Less-than-compare any two instances of a handle type. +template +static inline typename std::enable_if::value, bool>::type +operator<(T const &lhs, T const &rhs) { + return lhs.v < rhs.v; +} + +template +struct HandleHasher { + static_assert(IsHandleOracle::value, "Not a valid handle type"); + + inline size_t operator()(const T &h) const { + using Hasher = std::hash; + return Hasher{}(h.v); + } +}; + +} // namespace SolveSpace + +#endif // !SOVLESPACE_HANDLE_H diff --git a/src/param.h b/src/param.h index 69b811cbd..a32aec8ad 100644 --- a/src/param.h +++ b/src/param.h @@ -4,7 +4,7 @@ #include #include -#include "dsc.h" +#include "handle.h" namespace SolveSpace { @@ -39,7 +39,11 @@ class Param { void Clear() {} }; -using ParamList = IdList; +// Use a forward declaration in order to avoid pulling dsc.h in for units that +// don't need to use `ParamList` +template class IdList; + +using ParamList = IdList; using ParamSet = std::unordered_set>; diff --git a/src/srf/surface.h b/src/srf/surface.h index 2ef85ed11..d11716762 100644 --- a/src/srf/surface.h +++ b/src/srf/surface.h @@ -13,6 +13,7 @@ #include #include "dsc.h" +#include "handle.h" #include "polygon.h" namespace SolveSpace { From 68620cffecf75c3b8603aee6331430a0c7b18c35 Mon Sep 17 00:00:00 2001 From: Isaac Garzon Date: Tue, 8 Apr 2025 19:28:17 +0300 Subject: [PATCH 3/3] tests: reduce dependence on `solvespace.h` in order to reduce build time Only include files that are actually needed, instead of using the huge dependency that is `solvespace.h`. --- test/analysis/contour_area/test.cpp | 2 ++ test/constraint/pt_on_circle/test.cpp | 2 ++ test/core/expr/test.cpp | 2 ++ test/core/locale/test.cpp | 2 ++ test/group/translate_asy/test.cpp | 2 ++ test/harness.cpp | 5 ++++- test/harness.h | 5 ++++- test/request/circle/test.cpp | 2 ++ 8 files changed, 20 insertions(+), 2 deletions(-) diff --git a/test/analysis/contour_area/test.cpp b/test/analysis/contour_area/test.cpp index 748f0eb05..eae410d6f 100644 --- a/test/analysis/contour_area/test.cpp +++ b/test/analysis/contour_area/test.cpp @@ -1,3 +1,5 @@ +#include "solvespace.h" + #include "harness.h" TEST_CASE(normal_roundtrip) { diff --git a/test/constraint/pt_on_circle/test.cpp b/test/constraint/pt_on_circle/test.cpp index ce38ba511..3b4c470c6 100644 --- a/test/constraint/pt_on_circle/test.cpp +++ b/test/constraint/pt_on_circle/test.cpp @@ -1,3 +1,5 @@ +#include "solvespace.h" + #include "harness.h" TEST_CASE(normal_roundtrip) { diff --git a/test/core/expr/test.cpp b/test/core/expr/test.cpp index 5e73a0293..bbd117696 100644 --- a/test/core/expr/test.cpp +++ b/test/core/expr/test.cpp @@ -1,3 +1,5 @@ +#include "expr.h" + #include "harness.h" #define CHECK_PARSE(var, expr) \ diff --git a/test/core/locale/test.cpp b/test/core/locale/test.cpp index 46ad9e124..2b0a92b1f 100644 --- a/test/core/locale/test.cpp +++ b/test/core/locale/test.cpp @@ -1,3 +1,5 @@ +#include "ui.h" + #include "harness.h" TEST_CASE(parseable) { diff --git a/test/group/translate_asy/test.cpp b/test/group/translate_asy/test.cpp index 957dccefd..979081d94 100644 --- a/test/group/translate_asy/test.cpp +++ b/test/group/translate_asy/test.cpp @@ -1,3 +1,5 @@ +#include "solvespace.h" + #include "harness.h" TEST_CASE(normal_roundtrip) { diff --git a/test/harness.cpp b/test/harness.cpp index 303324da9..a41db4393 100644 --- a/test/harness.cpp +++ b/test/harness.cpp @@ -4,11 +4,14 @@ // Copyright 2016 whitequark //----------------------------------------------------------------------------- #include +#include #include #include #include #include +#include "solvespace.h" + #include "harness.h" #if defined(WIN32) @@ -19,7 +22,7 @@ namespace SolveSpace { namespace Platform { - // These are defined in headless.cpp, and aren't exposed in solvespace.h. + // These are defined in guinone.cpp, and aren't exposed in solvespace.h. extern std::vector fontFiles; } } diff --git a/test/harness.h b/test/harness.h index fa959000b..91b6d60bb 100644 --- a/test/harness.h +++ b/test/harness.h @@ -3,7 +3,10 @@ // // Copyright 2016 whitequark //----------------------------------------------------------------------------- -#include "solvespace.h" +#include +#include + +#include "platform/platform.h" // Hack... we should rename the ones in ui.h instead. #undef CHECK_TRUE diff --git a/test/request/circle/test.cpp b/test/request/circle/test.cpp index 82cd8781e..9a5d53659 100644 --- a/test/request/circle/test.cpp +++ b/test/request/circle/test.cpp @@ -1,3 +1,5 @@ +#include "solvespace.h" + #include "harness.h" TEST_CASE(normal_roundtrip) {