Home Manual Packages Global Index Keywords Quick Reference |
    /*
       BOWTIE.I
       Detect bowties, boomerangs, and other topological oddities in
       a quadrilateral mesh.

       $Id$
     */
    /*    Copyright (c) 1994.  The Regents of the University of California.
                        All rights reserved.  */

    func bowtie (rt, zt, ireg)
    /* DOCUMENT map= bowtie(rt, zt)

             or map= bowtie(rt, zt, ireg)
         returns a "bowtie map" for the quadrilateral mesh defined by
         RT, ZT, and (optionally) IREG.  If IREG is present, it should be

         an integer array of the same dimensions as RT and ZT; its first
         row and column are ignored, otherwise each non-zero element of

         IREG marks an existing zone in the mesh.  (An IREG with one fewer
         row and column than RT and ZT will also be accepted.)  If IREG
         is omitted, every zone is presumed to exist.

         The returned MAP is a 2-D integer array with one fewer row and
         column than RT and ZT.  It's values have the following meanings:

              2   marks a convex zone with positive area

    	  1   marks a concave (boomerang) zone with positive area
    	  0   marks a bowtied zone

    	 -1   marks a concave (boomerang) zone with negative area

    	 -2   marks a convex zone with negative area
    	 -9   marks a non-existent zone

         Use the nbow function to print the results.

       SEE ALSO: nbow
     */
    {
      dims= dimsof(rt);
      d= dimsof(zt);

      if (d(1)!=dims(1) || dims(1)!=2 || anyof(dims!=d) ||
          dims(2)<2 || dims(3)<2)

        error, "rt, zt are not quadrilateral mesh coordinates";

      dz1= zt(dif,1:-1);    dr1= rt(dif,1:-1);
      dz2= zt(2:0,dif);     dr2= rt(2:0,dif);
      dz3= zt(dif,2:0);     dr3= rt(dif,2:0);
      dz4= zt(1:-1,dif);    dr4= rt(1:-1,dif);

      a= array(0.0, 4, dimsof(dz1));
      a(1,,)= dz1*dr4 - dz4*dr1;
      a(2,,)= dz1*dr2 - dz2*dr1;
      a(3,,)= dz3*dr2 - dz2*dr3;
      a(4,,)= dz3*dr4 - dz4*dr3;

      map= long(sign(a))(sum,,)/2;

      if (is_void(ireg)) return map;

      if ((d=dimsof(ireg))(1)==2 && d(2)==dims(2) && d(3)==dims(3)) {
        ireg= ireg(2:0, 2:0);
      } else if (d(1)!=2 || d(2)!=dims(2)-1 || d(3)!=dims(3)-1) {

        error, "ireg not conformable with rt, zt arrays";
      }

      if (allof(ireg)) return map;

      map(where(!ireg))= -9;
      return map;
    }

    local nbow_negative ;
    /* DOCUMENT nbow_negative
         default value is 0

         set to 1 to reverse the sense of positive area for the nbow function
     */
    nbow_negative= 0;

    func nbow (rt, zt, ireg, all=)
    /* DOCUMENT nbow, map
             or nbow, file
             or nbow, rt, zt
    	 or nbow, rt, zt, ireg
         prints information about topological oddities in a mesh.

         MAP is a bowtie map as returned by the bowtie function.
         FILE is a binary file containing rt, zt, and ireg arrays.
         RT, ZT and IREG are 2-D arrays defining a quadrilateral mesh.

         The information printed includes the zone index (corner with
         the largest indices) of zones which are concave (boomerangs)
         or bowtied, and of zones with negative area.  You can set

         the global variable nbow_negative to 1 to reverse the default
         sense of positive area.  By default, only the first 10 zones
         in each category are printed; use the all=1 keyword argument

         to print a complete (and maybe very long) list.

       SEE ALSO: bowtie
     */
    {

      if (!is_void(zt)) map= bowtie(rt, zt, ireg);
      else if (is_stream(rt)) {
        f= rt;
        vars= get_vars(f);

        if ((vars(1) && anyof(*vars(1) == "ireg")) ||

    	(vars(2) && anyof(*vars(2) == "ireg"))) ireg= f.ireg;
        else ireg= [];
        map= bowtie(f.rt, f.zt, ireg);
      } else {
        map= rt;
      }

      if (nbow_negative) map= -map;

      list= where2(abs(map)<=2 & map<0);

      _nbow_print, list, "Found %ld zones with negative areas:\n";

      list= where2(map==0);

      _nbow_print, list, "Found %ld bowtied zones:\n";

      list= where2(map==1);

      _nbow_print, list, "Found %ld concave (boomerang) zones:\n";

      list= where(map==2);

      write, format="Found %ld convex, positive area zones\n", numberof(list);
    }

    func _nbow_print (list, format)
    {
      n= numberof(list);
      if (n) {
        list++;
        n/= 2;
        write, format=format, n;
        if (!all && n>10) np= 10;
        else np= n;

        write, format="     k= %3ld   l= %3ld\n", list(1,1:np), list(2,1:np);
        if (np<n)

          write, format="     (%ld more, use all=1 keyword to see them)\n", n-np;
      }
    }