1:  // -----------------------------------------------------------
   2:  // --   An Asymptote package for drawing orbitals.
   3:  // --      Free under any GNU public license.
   4:  // --      (C) Copyright: Peter Luschny, 2008
   5:  // --             Version 1 Release 1
   6:  // -----------------------------------------------------------
   7:  // --
   8:  // --  This file is accompanying the package orbital.asy
   9:  // --  and illustrates the use of the struct 'orbital'.
  10:  // --  For more information see
  11:  // --  http://www.luschny.de/math/swing/orbital/orbitaldoc.pdf
  12:  // --
  13:  // -----------------------------------------------------------
  14:  //
  15:  //  The struct Orbital provides 10 application functions.
  16:  //
  17:  //  Two graphical function:
  18:  //
  19:  //     * draw(picture dest=currentpicture, int[] jumps)
  20:  //       Draws an orbital and/or its transformed side by side
  21:  //       or in superposition according to the options set.
  22:  //
  23:  //     * draw(picture dest=currentpicture, int[] j1, int[] j2)
  24:  //       Draws two orbitals as given in one box.
  25:  //       It is required that length(j1) = length(j2).
  26:  //
  27:  //  Jumps may have the values -1 or 0 or 1, at most one
  28:  //  occurrence of 0 is allowed and the sum over all jumps
  29:  //  must be 0.
  30:  //
  31:  //  Eight functions to set the options are provided:
  32:  //
  33:  //     * settransform(string option)
  34:  //       Options:       (Default is "invers".)
  35:  //       -- "revers":   reversing the orbital.
  36:  //       -- "invers":   inverting the orbital.
  37:  //       -- "dual":     first reversing, then inverting.
  38:  //       -- "identity": draw as given
  39:  //       The second draw routine always uses "identity".
  40:  //
  41:  //     * setdisplay(string separate)
  42:  //       Options:        (Default is "inone".)
  43:  //       -- "inone":     all orbitals in one picture.
  44:  //       -- "separate":  two pictures in row.
  45:  //       -- "quad":      four pictures in a square.
  46:  //       The second draw routine always uses "inone".
  47:   
  48:  //     * setplot(string option)
  49:  //       Options:          (Default is "orbandtrans".)
  50:  //       -- "orbonly":     plot only the given orbital.
  51:  //       -- "transonly":   plot only the transformed orbital.
  52:  //       -- "orbandtrans": plot the orbital and its trans.
  53:  //       The second draw routine ignores this option.
  54:  //
  55:  //     * setlabel(string option)
  56:  //       Options:        (Default is "none".)
  57:  //       -- "none":      write no label.
  58:  //       -- "symbolic":  write a symbolic representation.
  59:  //       -- "numeric":   write the primorial of the orbital.
  60:  //       -- "info":      both "symbolic" and "numeric".
  61:  //
  62:  //     * sethome(string option)
  63:  //       Options:       (Default is "bighome".)
  64:  //       -- "nohome":   Set no marker at the homeposition.
  65:  //       -- "tinyhome": Set tiny marker at the homeposition.
  66:  //       -- "bighome":  Set big marker at the homeposition.
  67:  //
  68:  //     * setarrow(bool option)
  69:  //       Options:       (Default is 'false'.)
  70:  //       -- 'true':     Show arrow indicating the orientation.
  71:  //       -- 'false':    Show no arrow.
  72:  //
  73:  //     * setorbpen(pen orbcolor, pen transcolor)
  74:  //       The color of the orbitals and the tranformed
  75:  //       orbital. Default is 'green' and 'orange'.
  76:  //
  77:  //     * setfillpen(pen innercolor, pen outercolor)
  78:  //       The color of the inner and the outer part of the disk.
  79:  //       Default colors are 'gray(0.85)' and 'white'.
  80:  //
  81:  //
  82:  //  How to interpret the output:
  83:  //
  84:  //  All orbitals start in the same position, the 'home
  85:  //  position', and return to it (an orbital path is closed.)
  86:  //
  87:  //  Note the following conventions:
  88:  //
  89:  //  The given orbital runs in the counterclockwise sense (is
  90:  //  mathematically positive oriented) and has by default the
  91:  //  color green. Any transformed orbital runs in the clockwise
  92:  //  sense (is mathematically negative oriented) and has the
  93:  //  default color orange.
  94:  //
  95:  //  In the case that both the orbital and the transformed
  96:  //  orbital are displayed in the same picture, the label and
  97:  //  other visual hints always refer to the original orbital.
  98:  //
  99:  // -----------------------------------------------------------
 100:   
 101:  // Example use of struct Orbital:
 102:   
 103:  import orbital;
 104:  import orbitalgenerator;
 105:   
 106:  // import "YOURPATH/orbital.asy" as orbital;
 107:  // import "YOURPATH/orbitalgenerator.asy" as orbitalgenerator;
 108:   
 109:  // -- The most simple case.
 110:  // -- The orbital and its invers in one picture.
 111:   
 112:  void demo1()
 113:  {
 114:      int[] jump = {1,1,1,-1,-1,-1};
 115:   
 116:      Orbital orb = Orbital(200); // -- size 200
 117:      orb.draw(jump);
 118:   
 119:      shipout("orb1demo", bbox(0.2cm));
 120:  }
 121:   
 122:  // -- The most simple case with some options.
 123:   
 124:  void demo2()
 125:  {
 126:      int[] jump = {1,1,1,0,-1,-1,-1};
 127:   
 128:      Orbital orb = Orbital(200); // -- size 200
 129:   
 130:      // -- Path option
 131:      orb.setplot("orbonly");
 132:   
 133:      // -- Label option
 134:      orb.setlabel("symbolic");
 135:   
 136:      // -- Color options
 137:      pen orbpen = linewidth(6*linewidth())+lightblue;
 138:      orb.setorbpen(orbpen, orbpen);
 139:      orb.sethome("tinyhome");
 140:   
 141:      orb.draw(jump);
 142:   
 143:      shipout("orb2demo", bbox(0.2cm));
 144:  }
 145:   
 146:  // -- The option "seperate":
 147:  // -- The orbital and its invers in two pictures.
 148:   
 149:  void demo3()
 150:  {
 151:      int[] jump = {-1,-1,-1,-1,-1,-1,1,1,1,1,1,1};
 152:   
 153:      Orbital orb = Orbital(200);
 154:   
 155:      orb.setlabel("numeric");
 156:      orb.setdisplay("separate");
 157:      orb.setarrow(true);
 158:      orb.draw(jump);
 159:   
 160:      shipout("orb3demo", bbox(0.25cm));
 161:  }
 162:   
 163:  // -- The option "quad":
 164:  // -- The orbital and all its transformed forms in 4 pictures.
 165:   
 166:  void demo4()
 167:  {
 168:      int[] jump = {-1,-1,-1,1,1,1,1,1,-1,-1};
 169:   
 170:      Orbital orb = Orbital(150);
 171:   
 172:      orb.setlabel("numeric");
 173:      orb.setdisplay("quad");
 174:      orb.draw(jump);
 175:   
 176:      shipout("orb4demo", bbox(0.2cm));
 177:  }
 178:   
 179:  // -- The second form draw:
 180:  // -- Two orbitals as given in one picture.
 181:   
 182:  void demo6()
 183:  {
 184:      int[][]orbits =  {
 185:      {1,  1, -1, -1}, {1, -1, 1, -1},
 186:      {-1, 1, -1,  1}, {-1,-1, 1,  1} } ;
 187:   
 188:      int mag = 100; real margin = 5mm;
 189:      Orbital orb = Orbital(mag);
 190:   
 191:      picture pic1; orb.draw(pic1, orbits[0], orbits[2]);
 192:      picture pic2; orb.draw(pic2, orbits[0], orbits[3]);
 193:      picture pic3; orb.draw(pic3, orbits[1], orbits[2]);
 194:      picture pic4; orb.draw(pic4, orbits[1], orbits[3]);
 195:   
 196:      // -- add to current picture
 197:      size(currentpicture, 4*mag + 3*margin, mag);
 198:   
 199:      add(currentpicture, pic1.fit(),(0,0));
 200:      add(currentpicture, pic2.fit(),(240+margin,0));
 201:      add(currentpicture, pic3.fit(),(480+2*margin,0));
 202:      add(currentpicture, pic4.fit(),(720+3*margin,0));
 203:   
 204:      shipout("orb6demo", bbox(0.2cm));
 205:  }
 206:   
 207:  // -- More colors!
 208:   
 209:  void demo7()
 210:  {
 211:      size(520);
 212:   
 213:      int[][]orbits =  {
 214:      { 1,1,-1,-1}, { 1,-1, 1,-1}, { 1,-1,-1,1},
 215:      {-1,1, 1,-1}, {-1, 1,-1, 1}, {-1,-1, 1,1} } ;
 216:   
 217:      pair[] pos = {(3,1),(3,5/2),(1,4),(5,4),(3,11/2),(3,7)};
 218:   
 219:      void zeige(int i, int k)
 220:      {
 221:          draw(pos[i]--pos[k],black+linewidth(3.6*linewidth()));
 222:      }
 223:   
 224:      zeige(1,0); zeige(2,1); zeige(3,1);
 225:      zeige(4,2); zeige(4,3); zeige(5,4);
 226:   
 227:      Orbital orb = Orbital(1);
 228:      orb.setplot("orbonly");
 229:   
 230:      orb.setfillpen(gray(0.85),cmyk(0.15,0.0,0.69,0.0));
 231:      pen p = cmyk(0.0,1.0,0.0,0.0)+linewidth(4*linewidth());
 232:      orb.setorbpen(p,p);
 233:   
 234:      for(int i = 0; i < 6; ++i)
 235:      {
 236:          pair Z = pos[i];
 237:          picture pic;
 238:          orb.draw(pic, orbits[i]);
 239:          add(scale(8)*pic, Z);
 240:      }
 241:   
 242:      // Needs: import fontsize; but did not work.
 243:      // pen p = Symbol(series="m",shape="n");
 244:      // p = p+fontsize(56)+gray(0.85);
 245:      // label("$\Omega_4$",(3,4),p);
 246:      // Workaround with postscript:
 247:   
 248:      postscript("/inch{ 72 mul 30 sub } def");
 249:      postscript("0.0 0.0 0.0 0.4 setcmykcolor");
 250:      postscript("/Symbol findfont 64 scalefont setfont");
 251:      postscript("2.95 inch 4.1 inch moveto (\127) show");
 252:      postscript("/Symbol findfont 40 scalefont setfont");
 253:      postscript("3.65 inch 3.9 inch moveto (4) show");
 254:   
 255:      shipout("orb7demo", bbox(0.3cm));
 256:  }
 257:   
 258:  /////////////////////////////////////////////////////////////
 259:  //            Usage of generators
 260:  /////////////////////////////////////////////////////////////
 261:   
 262:  void demo8()
 263:  {
 264:       OrbitalGenerator og = OrbitalGenerator(6);
 265:       int n = og.generate();
 266:       write("Orbitals("+(string)6+") = "+(string)n);
 267:  }
 268:   
 269:  void demo9()
 270:  {
 271:      for(int i = 1; i < 7; ++i)
 272:      {
 273:         write();
 274:          write(" Omega("+(string)i +") prime ordered.");
 275:   
 276:          PrimeOrbitalGenerator pog = PrimeOrbitalGenerator(i);
 277:          pog.generate();
 278:          pog.write();
 279:      }
 280:  }
 281:   
 282:  // -- Using the visit hook.
 283:  void myVisit(int[] orb)
 284:  {
 285:     string s;
 286:     for(int o : orb)  { s = s + (string)o + " ";  }
 287:     write(reverse(s) + "  ...my visit...");
 288:  }
 289:   
 290:  void demo10()
 291:  {
 292:      int len = 4, count;
 293:      write("Generate all orbitals of length "+(string)len+" !");
 294:   
 295:      // -- without visit
 296:      OrbitalGenerator og = OrbitalGenerator(len);
 297:      count = og.generate();
 298:   
 299:      write("Orbitals("+(string)len+") = "+(string)count);
 300:      write("  ");
 301:      write("And now processing the orbitals my way!");
 302:   
 303:      // -- with visit
 304:      OrbitalGenerator myog = OrbitalGenerator(len, myVisit);
 305:      count = myog.generate();
 306:   
 307:      write("Orbitals("+(string)len+") = "+(string)count);
 308:  }
 309:   
 310:  // -- ... now the highlight!
 311:  // -- Display all orbitals of length 6 in primorial order.
 312:   
 313:  void demo11()
 314:  {
 315:      PrimeOrbitalGenerator pog = PrimeOrbitalGenerator(6);
 316:      PrimeOrbital[] po = pog.generate();
 317:      pog.write();
 318:   
 319:      Orbital orb = Orbital(1);
 320:      orb.setlabel("info");
 321:      int i = -1;
 322:   
 323:      for(int y = 690; y > 100; y -= 140)
 324:      {
 325:          for(int x = 135; x < 500; x += 110)
 326:          {
 327:              pair Z = (x, y+18);
 328:              picture pic;
 329:              orb.draw(pic, po[++i].jumps);
 330:              add(scale(7)*pic, Z);
 331:          }
 332:      }
 333:      shipout("orb11demo", bbox(1cm));
 334:  }
 335:   
 336:  void test()
 337:  {
 338:      demo1();demo2();demo3();demo4();
 339:      demo6();demo7();demo8();demo9();
 340:      demo10();demo11();    
 341:  }
 342:   
 343:   
 344:  /**********
 345:  0 [1/1]  1
 346:  Orbitals(1) = 1
 347:  
 348:  -1 1 [3/2]  1.50
 349:  1 -1 [2/3]  0.66
 350:  Orbitals(2) = 2
 351:  
 352:  -1 0 1 [5/2]  2.50
 353:  0 -1 1 [5/3]  1.67
 354:  -1 1 0 [3/2]  1.50
 355:  1 -1 0 [2/3]  0.66
 356:  0 1 -1 [3/5]  0.60
 357:  1 0 -1 [2/5]  0.40
 358:  Orbitals(3) = 6
 359:  
 360:  -1 -1 1 1 [35/6]   5.83
 361:  -1 1 -1 1 [21/10]  2.10
 362:  -1 1 1 -1 [15/14]  1.07
 363:  1 -1 -1 1 [14/15]  0.93
 364:  1 -1 1 -1 [10/21]  0.47
 365:  1 1 -1 -1 [6/35]   0.17
 366:  Orbitals(4) = 6
 367:  
 368:  -1 -1 0 1 1 [77/6]  12.80
 369:  -1 -1 1 0 1 [55/6]   9.17
 370:  -1 0 -1 1 1 [77/10]  7.70
 371:  -1 -1 1 1 0 [35/6]   5.83
 372:  0 -1 -1 1 1 [77/15]  5.13
 373:  -1 0 1 -1 1 [55/14]  3.93
 374:  -1 1 -1 0 1 [33/10]  3.30
 375:  0 -1 1 -1 1 [55/21]  2.62
 376:  -1 1 0 -1 1 [33/14]  2.36
 377:  -1 1 -1 1 0 [21/10]  2.10
 378:  -1 0 1 1 -1 [35/22]  1.59
 379:  1 -1 -1 0 1 [22/15]  1.47
 380:  -1 1 1 -1 0 [15/14]  1.07
 381:  0 -1 1 1 -1 [35/33]  1.06
 382:  1 -1 0 -1 1 [22/21]  1.05
 383:  -1 1 0 1 -1 [21/22]  0.95
 384:  0 1 -1 -1 1 [33/35]  0.94
 385:  1 -1 -1 1 0 [14/15]  0.93
 386:  -1 1 1 0 -1 [15/22]  0.68
 387:  1 0 -1 -1 1 [22/35]  0.62
 388:  1 -1 1 -1 0 [10/21]  0.47
 389:  1 -1 0 1 -1 [14/33]  0.42
 390:  0 1 -1 1 -1 [21/55]  0.38
 391:  1 -1 1 0 -1 [10/33]  0.30
 392:  1 0 -1 1 -1 [14/55]  0.25
 393:  0 1 1 -1 -1 [15/77]  0.19
 394:  1 1 -1 -1 0 [6/35]   0.17
 395:  1 0 1 -1 -1 [10/77]  0.13
 396:  1 1 -1 0 -1 [6/55]   0.10
 397:  1 1 0 -1 -1 [6/77]   0.07
 398:  Orbitals(5) = 30
 399:  
 400:  -1 -1 -1 1 1 1 [1001/30] 33.40
 401:  -1 -1 1 -1 1 1 [715/42]  17.00
 402:  -1 -1 1 1 -1 1 [455/66]   6.89
 403:  -1 1 -1 -1 1 1 [429/70]   6.13
 404:  -1 -1 1 1 1 -1 [385/78]   4.94
 405:  1 -1 -1 -1 1 1 [286/105]  2.72
 406:  -1 1 -1 1 -1 1 [273/110]  2.48
 407:  -1 1 -1 1 1 -1 [231/130]  1.78
 408:  -1 1 1 -1 -1 1 [195/154]  1.27
 409:  1 -1 -1 1 -1 1 [182/165]  1.10
 410:  -1 1 1 -1 1 -1 [165/182]  0.90
 411:  1 -1 -1 1 1 -1 [154/195]  0.79
 412:  1 -1 1 -1 -1 1 [130/231]  0.56
 413:  1 -1 1 -1 1 -1 [110/273]  0.40
 414:  -1 1 1 1 -1 -1 [105/286]  0.36
 415:  1 1 -1 -1 -1 1 [78/385]   0.20
 416:  1 -1 1 1 -1 -1 [70/429]   0.16
 417:  1 1 -1 -1 1 -1 [66/455]   0.14
 418:  1 1 -1 1 -1 -1 [42/715]   0.05
 419:  1 1 1 -1 -1 -1 [30/1001]  0.03
 420:  Orbitals(6) = 20
 421:  ****/