{
  "schema": "vextcad.vxl.v1",
  "id": "spiral_vase",
  "title": "Spiral-ribbed vase",
  "units": {
    "length": "mm",
    "angle": "deg"
  },
  "needs": [
    {
      "id": "n_closed",
      "source": "user",
      "text": "The vase is a closed, watertight solid."
    },
    {
      "id": "n_one_piece",
      "source": "user",
      "text": "The vase is one connected piece."
    },
    {
      "id": "n_no_self_intersection",
      "source": "user",
      "text": "The sixteen twisted ridges never make the surface intersect itself."
    },
    {
      "id": "n_size",
      "source": "user",
      "text": "About 93 mm wide and 120 mm tall, standing on a flat base at z = 0."
    },
    {
      "id": "n_wall",
      "source": "user",
      "text": "Walls and floor are at least 1.5 mm thick everywhere."
    },
    {
      "id": "n_mouth",
      "source": "user",
      "text": "The mouth is open: a 30 mm rod passes from inside the vase out through the top."
    }
  ],
  "params": [
    {
      "id": "height",
      "type": "length",
      "value": 120
    },
    {
      "id": "floor_t",
      "type": "length",
      "value": 3
    },
    {
      "id": "wall",
      "type": "length",
      "value": 2.6
    },
    {
      "id": "rib_ratio",
      "type": "unitless",
      "value": 0.0625
    },
    {
      "id": "rib_count",
      "type": "unitless",
      "value": 16
    },
    {
      "id": "twist",
      "type": "angle",
      "value": 330
    }
  ],
  "functions": [
    {
      "id": "body_radius",
      "params": [
        {
          "id": "h",
          "type": "length"
        },
        {
          "id": "top",
          "type": "length"
        }
      ],
      "expr": "30mm + 14mm * sin(250deg * (h / top)) + 14mm * smoothstep(0.78 * top, top, h)",
      "returns": "length"
    },
    {
      "id": "ribs",
      "params": [
        {
          "id": "px",
          "type": "length"
        },
        {
          "id": "py",
          "type": "length"
        },
        {
          "id": "h",
          "type": "length"
        },
        {
          "id": "top",
          "type": "length"
        },
        {
          "id": "ratio",
          "type": "unitless"
        },
        {
          "id": "count",
          "type": "unitless"
        },
        {
          "id": "turn",
          "type": "angle"
        }
      ],
      "expr": "ratio * body_radius(h, top) * (1 - 2 * (sqrt(s * s + 0.0225) - 0.15) / (sqrt(1.0225) - 0.15))",
      "returns": "length",
      "lets": [
        {
          "id": "s",
          "type": "unitless",
          "expr": "sin(0.5 * (count * atan2(py, px) + turn * (h / top)))"
        }
      ]
    }
  ],
  "parts": [
    {
      "id": "vase",
      "rep": "mesh",
      "deliver": "body",
      "steps": [
        {
          "id": "shape",
          "op": "field",
          
          "bind": "shape",
          "expr": {
            "kind": "cut",
            "base": {
              "kind": "intersect",
              "nodes": [
                {
                  "kind": "offset",
                  "node": {
                    "kind": "capsule",
                    "a": [
                      0,
                      0,
                      -60
                    ],
                    "b": [
                      0,
                      0,
                      200
                    ],
                    "radius": 35
                  },
                  "by": "body_radius(z, height) - 35mm + ribs(x, y, z, height, rib_ratio, rib_count, twist)",
                  "amplitude": 13
                },
                {
                  "kind": "box",
                  "center": [
                    0,
                    0,
                    "height / 2"
                  ],
                  "size": [
                    120,
                    120,
                    "2 * (height / 2)"
                  ]
                }
              ]
            },
            "tool": {
              "kind": "intersect",
              "nodes": [
                {
                  "kind": "offset",
                  "node": {
                    "kind": "capsule",
                    "a": [
                      0,
                      0,
                      -60
                    ],
                    "b": [
                      0,
                      0,
                      200
                    ],
                    "radius": 35
                  },
                  "by": "body_radius(z, height) - 35mm - wall + ribs(x, y, z, height, rib_ratio, rib_count, twist)",
                  "amplitude": 16
                },
                {
                  "kind": "box",
                  "center": [
                    0,
                    0,
                    "(floor_t + height + 20) / 2"
                  ],
                  "size": [
                    120,
                    120,
                    "2 * ((height + 20 - floor_t) / 2)"
                  ]
                }
              ]
            }
          }
        },
        {
          "id": "surface",
          "op": "extract",
          
          "source": "shape",
          "bind": "body",
          "mode": "dense",
          "grid": {
            "origin": [
              -48.4,
              -48.4,
              -1.2
            ],
            "voxel": [
              0.8,
              0.8,
              0.8
            ],
            "dims": [
              122,
              122,
              155
            ]
          }
        }
      ]
    }
  ],
  "requirements": [
    {
      "id": "r_closed",
      "kind": "closed_delivered_mesh",
      "subject": "vase",
      "covers": [
        "n_closed"
      ]
    },
    {
      "id": "r_one_piece",
      "kind": "component_count",
      "subject": "vase",
      "count": 1,
      "covers": [
        "n_one_piece"
      ]
    },
    {
      "id": "r_no_self_intersection",
      "kind": "self_intersection_free",
      "subject": "vase",
      "covers": [
        "n_no_self_intersection"
      ]
    },
    {
      "id": "r_size",
      "kind": "envelope",
      "subject": "vase",
      "bounds": {
        "min": [
          -46.75,
          -46.75,
          0
        ],
        "max": [
          46.75,
          46.75,
          120
        ]
      },
      "tol": 0.8,
      "covers": [
        "n_size"
      ]
    },
    {
      "id": "r_wall",
      "kind": "minimum_wall_mesh",
      "subject": "vase",
      "min": 1.5,
      "covers": [
        "n_wall"
      ]
    },
    {
      "id": "r_mouth",
      "kind": "opening",
      "subject": "vase",
      "at": [
        0,
        0,
        0
      ],
      "axis": "z",
      "diameter": 30,
      "span": [
        "floor_t + 2",
        "height + 10"
      ],
      "covers": [
        "n_mouth"
      ]
    }
  ]
}