This post focuses on the preferred design style for new designs. It won’t cover brilliance, scintillation, light return or anything like that, but will instead focus on structuring the cutting steps to achieve the desired outcome.
The main idea is that all steps should be connected in a way that allows changes to be made while keeping the overall design idea intact. While this approach may seem cumbersome at first, it can save you significant time and headaches later. It not only gives the designer greater flexibility in fine-tuning the design, but also benefits the automated optimizer (once it becomes available).
The additional benefit is that the cutting sequence in the final faceting diagram becomes more logical for human cutters to cut.
Design rules
Rule 1:
Minimize cuts at user-specified non-axial angles
What this means is that except for the facets at 0° or 90°, there should ideally be only one cut command at a directly specified angle (at each side of the stone). The angle of all other facets should be derived by Hackagem, for instance by cutting through two meet points.
Rule 2:
Don’t set the depth of the cut to an absolute number, except once for setting the size of the stone, and once for the crown or pavilion.
Similarly to the first rule, specify the logical connections of the design and let Hackagem figure out the depths.
Example: Round Brilliant Cut
Let’s go though the steps to cut a round brilliant following the best practices. We start with:
setSym(6, true)
cut("1", index(3), 42.5, centerPoint())
cut("2", index(3), 90, setSize())
So far, we used one user-specified non-axial angle (42.5°), but already two absolute depths. This may not directly be obvious, but centerPoint()
returns the vector (0, 1, 0) which means we will cut at a depth of 1. Similar with setSize()
. This is still within the rules.
We are now about to cut the pavilion facets, and in the Quick Start Tutorial we used this:
// Copied from the Quick Start Tutorial
setSym(6, true)
cut("1", index(3), 42.5, centerPoint())
cut("2", index(3), 90, setSize())
cut("3", index(0), 41.22, meet("1,2")) // <--- Design Rule Issue !
So, why is this an issue? The problem arises when we change the angle of the first cut — this can result in cutting facet 3 entirely “in the air.” Optimizers in other gem design tools scale the entire crown or pavilion to maintain the shape’s integrity, but those tools don’t allow for optimizing individual facets in an automated way.
We want the following: Cut at base index 0 and through the yellow and green dot.
Want | Have |
---|---|
The yellow point we can get with meet("1,2")
or meetGirdle()
. MeetGirdle without parameters meets the girdle as seen from the first index that will be cut. So our cut command for the third tier can be started with:
cut("3", index(0), meetGirdle(), ...
The green dot is on the line between the red and light blue dot. The blue dot we can get with meet("1")
. The red dot is like the yellow dot but at a different index, we can use e.g. meetGirdle(10)
to get the red dot. The green dot can now be defined as between(meetGirdle(10), meet("1"), 0.7)
. To set the exact position on the line we can use a variable, say c
:
setSym(6, true)
cut("1", index(3), 42.5, centerPoint())
cut("2", index(3), 90, setSize())
let c = 0.70
cut("3", index(0), meetGirdle(), between(meetGirdle(10), meet("1"), c))
The effect of this is:
- Tier 3 will always hit the existing tier 1, as long as 0.0 < c < 1.0
- We can simultaneously and independently optimize the angle of tier 1 & 3.
Alternative:
onEdge()
Rather than using
between()
to determine the second point for the cut, there’s actually a simpler approach in this case. We can select the edge shared by two adjacent faces and specify a point along that edge. This is done by identifying two unique neighboring facets, using their facet names and indices, as follows:let c = 0.70 cut("3", index(0), meetGirdle(), onEdge("1:3", "1:13", c))
The final program, with only two user-specified non-axial angles, and two absolute depths. With two angles and 3 additional variables, this design can be easily modified and optimized.
setIndexGear(96)
setSym(6, true)
let angle_pavilion = 42.5
let angle_crown = 47.0
cut("1", index(3), angle_pavilion, centerPoint())
cut("2", index(3), 90, setSize())
let c = 0.70
cut("3", index(0), meetGirdle(), onEdge("1:3", "1:13", c))
crown()
cut("A", index(3), angle_crown, meet("3").add(girdle))
let c2 = 0.20
cut("B", index(0), meetGirdle(), onEdge("A:3", "A:13", c2))
let c3 = 0.3
cut("C", index(3), meet("A"),
between(point(0, meet("A").y, 0), meet("B"), c3))
cut("D", table(), 0, meet("B"))