Before this commit, a single chord tolerance was used for both
displaying and exporting geometry. Moreover, this chord tolerance
was specified in screen pixels, and as such depended on zoom level.
This was inconvenient: exporting geometry with a required level of
precision required awkward manipulations of viewport. Moreover,
since some operations, e.g. mesh watertightness checking, were done
on triangle meshes which are generated differently depending on
the zoom level, these operations could report wildly different
and quite confusing results depending on zoom level.
The chord tolerance for display and export pursue completely distinct
goals: display chord tolerance should be set high enough to achieve
both fast regeneration and legible rendering, whereas export chord
tolerance should be set to match the dimension tolerance of
the fabrication process.
This commit introduces two distinct chord tolerances: a display
and an export one. Both chord tolerances are absolute and expressed
in millimeters; this is inappropriate for display purposes but
will be fixed in the next commits.
After exporting, the geometry is redrawn with the chord tolerance
configured for the export and an overlay message is displayed;
pressing Esc clears the message and returns the display back to
normal.
After this commit, SolveSpace can robustly handle non-ASCII filenames
on every OS. Additionally, on Windows, filenames longer than 260
characeters can be used, and files on network shares can be opened
directly, without mounting them as a network drive.
What do we gain from this? Several things.
* First, usage of PATH_MAX (the POSIX constant) is eliminated.
PATH_MAX is actually a lie; Linux and OS X (and probably other BSDs
too) do not have an actual path length limit. Linux claims 4096,
OS X claims 1024, but it is trivial to construct paths that are
longer.
* Second, while Windows does enforce a limit of MAX_PATH (the Win32
constant) for its ASCII functions, the Unicode variants, when
used with UNC paths, do not have this restriction.
The capability to use UNC paths is useful by itself, as it allows
to access files on network shares directly.
* Third, representing paths as std::string will make it easier to
interoperate with *W WinAPI functions later.
This will allow us to use non-POD classes inside these objects
in future and is otherwise functionally equivalent, as well
as more concise.
Note that there are some subtleties with handling of
brace-initialization. Specifically:
On aggregates (e.g. simple C-style structures) using an empty
brace-initializer zero-initializes the aggregate, i.e. it makes
all members zero.
On non-aggregates an empty brace-initializer calls the default
constructor. And if the constructor doesn't explicitly initialize
the members (which the auto-generated constructor doesn't) then
the members will be constructed but otherwise uninitialized.
So, what is an aggregate class? To quote the C++ standard
(C++03 8.5.1 §1):
An aggregate is an array or a class (clause 9) with no
user-declared constructors (12.1), no private or protected
non-static data members (clause 11), no base classes (clause 10),
and no virtual functions (10.3).
In SolveSpace, we only have to handle the case of base classes;
Constraint and Entity have those. Thus, they had to gain a default
constructor that does nothing but initializes the members to zero.
The SolveSpace top-level directory was getting a bit cluttered, so
following the example of numerous other free-software projects, we move the
main application source into a subdirectory and adjust the build systems
accordingly.
Also, got rid of the obj/ directory in favor of creating it on the fly in
Makefile.msvc.