Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Chapter 15: Inspecting the Virtual Stone — The stone() API

PART II · CHAPTER 15 Live Polyhedron Reflection · Table & Depth % · Facet Areas & Normals · Optimization Guards

What if your script wants to ask a question about the stone it has cut so far—such as:

  • "What is the current Table Percentage (tablePercentage), Total Depth Percentage (depthPercentage), or Length-to-Width Ratio (lengthWidthRatio)?"
  • "Is the girdle continuous and level around the stone (isGirdleEven, isGirdleOK)?"
  • "How many surviving facets (facetCount) and vertices (vertexCount) are on the stone right now?"

Calling stone() anywhere in an FSL or Lua script captures a live reflection snapshot of the 3D gemstone polyhedron at that exact step in the cutting sequence!


1. Stone-Level Properties Returned by stone()

When you write s = stone() (FSL) or local s = stone() (Lua), the returned object exposes the following overall metrics and arrays:

PropertyTypeDescription
s.nameStringCurrent gemstone title.
s.refractiveIndexNumberActive refractive index (ri).
s.facetCountNumberTotal number of surviving polygon faces on the 3D polyhedron.
s.vertexCountNumberTotal number of unique 3D vertices on the polyhedron.
s.tablePercentageNumberWidth of the flat 0° Table (T) expressed as a percentage of stone width (0–100).
s.depthPercentageNumberTotal stone height divided by stone width (height / width * 100).
s.crownHeightNumberVertical height of the Crown above the girdle plane (as % of width).
s.pavilionDepthNumberVertical depth of the Pavilion below the girdle plane (as % of width).
s.girdleThicknessNumberAverage vertical thickness of the 90° Girdle band (as % of width).
s.lengthWidthRatioNumberRatio of longest horizontal caliper dimension to narrowest (1.0 for rounds/squares).
s.compactnessNumberVolumetric efficiency ratio comparing the polyhedron volume to its bounding box.
s.isGirdleEvenBooleantrue if all girdle segments have consistent vertical height around the stone.
s.isGirdleOKBooleantrue if the girdle forms a valid, closed perimeter without zero-thickness overcuts.
s.verticesArray<Point>List of all unique 3D vertices (Point(x, y, z)) on the polyhedron.
s.facesArray<Face>List of every surviving 3D polygon face on the polyhedron (see below).

2. Inspecting Individual Faces (s.faces)

Each entry f in s.faces represents a single surviving polygon face on the 3D stone:

Face PropertyTypeDescription
f.tierStringTier name that created this facet (e.g., "P1", "C2", "T").
f.indexNumberGear tooth index of this specific facet (e.g., 0, 12, 24).
f.angleNumberMast tilt angle (0°–90°) of the facet.
f.areaNumber3D surface area of the polygon.
f.centroidPoint3D center of mass (Point(x, y, z)) of the facet polygon.
f.normalVectorOutward-pointing unit normal vector (Vector(x, y, z)).
f.verticesArray<Point>Ordered loop of 3D Point vertices around the facet perimeter.
f.isPavilion / f.isCrown / f.isGirdleBooleanRegion classification flags for filtering faces by hemisphere.

3. Interactive Example: Querying Metrics & Enforcing Optimization Constraints

One of the most powerful uses of stone() is combining it with assert() to keep the GPU Performance Optimizer within practical gem-cutting boundaries—for example, ensuring the Table Percentage stays between 45% and 68%, total depth stays below 75%, and the girdle remains valid (s.isGirdleOK)!

Click Run (Ctrl+Enter / Cmd+Enter) in the playground below and look at the Script Output panel to see the live stone() report:

name  = "Stone() Reflection & Constraint Demo"
ri    = 1.76
gear  = 96
color = "#38bdf8"

P1 3 @ 43.00 +/- 1.0 : cp() xx8
G1 3 @ 90.00         : size xx8
P2 0 @ 41.50 +/- 1.5 : gp() x8
C1 3 @ 42.00 +/- 2.0 : mp(P1, P2) + girdle xx8
C2 0 @ 34.50 +/- 1.5 : gp() x8
C3 6 @ 22.00 +/- 1.5 : mp(C1) x8
T  0 @ 0.00          : mp(C2) x1

// Capture live 3D stone snapshot
s = stone()
print("Gem Name:", s.name, "| RI:", s.refractiveIndex)
print("Total Facets:", s.facetCount, "| Vertices:", s.vertexCount)
print("Table %:", Math.round(s.tablePercentage * 10) / 10, "| Depth %:", Math.round(s.depthPercentage * 10) / 10)
print("Girdle OK:", s.isGirdleOK)

// Guardrails enforced during GPU Optimization:
assert(s.isGirdleOK, "Girdle must remain continuous and valid")
assert(s.tablePercentage >= 45.0, "Table became too small (< 45%)")
assert(s.tablePercentage <= 68.0, "Table became too wide (> 68%)")
assert(s.depthPercentage <= 75.0, "Stone became too deep (> 75%)")
-- lua script
name("Stone() Reflection & Constraint Demo")
ri(1.76)
gear(96)
color("#38bdf8")

TierAP("P1", 3, val(43.00, 1.0), cp(), "xx8")
TierAD("G1", 3, 90.00,           size, "xx8")
TierAP("P2", 0, val(41.50, 1.5), gp(), "x8")
TierAP("C1", 3, val(42.00, 2.0), mp("P1", "P2"):add(girdle), "xx8")
TierAP("C2", 0, val(34.50, 1.5), gp(), "x8")
TierAP("C3", 6, val(22.00, 1.5), mp("C1"), "x8")
TierAP("T",  0, 0.00,            mp("C2"), "x1")

-- Capture live 3D stone snapshot
local s = stone()
print("Gem Name:", s.name, "| RI:", s.refractiveIndex)
print("Total Facets:", s.facetCount, "| Vertices:", s.vertexCount)
print("Table %:", math.floor(s.tablePercentage * 10 + 0.5) / 10, "| Depth %:", math.floor(s.depthPercentage * 10 + 0.5) / 10)
print("Girdle OK:", s.isGirdleOK)

-- Guardrails enforced during GPU Optimization:
assert(s.isGirdleOK, "Girdle must remain continuous and valid")
assert(s.tablePercentage >= 45.0, "Table became too small (< 45%)")
assert(s.tablePercentage <= 68.0, "Table became too wide (> 68%)")
assert(s.depthPercentage <= 75.0, "Stone became too deep (> 75%)")

Next, let’s dive into the final chapter of Part II—Chapter 16: Complete Lua Scripting Guide — Loops, Tables & Procedural Cuts—to see how Lua unlocks full algorithmic gemstone design.