Skip to content

Commit

Permalink
Central-housing segment control.
Browse files Browse the repository at this point in the history
This includes changes to the Concertina, but the configuration has still
not been effectivized to take advantage of the new features.
  • Loading branch information
veikman committed Nov 27, 2020
1 parent a8b8587 commit ca5e0f0
Show file tree
Hide file tree
Showing 8 changed files with 124 additions and 49 deletions.
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,16 @@ version 0.2.0, thus covering only a fraction of the project’s history.
- The longer names, previously optional for MCU shelf sides, are no
longer permitted there.
- Disabled responsiveness to predicted resting key clearance by default.
This can be re-enabled with a new parameter (`use-key-travel`).
This can be re-enabled with a new parameter (`use-key-style`).
- Moved and replaced some (other) parameters:
- Made the `central-housing``adapter``receivers``thickness`
`bridge` parameter a section, with its function inherited by `tangential`
in that new section.
- Renamed MCU shelf `sides` to `rim` to prevent confusion with the
adjacent `bevel` section of parameters, which is indexed by sides
(compass points).
- Replaced central-housing interface settings for `adapter``offset`
with a `segments` map, as for key-cluster walls.
- Bundled designs:
- Stopped including threading on bolts in most models, for faster renders
and reduced sensitivity to printer accuracy.
Expand All @@ -37,6 +39,8 @@ version 0.2.0, thus covering only a fraction of the project’s history.
- Added support for custom key mounting plate size.
- Added a parameter for central-housing interface fastener-receiver radial
thickness.
- Added precise control over segment 1 for each node on the central housing
interface’s adapter.
- Bundled designs:
- Added a configuration fragment for removing the rear housing of the DMOTE.

Expand Down
50 changes: 41 additions & 9 deletions config/concertina/base.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -531,36 +531,50 @@ central-housing:
right-hand-alias: ci-near-base
adapter:
alias: ca-near-base
offset: [4, 0, 0]
segments:
"0": [4, 0, 0]
"1": [-1, 0, 0]
- base:
offset: [45, -55, 15]
adapter:
alias: ca-near-lower-1
offset: [4, 0, 0]
segments:
"0": [4, 0, 0]
"1": [-1, 0, 0]
- base:
offset: [45, -55, 20]
adapter:
alias: ca-near-lower-2
segments:
"1": [-1, 0, 0]
- base:
offset: [45, -55, 45]
right-hand-alias: ci-near-lower-3
adapter:
alias: ca-near-lower-3
segments:
"1": [-1, 0, 0]
- base:
offset: [40, -55, 50]
adapter:
alias: ca-near-lower-4
offset: [10, 0, -2]
segments:
"0": [10, 0, -2]
"1": [-3, 0, 1]
- base:
offset: [0, -55, 90]
right-hand-alias: ci-near-upper-1
adapter:
alias: ca-near-upper-1
segments:
"1": [2, 0, 0]
- base:
offset: [0, -55, 110]
right-hand-alias: ci-near-upper-2
adapter:
alias: ca-near-upper-2
segments:
"1": [2, 0, 0]
# The top, all the same height, with a couple of extra points just for
# the bottom plate mixed in to bring the plate out of the way of the
# bowled main key cluster.
Expand All @@ -569,15 +583,19 @@ central-housing:
right-hand-alias: ci-near-roof
adapter:
alias: ca-near-roof
segments:
"1": [2, 0, 0]
- base:
offset: [35, -35, -10] # Bottom plate only.
adapter:
alias: ca-bottom-1
- base:
offset: [0, -27, 125]
adapter:
offset: [15, 0, 0]
alias: ca-mid-1
segments:
"0": [15, 0, 0]
"1": [1, -1, 0]
- base:
offset: [35, -5, -10] # Bottom plate only.
adapter:
Expand All @@ -586,40 +604,54 @@ central-housing:
offset: [35, 25, 125]
right-hand-alias: ci-far-roof
adapter:
offset: [7, 0, 0]
alias: ca-far-roof
segments:
"0": [7, 0, 0]
"1": [-1, 0, 0]
# The far side, descending:
- base:
offset: [45, 40, 110]
adapter:
alias: ca-far-wall-5
segments:
"1": [-1, 0, 0]
- base:
offset: [45, 40, 60]
adapter:
alias: ca-far-wall-4
segments:
"1": [-1, 0, -1]
- base:
offset: [45, 40, 55]
right-hand-alias: ci-far-wall
adapter:
alias: ca-far-wall-3
offset: [7, 0, 0]
segments:
"0": [7, 0, 0]
"1": [-1, 0, -1]
- base:
offset: [45, 40, 28]
adapter:
alias: ca-far-wall-2
offset: [7, 0, 0]
segments:
"0": [7, 0, 0]
"1": [-1, 0, 1]
- base:
offset: [45, 40, 23]
adapter:
alias: ca-far-wall-1
offset: [2, 0, 0]
segments:
"0": [2, 0, 0]
"1": [-1, 0, 1]
- above-ground: true
base:
offset: [45, 40, -10]
right-hand-alias: ci-far-base
adapter:
alias: ca-far-base
offset: [2, 0, 0]
segments:
"0": [2, 0, 0]
"1": [-1, 0, 0]
# Finally, there’s an “ethereal” point that does not appear in the body or
# the plate but is useful for anchoring key clusters.
- at-ground: false
Expand Down
22 changes: 14 additions & 8 deletions doc/options-central.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ The thickness of the housing and its adapter (if any), in mm.

The `interface` setting is essentially a list of points: Coordinates in space. Each of these points can influence the shape of the central housing itself, its adapter, and/or the shape of its bottom plate.

There are no `body` parameters here (yet). Instead, the question of which bodies will include each item in the list is answered by the properties of each item in the list, including the position of each point. Specifically, the `base` z-axis `offset` coordinate (see below) controls the default values of the following two optional properties, if you omit them:
There are no `body` parameters here. Instead, the question of which bodies will include each item in the list is answered by the properties of each item in the list, including the position of each point. Specifically, the `base` z-axis `offset` coordinate (see below) controls the default values of the following two optional properties, if you omit them:

* `at-ground`: If `true`, or if omitted and the `base` z coordinate is not positive, the item will shape the bottom plate for the central housing, if any.
* `above-ground`: If `true`, or if the `base` z coordinate is not negative, the item will shape the central housing itself as a body. If an adapter is included, the item will shape that too.
Expand All @@ -78,11 +78,13 @@ Those items which are “above ground” determine the shape of each outer edge
* `left-hand-alias` (optional): A symbolic name for this point on the interface. Specifically, `left-hand-alias` will identify the point on the left-hand edge of the housing in its standard orientation.
* `right-hand-alias` (optional): A symbolic name for the point on the right-hand-side edge. Because the right-hand side of the main body of the keyboard is the source of the left-hand side (with `reflect`, hence with a central housing), a `right-hand-alias` has more general utility.

In addition to all properties named thus far, each item in the `interface` list may also include an `adapter` section. This section, and everything in it, is optional and relates to the central housing adapter feature. Briefly, the adapter fits precisely onto each interface of the housing. Here’s what the `adapter` section can contain:
* `offset`: Not to be confused with the base offset, this one is also three-dimensional and in mm. It’s added to the width of the adapter and the base position.
In addition to all properties named thus far, each item in the `interface` list may also include an `adapter` subsection. This section, and everything in it, is optional and relates to the central housing adapter feature, described elsewhere in this document. Briefly, the adapter fits precisely onto each interface of the housing. Here’s what the `adapter` subsection can contain:
* `alias`: A symbolic name for this point on the side of the adapter facing away from the central housing. Notice that the side facing toward the central housing is coterminous with the interface itself, so the corresponding point on it is named by `right-hand-alias`.
* `segments`: A map of integer segment IDs to three-dimensional offsets in mm. In this map, segment 0 refers to the outer shell of the adapter, and any offset provided for it is added to both the width of the adapter and the base position when determining the exact shape of the adapter. Segment 1 refers to the inside of the adapter; any offset provided for it is relative to the sum of the final position of segment 0 and the central housing’s thickness, which acts as a radial inset.

The following example covers only one vertex on the housing and one corresponding vertex on its adapter, and is therefore not a complete interface. That said, it does show all of the properties one item in the `interface` list can have, with realistic values.
`segments` resembles an entry in the `by-key` section of parameters. There are two important differences: Segment IDs other than 0 and 1 cannot be targeted, and because the offset for segment 1 is applied only after housing thickness, it does not provide total and direct control. Notice also that adapter segment offsets refer to global vector space.

The following example covers only one vertex on the housing and two corresponding vertices on its adapter, and is therefore not a complete interface. That said, it does show all of the properties one item in the `interface` list can have, with realistic values.

```
interface:
Expand All @@ -93,10 +95,14 @@ The following example covers only one vertex on the housing and one correspondin
left-hand-alias: housing-side-1L
right-hand-alias: housing-side-1R
adapter:
offset: [10, 0, 0]
alias: adapter-side-1
segments:
"0": [10, 0, 0]
"1": [-1, 0, 0]
```
In this example, the vertex named `adapter-side-1` will be placed 10 mm plus the overall width of the adapter away from `housing-side-1R`, with the adapter covering the intervening distance, so that the shell of the adapter touches both vertices, and the housing only touches one. Given that the `base` z coordinate is zero, both `at-ground` and `above-ground` have their default values and are therefore redundant.
In this example, the vertex named `adapter-side-1` will be placed 10 mm plus the overall width of the adapter away from `housing-side-1R`, with the adapter covering the intervening distance, so that the shell of the adapter touches both vertices, and the housing only touches one. Given that the `base` z coordinate is zero, both `at-ground` and `above-ground` have their default values and are therefore redundant in the example.

The example’s segment-1 offset puts a gradient on the outer face of the adapter, the side facing away from the central housing. Such a gradient can be useful for joining the adapter to key walls with `tweaks`.

Aliases for vertices on the interface itself, as opposed to the adapter, are useful mainly when you anchor features like an MCU holder to the central housing. Doing so, you need to be aware that the central housing has both symmetric and asymmetric properties. Its basic shape, including everything you can determine with `interface`, will be bilaterally symmetric. Adapters and their fasteners, and bottom plates, are also symmetric, except for threaded holes. By contrast, central-housing-specific `tweaks` and MCU holders will only appear on the specific side of the housing that you indicate, breaking symmetry.

Expand All @@ -113,7 +119,7 @@ Here’s an example of a valid, minimal, triangular profile, like a little ridge
```
In this example, the high point in the middle is offset on the x axis, giving the edge of the central housing a slant as seen from infinite y. Notice also that the lowest z coordinate is 0, which places this central housing on the floor, inside the `mask`. This is not required. A lower z coordinate will cause the `mask` to open the bottom of the central housing, which is usually more practical for running wires through the keyboard. Notice that if you do use a lower z coordinate and you still want the two lower points to be included in the central housing as a body, you will need to set `above-ground` to `true`, as an explicit addition to the two items at the extremes.

The DMOTE application uses the `interface` to construct OpenSCAD polyhedrons. OpenSCAD and CGAL have many requirements upon polyhedrons and a carelessly constructed interface will violate them, resulting in a central housing that cannot be rendered or printed. As a rule of thumb, define your interface moving **clockwise** from the point of view of positive infinite x, like the tent example above. Be especially careful with `adapter` offsets on the y and z axes, and try to keep the housing itself more than twice as broad as its wall thickness.
The DMOTE application uses the `interface` to construct OpenSCAD polyhedrons. OpenSCAD and CGAL have many requirements upon polyhedrons and a carelessly constructed interface will violate them, resulting in a central housing that cannot be rendered or printed. As a rule of thumb, define your interface moving **clockwise** from the point of view of positive infinite x, like the tent example above. Be especially careful with `adapter` segment offsets on the y and z axes, and try to keep the housing itself more than twice as broad as its wall thickness.

It may not be obvious why `at-ground` and `above-ground` are mutually independent of one another and of the `base` z coordinate that gives them their default values. The main reason for this design is to allow points that are “ethereal”, appearing in neither body. Ethereal points are similar to `secondaries`, except that unlike `secondaries`, they are influenced by width settings and not tied to other points on the interface. They are intended as anchors for key clusters and tweaks, where their responsiveness to width alone comes in handy as you work out the precise shape of the housing.

Expand All @@ -129,7 +135,7 @@ If this is `true`, add an adapter for the central housing.

### Parameter <a id="adapter-width">`width`</a>

The approximate width of the adapter on each side of the central housing, along its axis (the x axis). Individual points on the adapter can be offset from this width using the `interface` list.
The approximate width of the adapter on each side of the central housing, along its axis (the x axis). Individual points on the adapter can be offset from this width using the `interface` list’s `segments` maps.

### Section <a id="adapter-lip">`lip`</a>

Expand Down
37 changes: 26 additions & 11 deletions src/dactyl_keyboard/cad/body/central.clj
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,8 @@
"Get raw offsets for each point on the interface."
[interface]
[(map #(get-in % [:base :offset] [0 0 0]) interface)
(map #(get-in % [:adapter :offset] [0 0 0]) interface)])
(map #(get-in % [:adapter :segments 0] [0 0 0]) interface)
(map #(get-in % [:adapter :segments 1] [0 0 0]) interface)])

(defn- get-widths
"Get half the width of the central housing and the full width of its
Expand All @@ -150,14 +151,28 @@
[(/ (getopt :central-housing :shape :width) 2)
(getopt :central-housing :adapter :width)])

(defn- resolve-offsets
(defn- resolve-shell-offsets
"Find the 3D coordinates of points on the outer shell of passed interface."
[getopt interface]
(let [[half-width adapter-width] (get-widths getopt)
[base adapter] (get-offsets interface)
[base adapter0 _] (get-offsets interface)
gabel (shift-points base 0 half-width)]
[gabel
(mapv (partial mapv + [adapter-width 0 0]) gabel (shift-points adapter))]))
(mapv (partial mapv + [adapter-width 0 0]) gabel (shift-points adapter0))]))

(defn- resolve-point-offsets
"Find the 3D coordinates of more points on the adapter.
This extends resolve-shell-offsets with points on the inside of the adapter,
which is typically not valid for small subsets of the interface."
[getopt interface]
(let [[_ _ adapter1] (get-offsets interface)
adapter-thickness (getopt :central-housing :shape :thickness)
[gabel adapter-outer] (resolve-shell-offsets getopt interface)]
[gabel
adapter-outer
(mapv (partial mapv +)
(shift-points adapter-outer adapter-thickness)
adapter1)]))

(defn- filter-indexed
"Filter an interface list while annotating it with its source indices."
Expand Down Expand Up @@ -201,16 +216,16 @@
(let [[half-width _] (get-widths getopt)
thickness (getopt :central-housing :shape :thickness)
[cross-indexed items] (index-map interface :above-ground)
[base-offsets _] (get-offsets items)
[right-gabel-outer adapter-outer] (resolve-offsets getopt items)
[base-offsets _ _] (get-offsets items)
[outer adapter0 adapter1] (resolve-point-offsets getopt items)
shift-left (partial shift-points (mirror-shift base-offsets))]
(annotate-interface interface cross-indexed [:points :above-ground]
[:gabel :right 0] right-gabel-outer
[:gabel :right 0] outer
[:gabel :right 1] (shift-points base-offsets thickness half-width)
[:gabel :left 0] (shift-left 0 - half-width)
[:gabel :left 1] (shift-left thickness - half-width)
[:adapter 0] adapter-outer
[:adapter 1] (shift-points adapter-outer thickness))))
[:adapter 0] adapter0
[:adapter 1] adapter1)))

(defn- locate-lip
"Derive 3D coordinates on the adapter lip of the central housing."
Expand All @@ -231,7 +246,7 @@
[getopt interface]
(let [[cross-indexed items] (index-map interface :at-ground)
[gabel adapter] (map (partial mapv #(vec (take 2 %)))
(resolve-offsets getopt items))]
(resolve-shell-offsets getopt items))]
(annotate-interface interface cross-indexed [:points :at-ground]
[:gabel] gabel
[:adapter] adapter)))
Expand All @@ -243,7 +258,7 @@
housing or its floor, except as anchors."
[getopt interface]
(let [[cross-indexed items] (index-map interface (complement :above-ground))
[gabel adapter] (resolve-offsets getopt items)]
[gabel adapter] (resolve-shell-offsets getopt items)]
(annotate-interface interface cross-indexed [:points :ethereal]
[:gabel] gabel
[:adapter] adapter)))
Expand Down
4 changes: 2 additions & 2 deletions src/dactyl_keyboard/param/schema/parse.clj
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,8 @@
:base (map-like {:offset vec
:left-hand-alias keyword
:right-hand-alias keyword})
:adapter (map-like {:offset vec
:alias keyword})})))
:adapter (map-like {:alias keyword
:segments (map-of integer (tuple-of num))})})))

(def central-housing-normal-positions
(tuple-of
Expand Down
6 changes: 3 additions & 3 deletions src/dactyl_keyboard/param/schema/valid.clj
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@
(spec/def ::above-ground boolean?)
(spec/def :three/intrinsic-rotation ::tarmi/point-3d)

(spec/def :central/offset ::tarmi/point-3d)
(spec/def :central/left-hand-alias ::alias)
(spec/def :central/right-hand-alias ::alias)
(spec/def :central/starting-point keyword?)
Expand All @@ -75,6 +74,7 @@
(spec/def :two/offset ::tarmi/point-2d)
(spec/def :three/offset ::tarmi/point-3d)
(spec/def :three/override (spec/coll-of (spec/nilable number?) :count 3))
(spec/def :three/segments (spec/map-of integer? ::tarmi/point-3d))
(spec/def :flexible/offset ::tarmi/point-2-3d)


Expand All @@ -90,10 +90,10 @@
(spec/def ::nameable-spline (spec/coll-of ::spline-point))

(spec/def :central/base
(spec/keys :req-un [:central/offset]
(spec/keys :req-un [:three/offset]
:opt-un [:central/left-hand-alias :central/right-hand-alias]))
(spec/def :central/adapter
(spec/keys :opt-un [:central/offset ::alias]))
(spec/keys :opt-un [:three/segments ::alias]))
(spec/def :central/interface-node
(spec/keys :req-un [:central/base]
:opt-un [:central/adapter ::at-ground ::above-ground]))
Expand Down
Loading

0 comments on commit ca5e0f0

Please sign in to comment.