Commit Graph

63 Commits (e2e74762f4dc909876b99decb32f4f9fdb79de83)

Author SHA1 Message Date
whitequark e2e74762f4 Rework path and file operations to be more robust.
This commit updates a *lot* of rather questionable path handling
logic to be robust. Specifically:
  * All path operations go through Platform::Path.
  * All ad-hoc path handling functions are removed, together with
    PATH_SEP. This removes code that was in platform-independent
    parts, but had platform-dependent behavior.
  * Group::linkFileRel is removed; only an absolute path is stored
    in Group::linkFile. However, only Group::linkFileRel is saved,
    with the relative path calculated on the fly, from the filename
    passed into SaveToFile. This eliminates dependence on global
    state, and makes it unnecessary to have separare code paths
    for saved and not yet saved files.
  * In a departure from previous practice, functions with
    platform-independent code but platform-dependent behavior
    are all grouped under platform/. This makes it easy to grep
    for functions with platform-dependent behavior.
  * Similarly, new (GUI-independent) code for all platforms is added
    in the same platform.cpp file, guarded with #ifs. It turns out
    that implementations for different platforms had a lot of shared
    code that tended to go out of sync.
2017-03-11 18:58:53 +00:00
EvilSpirit 6bc2ed9771 Remove nonexistent degrees of freedom from lathe groups.
Before this commit, lathe groups had three DOFs, which of course
could not actually move. After this commit, lathe groups have
zero DOFs, as expected.

This bug was introduced in commit 6dced80.
2017-02-17 03:01:45 +00:00
EvilSpirit ced42440e7 Explicitly represent the parameter used in constraints.
Commit f5485cb and its ancestors add a parameter to some constraints.
This parameter must be materialized and assigned a non-zero value via
ModifyToSatisfy for the solver library to not make unnecessary
changes to the sketch during the initial generation. For this, we
represent it explicitly instead of using hc.param(0), such that
the materialized constraint does not conflict with any user-defined
ones.
2017-02-06 13:02:49 +00:00
EvilSpirit 9148d0cb91 Force DOF check every time a constraint is added.
Before this commit, it was possible to add some redundant constraints
(e.g. vertical, horizontal or midpoint) without failing the sketch,
because SolveBySubstitution() removed the redundant equations.
However, this could result in the solve failing later because
the system didn't converge, without any pointers as to the true
cause of the failure.
2016-12-21 19:40:33 +00:00
EvilSpirit 727c0a97dc Draw projected lines for pt-line-distance constraints in 3d. 2016-12-21 18:43:42 +00:00
EvilSpirit f5485cbf24 Rewrite equations generated for same-orientation constraints.
This has the same motivations and implementation as in 3d6d873.
2016-11-27 14:25:50 +00:00
EvilSpirit 3d6d873906 Rewrite equations generated for parallel constraints (in 3d).
Before this commit, parallel constraints in 3d are fragile:
constraints that are geometrically fine can end up singular anyway
because VectorsParallel() pivots wrong but converges anyway.
After this commit, much like in cc07058, the constraints are written
in a different form: instead of trying to remove two degrees of
freedom out of three, all three are removed, and one added; namely,
the constraint introduces a free parameter, signed length ratio.
2016-11-27 13:43:48 +00:00
EvilSpirit cc07058e48 Rewrite equations generated for pt-on-line constraints.
Before this commit, pt-on-line constraints are buggy. To reproduce,
extrude a circle, then add a datum point and constrain it to the
axis of the circle, then move it. The cylinder will collapse.

To quote Jonathan:

> On investigation, I (a) confirm that the problem is
> the unconstrained extrusion depth going to zero, and (b) retract
> my earlier statement blaming extrude and other similar non-entity
> parameter treatment for this problem; you can easily reproduce it
> with a point in 3d constrained to lie on any line whose length
> is free.
>
> PT_ON_LINE is written using VectorsParallel, for no obvious reason.
> Rewriting that constraint to work on two projected distances (using
> any two basis vectors perpendicular to the line) should fix that
> problem, since replacing the "point on line in 3d" constraint with
> two "point on line in 2d" constraints works. That still has
> the hairy ball problem of choosing the basis vectors, which you
> can't do with a continuous function; you'd need Vector::Normal()
> or equivalent.
>
> You could write three equations and make the constraint itself
> introduce one new parameter for t. I don't know how well that
> would work numerically, but it would avoid the hairy ball problem,
> perhaps elegant at the cost of speed.

Indeed, this commit implements the latter solution: it introduces
an additional free parameter. The point being coincident with
the start of the line corresponds to the parameter being zero, and
point being coincident with the end corresponds to one).

In effect, instead of constraining two of three degrees of freedom
(for which the equations do not exist because of the hairy ball
theorem), it constrains three and adds one more.
2016-11-26 19:35:38 +00:00
whitequark 74cb1f589c Add two more points to the TTF text request.
These points can be used for constraining the width of the text
(or to the width of the text).

The main parts of the commit are:
  * TtfFont is restructured to be able to return the aspect ratio
    for a given string.
  * This aspect ratio is written to the savefile, such that even if
    the font is missing, the sketch would still be solved correctly.
  * The two additional points are constrained via perpendicularly
    to the two main points (which form a v vector).

The compatibility features are as follows:
  * When the font is missing in old files, 1:1 aspect ratio is used,
    which works for the replacement symbol anyhow.
  * When the two additional points are missing in old files, their
    would-be positions are calculated and they are moved there,
    avoiding 'jumping' of underconstrained sketches.
2016-11-02 09:22:18 +00:00
EvilSpirit b37aba00e2 Preserve stipple phase across separate piecewise linear segments.
This significantly increases visual clarity, especially for curves
with a low chord tolerance value.
2016-10-13 23:15:35 +00:00
EvilSpirit 6658b1fa2b Allow combining extrude, lathe, translate and rotate group as assemblies.
This significantly improves performance e.g. in case of a sketch
containing a multitude of wooden panels, as the meshes can be
merely transformed instead of being joined.
2016-10-12 22:02:38 +00:00
EvilSpirit df83ee4c8f Factor out Style::Stroke. 2016-10-11 23:32:05 +00:00
whitequark 6e860fb148 Make "Show/hide hidden lines" a tri-state button instead.
The states are:
  * Draw all lines (on top of shaded mesh).
  * Draw occluded (by shaded mesh) lines as stippled.
  * Do not draw occluded (by shaded mesh) lines.

As usual, the export output follows the screen output.
2016-08-13 09:44:08 +00:00
whitequark 4b4944264b Align constraint lines to pixel grid.
This ensures that constraints always look crisp, no matter the camera
position.
2016-08-07 17:33:27 +00:00
whitequark 8960ee365a Add a new renderer that prepares geometry for 2d backends.
SurfaceRenderer is a new renderer implementing the Canvas interface
running entirely on the CPU; it projects strokes and triangles
in the exact same way as OpenGL would, and it can be used for
rendering into raster or vector 2d surfaces.
2016-08-01 00:48:37 +00:00
EvilSpirit 7f411d1593 Unify displayEdges and displayOutlines.
This has the following benefits:
  * Less geometry to generate; we can do both in one pass;
  * Less geometry to draw;
  * Eliminate overdraw of outlines on top of emphasized edges;
  * In future, being able to seamlessly stitch stippled lines.

The contour edges are now also drawn before emphasized edges;
this makes intersections of contour and emphasized edges look better
as the thinner emphasized edge doesn't clobber the depth buffer.
2016-07-23 22:41:16 +00:00
whitequark e7c8c1c8f2 Abstract all (ex-OpenGL) drawing operations into a Canvas interface.
This has several desirable consequences:
  * It is now possible to port SolveSpace to a later version of
    OpenGL, such as OpenGLES 2, so that it runs on platforms that
    only have that OpenGL version;
  * The majority of geometry is now rendered without references to
    the camera in C++ code, so a renderer can now submit it to
    the video card once and re-rasterize with a different projection
    matrix every time the projection is changed, avoiding expensive
    reuploads;
  * The DOGD (draw or get distance) interface is now
    a straightforward Canvas implementation;
  * There are no more direct references to SS.GW.(projection)
    in sketch rendering code, which allows rendering to multiple
    viewports;
  * There are no more unnecessary framebuffer flips on CPU on Cocoa
    and GTK;
  * The platform-dependent GL code is now confined to rendergl1.cpp.
  * The Microsoft and Apple headers required by it that are prone to
    identifier conflicts are no longer included globally;
  * The rendergl1.cpp implementation can now be omitted from
    compilation to run SolveSpace headless or with a different
    OpenGL version.

Note these implementation details of Canvas:
  * GetCamera currently always returns a reference to the field
    `Camera camera;`. This is so that a future renderer that caches
    geometry in the video memory can define it as asserting, which
    would provide assurance against code that could accidentally
    put something projection-dependent in the cache;
  * Line and triangle rendering is specified through a level of
    indirection, hStroke and hFill. This is so that a future renderer
    that batches geometry could cheaply group identical styles.
  * DrawPixmap and DrawVectorText accept a (o,u,v) and not a matrix.
    This is so that a future renderer into an output format that
    uses 2d transforms (e.g. SVG) could easily derive those.

Some additional internal changes were required to enable this:
  * Pixmap is now always passed as std::shared_ptr<{const ,}Pixmap>.
    This is so that the renderer could cache uploaded textures
    between API calls, which requires it to capture a (weak)
    reference.
  * The PlatformPathEqual function was properly extracted into
    platform-specific code. This is so that the <windows.h> header
    could be included only where needed (in platform/w32* as well
    as rendergl1.cpp).
  * The SBsp{2,3}::DebugDraw functions were removed. They can be
    rewritten using the Canvas API if they are ever needed.

While no visual changes were originally intended, some minor fixes
happened anyway:
  * The "emphasis" yellow line from top-left corner is now correctly
    rendered much wider.
  * The marquee rectangle is now pixel grid aligned.
  * The hidden entities now do not clobber the depth buffer, removing
    some minor artifacts.
  * The workplane "tab" now scales with the font used to render
    the workplane name.
  * The workplane name font is now taken from the normals style.
  * Workplane and constraint line stipple is insignificantly
    different. This is so that it can reuse the existing stipple
    codepaths; rendering of workplanes and constraints predates
    those.

Some debug functionality was added:
  * In graphics window, an fps counter that becomes red when
    rendering under 60fps is drawn.
2016-07-23 22:31:18 +00:00
whitequark faa84c61cf Add SHORT_DASH stipple pattern. 2016-05-27 11:41:17 +00:00
EvilSpirit 73d82a6347 Load actual factory default, not saved style, when requested. 2016-05-26 15:49:46 +00:00
whitequark 8aab0160d3 Refactor EntReqTable to not special-case last row.
Simplify it a bit while we're at it.
2016-05-26 12:43:52 +00:00
whitequark 1249f8496e Enable exhaustive switch coverage warnings as an error, and use them.
Specifically, this enables -Wswitch=error on GCC/Clang and its MSVC
equivalent; the exact way it is handled varies slightly, but what
they all have in common is that in a switch statement over an
enumeration, any enumerand that is not explicitly (via case:) or
implicitly (via default:) handled in the switch triggers an error.

Moreover, we also change the switch statements in three ways:

  * Switch statements that ought to be extended every time a new
    enumerand is added (e.g. Entity::DrawOrGetDistance(), are changed
    to explicitly list every single enumerand, and not have a
    default: branch.

    Note that the assertions are kept because it is legal for
    a enumeration to have a value unlike any of its defined
    enumerands, and we can e.g. read garbage from a file, or
    an uninitialized variable. This requires some rearranging if
    a default: branch is undesired.

  * Switch statements that ought to only ever see a few select
    enumerands, are changed to always assert in the default: branch.

  * Switch statements that do something meaningful for a few
    enumerands, and ignore everything else, are changed to do nothing
    in a default: branch, under the assumption that changing them
    every time an enumerand is added or removed would just result
    in noise and catch no bugs.

This commit also removes the {Request,Entity,Constraint}::UNKNOWN and
Entity::DATUM_POINT enumerands, as those were just fancy names for
zeroes. They mess up switch exhaustiveness checks and most of the time
were not the best way to implement what they did anyway.
2016-05-26 12:43:52 +00:00
EvilSpirit f33ddc94fb Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:

  class Foo {
    enum { X = 1, Y = 2 };
    int kind;
  }
  ... foo.kind = Foo::X; ...

and convert it to this:

  class Foo {
    enum class Kind : uint32_t { X = 1, Y = 2 };
    Kind kind;
  }
  ... foo.kind = Foo::Kind::X;

(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)

The benefits are as follows:
  * The type of the field gives a clear indication of intent, both
    to humans and tools (such as binding generators).
  * The compiler is able to automatically warn when a switch is not
    exhaustive; but this is currently suppressed by the
      default: ssassert(false, ...)
    idiom.
  * Integers and plain enums are weakly type checked: they implicitly
    convert into each other. This can hide bugs where type conversion
    is performed but not intended. Enum classes are strongly type
    checked.
  * Plain enums pollute parent namespaces; enum classes do not.
    Almost every defined enum we have already has a kind of ad-hoc
    namespacing via `NAMESPACE_`, which is now explicit.
  * Plain enums do not have a well-defined ABI size, which is
    important for bindings. Enum classes can have it, if specified.
    We specify the base type for all enums as uint32_t, which is
    a safe choice and allows us to not change the numeric values
    of any variants.

This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-25 07:17:14 +00:00
whitequark 274233fe08 Eliminate Constraint::dogd.refp.
While we're at it, let's also emphasize both parts of a two-part
constraint to make it easier to find.
2016-05-25 03:22:54 +00:00
whitequark 23ff9fa8d1 Eliminate Entity::dogd.refp. 2016-05-25 03:22:54 +00:00
whitequark 8372154384 Remove unused includingConstruction argument of Entity::GenerateEdges. 2016-05-25 03:22:54 +00:00
whitequark 20d87d93c5 Add const qualifiers to functions where trivially possible.
This will allow us in future to accept `const T &` anywhere it's
necessary to reduce the amount of copying.

This commit is quite conservative: it does not attempt very hard to
refactor code that performs incidental mutation. In particular
dogd and caches are not marked with the `mutable` keyword.
dogd will be eliminated later, opening up more opportunities to
add const qualifiers.

This commit also doesn't introduce any uses of the newly added const
qualifers. This will be done later.
2016-05-25 03:22:54 +00:00
EvilSpirit bbca4cc224 Rewrite declarations of form f(void) as f().
In C++ there is no difference and newly added functions are all
declared as f(), so this brings back consistency.
2016-05-20 12:43:20 +00:00
whitequark ad4a204edf Replace all oops() checks with ssassert()s.
This includes explanation and context for non-obvious cases and
shortens debug cycles when just-in-time debugging is not available
(like on Linux) by immediately printing description of the assert
as well as symbolized backtrace.
2016-05-20 12:38:30 +00:00
EvilSpirit 7b8e8b0b41 DXF: export color as indexed, not RGB.
The version of AutoCAD we advertise is unable to read RGB color, so
software attempting to be compatible with it ignores color attributes.
2016-05-17 11:47:49 +00:00
whitequark e969bc94ad Enable -Wall -Wextra -Wno-unused-parameter on GCC/Clang.
This is good practice and helps to catch bugs. Several changes
were made to accomodate the newly enabled warnings:
  * -Wunused-function:
    * in exposed/, static functions that were supposed to be inlined
      were explicitly marked as inline;
    * some actually unused functions were removed;
  * -Wsign-compare: explicit conversions were added, and in
    the future we should find a nicer way than aux* fields;
  * -Wmissing-field-initializers: added initializers;
  * -Wreorder: reordered properly;
  * -Wunused-but-set-variable: remove variable.

-Wunused-parameter was turned off as enabling it would result in
massive amount of churn in UI code. Despite that, we should enable
it at some point as it has a fairly high SNR otherwise.
2016-05-08 00:01:35 +00:00
whitequark febe0f5282 Rename the old "Import / Assemble" feature to "Link / Assemble".
This better reflects what it does and avoids clashes with the new
DXF import feature.
2016-05-07 05:27:54 +00:00
EvilSpirit a21a327a97 DXF: create certain constraints during import.
Specifically:
  * point-coincident, horizontal and vertical constraints (inferred);
  * point-point and point-line distance, angle, radius and diameter
    constraints (based on DXF dimensions).
2016-05-07 04:02:34 +00:00
EvilSpirit 70d84b30e8 DXF: implement import. 2016-05-07 04:02:34 +00:00
EvilSpirit a8465cbc8a Flip extrusion normal when switching between union and difference.
This is done because a meaningful union extrusion is almost never
a meaningful difference extrusion, and saves a bunch of common
manual work.

To avoid creating invalid sketches this isn't done when there are any
constraints.
2016-05-06 23:07:19 +00:00
whitequark c17f1160dc Allow snapping constraint labels to grid.
This is pretty much the only way to get a sketch with tidily placed
dimensions.
2016-04-23 04:38:32 +00:00
EvilSpirit 92f5bd450c Display angle in the middle of its dimension line, not adjacent.
Less visual clutter and more consistency with distance constraints.
2016-04-16 09:05:21 +00:00
EvilSpirit 07f3ab95e4 Draw extension lines for angle constraints between line segments. 2016-04-16 09:05:21 +00:00
EvilSpirit 24fc65a71c Allow rendering solid outlines using a distinct style.
A new button is added, "Show/hide outline of solid model".

When the outline is hidden, it is rendered using the "solid edge"
style. When the outline is shown, it is rendered using the "outline"
style.

In SolveSpace's true WYSIWYG tradition, the 2d view export follows
the rendered view exactly.

Moreover, shell edges are not rendered anymore, since there is not
much need in them anymore and not drawing them lessens the overlap
between various kinds of lines, which already includes entities,
solid edges and outlines.
2016-04-15 21:53:08 +00:00
EvilSpirit d1a2eb6d18 Allow rendering hidden solid edges using a distinct style.
Before this change, the two buttons "Show/hide shaded model" (S) and
"Show/hide hidden lines" (H) resulted in drawing the following
elements in the following styles:

  Button | Non-occluded | Non-occluded |  Occluded   |   Occluded
  state  | solid edges  |   entities   | solid edges |   entities
 --------+--------------+--------------+-------------+--------------
  !S !H  |              |              | solid-edge  | entity style
 --------+              |              +-------------+--------------
   S !H  |              |              |         invisible
 --------+  solid-edge  | entity style +-------------+--------------
  !S  H  |              |              |             |
 --------+              |              | solid-edge  | entity style
   S  H  |              |              |             |
 --------+--------------+--------------+-------------+--------------

After this change, they are drawn as follows:

  Button | Non-occluded | Non-occluded |  Occluded   |   Occluded
  state  | solid edges  |   entities   | solid edges |   entities
 --------+--------------+--------------+-------------+--------------
  !S !H  |              |              | solid-edge  | entity style
 --------+              |              +-------------+--------------
   S !H  |              |              |         invisible
 --------+  solid-edge  | entity style +-------------+--------------
  !S  H  |              |              |             |
 --------+              |              | hidden-edge |  stippled¹
   S  H  |              |              |             |
 --------+--------------+--------------+-------------+--------------

  ¹ entity style, but the stipple parameters taken from hidden-edge

In SolveSpace's true WYSIWYG tradition, the 2d view export follows
the rendered view exactly.

Also, it is now possible to edit the stipple parameters of built-in
styles, so that by changing the hidden-edge style to non-stippled
it is possible to regain the old behavior.
2016-04-15 21:53:08 +00:00
EvilSpirit 7c60be8203 Remove overlapping line segments when exporting a 2d view.
This adds a new style attribute, "Z-index", which is not currently
displayed and cannot be modified. It may be exposed in the UI later.
2016-04-15 21:53:08 +00:00
EvilSpirit 16ea824456 Allow adding spline points. 2016-04-15 06:11:03 +00:00
EvilSpirit 77d8291216 Allow removing spline points. 2016-04-15 06:11:03 +00:00
EvilSpirit 55e3162a05 When creating a new group, use the color of last requested solid. 2016-04-08 11:21:40 +00:00
EvilSpirit e17a24814b DXF: only export visible constraints. 2016-04-08 10:15:29 +00:00
EvilSpirit 73f28b9731 Make normals and workplanes non-stylable.
This does not seem to have any useful application, and it can
result in odd misrenderings with some styles.
2016-04-08 10:12:28 +00:00
whitequark bda2835e9f Cache bounding boxes.
This results in massive performance improvements for hit testing.
Files with very large amounts of entities (e.g. [1]) inflict
a delay of several seconds between moving the pointer and
highlighting an entity in commit HEAD^^^, whereas in this commit
the delay is barely perceptible.

[1]: http://solvespace.com/forum.pl?action=viewthread&parent=872
2016-03-05 16:48:56 +00:00
EvilSpirit e99eedd7a3 Check entity bounding box before hit testing edges. 2016-03-05 16:48:56 +00:00
EvilSpirit b054b9682a Cache generated bezier curves and edges in Entity. 2016-03-05 16:48:16 +00:00
EvilSpirit a0576e2a50 Allow changing text size for default styles.
This is especially useful for High-DPI displays on non-OS X.
2016-03-05 12:02:13 +00:00
EvilSpirit 96344c85a6 Eliminate DEFAULT_TEXT_HEIGHT from drawing code.
Instead, query the text height for constraint style.
2016-03-05 12:02:13 +00:00