text: /* $NoKeywords: $ */
  /*
  //
  // Copyright (c) 1993-2011 Robert McNeel & Associates. All rights reserved.
  // OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert
  // McNeel & Associates.
  //
  // THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
  // ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF
  // MERCHANTABILITY ARE HEREBY DISCLAIMED.
  //
  // For complete openNURBS copyright information see <http://www.opennurbs.org>.
  //
  ////////////////////////////////////////////////////////////////
  */
  
  ////////////////////////////////////////////////////////////////
  //
  //   Definition of surface proxy object
  //
  ////////////////////////////////////////////////////////////////
  
  #if !defined(OPENNURBS_SURFACEPROXY_INC_)
  #define OPENNURBS_SURFACEPROXY_INC_
  
  class ON_Curve;
  class ON_NurbsSurface;
  class ON_CLASS ON_SurfaceProxy : public ON_Surface {
    public:
      // virtual ON_Object::DestroyRuntimeCache override
      void DestroyRuntimeCache(bool bDelete = true);
  
    public:
      ON_SurfaceProxy();
      ON_SurfaceProxy(const ON_Surface *);
      ON_SurfaceProxy(const ON_SurfaceProxy &);
      ON_SurfaceProxy &operator=(const ON_SurfaceProxy &);
  
      virtual ~ON_SurfaceProxy();
  
      void SetProxySurface(const ON_Surface *proxy_surface);
      const ON_Surface *ProxySurface() const;
      bool ProxySurfaceIsTransposed() const;
  
    private:
      const ON_Surface *m_surface;
      bool m_bTransposed; // proxy surface parameterization is transpose of
                          // m_surface
  
    public:
      /*
      Description:
        Get a duplicate of the surface.
      Returns:
        A duplicate of the surface.
      Remarks:
        The caller must delete the returned surface.
        For non-ON_SurfaceProxy objects, this simply duplicates the surface using
        ON_Object::Duplicate.
        For ON_SurfaceProxy objects, this duplicates the actual proxy surface
        geometry and, if necessary, transposes the result to that
        the returned surfaces's parameterization and locus match the proxy
      surface's.
      */
      virtual ON_Surface *DuplicateSurface() const;
  
      /////////////////////////////////////////////////////////////////
      // ON_Object overrides
  
      // virtual ON_Object::SizeOf override
      unsigned int SizeOf() const;
  
      // virtual ON_Object::DataCRC override
      ON__UINT32 DataCRC(ON__UINT32 current_remainder) const;
  
      /*
      Description:
        Tests an object to see if its data members are correctly
        initialized.
      Parameters:
        text_log - [in] if the object is not valid and text_log
            is not NULL, then a brief englis description of the
            reason the object is not valid is appened to the log.
            The information appended to text_log is suitable for
            low-level debugging purposes by programmers and is
            not intended to be useful as a high level user
            interface tool.
      Returns:
        @untitled table
        true     object is valid
        false    object is invalid, uninitialized, etc.
      Remarks:
        Overrides virtual ON_Object::IsValid
      */
      ON_BOOL32 IsValid(ON_TextLog *text_log = NULL) const;
  
      void Dump(ON_TextLog &) const; // for debugging
  
      ON_BOOL32 Write(ON_BinaryArchive & // open binary file
      ) const;
  
      ON_BOOL32 Read(ON_BinaryArchive & // open binary file
      );
  
      /////////////////////////////////////////////////////////////////
      // ON_Geometry overrides
  
      int Dimension() const;
  
      ON_BOOL32 GetBBox(    // returns true if successful
          double *,         // minimum
          double *,         // maximum
          ON_BOOL32 = false // true means grow box
      ) const;
  
      ON_BOOL32 Transform(const ON_Xform &);
  
      ON_Interval Domain(
          int // 0 gets first parameter's domain, 1 gets second parameter's domain
      ) const;
  
      int SpanCount(
          int // 0 gets first parameter's domain, 1 gets second parameter's domain
      ) const; // number of smooth spans in curve
  
      ON_BOOL32 GetSpanVector( // span "knots"
          int,     // 0 gets first parameter's domain, 1 gets second parameter's
                   // domain
          double * // array of length SpanCount() + 1
      ) const;     //
  
      int Degree( // returns maximum algebraic degree of any span
                  // ( or a good estimate if curve spans are not algebraic )
          int // 0 gets first parameter's domain, 1 gets second parameter's domain
      ) const;
  
      ON_BOOL32 GetParameterTolerance( // returns tminus < tplus: parameters
                                       // tminus <= s <= tplus
          int,      // 0 gets first parameter, 1 gets second parameter
          double,   // t = parameter in domain
          double *, // tminus
          double *  // tplus
      ) const;
  
      // override virtual ON_Surface::IsIsoparametric
      ISO IsIsoparametric(const ON_Curve &curve,
                          const ON_Interval *curve_domain = NULL) const;
  
      // override virtual ON_Surface::IsIsoparametric
      ISO IsIsoparametric(const ON_BoundingBox &bbox) const;
  
      /*
      Description:
        Test a surface to see if it is planar.
      Parameters:
        plane - [out] if not NULL and true is returned,
                      the plane parameters are filled in.
        tolerance - [in] tolerance to use when checking
      Returns:
        true if there is a plane such that the maximum distance from
        the surface to the plane is <= tolerance.
      Remarks:
        Overrides virtual ON_Surface::IsPlanar.
      */
      ON_BOOL32 IsPlanar(ON_Plane *plane = NULL,
                         double tolerance = ON_ZERO_TOLERANCE) const;
  
      ON_BOOL32 IsClosed( // true if surface is closed in direction
          int             // dir  0 = "s", 1 = "t"
      ) const;
  
      ON_BOOL32 IsPeriodic( // true if surface is periodic in direction
          int               // dir  0 = "s", 1 = "t"
      ) const;
  
      ON_BOOL32 IsSingular( // true if surface side is collapsed to a point
          int               // side of parameter space to test
                            // 0 = south, 1 = east, 2 = north, 3 = west
      ) const;
  
      /*
      Description:
        Search for a derivatitive, tangent, or curvature
        discontinuity.
      Parameters:
        dir - [in] If 0, then "u" parameter is checked.  If 1, then
                   the "v" parameter is checked.
        c - [in] type of continity to test for.
        t0 - [in] Search begins at t0. If there is a discontinuity
                  at t0, it will be ignored.  This makes it
                  possible to repeatedly call GetNextDiscontinuity
                  and step through the discontinuities.
        t1 - [in] (t0 != t1)  If there is a discontinuity at t1 is
                  will be ingored unless c is a locus discontinuity
                  type and t1 is at the start or end of the curve.
        t - [out] if a discontinuity is found, then *t reports the
              parameter at the discontinuity.
        hint - [in/out] if GetNextDiscontinuity will be called
           repeatedly, passing a "hint" with initial value *hint=0
           will increase the speed of the search.
        dtype - [out] if not NULL, *dtype reports the kind of
            discontinuity found at *t.  A value of 1 means the first
            derivative or unit tangent was discontinuous.  A value
            of 2 means the second derivative or curvature was
            discontinuous.  A value of 0 means teh curve is not
            closed, a locus discontinuity test was applied, and
            t1 is at the start of end of the curve.
        cos_angle_tolerance - [in] default = cos(1 degree) Used only
            when c is ON::G1_continuous or ON::G2_continuous.  If the
            cosine of the angle between two tangent vectors is
            <= cos_angle_tolerance, then a G1 discontinuity is reported.
        curvature_tolerance - [in] (default = ON_SQRT_EPSILON) Used
            only when c is ON::G2_continuous.  If K0 and K1 are
            curvatures evaluated from above and below and
            |K0 - K1| > curvature_tolerance, then a curvature
            discontinuity is reported.
      Returns:
        Parametric continuity tests c = (C0_continuous, ..., G2_continuous):
  
          true if a parametric discontinuity was found strictly
          between t0 and t1. Note well that all curves are
          parametrically continuous at the ends of their domains.
  
        Locus continuity tests c = (C0_locus_continuous, ...,G2_locus_continuous):
  
          true if a locus discontinuity was found strictly between
          t0 and t1 or at t1 is the at the end of a curve.
          Note well that all open curves (IsClosed()=false) are locus
          discontinuous at the ends of their domains.  All closed
          curves (IsClosed()=true) are at least C0_locus_continuous at
          the ends of their domains.
      */
      bool GetNextDiscontinuity(
          int dir, ON::continuity c, double t0, double t1, double *t,
          int *hint = NULL, int *dtype = NULL,
          double cos_angle_tolerance = ON_DEFAULT_ANGLE_TOLERANCE_COSINE,
          double curvature_tolerance = ON_SQRT_EPSILON) const;
  
      /*
      Description:
        Test continuity at a surface parameter value.
      Parameters:
        c - [in] continuity to test for
        s - [in] surface parameter to test
        t - [in] surface parameter to test
        hint - [in] evaluation hint
        point_tolerance - [in] if the distance between two points is
            greater than point_tolerance, then the surface is not C0.
        d1_tolerance - [in] if the difference between two first derivatives is
            greater than d1_tolerance, then the surface is not C1.
        d2_tolerance - [in] if the difference between two second derivatives is
            greater than d2_tolerance, then the surface is not C2.
        cos_angle_tolerance - [in] default = cos(1 degree) Used only when
            c is ON::G1_continuous or ON::G2_continuous.  If the cosine
            of the angle between two normal vectors
            is <= cos_angle_tolerance, then a G1 discontinuity is reported.
        curvature_tolerance - [in] (default = ON_SQRT_EPSILON) Used only when
            c is ON::G2_continuous.  If K0 and K1 are curvatures evaluated
            from above and below and |K0 - K1| > curvature_tolerance,
            then a curvature discontinuity is reported.
      Returns:
        true if the surface has at least the c type continuity at the parameter t.
      Remarks:
        Overrides virtual ON_Surface::IsContinuous
      */
      bool
      IsContinuous(ON::continuity c, double s, double t, int *hint = NULL,
                   double point_tolerance = ON_ZERO_TOLERANCE,
                   double d1_tolerance = ON_ZERO_TOLERANCE,
                   double d2_tolerance = ON_ZERO_TOLERANCE,
                   double cos_angle_tolerance = ON_DEFAULT_ANGLE_TOLERANCE_COSINE,
                   double curvature_tolerance = ON_SQRT_EPSILON) const;
  
      ON_BOOL32
      Reverse( // reverse parameterizatrion, Domain changes from [a,b] to [-b,-a]
          int  // dir  0 = "s", 1 = "t"
      );
  
      ON_BOOL32
      Transpose(); // transpose surface parameterization (swap "s" and "t")
  
      // work horse evaluator
      ON_BOOL32 Evaluate( // returns false if unable to evaluate
          double, double, // evaluation parameters
          int,            // number of derivatives (>=0)
          int,            // array stride (>=Dimension())
          double *,       // array of length stride*(ndir+1)*(ndir+2)/2
          int = 0,        // optional - determines which quadrant to evaluate from
                          //         0 = default
                          //         1 from NE quadrant
                          //         2 from NW quadrant
                          //         3 from SW quadrant
                          //         4 from SE quadrant
          int * = 0       // optional - evaluation hint (int[2]) used to speed
                          //            repeated evaluations
      ) const;
  
      ON_Curve *IsoCurve(int dir, double c) const;
  
      int
      GetNurbForm( // returns 0: unable to create NURBS representation
                   //            with desired accuracy.
                   //         1: success - returned NURBS parameterization
                   //            matches the surface's to wthe desired accuracy
                   //         2: success - returned NURBS point locus matches
                   //            the surfaces's to the desired accuracy but, on
                   //            the interior of the surface's domain, the
                   //            surface's parameterization and the NURBS
                   //            parameterization may not match to the
                   //            desired accuracy.
          ON_NurbsSurface &, double = 0.0) const;
  
      int HasNurbForm( // returns 0: unable to create NURBS representation
                       //            with desired accuracy.
                       //         1: success - returned NURBS parameterization
                       //            matches the surface's to wthe desired
                       //            accuracy
                       //         2: success - returned NURBS point locus matches
                       //            the surfaces's to the desired accuracy but,
                       //            on the interior of the surface's domain, the
                       //            surface's parameterization and the NURBS
                       //            parameterization may not match to the
                       //            desired accuracy.
      ) const;
  
      bool GetSurfaceParameterFromNurbFormParameter(double nurbs_s,
                                                    double nurbs_t,
                                                    double *surface_s,
                                                    double *surface_t) const;
  
      bool GetNurbFormParameterFromSurfaceParameter(double surface_s,
                                                    double surface_t,
                                                    double *nurbs_s,
                                                    double *nurbs_t) const;
  
    private:
      ON_OBJECT_DECLARE(ON_SurfaceProxy);
  };
  
  #endif
  