Constraints UI (FreeCAD)

Ideas for improving the constraints UI in FreeCAD. These are some ideas that I have been thinking about since I first used FreeCAD in 2015.

It is lovely feature of FreeCAD that you can create a 2D drawing by the use of constraints — specifying geometry in terms of relationships such as “line A must be horizontal, the same length as line B, and tangential to arc C”. However, in FreeCAD at the moment this feature is confined to the Sketcher and segregated from the standard drawing tools such as those in the Draft workbench.

I’d like constraints to be available much more generally. On the FreeCAD discussion forum I asked last year if anyone has any grand plans and DanielC asked recently why Draft and Sketcher are separate. I have some ideas about how I think CAD should work, with and without constraints. I decided to expand on my ideas in writing in order to share them and improve them based on other people’s ideas. Maybe I will eventually turn the ideas into working code, or maybe someone else will.

Sketching a Face

The Sketcher documentation says a sketch is intended to be used to draw a single face, perhaps with holes in it, or alternatively to draw a set of features (pockets or pads) on an existing face. This means the sketch should consist of one or more closed and non-intersecting outlines. The Sketcher user interface currently provides no assistance with keeping to this rule: it allows freely scattering any set of disjoint and intersecting lines and even isolated points. Blender, by contrast, features a user interface in which the user can build a complex shape by starting with a simple shape and successively modifying it, at all times choosing actions that maintain the closed shape, never creating arbitrary disconnected or intersecting edges. This style can be seen in Yorik’s Blender tutorial where in step 4 he starts with a small square and by extending it in various ways creates a complex floor plan. That user interface is explicitly modelling a face, whereas Sketcher draws a line drawing which is only implicitly to be thought of as representing a face.

Sketching a face is an important task, and it makes sense to have a user interface that explicitly supports this task. Such a UI would explicitly support drawing a face, by ensuring its boundary line (and those of any holes) remains closed and non-intersecting. It would indicate which area is inside and which is outside, by colouring the area of the face. It would provide more tools which modify the shape of the face directly while keeping it a valid face, like the Blender tools mentioned above, such as the (already existing) fillet tool. It would still support arbitrary lines and points as construction geometry.

Real Physical Shapes

A basic concept is that we usually want to model a real physical shape rather than an abstract mathematical kind of geometry. Regardless whether we are drawing the outline of a single face or a much more general drawing, this has at least two consequences. As a user I expect the sign or handedness of dimensions to be preserved: the right-angle at a convex corner is not the same as the right-angle at a concave corner. And a real object has a non-zero size.

Elements (except points) have non-zero size. Examples:

  • line length != 0 (else degenerate to a point)
  • circle/arc radius != 0 (else degenerate to a point)
  • arc angle != 0 (else degenerate to a point)

Dimension constraints are “signed” and angles are “handed”: there is no ambiguity between positive and negative or left and right. (Failure to apply this principle has led to the “Flipping Problem” documented in this Sketcher tutorial, which has plagued FreeCAD for a long time.)

Signed distance:

  • x-position, y-position
  • x-distance, y-distance
  • point-to-line distance (sign indicates which side of the line the point is on, relative to the line direction)
  • parallel-lines distance (sign indicates which side the second line is on, relative to the first line’s direction)

Signed (or “handed”) angle, with range of a full 360°:

  • absolute orientation
  • arc start and end angles
  • relative angle

Some dimensions are unsigned (just a magnitude):

  • point-to-point distance
  • line length
  • circle/arc radius

Some apparently dimensionless constraints are effectively a signed value, although the magnitude is implied and only the sign is apparent to the user. (See Zero or Special Value Constraints below.) Examples:

  • horizontal, vertical line (sign indicates direction)
  • parallel, tangent (sign indicates relative directions)
  • perpendicular (sign indicates handedness relative to the two directions)

Solving the Flipping Problem

In 2015 I wrote a patch to test the idea of making the constraints signed or handed. To make it simple I implemented all the angle-related constraints, including special cases such as “horizontal” and “vertical”, in terms of the same basic numeric angle constraint code, removing all the optimized implementations of the special cases. The result seemed to robustly preserve topology, exhibiting no flipping.

I didn’t finish it or contribute it back to the project yet. I ought to at least put it in GitHub. Here it is as a patch:

2015-solve-flipping-1.patch

Zero or Special Value Constraints

Some common constraints can be defined as a user-interface alias for a certain value of a dimension constraint. Examples:

  • Coincident <-> point-to-point distance or H- and V-distances = 0
  • Point-On-Line <-> point-to-line distance = 0
  • H-align, V-align <-> V-, H-distance = 0
  • Horizontal, Vertical <-> absolute orientation = 0°, 180°, ±90°
  • Parallel, Perpendicular <-> relative angle = 0°, 180°, ±90°

The system need not remember whether the user entered a zero dimension as numeric zero or by its special name, and the user interface should always show the special name in preference to numeric zero.

The system may prefer to implement each special value constraint either using the general dimension implementation with a value of zero or using a special-case implementation. For example, some comments in the forums indicate that FreeCAD’s constraint solver works well only when the special-case implementations are used.

Basic Constraint Types

A fairly complete set of the most basic constraint types, including both dimensioned forms and zero or special value forms where possible. Note that the current Sketcher UI does not include line-to-line distance.

I have changed some of the icons, such as absolute angle, to better indicate their specific meaning; I would also like to change those for absolute h- and v-position.

Length and Distance

32px-Constraint_Length 32px-Constraint_Radius point-to-point distance / radius

32px-Constraint_HorizontalDistance 32px-Constraint_VerticalDistance absolute h- / v- / h- and v-position

32px-Constraint_HorizontalDistance 32px-Constraint_VerticalDistance h- / v-distance

32px-Constraint_PointOnPointcoincident (point-to-point or h- and v- distance = 0)

point-to-line distance

32px-Constraint_PointOnObject point on line (point-to-line distance = 0)

Constraint_Line_Line_Distance_1 line-to-line distance

32px-Constraint_Tangent tangent (line-to-line distance = 0)

Orientation and Angle

Constraint_AbsoluteAngle_1 absolute angle (orientation)

32px-Constraint_Horizontal 32px-Constraint_Vertical horizontal (abs. angle = 0° or 180°) / vertical (90° or -90°)

relative angle

32px-Constraint_Parallel 32px-Constraint_Perpendicular parallel (rel. angle = 0° or 180°) / perpendicular (90° or -90°)

Basic Relationships

32px-Constraint_EqualLength equal dimension

Complex Relationships

Some examples of more complex relationships. I would not consider these to be basic constraints.

32px-Constraint_Symmetric symmetry around a point (h- and v-distances negative of the other) or line (h- and v-distances related to the other)

32px-Constraint_SnellsLaw Snell’s law relating two angles

Constraint_Parallel_Distance Parallel at a distance (combination of parallel and line-to-line distance)

[-·-] Tangent continuation (combination of tangent and coincident)

User Interface

  • When editing a constraint of a type which has both a dimensioned form and a zero form (e.g. Point Distance From Line and Point On Line), provide an option to switch it to the other form.

Snapping is Constraint (FreeCAD)

Thinking about the Sketcher UI in FreeCAD

Snapping is Temporary Constraint

Sketcher Constraints help us to position a new point coincident with an existing point, or to set the angle of a new line parallel with an existing line, and so on. This relationship is stored, and the actual position is calculated from the relationship.

Draft Snap also helps us to position a new point coincident with an existing point, or to set the angle of a new line parallel with an existing line, and so on. However, only the new position is stored; the fact that this position was determined by a relationship with another object is immediately forgotten.

Notice that there is a lot of overlap in the available kinds of Sketcher constraint and the available kinds of Draft Snap. There are snaps that correspond more or less closely with each kind of constraint, and vice-versa. That should not be surprising.

Coincident 32px-Constraint_PointOnPoint <-> 32px-Snap_Endpoint 32px-Snap_Midpoint 32px-Snap_Center Endpoint / Midpoint / Centre

Point on line 32px-Constraint_PointOnObject <-> 32px-Snap_Near 32px-Snap_Extension Nearest / Extension

Lock X and Y 32px-Sketcher_ConstrainLock <-> 32px-Snap_Grid Grid intersection

Horizontal / Vertical 32px-Constraint_Horizontal 32px-Constraint_Vertical <-> 32px-Snap_Ortho Orthogonal

Parallel / Perpendicular 32px-Constraint_Parallel 32px-Constraint_Perpendicular <-> 32px-Snap_Parallel 32px-Snap_Perpendicular Parallel / Perpendicular

Both Snapping and Constraints have the same purpose: to determine the placement (position and/or orientation) of an object in terms of a relationship with either another object or the world coordinate system. The difference is that a constraint is stored in terms of its definition, whereas with snapping only the resulting placement is stored.

Snapping implies that there is some significant feature to snap to, and that the user wants the new object to have this relationship to that existing feature. A useful, intuitive behaviour would be:

  • snapping is available for every kind of constraint that relates to existing geometry
  • snapping always produces a stored constraint (if the user wants it)

In Sketcher there is an auto-constraint option that produces a stored constraint automatically for some kinds of constraint, including coincident point, point on line, tangent, horizontal, vertical; but not parallel, perpendicular, equal length, etc. One or more icons appear near the cursor to indicate what kind of constraint will be produced.

Sketcher also performs some limited snapping (to a point and to a grid intersection only, AFAICT). Like with Draft Snap, it just stores the resulting position (with no constraints applied) when snapping takes place and auto-constraint is not enabled.

For the record, a couple more features are closely related to constraints:

  • temporarily constraining movement to an axis during an operation such as Move is much the same thing as snapping, and likewise should generate a stored constraint
  • a Draft Dimension is similar to a non-driving constraint

How It Should Work

This is what I’d like to have.

  • Draft and Sketcher should both support snapping in the same way and with all the types of snap;
  • every type of snap should be able to produce a (stored) constraint in Sketcher;
  • consistent naming and icons between snapping and constraints, and between Draft and Sketcher;
  • consistency between Draft Dimensions and Sketcher Dimension Constraints (both driving and non-driving).

Snapping should be an easy, fast and intuitive method of entering most constraints.

 

Boot Rack

BootRack-Drawing2-Sample

Ever since we moved here I’ve been wanting to build something out of wood. A boot rack for the porch is an ideal first project. I’d love to build a solid, heavy work bench first, which would make all future woodworking much easier than using the garden wall as a sawing horse, but I chose to make this first. It can serve as a practise piece: a boot rack will immediately be useful even if it’s a bit rough around the edges or indeed all over, whereas a wobbly work bench would be worthless.

Isometric Delight

Searching for graph paper in my stationery drawer I came across an old pad of isometric drawing paper. What a delight! Sketching ideas and making neat scale drawings on that was as much fun as building the thing.

Of course I want to make drawings like these on the computer as well. One of the most exciting things computers could do, for me as a teenager, was CAD. I had lots of ideas about how my own CAD program would work. I recall programming a snap-to-nearest-point feature, in a mixture of BASIC and Z80 assembly language, which was very satisfying. Nowadays we have 3D CAD, even in the Open Source Software world where the best 3D modelling software by far is the truly excellent Blender. Its emphasis is on artistic rendering, whereas in second place is FreeCAD which is more suited to designing mechanical parts, and includes a constraint-based 2D drawing capability (“this line shall be the same length as that one”, etc.). FreeCAD is quite usable, but both its capabilities and its user interface need a lot of work to match the quality of Blender.

I started using FreeCAD because of the constraint drawing approach and because it looks like it would be fun and feasible to join in with developing it.

In case you are interested, you may download the FreeCAD project file here and open it in FreeCAD. (I was using FreeCAD v0.16.)

BootRack-r722.fcstdBootRack-r722.fcstd

Recycled Wood

I made a list of parts using the wood sizes available from DIY supermarkets, but thinking of my friend Andy who set up the Southampton Wood Recycling Project, I drove over to East Midlands Wood Recycling CIC in Derby to see what they had. From their stock of long pieces I chose rough sawn pine to use for the back legs and bracing batons and a planed, rounded-edge larger piece for the front legs. The staff voluntarily cut the leg pieces into shorter lengths for me. From their main room full of piles of wood, I chose some cedar planks in various widths for the shelves. I liked the cedar because it was already varnished and because it smells lovely, but I have found it rather brittle and weak to be a good choice for shelves. I might add more strengthening batons underneath the front edges to prevent it from snapping when I perch my foot on it to tie my laces.

A Lesson

I learnt a lesson. Mixing many sizes of wood made for much more work than if I’d made all the legs the same size and all the batons the same size.