convex hull example script

The following script can be used for a simple convex hull with only one ring. With iterations the number of points can be simplified.

container Simplified := Simplify(iter_domain, 50);  // domain and number of iterations 
 
template Simplify
{
   // begin case parameters
   unit<uint32> iter_domain;
   parameter<uint32> nrIterations;
   // end case parameters
   
   unit<uint32> iter := range(uint32, 0, nrIterations)
   {
      attribute<string> name     := 'I' + string(id(.));
      attribute<string> PrevName := MakeDefined(name[id(.)-1], 'StartingState');
   }

   container StartingState 
   {
      unit<uint32> NextValue := sequence2points(iter_domain/geometry_rd);
   }

   container Iters     := for_each_ne(Iter/name, 'IterT('+Iter/PrevName+', iter_domain)');
   container LastIterI := =last('Iters/'+Iter/name);
           
  template IterT 
  {
       <I>//  begin case parameters</I>
       container PrevIterator;
       unit<uint32> domain;
       <I>//  end case parameters</I>

       unit<uint32>  PrevValue   := PrevIterator/NextValue;
       container     ConvexHullT := MakeConvexHullT(domain, PrevValue);
       unit<uint32>  NextValue   := ConvexHullT/sequence/Convex_hull_points;
  }

  container MakeFinal 
   {
      unit <uint32> domain_with_endpoints := union_unit(iter_domain, LastIter/NextValue)
      {
         attribute<geometries/rdc> point := 
           union_data(., LastIter/NextValue/point, first(LastIter/NextValue/point, LastIter/NextValue/SequenceNr));
         attribute<uint32>         SequenceNr := union_data(., LastIter/NextValue/SequenceNr, ID(Iteratie_domain));
      }
      attribute<geometries/rdc> convex_hull (iter_domain, poly) := 
         points2sequence(domain_with_endpoints /point, domain_with_endpoints /SequenceNr);
    }
   
  template MakeConvexHullT
   {
       <I>//  begin case parameters</I>
        unit<uint32> domain;
        unit<uint32> seq;
       <I>//  end case parameters</I>

        unit<uint32> sequence := seq
        {
           attribute<geometries/rdc>  point              := seq/point;
           attribute<uint32>          SequenceNr         := seq/SequenceNr;

           attribute<uint32>          min_index (domain) := min_index(id(.), SequenceNr);
           attribute<uint32>          max_index (domain) := max_index(id(.), SequenceNr);

           attribute<bool>            IsFirst  := id(.) == min_index[SequenceNr];
           attribute<bool>            IsLast   := id(.) == max_index[SequenceNr];
           attribute<uint32>          prev_id  := IsFirst ? rjoin(SequenceNr, id(domain), max_index) : ID(.)-1;
           attribute<uint32>          next_id  := Islast  ? rjoin(SequenceNr, id(domain), min_index) : ID(.)+1;
           attribute<geometries/rdc>  A        := point[prev_id];
           attribute<geometries/rdc>  B        := point;
           attribute<geometries/rdc>  C        := point[next_id];
           attribute<geometries/rdc>  p        := B - A;
           attribute<geometries/rdc>  q        := C - B;

           attribute<float32>         Px       := pointcol(P);
           attribute<float32>         Py       := pointrow(P);
           attribute<float32>         Qx       := pointcol(Q);
           attribute<float32>         Qy       := pointrow(Q);
           
           attribute<float32>         det      := Px*Qy - Py*Qx;
           
           unit<uint32> Convex_hull_points := 
              select_with_org_rel(det <= 0f && (point != rjoin(prev_id, id(.), point)))
           {
              attribute<geometries/rdc> point       := ../point[org_rel];
              attribute<uint32>         SequenceNr  := ../SequenceNr[org_rel];
           }
      }
   }
}