Tweak docs and add a single blog post
This commit is contained in:
@@ -9,7 +9,7 @@ import clearancePivot from '../../static/img/openscad-tutorial/clearance-pivot.p
|
||||
import rotate from '../../static/img/openscad-tutorial/rotate.png';
|
||||
import readScad from '../../static/img/openscad-tutorial/read-scad.png';
|
||||
|
||||
Since we've started thinking about how the hinge will be assembled with the pin taper, we also need to think about tolerances and clearance gaps. Because we want this hinge to be a "print in place" which mean it prints pre-assembled, we need to add clearance gaps so that our part doesn't print solid!
|
||||
Since we've started thinking about how the hinge will be assembled with the pin taper, we also need to think about tolerances and clearance gaps. Because we want this hinge to be "print in place" which mean it prints pre-assembled, we need to add clearance gaps so that our part doesn't print solid!
|
||||
|
||||
Let start by adding a `clearance` variable and first thing we need to do is extrude our `hingeBodyHalf` slightly less than `hingeLength/2` since there needs to be some play between the two halves.
|
||||
|
||||
@@ -30,6 +30,7 @@ Oh no! there now a gap between our `pin` and `hingeBodyHalf`
|
||||
Here's the fix for that:
|
||||
|
||||
```cpp
|
||||
// highlight-next-line
|
||||
hingeHalfExtrudeLength=hingeLength/2-clearance/2;
|
||||
|
||||
module hingeBodyHalf() {
|
||||
@@ -38,7 +39,9 @@ module hingeBodyHalf() {
|
||||
}
|
||||
|
||||
module pin() {
|
||||
// highlight-next-line
|
||||
translate([0,pivotRadius,hingeHalfExtrudeLength]){
|
||||
// highlight-next-line
|
||||
cylinder(h=hingeLength/2+clearance/2, r1=pinRadius, r2=pinRadius+pinTaper);
|
||||
}
|
||||
}
|
||||
@@ -73,7 +76,7 @@ pin2();
|
||||
<Image img={rotate} style={{backgroundSize: 'contain'}} />
|
||||
|
||||
This is not where we want to leave our pin, but it's a good way to introduce `rotate` as well as using multiple modifiers, i.e. we're using both `translate` and `rotate` together here.
|
||||
`rotate` is similar to `translate` in that it takes an argument `[x, y, z]` but instead of moving it rotates about each of those axes. In the above example of `[0, 45, 0]` it's as if were were to put a pin into the object along the `y` axis and then rotate 45 degrees around that pin.
|
||||
`rotate` is similar to `translate` in that it takes an argument `[x, y, z]` but instead of moving, it rotates about each of those axes. In the above example of `[0, 45, 0]` it's as if were were to put a pin into the object along the `y` axis and then rotate 45 degrees around that pin.
|
||||
|
||||
## How To Read Chained Operations
|
||||
|
||||
|
||||
@@ -81,3 +81,6 @@ within both of the `linear_extrude`s, at first it might seem like we could remov
|
||||
<Image img={noFillet} style={{backgroundSize: 'contain'}} />
|
||||
|
||||
As it needs to be within `offset` group for this fillet to work.
|
||||
|
||||
Okay so we leave it in both `linear_extrude`s but this leaves us in a situation similar to before we introduced variables, in that we have repeated code that would be difficult to determine why to someone reading our code.
|
||||
Well similar to variables we can solve this with `module`s.
|
||||
|
||||
@@ -63,7 +63,7 @@ module plateHoles() {
|
||||
```
|
||||
|
||||
The reason we're using `[0:2]` and not `[0:3]` is because `0` counts so the code still runs 3 times.
|
||||
I've also introduced another function `echo`, this function can be used to display text to the console, we've added it a a temporary measure to help demonstrate that the code in the `for` loop is run multiple times.
|
||||
I've also introduced another function `echo`, this function can be used to display text to the console, we've added it as a temporary measure to help demonstrate that the code in the `for` loop is run multiple times.
|
||||
You should see in the console the following:
|
||||
|
||||
```cpp
|
||||
@@ -119,7 +119,7 @@ module plateHoles() {
|
||||
|
||||
<Image img={hole3} style={{backgroundSize: 'contain'}} />
|
||||
|
||||
Awesome, it obvious that the hole spacing is related to the length of the hinge now, we can even increase the amount of holes with mountingHoleCount=4; and it look correct:
|
||||
Awesome, it obvious that the hole spacing is related to the length of the hinge now, we can even increase the amount of holes with mountingHoleCount=4; and it looks correct:
|
||||
|
||||
<Image img={hole4} style={{backgroundSize: 'contain'}} />
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@ And now we can use the pin as both the hole and the shaft, above is the hole, bo
|
||||
|
||||
<Image img={bothHalves} style={{backgroundSize: 'contain'}} />
|
||||
|
||||
We're still not done with `pin` though! one more thing. Technically we can use the same module `pin` for the hole and shaft, but practically we can't because we having added any clearance between the two.
|
||||
We're still not done with `pin` though! one more thing. Technically we can use the same module `pin` for the hole and shaft, but practically we can't because we haven't added any clearance between the two.
|
||||
If we tried to print these together they would print solid.
|
||||
We can fix this with another argument that makes the hole a bit larger:
|
||||
|
||||
|
||||
@@ -6,8 +6,7 @@ import Image from '@theme/IdealImage';
|
||||
|
||||
import pivot from '../../static/img/openscad-tutorial/pivot.png';
|
||||
|
||||
Okay so we leave it in both `linear_extrude`s but this leaves us in a situation similar to before we introduced variables, in that we have repeated code that would be difficult to determine why to someone reading our code.
|
||||
Well similar to variables we can also define our own `module`s to associate some code with a name. Here's what it looks like.
|
||||
We can also define our own `module`s to associate some code with a name. Here's what it looks like.
|
||||
|
||||
```cpp
|
||||
// highlight-start
|
||||
@@ -70,7 +69,7 @@ hingeBodyHalf();
|
||||
## 3D Primitives
|
||||
|
||||
Next lets work on the pin, ie. what the other half of the hinge will pivot about.
|
||||
We're going to introduced a new function `cylinder` and to get in good habits lets put this immediately in a module that describes what we're making.
|
||||
We're going to introduce a new module `cylinder` and to get in good habits lets put this immediately in a module that describes what we're making.
|
||||
|
||||
```cpp
|
||||
// ... other variables above
|
||||
@@ -94,6 +93,6 @@ pin();
|
||||
|
||||
A couple notes about the above.
|
||||
|
||||
- `cylinder` is the 3d version of `circle` when `h` for height is the length that we would need to extrude `circle` by. It can also take one or two radii, here we're using two because it allows us to add a taper to the pin. The reason why we want to add a taper is because we're stating to think about the assemble of this hinge and if we taper the pin it means the other half of the hinge will be locked on.
|
||||
- `cylinder` is the 3d version of `circle` when `h` for height is the length that we would need to extrude `circle` by. It can also take one or two radii, here we're using two because it allows us to add a taper to the pin. The reason why we want to add a taper is because we're starting to think about the assemble of this hinge and if we taper the pin it means the other half of the hinge will be locked on.
|
||||
- In order to add the taper we've defined two variables `pinRadius` and `pitTaper` when, the latter is extra we add to the second `cylinder` radius.
|
||||
- The `translate` is there move the `cylinder` up so that it's centred with the hinge pivot and along so that it's protruding out of the hinge pivot.
|
||||
|
||||
@@ -69,7 +69,7 @@ We definitely could, but all of the numbers makes it difficult because it's not
|
||||
Have you ever walked into a room only to forget why?
|
||||
You know you came here for a reason but it completely eludes you!? Well reading old code, even only a couple weeks later is a bit like that, you know you put these numbers here for a reason . . .right!
|
||||
|
||||
In programming expressing intent in one of the most important principles for making code understandable and remember what we were doing.
|
||||
In programming expressing intent in one of the most important principles for making code understandable and to remember what we were doing.
|
||||
Isolated values like the ones in our code so far are commonly called "magic numbers" since we can't tell what they do, they might as well be magical.
|
||||
Luckily this can be solved by variables. Variables are a way of giving a number a name, so that we can reference that same number over and over again.
|
||||
This what it looks like in action.
|
||||
|
||||
124
docs/docs/definitive-beginners/wrap-up.mdx
Normal file
124
docs/docs/definitive-beginners/wrap-up.mdx
Normal file
@@ -0,0 +1,124 @@
|
||||
---
|
||||
title: Wrap Up
|
||||
---
|
||||
|
||||
import Image from '@theme/IdealImage';
|
||||
import parametric from '../../static/img/openscad-tutorial/parametric.png';
|
||||
|
||||
We're done coding and here's the final code in full:
|
||||
|
||||
```cpp
|
||||
baseWidth=15;
|
||||
hingeLength=30;
|
||||
baseThickness=3;
|
||||
pivotRadius=5;
|
||||
pinRadius=2;
|
||||
pinTaper=0.25;
|
||||
mountingHoleRadius=1.5;
|
||||
mountingHoleCount=3;
|
||||
mountingHoleEdgeOffset=4;
|
||||
clearance=0.2;
|
||||
tiny=0.005;
|
||||
|
||||
// calculated values
|
||||
hingeHalfExtrudeLength=hingeLength/2-clearance/2;
|
||||
mountingHoleMoveIncrement=(hingeLength-2*mountingHoleEdgeOffset)/
|
||||
(mountingHoleCount-1);
|
||||
|
||||
// modules
|
||||
module hingeBaseProfile() {
|
||||
translate([pivotRadius,0,0]){
|
||||
square([baseWidth,baseThickness]);
|
||||
}
|
||||
}
|
||||
|
||||
module hingeBodyHalf() {
|
||||
difference() {
|
||||
union() {
|
||||
linear_extrude(hingeHalfExtrudeLength){
|
||||
offset(1)offset(-2)offset(1){
|
||||
translate([0,pivotRadius,0]){
|
||||
circle(pivotRadius);
|
||||
}
|
||||
square([pivotRadius,pivotRadius]);
|
||||
hingeBaseProfile();
|
||||
}
|
||||
}
|
||||
linear_extrude(hingeLength){
|
||||
offset(1)offset(-1)hingeBaseProfile();
|
||||
}
|
||||
}
|
||||
plateHoles();
|
||||
}
|
||||
}
|
||||
|
||||
module pin(rotateY, radiusOffset) {
|
||||
translate([0,pivotRadius,hingeHalfExtrudeLength+tiny]){
|
||||
rotate([0,rotateY,0]) {
|
||||
cylinder(
|
||||
h=hingeLength/2+clearance/2,
|
||||
r1=pinRadius+radiusOffset,
|
||||
r2=pinRadius+pinTaper+radiusOffset
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module hingeHalfFemale() {
|
||||
difference() {
|
||||
hingeBodyHalf();
|
||||
pin(rotateY=180, radiusOffset=clearance);
|
||||
}
|
||||
}
|
||||
|
||||
module hingeHalfMale() {
|
||||
translate([0,0,hingeLength]) {
|
||||
rotate([0,180,0]) {
|
||||
hingeBodyHalf();
|
||||
pin(rotateY=0, radiusOffset=0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module plateHoles() {
|
||||
for(i=[0:mountingHoleCount-1]){
|
||||
translate([
|
||||
baseWidth/2+pivotRadius,
|
||||
-baseThickness,
|
||||
i*mountingHoleMoveIncrement+mountingHoleEdgeOffset
|
||||
]){
|
||||
rotate([-90,0,0]){
|
||||
cylinder(r=mountingHoleRadius,h=baseThickness*4);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// using high-level modules
|
||||
hingeHalfFemale();
|
||||
hingeHalfMale();
|
||||
```
|
||||
|
||||
Lets reflect on what you've achieved
|
||||
|
||||
### Parametric
|
||||
|
||||
By diligently using variables instead of hardcoding values, you have create some code that is not only much easier to read and re-use, but it's now parametric by default, which means we can change the value of the variables and the model adjusts
|
||||
Here are some variations:
|
||||
|
||||
<Image img={parametric} style={{backgroundSize: 'contain'}} />
|
||||
|
||||
### Composed of many small well named modules
|
||||
|
||||
By keeping modules small and making lots of them you've also done a great job of making the code easier to read.
|
||||
|
||||
### Included fillets
|
||||
|
||||
By taking extra steps to add fillets to you part, you've made the part stronger and already puts you head and shoulders above many OpenSCAD designs.
|
||||
|
||||
### Print in place
|
||||
|
||||
You've already tackled clearances for getting parts to fit together or print-in-place.
|
||||
|
||||
|
||||
<!-- Now that you up to speed with openscad you might be interested to learn how to host an OpenSCAD project -->
|
||||
@@ -9,10 +9,6 @@ import plainCube from '../../static/img/openscad-tutorial/plain-cube.png';
|
||||
import tallCube from '../../static/img/openscad-tutorial/tall-cube.png';
|
||||
|
||||
|
||||
import parametric from '../../static/img/openscad-tutorial/parametric.png';
|
||||
|
||||
Ready to learn some openSCAD!?
|
||||
|
||||
In order to maximise our learning we're actually going to tackle 3 things, that is feed 3 birds with one scone.
|
||||
|
||||
We're going to learn:
|
||||
@@ -25,11 +21,11 @@ We're going to achieve that by making this cute print-in-place hinge, print in p
|
||||
|
||||
<Image img={hinge} style={{backgroundSize: 'contain'}} />
|
||||
|
||||
This Tutorial makes no assumption about previous knowledge, which means it fine you you haven't done any programming before, we'll walk you through it.
|
||||
This tutorial makes no assumption about previous knowledge, which means it's fine you you haven't done any programming before, we'll walk you through it.
|
||||
If you have done some programming before and prefer a more concise guide that focuses more on OpenSCAD syntax you might prefer the Definitive OpenSCAD Primer instead.
|
||||
|
||||
If you came here from "getting started" then you would have already got a shape on screen with `cube([10,10,10]);`.
|
||||
If you came from elsewhere, open the OpenSCAD desktop app or go to our online editor, and add `cube([10,10,10]);` to get the following cube:
|
||||
If you came here from "[getting started](/docs)" then you would have already got a shape on screen with `cube([10,10,10]);`.
|
||||
If you came from elsewhere, open the OpenSCAD desktop app or go to our [online editor](https://cadhub.xyz/dev-ide/openScad), and add `cube([10,10,10]);` to get the following cube:
|
||||
|
||||
<Image img={plainCube} style={{backgroundSize: 'contain'}} />
|
||||
|
||||
@@ -53,122 +49,3 @@ Before we go any further, now is a good time to mention a couple of principles t
|
||||
6. If you code isn't working, 9 out of 10 times it's because you are missing a semi-colon `;`, all lines apart from ones with curly brace `}` need to end with a semi-colon.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
We'll done, we're done coding and here's the final code in full:
|
||||
|
||||
```cpp
|
||||
baseWidth=15;
|
||||
hingeLength=30;
|
||||
baseThickness=3;
|
||||
pivotRadius=5;
|
||||
pinRadius=2;
|
||||
pinTaper=0.25;
|
||||
mountingHoleRadius=1.5;
|
||||
mountingHoleCount=3;
|
||||
mountingHoleEdgeOffset=4;
|
||||
clearance=0.2;
|
||||
tiny=0.005;
|
||||
|
||||
// calculated values
|
||||
hingeHalfExtrudeLength=hingeLength/2-clearance/2;
|
||||
mountingHoleMoveIncrement=(hingeLength-2*mountingHoleEdgeOffset)/
|
||||
(mountingHoleCount-1);
|
||||
|
||||
// modules
|
||||
module hingeBaseProfile() {
|
||||
translate([pivotRadius,0,0]){
|
||||
square([baseWidth,baseThickness]);
|
||||
}
|
||||
}
|
||||
|
||||
module hingeBodyHalf() {
|
||||
difference() {
|
||||
union() {
|
||||
linear_extrude(hingeHalfExtrudeLength){
|
||||
offset(1)offset(-2)offset(1){
|
||||
translate([0,pivotRadius,0]){
|
||||
circle(pivotRadius);
|
||||
}
|
||||
square([pivotRadius,pivotRadius]);
|
||||
hingeBaseProfile();
|
||||
}
|
||||
}
|
||||
linear_extrude(hingeLength){
|
||||
offset(1)offset(-1)hingeBaseProfile();
|
||||
}
|
||||
}
|
||||
plateHoles();
|
||||
}
|
||||
}
|
||||
|
||||
module pin(rotateY, radiusOffset) {
|
||||
translate([0,pivotRadius,hingeHalfExtrudeLength+tiny]){
|
||||
rotate([0,rotateY,0]) {
|
||||
cylinder(
|
||||
h=hingeLength/2+clearance/2,
|
||||
r1=pinRadius+radiusOffset,
|
||||
r2=pinRadius+pinTaper+radiusOffset
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module hingeHalfFemale() {
|
||||
difference() {
|
||||
hingeBodyHalf();
|
||||
pin(rotateY=180, radiusOffset=clearance);
|
||||
}
|
||||
}
|
||||
|
||||
module hingeHalfMale() {
|
||||
translate([0,0,hingeLength]) {
|
||||
rotate([0,180,0]) {
|
||||
hingeBodyHalf();
|
||||
pin(rotateY=0, radiusOffset=0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module plateHoles() {
|
||||
for(i=[0:mountingHoleCount-1]){
|
||||
translate([
|
||||
baseWidth/2+pivotRadius,
|
||||
-baseThickness,
|
||||
i*mountingHoleMoveIncrement+mountingHoleEdgeOffset
|
||||
]){
|
||||
rotate([-90,0,0]){
|
||||
cylinder(r=mountingHoleRadius,h=baseThickness*4);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// using high-level modules
|
||||
hingeHalfFemale();
|
||||
hingeHalfMale();
|
||||
```
|
||||
|
||||
Lets reflect on what you've achieved
|
||||
|
||||
### Parametric
|
||||
|
||||
By diligently using variables instead of hardcoding values, you have create some code that is not only much easier to read and re-use, but it's now parametric by default, which means we can change the value of the variables and the model adjusts
|
||||
Here are some variations:
|
||||
|
||||
<Image img={parametric} style={{backgroundSize: 'contain'}} />
|
||||
|
||||
### Composed of many small well named modules
|
||||
|
||||
By keeping modules small and making lots of them you've also done a great job of making the code easier to read.
|
||||
|
||||
### Included fillets
|
||||
|
||||
By taking extra steps to add fillets to you part, you've made the part stronger and already puts you head and shoulders above many OpenSCAD designs.
|
||||
|
||||
### Print in place
|
||||
|
||||
You've already tackled clearances for getting parts to fit together or print-in-place.
|
||||
|
||||
Now that you up to speed with openscad you might be interested to learn how to host an OpenSCAD project
|
||||
|
||||
@@ -3,29 +3,33 @@ title: Getting Started
|
||||
slug: /
|
||||
---
|
||||
|
||||
To get started click the "+" button on the top right of CadHub
|
||||
|
||||
import Image from '@theme/IdealImage';
|
||||
import plus from '../../static/img/getting-started/plus.png';
|
||||
import plus from '../../static/img/getting-started/plus.jpg';
|
||||
import openscadSelect from '../../static/img/getting-started/openscad-select.jpg';
|
||||
import ide from '../../static/img/getting-started/ide.png';
|
||||
import cube from '../../static/img/getting-started/cube.jpg';
|
||||
import hinge from '../../static/img/getting-started/complete-hinge.png';
|
||||
|
||||
To get started click the "+" button on the top right of CadHub
|
||||
|
||||
<Image img={plus} style={{backgroundSize: 'contain', paddingBottom: '2rem'}} />
|
||||
<Image img={plus} style={{backgroundSize: 'contain', paddingBottom: '2rem', width: '400px', margin: '0 auto'}} />
|
||||
|
||||
Then select OpenSCAD. Note that [CadQuery](https://cadquery.readthedocs.io/en/latest/) is available too, but OpenSCAD is recomended and the rest of this tutorial is based on OpenSCAD.
|
||||
|
||||
<Image img={openscadSelect} style={{backgroundSize: 'contain', paddingBottom: '2rem', width: '300px', margin: '0 auto'}} size={300} />
|
||||
|
||||
You should now see the OpenSCAD IDE (integrated development environment)
|
||||
|
||||
<Image img={ide} style={{backgroundSize: 'contain'}} />
|
||||
|
||||
Here we should see the default code in the editor on the left-hand-side, there editor is where we design our CAD parts and we'll cover that more soon. You will also see the result will show up on the right-hand-side along with the console which gives us extra information too. You can click and drag inside the viewer to change the perspective, though the image will only update once you let go of the mouse.
|
||||
Here we should see the default code in the editor on the left-hand-side, the editor is where we design our CAD parts and we'll cover that more soon. You will also see the result will show up on the right-hand-side (along with the console which gives us extra information). You can click and drag inside the viewer to change the perspective, though the image will only update once you let go of the mouse.
|
||||
|
||||
You can also move the object with with right-click and drag, and scrolling will zoom in and out.
|
||||
|
||||
### What about the editor?
|
||||
|
||||
For that we'll need to learn about the OpenSCAD language. For now, try replacing all of the existing code with `cube([10,10,10]);` and then hit ctrl+s to tell CadHub to render a new image. You should see a cube appear!
|
||||
For that we'll need to learn about the OpenSCAD language. For now, try replacing all of the existing code with `cube([10,10,10]);` and then hit `ctrl + s` to tell CadHub to render a new image. You should see a cube appear!
|
||||
|
||||
<Image img={cube} style={{backgroundSize: 'contain'}} />
|
||||
|
||||
|
||||
@@ -6,3 +6,7 @@ title: Why OpenSCAD
|
||||
|
||||
OpenSCAD is a Code-CAD, which means models are made from a code script rather than from a series of clicks in a user interface.
|
||||
If you want an un-bias opinion on if this is a good paradigm you'll have to look elsewhere because CadHub are massive advocates for it.
|
||||
|
||||
A quick run down is that you get all the benifits of git version control. It makes reusing cad logic with a team much easier, and if you think of CAD models as a communication medium between colleagues and machine, what better way of storing it than in an auditable script.
|
||||
|
||||
We're going to learn OpenSCAD now over [the alternatives](/blog/curated-code-cad) because not only is it very mature and stable, it's also easy to pick up. Let's get started!
|
||||
|
||||
Reference in New Issue
Block a user