{
 "cells": [
  {
   "cell_type": "markdown",
   "source": [
    "A point light illuminates the grid points on the ground.\n",
    "You can buy the kit [via my Booth site](https://hyrodium.booth.pm/items/5046218)!"
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "![](../assets/stereographicprojection.jpg)"
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "# Load packages"
   ],
   "metadata": {}
  },
  {
   "outputs": [],
   "cell_type": "code",
   "source": [
    "using Luxor\n",
    "using IntervalSets\n",
    "using BasicBSpline\n",
    "using BasicBSplineFitting\n",
    "using StaticArrays\n",
    "using ElasticSurfaceEmbedding"
   ],
   "metadata": {},
   "execution_count": 1
  },
  {
   "cell_type": "markdown",
   "source": [
    "# Compute the embedding shapes\n",
    "## Shape definition"
   ],
   "metadata": {}
  },
  {
   "outputs": [
    {
     "output_type": "execute_result",
     "data": {
      "text/plain": "D (generic function with 1 method)"
     },
     "metadata": {},
     "execution_count": 2
    }
   ],
   "cell_type": "code",
   "source": [
    "ElasticSurfaceEmbedding.𝒑₍₀₎(u¹,u²) = SVector(2*u¹/(1+u¹^2+u²^2), 2*u²/(1+u¹^2+u²^2), (-1+u¹^2+u²^2)/(1+u¹^2+u²^2))\n",
    "n = 10\n",
    "D(i,n) = (-2.0..2.0, 2(i-1)/n..2i/n)"
   ],
   "metadata": {},
   "execution_count": 2
  },
  {
   "cell_type": "markdown",
   "source": [
    "## Strain estimation"
   ],
   "metadata": {}
  },
  {
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "┌ Info: Strain - domain: [-2.0, 2.0]×[0.0, 0.2]\n",
      "└ Predicted: (min: -0.00653530699604614, max: 0.013070613992092282)\n"
     ]
    }
   ],
   "cell_type": "code",
   "source": [
    "show_strain(D(1,n))"
   ],
   "metadata": {},
   "execution_count": 3
  },
  {
   "cell_type": "markdown",
   "source": [
    "## Main computation"
   ],
   "metadata": {}
  },
  {
   "outputs": [],
   "cell_type": "code",
   "source": [
    "steptree = StepTree()\n",
    "for i in 1:10\n",
    "    initial_state!(steptree, D(i,n))\n",
    "    newton_onestep!(steptree, fixingmethod=:fix3points)\n",
    "    newton_onestep!(steptree)\n",
    "    refinement!(steptree, p₊=(0,1), k₊=suggest_knotvector(steptree))\n",
    "    newton_onestep!(steptree)\n",
    "    newton_onestep!(steptree)\n",
    "    pin!(steptree)\n",
    "end"
   ],
   "metadata": {},
   "execution_count": 4
  },
  {
   "cell_type": "markdown",
   "source": [
    "## Helper functions to export svg images"
   ],
   "metadata": {}
  },
  {
   "outputs": [
    {
     "output_type": "execute_result",
     "data": {
      "text/plain": "svector2point (generic function with 1 method)"
     },
     "metadata": {},
     "execution_count": 5
    }
   ],
   "cell_type": "code",
   "source": [
    "function create_bezierpath(C::BSplineManifold{1,(3,),Point})\n",
    "    P = bsplinespaces(C)[1]\n",
    "    k = knotvector(P)\n",
    "    k′ = 3*unique(k) + k[[1,end]]\n",
    "    P′ = BSplineSpace{3}(k′)\n",
    "    C′ = refinement(C,P′)\n",
    "    a′ = controlpoints(C′)\n",
    "    n′ = dim(P′)\n",
    "    m = (n′-1) ÷ 3\n",
    "    bezierpath = BezierPath([BezierPathSegment(a′[3i-2], a′[3i-1], a′[3i], a′[3i+1]) for i in 1:m])\n",
    "    return bezierpath\n",
    "end\n",
    "function svector2point(M::BSplineManifold, unitlength)\n",
    "    P = bsplinespaces(M)\n",
    "    a = controlpoints(M)\n",
    "    a′ = [Point(p[1]*unitlength[1], -p[2]*unitlength[1]) for p in a]\n",
    "    M′ = BSplineManifold(a′, P)\n",
    "    return M′\n",
    "end"
   ],
   "metadata": {},
   "execution_count": 5
  },
  {
   "cell_type": "markdown",
   "source": [
    "## Settings for export"
   ],
   "metadata": {}
  },
  {
   "outputs": [
    {
     "output_type": "execute_result",
     "data": {
      "text/plain": "0.025"
     },
     "metadata": {},
     "execution_count": 6
    }
   ],
   "cell_type": "code",
   "source": [
    "xlims=(-3,3)\n",
    "ylims=(-1,1)\n",
    "unitlength = (200, \"mm\")\n",
    "r = 0.025"
   ],
   "metadata": {},
   "execution_count": 6
  },
  {
   "cell_type": "markdown",
   "source": [
    "## Export all embedded shapes with arcs"
   ],
   "metadata": {}
  },
  {
   "outputs": [],
   "cell_type": "code",
   "source": [
    "mkpath(\"stereographicprojection\")\n",
    "for i in 1:10\n",
    "    M = svector2point(steptree.steps[6i].manifold, unitlength)\n",
    "    D¹ = domain(bsplinespaces(M)[1])\n",
    "    D² = domain(bsplinespaces(M)[2])\n",
    "    u¹s = range(extrema(D¹)...,21)[2:end-1]\n",
    "    u²₋ = minimum(D²)\n",
    "    u²₊ = maximum(D²)\n",
    "\n",
    "    width = (xlims[2] - xlims[1]) * unitlength[1]\n",
    "    height = (ylims[2] - ylims[1]) * unitlength[1]\n",
    "\n",
    "    filepath = joinpath(\"stereographicprojection\", \"embedding-$(i).svg\")\n",
    "    Drawing(width, height, filepath)\n",
    "    origin()\n",
    "    background(\"white\")\n",
    "    sethue(\"red\")\n",
    "\n",
    "    C = M(:,u²₋)\n",
    "    path = create_bezierpath(C)\n",
    "    drawbezierpath(path, :stroke)\n",
    "    C = M(:,u²₊)\n",
    "    path = create_bezierpath(C)\n",
    "    drawbezierpath(path, :stroke)\n",
    "    C = M(2,:)\n",
    "    path = create_bezierpath(C)\n",
    "    drawbezierpath(path, :stroke)\n",
    "    C = M(-2,:)\n",
    "    path = create_bezierpath(C)\n",
    "    drawbezierpath(path, :stroke)\n",
    "\n",
    "    for u¹ in u¹s\n",
    "        k = KnotVector([0,0,0,0,0.25,0.5,0.75,1,1,1,1])\n",
    "        P = BSplineSpace{3}(k)\n",
    "        dim(P)\n",
    "\n",
    "        a = fittingcontrolpoints(t -> M(u¹+r*cospi(t), u²₋+r*sinpi(t)), P)\n",
    "        C = BSplineManifold(a,P)\n",
    "        path = create_bezierpath(C)\n",
    "        drawbezierpath(path, :stroke)\n",
    "\n",
    "        a = fittingcontrolpoints(t -> M(u¹+r*cospi(t), u²₊-r*sinpi(t)), P)\n",
    "        C = BSplineManifold(a,P)\n",
    "        path = create_bezierpath(C)\n",
    "        drawbezierpath(path, :stroke)\n",
    "    end\n",
    "\n",
    "    finish()\n",
    "    preview()\n",
    "\n",
    "    script = read(filepath, String)\n",
    "    lines = split(script, \"\\n\")\n",
    "    lines[2] = replace(lines[2],\"pt\\\"\"=>\"mm\\\"\")\n",
    "    write(filepath, join(lines,\"\\n\"))\n",
    "end"
   ],
   "metadata": {},
   "execution_count": 7
  },
  {
   "cell_type": "markdown",
   "source": [
    "The output files will be saved as `embedding-$(i).svg`.\n",
    "By modifying these files, we can place all of the shapes in yatsugiri-size (八ツ切, approximately 270×390 mm) paper like this:"
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "![](../assets/sgp4.svg)"
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "Cutting and weaving these shape will result the sphere in the top image.\n",
    "Please check the following references for more information."
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "# References\n",
    "- [紙工作で立体射影をつくった話](https://note.com/hyrodium/n/n7b7cf03a7d91)\n",
    "- [立体射影製作キット](https://hackmd.io/@hyrodium/HJsIPNKqo)\n",
    "- [Stereographic projection weaving kit](https://hackmd.io/@hyrodium/H1epn1rRj)\n",
    "- [Further adventures in stereographic projection](https://www.youtube.com/watch?v=lbUOScpu0ws)"
   ],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "---\n",
    "\n",
    "*This notebook was generated using [Literate.jl](https://github.com/fredrikekre/Literate.jl).*"
   ],
   "metadata": {}
  }
 ],
 "nbformat_minor": 3,
 "metadata": {
  "language_info": {
   "file_extension": ".jl",
   "mimetype": "application/julia",
   "name": "julia",
   "version": "1.11.4"
  },
  "kernelspec": {
   "name": "julia-1.11",
   "display_name": "Julia 1.11.4",
   "language": "julia"
  }
 },
 "nbformat": 4
}