// Constructor with initial values.
    public SurfaceEnvironmentType(Surface srf, bool wrap)
    {
      environment = srf;
      Wrap = wrap;
      double width, height;
      srf.GetSurfaceSize(out width, out height);
      Width = width;
      Height = height;

      Interval widthInterval = new Interval(0, width);
      Interval heightInterval = new Interval(0, height);

      Interval u = srf.Domain(0);
      Interval v = srf.Domain(1);
      
      Surface refEnvironment = new PlaneSurface(Plane.WorldXY, widthInterval, heightInterval);
      refEnvironment.SetDomain(0, u);
      refEnvironment.SetDomain(1, v);
      RefEnvironment = refEnvironment;

      Interval uDom = RefEnvironment.Domain(0);
      Interval vDom = RefEnvironment.Domain(1);

      minX = 0;
      maxX = width;
      minY = 0;
      maxY = height;
    }
    // Copy Constructor
    public SurfaceEnvironmentType(SurfaceEnvironmentType environment)
    {
      this.environment = environment.environment;
      Width = environment.Width;
      Height = environment.Height;
      Wrap = environment.Wrap;
      RefEnvironment = environment.RefEnvironment;

      Interval uDom = RefEnvironment.Domain(0);
      Interval vDom = RefEnvironment.Domain(1);

      minX = uDom.Min;
      maxX = uDom.Max;
      minY = vDom.Min;
      maxY = vDom.Max;
    }
 //initialize data
 //double w_interval;
 //public double UMin { get; private set; }
 //public double UMax { get; private set; }
 //public double VMin { get; private set; }
 //public double VMax { get; private set; }
 //public double WMin { get; private set; }
 //public double WMax { get; private set; }
 public SurfaceEnvironmentType(Surface srf, int x, int y, int z)
     : base(x, y, 1)
 {
     _srf = srf;
     //UMin = _box.Min.X;
     //UMax = _box.Max.X;
     //VMin = _box.Min.Y;
     //VMax = _box.Max.Y;
        // WMin = _box.Min.Z;
     //WMax = _box.Max.Z;
     uv_positions = new Point3d[u,v,1];
     u_interval = _srf.Domain(0).Length / u;
     v_interval = _srf.Domain(1).Length / v;
     //w_interval = (WMax - WMin) / w;
     trail = new float[u, v, 1];
     temptrail = new float[u, v, 1];
     particle_ids = new int[u, v, 1];
     griddata = new int[u, v, 1];
     agedata = new int[u, v, 1];
     grid_age = 0;
     for (int i = 0; i < u; i++)
     {
         for (int j = 0; j < v; j++)
         {
             //for (int k = 0; k < w; k++)
             //{
                 uv_positions[i, j, 0] = _srf.PointAt(i * u_interval + u_interval / 2, j * v_interval + v_interval / 2);
                 trail[i, j, 0] = 0;
                 temptrail[i, j, 0] = 0;
                 particle_ids[i, j, 0] = -2;
                 griddata[i, j, 0] = 2;
                 agedata[i, j, 0] = 0;
             //}
         }
     }
     projectvalue = 5;
     diffdamp = 0.1F;
     age_flag = false;
     _escape_p = 0;
     env_type = 2;
 }
    // Default Constructor.
    public SurfaceEnvironmentType()
    {
      Point3d pt1 = new Point3d(0, 0, 0);
      Point3d pt2 = new Point3d(RS.boxBoundsDefault, 0, 0);
      Point3d pt3 = new Point3d(0, RS.boxBoundsDefault, 0);
      environment = NurbsSurface.CreateFromCorners(pt1, pt2, pt3);
      Interval u = environment.Domain(0);
      Interval v = environment.Domain(1);
      pt1 = new Point3d(u.Min, v.Min, 0);
      pt2 = new Point3d(u.Max, v.Min, 0);
      pt3 = new Point3d(u.Min, v.Max, 0);
      RefEnvironment = NurbsSurface.CreateFromCorners(pt1, pt2, pt3);

      Interval uDom = RefEnvironment.Domain(0);
      Interval vDom = RefEnvironment.Domain(1);

      minX = uDom.Min;
      maxX = uDom.Max;
      minY = vDom.Min;
      maxY = vDom.Max;

      Width = maxX - minX;
      Height = maxY - minY;
    }
  static Curve TwistedCubeTrimmingCurve(Surface s, int side // 0 = SW to SE
    // 1 = SE to NE
    // 2 = NE to NW
    // 3 = NW to SW
    )
  {
    // A trimming curve is a 2d curve whose image lies in the surface's domain.
    // The "active" portion of the surface is to the left of the trimming curve.
    // An outer trimming loop consists of a simple closed curve running 
    // counter-clockwise around the region it trims.
    var u_domain = s.Domain(0);
    var v_domain = s.Domain(1);
    double u0 = u_domain[0];
    double u1 = u_domain[1];
    double v0 = v_domain[0];
    double v1 = v_domain[1];

    Point2d from;
    Point2d to;

    switch (side)
    {
      case 0:  // SW to SE
        from = new Point2d(u0, v0);
        to = new Point2d(u1, v0);
        break;
      case 1: // SE to NE
        from = new Point2d(u1, v0);
        to = new Point2d(u1, v1);
        break;
      case 2: // NE to NW
        from = new Point2d(u1, v1);
        to = new Point2d(u0, v1);
        break;
      case 3: // NW to SW
        from = new Point2d(u0, v1);
        to = new Point2d(u0, v0);
        break;
      default:
        return null;
    }

    return new LineCurve(from, to) { Domain = new Interval(0, 1) };
  }