{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 4.1.2 CSG in 2D\n",
    "\n",
    "An alternative approach to SplineGeometry is the new CSG2d interface, which allows using constructive solid geometry definitions (similar to 3D).\n",
    "\n",
    "This feature is new and currently has some limitations compared to `SplineGeometry`, like periodic boundaries."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "## First Example"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from netgen.geom2d import CSG2d, Circle, Rectangle\n",
    "\n",
    "geo = CSG2d()\n",
    "\n",
    "# define some primitives\n",
    "circle = Circle( center=(0,0), radius=1.0, mat=\"mat1\", bc=\"bc_circle\" )\n",
    "rect = Rectangle( pmin=(0,0), pmax=(1.5,1.5), mat=\"mat2\", bc=\"bc_rect\" )\n",
    "\n",
    "# use operators +, - and * for union, difference and intersection operations\n",
    "domain1 = circle - rect\n",
    "domain2 = circle * rect\n",
    "domain2.Mat(\"mat3\").Maxh(0.1) # change domain name and maxh\n",
    "domain3 = rect-circle\n",
    "\n",
    "# add top level objects to geometry\n",
    "geo.Add(domain1)\n",
    "geo.Add(domain2)\n",
    "geo.Add(domain3)\n",
    "\n",
    "# generate mesh\n",
    "m = geo.GenerateMesh(maxh=0.3)\n",
    "\n",
    "# use NGSolve just for visualization\n",
    "from ngsolve.webgui import Draw\n",
    "from ngsolve import Mesh, VOL\n",
    "mesh = Mesh(m)\n",
    "mesh.Curve(3)\n",
    "cf = mesh.RegionCF(VOL, dict(mat1=0, mat2=4, mat3=7)) \n",
    "Draw(cf, mesh)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Solid2d class\n",
    "\n",
    "Internally, there is just one solid type (`Solid2d`), containing a closed chain of quadratic spline segments. For convenience, there are a few helper Functions, like `Rectangle` and `Circle` used above.\n",
    "\n",
    "The general constructor of `Solid2d` expects a list of points. To define curved segments and set individual edge propierties (like boundary condition name and maxh), you can put `EdgeInfo` objects between two points, or a `PointInfo` object after a Point."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from netgen.geom2d import EdgeInfo as EI, PointInfo as PI, Solid2d\n",
    "\n",
    "geo = CSG2d()\n",
    "\n",
    "rect = Solid2d( [\n",
    "    (0,0),\n",
    "    (1,0),\n",
    "    PI(maxh=0.02),   # set maxh at point (1,0)\n",
    "    EI(bc=\"right\"),  # set bc for segment (1,0)-(1,1)\n",
    "    (1,1),\n",
    "    (0,1),\n",
    "    EI(maxh=0.05)    # set maxh for segment (0,1)-(0,0)\n",
    "  ], mat=\"rect\" )\n",
    "\n",
    "circle = Solid2d( [\n",
    "    (0, -1),\n",
    "    EI(( 1,  -1)), # control point for quadratic spline\n",
    "    (1,0),\n",
    "    EI(( 1,  1), maxh=0.05), # spline with maxh\n",
    "    (0,1),\n",
    "    EI((-1,  1)),\n",
    "    (-1,0),\n",
    "    EI((-1, -1), bc=\"left\"), # spline with bc\n",
    "    ])\n",
    "\n",
    "# Solid2d has some methods to change it in-place:\n",
    "# Move(), Scale() and Rotate()\n",
    "circle.Scale(0.5).Move((2,0))\n",
    "circles = circle + circle.Copy().Move((-3,0))\n",
    "\n",
    "rect.Rotate(45, center=(0.5,0.5))\n",
    "\n",
    "geo.Add(rect)\n",
    "geo.Add(circles)\n",
    "\n",
    "mesh = Mesh(geo.GenerateMesh())\n",
    "mesh.Curve(3)\n",
    "print(mesh.GetBoundaries())\n",
    "Draw(mesh)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "help(Solid2d)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "help(PI)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "help(EI)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
